Skip to content

Commit

Permalink
Merge pull request #1 from AdrianDC/master
Browse files Browse the repository at this point in the history
libbootimg: Add support Sony ELF boot image format
  • Loading branch information
Tasssadar committed Apr 3, 2016
2 parents 6607d1c + 16ac77b commit 577b380
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 19 deletions.
54 changes: 54 additions & 0 deletions include/boot_img_hdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@

#define BOOT_MAGIC "ANDROID!"
#define BOOT_MAGIC_SIZE 8
#define BOOT_MAGIC_ELF "ELF"
#define BOOT_MAGIC_ELF_SIZE 3
#define BOOT_NAME_SIZE 16
#define BOOT_ARGS_SIZE 512

Expand Down Expand Up @@ -79,6 +81,58 @@ struct boot_img_hdr
uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
};

struct boot_img_hdr_elf
{
uint8_t magic[8]; /* .ELF (0x00 to 0x07) */
uint8_t unused[8]; /* unused chars */
uint16_t type; /* boot type */
uint16_t machine; /* boot machine */
uint32_t version; /* boot version */
uint32_t entry_addr; /* boot entry */
uint32_t phoff; /* boot phoff */
uint32_t shoff; /* boot shoff */
uint32_t flags; /* boot flags */
uint16_t ehsize; /* boot ehsize */
uint16_t phentsize; /* boot phentsize */
uint16_t phnum; /* boot phnum */
uint16_t shentsize; /* boot shentsize */
uint16_t shnum; /* boot shnum */
uint16_t shstrndx; /* boot shstrndx */
uint32_t kernel_type; /* kernel type (0x34 to 0x37) */
uint32_t kernel_offset; /* kernel offset (0x38 to 0x3B) */
uint32_t kernel_vaddr; /* kernel address (0x3C to 0x3F) */
uint32_t kernel_paddr; /* kernel address duplicate */
uint32_t kernel_size; /* kernel size (0x44 to 0x47) */
uint32_t kernel_msize; /* kernel size duplicate */
uint32_t kernel_flags; /* kernel flags (0x4C to 0x4F) */
uint32_t kernel_align; /* kernel alignment */
uint32_t ramdisk_type; /* kernel type (0x54) */
uint32_t ramdisk_offset; /* ramdisk offset (0x58 to 0x5B) */
uint32_t ramdisk_vaddr; /* ramdisk address (0x5C to 0x5F) */
uint32_t ramdisk_paddr; /* ramdisk address duplicate */
uint32_t ramdisk_size; /* ramdisk size (0x64 to 0x67) */
uint32_t ramdisk_msize; /* ramdisk size duplicate */
uint32_t ramdisk_flags; /* ramdisk flags (0x6C to 0x6F) */
uint32_t ramdisk_align; /* cmdline alignment */
uint32_t rpm_type; /* rpm type (0x74 to 0x77) */
uint32_t rpm_offset; /* rpm offset (0x78 to 0x7B) */
uint32_t rpm_vaddr; /* rpm address (0x7C to 0x7F) */
uint32_t rpm_paddr; /* rpm address duplicate */
uint32_t rpm_size; /* rpm size (0x84 to 0x87) */
uint32_t rpm_msize; /* rpm size duplicate */
uint32_t rpm_flags; /* rpm flags (0x8C to 0x8F) */
uint32_t rpm_align; /* rpm alignment */
uint32_t cmd_type; /* cmdline type (0x94 to 0x97) */
uint32_t cmd_offset; /* cmdline offset (0x98 to 0x9B) */
uint32_t cmd_vaddr; /* cmdline address (0x9C to 0x9F) */
uint32_t cmd_paddr; /* cmdline address duplicate */
uint32_t cmd_size; /* cmdline size (0xA4 to 0xA7) */
uint32_t cmd_msize; /* cmdline size duplicate */
uint32_t cmd_flags; /* cmdline flags (0xAC to 0xAF) */
uint32_t cmd_align; /* cmdline alignment */
uint8_t name[BOOT_NAME_SIZE]; /* added - asciiz product name */
};

typedef struct boot_img_hdr boot_img_hdr;

#endif
24 changes: 23 additions & 1 deletion include/libbootimg.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ struct bootimg
struct boot_img_hdr hdr; /*!< Boot image header */
struct bootimg_blob blobs[LIBBOOTIMG_BLOB_CNT]; /*!< Blobs packed in the boot image. */
int start_offset; /*!< Offset of the boot image structure from the start of the file. Only used when loading blobs from boot.img file. */
struct boot_img_hdr_elf* hdr_elf; /*!< Boot image header in ELF format */
uint8_t is_elf; /*!< Select the ELF boot image format */
};

/**
Expand All @@ -110,10 +112,30 @@ int libbootimg_init_load(struct bootimg *img, const char *path, int load_blob_ma
* Loads boot_img_hdr from file on disk
* @param hdr pointer to boot_img_hdr structure
* @param path path to boot.img to load header from
* @return positive offset of the header from the start of the file if successful, negative value from libbootimg_error if failed.
* @return positive offset of the header from the start of the file if
* successful, negative value from libbootimg_error if failed.
*/
int libbootimg_load_header(struct boot_img_hdr *hdr, const char *path);

/**
* Loads boot_img_hdr or boot_img_hdr_elf from file on disk
* @param hdr pointer to boot_img_hdr structure
* @param hdr_elf pointer to boot_img_hdr_elf structure
* @param is_elf pointer to is_elf attribute
* @param path path to boot.img to load header from
* @return positive offset of the header from the start of the file if
* successful, negative value from libbootimg_error if failed.
*/
int libbootimg_load_headers(struct boot_img_hdr *hdr,
struct boot_img_hdr_elf *hdr_elf, uint8_t *is_elf, const char *path);

/**
* Updates the header addresses to the blobs.
* @param img pointer to initialized struct bootimg
* @return Zero if successful, negative value from libbootimg_error if failed.
*/
int libbootimg_update_headers(struct bootimg *b);

/**
* Frees all resources used by this bootimg struct
* @param b pointer to struct bootimg
Expand Down
141 changes: 123 additions & 18 deletions src/libbootimg.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ static inline unsigned align_size(unsigned size, unsigned page_size)

static int translate_errnum(int errnum)
{
switch(errno)
switch (errnum)
{
case EIO: return LIBBOOTIMG_ERROR_IO;
case EACCES: return LIBBOOTIMG_ERROR_ACCESS;
Expand Down Expand Up @@ -92,6 +92,9 @@ void libbootimg_init_new(struct bootimg *img)
memset(img, 0, sizeof(struct bootimg));
memcpy(img->hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
img->hdr.page_size = DEFAULT_PAGE_SIZE;
img->hdr_elf = malloc(sizeof(struct boot_img_hdr_elf));
memset(img->hdr_elf, sizeof(struct boot_img_hdr_elf), 0);
img->is_elf = 0;

img->blobs[LIBBOOTIMG_BLOB_KERNEL].size = &img->hdr.kernel_size;
img->blobs[LIBBOOTIMG_BLOB_RAMDISK].size = &img->hdr.ramdisk_size;
Expand All @@ -109,7 +112,7 @@ int libbootimg_init_load(struct bootimg *img, const char *path, int load_blob_ma

libbootimg_init_new(img);

res = libbootimg_load_header(&img->hdr, path);
res = libbootimg_load_headers(&img->hdr, img->hdr_elf, &img->is_elf, path);
if(res < 0)
{
libbootimg_destroy(img);
Expand Down Expand Up @@ -148,7 +151,14 @@ int libbootimg_init_load(struct bootimg *img, const char *path, int load_blob_ma
}
}

addr += align_size(*blob->size, img->hdr.page_size);
if (!img->is_elf)
{
addr += align_size(*blob->size, img->hdr.page_size);
}
else
{
addr += *blob->size;
}
}

fclose(f);
Expand All @@ -164,6 +174,7 @@ void libbootimg_destroy(struct bootimg *b)
{
struct bootimg_blob *blob = b->blobs;
struct bootimg_blob * const blobs_end = blob + LIBBOOTIMG_BLOB_CNT;
free(b->hdr_elf);
for(; blob != blobs_end; ++blob)
{
free(blob->data);
Expand All @@ -172,30 +183,72 @@ void libbootimg_destroy(struct bootimg *b)
}

int libbootimg_load_header(struct boot_img_hdr *hdr, const char *path)
{
struct boot_img_hdr_elf hdr_elf;
return libbootimg_load_headers(hdr, &hdr_elf, NULL, path);
}

int libbootimg_load_headers(struct boot_img_hdr *hdr,
struct boot_img_hdr_elf *hdr_elf, uint8_t *is_elf, const char *path)
{
int res = 0;
FILE *f;
size_t i;
uint32_t cmd_len;
static const int known_magic_pos[] = {
0x0, // default
0x100, // HTC signed boot images
};

f= fopen(path, "r");
if(!f)
if (!f)
return translate_errnum(errno);

res = LIBBOOTIMG_ERROR_INVALID_MAGIC;
for(i = 0; i < sizeof(known_magic_pos)/sizeof(known_magic_pos[0]); ++i)
for (i = 0; i < sizeof(known_magic_pos)/sizeof(known_magic_pos[0]); ++i)
{
fseek(f, known_magic_pos[i], SEEK_SET);
if(fread(hdr, sizeof(struct boot_img_hdr), 1, f) == 1)
if (fread(hdr, sizeof(struct boot_img_hdr), 1, f) == 1)
{
if(memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0)
if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE) == 0)
{
if (is_elf != NULL)
{
*is_elf = 0;
}
res = known_magic_pos[i];
break;
}
else if (hdr_elf != NULL && memcmp(hdr->magic + 1, BOOT_MAGIC_ELF,
BOOT_MAGIC_ELF_SIZE) == 0)
{
fseek(f, 0, SEEK_SET);
if (fread(hdr_elf, sizeof(struct boot_img_hdr_elf), 1, f) == 1)
{
hdr->kernel_size = hdr_elf->kernel_size;
hdr->kernel_addr = hdr_elf->kernel_offset;
hdr->ramdisk_size = hdr_elf->ramdisk_size;
hdr->ramdisk_addr = hdr_elf->ramdisk_offset;
hdr->second_size = hdr_elf->rpm_size;
hdr->second_addr = hdr_elf->rpm_offset;
hdr->page_size = hdr_elf->kernel_offset;
hdr->tags_addr = 0;
hdr->dt_size = 0;
hdr->id[0] = '\0';
memcpy(hdr->name, hdr_elf->name, BOOT_NAME_SIZE);
cmd_len = hdr_elf->cmd_size;
memset(hdr->cmdline, '\0', BOOT_ARGS_SIZE);
fseek(f, hdr_elf->cmd_offset, SEEK_SET);
fread(hdr->cmdline, cmd_len < BOOT_ARGS_SIZE ?
cmd_len : BOOT_ARGS_SIZE, 1, f);
res = known_magic_pos[i];
if (is_elf != NULL)
{
*is_elf = 1;
}
break;
}
}
}
else
{
Expand All @@ -208,6 +261,39 @@ int libbootimg_load_header(struct boot_img_hdr *hdr, const char *path)
return res;
}

int libbootimg_update_headers(struct bootimg *b)
{
uint32_t addr;

if (b == NULL)
return translate_errnum(ENOENT);

if (b->is_elf)
{
b->hdr_elf->kernel_size = b->hdr.kernel_size;
b->hdr_elf->kernel_msize = b->hdr.kernel_size;
b->hdr_elf->ramdisk_size = b->hdr.ramdisk_size;
b->hdr_elf->ramdisk_msize = b->hdr.ramdisk_size;
b->hdr_elf->rpm_size = b->hdr.second_size;
b->hdr_elf->rpm_msize = b->hdr.second_size;

addr = b->hdr_elf->kernel_offset;

addr += b->hdr_elf->kernel_size;
b->hdr_elf->ramdisk_offset = addr;

addr += b->hdr_elf->ramdisk_size;
b->hdr_elf->rpm_offset = addr;

addr += b->hdr_elf->rpm_size;
b->hdr_elf->cmd_offset = addr;

memcpy(b->hdr_elf->name, b->hdr.name, BOOT_NAME_SIZE);
}

return 0;
}

int libbootimg_dump_blob(struct bootimg_blob *blob, const char *dest)
{
FILE *f;
Expand Down Expand Up @@ -364,31 +450,50 @@ int libbootimg_write_img_fileptr(struct bootimg *b, FILE *f)
memset(blank, 0, b->hdr.page_size);

// write header
if(fwrite(&b->hdr, sizeof(b->hdr), 1, f) != 1)
goto fail_fwrite;
if (!b->is_elf)
{
if (fwrite(&b->hdr, sizeof(b->hdr), 1, f) != 1)
goto fail_fwrite;

padding = align_size(sizeof(b->hdr), b->hdr.page_size) - sizeof(b->hdr);
}
else
{
libbootimg_update_headers(b);

padding = align_size(sizeof(b->hdr), b->hdr.page_size) - sizeof(b->hdr);
if(fwrite(blank, 1, padding, f) != padding)
if (fwrite(b->hdr_elf, sizeof(*b->hdr_elf), 1, f) != 1)
goto fail_fwrite;

padding = align_size(sizeof(*b->hdr_elf), b->hdr.page_size) - sizeof(*b->hdr_elf);
}

if (fwrite(blank, 1, padding, f) != padding)
goto fail_fwrite;

for(i = 0; i < LIBBOOTIMG_BLOB_CNT; ++i)
for (i = 0; i < LIBBOOTIMG_BLOB_CNT; ++i)
{
blob = &b->blobs[i];

if(*blob->size == 0)
if (*blob->size == 0)
continue;

if(fwrite(blob->data, *blob->size, 1, f) != 1)
if (fwrite(blob->data, *blob->size, 1, f) != 1)
goto fail_fwrite;

padding = align_size(*blob->size, b->hdr.page_size) - *blob->size;
if(fwrite(blank, 1, padding, f) != padding)
goto fail_fwrite;
if (!b->is_elf)
{
padding = align_size(*blob->size, b->hdr.page_size) - *blob->size;
if (fwrite(blank, 1, padding, f) != padding)
goto fail_fwrite;
}
}

if (b->is_elf && fwrite(b->hdr.cmdline, b->hdr_elf->cmd_size, 1, f) != 1)
goto fail_fwrite;

pos_end = ftell(f);

if(pos_end > 0)
if (pos_end > 0)
res = pos_end - pos_start;
else
res = translate_errnum(errno);
Expand Down

0 comments on commit 577b380

Please sign in to comment.