modernize, switch to dracut

Signed-off-by: Martin Matous <m@matous.dev>
This commit is contained in:
Martin Matous 2023-09-24 02:38:51 +02:00
parent 5f17d90c7b
commit acd336e659
Signed by: mmatous
GPG key ID: 8BED4CD352953224
2 changed files with 22 additions and 79 deletions

View file

@ -61,14 +61,11 @@ Usage: `gtokei.sh https://github.com/some/repo`
## kernel-update.py ## kernel-update.py
Automate chores when configuring, compiling and updating kernel. Automate chores when configuring, compiling and updating kernel.
Install step can be simplified by using properly setup installkernel/kernel-install
invocation by `make install`.
Status: active use Status: active use
Dependencies: python-magic, Gentoo (not really but genkernel, eselect, specific names and paths...) Dependencies: dracut, Gentoo (not really but eselect, specific names and paths...)
Usage: `kernel-update.py <old-version> <new-version>` Usage: `kernel-update.py update <old-version> <new-version>`
--- ---

View file

@ -1,43 +1,19 @@
#!/usr/bin/env python #!/usr/bin/env python
import argparse import argparse
import magic
import os import os
import shutil import shutil
import subprocess import subprocess
import sys import sys
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, Tuple
BOOT_FILES = {
'config': Path('config-gentoo'),
'initramfs': Path('initramfs-gentoo.img'),
'kernel': Path('vmlinuz-gentoo'),
'system_map': Path('System.map-gentoo'),
}
SRC_DIR = Path('/usr/src') SRC_DIR = Path('/usr/src')
BOOT_DIR = Path('/boot') BOOT_DIR = Path('/boot')
def backup_kernel(boot_dir: Path, files: Dict[str, Path]) -> None: def update_config(old_dir: Path, new_dir: Path, make_cmd: list[str]) -> None:
for f in files.values():
src = boot_dir/f
dst = boot_dir/(f.name + '.old')
print(f'Backing-up {src} to {dst}')
shutil.copy2(src, dst)
def rollback_impl(boot_dir: Path, files: Dict[str, Path]) -> None:
for f in files.values():
src = boot_dir/(f.name + '.old')
dst = boot_dir/f
print(f'Restoring {src} to {dst}')
shutil.copy2(src, dst)
def update_config(old_dir: Path, new_dir: Path, make_cmd: List[str]) -> None:
if old_dir == new_dir: if old_dir == new_dir:
return return
old_config = old_dir/'.config' old_config = old_dir/'.config'
@ -55,7 +31,7 @@ def update_config(old_dir: Path, new_dir: Path, make_cmd: List[str]) -> None:
print(f'Setting symlink to {new_dir}') print(f'Setting symlink to {new_dir}')
subprocess.run(['eselect', 'kernel', 'set', new_dir.name]) subprocess.run(['eselect', 'kernel', 'set', new_dir.name])
print(f'Migrating config options') print('Migrating config options')
migrate = make_cmd + ['-C', new_dir.as_posix(), 'oldconfig'] migrate = make_cmd + ['-C', new_dir.as_posix(), 'oldconfig']
subprocess.run(migrate) subprocess.run(migrate)
menuconfig = make_cmd + ['-C', new_dir.as_posix(), 'menuconfig'] menuconfig = make_cmd + ['-C', new_dir.as_posix(), 'menuconfig']
@ -70,33 +46,26 @@ def update_config(old_dir: Path, new_dir: Path, make_cmd: List[str]) -> None:
print("unrecognized option {}", response) print("unrecognized option {}", response)
def compile_kernel(new_dir: Path, make_cmd: List[str]) -> None: def compile_kernel(new_dir: Path, make_cmd: list[str]) -> None:
cc = make_cmd + ['-C', new_dir.as_posix()] cc = make_cmd + ['-C', new_dir.as_posix()]
subprocess.run(cc) subprocess.run(cc)
def install_kernel(kernel_dir: Path, boot_dir: Path, boot_files: Dict[str, Path], make_cmd: List[str]) -> None: def install_kernel(kernel_dir: Path, make_cmd: list[str], kver: str) -> None:
make_files = {
'config': Path('.config'),
'system_map': Path('System.map'),
'kernel': Path('arch/x86/boot/bzImage')
}
config = (kernel_dir/make_files['config']).as_posix()
# subprocess.run(make_cmd.extend(['-C', kernel_dir, 'install'])) # this would create unwanted entries
common_keys = make_files.keys() & boot_files.keys()
for key in common_keys:
src = kernel_dir/make_files[key]
dst = boot_dir/boot_files[key]
print(f'Installing {src} to {dst}')
shutil.copy2(src, dst)
install_modules = make_cmd + ['-C', kernel_dir.as_posix(), 'modules_install'] install_modules = make_cmd + ['-C', kernel_dir.as_posix(), 'modules_install']
subprocess.run(install_modules) subprocess.run(install_modules)
genkernel = ['genkernel', f'--kernel-config={config}', '--microcode', 'initramfs'] kver = kver[6:]
subprocess.run(genkernel) # assumes proper dracut config in /etc
dracut = ['dracut', f'--kver={kver}', '--force', '--no-machineid']
res = subprocess.run(dracut)
print(res)
return
# todo: sign uki
uki_dir = res.split('')
sign_uki = ['sbctl', 'bundle', '--save', '']
subprocess.run(sign_uki)
def linux_folder(src_dir: Path, version: str) -> Path: def linux_folder(src_dir: Path, version: str) -> Path:
revision = '' revision = ''
@ -107,54 +76,31 @@ def linux_folder(src_dir: Path, version: str) -> Path:
return (src_dir / (f'linux-{version}-gentoo{revision}')) return (src_dir / (f'linux-{version}-gentoo{revision}'))
def module_check(boot_dir: Path, boot_files: Dict[str, Path]) -> Tuple[bool, Path]: def update_kernel(boot_dir: Path, args: argparse.Namespace) -> None:
kernel_name = boot_files['kernel'].name + '.old'
old_kernel: Path = boot_dir/kernel_name
magic_list = magic.from_file(old_kernel).split()
version = Path(magic_list[magic_list.index('version') + 1])
modules = Path('/lib/modules')/version
if not modules.exists():
return (False, version)
return (True, version)
def rollback_kernel(boot_dir: Path, boot_files: Dict[str, Path], _args: Any) -> None:
check = module_check(boot_dir, boot_files)
if not check[0]:
err = f'Module directory not found for {check[1]}.\nRefusing to proceed.'
raise RuntimeError(err)
rollback_impl(boot_dir, boot_files)
def update_kernel(boot_dir: Path, boot_files: Dict[str, Path], args: Any) -> None:
old_dir = linux_folder(SRC_DIR, args.old_version) old_dir = linux_folder(SRC_DIR, args.old_version)
new_dir = linux_folder(SRC_DIR, args.new_version) new_dir = linux_folder(SRC_DIR, args.new_version)
new_version = new_dir.name new_version = new_dir.name
make_cmd = ['make', f'-j{len(os.sched_getaffinity(0))}'] make_cmd = ['make', f'-j{len(os.sched_getaffinity(0))}']
clang_env = ['CC=clang', 'LD=ld.lld', 'LLVM=1', 'LLVM_IAS=1'] # https://docs.kernel.org/kbuild/llvm.html
if args.llvm: if args.llvm:
make_cmd.extend(clang_env) make_cmd.extend(['LLVM=1'])
none_selected = not (args.backup or args.config or args.compile or args.install or args.rollback) none_selected = not (args.backup or args.config or args.compile or args.install or args.rollback)
if none_selected: if none_selected:
backup_kernel(BOOT_DIR, BOOT_FILES)
update_config(old_dir, new_dir, make_cmd) update_config(old_dir, new_dir, make_cmd)
compile_kernel(new_dir, make_cmd) compile_kernel(new_dir, make_cmd)
install_kernel(new_dir, BOOT_DIR, BOOT_FILES, make_cmd) install_kernel(new_dir, make_cmd, new_version)
if args.backup:
backup_kernel(BOOT_DIR, BOOT_FILES)
if args.config: if args.config:
update_config(old_dir, new_dir, make_cmd) update_config(old_dir, new_dir, make_cmd)
if args.compile: if args.compile:
compile_kernel(new_dir, make_cmd) compile_kernel(new_dir, make_cmd)
if args.install: if args.install:
install_kernel(new_dir, BOOT_DIR, BOOT_FILES, make_cmd) install_kernel(new_dir, make_cmd, new_version)
def main() -> None: def main() -> None:
parser = argparse.ArgumentParser(description='Convenience for manual kernel updates') parser = argparse.ArgumentParser(description='Convenience for manual kernel updates')
subparsers = parser.add_subparsers() subparsers = parser.add_subparsers()
rollback = subparsers.add_parser('rollback')
rollback.set_defaults(func=rollback_kernel)
update = subparsers.add_parser('update', update = subparsers.add_parser('update',
usage=f'{sys.argv[0]} update 5.15.12 5.16.3', usage=f'{sys.argv[0]} update 5.15.12 5.16.3',
) )
@ -181,7 +127,7 @@ def main() -> None:
update.set_defaults(func=update_kernel) update.set_defaults(func=update_kernel)
args = parser.parse_args() args = parser.parse_args()
args.func(BOOT_DIR, BOOT_FILES, args) args.func(BOOT_DIR, args)
if __name__ == "__main__": if __name__ == "__main__":