mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
- Updated axi4_interconnect_tb to include an additional master and issue high-priority access tests. - Introduced hp_mailbox_tb for testing the HP mailbox functionality, including register and doorbell operations. - Added plic_tb to validate PLIC priority, claim, and completion mechanisms. - Enhanced pll_ctrl_tb to initialize additional system control signals. - Updated soc_irq_topology_tb to account for new IRQ sources and validate IRQ signal behavior. - Improved sysctrl_tb to include tests for HP lifecycle control and status registers. - Added tests for HP boot bundle layout, CRC, and payload validation. - Introduced test_hp_mailbox.py for RTL regression testing of the HP mailbox. - Added test_hp_platform.py to validate HP platform configuration and generated-source boundaries. - Enhanced test_librelane_flow.py to ensure correct signal placement in chip configuration. - Added performance log tests to validate LP and HP coremark ratios. - Updated test_soc_topology.py to reflect changes in IRQ and peripheral mappings.
128 lines
3.9 KiB
Python
Executable File
128 lines
3.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Package LP firmware and the fixed HP Linux image set into one flash image."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import struct
|
|
import zlib
|
|
from pathlib import Path
|
|
|
|
|
|
FLASH_SIZE = 16 * 1024 * 1024
|
|
BUNDLE_OFFSET = 1 * 1024 * 1024
|
|
PAYLOAD_ALIGNMENT = 4096
|
|
MAGIC = 0x50485352
|
|
VERSION = 1
|
|
REQUIRED = 1
|
|
HEADER = struct.Struct("<8I")
|
|
ENTRY = struct.Struct("<6I")
|
|
ARTIFACTS = (
|
|
(1, "fw_jump.bin", 0x38000000, 512 * 1024),
|
|
(2, "retrosoc_hp.dtb", 0x38080000, 64 * 1024),
|
|
(3, "Image", 0x38400000, 12 * 1024 * 1024),
|
|
(4, "rootfs.cpio.gz", 0x39000000, 8 * 1024 * 1024),
|
|
)
|
|
HEADER_SIZE = HEADER.size + (ENTRY.size * len(ARTIFACTS))
|
|
|
|
|
|
def align_up(value: int, alignment: int) -> int:
|
|
return (value + alignment - 1) & ~(alignment - 1)
|
|
|
|
|
|
def sha256(data: bytes) -> str:
|
|
return hashlib.sha256(data).hexdigest()
|
|
|
|
|
|
def package(args: argparse.Namespace) -> None:
|
|
firmware = args.firmware.read_bytes()
|
|
if len(firmware) > BUNDLE_OFFSET:
|
|
raise ValueError(
|
|
f"LP firmware is {len(firmware)} bytes; bundle starts at {BUNDLE_OFFSET}"
|
|
)
|
|
|
|
payload_offset = align_up(BUNDLE_OFFSET + HEADER_SIZE, PAYLOAD_ALIGNMENT)
|
|
entries: list[bytes] = []
|
|
payloads: list[tuple[int, bytes]] = []
|
|
artifact_manifest: dict[str, object] = {}
|
|
cursor = payload_offset
|
|
for kind, name, load_address, maximum in ARTIFACTS:
|
|
data = (args.images / name).read_bytes()
|
|
if not data or len(data) > maximum:
|
|
raise ValueError(f"{name} size {len(data)} is outside 1..{maximum} bytes")
|
|
crc32 = zlib.crc32(data) & 0xFFFFFFFF
|
|
entries.append(ENTRY.pack(kind, cursor, load_address, len(data), crc32, REQUIRED))
|
|
payloads.append((cursor, data))
|
|
artifact_manifest[name] = {
|
|
"crc32": f"0x{crc32:08X}",
|
|
"flash_offset": f"0x{cursor:08X}",
|
|
"load_address": f"0x{load_address:08X}",
|
|
"sha256": sha256(data),
|
|
"size_bytes": len(data),
|
|
}
|
|
cursor = align_up(cursor + len(data), PAYLOAD_ALIGNMENT)
|
|
|
|
if cursor > FLASH_SIZE:
|
|
raise ValueError(f"HP boot image needs {cursor} bytes; flash capacity is {FLASH_SIZE}")
|
|
total_size = cursor - BUNDLE_OFFSET
|
|
header = HEADER.pack(
|
|
MAGIC,
|
|
VERSION,
|
|
HEADER_SIZE,
|
|
len(entries),
|
|
total_size,
|
|
0,
|
|
REQUIRED,
|
|
0,
|
|
) + b"".join(entries)
|
|
header_crc32 = zlib.crc32(header) & 0xFFFFFFFF
|
|
header = HEADER.pack(
|
|
MAGIC,
|
|
VERSION,
|
|
HEADER_SIZE,
|
|
len(entries),
|
|
total_size,
|
|
header_crc32,
|
|
REQUIRED,
|
|
0,
|
|
) + b"".join(entries)
|
|
|
|
image = bytearray(b"\xFF" * cursor)
|
|
image[: len(firmware)] = firmware
|
|
image[BUNDLE_OFFSET : BUNDLE_OFFSET + len(header)] = header
|
|
for offset, data in payloads:
|
|
image[offset : offset + len(data)] = data
|
|
|
|
args.output.parent.mkdir(parents=True, exist_ok=True)
|
|
args.output.write_bytes(image)
|
|
manifest = {
|
|
"schema_version": 1,
|
|
"format": "retrosoc-hp-boot-bundle-v1",
|
|
"bundle_offset": f"0x{BUNDLE_OFFSET:08X}",
|
|
"flash_capacity_bytes": FLASH_SIZE,
|
|
"header_crc32": f"0x{header_crc32:08X}",
|
|
"image_sha256": sha256(image),
|
|
"image_size_bytes": len(image),
|
|
"lp_firmware_size_bytes": len(firmware),
|
|
"artifacts": artifact_manifest,
|
|
}
|
|
args.manifest.parent.mkdir(parents=True, exist_ok=True)
|
|
args.manifest.write_text(
|
|
json.dumps(manifest, indent=2, sort_keys=True) + "\n", encoding="utf-8"
|
|
)
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--firmware", type=Path, required=True)
|
|
parser.add_argument("--images", type=Path, required=True)
|
|
parser.add_argument("--output", type=Path, required=True)
|
|
parser.add_argument("--manifest", type=Path, required=True)
|
|
package(parser.parse_args())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|