Last active
May 30, 2026 15:12
-
-
Save 5ec1cff/da6ce992be5a85f52faf2ba125ef6641 to your computer and use it in GitHub Desktop.
Imhex pattern for android boot image
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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