/* tools/mkbootimg/unmkbootimg.c ** ** Copyright 2013, Pete Batard ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #include #include #include #include #include #include #include "bootimg.h" static void *load_file(const char *fn, unsigned *_sz) { char *data; int sz; FILE *fd; data = 0; fd = fopen(fn, "rb"); if(fd == 0) return 0; if(fseek(fd, 0, SEEK_END) != 0) goto oops; sz = ftell(fd); if(sz < 0) goto oops; if(fseek(fd, 0, SEEK_SET) != 0) goto oops; data = (char*) malloc(sz); if(data == 0) goto oops; if(fread(data, 1, sz, fd) != (size_t) sz) goto oops; fclose(fd); if(_sz) *_sz = sz; return data; oops: fclose(fd); if(data != 0) free(data); return 0; } static unsigned save_file(const char *fn, const void* data, const unsigned sz) { FILE *fd; unsigned _sz = 0; fd = fopen(fn, "wb"); if(fd == 0) return 0; _sz = fwrite(data, 1, sz, fd); fclose(fd); return _sz; } int usage(void) { fprintf(stderr,"usage: unmkbootimg\n" " [ --kernel ]\n" " [ --ramdisk ]\n" " [ --second <2ndbootloader-filename> ]\n" " -i|--input \n" ); return 1; } int main(int argc, char **argv) { void *file_data = 0; unsigned file_size = 0; boot_img_hdr *hdr = 0; char *kernel_fn = "kernel"; char *ramdisk_fn = "ramdisk.cpio.gz"; char *second_fn = "second_bootloader"; char *bootimg = 0; unsigned offset; argc--; argv++; while(argc > 0){ char *arg = argv[0]; char *val = argv[1]; if(argc < 2) { return usage(); } argc -= 2; argv += 2; if(!strcmp(arg, "--input") || !strcmp(arg, "-i")) { bootimg = val; } else if(!strcmp(arg, "--kernel")) { kernel_fn = val; } else if(!strcmp(arg, "--ramdisk")) { ramdisk_fn = val; } else if(!strcmp(arg, "--second")) { second_fn = val; } else { return usage(); } } if(bootimg == 0) { fprintf(stderr,"error: no input filename specified\n"); return usage(); } file_data = load_file(bootimg, &file_size); if(file_data == 0) { fprintf(stderr,"error: could not load image '%s'\n", bootimg); return 1; } if(file_size < sizeof(boot_img_hdr)) { fprintf(stderr,"error: file too small for a boot image\n"); goto fail; } hdr = (boot_img_hdr *)file_data; if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE) != 0) { fprintf(stderr,"error: not an Android boot image\n"); goto fail; } if(hdr->kernel_size != 0) { offset = hdr->page_size; if (save_file(kernel_fn, &((char *)file_data)[offset], hdr->kernel_size) != hdr->kernel_size) { fprintf(stderr,"error: could not save kernel '%s'\n", kernel_fn); return 1; } printf("kernel written to '%s' (%d bytes)\n", kernel_fn, hdr->kernel_size); } if(hdr->ramdisk_size != 0) { offset = ((hdr->kernel_size + 2*hdr->page_size - 1) / hdr->page_size) * hdr->page_size; if (save_file(ramdisk_fn, &((char *)file_data)[offset], hdr->ramdisk_size) != hdr->ramdisk_size) { fprintf(stderr,"error: could not save ramdisk '%s'\n", ramdisk_fn); return 1; } printf("ramdisk written to '%s' (%d bytes)\n", ramdisk_fn, hdr->ramdisk_size); } if(hdr->second_size != 0) { offset = ((hdr->kernel_size + hdr->ramdisk_size + 2*hdr->page_size - 1) / hdr->page_size) * hdr->page_size; if (save_file(second_fn, &((char *)file_data)[offset], hdr->second_size) != hdr->second_size) { fprintf(stderr,"error: could not save second bootloader '%s'\n", second_fn); return 1; } printf("second bootloader written to '%s' (%d bytes)\n", second_fn, hdr->second_size); } /* Ideally, we'd also check the SHA sums here */ printf("\nTo rebuild this boot image, you can use the command:\n"); printf(" mkbootimg --base 0 --pagesize %d ", hdr->page_size); if(hdr->name[0] != 0) { printf("--board %s ", hdr->name); } printf("--kernel_offset 0x%08x --ramdisk_offset 0x%08x ", hdr->kernel_addr, hdr->ramdisk_addr); printf("--second_offset 0x%08x --tags_offset 0x%08x ", hdr->second_addr, hdr->tags_addr); if(hdr->cmdline[0] != 0) { printf("--cmdline '%s%s' ", hdr->cmdline, hdr->extra_cmdline); } if(hdr->kernel_size != 0) { printf("--kernel %s ", kernel_fn); } if(hdr->ramdisk_size != 0) { printf("--ramdisk %s ", ramdisk_fn); } if(hdr->second_size != 0) { printf("--second %s ", second_fn); } printf("-o %s\n", bootimg); free(file_data); return 0; fail: free(file_data); return 1; }