This commit is contained in:
zj
2026-02-12 04:16:17 +08:00
parent 204e38b8d9
commit 116dfee22b

View File

@@ -1342,13 +1342,28 @@ def _manual_install_efi_files(mount_point: str, efi_target: str, efi_grub_file:
# 构建 chroot 内的输出路径 # 构建 chroot 内的输出路径
chroot_output_path = f"/boot/efi/EFI/{bootloader_id}/{efi_grub_file}" 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 分区,使用 '(<device>)/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 文件 # 尝试使用 grub-mkimage 生成 EFI 文件
chroot_cmd_prefix = ["sudo", "chroot", mount_point] chroot_cmd_prefix = ["sudo", "chroot", mount_point]
mkimage_cmd = chroot_cmd_prefix + [ mkimage_cmd = chroot_cmd_prefix + [
"grub2-mkimage", "grub2-mkimage",
"-o", chroot_output_path, "-o", chroot_output_path,
"-O", efi_target, "-O", efi_target,
"-p", "/boot/grub2", "-p", grub_prefix,
] + modules.split() ] + modules.split()
success, _, stderr = run_command( 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('/')) host_output_path = os.path.join(mount_point, chroot_output_path.lstrip('/'))
if success and os.path.exists(host_output_path): if success and os.path.exists(host_output_path):
log_success(f"✓ 成功生成 EFI 文件: {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: else:
log_error(f"生成 EFI 文件失败: {stderr}") log_error(f"生成 EFI 文件失败: {stderr}")
return False return False
@@ -2519,8 +2566,65 @@ def chroot_and_repair_grub(mount_point: str, target_disk: str,
log_warning(f"查找内核文件失败: {e}") log_warning(f"查找内核文件失败: {e}")
if kernel_files and root_uuid: 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
if boot_uuid:
# 独立 /boot 分区配置 - 需要先搜索 /boot 分区
grub_cfg_content = f"""# Minimal GRUB config generated by BootRepairTool 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 timeout=5
set default=0 set default=0
@@ -2538,7 +2642,7 @@ menuentry 'CentOS Linux (Auto)' {{
insmod gzio insmod gzio
insmod part_gpt insmod part_gpt
insmod xfs 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 ''} initrd /{initramfs_files[0] if initramfs_files else ''}
}} }}