diff --git a/README.md b/README.md index d884499..9d800e6 100644 --- a/README.md +++ b/README.md @@ -31,15 +31,28 @@ dh-python Then use these commands to build the package: ``` -git clone https://github.com/pop-os/kernelstub +git clone https://github.com/isantop/kernelstub cd kernelstub dpkg-buildpackage -b -us -uc sudo dpkg -i ../kernelstub*.deb ``` -For installation on non-debian systems, or if you prefer to use Python + +For installation on RPM-based systems (Fedora, RHEL, etc.), the Python packaging +can automatically build an RPM package for use on your system: +``` +git clone https://github.com/isantop/kernelstub +cd kernelstub +python3 setup.py bdist_rpm +``` +After this, you can install the resulting RPM package directly: +``` +sudo rpm -i dist/kernelstub-*.rpm +``` + +For installation on other systems, or if you prefer to use Python packaging, use: ``` -git clone https://github.com/pop-os/kernelstub +git clone https://github.com/isantop/kernelstub cd kernelstub sudo python3 setup.py install --record=installed_files.txt ``` diff --git a/data/initramfs/zz-kernelstub b/data/initramfs/zz-kernelstub index 62a4c03..ae0d478 100755 --- a/data/initramfs/zz-kernelstub +++ b/data/initramfs/zz-kernelstub @@ -1,8 +1,26 @@ #!/bin/bash -KERNEL="/boot/vmlinuz-$1" -INITRD="$2" +# Grab OS information to figure out how to operate +source /etc/os-release + +# If ID_LIKE is empty, use ID instead. Base Distros don't always use ID_LIKE +if [[ "$ID_LIKE" == "" ]]; then + ID_LIKE="$ID" +fi + +# Determine how to handle kernel paths: +if [[ "$ID_LIKE" == *"fedora"* ]]; then + echo "Operating in Fedora-mode (initramfs, /boot)" + INITRD="/boot/initramfs-$1.img" + KERNEL="$2" +elif [[ "$ID_LIKE" == *"debian"* ]]; then + echo "Operating in Debian-mode (initrd.img, /symlinks)" + INITRD="/initrd.img" + KERNEL="/vmlinuz" +fi kernelstub \ --verbose \ - --preserve-live-mode + --preserve-live-mode \ + --kernel-path $KERNEL \ + --initrd-path $INITRD diff --git a/data/kernel/zz-kernelstub b/data/kernel/zz-kernelstub index f0c6c9f..ae0d478 100755 --- a/data/kernel/zz-kernelstub +++ b/data/kernel/zz-kernelstub @@ -1,8 +1,26 @@ #!/bin/bash -INITRD="/boot/initrd.img-$1" -KERNEL="$2" +# Grab OS information to figure out how to operate +source /etc/os-release + +# If ID_LIKE is empty, use ID instead. Base Distros don't always use ID_LIKE +if [[ "$ID_LIKE" == "" ]]; then + ID_LIKE="$ID" +fi + +# Determine how to handle kernel paths: +if [[ "$ID_LIKE" == *"fedora"* ]]; then + echo "Operating in Fedora-mode (initramfs, /boot)" + INITRD="/boot/initramfs-$1.img" + KERNEL="$2" +elif [[ "$ID_LIKE" == *"debian"* ]]; then + echo "Operating in Debian-mode (initrd.img, /symlinks)" + INITRD="/initrd.img" + KERNEL="/vmlinuz" +fi kernelstub \ --verbose \ - --preserve-live-mode + --preserve-live-mode \ + --kernel-path $KERNEL \ + --initrd-path $INITRD diff --git a/debian/changelog b/debian/changelog index b083220..794a401 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +kernelstub (4.0.1) bionic; urgency=medium + + * Add support for Fedora-like kernel setups + + -- Ian Santopietro Wed, 09 Aug 2023 17:18:19 -0600 + kernelstub (3.1.4) bionic; urgency=medium * Do live mode check immediately after parsing config diff --git a/kernelstub/kernel_option.py b/kernelstub/kernel_option.py index 12edd2a..f6dd41f 100755 --- a/kernelstub/kernel_option.py +++ b/kernelstub/kernel_option.py @@ -1,16 +1,38 @@ #!/usr/bin/python3 -from debian.changelog import Version +import logging + +log = logging.getLogger('kernelstub.kernel_option') + +try: + from debian.changelog import Version + def vCompare(version1:str, version2:str): + if Version(version1) > Version(version2): + return True + return False + +except ImportError: + from rpm import labelCompare + def vCompare(version1:str, version2:str): + if labelCompare(version1, version2) == 1: + return True + return False import os import os.path def options(path): items={} for name in os.listdir(path): + log.debug('Checking item %s', name) key = None if name.startswith("vmlinuz-"): + log.debug('Item %s is kernel-image', name) key = "kernel" elif name.startswith("initrd.img-"): + log.debug('Item %s is debian-style initrd', name) + key = "initrd" + elif name.startswith("initramfs"): + log.debug('Item %s is fedora-style initrd', name) key = "initrd" if key is None: @@ -18,31 +40,41 @@ def options(path): parts = name.split("-", 1) version = parts[1] + if version.endswith('.img'): + version = version[:-4] + log.debug('Item version is %s', version) if not version in items: + log.debug('Adding item %s to list', name) items[version] = {} items[version][key] = os.path.join(path, name) + log.debug('Found items: %s', items) return items def get_newest_option(opts): + log.debug('Getting latest boot item version') latest_version = None latest_option = None for version, option in opts.items(): + log.debug('Checking option %s', option) # If option is not complete, skip if 'kernel' not in option or 'initrd' not in option: + log.debug('%s does not contain all items, skipping...', version) continue # If this option is newer, store this option and continue - if latest_version is None or Version(version) > Version(latest_version): + if latest_version is None or vCompare (version, latest_version): + log.debug('%s is the latest version', version) latest_version = version latest_option = option return latest_option, latest_version def latest_option(path): + log.debug('Checking for boot items in %s', path) opts = options(path) latest_option, latest_version = get_newest_option(opts) @@ -52,6 +84,8 @@ def latest_option(path): if len(opts) > 0: previous_option, latest_version = get_newest_option(opts) + log.debug('Latest option: %s', latest_option) + log.debug('Previous option: %s', previous_option) return latest_option, previous_option if __name__ == "__main__": diff --git a/kernelstub/opsys.py b/kernelstub/opsys.py index 09abb87..47cb724 100644 --- a/kernelstub/opsys.py +++ b/kernelstub/opsys.py @@ -22,12 +22,13 @@ terms. """ -import platform +import logging, platform class OS(): name_pretty = "Linux" name = "Linux" + like = ["Linux"] version = "1.0" cmdline = ['quiet', 'splash'] kernel_name = 'vmlinuz' @@ -39,12 +40,16 @@ class OS(): initrd_path = '/initrd.img' old_kernel_path = '/vmlinuz.old' old_initrd_path = '/initrd.img.old' + os_mode = 'debian' def __init__(self): + self.log = logging.getLogger('kernelstub.Opsys') self.name_pretty = self.get_os_name() self.name = self.clean_names(self.name_pretty) + self.like = self.get_os_like() self.version = self.get_os_version() self.cmdline = self.get_os_cmdline() + self.set_os_mode() def clean_names(self, name): # This is a list of characters we can't/don't want to have in technical @@ -116,6 +121,21 @@ def get_os_version(self): if item.startswith('VERSION_ID='): version = item.split('=')[1] return self.strip_quotes(version[:-1]) + + def get_os_like(self): + os_release = self.get_os_release() + for item in os_release: + if item.startswith('ID_LIKE='): + like = item.split('=')[1] + like = self.strip_quotes(like) + return like.split() + + # Fallback on ID= if we aren't on a derivative + for item in os_release: + if item.startswith('ID='): + like = item.split('=')[1] + like = self.strip_quotes(like) + return like.split() def strip_quotes(self, value): new_value = value @@ -124,6 +144,12 @@ def strip_quotes(self, value): if value.endswith('"'): new_value = new_value[:-1] return new_value + + def set_os_mode(self): + if 'debian' in self.like: + self.os_mode = 'debian' + elif 'fedora' in self.like: + self.os_mode = 'fedora' def get_os_release(self): try: diff --git a/setup.py b/setup.py index 4095250..de04b40 100755 --- a/setup.py +++ b/setup.py @@ -73,7 +73,7 @@ def run(self): run_pyflakes3() setup(name='kernelstub', - version='3.1.4', + version='4.0.1', description='Automatic kernel efistub manager for UEFI', url='https://launchpad.net/kernelstub', author='Ian Santopietro',