mirror of
https://git.launchpad.net/livecd-rootfs
synced 2026-02-17 15:33:32 +00:00
Add architecture-specific boot configurators that translate the debian-cd boot shell scripts (boot-amd64, boot-arm64, boot-ppc64el, boot-riscv64, boot-s390x) into Python. The package uses a class hierarchy: - BaseBootConfigurator: abstract base with common functionality - GrubBootConfigurator: shared GRUB config generation - UEFIBootConfigurator: UEFI-specific shim/ESP handling - Architecture classes: AMD64, ARM64, PPC64EL, RISCV64, S390X A factory function make_boot_configurator_for_arch() creates the appropriate configurator for each architecture. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
224 lines
6.9 KiB
Python
224 lines
6.9 KiB
Python
"""RISC-V 64-bit architecture boot configuration."""
|
|
|
|
import pathlib
|
|
import shutil
|
|
|
|
from .grub import GrubBootConfigurator
|
|
|
|
|
|
def copy_unsigned_monolithic_grub_to_boot_tree(
|
|
grub_dir: pathlib.Path, efi_suffix: str, grub_target: str, boot_tree: pathlib.Path
|
|
) -> None:
|
|
efi_boot_dir = boot_tree.joinpath("EFI", "boot")
|
|
efi_boot_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
shutil.copy(
|
|
grub_dir.joinpath(
|
|
"usr",
|
|
"lib",
|
|
"grub",
|
|
f"{grub_target}-efi",
|
|
"monolithic",
|
|
f"gcd{efi_suffix}.efi",
|
|
),
|
|
efi_boot_dir.joinpath(f"boot{efi_suffix}.efi"),
|
|
)
|
|
|
|
grub_boot_dir = boot_tree.joinpath("boot", "grub", f"{grub_target}-efi")
|
|
grub_boot_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
src_grub_dir = grub_dir.joinpath("usr", "lib", "grub", f"{grub_target}-efi")
|
|
for mod_file in src_grub_dir.glob("*.mod"):
|
|
shutil.copy(mod_file, grub_boot_dir)
|
|
for lst_file in src_grub_dir.glob("*.lst"):
|
|
shutil.copy(lst_file, grub_boot_dir)
|
|
|
|
|
|
class RISCV64BootConfigurator(GrubBootConfigurator):
|
|
"""Boot setup for RISC-V 64-bit architecture."""
|
|
|
|
def mkisofs_opts(self) -> list[str | pathlib.Path]:
|
|
"""Return mkisofs options for RISC-V64."""
|
|
efi_img = self.scratch.joinpath("efi.img")
|
|
|
|
return [
|
|
"-joliet",
|
|
"on",
|
|
"-compliance",
|
|
"joliet_long_names",
|
|
"--append_partition",
|
|
"2",
|
|
"0xef",
|
|
efi_img,
|
|
"-boot_image",
|
|
"any",
|
|
"partition_offset=10240",
|
|
"-boot_image",
|
|
"any",
|
|
"partition_cyl_align=all",
|
|
"-boot_image",
|
|
"any",
|
|
"efi_path=--interval:appended_partition_2:all::",
|
|
"-boot_image",
|
|
"any",
|
|
"appended_part_as=gpt",
|
|
"-boot_image",
|
|
"any",
|
|
"cat_path=/boot/boot.cat",
|
|
"-fs",
|
|
"64m",
|
|
]
|
|
|
|
def extract_files(self) -> None:
|
|
"""Download and extract bootloader packages for RISC-V64."""
|
|
self.logger.log("extracting RISC-V64 boot files")
|
|
u_boot_dir = self.scratch.joinpath("u-boot-sifive")
|
|
|
|
# Download and extract bootloader packages
|
|
self.download_and_extract_package("grub2-common", self.grub_dir)
|
|
self.download_and_extract_package("grub-efi-riscv64-bin", self.grub_dir)
|
|
self.download_and_extract_package("grub-efi-riscv64-unsigned", self.grub_dir)
|
|
self.download_and_extract_package("u-boot-sifive", u_boot_dir)
|
|
|
|
# Add GRUB to tree
|
|
self.setup_grub_common_files()
|
|
copy_unsigned_monolithic_grub_to_boot_tree(
|
|
self.grub_dir, "riscv64", "riscv64", self.boot_tree
|
|
)
|
|
|
|
# Extract DTBs to tree
|
|
self.logger.log("extracting device tree files")
|
|
kernel_layer = self.scratch.joinpath("kernel-layer")
|
|
squashfs_path = self.iso_root.joinpath(
|
|
"casper", "ubuntu-server-minimal.squashfs"
|
|
)
|
|
|
|
# Extract device tree firmware from squashfs
|
|
self.logger.run(
|
|
[
|
|
"unsquashfs",
|
|
"-no-xattrs",
|
|
"-d",
|
|
kernel_layer,
|
|
squashfs_path,
|
|
"usr/lib/firmware",
|
|
],
|
|
check=True,
|
|
)
|
|
|
|
# Copy DTBs if they exist
|
|
dtb_dir = self.boot_tree.joinpath("dtb")
|
|
dtb_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
firmware_dir = kernel_layer.joinpath("usr", "lib", "firmware")
|
|
device_tree_files = list(firmware_dir.glob("*/device-tree/*"))
|
|
|
|
if device_tree_files:
|
|
for dtb_file in device_tree_files:
|
|
if dtb_file.is_file():
|
|
shutil.copy(dtb_file, dtb_dir)
|
|
|
|
# Clean up kernel layer
|
|
shutil.rmtree(kernel_layer)
|
|
|
|
# Copy tree contents to live-media rootfs
|
|
self.logger.run(["cp", "-aT", self.boot_tree, self.iso_root], check=True)
|
|
|
|
# Create ESP image with GRUB and dtbs
|
|
efi_img = self.scratch.joinpath("efi.img")
|
|
self.logger.run(
|
|
["mkfs.msdos", "-n", "ESP", "-C", "-v", efi_img, "32768"], check=True
|
|
)
|
|
|
|
# Add EFI files to ESP
|
|
efi_dir = self.boot_tree.joinpath("EFI")
|
|
self.logger.run(["mcopy", "-s", "-i", efi_img, efi_dir, "::/."], check=True)
|
|
|
|
# Add DTBs to ESP
|
|
self.logger.run(["mcopy", "-s", "-i", efi_img, dtb_dir, "::/."], check=True)
|
|
|
|
def generate_grub_config(self) -> None:
|
|
"""Generate grub.cfg for RISC-V64."""
|
|
grub_dir = self.iso_root.joinpath("boot", "grub")
|
|
grub_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
grub_cfg = grub_dir.joinpath("grub.cfg")
|
|
|
|
# Write GRUB header (without loadfont for RISC-V)
|
|
self.write_grub_header(grub_cfg, include_loadfont=False)
|
|
|
|
# Main menu entry
|
|
with grub_cfg.open("a") as f:
|
|
f.write(
|
|
f"""menuentry "Try or Install {self.humanproject}" {{
|
|
\tset gfxpayload=keep
|
|
\tlinux\t/casper/vmlinux efi=debug sysctl.kernel.watchdog_thresh=60 ---
|
|
\tinitrd\t/casper/initrd
|
|
}}
|
|
"""
|
|
)
|
|
|
|
# HWE kernel option if available
|
|
self.write_hwe_menu_entry(
|
|
grub_cfg,
|
|
"vmlinux",
|
|
"---",
|
|
extra_params="efi=debug sysctl.kernel.watchdog_thresh=60 ",
|
|
)
|
|
|
|
def post_process_iso(self, iso_path: pathlib.Path) -> None:
|
|
"""Add GPT partitions with U-Boot for SiFive Unmatched board.
|
|
|
|
The SiFive Unmatched board needs a GPT table containing U-Boot in
|
|
order to boot. U-Boot does not currently support booting from a CD,
|
|
so the GPT table also contains an entry pointing to the ESP so that
|
|
U-Boot can find it.
|
|
"""
|
|
u_boot_dir = self.scratch.joinpath(
|
|
"u-boot-sifive", "usr", "lib", "u-boot", "sifive_unmatched"
|
|
)
|
|
self.logger.run(
|
|
[
|
|
"sgdisk",
|
|
iso_path,
|
|
"--set-alignment=2",
|
|
"-d",
|
|
"1",
|
|
"-n",
|
|
"1:2082:10273",
|
|
"-c",
|
|
"1:loader2",
|
|
"-t",
|
|
"1:2E54B353-1271-4842-806F-E436D6AF6985",
|
|
"-n",
|
|
"3:10274:12321",
|
|
"-c",
|
|
"3:loader1",
|
|
"-t",
|
|
"3:5B193300-FC78-40CD-8002-E86C45580B47",
|
|
"-c",
|
|
"2:ESP",
|
|
"-r=2:3",
|
|
],
|
|
)
|
|
self.logger.run(
|
|
[
|
|
"dd",
|
|
f"if={u_boot_dir / 'u-boot.itb'}",
|
|
f"of={iso_path}",
|
|
"bs=512",
|
|
"seek=2082",
|
|
"conv=notrunc",
|
|
],
|
|
)
|
|
self.logger.run(
|
|
[
|
|
"dd",
|
|
f"if={u_boot_dir / 'u-boot-spl.bin'}",
|
|
f"of={iso_path}",
|
|
"bs=512",
|
|
"seek=10274",
|
|
"conv=notrunc",
|
|
],
|
|
)
|