From a8e21f32be09347a071325f1d1548adf5c26705a Mon Sep 17 00:00:00 2001 From: Dmitry Ilyin <6576495+widgetii@users.noreply.github.com> Date: Sun, 28 Jun 2026 07:36:48 +0300 Subject: [PATCH] hisilicon: boot the GSL-signed Hi3519DV500 u-boot from a full NOR image PR #126 booted the raw self-extracting u-boot-z placed at flash offset 0, but the *published* dv500 NOR images (openipc-hi3519dv500-{dmeb,dmebpro}-nor-ultimate.bin) put the GSL-signed boot image first: a GSL/DDR header at offset 0 with the u-boot-z payload embedded deeper (~0x11200). The aarch64 flash-boot path blindly loaded the file from offset 0 to the DDR link address and started CPU0 there, so it executed the non-executable GSL header and hung right after the FMC load. Locate the u-boot-z block before loading: both the raw image (offset 0) and the GSL image open the payload with an aarch64 reset branch (b, opcode 0x14......) immediately followed by a run of 0xdeadbeef self-descriptor markers. Scan the first 256 KiB for that signature and load from there. Verified booting the published GSL-signed images end-to-end (U-Boot 2022.07 -> kernel -> squashfs -> "Welcome to OpenIPC" -> login), both binnings, deterministic across runs, zero Oops. Completes the dv500 NOR boot started in #126 so QEMU runs the actual released image, not just a raw u-boot. Co-Authored-By: Claude Opus 4.8 --- qemu/hw/arm/hisilicon.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/qemu/hw/arm/hisilicon.c b/qemu/hw/arm/hisilicon.c index 1ccfbe6..3d017e2 100644 --- a/qemu/hw/arm/hisilicon.c +++ b/qemu/hw/arm/hisilicon.c @@ -5289,7 +5289,34 @@ static void hisilicon_common_init(MachineState *machine, "", c->name, c->name); exit(1); } - rom_add_blob_fixed("hisilicon.uboot", udata, ulen, + /* + * The flash may hold either the raw self-extracting u-boot-z at + * offset 0, or a full NOR image whose first partition is the + * GSL-signed boot image (boot---nor.bin) — there the + * GSL/DDR header sits at offset 0 and the u-boot-z payload is + * embedded deeper (e.g. 0x11200). Both open with an aarch64 reset + * branch (b, opcode 0x14......) immediately followed by a run of + * 0xdeadbeef self-descriptor markers, so locate that block and load + * it at the DDR link address. Loading the GSL header verbatim would + * land non-executable bytes at the entry and hang at "Starting". + */ + size_t uoff = 0; + { + const uint32_t *w = (const uint32_t *)udata; + size_t nw = ulen / 4; + size_t scan = MIN(nw, (size_t)(0x40000 / 4)); /* first 256 KiB */ + for (size_t i = 0; i + 5 <= scan; i++) { + if ((le32_to_cpu(w[i]) & 0xFC000000) == 0x14000000 && + le32_to_cpu(w[i + 1]) == 0xdeadbeef && + le32_to_cpu(w[i + 2]) == 0xdeadbeef && + le32_to_cpu(w[i + 3]) == 0xdeadbeef && + le32_to_cpu(w[i + 4]) == 0xdeadbeef) { + uoff = (size_t)i * 4; + break; + } + } + } + rom_add_blob_fixed("hisilicon.uboot", udata + uoff, ulen - uoff, c->uboot_load_addr); g_free(udata);