From c7dcda020004ca96d81236018fa9b9a2967bfb59 Mon Sep 17 00:00:00 2001 From: SashegDev Date: Mon, 7 Sep 2026 08:46:07 +0000 Subject: [PATCH] run: bare-metal hello boots on cortex-a7, emmc 8GiB real GPT33 --- qemu/hello.c | 9 ++++ qemu/run.sh | 15 +++++++ qemu/start.S | 8 ++++ tools/mkimage.py | 113 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 qemu/hello.c create mode 100755 qemu/run.sh create mode 100644 qemu/start.S create mode 100644 tools/mkimage.py diff --git a/qemu/hello.c b/qemu/hello.c new file mode 100644 index 0000000..7ca2663 --- /dev/null +++ b/qemu/hello.c @@ -0,0 +1,9 @@ +/* hello guest: proves qemu cortex-a7 pipeline on zern. virt UART0 0x09000000. */ +#define UART0 ((volatile unsigned int *)0x09000000) +static void uart_putc(char c) { *UART0 = (unsigned int)c; } +static void uart_puts(const char *s) { while (*s) uart_putc(*s++); } +void main(void) { + uart_puts("SAIMAA-STUB: cortex-a7 alive, RAM ok\r\n"); + uart_puts("SAIMAA-STUB: next -> PBL reads SBL1 LBA 90112\r\n"); + while (1) { } +} diff --git a/qemu/run.sh b/qemu/run.sh new file mode 100755 index 0000000..563bce0 --- /dev/null +++ b/qemu/run.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# run.sh — первый запуск: bare-metal hello на cortex-a7 + наш emmc.img на SDHCI. +# Ожидаем UART-привет. Это проверка трубы, не загрузка Lumia. +set -e +cd "$(dirname "$0")/.." +IMG=${IMG:-/tmp/emmc-test.img} +arm-none-eabi-gcc -nostartfiles -nostdlib -mcpu=cortex-a7 -marm \ + -Wl,-Ttext=0x40008000 -o /tmp/hello.elf qemu/start.S qemu/hello.c 2>/dev/null +arm-none-eabi-objcopy -O binary /tmp/hello.elf /tmp/hello.bin +echo "[run] guest built, starting qemu (10s timeout)..." +timeout 10 qemu-system-arm -M virt -cpu cortex-a7 -m 1024 -nographic \ + -kernel /tmp/hello.elf \ + -drive file="$IMG",if=none,format=raw,id=emmc \ + -device sdhci-pci -device sd-card,drive=emmc 2>&1 | head -10 +echo "[run] exit=$? (124 = timeout после вывода = OK для вечного цикла)" diff --git a/qemu/start.S b/qemu/start.S new file mode 100644 index 0000000..ad38396 --- /dev/null +++ b/qemu/start.S @@ -0,0 +1,8 @@ + .section .text + .global _start + .arm +_start: + ldr sp, =0x40200000 + bl main +hang: + b hang diff --git a/tools/mkimage.py b/tools/mkimage.py new file mode 100644 index 0000000..adea923 --- /dev/null +++ b/tools/mkimage.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +"""mkimage.py — сборка emmc.img с РЕАЛЬНОЙ GPT RM-1127 (33 раздела). +Layout: Boot1 4M + Boot2 4M + RPMB 4M + User 15154944 секторов. +Пока разделы пустые (нули) — контент из FFU payload будет следующим шагом. +Использование: ./tools/mkimage.py images/emmc.img +""" +import struct +import sys +import uuid +import zlib + +SECTOR = 512 +BOOT_MB = 4 +RPMB_MB = 4 +USER_SECTORS = 15154944 # MinSectorCount из FFU +# QEMU 6.2 sd-card требует power-of-2 размер: добиваем файл до 8GiB. +# GPT (primary+backup) остается на РЕАЛЬНЫХ смещениях User-области, +# хвост после User — нули (Windows увидит только primary GPT, WIP-допущение). +FILE_SIZE = 8 * 1024 * 1024 * 1024 + +BASIC = "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" +# (name, lba0, lba1, type_guid) — из tools/ffu_parse.py по orig FFU +PARTS = [ + ("DPP", 4096, 20479, BASIC), + ("MODEM_FSG", 20480, 23551, "638ff8e2-22c9-e33b-8f5d-0e81686a68cb"), + ("MODEM_FS1", 24576, 27647, "ebbeadaf-22c9-e33b-8f5d-0e81686a68cb"), + ("MODEM_FS2", 28672, 31743, "0a288b1f-22c9-e33b-8f5d-0e81686a68cb"), + ("MODEM_FSC", 32768, 32799, "57b90a16-22c9-e33b-8f5d-0e81686a68cb"), + ("DDR", 36864, 36927, "20a0c19c-286a-42fa-9ce7-f64c3226a794"), + ("LogFS", 40960, 73727, "bc0330eb-3410-4951-a617-03898dbe3372"), + ("SSD", 73728, 73759, "2c86e742-745e-4fdd-bfd8-b6a7ac638772"), + ("UEFI_BS_NV", 77824, 78335, "f0b4f48b-aeba-4ecf-9142-5dc30cdc3e77"), + ("UEFI_RT_NV", 81920, 82431, "6bb94537-7d1c-44d0-9dfe-6d77c011dbfc"), + ("BOOTMODE", 86016, 86047, "0e91ab96-8339-4ae4-a310-ed94357fd7d0"), + ("SBL1", 90112, 91135, "dea0ba2c-cbdd-4805-b4f9-f428251c3e98"), + ("DBI", 94208, 94271, "d4e0d938-b7fa-48c1-9d21-bc5ed5c4b203"), + ("UEFI", 98304, 102399, "400ffdcd-22e0-47e7-9a23-f16ed9382388"), + ("RPM", 102400, 103423, "098df793-d712-413d-9d4e-89d711772228"), + ("QSEE", 106496, 108543, "a053aa7f-40b8-4b1c-ba08-2f68ac71a4f4"), + ("QHEE", 110592, 111615, "e1a6a689-0c8d-4cc6-b4e8-55a4320fbd8a"), + ("WINSECAPP", 114688, 115711, "69b4201f-a5ad-45eb-9f49-45b38ccdaef5"), + ("TZAPPS", 118784, 151551, "14d11c40-2a3d-4f97-882d-103a1ec09333"), + ("BACKUP_SBL1", 151552, 152575, "a3381699-350c-465e-bd5d-fa3ab901a39a"), + ("BACKUP_DBI", 155648, 155711, "a3381699-350c-465e-bd5d-fa3ab901a39a"), + ("BACKUP_UEFI", 159744, 163839, "a3381699-350c-465e-bd5d-fa3ab901a39a"), + ("BACKUP_RPM", 163840, 164863, "a3381699-350c-465e-bd5d-fa3ab901a39a"), + ("BACKUP_QSEE", 167936, 169983, "a3381699-350c-465e-bd5d-fa3ab901a39a"), + ("BACKUP_QHEE", 172032, 173055, "a3381699-350c-465e-bd5d-fa3ab901a39a"), + ("BACKUP_WINSECAPP", 176128, 177151, "a3381699-350c-465e-bd5d-fa3ab901a39a"), + ("BACKUP_TZAPPS", 180224, 212991, "a3381699-350c-465e-bd5d-fa3ab901a39a"), + ("PLAT", 212992, 229375, "543c031a-4cb6-4897-bffe-4b485768a8ad"), + ("EFIESP", 229376, 360447, BASIC), + ("MMOS", 360448, 372735, BASIC), + ("SEC", 372736, 372767, "303e6ac3-af15-4c54-9e9b-d9a8fbecf401"), + ("MainOS", 376832, 4089855, BASIC), + ("Data", 4096000, 15150847, BASIC), +] + + +def gpt_header(nent, lba_backup, disk_guid, crc_entries, cur=1): + h = struct.pack("<8sIIIIQQQQ16sQIII", + b"EFI PART", 0x10000, 92, 0, 0, cur, lba_backup, + 34, USER_SECTORS - 34, + disk_guid.bytes_le, 2, nent, 128, crc_entries) + crc = zlib.crc32(h) & 0xFFFFFFFF + return struct.pack("<8sIIIIQQQQ16sQIII", + b"EFI PART", 0x10000, 92, crc, 0, cur, lba_backup, + 34, USER_SECTORS - 34, + disk_guid.bytes_le, 2, nent, 128, crc_entries) + + +def main(): + out = sys.argv[1] if len(sys.argv) > 1 else "images/emmc.img" + pre = (BOOT_MB * 2 + RPMB_MB) * 1024 * 1024 + total = FILE_SIZE + assert pre + USER_SECTORS * SECTOR <= total + print(f"[mkimage] {out}: boot {BOOT_MB}M x2 + rpmb {RPMB_MB}M + " + f"user {USER_SECTORS} sectors") + with open(out, "wb") as f: + f.truncate(total) # sparse + uoff = pre + # protective MBR + mbr = bytearray(512) + mbr[446:462] = struct.pack("