Skip to content

Commit

Permalink
libbootimg: Add support for newer Sony ELF boot images
Browse files Browse the repository at this point in the history
 The boot image found in sony firmwares (stock) is different to the already
  implemented version. This change adds support for these images (found in
  the Z2) by introducing more flexibility in the ELF handling
  and the output format (ELF --> ANDROID!)

 In particular:

 - Use a more dynamic structure to describe elf files:
    Add handling information (e.g., the elf version) and separate structures
    for the ELF header, the program headers, and the section headers
 - Adjust the read/load operations to account for the new structure
 - Add handling code for the differentiation between the two known ELF versions
 - Adjust the writing code such that it can output the content of an ELF
    image as a standard ANDROID! image:
    The newer ELF versions are not booted if a single (unused) bit is modifed
    Possibly the (unlocked) bootloader performs a signature check only for
    ELF files
 - Add some debug code that allows to print either to stdout or the kernel
    log (useful for on-device debugging)
 - Extend the Sony Stock support in a dynamic way
 - Add dependencies for klog_write
 - Also fix all minor warnings

 The code has been tested with the boot image of an Xperia Z2,
  and on the devices from the original ELF implementation (SP)

Change-Id: I0e9a41ae6ce26bf4608ef86cec1e2735f746abb6
Signed-off-by: Alexander Diewald <[email protected]>
Signed-off-by: Adrian DC <[email protected]>
  • Loading branch information
Diewi authored and AdrianDC committed Nov 26, 2016
1 parent 11e79c5 commit 8986984
Show file tree
Hide file tree
Showing 4 changed files with 766 additions and 144 deletions.
13 changes: 10 additions & 3 deletions Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_UNSTRIPPED_PATH := $(TARGET_OUT_EXECUTABLES_UNSTRIPPED)

LOCAL_STATIC_LIBRARIES := libc
LOCAL_CFLAGS := -DDEBUG_KMSG
LOCAL_STATIC_LIBRARIES := libc libcutils

include $(BUILD_EXECUTABLE)

# bbootimge_host
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= $(bbootimg_src_file)
Expand All @@ -36,14 +38,19 @@ LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
LOCAL_MODULE_STEM := bbootimg

LOCAL_SRC_FILES:= src/bbootimg.c src/libbootimg.c
LOCAL_SHARED_LIBRARIES := libc

include $(BUILD_EXECUTABLE)
LOCAL_CFLAGS := -DDEBUG_KMSG
LOCAL_SHARED_LIBRARIES := libc libcutils

include $(BUILD_EXECUTABLE)

# libbootimg
include $(CLEAR_VARS)

LOCAL_SRC_FILES := src/libbootimg.c
LOCAL_MODULE := libbootimg
LOCAL_MODULE_TAGS := eng

LOCAL_CFLAGS := -DDEBUG_KMSG

include $(BUILD_STATIC_LIBRARY)
124 changes: 71 additions & 53 deletions include/boot_img_hdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include <stdint.h>

/*
** +-----------------+
** +-----------------+
** | boot header | 1 page
** +-----------------+
** | kernel | n pages
Expand Down Expand Up @@ -51,11 +51,24 @@

#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

#define BOOT_MAGIC_ELF "ELF"
#define BOOT_MAGIC_ELF_SIZE 3
#define VER_ELF_1 (1 << 0)
#define VER_ELF_2 (1 << 1)

#define OUT_ELF (1 << 0) /* Same output format: ELF container */
#define OUT_AND (1 << 1) /* Different output format: standard Android container */

#define ELF_PROG_KER 0
#define ELF_PROG_RAM 1
#define ELF_PROG_RPM 2
#define ELF_PROG_CMD 3

#define ELF_SECT_CMD 0

struct boot_img_hdr
{
uint8_t magic[BOOT_MAGIC_SIZE];
Expand All @@ -81,59 +94,64 @@ struct boot_img_hdr
uint32_t id[8]; /* timestamp / checksum / sha1 / etc */
};

struct boot_img_hdr_elf
struct boot_img_elf_hdr
{
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 header_vals[3900]; /* header additional values */
uint8_t name[BOOT_NAME_SIZE]; /* added - asciiz product name */
uint8_t unused[8]; /* unused chars (0x08 to 0x0F) */
uint16_t type; /* boot type (0x10 to 0x11) */
uint16_t machine; /* boot machine (0x12 to 0x13) */
uint32_t version; /* boot version (0x14 to 0x17) */
uint32_t entry_addr; /* boot entry (0x18 to 0x1B) */
uint32_t phoff; /* boot phoff (0x1C to 0x1F) */
uint32_t shoff; /* boot shoff (0x20 to 0x23) */
uint32_t flags; /* boot flags (0x24 to 0x27) */
uint16_t ehsize; /* boot ehsize (0x28 to 0x29) */
uint16_t phentsize; /* boot phentsize (0x2A to 0x2B) */
uint16_t phnum; /* boot phnum (0x2C to 0x2D) */
uint16_t shentsize; /* boot shentsize (0x2E to 0x2F)*/
uint16_t shnum; /* boot shnum (0x30 to 0x31) */
uint16_t shstrndx; /* boot shstrndx (0x32 to 0x33) */
};

struct boot_img_elf_info
{
struct boot_img_elf_hdr hdr; /* The ELF file header. */
struct boot_img_elf_prog_hdr* prog; /* The program header entries. */
struct boot_img_elf_sect_hdr* sect; /* The section header entries. */
struct boot_img_elf_misc_hdr* misc; /* Miscellaneous information found in some ELF versions. */
uint8_t elf_version;
uint8_t elf_out_format;
uint32_t cmdline_size;
};

struct boot_img_elf_prog_hdr
{
uint32_t type; /* type (position + 0x0 to 0x3) */
uint32_t offset; /* offset (position + 0x4 to 0x7) */
uint32_t vaddr; /* address (position + 0x8 to 0xB) */
uint32_t paddr; /* address duplicate (position + 0xC to 0xF) */
uint32_t size; /* size (position + 0x10 to 0x13) */
uint32_t msize; /* size duplicate (position + 0x14 to 0x17) */
uint32_t flags; /* flags (position + 0x18 to 0x1B) */
uint32_t align; /* alignment (position + 0x1C to 0x1F)*/
};

typedef struct boot_img_hdr boot_img_hdr;
struct boot_img_elf_sect_hdr
{
uint32_t name;
uint32_t type;
uint32_t flags;
uint32_t addr;
uint32_t offset;
uint32_t size;
uint8_t misc[16];
};

struct boot_img_elf_misc_hdr
{
uint8_t* data; /* header additional data */
uint32_t data_size; /* header additional size */
uint8_t name[BOOT_NAME_SIZE]; /* added - asciiz product name */
};

#endif
120 changes: 114 additions & 6 deletions include/libbootimg.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,20 @@ extern "C" {

#include <stdint.h>
#include <stdio.h>
#include <cutils/klog.h>
#include "boot_img_hdr.h"

#define LIBBOOTIMG_VERSION 0x000203 // 0xMMNNPP
#define LIBBOOTIMG_VERSION_STR "0.2.3"

#ifdef DEBUG_KMSG
#define LOG_DBG(fmt, ...) klog_write(3, "<3>%s: " fmt, "libbootimg", ##__VA_ARGS__)
#elif DEBUG_STDOUT
#define LOG_DBG printf("libbootimg: "); printf
#else
#define LOG_DBG(fmt, ...) ""
#endif

/**
* Enum containing possible blob types in a boot image.
*/
Expand Down Expand Up @@ -84,10 +93,12 @@ struct bootimg_blob
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 */
struct bootimg_blob blob; /* Complete blob */
uint32_t blob_size; /* Size of the complete blob */
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 */
uint8_t is_elf; /*!< Select the ELF boot image format */
struct boot_img_elf_info* hdr_info; /*!< Boot image meta-information for ELF formats */
};

/**
Expand Down Expand Up @@ -117,6 +128,62 @@ int libbootimg_init_load(struct bootimg *img, const char *path, int load_blob_ma
*/
int libbootimg_load_header(struct boot_img_hdr *hdr, const char *path);

/**
* Determines the ELF boot image version (custom definition) and the
* required output format (ELF or ANDROID!) based on the number of
* program headers given by the ELF header.
* @param hdr_info pointer to the structure holding the read header information
*/
void libbootimg_get_elf_version(struct boot_img_elf_info *hdr_info);

/**
* Reads the program headers from the given ELF file and adds the content
* of each header to the given structure.
* @param hdr_info structure holding the meta-information of the given ELF file
* @param f pointer to the file descriptor of the ELF file
* @return zero on success or the error code returned by the file operations.
*/
int libbootimg_load_elf_prog_header(struct boot_img_elf_info *hdr_info, FILE *f);

/**
* Reads the section headers from the given ELF file and adds the content
* of each header to the given structure.
* @param hdr_info structure holding the meta-information of the given ELF file
* @param f pointer to the file descriptor of the ELF file
* @return zero on success or the error code returned by the file operations.
*/
int libbootimg_load_elf_sect_header(struct boot_img_elf_info *hdr_info, FILE *f);

/**
* Reads the miscellaneous information from the given ELF file and adds the content
* to the given structure. This information is present in some ELF versions and
* required for them to operate properly (version 1).
* @param hdr_info structure holding the meta-information of the given ELF file
* @param size of the bootimage pagesize needed for alignment
* @param f pointer to the file descriptor of the ELF file
* @return one on success or the error code returned by the file operations.
*/
int libbootimg_load_elf_misc_header(struct boot_img_elf_info *hdr_info, uint32_t page_size, FILE *f);

/**
* Extracts the kernel boot command line from an ELF file and adds it to
* the generic structure describing the blob (-> hdr).
* @param hdr pointer to boot_img_hdr structure
* @param elf_info structure holding the meta-information of the given ELF file.
* @param f pointer to the file descriptor of the ELF file.
*/
void libbootimg_read_cmdline(struct boot_img_hdr *hdr, struct boot_img_elf_info *elf_info, FILE *f);

/**
* Returns a pointer referencing the ELF program header which describes the content
* of a given type like the kernel or ramdisk part of a boot image.
* @param hdr_info structure holding the meta-information of the given ELF file.
* @param type integer value that describes the desired pointer as given in the enum
* {@link libbootimg_blob_type}.
* @return pointer to the program header describing the desired part of the boot image.
*/
struct boot_img_elf_prog_hdr* get_elf_proc_hdr_of(struct boot_img_elf_info *elf_info, int type);

/**
* Loads boot_img_hdr or boot_img_hdr_elf from file on disk
* @param hdr pointer to boot_img_hdr structure
Expand All @@ -127,7 +194,7 @@ int libbootimg_load_header(struct boot_img_hdr *hdr, const char *path);
* 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);
struct boot_img_elf_info *hdr_elf, uint8_t *is_elf, const char *path);

/**
* Updates the header addresses to the blobs.
Expand All @@ -142,8 +209,6 @@ int libbootimg_update_headers(struct bootimg *b);
*/
void libbootimg_destroy(struct bootimg *b);



/**
* Writes blob to a file.
* @param blob pointer to source struct bootimg_blob
Expand Down Expand Up @@ -244,6 +309,14 @@ int libbootimg_write_img(struct bootimg *b, const char *dest);
*/
int libbootimg_write_img_fileptr(struct bootimg *b, FILE *f);

/**
* Writes boot image to a file: Updated implementation that effectively *injects* data into an existing boot image
* @param b pointer to struct bootimg
* @param f pointer to FILE to write data into
* @return number of bytes written to the file if successful, negative value from libbootimg_error if failed.
*/
int libbootimg_write_img_fileptr_new(struct bootimg *b, FILE *f);

/**
* Writes boot image to a file and then calls libbootimg_destroy.
* The bootimg struct is destroyed even if this function fails.
Expand Down Expand Up @@ -274,6 +347,41 @@ const char *libbootimg_version_str(void);
*/
const char *libbootimg_error_str(int error);

/**
* Prints the content of the boot image information to the stdout or
* the kernel log (dmesg).
* @param hdr pointer to the boot image information.
*/
void print_hdr_to_log(struct boot_img_hdr* hdr);

/**
* Prints the content of an elf header described by the given structure
* to the stdout or the kernel log (dmesg).
* @param elf_info pointer to the elf header information.
*/
void print_elf_hdr_to_log(struct boot_img_elf_info* elf_info);

/**
* Prints the content of an elf program header described by the given structure
* to the stdout or the kernel log (dmesg).
* @param elf_prog_hdr pointer to the program header information.
*/
void print_elf_prog_hdr_to_log(struct boot_img_elf_prog_hdr* elf_prog_hdr);

/**
* Prints the content of an elf section header described by the given structure
* to the stdout or the kernel log (dmesg).
* @param elf_sect_hdr pointer to the section header information.
*/
void print_elf_sect_hdr_to_log(struct boot_img_elf_sect_hdr* elf_sect_hdr);

/**
* Prints the content of an elf misc header described by the given structure
* to the stdout or the kernel log (dmesg).
* @param elf_sect_hdr pointer to the section header information.
*/
void print_elf_misc_hdr_to_log(struct boot_img_elf_misc_hdr* elf_misc_hdr);

#ifdef __cplusplus
}
#endif
Expand Down
Loading

0 comments on commit 8986984

Please sign in to comment.