Add support to PXA devices

Close #340
This commit is contained in:
topjohnwu 2018-01-29 02:44:30 +08:00
parent c471bb6f67
commit eed86c760f
5 changed files with 208 additions and 136 deletions

View File

@ -13,6 +13,14 @@
#define ELF32_RET 4
#define ELF64_RET 5
// Macros to determine header on-the-go
#define lheader(b, e, o) \
((b)->flags & PXA_FLAG) ? \
(((struct pxa_boot_img_hdr*) (b)->hdr)->e o) : \
(((struct boot_img_hdr*) (b)->hdr)->e o)
#define header(b, e) (lheader(b, e,))
static void dump(void *buf, size_t size, const char *filename) {
int fd = creat(filename, 0644);
xwrite(fd, buf, size);
@ -32,29 +40,42 @@ static void restore_buf(int fd, const void *buf, size_t size) {
xwrite(fd, buf, size);
}
static void print_hdr(const boot_img_hdr *hdr) {
fprintf(stderr, "KERNEL [%d] @ 0x%08x\n", hdr->kernel_size, hdr->kernel_addr);
fprintf(stderr, "RAMDISK [%d] @ 0x%08x\n", hdr->ramdisk_size, hdr->ramdisk_addr);
fprintf(stderr, "SECOND [%d] @ 0x%08x\n", hdr->second_size, hdr->second_addr);
fprintf(stderr, "EXTRA [%d] @ 0x%08x\n", hdr->extra_size, hdr->tags_addr);
fprintf(stderr, "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;
static void print_hdr(const boot_img *boot) {
fprintf(stderr, "KERNEL [%u]\n", header(boot, kernel_size));
fprintf(stderr, "RAMDISK [%u]\n", header(boot, ramdisk_size));
fprintf(stderr, "SECOND [%u]\n", header(boot, second_size));
fprintf(stderr, "EXTRA [%u]\n", header(boot, extra_size));
fprintf(stderr, "PAGESIZE [%u]\n", header(boot, page_size));
a = (os_version >> 14) & 0x7f;
b = (os_version >> 7) & 0x7f;
c = os_version & 0x7f;
fprintf(stderr, "OS_VERSION [%d.%d.%d]\n", a, b, c);
if (!(boot->flags & PXA_FLAG)) {
uint32_t os_version = ((boot_img_hdr*) boot->hdr)->os_version;
if (os_version) {
int a,b,c,y,m = 0;
int version, patch_level;
version = os_version >> 11;
patch_level = os_version & 0x7ff;
y = (os_patch_level >> 4) + 2000;
m = os_patch_level & 0xf;
fprintf(stderr, "PATCH_LEVEL [%d-%02d]\n", y, m);
a = (version >> 14) & 0x7f;
b = (version >> 7) & 0x7f;
c = version & 0x7f;
fprintf(stderr, "OS_VERSION [%d.%d.%d]\n", a, b, c);
y = (patch_level >> 4) + 2000;
m = patch_level & 0xf;
fprintf(stderr, "PATCH_LEVEL [%d-%02d]\n", y, m);
}
}
fprintf(stderr, "NAME [%s]\n", hdr->name);
fprintf(stderr, "CMDLINE [%s]\n", hdr->cmdline);
fprintf(stderr, "NAME [%s]\n", header(boot, name));
fprintf(stderr, "CMDLINE [%s]\n", header(boot, cmdline));
}
static void clean_boot(boot_img *boot) {
munmap(boot->map_addr, boot->map_size);
free(boot->hdr);
free(boot->k_hdr);
free(boot->r_hdr);
memset(boot, 0, sizeof(*boot));
}
int parse_img(const char *image, boot_img *boot) {
@ -77,29 +98,37 @@ int parse_img(const char *image, boot_img *boot) {
exit(ELF64_RET);
case AOSP:
// Read the header
memcpy(&boot->hdr, head + pos, sizeof(boot->hdr));
pos += boot->hdr.page_size;
if (((boot_img_hdr*) head)->page_size >= 0x02000000) {
boot->flags |= PXA_FLAG;
fprintf(stderr, "PXA_BOOT_HDR\n");
boot->hdr = malloc(sizeof(pxa_boot_img_hdr));
memcpy(boot->hdr, head, sizeof(pxa_boot_img_hdr));
} else {
boot->hdr = malloc(sizeof(boot_img_hdr));
memcpy(boot->hdr, head, sizeof(boot_img_hdr));
}
pos += header(boot, page_size);
print_hdr(&boot->hdr);
print_hdr(boot);
boot->kernel = head + pos;
pos += boot->hdr.kernel_size;
mem_align(&pos, boot->hdr.page_size);
pos += header(boot, kernel_size);
mem_align(&pos, header(boot, page_size));
boot->ramdisk = head + pos;
pos += boot->hdr.ramdisk_size;
mem_align(&pos, boot->hdr.page_size);
pos += header(boot, ramdisk_size);
mem_align(&pos, header(boot, page_size));
if (boot->hdr.second_size) {
if (header(boot, second_size)) {
boot->second = head + pos;
pos += boot->hdr.second_size;
mem_align(&pos, boot->hdr.page_size);
pos += header(boot, second_size);
mem_align(&pos, header(boot, page_size));
}
if (boot->hdr.extra_size) {
if (header(boot, extra_size)) {
boot->extra = head + pos;
pos += boot->hdr.extra_size;
mem_align(&pos, boot->hdr.page_size);
pos += header(boot, extra_size);
mem_align(&pos, header(boot, page_size));
}
if (pos < boot->map_size) {
@ -108,33 +137,40 @@ int parse_img(const char *image, boot_img *boot) {
}
// Search for dtb in kernel
for (uint32_t i = 0; i < boot->hdr.kernel_size; ++i) {
for (uint32_t i = 0; i < header(boot, kernel_size); ++i) {
if (memcmp(boot->kernel + i, DTB_MAGIC, 4) == 0) {
boot->dtb = boot->kernel + i;
boot->dt_size = boot->hdr.kernel_size - i;
boot->hdr.kernel_size = i;
boot->dt_size = header(boot, kernel_size) - i;
lheader(boot, kernel_size, = i);
fprintf(stderr, "DTB [%u]\n", boot->dt_size);
break;
}
}
boot->ramdisk_type = check_type(boot->ramdisk);
boot->kernel_type = check_type(boot->kernel);
boot->ramdisk_type = check_type(boot->ramdisk);
// Check MTK
if (boot->kernel_type == MTK) {
fprintf(stderr, "MTK_KERNEL_HDR [512]\n");
fprintf(stderr, "MTK_KERNEL_HDR\n");
boot->flags |= MTK_KERNEL;
memcpy(&boot->mtk_kernel_hdr, boot->kernel, sizeof(mtk_hdr));
boot->k_hdr = malloc(sizeof(mtk_hdr));
memcpy(boot->k_hdr, boot->kernel, sizeof(mtk_hdr));
fprintf(stderr, "KERNEL [%u]\n", boot->k_hdr->size);
fprintf(stderr, "NAME [%s]\n", boot->k_hdr->name);
boot->kernel += 512;
boot->hdr.kernel_size -= 512;
lheader(boot, kernel_size, -= 512);
boot->kernel_type = check_type(boot->kernel);
}
if (boot->ramdisk_type == MTK) {
fprintf(stderr, "MTK_RAMDISK_HDR [512]\n");
fprintf(stderr, "MTK_RAMDISK_HDR\n");
boot->flags |= MTK_RAMDISK;
memcpy(&boot->mtk_ramdisk_hdr, boot->ramdisk, sizeof(mtk_hdr));
boot->r_hdr = malloc(sizeof(mtk_hdr));
memcpy(boot->r_hdr, boot->kernel, sizeof(mtk_hdr));
fprintf(stderr, "RAMDISK [%u]\n", boot->r_hdr->size);
fprintf(stderr, "NAME [%s]\n", boot->r_hdr->name);
boot->ramdisk += 512;
boot->hdr.ramdisk_size -= 512;
lheader(boot, ramdisk_size, -= 512);
boot->ramdisk_type = check_type(boot->ramdisk);
}
@ -154,7 +190,7 @@ int parse_img(const char *image, boot_img *boot) {
LOGE("No boot image magic found!\n");
}
void unpack(const char* image) {
int unpack(const char *image) {
boot_img boot;
int ret = parse_img(image, &boot);
int fd;
@ -162,10 +198,10 @@ void unpack(const char* image) {
// Dump kernel
if (COMPRESSED(boot.kernel_type)) {
fd = creat(KERNEL_FILE, 0644);
decomp(boot.kernel_type, fd, boot.kernel, boot.hdr.kernel_size);
decomp(boot.kernel_type, fd, boot.kernel, header(&boot, kernel_size));
close(fd);
} else {
dump(boot.kernel, boot.hdr.kernel_size, KERNEL_FILE);
dump(boot.kernel, header(&boot, kernel_size), KERNEL_FILE);
}
if (boot.dt_size) {
@ -176,32 +212,32 @@ void unpack(const char* image) {
// Dump ramdisk
if (COMPRESSED(boot.ramdisk_type)) {
fd = creat(RAMDISK_FILE, 0644);
decomp(boot.ramdisk_type, fd, boot.ramdisk, boot.hdr.ramdisk_size);
decomp(boot.ramdisk_type, fd, boot.ramdisk, header(&boot, ramdisk_size));
close(fd);
} else {
dump(boot.ramdisk, boot.hdr.ramdisk_size, RAMDISK_FILE ".raw");
dump(boot.ramdisk, header(&boot, ramdisk_size), RAMDISK_FILE ".raw");
LOGE("Unknown ramdisk format! Dumped to %s\n", RAMDISK_FILE ".raw");
}
if (boot.hdr.second_size) {
if (header(&boot, second_size)) {
// Dump second
dump(boot.second, boot.hdr.second_size, SECOND_FILE);
dump(boot.second, header(&boot, second_size), SECOND_FILE);
}
if (boot.hdr.extra_size) {
if (header(&boot, extra_size)) {
// Dump extra
dump(boot.extra, boot.hdr.extra_size, EXTRA_FILE);
dump(boot.extra, header(&boot, extra_size), EXTRA_FILE);
}
munmap(boot.map_addr, boot.map_size);
exit(ret);
clean_boot(&boot);
return ret;
}
void repack(const char* orig_image, const char* out_image) {
boot_img boot;
// There are possible two MTK headers
size_t mtk_kernel_off, mtk_ramdisk_off;
off_t mtk_kernel_off, mtk_ramdisk_off;
// Parse original image
parse_img(orig_image, &boot);
@ -212,7 +248,7 @@ void repack(const char* orig_image, const char* out_image) {
int fd = creat(out_image, 0644);
// Skip a page for header
write_zero(fd, boot.hdr.page_size);
write_zero(fd, header(&boot, page_size));
if (boot.flags & MTK_KERNEL) {
// Record position and skip MTK header
@ -223,16 +259,16 @@ void repack(const char* orig_image, const char* out_image) {
size_t raw_size;
void *kernel_raw;
mmap_ro(KERNEL_FILE, &kernel_raw, &raw_size);
boot.hdr.kernel_size = comp(boot.kernel_type, fd, kernel_raw, raw_size);
lheader(&boot, kernel_size, = comp(boot.kernel_type, fd, kernel_raw, raw_size));
munmap(kernel_raw, raw_size);
} else {
boot.hdr.kernel_size = restore(KERNEL_FILE, fd);
lheader(&boot, kernel_size, = restore(KERNEL_FILE, fd));
}
// Restore dtb
if (boot.dt_size && access(DTB_FILE, R_OK) == 0) {
boot.hdr.kernel_size += restore(DTB_FILE, fd);
lheader(&boot, kernel_size, += restore(DTB_FILE, fd));
}
file_align(fd, boot.hdr.page_size, 1);
file_align(fd, header(&boot, page_size), 1);
if (boot.flags & MTK_RAMDISK) {
// Record position and skip MTK header
@ -244,7 +280,7 @@ void repack(const char* orig_image, const char* out_image) {
size_t cpio_size;
void *cpio;
mmap_ro(RAMDISK_FILE, &cpio, &cpio_size);
boot.hdr.ramdisk_size = comp(boot.ramdisk_type, fd, cpio, cpio_size);
lheader(&boot, ramdisk_size, = comp(boot.ramdisk_type, fd, cpio, cpio_size));
munmap(cpio, cpio_size);
} else {
// Find compressed ramdisk
@ -259,20 +295,20 @@ void repack(const char* orig_image, const char* out_image) {
}
if (!found)
LOGE("No ramdisk exists!\n");
boot.hdr.ramdisk_size = restore(name, fd);
lheader(&boot, ramdisk_size, = restore(name, fd));
}
file_align(fd, boot.hdr.page_size, 1);
file_align(fd, header(&boot, page_size), 1);
// Restore second
if (boot.hdr.second_size && access(SECOND_FILE, R_OK) == 0) {
boot.hdr.second_size = restore(SECOND_FILE, fd);
file_align(fd, boot.hdr.page_size, 1);
if (header(&boot, second_size) && access(SECOND_FILE, R_OK) == 0) {
lheader(&boot, second_size, = restore(SECOND_FILE, fd));
file_align(fd, header(&boot, page_size), 1);
}
// Restore extra
if (boot.hdr.extra_size && access(EXTRA_FILE, R_OK) == 0) {
boot.hdr.extra_size = restore(EXTRA_FILE, fd);
file_align(fd, boot.hdr.page_size, 1);
if (header(&boot, extra_size) && access(EXTRA_FILE, R_OK) == 0) {
lheader(&boot, extra_size, = restore(EXTRA_FILE, fd));
file_align(fd, header(&boot, page_size), 1);
}
// Check tail info, currently only for LG Bump and Samsung SEANDROIDENFORCE
@ -286,23 +322,23 @@ void repack(const char* orig_image, const char* out_image) {
// Write MTK headers back
if (boot.flags & MTK_KERNEL) {
lseek(fd, mtk_kernel_off, SEEK_SET);
boot.mtk_kernel_hdr.size = boot.hdr.kernel_size;
boot.hdr.kernel_size += 512;
restore_buf(fd, &boot.mtk_kernel_hdr, sizeof(mtk_hdr));
boot.k_hdr->size = header(&boot, kernel_size);
lheader(&boot, kernel_size, += 512);
restore_buf(fd, boot.k_hdr, sizeof(mtk_hdr));
}
if (boot.flags & MTK_RAMDISK) {
lseek(fd, mtk_ramdisk_off, SEEK_SET);
boot.mtk_ramdisk_hdr.size = boot.hdr.ramdisk_size;
boot.hdr.ramdisk_size += 512;
restore_buf(fd, &boot.mtk_ramdisk_hdr, sizeof(mtk_hdr));
boot.r_hdr->size = header(&boot, ramdisk_size);
lheader(&boot, ramdisk_size, += 512);
restore_buf(fd, boot.r_hdr, sizeof(mtk_hdr));
}
// Main header
lseek(fd, 0, SEEK_SET);
restore_buf(fd, &boot.hdr, sizeof(boot.hdr));
restore_buf(fd, boot.hdr, (boot.flags & PXA_FLAG) ? sizeof(pxa_boot_img_hdr) : sizeof(boot_img_hdr));
// Print new image info
print_hdr(&boot.hdr);
print_hdr(&boot);
munmap(boot.map_addr, boot.map_size);
clean_boot(&boot);
close(fd);
}

View File

@ -21,48 +21,69 @@
#ifndef _BOOT_IMAGE_H_
#define _BOOT_IMAGE_H_
typedef struct boot_img_hdr boot_img_hdr;
#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512
#define BOOT_EXTRA_ARGS_SIZE 1024
struct boot_img_hdr
{
uint8_t magic[BOOT_MAGIC_SIZE];
typedef struct boot_img_hdr {
char magic[8];
uint32_t kernel_size; /* size in bytes */
uint32_t kernel_addr; /* physical load addr */
uint32_t kernel_size; /* size in bytes */
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t second_size; /* size in bytes */
uint32_t second_addr; /* physical load addr */
uint32_t second_size; /* size in bytes */
uint32_t second_addr; /* physical load addr */
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
uint32_t extra_size; /* extra blob size in bytes */
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
uint32_t extra_size; /* extra blob size in bytes */
/* operating system version and security patch level; for
* version "A.B.C" and patch level "Y-M-D":
* ver = A << 14 | B << 7 | C (7 bits for each of A, B, C)
* lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M)
* os_version = ver << 11 | lvl */
uint32_t os_version;
/* operating system version and security patch level; for
* version "A.B.C" and patch level "Y-M-D":
* ver = A << 14 | B << 7 | C (7 bits for each of A, B, C)
* lvl = ((Y - 2000) & 127) << 4 | M (7 bits for Y, 4 bits for M)
* os_version = ver << 11 | lvl */
uint32_t os_version;
uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */
char name[16]; /* asciiz product name */
uint8_t cmdline[BOOT_ARGS_SIZE];
char cmdline[512];
uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
/* Supplemental command line data; kept here to maintain
* binary compatibility with older versions of mkbootimg */
uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
} __attribute__((packed));
/* Supplemental command line data; kept here to maintain
* binary compatibility with older versions of mkbootimg */
char extra_cmdline[1024];
} __attribute__((packed)) boot_img_hdr ;
typedef struct pxa_boot_img_hdr {
char magic[8];
uint32_t kernel_size; /* size in bytes */
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t second_size; /* size in bytes */
uint32_t second_addr; /* physical load addr */
uint32_t extra_size; /* extra blob size in bytes */
uint32_t unknown; /* unknown value */
uint32_t tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
char name[24]; /* asciiz product name */
char cmdline[512];
uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
/* Supplemental command line data; kept here to maintain
* binary compatibility with older versions of mkbootimg */
char extra_cmdline[1024];
} __attribute__((packed)) pxa_boot_img_hdr;
/*
** +-----------------+
@ -74,7 +95,7 @@ struct boot_img_hdr
** +-----------------+
** | second stage | o pages
** +-----------------+
** | extra blobs | p pages
** | extra blob | p pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
@ -95,33 +116,47 @@ struct boot_img_hdr
*/
typedef struct mtk_hdr {
uint8_t magic[4]; /* MTK magic */
uint32_t size; /* Size of the content */
uint8_t name[32]; /* The type of the header */
} mtk_hdr;
uint32_t magic; /* MTK magic */
uint32_t size; /* Size of the content */
char name[32]; /* The type of the header */
} __attribute__((packed)) mtk_hdr;
// Flags
#define MTK_KERNEL 0x1
#define MTK_RAMDISK 0x2
#define CHROMEOS_FLAG 0x4
#define MTK_KERNEL 0x01
#define MTK_RAMDISK 0x02
#define CHROMEOS_FLAG 0x04
#define PXA_FLAG 0x08
typedef struct boot_img {
size_t map_size;
uint32_t dt_size;
size_t tail_size;
uint8_t flags;
file_t kernel_type, ramdisk_type;
// Memory map of the whole image
void *map_addr;
size_t map_size;
boot_img_hdr hdr;
mtk_hdr mtk_kernel_hdr, mtk_ramdisk_hdr;
// Headers
void *hdr; /* Either boot_img_hdr or pxa_boot_img_hdr */
mtk_hdr *k_hdr; /* MTK kernel header */
mtk_hdr *r_hdr; /* MTK ramdisk header */
void *map_addr;
void *kernel;
void *dtb;
void *ramdisk;
void *second;
void *extra;
void *tail;
// Flags to indicate the state of current boot image
uint8_t flags;
// The format of kernel and ramdisk
file_t kernel_type;
file_t ramdisk_type;
// Pointer to dtb that is appended after kernel
void *dtb;
uint32_t dt_size;
// Pointer to end of image
void *tail;
size_t tail_size;
// Pointers to blocks defined in header
void *kernel;
void *ramdisk;
void *second;
void *extra;
} boot_img;
#endif

View File

@ -14,7 +14,7 @@
#define NEW_BOOT "new-boot.img"
// Main entries
void unpack(const char *image);
int unpack(const char *image);
void repack(const char* orig_image, const char* out_image);
void hexpatch(const char *image, const char *from, const char *to);
int parse_img(const char *image, boot_img *boot);

View File

@ -136,9 +136,9 @@ int main(int argc, char *argv[]) {
munmap(buf, size);
} else if (argc > 2 && strcmp(argv[1], "--parse") == 0) {
boot_img boot;
exit(parse_img(argv[2], &boot));
return parse_img(argv[2], &boot);
} else if (argc > 2 && strcmp(argv[1], "--unpack") == 0) {
unpack(argv[2]);
return unpack(argv[2]);
} else if (argc > 2 && strcmp(argv[1], "--repack") == 0) {
repack(argv[2], argc > 3 ? argv[3] : NEW_BOOT);
} else if (argc > 2 && strcmp(argv[1], "--decompress") == 0) {
@ -157,7 +157,8 @@ int main(int argc, char *argv[]) {
char *cmd = argv[1] + 5;
if (*cmd == '\0') usage(argv[0]);
else ++cmd;
if (dtb_commands(cmd, argc - 2, argv + 2)) usage(argv[0]);
if (dtb_commands(cmd, argc - 2, argv + 2))
usage(argv[0]);
} else {
usage(argv[0]);
}

View File

@ -6,7 +6,7 @@
file_t check_type(const void *buf) {
if (memcmp(buf, CHROMEOS_MAGIC, 8) == 0) {
return CHROMEOS;
} else if (memcmp(buf, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0) {
} else if (memcmp(buf, BOOT_MAGIC, 8) == 0) {
return AOSP;
} else if (memcmp(buf, ELF32_MAGIC, 5) == 0) {
return ELF32;