mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 12:17:38 +00:00
Add ELF support
This commit is contained in:
parent
6f609f0dd7
commit
7ef0746c52
@ -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)
|
||||
|
@ -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
149
jni/bootimgtools/elf.h
Normal 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
|
@ -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
232
jni/bootimgtools/parseimg.c
Normal 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();
|
||||
}
|
@ -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,39 +32,51 @@ 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;
|
||||
@ -72,27 +84,24 @@ static int aosp() {
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user