#!/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("