stages/grub2: support identifying fs via labels
In addition to support for identifying file-systems via their uuids, they now can be identified via their label as well. Two new options are introduce for this: `rootfs` and `bootfs` for the root and boot file system. The latter is option in the case a separated partition is used for /boot. Both options are an object that can either have `uuid` or `label` set. The old uuid based options, `root_fs_uuid` & `boot_fs_uuid` are still supported for now. Additionally, remove the `GRUB2_ROOT_FS_UUID` option from the grubenv file and directly write the root file system identifier into the grub config file.
This commit is contained in:
parent
d5575edbc7
commit
22d131a5d9
1 changed files with 74 additions and 15 deletions
|
|
@ -9,8 +9,12 @@ STAGE_DESC = "Configure GRUB2 bootloader and set boot options"
|
|||
STAGE_INFO = """
|
||||
Configure the system to use GRUB2 as the bootloader, and set boot options.
|
||||
|
||||
Sets the GRUB2 boot/root filesystem to `root_fs_uuid` and sets kernel boot
|
||||
arguments to "root=UUID={root_fs_uuid} {kernel_opts}".
|
||||
Sets the GRUB2 boot/root filesystem to `rootfs`. If a separated boot
|
||||
partition is used it can be specified via `bootfs`. The file-systems
|
||||
can be identified either via uuid (`{"uuid": "<uuid>"}`) or label
|
||||
(`{"label": "<label>"}`). The kernel boot argument will be composed
|
||||
of the root file system id and additional options specified in
|
||||
`{kernel_opts}`, if any.
|
||||
|
||||
Configures GRUB2 to boot via the Boot Loader Specification
|
||||
(https://systemd.io/BOOT_LOADER_SPECIFICATION), which is the default
|
||||
|
|
@ -38,8 +42,41 @@ and accompanying data can be installed from the built root via `uefi.install`.
|
|||
Both UEFI and Legacy can be specified at the same time.
|
||||
"""
|
||||
STAGE_OPTS = """
|
||||
"required": ["root_fs_uuid"],
|
||||
"oneOf": [{
|
||||
"required": ["root_fs_uuid"]
|
||||
}, {
|
||||
"required": ["rootfs"]
|
||||
}],
|
||||
"definitions": {
|
||||
"filesystem": {
|
||||
"description": "Description of how to locate a file system",
|
||||
"type": "object",
|
||||
"oneOf": [{
|
||||
"required": ["uuid"]
|
||||
}, {
|
||||
"required": ["label"]
|
||||
}],
|
||||
"properties": {
|
||||
"label": {
|
||||
"description": "Identify the file system by label",
|
||||
"type": "string"
|
||||
},
|
||||
"uuid": {
|
||||
"description": "Identify the file system by UUID",
|
||||
"type": "string",
|
||||
"oneOf": [
|
||||
{ "pattern": "^[0-9A-Za-z]{8}(-[0-9A-Za-z]{4}){3}-[0-9A-Za-z]{12}$",
|
||||
"examples": ["9c6ae55b-cf88-45b8-84e8-64990759f39d"] },
|
||||
{ "pattern": "^[0-9A-Za-z]{4}-[0-9A-Za-z]{4}$",
|
||||
"examples": ["6699-AFB5"] }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"rootfs": { "$ref": "#/definitions/filesystem" },
|
||||
"bootfs": { "$ref": "#/definitions/filesystem" },
|
||||
"root_fs_uuid": {
|
||||
"description": "UUID of the root filesystem image",
|
||||
"type": "string",
|
||||
|
|
@ -99,6 +136,14 @@ STAGE_OPTS = """
|
|||
"""
|
||||
|
||||
|
||||
def fs_spec_decode(spec):
|
||||
for key in ["uuid", "label"]:
|
||||
val = spec.get(key)
|
||||
if val:
|
||||
return key.upper(), val
|
||||
raise ValueError("unknown filesystem type")
|
||||
|
||||
|
||||
def copy_modules(tree, platform):
|
||||
"""Copy all modules from the build image to /boot"""
|
||||
target = f"{tree}/boot/grub2/{platform}"
|
||||
|
|
@ -128,12 +173,18 @@ def copy_efi_data(tree, vendor):
|
|||
symlinks=False)
|
||||
|
||||
|
||||
def write_grub_cfg(tree, path):
|
||||
"""Write the grub config"""
|
||||
def write_grub_cfg(tree, path, grub_fs):
|
||||
"""Write the grub config to `tree` at `path`"""
|
||||
fs_type, fs_id = fs_spec_decode(grub_fs)
|
||||
type2opt = {
|
||||
"UUID": "--fs-uuid",
|
||||
"LABEL": "--label"
|
||||
}
|
||||
search = type2opt[fs_type] + " " + fs_id
|
||||
with open(os.path.join(tree, path), "w") as cfg:
|
||||
cfg.write("set timeout=0\n"
|
||||
"load_env\n"
|
||||
"search --no-floppy --fs-uuid --set=root ${GRUB2_ROOT_FS_UUID}\n"
|
||||
f"search --no-floppy --set=root {search}\n"
|
||||
"set boot=${root}\n"
|
||||
"function load_video {\n"
|
||||
" insmod all_video\n"
|
||||
|
|
@ -152,13 +203,20 @@ def write_grub_cfg_redirect(tree, path, separate_boot):
|
|||
|
||||
|
||||
def main(tree, options):
|
||||
root_fs_uuid = options["root_fs_uuid"]
|
||||
boot_fs_uuid = options.get("boot_fs_uuid", None)
|
||||
root_fs = options.get("rootfs")
|
||||
boot_fs = options.get("bootfs")
|
||||
kernel_opts = options.get("kernel_opts", "")
|
||||
legacy = options.get("legacy", None)
|
||||
uefi = options.get("uefi", None)
|
||||
write_defaults = options.get("write_defaults", True)
|
||||
|
||||
# backwards compatibility
|
||||
if not root_fs:
|
||||
root_fs = {"uuid": options["root_fs_uuid"]}
|
||||
|
||||
if not boot_fs and "boot_fs_uuid" in options:
|
||||
boot_fs = {"uuid": options["boot_fs_uuid"]}
|
||||
|
||||
# legacy boolean means the
|
||||
if isinstance(legacy, bool) and legacy:
|
||||
legacy = "i386-pc"
|
||||
|
|
@ -170,9 +228,10 @@ def main(tree, options):
|
|||
# /boot/grub2 and will not have a grubenv itself.
|
||||
hybrid = uefi and legacy
|
||||
|
||||
# grub_fs_uuid points to the filesystem containing the grub files
|
||||
grub_fs_uuid = boot_fs_uuid or root_fs_uuid
|
||||
separate_boot = boot_fs_uuid is not None
|
||||
# grub_fs points to the filesystem containing the grub files, which is
|
||||
# either a separate partition (boot_fs) or the root file system (root_fs)
|
||||
grub_fs = boot_fs or root_fs
|
||||
separate_boot = boot_fs is not None
|
||||
|
||||
# Create the configuration file that determines how grub.cfg is generated.
|
||||
if write_defaults:
|
||||
|
|
@ -194,9 +253,9 @@ def main(tree, options):
|
|||
pass
|
||||
|
||||
with open(grubenv, "w") as env:
|
||||
fs_type, fs_id = fs_spec_decode(root_fs)
|
||||
env.write("# GRUB Environment Block\n"
|
||||
f"GRUB2_ROOT_FS_UUID={grub_fs_uuid}\n"
|
||||
f"kernelopts=root=UUID={root_fs_uuid} {kernel_opts}\n")
|
||||
f"kernelopts=root={fs_type}={fs_id} {kernel_opts}\n")
|
||||
|
||||
if uefi is not None:
|
||||
# UEFI support:
|
||||
|
|
@ -219,10 +278,10 @@ def main(tree, options):
|
|||
if hybrid:
|
||||
write_grub_cfg_redirect(tree, grubcfg, separate_boot)
|
||||
else:
|
||||
write_grub_cfg(tree, grubcfg)
|
||||
write_grub_cfg(tree, grubcfg, grub_fs)
|
||||
|
||||
if legacy:
|
||||
write_grub_cfg(tree, "boot/grub2/grub.cfg")
|
||||
write_grub_cfg(tree, "boot/grub2/grub.cfg", grub_fs)
|
||||
copy_modules(tree, legacy)
|
||||
copy_font(tree)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue