Home | History | Annotate | Download | only in reflash-bootloader
      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