From f3524c1f091b51fab18498a414979e12834b70e3 Mon Sep 17 00:00:00 2001 From: Thomas Castleman Date: Fri, 30 Dec 2022 23:39:38 -0500 Subject: [PATCH] add "Compatibility Mode" support, simplify loader.conf creation and setup --- DEBIAN/control | 2 +- usr/bin/system-installer.cxx | 2 +- usr/share/system-installer/UI/confirm.py | 14 +++ usr/share/system-installer/UI/main.py | 24 ++++- usr/share/system-installer/modules/master.py | 104 ++++++++++--------- 5 files changed, 91 insertions(+), 55 deletions(-) diff --git a/DEBIAN/control b/DEBIAN/control index 8d81c2d2..8a606d1e 100644 --- a/DEBIAN/control +++ b/DEBIAN/control @@ -1,5 +1,5 @@ Package: system-installer -Version: 2.4.4 +Version: 2.4.5 Maintainer: Thomas Castleman Homepage: https://github.com/drauger-os-development/system-installer Section: admin diff --git a/usr/bin/system-installer.cxx b/usr/bin/system-installer.cxx index c4c562da..34484dfb 100644 --- a/usr/bin/system-installer.cxx +++ b/usr/bin/system-installer.cxx @@ -46,7 +46,7 @@ using namespace std; -str VERSION = "2.4.4"; +str VERSION = "2.4.5"; str R = "\033[0;31m"; str G = "\033[0;32m"; str Y = "\033[1;33m"; diff --git a/usr/share/system-installer/UI/confirm.py b/usr/share/system-installer/UI/confirm.py index 618f2544..90538737 100755 --- a/usr/share/system-installer/UI/confirm.py +++ b/usr/share/system-installer/UI/confirm.py @@ -24,6 +24,7 @@ """Confirm UI for System Installer""" from __future__ import print_function from sys import argv, stderr +import auto_partitioner as ap import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk @@ -153,6 +154,19 @@ def __init__(self, settings): label12 = self._set_default_margins(label12) self.grid.attach(label12, 5, 5, 1, 1) + if ap.is_EFI(): + label31 = Gtk.Label() + label31.set_markup(" Compatibility Mode: ") + label31.set_justify(Gtk.Justification.CENTER) + label31 = self._set_default_margins(label31) + self.grid.attach(label31, 4, 6, 1, 1) + + label32 = Gtk.Label() + label32.set_markup(settings["COMPAT_MODE"]) + label32.set_justify(Gtk.Justification.CENTER) + label32 = self._set_default_margins(label32) + self.grid.attach(label32, 5, 6, 1, 1) + sep1 = Gtk.Separator.new(Gtk.Orientation.VERTICAL) self.grid.attach(sep1, 6, 2, 1, 6) diff --git a/usr/share/system-installer/UI/main.py b/usr/share/system-installer/UI/main.py index 46d386ca..6dd3f944 100755 --- a/usr/share/system-installer/UI/main.py +++ b/usr/share/system-installer/UI/main.py @@ -92,7 +92,8 @@ def __init__(self): "disks": {"1": None, "2": None, "3": None, - "4": None}}} + "4": None}}, + "COMPAT_MODE": ""} self.langs = {'Afar': "aa", 'Afrikaans': "af", 'Aragonese': "an", 'Arabic': "ar", 'Asturian': "ast", 'Belarusian': "be", @@ -1624,7 +1625,7 @@ def options(self, button): label1 = Gtk.Label() label1.set_markup(""" - Install third-party packages such as NVIDIA drivers if necessary\t\t + Install third-party packages, such as NVIDIA drivers, if necessary\t\t """) label1.set_justify(Gtk.Justification.LEFT) label1 = self._set_default_margins(label1) @@ -1662,15 +1663,30 @@ def options(self, button): self.login = self._set_default_margins(self.login) self.grid.attach(self.login, 1, 7, 2, 1) + if ap.is_EFI(): + label2 = Gtk.Label() + label2.set_markup(""" + Enable compatibility mode to improve installation reliability + with some UEFI systems. Does NOT require internet.""") + label2.set_justify(Gtk.Justification.LEFT) + label2 = self._set_default_margins(label2) + self.grid.attach(label2, 1, 8, 2, 1) + + self.compat_mode = Gtk.CheckButton.new_with_label("Enable Bootloader Compatibility Mode") + if self.data["COMPAT_MODE"] == 1: + self.compat_mode.set_active(True) + self.compat_mode = self._set_default_margins(self.compat_mode) + self.grid.attach(self.compat_mode, 1, 9, 2, 1) + button1 = Gtk.Button.new_with_label("Okay -->") button1.connect("clicked", self.options_next) button1 = self._set_default_margins(button1) - self.grid.attach(button1, 2, 8, 1, 1) + self.grid.attach(button1, 2, 10, 1, 1) button3 = Gtk.Button.new_with_label("<-- Back") button3.connect("clicked", self.main_menu) buton3 = self._set_default_margins(button3) - self.grid.attach(button3, 1, 8, 1, 1) + self.grid.attach(button3, 1, 10, 1, 1) self.show_all() diff --git a/usr/share/system-installer/modules/master.py b/usr/share/system-installer/modules/master.py index 25627862..341f31f7 100755 --- a/usr/share/system-installer/modules/master.py +++ b/usr/share/system-installer/modules/master.py @@ -26,7 +26,7 @@ """ from __future__ import print_function from sys import argv, stderr -import subprocess +import subprocess as subproc import multiprocessing import os from shutil import rmtree, copyfile @@ -145,16 +145,16 @@ def set_passwd(USERNAME, PASSWORD): if PASSWORD == "OEM": PASSWORD = "toor" if USERNAME != "drauger-user": - process = subprocess.Popen("chpasswd", + process = subproc.Popen("chpasswd", stdout=stderr.buffer, - stdin=subprocess.PIPE, - stderr=subprocess.PIPE) + stdin=subproc.PIPE, + stderr=subproc.PIPE) process.communicate(input=bytes(r"root:%s" % (PASSWORD), "utf-8")) - process = subprocess.Popen("chpasswd", + process = subproc.Popen("chpasswd", stdout=stderr.buffer, - stdin=subprocess.PIPE, - stderr=subprocess.PIPE) + stdin=subproc.PIPE, + stderr=subproc.PIPE) process.communicate(input=bytes(r"%s:%s" % (USERNAME, PASSWORD), "utf-8")) @@ -201,7 +201,7 @@ def set_keyboard(MODEL, LAYOUT, VARIENT): """ with open("/etc/default/keyboard", "w+") as xkb_default: xkb_default.write(xkb_file) - subprocess.Popen(["udevadm", "trigger", "--subsystem-match=input", + subproc.Popen(["udevadm", "trigger", "--subsystem-match=input", "--action=change"], stdout=stderr.buffer) def remove_launcher(USERNAME): @@ -221,7 +221,7 @@ def remove_launcher(USERNAME): def set_plymouth_theme(): """Ensure the plymouth theme is set correctly""" - subprocess.Popen(["update-alternatives", "--install", + subproc.Popen(["update-alternatives", "--install", "/usr/share/plymouth/themes/default.plymouth", "default.plymouth", "/usr/share/plymouth/themes/drauger-theme/drauger-theme.plymouth", @@ -230,11 +230,11 @@ def set_plymouth_theme(): "default.plymouth.grub", "/usr/share/plymouth/themes/drauger-theme/drauger-theme.grub"], stdout=stderr.buffer) - process = subprocess.Popen(["update-alternatives", "--config", + process = subproc.Popen(["update-alternatives", "--config", "default.plymouth"], stdout=stderr.buffer, - stdin=subprocess.PIPE, - stderr=subprocess.PIPE) + stdin=subproc.PIPE, + stderr=subproc.PIPE) process.communicate(input=bytes("2\n", "utf-8")) @@ -244,22 +244,22 @@ def install_kernel(release): # it's just easier and more reliable packages = ["linux-headers-" + release, "linux-image-" + release] install_command = ["dpkg", "--install"] - subprocess.check_call(["apt-get", "purge", "-y"] + packages, + subproc.check_call(["apt-get", "purge", "-y"] + packages, stdout=stderr.buffer) - subprocess.check_call(["apt-get", "autoremove", "-y", "--purge"], + subproc.check_call(["apt-get", "autoremove", "-y", "--purge"], stdout=stderr.buffer) packages = [each for each in os.listdir("/repo") if "linux-" in each] os.chdir("/repo") - subprocess.check_call(install_command + packages, stdout=stderr.buffer) + subproc.check_call(install_command + packages, stdout=stderr.buffer) os.chdir("/") -def install_bootloader(efi, root, release, distro): +def install_bootloader(efi, root, release, distro, compat_mode): """Determine whether bootloader needs to be systemd-boot (for UEFI) or GRUB (for BIOS) and install the correct one.""" if efi not in ("NULL", None, "", False): - _install_systemd_boot(release, root, distro) + _install_systemd_boot(release, root, distro, compat_mode) else: _install_grub(root) @@ -280,25 +280,25 @@ def _install_grub(root): redo = False os.mkdir("/boot/grub") try: - subprocess.check_call(["grub-mkdevicemap", "--verbose"], + subproc.check_call(["grub-mkdevicemap", "--verbose"], stdout=stderr.buffer) - except subprocess.CalledProcessError: + except subproc.CalledProcessError: redo = True - subprocess.check_call(["grub-install", "--verbose", "--force", + subproc.check_call(["grub-install", "--verbose", "--force", "--target=i386-pc", root], stdout=stderr.buffer) if redo: try: - subprocess.check_call(["grub-mkdevicemap", "--verbose"], + subproc.check_call(["grub-mkdevicemap", "--verbose"], stdout=stderr.buffer) - except subprocess.CalledProcessError as e: + except subproc.CalledProcessError as e: eprint("WARNING: GRUB device map failed to generate") eprint("The error was as follows:") eprint(traceback.format_exeception()) - subprocess.check_call(["grub-mkconfig", "-o", "/boot/grub/grub.cfg"], + subproc.check_call(["grub-mkconfig", "-o", "/boot/grub/grub.cfg"], stdout=stderr.buffer) -def _install_systemd_boot(release, root, distro): +def _install_systemd_boot(release, root, distro, compat_mode): """set up and install systemd-boot""" try: os.makedirs("/boot/efi/loader/entries", exist_ok=True) @@ -312,9 +312,9 @@ def _install_systemd_boot(release, root, distro): with open("/etc/environment", "a") as envi: envi.write("export SYSTEMD_RELAX_ESP_CHECKS=1") try: - subprocess.check_call(["bootctl", "--path=/boot/efi", "install"], + subproc.check_call(["bootctl", "--path=/boot/efi", "install"], stdout=stderr.buffer) - except subprocess.CalledProcessError as e: + except subproc.CalledProcessError as e: eprint("WARNING: bootctl issued CalledProcessError:") eprint(e) eprint("Performing manual installation of systemd-boot.") @@ -340,19 +340,19 @@ def _install_systemd_boot(release, root, distro): "/boot/efi/EFI/systemd/systemd-bootx64.efi") except FileExistsError: pass - with open("/boot/efi/loader/loader.conf", "w+") as loader_conf: - loader_conf.write(f"default {distro}\n") - loader_conf.write("timeout 5\nconsole-mode 1\neditor 1") - try: - subprocess.check_call(["chattr", "-i", "/boot/efi/loader/loader.conf"], - stdout=stderr.buffer) - except subprocess.CalledProcessError: - eprint("CHATTR FAILED ON loader.conf, setting octal permissions to 444") - os.chmod("/boot/efi/loader/loader.conf", 0o444) + # with open("/boot/efi/loader/loader.conf", "w+") as loader_conf: + # loader_conf.write(f"default {distro}\n") + # loader_conf.write("timeout 5\nconsole-mode auto\neditor 1") + # try: + # subproc.check_call(["chattr", "-i", "/boot/efi/loader/loader.conf"], + # stdout=stderr.buffer) + # except subproc.CalledProcessError: + # eprint("CHATTR FAILED ON loader.conf, setting octal permissions to 444") + # os.chmod("/boot/efi/loader/loader.conf", 0o444) install_command = ["dpkg", "--install"] packages = [each for each in os.listdir("/repo") if "systemd-boot-manager" in each] os.chdir("/repo") - depends = subprocess.check_output(["dpkg", "-f"] + packages + ["depends"]) + depends = subproc.check_output(["dpkg", "-f"] + packages + ["depends"]) depends = depends.decode()[:-1].split(", ") # List of dependencies depends = [depends[each[0]].split(" ")[0] for each in enumerate(depends)] @@ -364,35 +364,40 @@ def _install_systemd_boot(release, root, distro): if ((each1 in each) and (each not in packages)): packages.append(each) break - subprocess.check_call(install_command + packages, + subproc.check_call(install_command + packages, stdout=stderr.buffer) os.chdir("/") - subprocess.check_call(["systemd-boot-manager", "-e"], + if compat_mode: + subproc.check_call(["systemd-boot-manager", "--compat-mode=enable"], + stdout=stderr.buffer) + subproc.check_call(["systemd-boot-manager", "-e"], + stdout=stderr.buffer) + subproc.check_call(["systemd-boot-manager", "--apply-loader-config"], stdout=stderr.buffer) - subprocess.check_call(["systemd-boot-manager", "-r"], + subproc.check_call(["systemd-boot-manager", "-r"], stdout=stderr.buffer) - subprocess.check_call(["systemd-boot-manager", + subproc.check_call(["systemd-boot-manager", "--enforce-default-entry=enable"], stdout=stderr.buffer) # This lib didn't exist before we installed this package. # So we can only now import it import systemd_boot_manager systemd_boot_manager.update_defaults_file(distro + ".conf") - subprocess.check_call(["systemd-boot-manager", "-u"], + subproc.check_call(["systemd-boot-manager", "-u"], stdout=stderr.buffer) check_systemd_boot(release, root, distro) -def setup_lowlevel(efi, root, distro): +def setup_lowlevel(efi, root, distro, compat_mode): """Set up kernel and bootloader""" - release = subprocess.check_output(["uname", "--release"]).decode()[0:-1] + release = subproc.check_output(["uname", "--release"]).decode()[0:-1] install_kernel(release) set_plymouth_theme() __update__(91) eprint("\n ### MAKING INITRAMFS ### ") - subprocess.check_call(["mkinitramfs", "-o", "/boot/initrd.img-" + release], + subproc.check_call(["mkinitramfs", "-o", "/boot/initrd.img-" + release], stdout=stderr.buffer) - install_bootloader(efi, root, release, distro) + install_bootloader(efi, root, release, distro, compat_mode) sleep(0.5) os.symlink("/boot/initrd.img-" + release, "/boot/initrd.img") os.symlink("/boot/vmlinuz-" + release, "/boot/vmlinuz") @@ -404,7 +409,7 @@ def check_systemd_boot(release, root, distro): root_flags = "quiet splash" recovery_flags = "ro recovery nomodeset" # Get Root UUID - uuid = subprocess.check_output(["blkid", "-s", "PARTUUID", + uuid = subproc.check_output(["blkid", "-s", "PARTUUID", "-o", "value", root]).decode()[0:-1] # Check for standard boot config @@ -500,8 +505,8 @@ def _check_for_laptop(): Returns True if it is a laptop, returns False otherwise. """ try: - subprocess.check_call(["laptop-detect"]) - except subprocess.CalledProcessError: + subproc.check_call(["laptop-detect"]) + except subproc.CalledProcessError: return False return True @@ -522,7 +527,8 @@ def install(settings, distro): del processes_to_do[each] MainInstallation(processes_to_do, settings) handle_laptops(settings["USERNAME"]) - setup_lowlevel(settings["EFI"], settings["ROOT"], distro) + setup_lowlevel(settings["EFI"], settings["ROOT"], distro, + settings["COMPAT_MODE"]) verify(settings["USERNAME"], settings["ROOT"], distro) if "PURGE" in settings: purge_package(settings["PURGE"])