Add ELF support

This commit is contained in:
topjohnwu 2017-02-25 03:29:12 +08:00
parent 6f609f0dd7
commit 7ef0746c52
7 changed files with 552 additions and 182 deletions

View File

@ -3,6 +3,6 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := bootimgtools
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := main.c unpack.c repack.c hexpatch.c
LOCAL_SRC_FILES := main.c unpack.c repack.c hexpatch.c parseimg.c
LOCAL_CFLAGS += -std=gnu11
include $(BUILD_EXECUTABLE)

View File

@ -93,8 +93,20 @@ struct boot_img_hdr
** else: jump to kernel_addr
*/
/* Self defined stuffs */
// Global pointers to mmap
unsigned char *base, *kernel, *ramdisk, *second, *dtb;
// Parsed header
boot_img_hdr hdr;
int unpack(const char *image);
int repack(const char *image);
int hexpatch(char *image, char *from, char *to);
void error(int rc, const char *msg, ...);
void print_header();
void parse_elf();
void parse_aosp();
#endif

149
jni/bootimgtools/elf.h Normal file
View File

@ -0,0 +1,149 @@
#ifndef _ELF_H_
#define _ELF_H_
#include <stdint.h>
/*
** ELF structure
**
** +-----------------+
** | ELF magic | | 4 bytes
** +------------ +
** | ELF class | | 1 byte
** +------------ +
** | ELF header |
** +-----------------+
** ~
** +-----------------+
** | program header | kernel info
** +-----------------+
** | program header | ramdisk info
** +-----------------+
** | program header | dtb info
** +-----------------+
** ~
** +-----------------+
** | section header | cmdline info
** +-----------------+
** ~
** +-----------------+
** | |
** | Data |
** | |
** +-----------------+
*/
typedef uint32_t elf32_addr;
typedef uint16_t elf32_half;
typedef uint32_t elf32_off;
typedef uint32_t elf32_word;
typedef uint64_t elf64_addr;
typedef uint16_t elf64_half;
typedef uint64_t elf64_off;
typedef uint32_t elf64_word;
typedef uint64_t elf64_xword;
#define ELF_MAGIC "\x7f""ELF"
#define ELF_MAGIC_SIZE 4
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define EI_OSABI 7
#define EI_PAD 8
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
#define ELFCLASSNUM 3
#define ET_EXEC 2
#define EM_ARM 40
#define EI_NIDENT 16
typedef struct elf32_ehdr{
unsigned char e_ident[EI_NIDENT];
elf32_half e_type;
elf32_half e_machine;
elf32_word e_version;
elf32_addr e_entry; /* Entry point */
elf32_off e_phoff;
elf32_off e_shoff;
elf32_word e_flags;
elf32_half e_ehsize;
elf32_half e_phentsize;
elf32_half e_phnum;
elf32_half e_shentsize;
elf32_half e_shnum;
elf32_half e_shstrndx;
} elf32_ehdr;
typedef struct elf64_ehdr {
unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
elf64_half e_type;
elf64_half e_machine;
elf64_word e_version;
elf64_addr e_entry; /* Entry point virtual address */
elf64_off e_phoff; /* Program header table file offset */
elf64_off e_shoff; /* Section header table file offset */
elf64_word e_flags;
elf64_half e_ehsize;
elf64_half e_phentsize;
elf64_half e_phnum;
elf64_half e_shentsize;
elf64_half e_shnum;
elf64_half e_shstrndx;
} elf64_ehdr;
typedef struct elf32_phdr{
elf32_word p_type;
elf32_off p_offset;
elf32_addr p_vaddr;
elf32_addr p_paddr;
elf32_word p_filesz;
elf32_word p_memsz;
elf32_word p_flags;
elf32_word p_align;
} elf32_phdr;
typedef struct elf64_phdr {
elf64_word p_type;
elf64_word p_flags;
elf64_off p_offset; /* Segment file offset */
elf64_addr p_vaddr; /* Segment virtual address */
elf64_addr p_paddr; /* Segment physical address */
elf64_xword p_filesz; /* Segment size in file */
elf64_xword p_memsz; /* Segment size in memory */
elf64_xword p_align; /* Segment alignment, file & memory */
} elf64_phdr;
typedef struct elf32_shdr {
elf32_word s_name;
elf32_word s_type;
elf32_word s_flags;
elf32_addr s_addr;
elf32_off s_offset;
elf32_word s_size;
elf32_word s_link;
elf32_word s_info;
elf32_word s_addralign;
elf32_word s_entsize;
} elf32_shdr;
typedef struct elf64_shdr {
elf64_word s_name; /* Section name, index in string tbl */
elf64_word s_type; /* Type of section */
elf64_xword s_flags; /* Miscellaneous section attributes */
elf64_addr s_addr; /* Section virtual addr at execution */
elf64_off s_offset; /* Section file offset */
elf64_xword s_size; /* Size of section in bytes */
elf64_word s_link; /* Index of another section */
elf64_word s_info; /* Additional section information */
elf64_xword s_addralign; /* Section alignment */
elf64_xword s_entsize; /* Entry size if section holds table */
} elf64_shdr;
#endif

View File

@ -1,5 +1,7 @@
#include <getopt.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "bootimg.h"
@ -7,7 +9,7 @@
Patch Boot Image
*********************/
static int usage(char *arg0) {
static void usage(char *arg0) {
fprintf(stderr, "Boot Image Unpack/Repack Tool\n");
fprintf(stderr, "%s --unpack <bootimage>\n", arg0);
fprintf(stderr, " Unpack <bootimage> into current directory\n\n");
@ -15,30 +17,34 @@ static int usage(char *arg0) {
fprintf(stderr, " Repack kernel, dtb, ramdisk... from current directory to new-image.img\n <bootimage> is the image you've just unpacked\n\n");
fprintf(stderr, "%s --hexpatch <bootimage> <hexpattern1> <hexpattern2>\n", arg0);
fprintf(stderr, " Search <hexpattern1> in <bootimage>, and replace with <hexpattern2>\n\n");
return 1;
exit(1);
}
void error(int rc, const char *msg, ...) {
va_list ap;
va_start(ap, msg);
vfprintf(stderr, msg, ap);
fprintf(stderr,"\n\n");
va_end(ap);
exit(rc);
}
int main(int argc, char *argv[]) {
char ch;
struct option long_options[] = {
{"unpack", required_argument, NULL, 'u'},
{"repack", required_argument, NULL, 'r'},
{"hexpatch", required_argument, NULL, 'p'},
{NULL, 0, NULL, 0}
};
while ((ch = getopt_long(argc, argv, "e:r:p:", long_options, NULL)) != -1) {
switch (ch) {
case 'e':
return unpack(optarg);
case 'r':
return repack(optarg);
case 'p':
if (argc < 5) return usage(argv[0]);
optind += 2;
return hexpatch(argv[optind - 3], argv[optind - 2], argv[optind - 1]);
default:
return usage(argv[0]);
}
if (argc < 3)
usage(argv[0]);
if (strcmp(argv[1], "--unpack") == 0) {
unpack(argv[2]);
} else if (strcmp(argv[1], "--repack") == 0) {
repack(argv[2]);
} else if (strcmp(argv[1], "--hexpatch") == 0) {
if (argc < 5)
usage(argv[0]);
hexpatch(argv[2], argv[3], argv[4]);
} else {
usage(argv[0]);
}
return 0;
}

232
jni/bootimgtools/parseimg.c Normal file
View File

@ -0,0 +1,232 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include "bootimg.h"
#include "elf.h"
void print_header() {
printf("KERNEL [%d] @ 0x%08x\n", hdr.kernel_size, hdr.kernel_addr);
printf("RAMDISK [%d] @ 0x%08x\n", hdr.ramdisk_size, hdr.ramdisk_addr);
printf("SECOND [%d] @ 0x%08x\n", hdr.second_size, hdr.second_addr);
printf("DTB [%d] @ 0x%08x\n", hdr.dt_size, hdr.tags_addr);
printf("PAGESIZE [%d]\n", hdr.page_size);
if (hdr.os_version != 0) {
int a,b,c,y,m = 0;
int os_version, os_patch_level;
os_version = hdr.os_version >> 11;
os_patch_level = hdr.os_version & 0x7ff;
a = (os_version >> 14) & 0x7f;
b = (os_version >> 7) & 0x7f;
c = os_version & 0x7f;
printf("OS_VERSION [%d.%d.%d]\n", a, b, c);
y = (os_patch_level >> 4) + 2000;
m = os_patch_level & 0xf;
printf("PATCH_LEVEL [%d-%02d]\n", y, m);
}
printf("NAME [%s]\n", hdr.name);
printf("CMDLINE [%s]\n", hdr.cmdline);
}
static void page_align(unsigned char **pos) {
uint32_t itemsize = *pos - base, pagemask = hdr.page_size - 1L;
if (itemsize & pagemask) {
*pos += hdr.page_size - (itemsize & pagemask);
}
}
static void elf_header_check(void *elf, int is64) {
size_t e_size, mach, ver, p_size, p_num, s_size, s_num;
size_t r_e_size, r_p_size, r_s_size;
if (is64) {
e_size = ((elf64_ehdr *) elf)->e_ehsize;
mach = ((elf64_ehdr *) elf)->e_machine;
ver = ((elf64_ehdr *) elf)->e_version;
p_size = ((elf64_ehdr *) elf)->e_phentsize;
p_num = ((elf64_ehdr *) elf)->e_phnum;
s_size = ((elf64_ehdr *) elf)->e_shentsize;
s_num = ((elf64_ehdr *) elf)->e_shnum;
r_e_size = sizeof(elf64_ehdr);
r_p_size = sizeof(elf64_phdr);
r_s_size = sizeof(elf64_shdr);
} else {
e_size = ((elf32_ehdr *) elf)->e_ehsize;
mach = ((elf32_ehdr *) elf)->e_machine;
ver = ((elf32_ehdr *) elf)->e_version;
p_size = ((elf32_ehdr *) elf)->e_phentsize;
p_num = ((elf32_ehdr *) elf)->e_phnum;
s_size = ((elf32_ehdr *) elf)->e_shentsize;
s_num = ((elf32_ehdr *) elf)->e_shnum;
r_e_size = sizeof(elf32_ehdr);
r_p_size = sizeof(elf32_phdr);
r_s_size = sizeof(elf32_shdr);
}
if (e_size != r_e_size)
error(1, "Header size not %d", r_e_size);
if (mach != EM_ARM)
error(1, "ELF machine is not ARM");
if (ver != 1)
error(1, "Unknown ELF version");
if (p_size != r_p_size)
error(1, "Program header size not %d", r_p_size);
if (p_num < 2 || p_num > 4)
error(1, "Unexpected number of elements: %d", p_num);
if (s_num && s_size != r_s_size)
error(1, "Section header size not %d", r_s_size);
if (s_num > 1)
error(1, "More than one section header");
}
static void elf_set(int i, size_t size, size_t offset, size_t addr) {
if (size <= 4096) {
// Possible cmdline
memset(hdr.cmdline, 0, BOOT_ARGS_SIZE);
strncpy((char *) hdr.cmdline, (char *) (base + offset), BOOT_ARGS_SIZE);
hdr.cmdline[strcspn((char*) hdr.cmdline, "\n")] = '\0';
return;
}
switch(i) {
case 0:
// kernel
kernel = base + offset;
hdr.kernel_size = size;
hdr.kernel_addr = addr;
break;
case 1:
// ramdisk
ramdisk = base + offset;
hdr.ramdisk_size = size;
hdr.ramdisk_addr = addr;
break;
case 2:
// dtb
dtb = base + offset;
hdr.dt_size = size;
hdr.tags_addr = addr;
break;
}
}
void parse_elf() {
// Reset boot image header
memset(&hdr, 0, sizeof(hdr));
// Hardcode pagesize
hdr.page_size = 4096;
switch(base[EI_CLASS]) {
case ELFCLASS32: {
elf32_ehdr *elf32;
elf32_phdr *ph32;
elf32_shdr *sh32;
printf("IMAGE [ELF32]\n");
elf32 = (elf32_ehdr *) base;
elf_header_check(elf32, 0);
ph32 = (elf32_phdr *) (base + elf32->e_phoff);
sh32 = (elf32_shdr *) (base + elf32->e_shoff);
for (int i = 0; i < elf32->e_phnum; ++i) {
elf_set(i, ph32[i].p_filesz, ph32[i].p_offset, ph32[i].p_paddr);
}
if (elf32->e_shnum) {
// cmdline
memset(hdr.cmdline, 0, BOOT_ARGS_SIZE);
strncpy((char *) hdr.cmdline, (char *) (base + sh32->s_offset + 8), BOOT_ARGS_SIZE);
hdr.cmdline[strcspn((char*) hdr.cmdline, "\n")] = '\0';
}
break;
}
case ELFCLASS64: {
elf64_ehdr *elf64;
elf64_phdr *ph64;
elf64_shdr *sh64;
printf("IMAGE [ELF64]\n");
elf64 = (elf64_ehdr *) base;
elf_header_check(elf64, 1);
ph64 = (elf64_phdr *) (base + elf64->e_phoff);
sh64 = (elf64_shdr *) (base + elf64->e_shoff);
for (int i = 0; i < elf64->e_phnum; ++i) {
elf_set(i, ph64[i].p_filesz, ph64[i].p_offset, ph64[i].p_paddr);
}
if (elf64->e_shnum) {
// cmdline
memset(hdr.cmdline, 0, BOOT_ARGS_SIZE);
strncpy((char *) hdr.cmdline, (char *) (base + sh64->s_offset + 8), BOOT_ARGS_SIZE);
hdr.cmdline[strcspn((char*) hdr.cmdline, "\n")] = '\0';
}
break;
}
default:
error(1, "ELF format error!");
}
print_header();
}
void parse_aosp() {
printf("IMG [AOSP]\n");
unsigned char *pos = base;
// Read the header
memcpy(&hdr, pos, sizeof(hdr));
pos += hdr.page_size;
// Kernel position
kernel = pos;
pos += hdr.kernel_size;
page_align(&pos);
// Ramdisk position
ramdisk = pos;
pos += hdr.ramdisk_size;
page_align(&pos);
if (hdr.second_size) {
// Second position
second = pos;
pos += hdr.second_size;
page_align(&pos);
}
if (hdr.dt_size) {
// dtb position
dtb = pos;
pos += hdr.dt_size;
page_align(&pos);
}
print_header();
}

View File

@ -10,12 +10,12 @@
#include <string.h>
#include "bootimg.h"
#include "elf.h"
// Global pointer of current positions
static void *ibase, *ipos;
static int ofd, opos;
static size_t dump(const char *filename) {
static size_t restore(const char *filename) {
int fd = open(filename, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Cannot open %s\n", filename);
@ -32,67 +32,76 @@ static size_t dump(const char *filename) {
return size;
}
static void dump_buf(size_t size, const void *buf) {
if (write(ofd, buf, size) < 0) {
static void restore_buf(size_t size, const void *buf) {
if (write(ofd, buf, size) != size) {
fprintf(stderr, "Cannot dump from input file\n");
exit(1);
}
opos += size;
}
static void in_page_align(uint32_t pagesize) {
uint32_t itemsize = ipos - ibase, pagemask = pagesize - 1L;
if (itemsize & pagemask) {
ipos += pagesize - (itemsize & pagemask);
}
}
static void out_page_align(uint32_t pagesize) {
uint32_t pagemask = pagesize - 1L;
static void page_align() {
uint32_t pagemask = hdr.page_size - 1L;
if (opos & pagemask) {
opos += pagesize - (opos & pagemask);
opos += hdr.page_size - (opos & pagemask);
}
ftruncate(ofd, opos);
lseek(ofd, 0, SEEK_END);
}
static int aosp() {
printf("AOSP Boot Image Detected\n");
int repack(const char* image) {
// Load original boot
int ifd = open(image, O_RDONLY), ret = -1;
if (ifd < 0)
error(1, "Cannot open %s", image);
size_t isize = lseek(ifd, 0, SEEK_END);
lseek(ifd, 0, SEEK_SET);
unsigned char *orig = mmap(NULL, isize, PROT_READ, MAP_SHARED, ifd, 0);
// Create new boot image
unlink("new-boot.img");
ofd = open("new-boot.img", O_RDWR | O_CREAT, 0644);
// Parse images
for(base = orig; base < (orig + isize); base += 256) {
if (memcmp(base, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) {
parse_aosp();
break;
} else if (memcmp(base, ELF_MAGIC, ELF_MAGIC_SIZE) == 0) {
parse_elf();
break;
}
}
printf("\n");
char *name;
boot_img_hdr hdr, ihdr;
// Read the original header
memcpy(&ihdr, ibase, sizeof(ihdr));
hdr = ihdr;
// Set all sizes to 0
hdr.kernel_size = 0;
hdr.ramdisk_size = 0;
hdr.second_size = 0;
hdr.dt_size = 0;
// Skip a page
// Skip a page for header
ftruncate(ofd, hdr.page_size);
lseek(ofd, 0, SEEK_END);
opos += hdr.page_size;
ipos = ibase + hdr.page_size;
// Dump zImage
if (memcmp(ipos, "\x88\x16\x88\x58", 4) == 0) {
printf("Dumping MTK header back to zImage\n");
dump_buf(512, ipos);
// Restore kernel
if (memcmp(kernel, "\x88\x16\x88\x58", 4) == 0) {
printf("Dumping MTK header back to kernel\n");
restore_buf(512, kernel);
hdr.kernel_size += 512;
}
hdr.kernel_size += dump("kernel");
ipos += ihdr.kernel_size;
in_page_align(hdr.page_size);
out_page_align(hdr.page_size);
hdr.kernel_size += restore("kernel");
page_align();
// Dump ramdisk
if (memcmp(ipos, "\x88\x16\x88\x58", 4) == 0) {
if (memcmp(ramdisk, "\x88\x16\x88\x58", 4) == 0) {
printf("Dumping MTK header back to ramdisk\n");
dump_buf(512, ipos);
restore_buf(512, ramdisk);
hdr.ramdisk_size += 512;
}
if (access("ramdisk.gz", R_OK) == 0) {
@ -108,50 +117,31 @@ static int aosp() {
} else if (access("ramdisk.lz4", R_OK) == 0) {
name = "ramdisk.lz4";
} else {
fprintf(stderr, "Ramdisk file doesn't exist!\n");
return 1;
error(1, "Ramdisk file doesn't exist!");
}
hdr.ramdisk_size += dump(name);
out_page_align(hdr.page_size);
hdr.ramdisk_size += restore(name);
page_align();
// Dump second
if (access("second", R_OK) == 0) {
hdr.second_size += dump("second");
out_page_align(hdr.page_size);
hdr.second_size += restore("second");
page_align();
}
// Dump dtb
if (access("dtb", R_OK) == 0) {
hdr.dt_size += dump("dtb");
out_page_align(hdr.page_size);
hdr.dt_size += restore("dtb");
page_align();
}
print_header();
// Write header back
lseek(ofd, 0, SEEK_SET);
write(ofd, &hdr, sizeof(hdr));
return 0;
}
int repack(const char* image) {
// Load original boot
int ifd = open(image, O_RDONLY), ret = -1;
size_t isize = lseek(ifd, 0, SEEK_END);
lseek(ifd, 0, SEEK_SET);
void *orig = mmap(NULL, isize, PROT_READ, MAP_SHARED, ifd, 0);
// Create new boot image
unlink("new-boot.img");
ofd = open("new-boot.img", O_RDWR | O_CREAT, 0644);
// Check headers
for(ibase = orig; ibase < (orig + isize); ibase += 256) {
if (memcmp(ibase, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) {
ret = aosp();
break;
}
}
munmap(orig, isize);
close(ifd);
close(ofd);
return ret;
}

View File

@ -10,119 +10,100 @@
#include <string.h>
#include "bootimg.h"
#include "elf.h"
// Global pointer of current positions
static unsigned char *base, *pos;
static void dump(size_t size, const char *filename) {
static void dump(unsigned char *buf, size_t size, const char *filename) {
unlink(filename);
int ofd = open(filename, O_WRONLY | O_CREAT, 0644);
assert(ofd >= 0);
int ret = write(ofd, pos, size);
assert(ret == size);
if (ofd < 0)
error(1, "Cannot open %s", filename);
if (write(ofd, buf, size) != size)
error(1, "Cannot dump %s", filename);
close(ofd);
pos += size;
}
static void page_align(uint32_t pagesize) {
uint32_t itemsize = pos - base, pagemask = pagesize - 1L;
if (itemsize & pagemask) {
pos += pagesize - (itemsize & pagemask);
}
}
static int aosp() {
printf("AOSP Boot Image Detected\n");
char name[PATH_MAX], *ext;
// Read the header
boot_img_hdr hdr;
memcpy(&hdr, base, sizeof(hdr));
pos = base + hdr.page_size;
// Dump zImage
if (memcmp(pos, "\x88\x16\x88\x58", 4) == 0) {
printf("MTK header found in zImage\n");
pos += 512;
hdr.kernel_size -= 512;
}
dump(hdr.kernel_size, "kernel");
page_align(hdr.page_size);
// Dump ramdisk
if (memcmp(pos, "\x88\x16\x88\x58", 4) == 0) {
printf("MTK header found in ramdisk\n");
pos += 512;
hdr.ramdisk_size -= 512;
}
// Compression detection
if (memcmp(pos, "\x1f\x8b\x08\x00", 4) == 0) {
// gzip header
printf("gzip ramdisk format detected!\n");
ext = "gz";
} else if (memcmp(pos, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9) == 0) {
// lzop header
printf("lzop ramdisk format detected!\n");
ext = "lzo";
} else if (memcmp(pos, "\xfd""7zXZ\x00", 6) == 0) {
// xz header
printf("xz ramdisk format detected!\n");
ext = "xz";
} else if (memcmp(pos, "\x5d\x00\x00", 3) == 0
&& (pos[12] == (unsigned char) '\xff' || pos[12] == (unsigned char) '\x00')) {
// lzma header
printf("lzma ramdisk format detected!\n");
ext = "lzma";
} else if (memcmp(pos, "BZh", 3) == 0) {
// bzip2 header
printf("bzip2 ramdisk format detected!\n");
ext = "bz2";
} else if ( ( memcmp(pos, "\x04\x22\x4d\x18", 4) == 0
|| memcmp(pos, "\x03\x21\x4c\x18", 4) == 0)
|| memcmp(pos, "\x02\x21\x4c\x18", 4) == 0) {
// lz4 header
printf("lz4 ramdisk format detected!\n");
ext = "lz4";
} else {
fprintf(stderr, "Unknown ramdisk format!\n");
return 1;
}
sprintf(name, "%s.%s", "ramdisk", ext);
dump(hdr.ramdisk_size, name);
page_align(hdr.page_size);
if (hdr.second_size) {
// Dump second
dump(hdr.second_size, "second");
page_align(hdr.page_size);
}
if (hdr.dt_size) {
// Dump dtb
dump(hdr.dt_size, "dtb");
page_align(hdr.page_size);
}
return 0;
}
int unpack(const char* image) {
int fd = open(image, O_RDONLY), ret = 0;
if (fd < 0)
error(1, "Cannot open %s", image);
size_t size = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
unsigned char *orig = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
// Check headers
// Parse images
for(base = orig; base < (orig + size); base += 256) {
if (memcmp(base, CHROMEOS_MAGIC, CHROMEOS_MAGIC_SIZE) == 0) {
dump(0, "chromeos");
dump(base, 0, "chromeos");
} else if (memcmp(base, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) {
ret = aosp();
parse_aosp();
break;
} else if (memcmp(base, ELF_MAGIC, ELF_MAGIC_SIZE) == 0) {
parse_elf();
break;
}
}
char name[PATH_MAX], *ext;
// Dump kernel
if (memcmp(kernel, "\x88\x16\x88\x58", 4) == 0) {
printf("MTK header found in kernel\n");
kernel += 512;
hdr.kernel_size -= 512;
}
dump(kernel, hdr.kernel_size, "kernel");
// Dump ramdisk
if (memcmp(ramdisk, "\x88\x16\x88\x58", 4) == 0) {
printf("MTK header found in ramdisk\n");
ramdisk += 512;
hdr.ramdisk_size -= 512;
}
// Compression detection
if (memcmp(ramdisk, "\x1f\x8b\x08\x00", 4) == 0) {
// gzip header
printf("COMPRESSION [gzip]\n");
ext = "gz";
} else if (memcmp(ramdisk, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9) == 0) {
// lzop header
printf("COMPRESSION [lzop]\n");
ext = "lzo";
} else if (memcmp(ramdisk, "\xfd""7zXZ\x00", 6) == 0) {
// xz header
printf("COMPRESSION [xz]\n");
ext = "xz";
} else if (memcmp(ramdisk, "\x5d\x00\x00", 3) == 0
&& (ramdisk[12] == (unsigned char) '\xff' || ramdisk[12] == (unsigned char) '\x00')) {
// lzma header
printf("COMPRESSION [lzma]\n");
ext = "lzma";
} else if (memcmp(ramdisk, "BZh", 3) == 0) {
// bzip2 header
printf("COMPRESSION [bzip2]\n");
ext = "bz2";
} else if ( ( memcmp(ramdisk, "\x04\x22\x4d\x18", 4) == 0
|| memcmp(ramdisk, "\x03\x21\x4c\x18", 4) == 0)
|| memcmp(ramdisk, "\x02\x21\x4c\x18", 4) == 0) {
// lz4 header
printf("COMPRESSION [lz4]\n");
ext = "lz4";
} else {
error(1, "Unknown ramdisk format!");
}
sprintf(name, "%s.%s", "ramdisk", ext);
dump(ramdisk, hdr.ramdisk_size, name);
if (hdr.second_size) {
// Dump second
dump(second, hdr.second_size, "second");
}
if (hdr.dt_size) {
// Dump dtb
dump(dtb, hdr.dt_size, "dtb");
}
munmap(orig, size);
close(fd);
return ret;