diff --git a/backend.py b/backend.py index ad07a4e..d8c9a99 100644 --- a/backend.py +++ b/backend.py @@ -1342,13 +1342,28 @@ def _manual_install_efi_files(mount_point: str, efi_target: str, efi_grub_file: # 构建 chroot 内的输出路径 chroot_output_path = f"/boot/efi/EFI/{bootloader_id}/{efi_grub_file}" + # 检测是否有独立的 /boot 分区 + has_separate_boot = os.path.ismount(os.path.join(mount_point, "boot")) + + # 确定正确的 prefix + # 对于独立 /boot 分区,使用 '()/grub2' 格式,让 GRUB 自动搜索 + # 或者使用 '/boot/grub2' 配合 search 命令 + if has_separate_boot: + # 独立 /boot 分区:使用相对路径,依赖 grub.cfg 中的 search 命令 + # 或者使用 '(,gpt2)/grub2' 格式指定分区 + grub_prefix = "/grub2" + log_info(f"检测到独立 /boot 分区,使用 prefix: {grub_prefix}") + else: + grub_prefix = "/boot/grub2" + log_info(f"使用标准 prefix: {grub_prefix}") + # 尝试使用 grub-mkimage 生成 EFI 文件 chroot_cmd_prefix = ["sudo", "chroot", mount_point] mkimage_cmd = chroot_cmd_prefix + [ "grub2-mkimage", "-o", chroot_output_path, "-O", efi_target, - "-p", "/boot/grub2", + "-p", grub_prefix, ] + modules.split() success, _, stderr = run_command( @@ -1361,6 +1376,38 @@ def _manual_install_efi_files(mount_point: str, efi_target: str, efi_grub_file: host_output_path = os.path.join(mount_point, chroot_output_path.lstrip('/')) if success and os.path.exists(host_output_path): log_success(f"✓ 成功生成 EFI 文件: {host_output_path}") + + # 对于独立 /boot 分区,创建一个辅助的 grub.cfg 来设置正确的 root + if has_separate_boot: + log_info("为独立 /boot 分区创建辅助 grub.cfg...") + helper_cfg_path = os.path.join(mount_point, f"boot/efi/EFI/{bootloader_id}/grub.cfg") + try: + helper_cfg = '''# Auto-generated by BootRepairTool for separate /boot partition +# This file sets the correct root and loads the main config + +# Search for the /boot partition by filesystem type and files +search --no-floppy --fs-uuid --set=root + +# If search fails, try common partition numbers +if [ "${root}" = "${prefix}" ]; then + # Try (hd0,gpt2) - common /boot partition + if [ -f (hd0,gpt2)/grub2/grub.cfg ]; then + set root=(hd0,gpt2) + set prefix=(hd0,gpt2)/grub2 + elif [ -f (hd0,2)/grub2/grub.cfg ]; then + set root=(hd0,2) + set prefix=(hd0,2)/grub2 + fi +fi + +# Load the main configuration +configfile ${prefix}/grub.cfg +''' + with open(helper_cfg_path, 'w') as f: + f.write(helper_cfg) + log_success(f"✓ 创建辅助 grub.cfg: {helper_cfg_path}") + except Exception as e: + log_warning(f"创建辅助 grub.cfg 失败: {e}") else: log_error(f"生成 EFI 文件失败: {stderr}") return False @@ -2519,8 +2566,65 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str, log_warning(f"查找内核文件失败: {e}") if kernel_files and root_uuid: + # 检测是否有独立 /boot 分区 + boot_uuid = None + try: + boot_mount_point = os.path.join(mount_point, "boot") + if os.path.ismount(boot_mount_point): + # 有独立 /boot 分区,获取其 UUID + success_uuid, uuid_out, _ = run_command( + ["sudo", "blkid", "-s", "UUID", "-o", "value", boot_mount_point], + "获取 /boot 分区 UUID", + timeout=10 + ) + if success_uuid: + boot_uuid = uuid_out.strip() + log_info(f"检测到独立 /boot 分区,UUID: {boot_uuid}") + except Exception as e: + log_warning(f"获取 /boot UUID 失败: {e}") + # 创建基本 grub.cfg - grub_cfg_content = f"""# Minimal GRUB config generated by BootRepairTool + if boot_uuid: + # 独立 /boot 分区配置 - 需要先搜索 /boot 分区 + grub_cfg_content = f"""# Minimal GRUB config generated by BootRepairTool +# For system with separate /boot partition + +set timeout=5 +set default=0 + +# Load necessary modules +insmod part_gpt +insmod xfs +insmod fat + +# Search for the /boot partition by UUID, then set root to the system root +search --no-floppy --fs-uuid --set=root {boot_uuid} +set prefix=($root)/grub2 + +menuentry 'CentOS Linux (Auto)' {{ + load_video + set gfxpayload=keep + insmod gzio + insmod part_gpt + insmod xfs + linux /{kernel_files[0]} root=UUID={root_uuid} ro rhgb quiet + initrd /{initramfs_files[0] if initramfs_files else ''} +}} + +menuentry 'CentOS Linux (Rescue)' {{ + load_video + set gfxpayload=keep + insmod gzio + insmod part_gpt + insmod xfs + linux /{kernel_files[0]} root=UUID={root_uuid} ro rescue + initrd /{initramfs_files[0] if initramfs_files else ''} +}} +""" + else: + # 无独立 /boot 分区配置 + grub_cfg_content = f"""# Minimal GRUB config generated by BootRepairTool + set timeout=5 set default=0 @@ -2538,7 +2642,7 @@ menuentry 'CentOS Linux (Auto)' {{ insmod gzio insmod part_gpt insmod xfs - linux /{kernel_files[0]} root=UUID={root_uuid} ro + linux /{kernel_files[0]} root=UUID={root_uuid} ro rhgb quiet initrd /{initramfs_files[0] if initramfs_files else ''} }}