diff --git a/README.md b/README.md new file mode 100644 index 00000000..028b04b0 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +Related issue: #1025 +Post-update check for kernel updates on UEFI dual-boot systems with instructions +Adds a post-update check after kernel updates to detect potential bootloader +issues on UEFI dual-boot systems (Linux Mint + Windows) and provides the user +with instructions to recover safely. + +Motivation: Prevents unbootable system scenarios similar to reported incidents. + +Changes: +- Added `post_kernel_update_check()` called after kernel updates +- Detects UEFI + dual-boot with Windows +- Shows dialog with recovery instructions if potential issue detected diff --git a/usr/lib/linuxmint/mintUpdate/mintUpdate.py b/usr/lib/linuxmint/mintUpdate/mintUpdate.py index f256f942..58a80f62 100755 --- a/usr/lib/linuxmint/mintUpdate/mintUpdate.py +++ b/usr/lib/linuxmint/mintUpdate/mintUpdate.py @@ -25,6 +25,7 @@ import aptkit.simpleclient import checkAPT from multiprocess import Process, Queue +import subprocess gi.require_version('Gtk', '3.0') gi.require_version('Notify', '0.7') @@ -2305,6 +2306,50 @@ def refresh_updates(self): self.logger.write_error("Exception occurred in the refresh thread: %s" % str(sys.exc_info()[0])) self.set_status(_("Could not refresh the list of updates"), _("Could not refresh the list of updates"), "mintupdate-error-symbolic", True) + def system_is_uefi(): + return os.path.exists("/sys/firmware/efi") + + def windows_boot_entry_present(): + try: + output = subprocess.check_output(["efibootmgr"], universal_newlines=True) + return "Windows Boot Manager" in output + except: + return False + + def post_kernel_update_check(): + """ + Checks for potential boot issues on UEFI dual-boot systems + after kernel updates and shows instructions if needed. + """ + if not system_is_uefi(): + return + + if not windows_boot_entry_present(): + return + + try: + output = subprocess.check_output(["efibootmgr"], universal_newlines=True) + if "Linux Boot Manager" not in output: + show_recovery_dialog() + except: + show_recovery_dialog() + + def show_recovery_dialog(): + """ + Show a dialog to the user with instructions to fix bootloader issues + """ + message = ( + "Your system may not boot properly after this kernel update.\n\n" + "Recommended actions:\n" + "1. Boot from a live USB.\n" + "2. Install and run `boot-repair` or manually restore GRUB using efibootmgr.\n" + "3. Reboot and verify both Linux Mint and Windows boot entries.\n\n" + "See https://help.ubuntu.com/community/Boot-Repair for detailed instructions." + ) + show_warning_dialog( + title=_("Potential bootloader issue detected"), + message=message + ) def show_updates(self, updates): try: @@ -2346,6 +2391,7 @@ def show_updates(self, updates): sort_key = 2 tooltip = _("Kernel update") num_security += 1 + post_kernel_update_check() elif update.type == "unstable": sort_key = 7 tooltip = _("Unstable software. Only apply this update to help developers beta-test new software.")