Files
UniXNU Docs 5c92d4048f docs: add the VitePress documentation site
Add English and Simplified Chinese documentation under docs/, covering the boot chain, build, boot, debugging, porting, drivers, XNU 4 KiB pages, macOS and device notes. Add the Pages workflow and CNAME. Rename the boot manager from CrabApple to UniXNU across the package, symbols, paths, configuration file and logs. Update README with the documentation badge and CONTRIBUTING link.
2026-10-19 22:10:43 +08:00

74 lines
2.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""Assemble an ESP directory for UniXNU.
Copies one or more source trees into OUT (later trees win), compiles every
*.dts to *.dtb and *.dtso to *.dtbo with dtc (sources are not copied), and
places extra files with --put SRC=DEST (DEST relative to OUT).
Example:
stage-esp.py -o out/esp UniXNUPkg/Test/Qemu/esp \\
--put Build/Out/AARCH64-DEBUG/UniXNU.efi=EFI/BOOT/BOOTAA64.EFI
"""
import argparse
import shutil
import subprocess
import sys
from pathlib import Path
DT_SOURCES = {".dts": ".dtb", ".dtso": ".dtbo"}
def copy_tree(src: Path, out: Path) -> None:
for path in sorted(src.rglob("*")):
rel = path.relative_to(src)
dest = out / rel
if path.is_dir():
dest.mkdir(parents=True, exist_ok=True)
continue
dest.parent.mkdir(parents=True, exist_ok=True)
if path.suffix in DT_SOURCES:
target = dest.with_suffix(DT_SOURCES[path.suffix])
subprocess.run(
["dtc", "-q", "-I", "dts", "-O", "dtb", "-o", str(target), str(path)],
check=True,
)
else:
shutil.copy2(path, dest)
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("trees", nargs="+", type=Path, help="source trees, copied in order")
parser.add_argument("-o", "--out", type=Path, required=True, help="ESP directory to (re)create")
parser.add_argument("--put", action="append", default=[], metavar="SRC=DEST", help="extra file to place")
args = parser.parse_args()
if args.out.exists():
shutil.rmtree(args.out)
args.out.mkdir(parents=True)
for tree in args.trees:
if not tree.is_dir():
print(f"error: {tree} is not a directory", file=sys.stderr)
return 1
copy_tree(tree, args.out)
for item in args.put:
src, _, dest = item.partition("=")
if not dest:
print(f"error: --put needs SRC=DEST, got {item!r}", file=sys.stderr)
return 1
target = args.out / dest
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, target)
for path in sorted(args.out.rglob("*")):
if path.is_file():
print(f" {path.relative_to(args.out)} ({path.stat().st_size} bytes)")
return 0
if __name__ == "__main__":
sys.exit(main())