diff options
Diffstat (limited to 'src/appdesc.zig')
| -rw-r--r-- | src/appdesc.zig | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/appdesc.zig b/src/appdesc.zig new file mode 100644 index 0000000..bec2915 --- /dev/null +++ b/src/appdesc.zig @@ -0,0 +1,63 @@ +//! esp_app_desc_t, the 256-byte block the second-stage bootloader reads from image offset 0x20. +//! +//! Two facts about it were established by flashing deliberately broken images at this board: +//! * the magic word is never validated in a default build - the descriptor is trusted purely by +//! position, so an image with ordinary rodata there can boot; +//! * what the loader actually reads is min/max_efuse_blk_rev_full at offsets 0xB0/0xB2, and +//! `IS_FIELD_SET()` treats zero as "unset" (bootloader_common_loader.c:102-112). +//! +//! Everything past 0xB5 is reserved padding, so `minimal` stops there and saves 72 bytes of flash. +//! `full` keeps all 256 so that `esptool image-info` can parse it. + +const config = @import("config"); + +pub const magic: u32 = 0xABCD5432; + +pub const Minimal = extern struct { + magic_word: u32 = magic, + secure_version: u32 = 0, + reserv1: [2]u32 = .{ 0, 0 }, + version: [32]u8, + project_name: [32]u8, + time: [16]u8 = @splat(0), + date: [16]u8 = @splat(0), + idf_ver: [32]u8 = @splat(0), + app_elf_sha256: [32]u8 = @splat(0), + min_efuse_blk_rev_full: u16, + max_efuse_blk_rev_full: u16, + mmu_page_size: u8 = 16, // log2(64 KiB); fixed on the P4, which has no configurable MMU page + reserv3: [3]u8 = @splat(0), +}; + +pub const Full = extern struct { + head: Minimal, + reserv2: [18]u32 = @splat(0), +}; + +fn str(comptime n: usize, comptime s: []const u8) [n]u8 { + var out: [n]u8 = @splat(0); + @memcpy(out[0..s.len], s); + return out; +} + +const head: Minimal = .{ + .version = str(32, "0.1"), + .project_name = str(32, "zig-p4"), + // The eFuse *block* revision, which has nothing to do with the silicon revision window that + // -Dmin-rev sets in the image header. Deriving one from the other made `-Dmin-rev=150` emit an + // image the bootloader refuses with "Image requires efuse blk rev >= v0.50". Zero means unset, + // which is what `IS_FIELD_SET()` checks for (bootloader_common_loader.c:102-112). + .min_efuse_blk_rev_full = 0, + .max_efuse_blk_rev_full = 0, +}; + +/// Placed first in .flash.rodata by the linker script, so it lands at image offset 0x20. +/// +/// `export` is load-bearing: a `comptime _ = descriptor;` reference is enough in Debug but not +/// under ReleaseSmall, where the constant is folded away, the section disappears, `KEEP` has +/// nothing to keep, and the image ends up with one mapped segment starting at the wrong offset. +/// An exported symbol is always emitted. +pub export const esp_app_desc linksection(".rodata.appdesc") = if (config.full_descriptor) + Full{ .head = head } +else + head; |
