Skip to content

Instantly share code, notes, and snippets.

@5ec1cff
Last active May 30, 2026 15:12
Show Gist options
  • Select an option

  • Save 5ec1cff/da6ce992be5a85f52faf2ba125ef6641 to your computer and use it in GitHub Desktop.

Select an option

Save 5ec1cff/da6ce992be5a85f52faf2ba125ef6641 to your computer and use it in GitHub Desktop.
Imhex pattern for android boot image
#pragma description Android Boot image
#pragma magic [ 41 4e 44 52 4f 49 44 21 ] @ 0x00
#pragma magic [ 56 4e 44 52 42 4f 4f 54 ] @ 0x00
#pragma endian little
using uint8_t = u8;
using uint32_t = u32;
using uint64_t = u64;
import std.mem;
import std.core;
import std.io;
#define BOOT_MAGIC_SIZE 8
#define BOOT_NAME_SIZE 16
#define BOOT_ID_SIZE 32
#define BOOT_ARGS_SIZE 512
#define BOOT_EXTRA_ARGS_SIZE 1024
#define VENDOR_BOOT_ARGS_SIZE 2048
#define VENDOR_RAMDISK_NAME_SIZE 32
#define VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE 16
u64 magic = std::mem::read_unsigned(0, 8);
struct DataBlock<auto len, auto mask> {
u64 space = (len + mask) & ~mask;
u64 pos = $;
char data[len];
$ -= 1;
char end;
padding[space-len];
$ -= 1;
char padding_end;
};
struct BootImage {
char magic[BOOT_MAGIC_SIZE];
u32 version = std::mem::read_unsigned(40, 4);
if (version < 3) {
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 tags_addr; /* physical addr for kernel tags */
uint32_t page_size; /* flash page size we assume */
uint32_t header_version; /* the version of the header */
// Operating system version and security patch level.
// For version "A.B.C" and patch level "Y-M-D":
// (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M)
// os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0]
uint32_t os_version;
char name[BOOT_NAME_SIZE]; /* asciiz product name */
char cmdline[BOOT_ARGS_SIZE];
char id[BOOT_ID_SIZE]; /* timestamp / checksum / sha1 / etc */
// Supplemental command line data; kept here to maintain
// binary compatibility with older versions of mkbootimg.
char extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
if (version >= 1) {
uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO/ACPIO image */
uint64_t recovery_dtbo_offset; /* offset to recovery dtbo/acpio in boot image */
uint32_t header_size;
if (version >= 2) {
uint32_t dtb_size; /* size in bytes for DTB image */
uint64_t dtb_addr; /* physical load address for DTB image */
}
} else {
uint32_t header_size = 8 + 4 * 10 + BOOT_NAME_SIZE + BOOT_ARGS_SIZE + BOOT_ID_SIZE + BOOT_EXTRA_ARGS_SIZE;
}
} else {
uint32_t kernel_size; /* size in bytes */
uint32_t ramdisk_size; /* size in bytes */
uint32_t os_version;
uint32_t header_size;
uint32_t reserved[4] [[hidden]];
uint32_t page_size = 4096;
uint32_t header_version;
char cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE];
if (version >= 4) {
uint32_t signature_size; /* size in bytes */
}
}
u64 mask = page_size - 1;
u64 hdrsz = (header_size + mask) & (~mask);
padding[hdrsz-$];
if (kernel_size > 0) {
DataBlock<kernel_size, mask> kernel;
}
if (ramdisk_size > 0) {
DataBlock<ramdisk_size, mask> ramdisk;
}
if (version < 3) {
if (second_size > 0) {
DataBlock<second_size, mask> second;
}
if (version >= 1 && recovery_dtbo_size > 0) {
DataBlock<recovery_dtbo_size, mask> recovery_dtbo;
}
if (version >= 2 && dtb_size > 0) {
DataBlock<dtb_size, mask> dtb;
}
}
if (version >= 4 && signature_size > 0) {
DataBlock<signature_size, mask> signature;
}
};
enum VendorRamdiskType : u32 {
None = 0,
Platform = 1,
Recovery = 2,
DLKM = 3,
};
struct VendorRamdiskTableEntry<auto ramdisk_pos> {
uint32_t ramdisk_size; /* size in bytes for the ramdisk image */
uint32_t ramdisk_offset; /* offset to the ramdisk image in vendor ramdisk section */
VendorRamdiskType ramdisk_type; /* type of the ramdisk */
char ramdisk_name[VENDOR_RAMDISK_NAME_SIZE]; /* asciiz ramdisk name */
char ramdisk_block[ramdisk_size] @ (ramdisk_pos + ramdisk_offset);
char ramdisk_block_end @ (ramdisk_pos + ramdisk_offset + ramdisk_size - 1);
// Hardware identifiers describing the board, soc or platform which this
// ramdisk is intended to be loaded on.
uint32_t board_id[VENDOR_RAMDISK_TABLE_ENTRY_BOARD_ID_SIZE];
} [[format("vendor_ramdisk_table_entry_formatter")]];
fn vendor_ramdisk_table_entry_formatter(auto entry) {
return std::format("{} {}", entry.ramdisk_type, entry.ramdisk_name);
};
union VendorRamdiskTable<auto len, auto mask, auto size, auto ramdisk_pos> {
VendorRamdiskTableEntry<ramdisk_pos> entries[size];
DataBlock<len, mask> [[inline]];
};
struct VendorBootImage {
char magic[BOOT_MAGIC_SIZE];
// Version of the vendor boot image header.
uint32_t header_version;
uint32_t page_size; /* flash page size we assume */
uint32_t kernel_addr; /* physical load addr */
uint32_t ramdisk_addr; /* physical load addr */
uint32_t ramdisk_size; /* size in bytes */
char cmdline[VENDOR_BOOT_ARGS_SIZE];
uint32_t tags_addr; /* physical addr for kernel tags (if required) */
char name[BOOT_NAME_SIZE]; /* asciiz product name */
uint32_t header_size;
uint32_t dtb_size; /* size in bytes for DTB image */
uint64_t dtb_addr; /* physical load address for DTB image */
if (header_version >= 4) {
uint32_t vendor_ramdisk_table_size; /* size in bytes for the vendor ramdisk table */
uint32_t vendor_ramdisk_table_entry_num; /* number of entries in the vendor ramdisk table */
uint32_t vendor_ramdisk_table_entry_size; /* size in bytes for a vendor ramdisk table entry */
uint32_t bootconfig_size; /* size in bytes for the bootconfig section */
}
u64 mask = page_size - 1;
u64 hdrsz = (header_size + mask) & (~mask);
padding[hdrsz-$];
u64 ramdisk_pos = $;
if (ramdisk_size > 0) {
DataBlock<ramdisk_size, mask> ramdisk;
}
if (dtb_size > 0) {
DataBlock<dtb_size, mask> dtb;
}
if (header_version >= 4 && vendor_ramdisk_table_size > 0) {
VendorRamdiskTable<vendor_ramdisk_table_size, mask, vendor_ramdisk_table_entry_num, ramdisk_pos> vendor_ramdisk_table;
}
if (header_version >= 4 && bootconfig_size > 0) {
DataBlock<bootconfig_size, mask> bootconfig;
}
};
struct Image {
if (magic == 0x2144494f52444e41) {
BootImage [[inline]];
} else {
VendorBootImage [[inline]];
}
};
Image image @ 0;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment