mirror of
https://git.launchpad.net/livecd-rootfs
synced 2026-03-13 11:07:41 +00:00
Compare commits
33 Commits
26.04.19
...
ubuntu/mas
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dad4a04751 | ||
|
|
9861d393aa | ||
|
|
0b30131aae | ||
|
|
301cf9622c | ||
|
|
a3c8532764 | ||
|
|
92e680cc2c | ||
|
|
b1c61d8bf1 | ||
|
|
9c4ce17909 | ||
|
|
b1ca2ae69b | ||
|
|
31a0c2716c | ||
|
|
a66fbc54b7 | ||
|
|
9819eae23c | ||
|
|
b135edf10c | ||
|
|
112153325c | ||
|
|
39ab3ea113 | ||
|
|
a6ac43fcda | ||
|
|
92c29ecbf2 | ||
|
|
7fdf181234 | ||
|
|
49a0415299 | ||
|
|
96f41a4cf5 | ||
|
|
2579dc30cb | ||
|
|
77db814700 | ||
|
|
a1c8d7f3bd | ||
|
|
f734d8cb8c | ||
|
|
7e3c74afac | ||
|
|
7c4588191c | ||
|
|
42df11d4cc | ||
|
|
6db44c1ea6 | ||
|
|
081981e650 | ||
|
|
a2a166d93d | ||
|
|
a6466ab0a3 | ||
|
|
a5cffa8414 | ||
|
|
ff3addb2f8 |
49
debian/changelog
vendored
49
debian/changelog
vendored
@ -1,3 +1,52 @@
|
|||||||
|
livecd-rootfs (26.04.23) resolute; urgency=medium
|
||||||
|
|
||||||
|
[ Tobias Heider ]
|
||||||
|
* Fix ISO builds when KERNEL_FLAVOUR != generic.
|
||||||
|
|
||||||
|
-- Michael Hudson-Doyle <michael.hudson@ubuntu.com> Mon, 02 Mar 2026 10:51:47 +1300
|
||||||
|
|
||||||
|
livecd-rootfs (26.04.22) resolute; urgency=medium
|
||||||
|
|
||||||
|
[ Oliver Gayot ]
|
||||||
|
* Pull the model from Launchpad's lp:canonical-models
|
||||||
|
repo, instead of having it uploaded as part of livecd-rootfs. This
|
||||||
|
indirection makes it possible to update the models without requiring a new
|
||||||
|
upload of livecd-rootfs every time.
|
||||||
|
|
||||||
|
[ Michael Hudson-Doyle ]
|
||||||
|
* Fix two more problems with livefs-built ISOs:
|
||||||
|
- Generate the for-iso squashfs in the right place for Kubuntu.
|
||||||
|
- Fix confusion about the kernel path on the ISO on riscv64.
|
||||||
|
|
||||||
|
[ Tobias Heider ]
|
||||||
|
* Fix pool generation when using extra_ppas.
|
||||||
|
|
||||||
|
-- Michael Hudson-Doyle <michael.hudson@ubuntu.com> Thu, 26 Feb 2026 10:56:42 +1300
|
||||||
|
|
||||||
|
livecd-rootfs (26.04.21) resolute; urgency=medium
|
||||||
|
|
||||||
|
[ Dan Bungert ]
|
||||||
|
* Update new signed models to ship latest nvidia drivers for ubuntu hybrid.
|
||||||
|
|
||||||
|
-- Didier Roche-Tolomelli <didrocks@ubuntu.com> Wed, 25 Feb 2026 08:38:32 +0100
|
||||||
|
|
||||||
|
livecd-rootfs (26.04.20) resolute; urgency=medium
|
||||||
|
|
||||||
|
[ Michael Raymond ]
|
||||||
|
* Bug-fix: Only use main archive keyring when building with debootstrap
|
||||||
|
so EOL release signatures can be verified after EOL.
|
||||||
|
|
||||||
|
[ Allen Abraham ]
|
||||||
|
* Make SBOM generation optional in create_manifest function.
|
||||||
|
|
||||||
|
[ Michael Hudson-Doyle ]
|
||||||
|
* 030-ubuntu-live-system-seed.binary: do not run if there is no layer to
|
||||||
|
install the system, in particular on arm64.
|
||||||
|
* Fix some path confusion in the new isobuilder.boot package and refactor
|
||||||
|
grub config generation to be more string based.
|
||||||
|
|
||||||
|
-- Michael Hudson-Doyle <michael.hudson@ubuntu.com> Fri, 20 Feb 2026 12:45:41 +1300
|
||||||
|
|
||||||
livecd-rootfs (26.04.19) resolute; urgency=medium
|
livecd-rootfs (26.04.19) resolute; urgency=medium
|
||||||
|
|
||||||
* Translate the debian-cd tools/boot/$series/boot-$arch scripts to Python
|
* Translate the debian-cd tools/boot/$series/boot-$arch scripts to Python
|
||||||
|
|||||||
@ -576,7 +576,7 @@ if [ "${MAKE_ISO}" = "yes" ]; then
|
|||||||
# create a for-iso.filesystem.squashfs that does.
|
# create a for-iso.filesystem.squashfs that does.
|
||||||
if [ -z "$PASSES" ]; then
|
if [ -z "$PASSES" ]; then
|
||||||
isobuild generate-sources --mountpoint=/cdrom > chroot/etc/apt/sources.list.d/cdrom.sources
|
isobuild generate-sources --mountpoint=/cdrom > chroot/etc/apt/sources.list.d/cdrom.sources
|
||||||
create_squashfs chroot for-iso.filesystem.squashfs
|
create_squashfs chroot ${PWD}/for-iso.filesystem.squashfs
|
||||||
fi
|
fi
|
||||||
# Link kernel and initrd files. The ${thing#${PREFIX}} expansion strips
|
# Link kernel and initrd files. The ${thing#${PREFIX}} expansion strips
|
||||||
# the PREFIX, so "livecd.ubuntu-server.kernel-generic" becomes
|
# the PREFIX, so "livecd.ubuntu-server.kernel-generic" becomes
|
||||||
|
|||||||
@ -1397,6 +1397,8 @@ if [ -n "$PASSES" ] && [ -z "$LIVE_PASSES" ]; then
|
|||||||
"Either set \$LIVE_PASSES or add a pass ending with '.live'."
|
"Either set \$LIVE_PASSES or add a pass ending with '.live'."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "DEBOOTSTRAP_OPTIONS=\"--keyring=/usr/share/keyrings/ubuntu-archive-keyring.gpg\"" >> config/bootstrap
|
||||||
|
|
||||||
echo "LB_CHROOT_HOOKS=\"$CHROOT_HOOKS\"" >> config/chroot
|
echo "LB_CHROOT_HOOKS=\"$CHROOT_HOOKS\"" >> config/chroot
|
||||||
echo "SUBPROJECT=\"${SUBPROJECT:-}\"" >> config/chroot
|
echo "SUBPROJECT=\"${SUBPROJECT:-}\"" >> config/chroot
|
||||||
echo "LB_DISTRIBUTION=\"$SUITE\"" >> config/chroot
|
echo "LB_DISTRIBUTION=\"$SUITE\"" >> config/chroot
|
||||||
|
|||||||
@ -44,6 +44,7 @@ create_manifest() {
|
|||||||
local base_default_sbom_name="ubuntu-cloud-image-$(grep "VERSION_ID" $chroot_root/etc/os-release | cut --delimiter "=" --field 2 | tr -d '"')-${ARCH}-$(date +%Y%m%dT%H:%M:%S)"
|
local base_default_sbom_name="ubuntu-cloud-image-$(grep "VERSION_ID" $chroot_root/etc/os-release | cut --delimiter "=" --field 2 | tr -d '"')-${ARCH}-$(date +%Y%m%dT%H:%M:%S)"
|
||||||
local sbom_file_name=${3:-"${base_default_sbom_name}.spdx"}
|
local sbom_file_name=${3:-"${base_default_sbom_name}.spdx"}
|
||||||
local sbom_document_name=${4:-"${base_default_sbom_name}"}
|
local sbom_document_name=${4:-"${base_default_sbom_name}"}
|
||||||
|
local should_include_sbom=${5:-"true"}
|
||||||
local sbom_log=${sbom_document_name}.log
|
local sbom_log=${sbom_document_name}.log
|
||||||
echo "create_manifest chroot_root: ${chroot_root}"
|
echo "create_manifest chroot_root: ${chroot_root}"
|
||||||
dpkg-query --show --admindir="${chroot_root}/var/lib/dpkg" > ${target_file}
|
dpkg-query --show --admindir="${chroot_root}/var/lib/dpkg" > ${target_file}
|
||||||
@ -54,22 +55,26 @@ create_manifest() {
|
|||||||
echo "create_manifest creating file listing."
|
echo "create_manifest creating file listing."
|
||||||
local target_filelist=${2%.manifest}.filelist
|
local target_filelist=${2%.manifest}.filelist
|
||||||
(cd "${chroot_root}" && find -xdev) | sort > "${target_filelist}"
|
(cd "${chroot_root}" && find -xdev) | sort > "${target_filelist}"
|
||||||
# only creating sboms for CPC project at this time
|
if [ "$should_include_sbom" = "true" ]; then
|
||||||
if [[ ! $(which cpc-sbom) ]]; then
|
# only creating sboms for CPC project at this time
|
||||||
# ensure the tool is installed
|
if [[ ! $(which cpc-sbom) ]]; then
|
||||||
sudo snap install --classic --edge cpc-sbom
|
# ensure the tool is installed
|
||||||
fi
|
sudo snap install --classic --edge cpc-sbom
|
||||||
# generate the SBOM
|
fi
|
||||||
cpc-sbom --rootdir ${chroot_root} --ignore-copyright-parsing-errors --ignore-copyright-file-not-found-errors --document-name ${sbom_document_name} >"${sbom_file_name}" 2>"${sbom_log}"
|
# generate the SBOM
|
||||||
SBOM_GENERATION_EXIT_CODE=$?
|
cpc-sbom --rootdir ${chroot_root} --ignore-copyright-parsing-errors --ignore-copyright-file-not-found-errors --document-name ${sbom_document_name} >"${sbom_file_name}" 2>"${sbom_log}"
|
||||||
if [[ ${SBOM_GENERATION_EXIT_CODE} != "0" ]]; then
|
SBOM_GENERATION_EXIT_CODE=$?
|
||||||
# check for failure and print log
|
if [[ ${SBOM_GENERATION_EXIT_CODE} != "0" ]]; then
|
||||||
echo "ERROR: SBOM generation failed. See ${sbom_log}"
|
# check for failure and print log
|
||||||
cat "$sbom_log"
|
echo "ERROR: SBOM generation failed. See ${sbom_log}"
|
||||||
exit 1
|
cat "$sbom_log"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "SBOM generation succeeded. see ${sbom_log} for details"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo "SBOM generation succeeded. see ${sbom_log} for details"
|
echo "SBOM generation skipped"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
echo "create_manifest finished"
|
echo "create_manifest finished"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,10 +108,10 @@ class AptStateManager:
|
|||||||
def in_release_path(self) -> pathlib.Path:
|
def in_release_path(self) -> pathlib.Path:
|
||||||
"""Return the path to the InRelease file.
|
"""Return the path to the InRelease file.
|
||||||
|
|
||||||
This assumes exactly one InRelease file matches the pattern.
|
This ignores all but the first path.
|
||||||
Will raise ValueError if there are 0 or multiple matches.
|
Will raise Error if there isn't at least one match.
|
||||||
"""
|
"""
|
||||||
[path] = self.apt_root.joinpath("var/lib/apt/lists").glob(
|
[path] = self.apt_root.joinpath("var/lib/apt/lists").glob(
|
||||||
f"*_dists_{self.series}_InRelease"
|
f"*ubuntu.com*_dists_{self.series}_InRelease"
|
||||||
)
|
)
|
||||||
return path
|
return path
|
||||||
|
|||||||
@ -17,6 +17,7 @@ def make_boot_configurator_for_arch(
|
|||||||
arch: str,
|
arch: str,
|
||||||
logger: "Logger",
|
logger: "Logger",
|
||||||
apt_state: "AptStateManager",
|
apt_state: "AptStateManager",
|
||||||
|
workdir: pathlib.Path,
|
||||||
iso_root: pathlib.Path,
|
iso_root: pathlib.Path,
|
||||||
) -> "BaseBootConfigurator":
|
) -> "BaseBootConfigurator":
|
||||||
"""Factory function to create boot configurator for a specific architecture."""
|
"""Factory function to create boot configurator for a specific architecture."""
|
||||||
@ -24,23 +25,23 @@ def make_boot_configurator_for_arch(
|
|||||||
case "amd64":
|
case "amd64":
|
||||||
from .amd64 import AMD64BootConfigurator
|
from .amd64 import AMD64BootConfigurator
|
||||||
|
|
||||||
return AMD64BootConfigurator(logger, apt_state, iso_root)
|
return AMD64BootConfigurator(logger, apt_state, workdir, iso_root)
|
||||||
case "arm64":
|
case "arm64":
|
||||||
from .arm64 import ARM64BootConfigurator
|
from .arm64 import ARM64BootConfigurator
|
||||||
|
|
||||||
return ARM64BootConfigurator(logger, apt_state, iso_root)
|
return ARM64BootConfigurator(logger, apt_state, workdir, iso_root)
|
||||||
case "ppc64el":
|
case "ppc64el":
|
||||||
from .ppc64el import PPC64ELBootConfigurator
|
from .ppc64el import PPC64ELBootConfigurator
|
||||||
|
|
||||||
return PPC64ELBootConfigurator(logger, apt_state, iso_root)
|
return PPC64ELBootConfigurator(logger, apt_state, workdir, iso_root)
|
||||||
case "riscv64":
|
case "riscv64":
|
||||||
from .riscv64 import RISCV64BootConfigurator
|
from .riscv64 import RISCV64BootConfigurator
|
||||||
|
|
||||||
return RISCV64BootConfigurator(logger, apt_state, iso_root)
|
return RISCV64BootConfigurator(logger, apt_state, workdir, iso_root)
|
||||||
case "s390x":
|
case "s390x":
|
||||||
from .s390x import S390XBootConfigurator
|
from .s390x import S390XBootConfigurator
|
||||||
|
|
||||||
return S390XBootConfigurator(logger, apt_state, iso_root)
|
return S390XBootConfigurator(logger, apt_state, workdir, iso_root)
|
||||||
case _:
|
case _:
|
||||||
raise ValueError(f"Unsupported architecture: {arch}")
|
raise ValueError(f"Unsupported architecture: {arch}")
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,9 @@
|
|||||||
import pathlib
|
import pathlib
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from .uefi import UEFIBootConfigurator
|
|
||||||
from .base import default_kernel_params
|
from .base import default_kernel_params
|
||||||
|
from .grub import copy_grub_modules
|
||||||
|
from .uefi import UEFIBootConfigurator
|
||||||
|
|
||||||
|
|
||||||
CALAMARES_PROJECTS = ["kubuntu", "lubuntu"]
|
CALAMARES_PROJECTS = ["kubuntu", "lubuntu"]
|
||||||
@ -51,16 +52,13 @@ class AMD64BootConfigurator(UEFIBootConfigurator):
|
|||||||
opts.extend(
|
opts.extend(
|
||||||
[
|
[
|
||||||
"--grub2-mbr",
|
"--grub2-mbr",
|
||||||
self.grub_dir.joinpath("usr/lib/grub/i386-pc/boot_hybrid.img"),
|
self.scratch.joinpath("boot_hybrid.img"),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
# ## Set up the mkisofs options for UEFI boot.
|
# ## Set up the mkisofs options for UEFI boot.
|
||||||
opts.extend(self.get_uefi_mkisofs_opts())
|
opts.extend(self.get_uefi_mkisofs_opts())
|
||||||
|
|
||||||
# ## Add cd-boot-tree to the ISO
|
|
||||||
opts.append(str(self.boot_tree))
|
|
||||||
|
|
||||||
return opts
|
return opts
|
||||||
|
|
||||||
def extract_files(self) -> None:
|
def extract_files(self) -> None:
|
||||||
@ -71,115 +69,113 @@ class AMD64BootConfigurator(UEFIBootConfigurator):
|
|||||||
|
|
||||||
# AMD64-specific: Add BIOS/legacy boot files
|
# AMD64-specific: Add BIOS/legacy boot files
|
||||||
with self.logger.logged("adding BIOS/legacy boot files"):
|
with self.logger.logged("adding BIOS/legacy boot files"):
|
||||||
self.download_and_extract_package("grub-pc-bin", self.grub_dir)
|
grub_pc_pkg_dir = self.scratch.joinpath("grub-pc-pkg")
|
||||||
|
self.download_and_extract_package("grub-pc-bin", grub_pc_pkg_dir)
|
||||||
|
|
||||||
grub_boot_dir = self.boot_tree.joinpath("boot", "grub", "i386-pc")
|
grub_boot_dir = self.iso_root.joinpath("boot", "grub", "i386-pc")
|
||||||
grub_boot_dir.mkdir(parents=True, exist_ok=True)
|
grub_boot_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
src_grub_dir = self.grub_dir.joinpath("usr", "lib", "grub", "i386-pc")
|
src_grub_dir = grub_pc_pkg_dir.joinpath("usr", "lib", "grub", "i386-pc")
|
||||||
|
|
||||||
shutil.copy(src_grub_dir.joinpath("eltorito.img"), grub_boot_dir)
|
shutil.copy(src_grub_dir.joinpath("eltorito.img"), grub_boot_dir)
|
||||||
|
shutil.copy(src_grub_dir.joinpath("boot_hybrid.img"), self.scratch)
|
||||||
|
|
||||||
self.copy_grub_modules(
|
copy_grub_modules(
|
||||||
src_grub_dir, grub_boot_dir, ["*.mod", "*.lst", "*.o"]
|
grub_pc_pkg_dir,
|
||||||
|
self.iso_root,
|
||||||
|
"i386-pc",
|
||||||
|
["*.mod", "*.lst", "*.o"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate_grub_config(self) -> None:
|
def generate_grub_config(self) -> str:
|
||||||
"""Generate grub.cfg and loopback.cfg for the boot tree."""
|
"""Generate grub.cfg content for AMD64."""
|
||||||
boot_grub_dir = self.boot_tree.joinpath("boot", "grub")
|
result = self.grub_header()
|
||||||
boot_grub_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
grub_cfg = boot_grub_dir.joinpath("grub.cfg")
|
|
||||||
|
|
||||||
if self.project == "ubuntu-mini-iso":
|
if self.project == "ubuntu-mini-iso":
|
||||||
self.write_grub_header(grub_cfg)
|
result += """\
|
||||||
with grub_cfg.open("a") as f:
|
menuentry "Choose an Ubuntu version to install" {
|
||||||
f.write(
|
|
||||||
"""menuentry "Choose an Ubuntu version to install" {
|
|
||||||
set gfxpayload=keep
|
set gfxpayload=keep
|
||||||
linux /casper/vmlinuz iso-chooser-menu ip=dhcp ---
|
linux /casper/vmlinuz iso-chooser-menu ip=dhcp ---
|
||||||
initrd /casper/initrd
|
initrd /casper/initrd
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
)
|
return result
|
||||||
return
|
|
||||||
|
|
||||||
# Generate grub.cfg
|
|
||||||
kernel_params = default_kernel_params(self.project)
|
kernel_params = default_kernel_params(self.project)
|
||||||
|
|
||||||
# Write common GRUB header
|
|
||||||
self.write_grub_header(grub_cfg)
|
|
||||||
|
|
||||||
# Main menu entry
|
# Main menu entry
|
||||||
with grub_cfg.open("a") as f:
|
result += f"""\
|
||||||
f.write(
|
menuentry "Try or Install {self.humanproject}" {{
|
||||||
f"""menuentry "Try or Install {self.humanproject}" {{
|
|
||||||
set gfxpayload=keep
|
set gfxpayload=keep
|
||||||
linux /casper/vmlinuz {kernel_params}
|
linux /casper/vmlinuz {kernel_params}
|
||||||
initrd /casper/initrd
|
initrd /casper/initrd
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
)
|
|
||||||
|
|
||||||
# All but server get safe-graphics mode
|
# All but server get safe-graphics mode
|
||||||
if self.project != "ubuntu-server":
|
if self.project != "ubuntu-server":
|
||||||
with grub_cfg.open("a") as f:
|
result += f"""\
|
||||||
f.write(
|
menuentry "{self.humanproject} (safe graphics)" {{
|
||||||
f"""menuentry "{self.humanproject} (safe graphics)" {{
|
|
||||||
set gfxpayload=keep
|
set gfxpayload=keep
|
||||||
linux /casper/vmlinuz nomodeset {kernel_params}
|
linux /casper/vmlinuz nomodeset {kernel_params}
|
||||||
initrd /casper/initrd
|
initrd /casper/initrd
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
)
|
|
||||||
|
|
||||||
# ubiquity based projects get OEM mode
|
# ubiquity based projects get OEM mode
|
||||||
if "maybe-ubiquity" in kernel_params:
|
if "maybe-ubiquity" in kernel_params:
|
||||||
oem_kernel_params = kernel_params.replace(
|
oem_kernel_params = kernel_params.replace(
|
||||||
"maybe-ubiquity", "only-ubiquity oem-config/enable=true"
|
"maybe-ubiquity", "only-ubiquity oem-config/enable=true"
|
||||||
)
|
)
|
||||||
with grub_cfg.open("a") as f:
|
result += f"""\
|
||||||
f.write(
|
menuentry "OEM install (for manufacturers)" {{
|
||||||
f"""menuentry "OEM install (for manufacturers)" {{
|
|
||||||
set gfxpayload=keep
|
set gfxpayload=keep
|
||||||
linux /casper/vmlinuz {oem_kernel_params}
|
linux /casper/vmlinuz {oem_kernel_params}
|
||||||
initrd /casper/initrd
|
initrd /casper/initrd
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
)
|
|
||||||
|
|
||||||
# Calamares-based projects get OEM mode
|
# Calamares-based projects get OEM mode
|
||||||
if self.project in CALAMARES_PROJECTS:
|
if self.project in CALAMARES_PROJECTS:
|
||||||
with grub_cfg.open("a") as f:
|
result += f"""\
|
||||||
f.write(
|
menuentry "OEM install (for manufacturers)" {{
|
||||||
f"""menuentry "OEM install (for manufacturers)" {{
|
|
||||||
set gfxpayload=keep
|
set gfxpayload=keep
|
||||||
linux /casper/vmlinuz {kernel_params} oem-config/enable=true
|
linux /casper/vmlinuz {kernel_params} oem-config/enable=true
|
||||||
initrd /casper/initrd
|
initrd /casper/initrd
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
)
|
|
||||||
|
|
||||||
# Currently only server is built with HWE, hence no safe-graphics/OEM
|
# Currently only server is built with HWE, hence no safe-graphics/OEM
|
||||||
if self.hwe:
|
if self.hwe:
|
||||||
with grub_cfg.open("a") as f:
|
result += f"""\
|
||||||
f.write(
|
menuentry "{self.humanproject} with the HWE kernel" {{
|
||||||
f"""menuentry "{self.humanproject} with the HWE kernel" {{
|
|
||||||
set gfxpayload=keep
|
set gfxpayload=keep
|
||||||
linux /casper/hwe-vmlinuz {kernel_params}
|
linux /casper/hwe-vmlinuz {kernel_params}
|
||||||
initrd /casper/hwe-initrd
|
initrd /casper/hwe-initrd
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
)
|
|
||||||
|
|
||||||
# Create the loopback config, based on the main config
|
# UEFI Entries (wrapped in grub_platform check for dual BIOS/UEFI support)
|
||||||
with grub_cfg.open("r") as f:
|
uefi_menu_entries = self.uefi_menu_entries()
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
# sed: delete from line 1 to menu_color_highlight, delete from
|
result += f"""\
|
||||||
# grub_platform to end and replace '---' with
|
grub_platform
|
||||||
# 'iso-scan/filename=${iso_path} ---' in lines with 'linux'
|
if [ "$grub_platform" = "efi" ]; then
|
||||||
lines = content.split("\n")
|
{uefi_menu_entries}\
|
||||||
|
fi
|
||||||
|
"""
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def generate_loopback_config(grub_content: str) -> str:
|
||||||
|
"""Derive loopback.cfg from grub.cfg content.
|
||||||
|
|
||||||
|
Strips the header (up to menu_color_highlight) and the UEFI
|
||||||
|
trailer (from grub_platform to end), and adds iso-scan/filename
|
||||||
|
to linux lines.
|
||||||
|
"""
|
||||||
|
lines = grub_content.split("\n")
|
||||||
start_idx = 0
|
start_idx = 0
|
||||||
for i, line in enumerate(lines):
|
for i, line in enumerate(lines):
|
||||||
if "menu_color_highlight" in line:
|
if "menu_color_highlight" in line:
|
||||||
@ -202,16 +198,19 @@ class AMD64BootConfigurator(UEFIBootConfigurator):
|
|||||||
for line in loopback_lines
|
for line in loopback_lines
|
||||||
]
|
]
|
||||||
|
|
||||||
loopback_cfg = boot_grub_dir.joinpath("loopback.cfg")
|
return "\n".join(loopback_lines)
|
||||||
with loopback_cfg.open("w") as f:
|
|
||||||
f.write("\n".join(loopback_lines))
|
|
||||||
|
|
||||||
# UEFI Entries (wrapped in grub_platform check for dual BIOS/UEFI support)
|
def make_bootable(
|
||||||
with grub_cfg.open("a") as f:
|
self,
|
||||||
f.write("grub_platform\n")
|
project: str,
|
||||||
f.write('if [ "$grub_platform" = "efi" ]; then\n')
|
capproject: str,
|
||||||
|
subarch: str,
|
||||||
self.write_uefi_menu_entries(grub_cfg)
|
hwe: bool,
|
||||||
|
) -> None:
|
||||||
with grub_cfg.open("a") as f:
|
"""Make the ISO bootable, including generating loopback.cfg."""
|
||||||
f.write("fi\n")
|
super().make_bootable(project, capproject, subarch, hwe)
|
||||||
|
grub_cfg = self.iso_root.joinpath("boot", "grub", "grub.cfg")
|
||||||
|
grub_content = grub_cfg.read_text()
|
||||||
|
self.iso_root.joinpath("boot", "grub", "loopback.cfg").write_text(
|
||||||
|
self.generate_loopback_config(grub_content)
|
||||||
|
)
|
||||||
|
|||||||
@ -26,7 +26,6 @@ class ARM64BootConfigurator(UEFIBootConfigurator):
|
|||||||
opts.extend(self.get_uefi_mkisofs_opts())
|
opts.extend(self.get_uefi_mkisofs_opts())
|
||||||
# ARM64-specific: partition cylinder alignment
|
# ARM64-specific: partition cylinder alignment
|
||||||
opts.extend(["-partition_cyl_align", "all"])
|
opts.extend(["-partition_cyl_align", "all"])
|
||||||
opts.append(self.boot_tree)
|
|
||||||
return opts
|
return opts
|
||||||
|
|
||||||
def extract_files(self) -> None:
|
def extract_files(self) -> None:
|
||||||
@ -34,19 +33,15 @@ class ARM64BootConfigurator(UEFIBootConfigurator):
|
|||||||
with self.logger.logged("extracting ARM64 boot files"):
|
with self.logger.logged("extracting ARM64 boot files"):
|
||||||
self.extract_uefi_files()
|
self.extract_uefi_files()
|
||||||
|
|
||||||
def generate_grub_config(self) -> None:
|
def generate_grub_config(self) -> str:
|
||||||
"""Generate grub.cfg for ARM64."""
|
"""Generate grub.cfg for ARM64."""
|
||||||
kernel_params = default_kernel_params(self.project)
|
kernel_params = default_kernel_params(self.project)
|
||||||
|
|
||||||
grub_cfg = self.grub_dir.joinpath("grub.cfg")
|
result = self.grub_header()
|
||||||
|
|
||||||
# Write common GRUB header
|
|
||||||
self.write_grub_header(grub_cfg)
|
|
||||||
|
|
||||||
# ARM64-specific: Snapdragon workarounds
|
# ARM64-specific: Snapdragon workarounds
|
||||||
with grub_cfg.open("a") as f:
|
result += f"""\
|
||||||
f.write(
|
set cmdline=
|
||||||
"""set cmdline=
|
|
||||||
smbios --type 4 --get-string 5 --set proc_version
|
smbios --type 4 --get-string 5 --set proc_version
|
||||||
regexp "Snapdragon.*" "$proc_version"
|
regexp "Snapdragon.*" "$proc_version"
|
||||||
if [ $? = 0 ]; then
|
if [ $? = 0 ]; then
|
||||||
@ -59,16 +54,14 @@ if [ $? = 0 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
menuentry "Try or Install {self.humanproject}" {{
|
menuentry "Try or Install {self.humanproject}" {{
|
||||||
\tset gfxpayload=keep
|
set gfxpayload=keep
|
||||||
\tlinux\t/casper/vmlinuz $cmdline {kernel_params} console=tty0
|
linux /casper/vmlinuz $cmdline {kernel_params} console=tty0
|
||||||
\tinitrd\t/casper/initrd
|
initrd /casper/initrd
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
)
|
|
||||||
|
|
||||||
# HWE kernel option if available
|
# HWE kernel option if available
|
||||||
self.write_hwe_menu_entry(
|
result += self.hwe_menu_entry(
|
||||||
grub_cfg,
|
|
||||||
"vmlinuz",
|
"vmlinuz",
|
||||||
f"{kernel_params} console=tty0",
|
f"{kernel_params} console=tty0",
|
||||||
extra_params="$cmdline ",
|
extra_params="$cmdline ",
|
||||||
@ -78,4 +71,6 @@ menuentry "Try or Install {self.humanproject}" {{
|
|||||||
# but it's not actually set anywhere in the grub.cfg, so we omit it here
|
# but it's not actually set anywhere in the grub.cfg, so we omit it here
|
||||||
|
|
||||||
# UEFI Entries (ARM64 is UEFI-only, no grub_platform check needed)
|
# UEFI Entries (ARM64 is UEFI-only, no grub_platform check needed)
|
||||||
self.write_uefi_menu_entries(grub_cfg)
|
result += self.uefi_menu_entries()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
"""Base classes and helper functions for boot configuration."""
|
"""Base classes and helper functions for boot configuration."""
|
||||||
|
|
||||||
import pathlib
|
import pathlib
|
||||||
import shutil
|
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
@ -34,16 +33,13 @@ class BaseBootConfigurator(ABC):
|
|||||||
self,
|
self,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
apt_state: AptStateManager,
|
apt_state: AptStateManager,
|
||||||
|
workdir: pathlib.Path,
|
||||||
iso_root: pathlib.Path,
|
iso_root: pathlib.Path,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
self.apt_state = apt_state
|
self.apt_state = apt_state
|
||||||
self.iso_root = iso_root
|
|
||||||
|
|
||||||
def create_dirs(self, workdir):
|
|
||||||
self.scratch = workdir.joinpath("boot-stuff")
|
self.scratch = workdir.joinpath("boot-stuff")
|
||||||
self.scratch.mkdir(exist_ok=True)
|
self.iso_root = iso_root
|
||||||
self.boot_tree = self.scratch.joinpath("cd-boot-tree")
|
|
||||||
|
|
||||||
def download_and_extract_package(
|
def download_and_extract_package(
|
||||||
self, pkg_name: str, target_dir: pathlib.Path
|
self, pkg_name: str, target_dir: pathlib.Path
|
||||||
@ -65,14 +61,6 @@ class BaseBootConfigurator(ABC):
|
|||||||
dpkg_proc.stdout.close()
|
dpkg_proc.stdout.close()
|
||||||
tar_proc.communicate()
|
tar_proc.communicate()
|
||||||
|
|
||||||
def copy_grub_modules(
|
|
||||||
self, src_dir: pathlib.Path, dest_dir: pathlib.Path, extensions: list[str]
|
|
||||||
) -> None:
|
|
||||||
"""Copy GRUB module files matching given extensions from src to dest."""
|
|
||||||
for ext in extensions:
|
|
||||||
for file in src_dir.glob(ext):
|
|
||||||
shutil.copy(file, dest_dir)
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def extract_files(self) -> None:
|
def extract_files(self) -> None:
|
||||||
"""Download and extract bootloader packages to the boot tree.
|
"""Download and extract bootloader packages to the boot tree.
|
||||||
@ -95,7 +83,6 @@ class BaseBootConfigurator(ABC):
|
|||||||
|
|
||||||
def make_bootable(
|
def make_bootable(
|
||||||
self,
|
self,
|
||||||
workdir: pathlib.Path,
|
|
||||||
project: str,
|
project: str,
|
||||||
capproject: str,
|
capproject: str,
|
||||||
subarch: str,
|
subarch: str,
|
||||||
@ -106,6 +93,6 @@ class BaseBootConfigurator(ABC):
|
|||||||
self.humanproject = capproject.replace("-", " ")
|
self.humanproject = capproject.replace("-", " ")
|
||||||
self.subarch = subarch
|
self.subarch = subarch
|
||||||
self.hwe = hwe
|
self.hwe = hwe
|
||||||
self.create_dirs(workdir)
|
self.scratch.mkdir(exist_ok=True)
|
||||||
with self.logger.logged("configuring boot"):
|
with self.logger.logged("configuring boot"):
|
||||||
self.extract_files()
|
self.extract_files()
|
||||||
|
|||||||
@ -7,17 +7,31 @@ from abc import abstractmethod
|
|||||||
from .base import BaseBootConfigurator
|
from .base import BaseBootConfigurator
|
||||||
|
|
||||||
|
|
||||||
def copy_grub_common_files_to_boot_tree(
|
def copy_grub_common_files(grub_pkg_dir: pathlib.Path, iso_root: pathlib.Path) -> None:
|
||||||
grub_dir: pathlib.Path, boot_tree: pathlib.Path
|
fonts_dir = iso_root.joinpath("boot", "grub", "fonts")
|
||||||
) -> None:
|
|
||||||
fonts_dir = boot_tree.joinpath("boot", "grub", "fonts")
|
|
||||||
fonts_dir.mkdir(parents=True, exist_ok=True)
|
fonts_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
src = grub_dir.joinpath("usr", "share", "grub", "unicode.pf2")
|
src = grub_pkg_dir.joinpath("usr", "share", "grub", "unicode.pf2")
|
||||||
dst = fonts_dir.joinpath("unicode.pf2")
|
dst = fonts_dir.joinpath("unicode.pf2")
|
||||||
shutil.copy(src, dst)
|
shutil.copy(src, dst)
|
||||||
|
|
||||||
|
|
||||||
|
def copy_grub_modules(
|
||||||
|
grub_pkg_dir: pathlib.Path,
|
||||||
|
iso_root: pathlib.Path,
|
||||||
|
grub_target: str,
|
||||||
|
patterns: list[str],
|
||||||
|
) -> None:
|
||||||
|
"""Copy GRUB module files matching given patterns from src to dest."""
|
||||||
|
src_dir = grub_pkg_dir.joinpath("usr", "lib", "grub", grub_target)
|
||||||
|
dest_dir = iso_root.joinpath("boot", "grub", grub_target)
|
||||||
|
dest_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
for pat in patterns:
|
||||||
|
for file in src_dir.glob(pat):
|
||||||
|
shutil.copy(file, dest_dir)
|
||||||
|
|
||||||
|
|
||||||
class GrubBootConfigurator(BaseBootConfigurator):
|
class GrubBootConfigurator(BaseBootConfigurator):
|
||||||
"""Base class for architectures that use GRUB (all except S390X).
|
"""Base class for architectures that use GRUB (all except S390X).
|
||||||
|
|
||||||
@ -25,79 +39,66 @@ class GrubBootConfigurator(BaseBootConfigurator):
|
|||||||
Subclasses must implement generate_grub_config().
|
Subclasses must implement generate_grub_config().
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def create_dirs(self, workdir):
|
def grub_header(self, include_loadfont: bool = True) -> str:
|
||||||
super().create_dirs(workdir)
|
"""Return common GRUB config header (timeout, colors).
|
||||||
self.grub_dir = self.boot_tree.joinpath("grub")
|
|
||||||
|
|
||||||
def setup_grub_common_files(self) -> None:
|
|
||||||
"""Copy common GRUB files (fonts, etc.) to boot tree."""
|
|
||||||
copy_grub_common_files_to_boot_tree(self.grub_dir, self.boot_tree)
|
|
||||||
|
|
||||||
def write_grub_header(
|
|
||||||
self, grub_cfg: pathlib.Path, include_loadfont: bool = True
|
|
||||||
) -> None:
|
|
||||||
"""Write common GRUB config header (timeout, colors).
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
grub_cfg: Path to grub.cfg file
|
|
||||||
include_loadfont: Whether to include 'loadfont unicode'
|
include_loadfont: Whether to include 'loadfont unicode'
|
||||||
(not needed for RISC-V)
|
(not needed for RISC-V)
|
||||||
"""
|
"""
|
||||||
with grub_cfg.open("a") as f:
|
result = "set timeout=30\n\n"
|
||||||
f.write("set timeout=30\n\n")
|
if include_loadfont:
|
||||||
if include_loadfont:
|
result += "loadfont unicode\n\n"
|
||||||
f.write("loadfont unicode\n\n")
|
result += """\
|
||||||
f.write(
|
set menu_color_normal=white/black
|
||||||
"""set menu_color_normal=white/black
|
|
||||||
set menu_color_highlight=black/light-gray
|
set menu_color_highlight=black/light-gray
|
||||||
|
|
||||||
"""
|
"""
|
||||||
)
|
return result
|
||||||
|
|
||||||
def write_hwe_menu_entry(
|
def hwe_menu_entry(
|
||||||
self,
|
self,
|
||||||
grub_cfg: pathlib.Path,
|
|
||||||
kernel_name: str,
|
kernel_name: str,
|
||||||
kernel_params: str,
|
kernel_params: str,
|
||||||
extra_params: str = "",
|
extra_params: str = "",
|
||||||
) -> None:
|
) -> str:
|
||||||
"""Write HWE kernel menu entry if HWE is enabled.
|
"""Return HWE kernel menu entry if HWE is enabled.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
grub_cfg: Path to grub.cfg file
|
|
||||||
kernel_name: Kernel binary name (vmlinuz or vmlinux)
|
kernel_name: Kernel binary name (vmlinuz or vmlinux)
|
||||||
kernel_params: Kernel parameters to append
|
kernel_params: Kernel parameters to append
|
||||||
extra_params: Additional parameters (e.g., console=tty0, $cmdline)
|
extra_params: Additional parameters (e.g., console=tty0, $cmdline)
|
||||||
"""
|
"""
|
||||||
if self.hwe:
|
if not self.hwe:
|
||||||
with grub_cfg.open("a") as f:
|
return ""
|
||||||
f.write(
|
return f"""\
|
||||||
f"""menuentry "{self.humanproject} with the HWE kernel" {{
|
menuentry "{self.humanproject} with the HWE kernel" {{
|
||||||
\tset gfxpayload=keep
|
set gfxpayload=keep
|
||||||
\tlinux\t/casper/hwe-{kernel_name} {extra_params}{kernel_params}
|
linux /casper/hwe-{kernel_name} {extra_params}{kernel_params}
|
||||||
\tinitrd\t/casper/hwe-initrd
|
initrd /casper/hwe-initrd
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
)
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def generate_grub_config(self) -> None:
|
def generate_grub_config(self) -> str:
|
||||||
"""Generate grub.cfg configuration file.
|
"""Generate grub.cfg content.
|
||||||
|
|
||||||
Each GRUB-based architecture must implement this to create its
|
Each GRUB-based architecture must implement this to return the
|
||||||
specific GRUB configuration.
|
GRUB configuration.
|
||||||
"""
|
"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def make_bootable(
|
def make_bootable(
|
||||||
self,
|
self,
|
||||||
workdir: pathlib.Path,
|
|
||||||
project: str,
|
project: str,
|
||||||
capproject: str,
|
capproject: str,
|
||||||
subarch: str,
|
subarch: str,
|
||||||
hwe: bool,
|
hwe: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Make the ISO bootable by extracting files and generating GRUB config."""
|
"""Make the ISO bootable by extracting files and generating GRUB config."""
|
||||||
super().make_bootable(workdir, project, capproject, subarch, hwe)
|
super().make_bootable(project, capproject, subarch, hwe)
|
||||||
with self.logger.logged("generating grub config"):
|
with self.logger.logged("generating grub config"):
|
||||||
self.generate_grub_config()
|
content = self.generate_grub_config()
|
||||||
|
grub_dir = self.iso_root.joinpath("boot", "grub")
|
||||||
|
grub_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
grub_dir.joinpath("grub.cfg").write_text(content)
|
||||||
|
|||||||
@ -3,7 +3,11 @@
|
|||||||
import pathlib
|
import pathlib
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from .grub import GrubBootConfigurator
|
from .grub import (
|
||||||
|
copy_grub_common_files,
|
||||||
|
copy_grub_modules,
|
||||||
|
GrubBootConfigurator,
|
||||||
|
)
|
||||||
from .base import default_kernel_params
|
from .base import default_kernel_params
|
||||||
|
|
||||||
|
|
||||||
@ -12,28 +16,26 @@ class PPC64ELBootConfigurator(GrubBootConfigurator):
|
|||||||
|
|
||||||
def mkisofs_opts(self) -> list[str | pathlib.Path]:
|
def mkisofs_opts(self) -> list[str | pathlib.Path]:
|
||||||
"""Return mkisofs options for PPC64EL."""
|
"""Return mkisofs options for PPC64EL."""
|
||||||
# Add cd-boot-tree to the ISO
|
return []
|
||||||
return [self.boot_tree]
|
|
||||||
|
|
||||||
def extract_files(self) -> None:
|
def extract_files(self) -> None:
|
||||||
"""Download and extract bootloader packages for PPC64EL."""
|
"""Download and extract bootloader packages for PPC64EL."""
|
||||||
self.logger.log("extracting PPC64EL boot files")
|
self.logger.log("extracting PPC64EL boot files")
|
||||||
|
|
||||||
|
grub_pkg_dir = self.scratch.joinpath("grub-pkg")
|
||||||
|
|
||||||
# Download and extract bootloader packages
|
# Download and extract bootloader packages
|
||||||
self.download_and_extract_package("grub2-common", self.grub_dir)
|
self.download_and_extract_package("grub2-common", grub_pkg_dir)
|
||||||
self.download_and_extract_package("grub-ieee1275-bin", self.grub_dir)
|
self.download_and_extract_package("grub-ieee1275-bin", grub_pkg_dir)
|
||||||
|
|
||||||
# Add common files for GRUB to tree
|
# Add common files for GRUB to tree
|
||||||
self.setup_grub_common_files()
|
copy_grub_common_files(grub_pkg_dir, self.iso_root)
|
||||||
|
|
||||||
# Add IEEE1275 ppc boot files
|
# Add IEEE1275 ppc boot files
|
||||||
ppc_dir = self.boot_tree.joinpath("ppc")
|
ppc_dir = self.iso_root.joinpath("ppc")
|
||||||
ppc_dir.mkdir(parents=True, exist_ok=True)
|
ppc_dir.mkdir()
|
||||||
|
|
||||||
grub_boot_dir = self.boot_tree.joinpath("boot", "grub", "powerpc-ieee1275")
|
src_grub_dir = grub_pkg_dir.joinpath("usr", "lib", "grub", "powerpc-ieee1275")
|
||||||
grub_boot_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
src_grub_dir = self.grub_dir.joinpath("usr", "lib", "grub", "powerpc-ieee1275")
|
|
||||||
|
|
||||||
# Copy bootinfo.txt to ppc directory
|
# Copy bootinfo.txt to ppc directory
|
||||||
shutil.copy(
|
shutil.copy(
|
||||||
@ -43,33 +45,30 @@ class PPC64ELBootConfigurator(GrubBootConfigurator):
|
|||||||
# Copy eltorito.elf to boot/grub as powerpc.elf
|
# Copy eltorito.elf to boot/grub as powerpc.elf
|
||||||
shutil.copy(
|
shutil.copy(
|
||||||
src_grub_dir.joinpath("eltorito.elf"),
|
src_grub_dir.joinpath("eltorito.elf"),
|
||||||
self.boot_tree.joinpath("boot", "grub", "powerpc.elf"),
|
self.iso_root.joinpath("boot", "grub", "powerpc.elf"),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Copy GRUB modules
|
# Copy GRUB modules
|
||||||
self.copy_grub_modules(src_grub_dir, grub_boot_dir, ["*.mod", "*.lst"])
|
copy_grub_modules(
|
||||||
|
grub_pkg_dir, self.iso_root, "powerpc-ieee1275", ["*.mod", "*.lst"]
|
||||||
|
)
|
||||||
|
|
||||||
def generate_grub_config(self) -> None:
|
def generate_grub_config(self) -> str:
|
||||||
"""Generate grub.cfg for PPC64EL."""
|
"""Generate grub.cfg for PPC64EL."""
|
||||||
kernel_params = default_kernel_params(self.project)
|
kernel_params = default_kernel_params(self.project)
|
||||||
|
|
||||||
grub_cfg = self.grub_dir.joinpath("grub.cfg")
|
result = self.grub_header()
|
||||||
|
|
||||||
# Write common GRUB header
|
|
||||||
self.write_grub_header(grub_cfg)
|
|
||||||
|
|
||||||
# Main menu entry
|
# Main menu entry
|
||||||
with grub_cfg.open("a") as f:
|
result += f"""\
|
||||||
f.write(
|
menuentry "Try or Install {self.humanproject}" {{
|
||||||
f"""menuentry "Try or Install {self.humanproject}" {{
|
set gfxpayload=keep
|
||||||
\tset gfxpayload=keep
|
linux /casper/vmlinux quiet {kernel_params}
|
||||||
\tlinux\t/casper/vmlinux quiet {kernel_params}
|
initrd /casper/initrd
|
||||||
\tinitrd\t/casper/initrd
|
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
)
|
|
||||||
|
|
||||||
# HWE kernel option if available
|
# HWE kernel option if available
|
||||||
self.write_hwe_menu_entry(
|
result += self.hwe_menu_entry("vmlinux", kernel_params, extra_params="quiet ")
|
||||||
grub_cfg, "vmlinux", kernel_params, extra_params="quiet "
|
|
||||||
)
|
return result
|
||||||
|
|||||||
@ -3,35 +3,31 @@
|
|||||||
import pathlib
|
import pathlib
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from .grub import GrubBootConfigurator
|
from .grub import GrubBootConfigurator, copy_grub_common_files, copy_grub_modules
|
||||||
|
|
||||||
|
|
||||||
def copy_unsigned_monolithic_grub_to_boot_tree(
|
def copy_unsigned_monolithic_grub(
|
||||||
grub_dir: pathlib.Path, efi_suffix: str, grub_target: str, boot_tree: pathlib.Path
|
grub_pkg_dir: pathlib.Path,
|
||||||
|
efi_suffix: str,
|
||||||
|
grub_target: str,
|
||||||
|
iso_root: pathlib.Path,
|
||||||
) -> None:
|
) -> None:
|
||||||
efi_boot_dir = boot_tree.joinpath("EFI", "boot")
|
efi_boot_dir = iso_root.joinpath("EFI", "boot")
|
||||||
efi_boot_dir.mkdir(parents=True, exist_ok=True)
|
efi_boot_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
shutil.copy(
|
shutil.copy(
|
||||||
grub_dir.joinpath(
|
grub_pkg_dir.joinpath(
|
||||||
"usr",
|
"usr",
|
||||||
"lib",
|
"lib",
|
||||||
"grub",
|
"grub",
|
||||||
f"{grub_target}-efi",
|
grub_target,
|
||||||
"monolithic",
|
"monolithic",
|
||||||
f"gcd{efi_suffix}.efi",
|
f"gcd{efi_suffix}.efi",
|
||||||
),
|
),
|
||||||
efi_boot_dir.joinpath(f"boot{efi_suffix}.efi"),
|
efi_boot_dir.joinpath(f"boot{efi_suffix}.efi"),
|
||||||
)
|
)
|
||||||
|
|
||||||
grub_boot_dir = boot_tree.joinpath("boot", "grub", f"{grub_target}-efi")
|
copy_grub_modules(grub_pkg_dir, iso_root, grub_target, ["*.mod", "*.lst"])
|
||||||
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):
|
class RISCV64BootConfigurator(GrubBootConfigurator):
|
||||||
@ -74,16 +70,19 @@ class RISCV64BootConfigurator(GrubBootConfigurator):
|
|||||||
self.logger.log("extracting RISC-V64 boot files")
|
self.logger.log("extracting RISC-V64 boot files")
|
||||||
u_boot_dir = self.scratch.joinpath("u-boot-sifive")
|
u_boot_dir = self.scratch.joinpath("u-boot-sifive")
|
||||||
|
|
||||||
|
grub_pkg_dir = self.scratch.joinpath("grub-pkg")
|
||||||
|
|
||||||
# Download and extract bootloader packages
|
# Download and extract bootloader packages
|
||||||
self.download_and_extract_package("grub2-common", self.grub_dir)
|
self.download_and_extract_package("grub2-common", grub_pkg_dir)
|
||||||
self.download_and_extract_package("grub-efi-riscv64-bin", self.grub_dir)
|
self.download_and_extract_package("grub-efi-riscv64-bin", grub_pkg_dir)
|
||||||
self.download_and_extract_package("grub-efi-riscv64-unsigned", self.grub_dir)
|
self.download_and_extract_package("grub-efi-riscv64-unsigned", grub_pkg_dir)
|
||||||
self.download_and_extract_package("u-boot-sifive", u_boot_dir)
|
self.download_and_extract_package("u-boot-sifive", u_boot_dir)
|
||||||
|
|
||||||
# Add GRUB to tree
|
# Add GRUB to tree
|
||||||
self.setup_grub_common_files()
|
copy_grub_common_files(grub_pkg_dir, self.iso_root)
|
||||||
copy_unsigned_monolithic_grub_to_boot_tree(
|
|
||||||
self.grub_dir, "riscv64", "riscv64", self.boot_tree
|
copy_unsigned_monolithic_grub(
|
||||||
|
grub_pkg_dir, "riscv64", "riscv64-efi", self.iso_root
|
||||||
)
|
)
|
||||||
|
|
||||||
# Extract DTBs to tree
|
# Extract DTBs to tree
|
||||||
@ -107,22 +106,14 @@ class RISCV64BootConfigurator(GrubBootConfigurator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Copy DTBs if they exist
|
# Copy DTBs if they exist
|
||||||
dtb_dir = self.boot_tree.joinpath("dtb")
|
dtb_dir = self.iso_root.joinpath("dtb")
|
||||||
dtb_dir.mkdir(parents=True, exist_ok=True)
|
dtb_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
firmware_dir = kernel_layer.joinpath("usr", "lib", "firmware")
|
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 firmware_dir.glob("*/device-tree/*"):
|
||||||
for dtb_file in device_tree_files:
|
if dtb_file.is_file():
|
||||||
if dtb_file.is_file():
|
shutil.copy(dtb_file, dtb_dir)
|
||||||
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
|
# Create ESP image with GRUB and dtbs
|
||||||
efi_img = self.scratch.joinpath("efi.img")
|
efi_img = self.scratch.joinpath("efi.img")
|
||||||
@ -131,41 +122,34 @@ class RISCV64BootConfigurator(GrubBootConfigurator):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Add EFI files to ESP
|
# Add EFI files to ESP
|
||||||
efi_dir = self.boot_tree.joinpath("EFI")
|
efi_dir = self.iso_root.joinpath("EFI")
|
||||||
self.logger.run(["mcopy", "-s", "-i", efi_img, efi_dir, "::/."], check=True)
|
self.logger.run(["mcopy", "-s", "-i", efi_img, efi_dir, "::/."], check=True)
|
||||||
|
|
||||||
# Add DTBs to ESP
|
# Add DTBs to ESP
|
||||||
self.logger.run(["mcopy", "-s", "-i", efi_img, dtb_dir, "::/."], check=True)
|
self.logger.run(["mcopy", "-s", "-i", efi_img, dtb_dir, "::/."], check=True)
|
||||||
|
|
||||||
def generate_grub_config(self) -> None:
|
def generate_grub_config(self) -> str:
|
||||||
"""Generate grub.cfg for RISC-V64."""
|
"""Generate grub.cfg for RISC-V64."""
|
||||||
grub_dir = self.iso_root.joinpath("boot", "grub")
|
result = self.grub_header(include_loadfont=False)
|
||||||
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
|
# Main menu entry
|
||||||
with grub_cfg.open("a") as f:
|
result += f"""\
|
||||||
f.write(
|
menuentry "Try or Install {self.humanproject}" {{
|
||||||
f"""menuentry "Try or Install {self.humanproject}" {{
|
set gfxpayload=keep
|
||||||
\tset gfxpayload=keep
|
linux /casper/vmlinux efi=debug sysctl.kernel.watchdog_thresh=60 ---
|
||||||
\tlinux\t/casper/vmlinux efi=debug sysctl.kernel.watchdog_thresh=60 ---
|
initrd /casper/initrd
|
||||||
\tinitrd\t/casper/initrd
|
|
||||||
}}
|
}}
|
||||||
"""
|
"""
|
||||||
)
|
|
||||||
|
|
||||||
# HWE kernel option if available
|
# HWE kernel option if available
|
||||||
self.write_hwe_menu_entry(
|
result += self.hwe_menu_entry(
|
||||||
grub_cfg,
|
|
||||||
"vmlinux",
|
"vmlinux",
|
||||||
"---",
|
"---",
|
||||||
extra_params="efi=debug sysctl.kernel.watchdog_thresh=60 ",
|
extra_params="efi=debug sysctl.kernel.watchdog_thresh=60 ",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def post_process_iso(self, iso_path: pathlib.Path) -> None:
|
def post_process_iso(self, iso_path: pathlib.Path) -> None:
|
||||||
"""Add GPT partitions with U-Boot for SiFive Unmatched board.
|
"""Add GPT partitions with U-Boot for SiFive Unmatched board.
|
||||||
|
|
||||||
|
|||||||
@ -4,29 +4,31 @@ import pathlib
|
|||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from ..builder import Logger
|
from ..builder import Logger
|
||||||
from .grub import GrubBootConfigurator
|
from .grub import copy_grub_common_files, GrubBootConfigurator
|
||||||
|
|
||||||
|
|
||||||
def copy_signed_shim_grub_to_boot_tree(
|
def copy_signed_shim_grub(
|
||||||
shim_dir: pathlib.Path,
|
shim_pkg_dir: pathlib.Path,
|
||||||
grub_dir: pathlib.Path,
|
grub_pkg_dir: pathlib.Path,
|
||||||
efi_suffix: str,
|
efi_suffix: str,
|
||||||
grub_target: str,
|
grub_target: str,
|
||||||
boot_tree: pathlib.Path,
|
iso_root: pathlib.Path,
|
||||||
) -> None:
|
) -> None:
|
||||||
efi_boot_dir = boot_tree.joinpath("EFI", "boot")
|
efi_boot_dir = iso_root.joinpath("EFI", "boot")
|
||||||
efi_boot_dir.mkdir(parents=True, exist_ok=True)
|
efi_boot_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
shutil.copy(
|
shutil.copy(
|
||||||
shim_dir.joinpath("usr", "lib", "shim", f"shim{efi_suffix}.efi.signed.latest"),
|
shim_pkg_dir.joinpath(
|
||||||
|
"usr", "lib", "shim", f"shim{efi_suffix}.efi.signed.latest"
|
||||||
|
),
|
||||||
efi_boot_dir.joinpath(f"boot{efi_suffix}.efi"),
|
efi_boot_dir.joinpath(f"boot{efi_suffix}.efi"),
|
||||||
)
|
)
|
||||||
shutil.copy(
|
shutil.copy(
|
||||||
shim_dir.joinpath("usr", "lib", "shim", f"mm{efi_suffix}.efi"),
|
shim_pkg_dir.joinpath("usr", "lib", "shim", f"mm{efi_suffix}.efi"),
|
||||||
efi_boot_dir.joinpath(f"mm{efi_suffix}.efi"),
|
efi_boot_dir.joinpath(f"mm{efi_suffix}.efi"),
|
||||||
)
|
)
|
||||||
shutil.copy(
|
shutil.copy(
|
||||||
grub_dir.joinpath(
|
grub_pkg_dir.joinpath(
|
||||||
"usr",
|
"usr",
|
||||||
"lib",
|
"lib",
|
||||||
"grub",
|
"grub",
|
||||||
@ -36,10 +38,10 @@ def copy_signed_shim_grub_to_boot_tree(
|
|||||||
efi_boot_dir.joinpath(f"grub{efi_suffix}.efi"),
|
efi_boot_dir.joinpath(f"grub{efi_suffix}.efi"),
|
||||||
)
|
)
|
||||||
|
|
||||||
grub_boot_dir = boot_tree.joinpath("boot", "grub", f"{grub_target}-efi")
|
grub_boot_dir = iso_root.joinpath("boot", "grub", f"{grub_target}-efi")
|
||||||
grub_boot_dir.mkdir(parents=True, exist_ok=True)
|
grub_boot_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
src_grub_dir = grub_dir.joinpath("usr", "lib", "grub", f"{grub_target}-efi")
|
src_grub_dir = grub_pkg_dir.joinpath("usr", "lib", "grub", f"{grub_target}-efi")
|
||||||
for mod_file in src_grub_dir.glob("*.mod"):
|
for mod_file in src_grub_dir.glob("*.mod"):
|
||||||
shutil.copy(mod_file, grub_boot_dir)
|
shutil.copy(mod_file, grub_boot_dir)
|
||||||
for lst_file in src_grub_dir.glob("*.lst"):
|
for lst_file in src_grub_dir.glob("*.lst"):
|
||||||
@ -47,10 +49,10 @@ def copy_signed_shim_grub_to_boot_tree(
|
|||||||
|
|
||||||
|
|
||||||
def create_eltorito_esp_image(
|
def create_eltorito_esp_image(
|
||||||
logger: Logger, boot_tree: pathlib.Path, target_file: pathlib.Path
|
logger: Logger, iso_root: pathlib.Path, target_file: pathlib.Path
|
||||||
) -> None:
|
) -> None:
|
||||||
logger.log("creating El Torito ESP image")
|
logger.log("creating El Torito ESP image")
|
||||||
efi_dir = boot_tree.joinpath("EFI")
|
efi_dir = iso_root.joinpath("EFI")
|
||||||
|
|
||||||
# Calculate size: du -s --apparent-size --block-size=1024 + 1024
|
# Calculate size: du -s --apparent-size --block-size=1024 + 1024
|
||||||
result = logger.run(
|
result = logger.run(
|
||||||
@ -84,10 +86,6 @@ class UEFIBootConfigurator(GrubBootConfigurator):
|
|||||||
grub_target: str = ""
|
grub_target: str = ""
|
||||||
arch: str = ""
|
arch: str = ""
|
||||||
|
|
||||||
def create_dirs(self, workdir):
|
|
||||||
super().create_dirs(workdir)
|
|
||||||
self.shim_dir = self.boot_tree.joinpath("shim")
|
|
||||||
|
|
||||||
def get_uefi_grub_packages(self) -> list[str]:
|
def get_uefi_grub_packages(self) -> list[str]:
|
||||||
"""Return list of UEFI GRUB packages to download."""
|
"""Return list of UEFI GRUB packages to download."""
|
||||||
return [
|
return [
|
||||||
@ -98,40 +96,42 @@ class UEFIBootConfigurator(GrubBootConfigurator):
|
|||||||
|
|
||||||
def extract_uefi_files(self) -> None:
|
def extract_uefi_files(self) -> None:
|
||||||
"""Extract common UEFI files to boot tree."""
|
"""Extract common UEFI files to boot tree."""
|
||||||
|
|
||||||
|
shim_pkg_dir = self.scratch.joinpath("shim-pkg")
|
||||||
|
grub_pkg_dir = self.scratch.joinpath("grub-pkg")
|
||||||
|
|
||||||
# Download UEFI packages
|
# Download UEFI packages
|
||||||
self.download_and_extract_package("shim-signed", self.shim_dir)
|
self.download_and_extract_package("shim-signed", shim_pkg_dir)
|
||||||
for pkg in self.get_uefi_grub_packages():
|
for pkg in self.get_uefi_grub_packages():
|
||||||
self.download_and_extract_package(pkg, self.grub_dir)
|
self.download_and_extract_package(pkg, grub_pkg_dir)
|
||||||
|
|
||||||
# Add common files for GRUB to tree
|
# Add common files for GRUB to tree
|
||||||
self.setup_grub_common_files()
|
copy_grub_common_files(grub_pkg_dir, self.iso_root)
|
||||||
|
|
||||||
# Add EFI GRUB to tree
|
# Add EFI GRUB to tree
|
||||||
copy_signed_shim_grub_to_boot_tree(
|
copy_signed_shim_grub(
|
||||||
self.shim_dir,
|
shim_pkg_dir,
|
||||||
self.grub_dir,
|
grub_pkg_dir,
|
||||||
self.efi_suffix,
|
self.efi_suffix,
|
||||||
self.grub_target,
|
self.grub_target,
|
||||||
self.boot_tree,
|
self.iso_root,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create ESP image for El-Torito catalog and hybrid boot
|
# Create ESP image for El-Torito catalog and hybrid boot
|
||||||
create_eltorito_esp_image(
|
create_eltorito_esp_image(
|
||||||
self.logger, self.boot_tree, self.scratch.joinpath("cd-boot-efi.img")
|
self.logger, self.iso_root, self.scratch.joinpath("cd-boot-efi.img")
|
||||||
)
|
)
|
||||||
|
|
||||||
def write_uefi_menu_entries(self, grub_cfg: pathlib.Path) -> None:
|
def uefi_menu_entries(self) -> str:
|
||||||
"""Write UEFI firmware menu entries."""
|
"""Return UEFI firmware menu entries."""
|
||||||
with grub_cfg.open("a") as f:
|
return """\
|
||||||
f.write(
|
menuentry 'Boot from next volume' {
|
||||||
"""menuentry 'Boot from next volume' {
|
exit 1
|
||||||
\texit 1
|
|
||||||
}
|
}
|
||||||
menuentry 'UEFI Firmware Settings' {
|
menuentry 'UEFI Firmware Settings' {
|
||||||
\tfwsetup
|
fwsetup
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
)
|
|
||||||
|
|
||||||
def get_uefi_mkisofs_opts(self) -> list[str | pathlib.Path]:
|
def get_uefi_mkisofs_opts(self) -> list[str | pathlib.Path]:
|
||||||
"""Return common UEFI mkisofs options."""
|
"""Return common UEFI mkisofs options."""
|
||||||
|
|||||||
@ -268,7 +268,7 @@ class ISOBuilder:
|
|||||||
target.hardlink_to(src)
|
target.hardlink_to(src)
|
||||||
|
|
||||||
kernel_name = "vmlinuz"
|
kernel_name = "vmlinuz"
|
||||||
if self.arch == "ppc64el":
|
if self.arch in ("ppc64el", "riscv64"):
|
||||||
kernel_name = "vmlinux"
|
kernel_name = "vmlinux"
|
||||||
|
|
||||||
with self.logger.logged(
|
with self.logger.logged(
|
||||||
@ -278,19 +278,18 @@ class ISOBuilder:
|
|||||||
for path in artifact_dir.glob(f"{filename_prefix}*.{ext}"):
|
for path in artifact_dir.glob(f"{filename_prefix}*.{ext}"):
|
||||||
newname = path.name[len(filename_prefix) :]
|
newname = path.name[len(filename_prefix) :]
|
||||||
link(path, newname)
|
link(path, newname)
|
||||||
for suffix, prefix in (
|
|
||||||
("-generic", ""),
|
for kernel_path in artifact_dir.glob(f"{filename_prefix}kernel*"):
|
||||||
("-generic-hwe", "hwe-"),
|
suffix = kernel_path.name[len(filename_prefix) + len("kernel") :]
|
||||||
):
|
prefix = "hwe-" if suffix.endswith("-hwe") else ""
|
||||||
if artifact_dir.joinpath(f"{filename_prefix}kernel{suffix}").exists():
|
link(
|
||||||
link(
|
artifact_dir.joinpath(f"{filename_prefix}kernel{suffix}"),
|
||||||
artifact_dir.joinpath(f"{filename_prefix}kernel{suffix}"),
|
f"{prefix}{kernel_name}",
|
||||||
f"{prefix}{kernel_name}",
|
)
|
||||||
)
|
link(
|
||||||
link(
|
artifact_dir.joinpath(f"{filename_prefix}initrd{suffix}"),
|
||||||
artifact_dir.joinpath(f"{filename_prefix}initrd{suffix}"),
|
f"{prefix}initrd",
|
||||||
f"{prefix}initrd",
|
)
|
||||||
)
|
|
||||||
self._extract_casper_uuids()
|
self._extract_casper_uuids()
|
||||||
|
|
||||||
def make_bootable(self, project: str, capproject: str, subarch: str):
|
def make_bootable(self, project: str, capproject: str, subarch: str):
|
||||||
@ -298,10 +297,10 @@ class ISOBuilder:
|
|||||||
self.arch,
|
self.arch,
|
||||||
self.logger,
|
self.logger,
|
||||||
self.apt_state,
|
self.apt_state,
|
||||||
|
self.workdir,
|
||||||
self.iso_root,
|
self.iso_root,
|
||||||
)
|
)
|
||||||
configurator.make_bootable(
|
configurator.make_bootable(
|
||||||
self.workdir,
|
|
||||||
project,
|
project,
|
||||||
capproject,
|
capproject,
|
||||||
subarch,
|
subarch,
|
||||||
@ -341,9 +340,9 @@ class ISOBuilder:
|
|||||||
self.arch,
|
self.arch,
|
||||||
self.logger,
|
self.logger,
|
||||||
self.apt_state,
|
self.apt_state,
|
||||||
|
self.workdir,
|
||||||
self.iso_root,
|
self.iso_root,
|
||||||
)
|
)
|
||||||
configurator.create_dirs(self.workdir)
|
|
||||||
mkisofs_opts = configurator.mkisofs_opts()
|
mkisofs_opts = configurator.mkisofs_opts()
|
||||||
cmd: list[str | pathlib.Path] = ["xorriso"]
|
cmd: list[str | pathlib.Path] = ["xorriso"]
|
||||||
if self.arch == "riscv64":
|
if self.arch == "riscv64":
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# create the system seed for TPM-backed FDE in the live layer of the installer.
|
# create the system seed for TPM-backed FDE in the live layer of the installer.
|
||||||
|
|
||||||
set -eux
|
set -eu
|
||||||
|
|
||||||
case ${PASS:-} in
|
case ${PASS:-} in
|
||||||
*.live)
|
*.live)
|
||||||
@ -13,8 +13,15 @@ case ${PASS:-} in
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
. config/binary
|
. config/binary
|
||||||
|
. config/common
|
||||||
. config/functions
|
. config/functions
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
if ! echo $PASSES | grep --quiet enhanced-secureboot; then
|
||||||
|
# Only run this hook if there is going to be a layer that installs it...
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
# Naive conversion from YAML to JSON. This is needed because yq is in universe
|
# Naive conversion from YAML to JSON. This is needed because yq is in universe
|
||||||
# (but jq is not).
|
# (but jq is not).
|
||||||
@ -126,8 +133,25 @@ get_components()
|
|||||||
|
|
||||||
# env SNAPPY_STORE_NO_CDN=1 snap known --remote model series=16 brand-id=canonical model=ubuntu-classic-2410-amd64 > config/classic-model.model
|
# env SNAPPY_STORE_NO_CDN=1 snap known --remote model series=16 brand-id=canonical model=ubuntu-classic-2410-amd64 > config/classic-model.model
|
||||||
#
|
#
|
||||||
dangerous_model=/usr/share/livecd-rootfs/live-build/${PROJECT}/ubuntu-classic-amd64-dangerous.model
|
|
||||||
stable_model=/usr/share/livecd-rootfs/live-build/${PROJECT}/ubuntu-classic-amd64.model
|
# We used to have the models included in livecd-rootfs itself, but now we pull
|
||||||
|
# them from the Launchpad git mirror.
|
||||||
|
canonical_models_tree=$(mktemp -d)
|
||||||
|
git clone --depth 1 https://git.launchpad.net/canonical-models -- "${canonical_models_tree}"
|
||||||
|
|
||||||
|
cleanup_repo()
|
||||||
|
{
|
||||||
|
rm -rf -- "${canonical_models_tree}"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup_repo EXIT
|
||||||
|
|
||||||
|
echo 'Checked out canonical-models revision' "$(git -C "${canonical_models_tree}" rev-parse HEAD)"
|
||||||
|
|
||||||
|
model_version=$(release_ver | sed 's/\.//')
|
||||||
|
|
||||||
|
dangerous_model="${canonical_models_tree}"/ubuntu-classic-"${model_version}"-amd64-dangerous.model
|
||||||
|
stable_model="${canonical_models_tree}"/ubuntu-classic-"${model_version}"-amd64.model
|
||||||
|
|
||||||
prepare_args=()
|
prepare_args=()
|
||||||
|
|
||||||
|
|||||||
@ -1,109 +0,0 @@
|
|||||||
type: model
|
|
||||||
authority-id: canonical
|
|
||||||
series: 16
|
|
||||||
brand-id: canonical
|
|
||||||
model: ubuntu-classic-2604-amd64-dangerous
|
|
||||||
architecture: amd64
|
|
||||||
base: core24
|
|
||||||
classic: true
|
|
||||||
distribution: ubuntu
|
|
||||||
grade: dangerous
|
|
||||||
snaps:
|
|
||||||
-
|
|
||||||
default-channel: classic-26.04/edge
|
|
||||||
id: UqFziVZDHLSyO3TqSWgNBoAdHbLI4dAH
|
|
||||||
name: pc
|
|
||||||
type: gadget
|
|
||||||
-
|
|
||||||
components:
|
|
||||||
nvidia-580-uda-ko:
|
|
||||||
presence: optional
|
|
||||||
nvidia-580-uda-user:
|
|
||||||
presence: optional
|
|
||||||
default-channel: 26.04/beta
|
|
||||||
id: pYVQrBcKmBa0mZ4CCN7ExT6jH8rY1hza
|
|
||||||
name: pc-kernel
|
|
||||||
type: kernel
|
|
||||||
-
|
|
||||||
default-channel: latest/edge
|
|
||||||
id: amcUKQILKXHHTlmSa7NMdnXSx02dNeeT
|
|
||||||
name: core22
|
|
||||||
type: base
|
|
||||||
-
|
|
||||||
default-channel: latest/edge
|
|
||||||
id: dwTAh7MZZ01zyriOZErqd1JynQLiOGvM
|
|
||||||
name: core24
|
|
||||||
type: base
|
|
||||||
-
|
|
||||||
default-channel: latest/edge
|
|
||||||
id: cUqM61hRuZAJYmIS898Ux66VY61gBbZf
|
|
||||||
name: core26
|
|
||||||
type: base
|
|
||||||
-
|
|
||||||
default-channel: latest/edge
|
|
||||||
id: PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4
|
|
||||||
name: snapd
|
|
||||||
type: snapd
|
|
||||||
-
|
|
||||||
default-channel: latest/edge
|
|
||||||
id: EISPgh06mRh1vordZY9OZ34QHdd7OrdR
|
|
||||||
name: bare
|
|
||||||
type: base
|
|
||||||
-
|
|
||||||
default-channel: latest/edge
|
|
||||||
id: HyhSEBPv3vHsW6uOHkQR384NgI7S6zpj
|
|
||||||
name: mesa-2404
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: 1/edge
|
|
||||||
id: EI0D1KHjP8XiwMZKqSjuh6W8zvcowUVP
|
|
||||||
name: firmware-updater
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: 1/edge
|
|
||||||
id: FppXWunWzuRT2NUT9CwoBPNJNZBYOCk0
|
|
||||||
name: desktop-security-center
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: 1/edge
|
|
||||||
id: aoc5lfC8aUd2VL8VpvynUJJhGXp5K6Dj
|
|
||||||
name: prompting-client
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: 2/edge
|
|
||||||
id: gjf3IPXoRiipCu9K0kVu52f0H56fIksg
|
|
||||||
name: snap-store
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: latest/edge
|
|
||||||
id: jZLfBRzf1cYlYysIjD2bwSzNtngY0qit
|
|
||||||
name: gtk-common-themes
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: latest/edge
|
|
||||||
id: 3wdHCAVyZEmYsCMFDE9qt92UV8rC8Wdk
|
|
||||||
name: firefox
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: latest/edge
|
|
||||||
id: ew7OxpbRTxfK7ImpIygRR85lkxvU7Pzt
|
|
||||||
name: gnome-46-2404
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: latest/edge
|
|
||||||
id: IrwRHakqtzhFRHJOOPxKVPU0Kk7Erhcu
|
|
||||||
name: snapd-desktop-integration
|
|
||||||
type: app
|
|
||||||
timestamp: 2025-12-09T12:00:00.0Z
|
|
||||||
sign-key-sha3-384: 9tydnLa6MTJ-jaQTFUXEwHl1yRx7ZS4K5cyFDhYDcPzhS7uyEkDxdUjg9g08BtNn
|
|
||||||
|
|
||||||
AcLBXAQAAQoABgUCaUFt7QAKCRDgT5vottzAEhdnD/92LBcQm3iw/kPao4KqGE0OhfXDFd7Z6+Qv
|
|
||||||
A1Dlzz6Cw0tuj0r5aZH7vJQCx4kC1Eaoi8apg3XhqAyhr74/MsIwMhPPL8qcSNv8ZWruoGwFp/rx
|
|
||||||
M6NSBKc6hrYqACYfEkBwfq9SgmIDQKFeBVudwswLK2SN58wrDNJjuWz/eJ5hUIIe3ga5ScfzO4Jr
|
|
||||||
jTWS4kh5lpttCPFX8ouLkMgLUxijQpxFbHoF1trXJndFvavStT0yuC0y5TXzb3wJbbiF/MXZWyjV
|
|
||||||
/4U+oQLodO77MhaD01kk2y5bZ62YuQ3MPL0fQGypon12GPHeNNcEcYWRZlFv+JkWAduWlnuefj1D
|
|
||||||
dVWV8dQQmSZGZNiGTsIJxkY9+4B+t/OhosGDc6jEmEZcKNVi9fnl0+awkzK6scNNmupZ8NwJl8ZR
|
|
||||||
mJSsfaBcH4paYV1x31y4uTELv+OuDWAJ3D0RoCR8H0djTBxRhsF2/JpSJasxVmSbzWHPSeM3f1aO
|
|
||||||
ChZGwbD6J2SpzsrdogUP/9z6o8YuVnJkOxoBYuXhT1pEYTd93/hE++j3MpOqey/xw8UDbYmq5oJf
|
|
||||||
uKaYLOMphqDm5hUCZmxQp8gTzDleZGjxYS2fOS4qFUJlvyVwsSoJMXU+6YfA6tgEQ4Dbh6zp6r78
|
|
||||||
MjEqfWn4lL16xW2Zzr6e8xWwUrM7T3Gp4WTA7/xOeA==
|
|
||||||
@ -1,104 +0,0 @@
|
|||||||
type: model
|
|
||||||
authority-id: canonical
|
|
||||||
series: 16
|
|
||||||
brand-id: canonical
|
|
||||||
model: ubuntu-classic-2604-amd64
|
|
||||||
architecture: amd64
|
|
||||||
base: core24
|
|
||||||
classic: true
|
|
||||||
distribution: ubuntu
|
|
||||||
grade: signed
|
|
||||||
snaps:
|
|
||||||
-
|
|
||||||
default-channel: classic-26.04/stable
|
|
||||||
id: UqFziVZDHLSyO3TqSWgNBoAdHbLI4dAH
|
|
||||||
name: pc
|
|
||||||
type: gadget
|
|
||||||
-
|
|
||||||
components:
|
|
||||||
nvidia-580-uda-ko:
|
|
||||||
presence: optional
|
|
||||||
nvidia-580-uda-user:
|
|
||||||
presence: optional
|
|
||||||
default-channel: 26.04/stable
|
|
||||||
id: pYVQrBcKmBa0mZ4CCN7ExT6jH8rY1hza
|
|
||||||
name: pc-kernel
|
|
||||||
type: kernel
|
|
||||||
-
|
|
||||||
default-channel: latest/stable
|
|
||||||
id: amcUKQILKXHHTlmSa7NMdnXSx02dNeeT
|
|
||||||
name: core22
|
|
||||||
type: base
|
|
||||||
-
|
|
||||||
default-channel: latest/stable
|
|
||||||
id: dwTAh7MZZ01zyriOZErqd1JynQLiOGvM
|
|
||||||
name: core24
|
|
||||||
type: base
|
|
||||||
-
|
|
||||||
default-channel: latest/stable
|
|
||||||
id: PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4
|
|
||||||
name: snapd
|
|
||||||
type: snapd
|
|
||||||
-
|
|
||||||
default-channel: latest/stable
|
|
||||||
id: EISPgh06mRh1vordZY9OZ34QHdd7OrdR
|
|
||||||
name: bare
|
|
||||||
type: base
|
|
||||||
-
|
|
||||||
default-channel: latest/stable/ubuntu-26.04
|
|
||||||
id: HyhSEBPv3vHsW6uOHkQR384NgI7S6zpj
|
|
||||||
name: mesa-2404
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: 1/stable/ubuntu-26.04
|
|
||||||
id: EI0D1KHjP8XiwMZKqSjuh6W8zvcowUVP
|
|
||||||
name: firmware-updater
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: 1/stable/ubuntu-26.04
|
|
||||||
id: FppXWunWzuRT2NUT9CwoBPNJNZBYOCk0
|
|
||||||
name: desktop-security-center
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: 1/stable/ubuntu-26.04
|
|
||||||
id: aoc5lfC8aUd2VL8VpvynUJJhGXp5K6Dj
|
|
||||||
name: prompting-client
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: 2/stable/ubuntu-26.04
|
|
||||||
id: gjf3IPXoRiipCu9K0kVu52f0H56fIksg
|
|
||||||
name: snap-store
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: latest/stable/ubuntu-26.04
|
|
||||||
id: jZLfBRzf1cYlYysIjD2bwSzNtngY0qit
|
|
||||||
name: gtk-common-themes
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: latest/stable/ubuntu-26.04
|
|
||||||
id: 3wdHCAVyZEmYsCMFDE9qt92UV8rC8Wdk
|
|
||||||
name: firefox
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: latest/stable/ubuntu-26.04
|
|
||||||
id: ew7OxpbRTxfK7ImpIygRR85lkxvU7Pzt
|
|
||||||
name: gnome-46-2404
|
|
||||||
type: app
|
|
||||||
-
|
|
||||||
default-channel: latest/stable/ubuntu-26.04
|
|
||||||
id: IrwRHakqtzhFRHJOOPxKVPU0Kk7Erhcu
|
|
||||||
name: snapd-desktop-integration
|
|
||||||
type: app
|
|
||||||
timestamp: 2025-12-09T12:00:00.0Z
|
|
||||||
sign-key-sha3-384: 9tydnLa6MTJ-jaQTFUXEwHl1yRx7ZS4K5cyFDhYDcPzhS7uyEkDxdUjg9g08BtNn
|
|
||||||
|
|
||||||
AcLBXAQAAQoABgUCaYzP9QAKCRDgT5vottzAEus2D/4jJVutpoPmDrLjNQLn2KNf/f1L2zU8ESSe
|
|
||||||
VpFjy+9Ff7AxXckALM4eEy/J5mc+UNhHQ/7Thp4XYy2NiH14n9Lv5kVqZCz8udiEfcfLy5gGveio
|
|
||||||
oXyGX7J5x9sq3YXV1IHS84aqJS0si80TTLCRQXUN8oUZIVRkgFOGIVVneQkn1ppNs87kNgvBT1ow
|
|
||||||
nwr9fVvZnt5bTprCxs4R5cEUlWTJMN4l96Eh530Q+wqCjFxbTs6FADUYielsFnBDl/Q1M0fozg4F
|
|
||||||
Ct4gBbvFGWZhp8LXiCbJvTd3PAAV1HYAgtKDKZT0NQp8qaU5DpgTDiUzIjaAJP7feSU5AYDLuVSH
|
|
||||||
V3zD8sosg1nmPvVtuSi2q5Z+/zd6gmG+vLn5d16whNqELDnX0O9Hxarc/3DD3ANZrrbXlq/PEJNB
|
|
||||||
Lor5osHLN4utW7CUC5MIEQ5/Z/6cSuav6rQ+bBiAOzQSHRCbhfyCGSMMINX2CE3ePw3moi9gwXeh
|
|
||||||
vKw1iItEOxywEKbeBNEvddnGsvmzoqf9Jg53/X0yrQQVZTHYFsQlTRk9ggajdZnPjJMTqlAqjXnP
|
|
||||||
QCsgnprvln0akW4IfEzc+IgoF5eiShJd4IidkBbbdNXRRYlHfmOG7ZvR9upJwe1M73Zfu1nQFEvT
|
|
||||||
fly59e2Vw8O50ljOVW3jT5fW36z8h1+ttxkKwVsQJg==
|
|
||||||
Loading…
x
Reference in New Issue
Block a user