feat: add initial support for custom bootloaders
This commit is contained in:
parent
f17c272b65
commit
76b61eb57a
3 changed files with 120 additions and 19 deletions
|
|
@ -35,6 +35,7 @@ def resolve_config(system_config: dict) -> dict:
|
||||||
"auto-update": system_config["auto-update"]
|
"auto-update": system_config["auto-update"]
|
||||||
if isinstance(system_config.get("auto-update"), dict)
|
if isinstance(system_config.get("auto-update"), dict)
|
||||||
else {"enabled": False},
|
else {"enabled": False},
|
||||||
|
"boot": system_config["boot"],
|
||||||
}
|
}
|
||||||
except IndexError:
|
except IndexError:
|
||||||
output.error("base track must include distro-config")
|
output.error("base track must include distro-config")
|
||||||
|
|
@ -96,6 +97,12 @@ def resolve_config(system_config: dict) -> dict:
|
||||||
else base_config["auto-update"]
|
else base_config["auto-update"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
base_config["boot"] = (
|
||||||
|
system_config["boot"]
|
||||||
|
if isinstance(system_config.get("boot"), dict)
|
||||||
|
else base_config["boot"]
|
||||||
|
)
|
||||||
|
|
||||||
return base_config
|
return base_config
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,13 @@ def update_cleanup() -> None:
|
||||||
"""Clean-up from previous rebase/update."""
|
"""Clean-up from previous rebase/update."""
|
||||||
|
|
||||||
# FIXME: should not ideally handle /var/cache/blendOS explicitly
|
# FIXME: should not ideally handle /var/cache/blendOS explicitly
|
||||||
|
for path in (
|
||||||
|
"/etc/grub.d",
|
||||||
|
"/etc/default/grub",
|
||||||
|
"/var/cache/akshara/rootfs/var/cache/blendOS",
|
||||||
|
):
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["umount", "-l", "/var/cache/akshara/rootfs/var/cache/blendOS"],
|
["umount", "-l", path],
|
||||||
stdout=subprocess.DEVNULL,
|
stdout=subprocess.DEVNULL,
|
||||||
stderr=subprocess.DEVNULL,
|
stderr=subprocess.DEVNULL,
|
||||||
)
|
)
|
||||||
|
|
@ -135,21 +140,108 @@ def merge_var(new_rootfs: RootFS, overrides_keep_new: dict) -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def replace_boot_files() -> None:
|
def is_bind_mnt(src, mountpoint) -> bool:
|
||||||
"""Replace files in /boot with those from new rootfs."""
|
"""Checks if /boot presently has /.tmp.boot bind-mounted to it.
|
||||||
new_boot_files = []
|
|
||||||
|
|
||||||
for f in os.listdir("/.update_rootfs/boot"):
|
Args:
|
||||||
if not os.path.isdir(f"/.update_rootfs/boot/{f}"):
|
src: Source directory of bind-mount.
|
||||||
subprocess.run(["mv", f"/.update_rootfs/boot/{f}", "/boot"])
|
mountpoint: Mountpoint for bind-mount.
|
||||||
new_boot_files.append(f)
|
"""
|
||||||
|
with open("/proc/self/mountinfo") as mountinfo_file:
|
||||||
|
for line in mountinfo_file:
|
||||||
|
parts = line.strip().split()
|
||||||
|
if parts[3] != "/" and parts[3] == src and parts[4] == mountpoint:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
for f in os.listdir("/boot"):
|
|
||||||
if not os.path.isdir(f"/boot/{f}"):
|
|
||||||
if f not in new_boot_files:
|
|
||||||
subprocess.run(["rm", "-f", f"/boot/{f}"])
|
|
||||||
|
|
||||||
subprocess.run(["grub-mkconfig", "-o", "/boot/grub/grub.cfg"])
|
def handle_boot(new_rootfs, boot_config) -> None:
|
||||||
|
"""Handles /boot partition."""
|
||||||
|
|
||||||
|
if os.path.isdir("/.tmp.boot"):
|
||||||
|
if is_bind_mnt("/.tmp.boot", "/boot"):
|
||||||
|
subprocess.run(["umount", "-l", "/boot"])
|
||||||
|
subprocess.run(["rm", "-rf", "/.tmp.boot"])
|
||||||
|
|
||||||
|
subprocess.run(["cp", "-ax", os.path.join(str(new_rootfs), "boot"), "/.tmp.boot"])
|
||||||
|
subprocess.run(["mount", "--bind", "/.tmp.boot", "/boot"])
|
||||||
|
|
||||||
|
if boot_config["type"] == "bios":
|
||||||
|
if boot_config["loader"] == "grub":
|
||||||
|
if (
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"grub-install",
|
||||||
|
f"--directory={os.path.join(str(new_rootfs), 'usr/lib/grub/i386-pc')}",
|
||||||
|
"--target=i386-pc",
|
||||||
|
boot_config["device"],
|
||||||
|
]
|
||||||
|
).returncode
|
||||||
|
!= 0
|
||||||
|
):
|
||||||
|
output.error("aborting update...")
|
||||||
|
subprocess.run(["umount", "-l", "/boot"])
|
||||||
|
subprocess.run(["rm", "-rf", "/.tmp.boot"])
|
||||||
|
output.error("failed to install GRUB")
|
||||||
|
exit(1)
|
||||||
|
else:
|
||||||
|
subprocess.run(["umount", "-l", "/boot"])
|
||||||
|
subprocess.run(["rm", "-rf", "/.tmp.boot"])
|
||||||
|
output.error("unsupported bootloader for BIOS configuration")
|
||||||
|
exit(1)
|
||||||
|
elif boot_config["type"] == "uefi":
|
||||||
|
if boot_config["loader"] == "grub":
|
||||||
|
if (
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"grub-install",
|
||||||
|
f"--directory={os.path.join(str(new_rootfs), 'usr/lib/grub/x86_64-efi')}",
|
||||||
|
"--efi-directory=/boot",
|
||||||
|
"--target=x86_64-efi",
|
||||||
|
"--removable",
|
||||||
|
"--bootloader-id=blendOS",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
!= 0
|
||||||
|
):
|
||||||
|
output.error("aborting update...")
|
||||||
|
subprocess.run(["umount", "-l", "/boot"])
|
||||||
|
subprocess.run(["rm", "-rf", "/.tmp.boot"])
|
||||||
|
output.error("failed to install GRUB")
|
||||||
|
exit(1)
|
||||||
|
else:
|
||||||
|
subprocess.run(["umount", "-l", "/boot"])
|
||||||
|
subprocess.run(["rm", "-rf", "/.tmp.boot"])
|
||||||
|
output.error("unsupported bootloader for BIOS configuration")
|
||||||
|
exit(1)
|
||||||
|
else:
|
||||||
|
subprocess.run(["umount", "-l", "/boot"])
|
||||||
|
subprocess.run(["rm", "-rf", "/.tmp.boot"])
|
||||||
|
output.error(f"unsupported system type - {boot_config['type']}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
if boot_config["loader"] == "grub":
|
||||||
|
new_rootfs.exec(["grub-mkconfig", "-o", "/grub.cfg"])
|
||||||
|
subprocess.run(["cp", f"{new_rootfs}/grub.cfg", "/boot/grub/grub.cfg"])
|
||||||
|
|
||||||
|
subprocess.run(["umount", "-l", "/boot"])
|
||||||
|
|
||||||
|
# Replace /boot with /.tmp.boot
|
||||||
|
# FIXME: should be atomic
|
||||||
|
for tmp_boot, dirs, files in os.walk("/.tmp.boot"):
|
||||||
|
boot = tmp_boot.replace("/tmp.boot", "/boot", 1)
|
||||||
|
for path in dirs + files:
|
||||||
|
subprocess.run(["rm", "-rf", "--", os.path.join(boot, path)])
|
||||||
|
subprocess.run(
|
||||||
|
[
|
||||||
|
"cp",
|
||||||
|
"-ax",
|
||||||
|
os.path.join(tmp_boot, path),
|
||||||
|
os.path.join(boot, path),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
subprocess.run(["rm", "-rf", "/.tmp.boot"])
|
||||||
|
|
||||||
|
|
||||||
def update() -> None:
|
def update() -> None:
|
||||||
|
|
@ -194,6 +286,7 @@ def update() -> None:
|
||||||
else {}
|
else {}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
output.info("merging /etc...")
|
||||||
merge_etc(new_rootfs, overrides_keep_new)
|
merge_etc(new_rootfs, overrides_keep_new)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -221,6 +314,7 @@ def update() -> None:
|
||||||
output.error("malformed /etc/shadow")
|
output.error("malformed /etc/shadow")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
output.info("merging /var...")
|
||||||
merge_var(new_rootfs, overrides_keep_new)
|
merge_var(new_rootfs, overrides_keep_new)
|
||||||
|
|
||||||
with open(
|
with open(
|
||||||
|
|
@ -242,6 +336,6 @@ def update() -> None:
|
||||||
|
|
||||||
subprocess.run(["cp", "-ax", str(new_rootfs), "/.update_rootfs"])
|
subprocess.run(["cp", "-ax", str(new_rootfs), "/.update_rootfs"])
|
||||||
|
|
||||||
replace_boot_files()
|
handle_boot(new_rootfs, system_config["boot"])
|
||||||
|
|
||||||
print()
|
print()
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ echo
|
||||||
mount -o remount,rw "$NEWROOT" >/dev/null 2>&1 || true
|
mount -o remount,rw "$NEWROOT" >/dev/null 2>&1 || true
|
||||||
|
|
||||||
# Remove "$NEWROOT"/.successful-update if exists
|
# Remove "$NEWROOT"/.successful-update if exists
|
||||||
rm -f "$NEWROOT"/.successful-update "$NEWROOT"/.update
|
rm -f "$NEWROOT"/.successful-update "$NEWROOT"/.update "$NEWROOT"/.tmp.boot
|
||||||
|
|
||||||
# Check if there is an available update
|
# Check if there is an available update
|
||||||
if [ -d "$NEWROOT"/.update_rootfs ]; then
|
if [ -d "$NEWROOT"/.update_rootfs ]; then
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue