• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 
23 #include <sys/mount.h>
24 #include <sys/types.h>
25 #include <sys/reboot.h>
26 #include <sys/stat.h>
27 
28 #define error(s, a...)                          \
29     {                                           \
30         printf("error: " s "\n", ##a);          \
31         exit(-1);                               \
32     }
33 
34 #define error_errno(s, a...) error(s ": %s", ##a, strerror(errno))
35 
36 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
37 
38 enum omap_type_enum {
39     OMAP4460_EMU = 0,
40     OMAP4460_HS,
41     OMAP4460_HS_PROD,
42     OMAP4430_HS,
43 };
44 
45 struct omap_type {
46     const char *family;
47     const char *type;
48     unsigned long msv_val;
49     const char *msv_type;
50     off_t offset;
51 } omap_type_list[] = {
52     [OMAP4460_EMU]     = {"OMAP4460", "EMU", 0x00000000, "eng",  0x1000},
53     [OMAP4460_HS]      = {"OMAP4460", "HS",  0x00000000, "eng",  0x21000},
54     [OMAP4460_HS_PROD] = {"OMAP4460", "HS",  0xf0000f00, "prod", 0x41000},
55     [OMAP4430_HS]      = {"OMAP4430", "HS",  0x00000000, "eng",  0x61000},
56 };
57 
58 #define IMG_PIT_OFFSET 0UL
59 #define IMG_SBL_OFFSET 0x81000UL
60 
61 #define MMC_PIT_OFFSET 0x4400UL
62 #define MMC_XLOADER_OFFSET 0x20000UL
63 #define MMC_SBL_OFFSET 0x80000UL
64 
65 #define PIT_SIZE 0x1000UL
66 #define XLOADER_SIZE 0x20000UL
67 
drop_caches(void)68 static void drop_caches(void)
69 {
70     int fd;
71     int ret;
72     char buf[] = "3\n";
73 
74     fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
75     if (fd < 0)
76         error_errno("failed to open /proc/sys/vm/drop_caches");
77 
78     ret = write(fd, buf, sizeof(buf));
79     if (ret < 0)
80         error_errno("failed to write to /proc/sys/vm/drop_caches");
81 }
82 
read_file(const char * filename,char * buf,size_t size)83 static void read_file(const char *filename, char *buf, size_t size)
84 {
85     int fd;
86     ssize_t ret;
87 
88     fd = open(filename, O_RDONLY);
89     if (fd < 0)
90         error_errno("failed to open %s", filename);
91 
92     ret = read(fd, buf, size - 1);
93     if (ret < 0)
94         error_errno("failed to read %s", filename);
95     buf[ret] = 0;
96     while (buf[ret - 1] == '\n')
97         buf[--ret] = 0;
98 
99     close(fd);
100 }
101 
get_omap_type(void)102 static const struct omap_type *get_omap_type(void)
103 {
104     int fd;
105     char family[10];
106     char type[5];
107     char msv[9];
108     unsigned long msv_val;
109     ssize_t ret;
110     unsigned int i;
111 
112     read_file("/sys/board_properties/soc/type", type, sizeof(type));
113     read_file("/sys/board_properties/soc/family", family, sizeof(family));
114     read_file("/sys/board_properties/soc/msv", msv, sizeof(msv));
115 
116     msv_val = strtoul(msv, NULL, 16);
117 
118     for (i = 0; i < ARRAY_SIZE(omap_type_list); i++)
119         if ((strcmp(omap_type_list[i].family, family) == 0) &&
120             (strcmp(omap_type_list[i].type, type) == 0) &&
121             msv_val == omap_type_list[i].msv_val)
122             return &omap_type_list[i];
123 
124     error("unknown omap type %s %s %s (0x%08lx)", family, type, msv, msv_val);
125 }
126 
zero_data(int to_fd,off_t to_offset,ssize_t size)127 static void zero_data(int to_fd, off_t to_offset, ssize_t size)
128 {
129     char buf[4096];
130     int ret;
131     unsigned int to_write;
132 
133     memset(buf, 0, sizeof(buf));
134 
135     ret = lseek(to_fd, to_offset, SEEK_SET);
136     if (ret < 0)
137         error_errno("failed to seek output file to %lx", to_offset);
138 
139     while (size != 0) {
140         to_write = size;
141         if (to_write > sizeof(buf))
142             to_write = sizeof(buf);
143 
144         ret = write(to_fd, buf, to_write);
145         if (ret < 0)
146             error_errno("failed to write to output file");
147         size -= ret;
148     }
149 }
150 
verify_data(int to_fd,off_t to_offset,int from_fd,off_t from_offset,ssize_t size)151 static void verify_data(int to_fd, off_t to_offset,
152                       int from_fd, off_t from_offset,
153                       ssize_t size)
154 {
155     char buf_to[4096];
156     char buf_from[4096];
157     int ret;
158     int to_read;
159     int c;
160     char *ptr;
161 
162     ret = lseek(to_fd, to_offset, SEEK_SET);
163     if (ret < 0)
164         error_errno("failed to seek output file to %lx", to_offset);
165 
166     ret = lseek(from_fd, from_offset, SEEK_SET);
167     if (ret < 0)
168         error_errno("failed to seek input file to %lx", from_offset);
169 
170     while (size != 0) {
171         to_read = sizeof(buf_to);
172         if (size > 0 && to_read > size)
173             to_read = size;
174 
175         ptr = buf_to;
176         c = to_read;
177         while (c > 0) {
178             ret = read(to_fd, ptr, c);
179             if (ret < 0)
180                 error_errno("failed to read from output file");
181             if (ret == 0 && size < 0)
182                 return;
183             if (ret == 0)
184                 error_errno("eof while reading output file");
185             ptr += ret;
186             c -= ret;
187         }
188 
189         ptr = buf_from;
190         c = to_read;
191         while (c > 0) {
192             ret = read(from_fd, ptr, c);
193             if (ret < 0)
194                 error_errno("failed to read from input file");
195             if (ret == 0 && size < 0)
196                 return;
197             if (ret == 0)
198                 error_errno("eof while reading input file");
199             ptr += ret;
200             c -= ret;
201         }
202 
203         if (memcmp(buf_from, buf_to, to_read) != 0)
204             error("mismatch while verifying written data");
205 
206         size -= to_read;
207     }
208 }
209 
copy_data(int to_fd,off_t to_offset,int from_fd,off_t from_offset,ssize_t size)210 static void copy_data(int to_fd, off_t to_offset,
211                       int from_fd, off_t from_offset,
212                       ssize_t size)
213 {
214     char buf[4096];
215     int ret;
216     int to_write;
217     const char *ptr;
218 
219     ret = lseek(to_fd, to_offset, SEEK_SET);
220     if (ret < 0)
221         error_errno("failed to seek output file to %lx", to_offset);
222 
223     ret = lseek(from_fd, from_offset, SEEK_SET);
224     if (ret < 0)
225         error_errno("failed to seek input file to %lx", from_offset);
226 
227     while (size != 0) {
228         ret = read(from_fd, buf, sizeof(buf));
229         if (ret < 0)
230             error_errno("failed to read from input file");
231         if (ret == 0 && size > 0)
232             error_errno("eof while reading input file");
233         if (ret == 0)
234             return;
235 
236         to_write = ret;
237         ptr = buf;
238 
239         if (size > 0)
240             size -= to_write;
241 
242         while (to_write > 0) {
243             ret = write(to_fd, ptr, to_write);
244             if (ret < 0)
245                 error_errno("failed to write to output file");
246             to_write -= ret;
247             ptr += ret;
248         }
249     }
250 }
251 
init(void)252 static void init(void)
253 {
254     int ret;
255 
256     umask(0);
257 
258     ret = mkdir("/dev", 0755);
259     if (ret && errno != EEXIST)
260         error_errno("failed to create /dev");
261 
262     ret = mkdir("/proc", 0755);
263     if (ret && errno != EEXIST)
264         error_errno("failed to create /proc");
265 
266     ret = mkdir("/sys", 0755);
267     if (ret && errno != EEXIST)
268         error_errno("failed to create /sys");
269 
270     ret = mount("proc", "/proc", "proc", 0, NULL);
271     if (ret)
272         error_errno("failed to mount proc");
273 
274     ret = mount("sysfs", "/sys", "sysfs", 0, NULL);
275     if (ret)
276         error_errno("failed to mount sys");
277 
278     ret = mkdir("/dev/block", 0755);
279     if (ret && errno != EEXIST)
280         error_errno("failed to create /dev/block");
281 
282     ret = mknod("/dev/block/mmcblk0", S_IFBLK | 0755, makedev(179, 0));
283     if (ret)
284         error_errno("failed to create mmcblk0");
285 }
286 
main(int argc,char ** argv)287 int main(int argc, char **argv)
288 {
289     int in_fd;
290     int out_fd;
291     const struct omap_type *type;
292 
293     if (getpid() == 1)
294         init();
295 
296     in_fd = open("bootloader.img", O_RDONLY);
297     if (in_fd < 0)
298         error_errno("failed to open bootloader.img");
299 
300     out_fd = open("/dev/block/mmcblk0", O_RDWR);
301     if (out_fd < 0)
302         error_errno("failed to open mmcblk0");
303 
304     type = get_omap_type();
305 
306     printf("Found %s %s %s\n", type->family, type->type, type->msv_type);
307 
308     printf("Zeroing to end of sbl\n");
309     zero_data(out_fd, 0, MMC_SBL_OFFSET);
310 
311     /* Don't write the partition table, let the bootloader do it on next boot */
312 #if 0
313     printf("Writing partition-table from %lx to %lx\n",
314            IMG_PIT_OFFSET, MMC_PIT_OFFSET);
315     copy_data(out_fd, MMC_PIT_OFFSET, in_fd, IMG_PIT_OFFSET, PIT_SIZE);
316 #endif
317 
318     printf("Writing xloader from %lx to %lx\n",
319            type->offset, MMC_XLOADER_OFFSET);
320     copy_data(out_fd, MMC_XLOADER_OFFSET, in_fd, type->offset, XLOADER_SIZE);
321 
322     printf("Writing sbl from %lx to %lx\n",
323            IMG_SBL_OFFSET, MMC_SBL_OFFSET);
324     copy_data(out_fd, MMC_SBL_OFFSET, in_fd, IMG_SBL_OFFSET, -1);
325 
326 #if 0
327     printf("Verifying partition table\n");
328     verify_data(out_fd, MMC_PIT_OFFSET, in_fd, IMG_PIT_OFFSET, PIT_SIZE);
329 #endif
330 
331     printf("Verifying xloader\n");
332     verify_data(out_fd, MMC_XLOADER_OFFSET, in_fd, type->offset, XLOADER_SIZE);
333 
334     printf("Verifying sbl\n");
335     verify_data(out_fd, MMC_SBL_OFFSET, in_fd, IMG_SBL_OFFSET, -1);
336 
337     printf("Syncing\n");
338     sync();
339 
340     printf("Dropping caches\n");
341     drop_caches();
342 
343     printf("Verifying xloader.img\n");
344     verify_data(out_fd, MMC_XLOADER_OFFSET, in_fd, type->offset, XLOADER_SIZE);
345 
346     printf("Verifying sbl.img\n");
347     verify_data(out_fd, MMC_SBL_OFFSET, in_fd, IMG_SBL_OFFSET, -1);
348 
349     printf("Done\n");
350 
351     if (getpid() == 1) {
352         __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
353                  LINUX_REBOOT_CMD_RESTART2, "bootloader");
354 
355         while (1) { sleep(1); }
356     }
357 
358     return 0;
359 }
360