diff --git a/patches/genimage/0001-hdimage-put-GPT-protective-MBR-entry-first-in-hybrid.patch b/patches/genimage/0001-hdimage-put-GPT-protective-MBR-entry-first-in-hybrid.patch new file mode 100644 index 00000000..2714e611 --- /dev/null +++ b/patches/genimage/0001-hdimage-put-GPT-protective-MBR-entry-first-in-hybrid.patch @@ -0,0 +1,133 @@ +From 7f50533b9e57f5e7d1e4dd47c3f43e2d6a9c8b1a Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Sun, 8 Mar 2026 04:33:56 +0100 +Subject: [PATCH] hdimage: add gpt-protective-first option for hybrid MBR +Organization: Wires + +In a hybrid MBR the conventional layout (used by gdisk and others) is: + + MBR[0] = 0xEE (GPT protective, covers whole disk) + MBR[1..3] = user-selected GPT partitions with legacy type codes + +genimage currently appends the 0xEE entry after the data partitions, +producing the opposite order. This is fine for most platforms, but +breaks firmware that detects GPT by inspecting only MBR entry 0: seeing +a non-0xEE type there it falls into pure-MBR mode and cannot look up +GPT partitions by name. + +The TF-A partition driver (drivers/partition/partition.c) exhibits +exactly this behaviour: load_mbr_header() copies entry[0] and checks +type == 0xEE to select between MBR and GPT mode. The MediaTek MT7622 +platform (BananaPi BPI-R64) is a concrete example where this matters. + +On the other hand, Raspberry Pi firmware scans all MBR slots for a +bootable FAT32 partition. If slot 0 holds a 0xEE protective entry the +firmware switches to GPT detection, looks for an EFI System Partition +UUID, and reports "no bootable partitions" when none is found. + +Add an opt-in hdimage option `gpt-protective-first = true` that places +the 0xEE entry at slot 0 and shifts data partitions to slots 1..3. +The default (false) preserves the existing genimage behaviour so that +platforms like Raspberry Pi continue to work without any changes. + +Signed-off-by: Joachim Wiberg +--- + README.rst | 10 ++++++++++ + image-hd.c | 27 ++++++++++++++++++++++----- + 2 files changed, 32 insertions(+), 5 deletions(-) + +diff --git a/README.rst b/README.rst +index 9a95f75..f45fb93 100644 +--- a/README.rst ++++ b/README.rst +@@ -480,6 +480,16 @@ Options: + placed at 512 bytes (sector 1). Defaults to 1024 bytes (sector 2). + :gpt-no-backup: Boolean. If true, then the backup partition table at the end of + the image is not written. ++:gpt-protective-first: Boolean. If true, then for ``hybrid`` partition tables, the GPT ++ protective entry (type ``0xEE``) is placed at MBR slot 0 and ++ data partitions fill slots 1..3. This matches the layout ++ produced by tools such as gdisk and is required by firmware ++ that identifies GPT disks by inspecting only MBR entry 0 — ++ for example the TF-A partition driver used on MediaTek MT7622 ++ (BananaPi BPI-R64). When false (the default), the 0xEE entry ++ is placed after the data partitions, which is compatible with ++ firmware that scans MBR slots for a bootable partition (e.g. ++ Raspberry Pi). + :disk-uuid: UUID string used as disk id in GPT partitioning. Defaults to a + random value. + :fill: If this is set to true, then the image file will be filled +diff --git a/image-hd.c b/image-hd.c +index 274c6ac..610d9d1 100644 +--- a/image-hd.c ++++ b/image-hd.c +@@ -46,6 +46,7 @@ struct hdimage { + int table_type; + unsigned long long gpt_location; + cfg_bool_t gpt_no_backup; ++ cfg_bool_t gpt_protective_first; + cfg_bool_t fill; + unsigned long long file_size; + }; +@@ -152,6 +153,26 @@ static int hdimage_insert_mbr(struct image *image, struct list_head *partitions) + memset(&mbr, 0, sizeof(mbr)); + memcpy(&mbr.disk_signature, &hd->disksig, sizeof(hd->disksig)); + ++ /* ++ * For hybrid MBR, optionally write the GPT protective entry (0xEE) at ++ * slot 0 first when gpt-protective-first = true. This matches the ++ * conventional layout used by tools such as gdisk and is required by ++ * firmware that detects GPT by inspecting only MBR[0] (e.g. the TF-A ++ * partition driver on MediaTek MT7622). Leave slot 0 free by default ++ * so that firmware scanning for a bootable MBR partition (e.g. ++ * Raspberry Pi) can find data partitions at slots 0..2. ++ */ ++ if (hd->table_type == TYPE_HYBRID && hd->gpt_protective_first) { ++ struct mbr_partition_entry *entry = &mbr.part_entry[0]; ++ ++ entry->boot = 0x00; ++ entry->partition_type = 0xee; ++ entry->relative_sectors = 1; ++ entry->total_sectors = hd->gpt_location / 512 + GPT_SECTORS - 2; ++ hdimage_setup_chs(entry, 0); ++ i = 1; ++ } ++ + list_for_each_entry(part, partitions, list) { + struct mbr_partition_entry *entry; + +@@ -176,13 +197,13 @@ static int hdimage_insert_mbr(struct image *image, struct list_head *partitions) + i++; + } + +- if (hd->table_type == TYPE_HYBRID) { ++ /* For hybrid MBR without gpt-protective-first, append 0xEE after data partitions. */ ++ if (hd->table_type == TYPE_HYBRID && !hd->gpt_protective_first) { + struct mbr_partition_entry *entry; + + entry = &mbr.part_entry[i]; + + entry->boot = 0x00; +- + entry->partition_type = 0xee; + entry->relative_sectors = 1; + entry->total_sectors = hd->gpt_location / 512 + GPT_SECTORS - 2; +@@ -978,6 +999,7 @@ static int hdimage_setup(struct image *image, cfg_t *cfg) + table_type = cfg_getstr(cfg, "partition-table-type"); + hd->gpt_location = cfg_getint_suffix(cfg, "gpt-location"); + hd->gpt_no_backup = cfg_getbool(cfg, "gpt-no-backup"); ++ hd->gpt_protective_first = cfg_getbool(cfg, "gpt-protective-first"); + hd->fill = cfg_getbool(cfg, "fill"); + + if (is_block_device(imageoutfile(image))) { +@@ -1227,6 +1249,7 @@ static cfg_opt_t hdimage_opts[] = { + CFG_BOOL("gpt", cfg_false, CFGF_NODEFAULT), + CFG_STR("gpt-location", NULL, CFGF_NONE), + CFG_BOOL("gpt-no-backup", cfg_false, CFGF_NONE), ++ CFG_BOOL("gpt-protective-first", cfg_false, CFGF_NONE), + CFG_BOOL("fill", cfg_false, CFGF_NONE), + CFG_END() + }; +-- +2.43.0 +