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