mirror of
https://github.com/anestisb/android-unpackbootimg.git
synced 2024-05-16 10:59:32 +00:00
Update code from upstream
Signed-off-by: Anestis Bechtsoudis <anestis@census-labs.com>
This commit is contained in:
parent
f4be990773
commit
bf6bc5de36
2
Makefile
2
Makefile
|
@ -4,7 +4,7 @@ DEP_CC ?= gcc
|
|||
AR ?= ar
|
||||
RANLIB ?= ranlib
|
||||
STRIP ?= strip
|
||||
CFLAGS += -O2 -Wall -Werror
|
||||
CFLAGS += -O2 -Wall -Werror -Wno-address-of-packed-member
|
||||
LDFLAGS +=
|
||||
|
||||
# libmincrypt
|
||||
|
|
49
bootimg.h
49
bootimg.h
|
@ -15,6 +15,8 @@
|
|||
** limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef _BOOT_IMAGE_H_
|
||||
#define _BOOT_IMAGE_H_
|
||||
|
||||
|
@ -24,30 +26,42 @@ typedef struct boot_img_hdr boot_img_hdr;
|
|||
#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
|
||||
{
|
||||
unsigned char magic[BOOT_MAGIC_SIZE];
|
||||
uint8_t magic[BOOT_MAGIC_SIZE];
|
||||
|
||||
unsigned kernel_size; /* size in bytes */
|
||||
unsigned kernel_addr; /* physical load addr */
|
||||
uint32_t kernel_size; /* size in bytes */
|
||||
uint32_t kernel_addr; /* physical load addr */
|
||||
|
||||
unsigned ramdisk_size; /* size in bytes */
|
||||
unsigned ramdisk_addr; /* physical load addr */
|
||||
uint32_t ramdisk_size; /* size in bytes */
|
||||
uint32_t ramdisk_addr; /* physical load addr */
|
||||
|
||||
unsigned second_size; /* size in bytes */
|
||||
unsigned second_addr; /* physical load addr */
|
||||
uint32_t second_size; /* size in bytes */
|
||||
uint32_t second_addr; /* physical load addr */
|
||||
|
||||
unsigned tags_addr; /* physical addr for kernel tags */
|
||||
unsigned page_size; /* flash page size we assume */
|
||||
unsigned unused[2]; /* future expansion: should be 0 */
|
||||
uint32_t tags_addr; /* physical addr for kernel tags */
|
||||
uint32_t page_size; /* flash page size we assume */
|
||||
uint32_t dt_size; /* device tree in bytes */
|
||||
|
||||
unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
|
||||
|
||||
unsigned char cmdline[BOOT_ARGS_SIZE];
|
||||
/* 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;
|
||||
|
||||
unsigned id[8]; /* timestamp / checksum / sha1 / etc */
|
||||
};
|
||||
uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */
|
||||
|
||||
uint8_t cmdline[BOOT_ARGS_SIZE];
|
||||
|
||||
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));
|
||||
|
||||
/*
|
||||
** +-----------------+
|
||||
|
@ -59,10 +73,13 @@ struct boot_img_hdr
|
|||
** +-----------------+
|
||||
** | second stage | o pages
|
||||
** +-----------------+
|
||||
** | device tree | p pages
|
||||
** +-----------------+
|
||||
**
|
||||
** n = (kernel_size + page_size - 1) / page_size
|
||||
** m = (ramdisk_size + page_size - 1) / page_size
|
||||
** o = (second_size + page_size - 1) / page_size
|
||||
** p = (dt_size + page_size - 1) / page_size
|
||||
**
|
||||
** 0. all entities are page_size aligned in flash
|
||||
** 1. kernel and ramdisk are required (size != 0)
|
||||
|
@ -78,14 +95,12 @@ struct boot_img_hdr
|
|||
|
||||
#if 0
|
||||
typedef struct ptentry ptentry;
|
||||
|
||||
struct ptentry {
|
||||
char name[16]; /* asciiz partition name */
|
||||
unsigned start; /* starting block number */
|
||||
unsigned length; /* length in blocks */
|
||||
unsigned flags; /* set to zero */
|
||||
};
|
||||
|
||||
/* MSM Partition Table ATAG
|
||||
**
|
||||
** length: 2 + 7 * n
|
||||
|
|
345
mkbootimg.c
345
mkbootimg.c
|
@ -21,8 +21,10 @@
|
|||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "mincrypt/sha.h"
|
||||
#include "mincrypt/sha256.h"
|
||||
#include "bootimg.h"
|
||||
|
||||
static void *load_file(const char *fn, unsigned *_sz)
|
||||
|
@ -59,13 +61,21 @@ int usage(void)
|
|||
{
|
||||
fprintf(stderr,"usage: mkbootimg\n"
|
||||
" --kernel <filename>\n"
|
||||
" --ramdisk <filename>\n"
|
||||
" [ --ramdisk <filename> ]\n"
|
||||
" [ --second <2ndbootloader-filename> ]\n"
|
||||
" [ --cmdline <kernel-commandline> ]\n"
|
||||
" [ --board <boardname> ]\n"
|
||||
" [ --base <address> ]\n"
|
||||
" [ --pagesize <pagesize> ]\n"
|
||||
" [ --ramdiskaddr <address> ]\n"
|
||||
" [ --dt <filename> ]\n"
|
||||
" [ --kernel_offset <base offset> ]\n"
|
||||
" [ --ramdisk_offset <base offset> ]\n"
|
||||
" [ --second_offset <base offset> ]\n"
|
||||
" [ --tags_offset <base offset> ]\n"
|
||||
" [ --os_version <A.B.C version> ]\n"
|
||||
" [ --os_patch_level <YYYY-MM-DD date> ]\n"
|
||||
" [ --hash <sha1(default)|sha256> ]\n"
|
||||
" [ --id ]\n"
|
||||
" -o|--output <filename>\n"
|
||||
);
|
||||
return 1;
|
||||
|
@ -73,12 +83,21 @@ int usage(void)
|
|||
|
||||
|
||||
|
||||
static unsigned char padding[4096] = { 0, };
|
||||
static unsigned char padding[131072] = { 0, };
|
||||
|
||||
static void print_id(const uint8_t *id, size_t id_len) {
|
||||
printf("0x");
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < id_len; i++) {
|
||||
printf("%02x", id[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int write_padding(int fd, unsigned pagesize, unsigned itemsize)
|
||||
{
|
||||
unsigned pagemask = pagesize - 1;
|
||||
unsigned count;
|
||||
ssize_t count;
|
||||
|
||||
if((itemsize & pagemask) == 0) {
|
||||
return 0;
|
||||
|
@ -86,75 +105,234 @@ int write_padding(int fd, unsigned pagesize, unsigned itemsize)
|
|||
|
||||
count = pagesize - (itemsize & pagemask);
|
||||
|
||||
if(write(fd, padding, count) != (signed)count) {
|
||||
if(write(fd, padding, count) != count) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int parse_os_version(char *ver)
|
||||
{
|
||||
char *token;
|
||||
int verArray[3] = {0};
|
||||
int a,b,c = 0;
|
||||
int i = 0;
|
||||
|
||||
token = strtok(ver, ".");
|
||||
while(token != NULL) {
|
||||
sscanf(token, "%d", &verArray[i]);
|
||||
token = strtok(NULL, ".");
|
||||
i++;
|
||||
}
|
||||
a = verArray[0];
|
||||
b = verArray[1];
|
||||
c = verArray[2];
|
||||
if((a < 128) && (b < 128) && (c < 128))
|
||||
return (a << 14) | (b << 7) | c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_os_patch_level(char *lvl)
|
||||
{
|
||||
char *token;
|
||||
int lvlArray[2] = {0};
|
||||
int y,m = 0;
|
||||
int i = 0;
|
||||
|
||||
token = strtok(lvl, "-");
|
||||
while(token != NULL) {
|
||||
sscanf(token, "%d", &lvlArray[i]);
|
||||
token = strtok(NULL, "-");
|
||||
i++;
|
||||
}
|
||||
y = lvlArray[0] - 2000;
|
||||
m = lvlArray[1];
|
||||
if((y >= 0) && (y < 128) && (m > 0) && (m <= 12))
|
||||
return (y << 4) | m;
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum hash_alg {
|
||||
HASH_UNKNOWN = -1,
|
||||
HASH_SHA1 = 0,
|
||||
HASH_SHA256,
|
||||
};
|
||||
|
||||
struct hash_name {
|
||||
const char *name;
|
||||
enum hash_alg alg;
|
||||
};
|
||||
|
||||
const struct hash_name hash_names[] = {
|
||||
{ "sha1", HASH_SHA1 },
|
||||
{ "sha256", HASH_SHA256 },
|
||||
{ NULL, /* Sentinel */ },
|
||||
};
|
||||
|
||||
enum hash_alg parse_hash_alg(char *name)
|
||||
{
|
||||
const struct hash_name *ptr = hash_names;
|
||||
|
||||
while (ptr->name) {
|
||||
if (!strcmp(ptr->name, name))
|
||||
return ptr->alg;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return HASH_UNKNOWN;
|
||||
}
|
||||
|
||||
void generate_id_sha1(boot_img_hdr *hdr, void *kernel_data, void *ramdisk_data,
|
||||
void *second_data, void *dt_data)
|
||||
{
|
||||
SHA_CTX ctx;
|
||||
const uint8_t *sha;
|
||||
|
||||
SHA_init(&ctx);
|
||||
SHA_update(&ctx, kernel_data, hdr->kernel_size);
|
||||
SHA_update(&ctx, &hdr->kernel_size, sizeof(hdr->kernel_size));
|
||||
SHA_update(&ctx, ramdisk_data, hdr->ramdisk_size);
|
||||
SHA_update(&ctx, &hdr->ramdisk_size, sizeof(hdr->ramdisk_size));
|
||||
SHA_update(&ctx, second_data, hdr->second_size);
|
||||
SHA_update(&ctx, &hdr->second_size, sizeof(hdr->second_size));
|
||||
if(dt_data) {
|
||||
SHA_update(&ctx, dt_data, hdr->dt_size);
|
||||
SHA_update(&ctx, &hdr->dt_size, sizeof(hdr->dt_size));
|
||||
}
|
||||
sha = SHA_final(&ctx);
|
||||
memcpy(hdr->id, sha,
|
||||
SHA_DIGEST_SIZE > sizeof(hdr->id) ? sizeof(hdr->id) : SHA_DIGEST_SIZE);
|
||||
}
|
||||
|
||||
void generate_id_sha256(boot_img_hdr *hdr, void *kernel_data, void *ramdisk_data,
|
||||
void *second_data, void *dt_data)
|
||||
{
|
||||
SHA256_CTX ctx;
|
||||
const uint8_t *sha;
|
||||
|
||||
SHA256_init(&ctx);
|
||||
SHA256_update(&ctx, kernel_data, hdr->kernel_size);
|
||||
SHA256_update(&ctx, &hdr->kernel_size, sizeof(hdr->kernel_size));
|
||||
SHA256_update(&ctx, ramdisk_data, hdr->ramdisk_size);
|
||||
SHA256_update(&ctx, &hdr->ramdisk_size, sizeof(hdr->ramdisk_size));
|
||||
SHA256_update(&ctx, second_data, hdr->second_size);
|
||||
SHA256_update(&ctx, &hdr->second_size, sizeof(hdr->second_size));
|
||||
if(dt_data) {
|
||||
SHA256_update(&ctx, dt_data, hdr->dt_size);
|
||||
SHA256_update(&ctx, &hdr->dt_size, sizeof(hdr->dt_size));
|
||||
}
|
||||
sha = SHA256_final(&ctx);
|
||||
memcpy(hdr->id, sha,
|
||||
SHA256_DIGEST_SIZE > sizeof(hdr->id) ? sizeof(hdr->id) : SHA256_DIGEST_SIZE);
|
||||
}
|
||||
|
||||
void generate_id(enum hash_alg alg, boot_img_hdr *hdr, void *kernel_data,
|
||||
void *ramdisk_data, void *second_data, void *dt_data)
|
||||
{
|
||||
switch (alg) {
|
||||
case HASH_SHA1:
|
||||
generate_id_sha1(hdr, kernel_data, ramdisk_data,
|
||||
second_data, dt_data);
|
||||
break;
|
||||
case HASH_SHA256:
|
||||
generate_id_sha256(hdr, kernel_data, ramdisk_data,
|
||||
second_data, dt_data);
|
||||
break;
|
||||
case HASH_UNKNOWN:
|
||||
default:
|
||||
fprintf(stderr, "Unknown hash type.\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
boot_img_hdr hdr;
|
||||
|
||||
char *kernel_fn = 0;
|
||||
void *kernel_data = 0;
|
||||
char *ramdisk_fn = 0;
|
||||
void *ramdisk_data = 0;
|
||||
char *second_fn = 0;
|
||||
void *second_data = 0;
|
||||
char *kernel_fn = NULL;
|
||||
void *kernel_data = NULL;
|
||||
char *ramdisk_fn = NULL;
|
||||
void *ramdisk_data = NULL;
|
||||
char *second_fn = NULL;
|
||||
void *second_data = NULL;
|
||||
char *cmdline = "";
|
||||
char *bootimg = 0;
|
||||
char *bootimg = NULL;
|
||||
char *board = "";
|
||||
unsigned pagesize = 2048;
|
||||
int os_version = 0;
|
||||
int os_patch_level = 0;
|
||||
char *dt_fn = NULL;
|
||||
void *dt_data = NULL;
|
||||
uint32_t pagesize = 2048;
|
||||
int fd;
|
||||
SHA_CTX ctx;
|
||||
const uint8_t* sha;
|
||||
uint32_t base = 0x10000000U;
|
||||
uint32_t kernel_offset = 0x00008000U;
|
||||
uint32_t ramdisk_offset = 0x01000000U;
|
||||
uint32_t second_offset = 0x00f00000U;
|
||||
uint32_t tags_offset = 0x00000100U;
|
||||
size_t cmdlen;
|
||||
enum hash_alg hash_alg = HASH_SHA1;
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
|
||||
/* default load addresses */
|
||||
hdr.kernel_addr = 0x10008000;
|
||||
hdr.ramdisk_addr = 0x11000000;
|
||||
hdr.second_addr = 0x10F00000;
|
||||
hdr.tags_addr = 0x10000100;
|
||||
|
||||
bool get_id = false;
|
||||
while(argc > 0){
|
||||
char *arg = argv[0];
|
||||
char *val = argv[1];
|
||||
if(argc < 2) {
|
||||
return usage();
|
||||
}
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) {
|
||||
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 if(!strcmp(arg, "--cmdline")) {
|
||||
cmdline = val;
|
||||
} else if(!strcmp(arg, "--base")) {
|
||||
unsigned base = strtoul(val, 0, 16);
|
||||
hdr.kernel_addr = base + 0x00008000;
|
||||
hdr.ramdisk_addr = base + 0x01000000;
|
||||
hdr.second_addr = base + 0x00F00000;
|
||||
hdr.tags_addr = base + 0x00000100;
|
||||
} else if(!strcmp(arg, "--ramdiskaddr")) {
|
||||
hdr.ramdisk_addr = strtoul(val, 0, 16);
|
||||
} else if(!strcmp(arg, "--board")) {
|
||||
board = val;
|
||||
} else if(!strcmp(arg,"--pagesize")) {
|
||||
pagesize = strtoul(val, 0, 10);
|
||||
if ((pagesize != 2048) && (pagesize != 4096)) {
|
||||
fprintf(stderr,"error: unsupported page size %d\n", pagesize);
|
||||
return -1;
|
||||
if (!strcmp(arg, "--id")) {
|
||||
get_id = true;
|
||||
argc -= 1;
|
||||
argv += 1;
|
||||
} else if(argc >= 2) {
|
||||
char *val = argv[1];
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) {
|
||||
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 if(!strcmp(arg, "--cmdline")) {
|
||||
cmdline = val;
|
||||
} else if(!strcmp(arg, "--base")) {
|
||||
base = strtoul(val, 0, 16);
|
||||
} else if(!strcmp(arg, "--kernel_offset")) {
|
||||
kernel_offset = strtoul(val, 0, 16);
|
||||
} else if(!strcmp(arg, "--ramdisk_offset")) {
|
||||
ramdisk_offset = strtoul(val, 0, 16);
|
||||
} else if(!strcmp(arg, "--second_offset")) {
|
||||
second_offset = strtoul(val, 0, 16);
|
||||
} else if(!strcmp(arg, "--tags_offset")) {
|
||||
tags_offset = strtoul(val, 0, 16);
|
||||
} else if(!strcmp(arg, "--board")) {
|
||||
board = val;
|
||||
} else if(!strcmp(arg,"--pagesize")) {
|
||||
pagesize = strtoul(val, 0, 10);
|
||||
if ((pagesize != 2048) && (pagesize != 4096)
|
||||
&& (pagesize != 8192) && (pagesize != 16384)
|
||||
&& (pagesize != 32768) && (pagesize != 65536)
|
||||
&& (pagesize != 131072)) {
|
||||
fprintf(stderr,"error: unsupported page size %d\n", pagesize);
|
||||
return -1;
|
||||
}
|
||||
} else if(!strcmp(arg, "--dt")) {
|
||||
dt_fn = val;
|
||||
} else if(!strcmp(arg, "--os_version")) {
|
||||
os_version = parse_os_version(val);
|
||||
} else if(!strcmp(arg, "--os_patch_level")) {
|
||||
os_patch_level = parse_os_patch_level(val);
|
||||
} else if(!strcmp(arg, "--hash")) {
|
||||
hash_alg = parse_hash_alg(val);
|
||||
if (hash_alg == HASH_UNKNOWN) {
|
||||
fprintf(stderr, "error: unknown hash algorithm '%s'\n", val);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return usage();
|
||||
}
|
||||
} else {
|
||||
return usage();
|
||||
|
@ -162,6 +340,12 @@ int main(int argc, char **argv)
|
|||
}
|
||||
hdr.page_size = pagesize;
|
||||
|
||||
hdr.kernel_addr = base + kernel_offset;
|
||||
hdr.ramdisk_addr = base + ramdisk_offset;
|
||||
hdr.second_addr = base + second_offset;
|
||||
hdr.tags_addr = base + tags_offset;
|
||||
|
||||
hdr.os_version = (os_version << 11) | os_patch_level;
|
||||
|
||||
if(bootimg == 0) {
|
||||
fprintf(stderr,"error: no output filename specified\n");
|
||||
|
@ -173,25 +357,28 @@ int main(int argc, char **argv)
|
|||
return usage();
|
||||
}
|
||||
|
||||
if(ramdisk_fn == 0) {
|
||||
fprintf(stderr,"error: no ramdisk image specified\n");
|
||||
return usage();
|
||||
}
|
||||
|
||||
if(strlen(board) >= BOOT_NAME_SIZE) {
|
||||
fprintf(stderr,"error: board name too large\n");
|
||||
return usage();
|
||||
}
|
||||
|
||||
strcpy((char *)hdr.name, board);
|
||||
strcpy((char *) hdr.name, board);
|
||||
|
||||
memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
|
||||
|
||||
if(strlen(cmdline) > (BOOT_ARGS_SIZE - 1)) {
|
||||
cmdlen = strlen(cmdline);
|
||||
if(cmdlen > (BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE - 2)) {
|
||||
fprintf(stderr,"error: kernel commandline too large\n");
|
||||
return 1;
|
||||
}
|
||||
strcpy((char*)hdr.cmdline, cmdline);
|
||||
/* Even if we need to use the supplemental field, ensure we
|
||||
* are still NULL-terminated */
|
||||
strncpy((char *)hdr.cmdline, cmdline, BOOT_ARGS_SIZE - 1);
|
||||
hdr.cmdline[BOOT_ARGS_SIZE - 1] = '\0';
|
||||
if (cmdlen >= (BOOT_ARGS_SIZE - 1)) {
|
||||
cmdline += (BOOT_ARGS_SIZE - 1);
|
||||
strncpy((char *)hdr.extra_cmdline, cmdline, BOOT_EXTRA_ARGS_SIZE);
|
||||
}
|
||||
|
||||
kernel_data = load_file(kernel_fn, &hdr.kernel_size);
|
||||
if(kernel_data == 0) {
|
||||
|
@ -199,7 +386,7 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if(!strcmp(ramdisk_fn,"NONE")) {
|
||||
if(ramdisk_fn == 0) {
|
||||
ramdisk_data = 0;
|
||||
hdr.ramdisk_size = 0;
|
||||
} else {
|
||||
|
@ -218,19 +405,19 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
if(dt_fn) {
|
||||
dt_data = load_file(dt_fn, &hdr.dt_size);
|
||||
if (dt_data == 0) {
|
||||
fprintf(stderr,"error: could not load device tree image '%s'\n", dt_fn);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* put a hash of the contents in the header so boot images can be
|
||||
* differentiated based on their first 2k.
|
||||
*/
|
||||
SHA_init(&ctx);
|
||||
SHA_update(&ctx, kernel_data, (int)hdr.kernel_size);
|
||||
SHA_update(&ctx, &hdr.kernel_size, (int)sizeof(hdr.kernel_size));
|
||||
SHA_update(&ctx, ramdisk_data, hdr.ramdisk_size);
|
||||
SHA_update(&ctx, &hdr.ramdisk_size, (int)sizeof(hdr.ramdisk_size));
|
||||
SHA_update(&ctx, second_data, (int)hdr.second_size);
|
||||
SHA_update(&ctx, &hdr.second_size, (int)sizeof(hdr.second_size));
|
||||
sha = SHA_final(&ctx);
|
||||
memcpy(hdr.id, sha,
|
||||
SHA_DIGEST_SIZE > sizeof(hdr.id) ? sizeof(hdr.id) : SHA_DIGEST_SIZE);
|
||||
generate_id(hash_alg, &hdr, kernel_data, ramdisk_data, second_data,
|
||||
dt_data);
|
||||
|
||||
fd = open(bootimg, O_CREAT | O_TRUNC | O_WRONLY, 0644);
|
||||
if(fd < 0) {
|
||||
|
@ -241,17 +428,25 @@ int main(int argc, char **argv)
|
|||
if(write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) goto fail;
|
||||
if(write_padding(fd, pagesize, sizeof(hdr))) goto fail;
|
||||
|
||||
if(write(fd, kernel_data, hdr.kernel_size) != (signed)hdr.kernel_size) goto fail;
|
||||
if(write(fd, kernel_data, hdr.kernel_size) != (ssize_t) hdr.kernel_size) goto fail;
|
||||
if(write_padding(fd, pagesize, hdr.kernel_size)) goto fail;
|
||||
|
||||
if(write(fd, ramdisk_data, hdr.ramdisk_size) != (signed)hdr.ramdisk_size) goto fail;
|
||||
if(write(fd, ramdisk_data, hdr.ramdisk_size) != (ssize_t) hdr.ramdisk_size) goto fail;
|
||||
if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
|
||||
|
||||
if(second_data) {
|
||||
if(write(fd, second_data, hdr.second_size) != (signed)hdr.second_size) goto fail;
|
||||
if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
|
||||
if(write(fd, second_data, hdr.second_size) != (ssize_t) hdr.second_size) goto fail;
|
||||
if(write_padding(fd, pagesize, hdr.second_size)) goto fail;
|
||||
}
|
||||
|
||||
if(dt_data) {
|
||||
if(write(fd, dt_data, hdr.dt_size) != (ssize_t) hdr.dt_size) goto fail;
|
||||
if(write_padding(fd, pagesize, hdr.dt_size)) goto fail;
|
||||
}
|
||||
|
||||
if (get_id) {
|
||||
print_id((uint8_t *) hdr.id, sizeof(hdr.id));
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
|
214
unpackbootimg.c
214
unpackbootimg.c
|
@ -6,6 +6,7 @@
|
|||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <libgen.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "mincrypt/sha.h"
|
||||
#include "bootimg.h"
|
||||
|
@ -25,12 +26,12 @@ int read_padding(FILE* f, unsigned itemsize, int pagesize)
|
|||
|
||||
count = pagesize - (itemsize & pagemask);
|
||||
|
||||
fread(buf, count, 1, f);
|
||||
if(fread(buf, count, 1, f)){};
|
||||
free(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
void write_string_to_file(char* file, char* string)
|
||||
void write_string_to_file(const char* file, const char* string)
|
||||
{
|
||||
FILE* f = fopen(file, "w");
|
||||
fwrite(string, strlen(string), 1, f);
|
||||
|
@ -38,6 +39,27 @@ void write_string_to_file(char* file, char* string)
|
|||
fclose(f);
|
||||
}
|
||||
|
||||
const char *detect_hash_type(const struct boot_img_hdr *hdr)
|
||||
{
|
||||
/*
|
||||
* This isn't a sophisticated or 100% reliable method to detect the hash
|
||||
* type but it's probably good enough.
|
||||
*
|
||||
* sha256 is expected to have no zeroes in the id array
|
||||
* sha1 is expected to have zeroes in id[5], id[6] and id[7]
|
||||
* Zeroes anywhere else probably indicates neither.
|
||||
*/
|
||||
const uint32_t *id = hdr->id;
|
||||
if (id[0] != 0 && id[1] != 0 && id[2] != 0 && id[3] != 0 &&
|
||||
id[4] != 0 && id[5] != 0 && id[6] != 0 && id[7] != 0)
|
||||
return "sha256";
|
||||
else if (id[0] != 0 && id[1] != 0 && id[2] != 0 && id[3] != 0 &&
|
||||
id[4] != 0 && id[5] == 0 && id[6] == 0 && id[7] == 0)
|
||||
return "sha1";
|
||||
else
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
int usage() {
|
||||
printf("usage: unpackbootimg\n");
|
||||
printf("\t-i|--input boot.img\n");
|
||||
|
@ -52,10 +74,10 @@ int main(int argc, char** argv)
|
|||
char* directory = "./";
|
||||
char* filename = NULL;
|
||||
int pagesize = 0;
|
||||
int base = 0;
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
while(argc > 0){
|
||||
char *arg = argv[0];
|
||||
char *val = argv[1];
|
||||
|
@ -71,35 +93,88 @@ int main(int argc, char** argv)
|
|||
return usage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (filename == NULL) {
|
||||
return usage();
|
||||
}
|
||||
|
||||
|
||||
int total_read = 0;
|
||||
FILE* f = fopen(filename, "rb");
|
||||
boot_img_hdr header;
|
||||
|
||||
//printf("Reading header...\n");
|
||||
fread(&header, sizeof(header), 1, f);
|
||||
int i;
|
||||
int seeklimit = 65536;
|
||||
for (i = 0; i <= seeklimit; i++) {
|
||||
fseek(f, i, SEEK_SET);
|
||||
if(fread(tmp, BOOT_MAGIC_SIZE, 1, f)){};
|
||||
if (memcmp(tmp, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0)
|
||||
break;
|
||||
}
|
||||
total_read = i;
|
||||
if (i > seeklimit) {
|
||||
printf("Android boot magic not found.\n");
|
||||
return 1;
|
||||
}
|
||||
fseek(f, i, SEEK_SET);
|
||||
if (i > 0) {
|
||||
printf("Android magic found at: %d\n", i);
|
||||
}
|
||||
|
||||
if(fread(&header, sizeof(header), 1, f)){};
|
||||
base = header.kernel_addr - 0x00008000;
|
||||
printf("BOARD_KERNEL_CMDLINE %s\n", header.cmdline);
|
||||
printf("BOARD_KERNEL_BASE %08x\n", header.kernel_addr - 0x00008000);
|
||||
printf("BOARD_KERNEL_BASE %08x\n", base);
|
||||
printf("BOARD_NAME %s\n", header.name);
|
||||
printf("BOARD_PAGE_SIZE %d\n", header.page_size);
|
||||
|
||||
printf("BOARD_HASH_TYPE %s\n", detect_hash_type(&header));
|
||||
printf("BOARD_KERNEL_OFFSET %08x\n", header.kernel_addr - base);
|
||||
printf("BOARD_RAMDISK_OFFSET %08x\n", header.ramdisk_addr - base);
|
||||
printf("BOARD_SECOND_OFFSET %08x\n", header.second_addr - base);
|
||||
printf("BOARD_TAGS_OFFSET %08x\n", header.tags_addr - base);
|
||||
int a,b,c,y,m = 0;
|
||||
if (header.os_version != 0) {
|
||||
int os_version,os_patch_level;
|
||||
os_version = header.os_version >> 11;
|
||||
os_patch_level = header.os_version&0x7ff;
|
||||
|
||||
a = (os_version >> 14)&0x7f;
|
||||
b = (os_version >> 7)&0x7f;
|
||||
c = os_version&0x7f;
|
||||
|
||||
y = (os_patch_level >> 4) + 2000;
|
||||
m = os_patch_level&0xf;
|
||||
|
||||
if((a < 128) && (b < 128) && (c < 128) && (y >= 2000) && (y < 2128) && (m > 0) && (m <= 12)) {
|
||||
printf("BOARD_OS_VERSION %d.%d.%d\n", a, b, c);
|
||||
printf("BOARD_OS_PATCH_LEVEL %d-%02d\n", y, m);
|
||||
} else {
|
||||
header.os_version = 0;
|
||||
}
|
||||
}
|
||||
if (header.dt_size != 0) {
|
||||
printf("BOARD_DT_SIZE %d\n", header.dt_size);
|
||||
}
|
||||
|
||||
if (pagesize == 0) {
|
||||
pagesize = header.page_size;
|
||||
}
|
||||
|
||||
|
||||
//printf("cmdline...\n");
|
||||
sprintf(tmp, "%s/%s", directory, basename(filename));
|
||||
strcat(tmp, "-cmdline");
|
||||
write_string_to_file(tmp, (char*)header.cmdline);
|
||||
|
||||
write_string_to_file(tmp, (char *)header.cmdline);
|
||||
|
||||
//printf("board...\n");
|
||||
sprintf(tmp, "%s/%s", directory, basename(filename));
|
||||
strcat(tmp, "-board");
|
||||
write_string_to_file(tmp, (char *)header.name);
|
||||
|
||||
//printf("base...\n");
|
||||
sprintf(tmp, "%s/%s", directory, basename(filename));
|
||||
strcat(tmp, "-base");
|
||||
char basetmp[200];
|
||||
sprintf(basetmp, "%08x", header.kernel_addr - 0x00008000);
|
||||
sprintf(basetmp, "%08x", base);
|
||||
write_string_to_file(tmp, basetmp);
|
||||
|
||||
//printf("pagesize...\n");
|
||||
|
@ -108,7 +183,57 @@ int main(int argc, char** argv)
|
|||
char pagesizetmp[200];
|
||||
sprintf(pagesizetmp, "%d", header.page_size);
|
||||
write_string_to_file(tmp, pagesizetmp);
|
||||
|
||||
|
||||
//printf("kerneloff...\n");
|
||||
sprintf(tmp, "%s/%s", directory, basename(filename));
|
||||
strcat(tmp, "-kerneloff");
|
||||
char kernelofftmp[200];
|
||||
sprintf(kernelofftmp, "%08x", header.kernel_addr - base);
|
||||
write_string_to_file(tmp, kernelofftmp);
|
||||
|
||||
//printf("ramdiskoff...\n");
|
||||
sprintf(tmp, "%s/%s", directory, basename(filename));
|
||||
strcat(tmp, "-ramdiskoff");
|
||||
char ramdiskofftmp[200];
|
||||
sprintf(ramdiskofftmp, "%08x", header.ramdisk_addr - base);
|
||||
write_string_to_file(tmp, ramdiskofftmp);
|
||||
|
||||
//printf("secondoff...\n");
|
||||
sprintf(tmp, "%s/%s", directory, basename(filename));
|
||||
strcat(tmp, "-secondoff");
|
||||
char secondofftmp[200];
|
||||
sprintf(secondofftmp, "%08x", header.second_addr - base);
|
||||
write_string_to_file(tmp, secondofftmp);
|
||||
|
||||
//printf("tagsoff...\n");
|
||||
sprintf(tmp, "%s/%s", directory, basename(filename));
|
||||
strcat(tmp, "-tagsoff");
|
||||
char tagsofftmp[200];
|
||||
sprintf(tagsofftmp, "%08x", header.tags_addr - base);
|
||||
write_string_to_file(tmp, tagsofftmp);
|
||||
|
||||
if (header.os_version != 0) {
|
||||
//printf("os_version...\n");
|
||||
sprintf(tmp, "%s/%s", directory, basename(filename));
|
||||
strcat(tmp, "-osversion");
|
||||
char osvertmp[200];
|
||||
sprintf(osvertmp, "%d.%d.%d", a, b, c);
|
||||
write_string_to_file(tmp, osvertmp);
|
||||
|
||||
//printf("os_patch_level...\n");
|
||||
sprintf(tmp, "%s/%s", directory, basename(filename));
|
||||
strcat(tmp, "-oslevel");
|
||||
char oslvltmp[200];
|
||||
sprintf(oslvltmp, "%d-%02d", y, m);
|
||||
write_string_to_file(tmp, oslvltmp);
|
||||
}
|
||||
|
||||
//printf("hash...\n");
|
||||
sprintf(tmp, "%s/%s", directory, basename(filename));
|
||||
strcat(tmp, "-hash");
|
||||
const char *hashtype = detect_hash_type(&header);
|
||||
write_string_to_file(tmp, hashtype);
|
||||
|
||||
total_read += sizeof(header);
|
||||
//printf("total read: %d\n", total_read);
|
||||
total_read += read_padding(f, sizeof(header), pagesize);
|
||||
|
@ -118,7 +243,7 @@ int main(int argc, char** argv)
|
|||
FILE *k = fopen(tmp, "wb");
|
||||
byte* kernel = (byte*)malloc(header.kernel_size);
|
||||
//printf("Reading kernel...\n");
|
||||
fread(kernel, header.kernel_size, 1, f);
|
||||
if(fread(kernel, header.kernel_size, 1, f)){};
|
||||
total_read += header.kernel_size;
|
||||
fwrite(kernel, header.kernel_size, 1, k);
|
||||
fclose(k);
|
||||
|
@ -131,13 +256,68 @@ int main(int argc, char** argv)
|
|||
FILE *r = fopen(tmp, "wb");
|
||||
byte* ramdisk = (byte*)malloc(header.ramdisk_size);
|
||||
//printf("Reading ramdisk...\n");
|
||||
fread(ramdisk, header.ramdisk_size, 1, f);
|
||||
if(fread(ramdisk, header.ramdisk_size, 1, f)){};
|
||||
total_read += header.ramdisk_size;
|
||||
fwrite(ramdisk, header.ramdisk_size, 1, r);
|
||||
fclose(r);
|
||||
|
||||
|
||||
//printf("total read: %d\n", header.ramdisk_size);
|
||||
total_read += read_padding(f, header.ramdisk_size, pagesize);
|
||||
|
||||
/*
|
||||
* Even though the second_size is 0, some vendors may place a signature
|
||||
* image there. In such a case read to EOF and try to calculate the
|
||||
* size based on termination with a null, then fix it in header.
|
||||
*/
|
||||
if (header.second_size == 0) {
|
||||
struct stat st;
|
||||
stat(filename, &st);
|
||||
int second_test_size = st.st_size - total_read;
|
||||
if (second_test_size > header.dt_size) {
|
||||
byte* second_test = (byte*)malloc(second_test_size);
|
||||
if(fread(second_test, second_test_size, 1, f)){};
|
||||
u_int16_t *sbuf = (u_int16_t*)second_test;
|
||||
if (sbuf[0]) {
|
||||
int second_size = 0;
|
||||
while (sbuf[0]) {
|
||||
second_size += 2;
|
||||
sbuf++;
|
||||
}
|
||||
if ((second_size >= 1024) && (second_size < 2048))
|
||||
header.second_size = second_size;
|
||||
}
|
||||
fseek(f, total_read, SEEK_SET);
|
||||
}
|
||||
}
|
||||
if (header.second_size != 0) {
|
||||
sprintf(tmp, "%s/%s", directory, basename(filename));
|
||||
strcat(tmp, "-second");
|
||||
FILE *s = fopen(tmp, "wb");
|
||||
byte* second = (byte*)malloc(header.second_size);
|
||||
//printf("Reading second...\n");
|
||||
if(fread(second, header.second_size, 1, f)){};
|
||||
total_read += header.second_size;
|
||||
fwrite(second, header.second_size, 1, s);
|
||||
fclose(s);
|
||||
}
|
||||
|
||||
//printf("total read: %d\n", header.second_size);
|
||||
total_read += read_padding(f, header.second_size, pagesize);
|
||||
|
||||
if (header.dt_size != 0) {
|
||||
sprintf(tmp, "%s/%s", directory, basename(filename));
|
||||
strcat(tmp, "-dtb");
|
||||
FILE *d = fopen(tmp, "wb");
|
||||
byte* dtb = (byte*)malloc(header.dt_size);
|
||||
//printf("Reading dtb...\n");
|
||||
if(fread(dtb, header.dt_size, 1, f)){};
|
||||
total_read += header.dt_size;
|
||||
fwrite(dtb, header.dt_size, 1, d);
|
||||
fclose(d);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
|
||||
//printf("Total Read: %d\n", total_read);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user