#include #include #include #include #include #include #include #include #include #include #include "bootimgtools.h" void dump(uint8_t *ptr, size_t size, char* filename) { unlink(filename); int ofd = open(filename, O_WRONLY|O_CREAT, 0644); assert(ofd >= 0); int ret = write(ofd, ptr, size); assert(ret == size); close(ofd); } //TODO: Search for other header types void dump_ramdisk(uint8_t *ptr, size_t size) { //GZip header if(memcmp(ptr, "\x1f\x8b\x08\x00", 4) == 0) { dump(ptr, size, "ramdisk.gz"); //MTK header } else if(memcmp(ptr, "\x88\x16\x88\x58", 4) == 0) { if(memcmp(ptr+8, "RECOVERY", 8)==0) { dump(ptr, 0, "ramdisk-mtk-recovery"); } else if(memcmp(ptr+8, "ROOTFS\0\0", 8)==0) { dump(ptr, 0, "ramdisk-mtk-boot"); } else { exit(1); } dump(ptr, 0, "ramdisk-mtk"); //Create an mtk flag dump_ramdisk(ptr+512, size-512); } else { //Since our first aim is to extract/repack ramdisk //Stop if we can't find it //Still dump it for debug purposes dump(ptr, size, "ramdisk"); fprintf(stderr, "Unknown ramdisk type\n"); abort(); } } void search_security_hdr(uint8_t *buf, size_t size) { if(memcmp(buf, "CHROMEOS", 8) == 0) { dump(buf, 0, "chromeos"); return; } } int search_security(uint8_t *buf, size_t size, int pos) { //Rockchip signature if(memcmp(buf+1024, "SIGN", 4) == 0) { //Rockchip signature AT LEAST means the bootloader will check the crc dump(buf, 0, "rkcrc"); //Create an flag to tell it //And it's possible there is a security too return 1; } //If we didn't parse the whole file, it is highly likely there is a boot signature if(pos < size) { return 1; } return 0; } /* * TODO: * - At the moment we dump kernel + ramdisk + second + DT, it's likely we only want ramdisk * - Error-handling via assert() is perhaps not the best */ int extract(char *image) { int fd = open(image, O_RDONLY); off_t size = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); uint8_t *orig = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); uint8_t *base = orig; assert(base); search_security_hdr(base, size); //We're searching for the header in the whole file, we could stop earlier. //At least HTC and nVidia have a signature header while(base<(orig+size)) { if(memcmp(base, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) break; //We're searching every 256bytes, is it ok? base += 256; } assert(base < (orig+size)); struct boot_img_hdr *hdr = (struct boot_img_hdr*) base; assert( hdr->page_size == 2048 || hdr->page_size == 4096 || hdr->page_size == 16384 ); long pos = hdr->page_size; dump(base+pos, hdr->kernel_size, "kernel"); pos += hdr->kernel_size + hdr->page_size-1; pos &= ~(hdr->page_size-1L); dump_ramdisk(base+pos, hdr->ramdisk_size); pos += hdr->ramdisk_size + hdr->page_size-1; pos &= ~(hdr->page_size-1L); if(hdr->second_size) { assert( (pos+hdr->second_size) <= size); dump(base+pos, hdr->second_size, "second"); pos += hdr->second_size + hdr->page_size-1; pos &= ~(hdr->page_size-1L); } //This is non-standard, so we triple check if( hdr->unused[0] && pos < size && (pos+hdr->unused[0]) <= size) { if(memcmp(base+pos, "QCDT", 4) == 0 || memcmp(base+pos, "SPRD", 4) == 0 || memcmp(base+pos, "DTBH", 4) == 0 ) { dump(base+pos, hdr->unused[0], "dt"); pos += hdr->unused[0] + hdr->page_size-1; pos &= ~(hdr->page_size-1L); } } //If we think we find some security-related infos in the boot.img //create a "secure" flag to warn the user it is dangerous if(search_security(base, size, pos)) { dump(base, 0, "secure"); } munmap(orig, size); close(fd); return 0; }