summaryrefslogtreecommitdiff
path: root/src/appdesc.zig
blob: bec29151b25eb7a8fb13a21e801d3ff5d22e1adf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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;