Load kernel and initrd into an existing image.
authorThadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
Fri, 28 Mar 2014 02:39:08 +0000 (23:39 -0300)
committerThadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
Fri, 28 Mar 2014 02:39:08 +0000 (23:39 -0300)
This allows us to replace both kernel and initrd from an existing image
and keep its command line, atags, and load addresses, just changing the
kernel and initrd sizes.

Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
bootimg.c

index b015c10..cacd658 100644 (file)
--- a/bootimg.c
+++ b/bootimg.c
@@ -105,14 +105,20 @@ static int load(int fd, size_t *len, int pgsz, char *fname)
 int main(int argc, char **argv)
 {
        int fd;
-       uint32_t kernel, initrd, second, pgsz;
+       uint32_t *kernel, *initrd, *second, pgsz;
        char buffer[4096];
        char *p;
        int r;
        off_t offset;
+       int is_load;
        if (argc < 2)
                return 1;
-       fd = open(argv[1], O_RDONLY);
+       if (argc > 2)
+               is_load = 1;
+       if (is_load)
+               fd = open(argv[1], O_RDWR);
+       else
+               fd = open(argv[1], O_RDONLY);
        if (fd < 0) {
                return 2;
        }
@@ -123,27 +129,40 @@ int main(int argc, char **argv)
        if (strncmp(buffer, "ANDROID!", 8)) {
                return 4;
        }
-       kernel = *(uint32_t *) p;
+       kernel = (uint32_t *) p;
        p += 8;
-       initrd = *(uint32_t *) p;
+       initrd = (uint32_t *) p;
        p += 8;
-       second = *(uint32_t *) p;
+       second = (uint32_t *) p;
        p += 12;
        pgsz = *(uint32_t *) p;
        offset = pgsz;
-       if (kernel > 0) {
+       if (!is_load && *kernel > 0) {
+               lseek(fd, offset, SEEK_SET);
+               dump(fd, *kernel, pgsz, "kernel");
+       } else {
                lseek(fd, offset, SEEK_SET);
-               dump(fd, kernel, pgsz, "kernel");
+               load(fd, kernel, pgsz, "kernel");
        }
-       offset += ((kernel + pgsz - 1) / pgsz) * pgsz;
-       if (initrd > 0) {
+       offset += ((*kernel + pgsz - 1) / pgsz) * pgsz;
+       if (!is_load && *initrd > 0) {
                lseek(fd, offset, SEEK_SET);
-               dump(fd, initrd, pgsz, "initrd");
+               dump(fd, *initrd, pgsz, "initrd");
+       } else {
+               lseek(fd, offset, SEEK_SET);
+               load(fd, initrd, pgsz, "initrd");
        }
-       offset += ((initrd + pgsz - 1) / pgsz) * pgsz;
-       if (second > 0) {
+       offset += ((*initrd + pgsz - 1) / pgsz) * pgsz;
+       if (!is_load && *second > 0) {
                lseek(fd, offset, SEEK_SET);
-               dump(fd, second, pgsz, "second");
+               dump(fd, *second, pgsz, "second");
+       } else {
+               /* For now, don't care about using second. */
+               /* The header must be written back, and we may need to
+                * truncate the file. */
+               ftruncate(fd, offset);
+               lseek(fd, 0, SEEK_SET);
+               write(fd, buffer, pgsz);
        }
        close(fd);
        return 0;