1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #define _GNU_SOURCE
17 
18 #include <pthread.h>
19 #include <stdio.h>
20 #include <stdio.h>
21 #include <sys/stat.h>
22 #include <sys/wait.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/ioctl.h>
26 #include <sys/time.h>
27 #include <sys/mman.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <linux/ion.h>
33 
34 #define ION_HEAP(bit) (1 << (bit))
35 
36 enum ion_heap_ids {
37     INVALID_HEAP_ID = -1,
38     ION_CP_MM_HEAP_ID = 8,
39     ION_SECURE_HEAP_ID = 9,
40     ION_SECURE_DISPLAY_HEAP_ID = 10,
41     ION_CP_MFC_HEAP_ID = 12,
42     ION_CP_WB_HEAP_ID = 16, /* 8660 only */
43     ION_CAMERA_HEAP_ID = 20, /* 8660 only */
44     ION_SYSTEM_CONTIG_HEAP_ID = 21,
45     ION_ADSP_HEAP_ID = 22,
46     ION_PIL1_HEAP_ID = 23, /* Currently used for other PIL images */
47     ION_SF_HEAP_ID = 24,
48     ION_SYSTEM_HEAP_ID = 25,
49     ION_PIL2_HEAP_ID = 26, /* Currently used for modem firmware images */
50     ION_QSECOM_HEAP_ID = 27,
51     ION_AUDIO_HEAP_ID = 28,
52     ION_MM_FIRMWARE_HEAP_ID = 29,
53     ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_FLAG_SECURE flag */
54 };
55 
56 static unsigned int ion_type[] = {
57     ION_HEAP(ION_CP_MM_HEAP_ID),
58     ION_HEAP(ION_CP_MFC_HEAP_ID),
59     ION_HEAP(ION_SYSTEM_CONTIG_HEAP_ID),
60     ION_HEAP(ION_ADSP_HEAP_ID ),
61     ION_HEAP(ION_SF_HEAP_ID),
62     ION_HEAP(ION_SYSTEM_HEAP_ID),
63     ION_HEAP(ION_QSECOM_HEAP_ID),
64     ION_HEAP(ION_AUDIO_HEAP_ID),
65 };
66 
67 #define NEW_ION
ion_alloc(int fd,int len,int * hdl,unsigned int ion_type)68 int ion_alloc(int fd, int len, int *hdl, unsigned int ion_type)
69 {
70     int ret;
71     struct ion_allocation_data req = {
72         .len = len,
73 #ifdef NEW_ION
74         .heap_id_mask = ion_type,
75         //.flags = ION_SECURE | ION_FORCE_CONTIGUOUS,
76         .flags = (1 << 0),
77         .flags = 0x0,
78 #else
79         .flags = ION_SECURE | ION_FORCE_CONTIGUOUS | ION_HEAP(ION_CP_MM_HEAP_ID),
80 #endif
81         .align = len,
82     };
83 
84     ret = ioctl(fd, ION_IOC_ALLOC, &req);
85     if (ret) {
86         return ret;
87     }
88 
89     *hdl = req.handle;
90 
91     return 0;
92 }
93 
ion_free(int fd,int hdl)94 int ion_free(int fd, int hdl)
95 {
96     int ret;
97     struct ion_handle_data req = {
98         .handle = hdl,
99     };
100 
101     ret = ioctl(fd, ION_IOC_FREE, &req);
102     if (ret) {
103         return ret;
104     }
105 
106     return 0;
107 }
108 
ion_map(int fd,int hdl)109 int ion_map(int fd, int hdl)
110 {
111     int ret;
112     struct ion_fd_data req = {
113         .handle = hdl,
114     };
115 
116     ret = ioctl(fd, ION_IOC_MAP, &req);
117     if (ret) {
118         return ret;
119    }
120 
121    return req.fd;
122 }
123 
124 int ion_fd;
125 int ion_handle;
126 int status[2];
127 int cmd = 0;
128 
threadForIonFree01()129 void *threadForIonFree01()
130 {
131     status[0] = 1;
132 
133     while (cmd == 0) {
134         usleep(10);
135     }
136     if (cmd == -1)
137         goto failed;
138 
139     usleep(50);
140     ion_free(ion_fd, ion_handle);
141 
142 failed:
143     status[0] = 2;
144     return NULL;
145 }
146 
147 
threadForIonFree02()148 void *threadForIonFree02()
149 {
150     status[1] = 1;
151 
152     while (cmd == 0) {
153         usleep(10);
154     }
155     if(cmd == -1)
156         goto failed;
157 
158     usleep(50);
159     ion_free(ion_fd, ion_handle);
160 
161 failed:
162     status[1] = 2;
163     return NULL;
164 }
165 
main()166 int main()
167 {
168     int ret, i, count;
169     pthread_t tid_free[2];
170 
171     count = 0;
172 retry:
173     status[0] = 0;
174     status[1] = 0;
175     cmd = 0;
176     ion_fd = open("/dev/ion", O_RDONLY| O_SYNC, 0);
177     if (ion_fd < 0) {
178 	return -1;
179     }
180 
181     for (i=0; i < sizeof(ion_type)/sizeof(ion_type[0]); i++) {
182         ret = ion_alloc(ion_fd, 0x1000, &ion_handle, ion_type[i]);
183         if (ret == 0) {
184             break;
185         }
186     }
187 
188     if (i == sizeof(ion_type)/sizeof(ion_type[0])) {
189         goto failed;
190     }
191 
192     ret = pthread_create(&tid_free[0], NULL, threadForIonFree01, NULL);
193     if (ret != 0) {
194         goto failed;
195     }
196 
197     ret = pthread_create(&tid_free[1], NULL, threadForIonFree02, NULL);
198     if (ret != 0) {
199         cmd = -1;
200         goto failed;
201     }
202 
203     while (status[0] != 1 || status[1] != 1) {
204         usleep(50);
205     }
206 
207     cmd = 1;
208     ret = ion_map(ion_fd, ion_handle);
209 
210     while (status[0] != 2 || status[1] != 2) {
211         usleep(50);
212     }
213 
214 failed:
215     ion_free(ion_fd,ion_handle);
216     close(ion_fd);
217     goto retry;
218 
219     return 0;
220 }
221 
222