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 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 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 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 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 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 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 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 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