GRUB (简体中文)/Tips and tricks (简体中文)

From ArchWiki


其它安装方式

安装到 U 盘

BIOS

假设 U 盘的第一个分区是 FAT32格式,其分区是/dev/sdy1

# mkdir -p /mnt/usb
# mount /dev/sdy1 /mnt/usb
# grub-install --target=i386-pc --debug --boot-directory=/mnt/usb/boot /dev/sdy
# grub-mkconfig -o /mnt/usb/boot/grub/grub.cfg

可以选择将配置备份到 grub.cfg

# mkdir -p /mnt/usb/etc/default
# cp /etc/default/grub /mnt/usb/etc/default
# cp -a /etc/grub.d /mnt/usb/etc
# sync; umount /mnt/usb

EFI

在你运行 grub-install 的时候使用 --removable 选项,就可以让 GRUB 把它的 EFI 映像写入到 /boot/efi/EFI/BOOT/BOOTX64.efi,这样启动固件就可以在没有 UEFI 启动条目的的情况下找到。

安装到分区上或者无分区磁盘上

警告: GRUB 极不推荐 将其安装到分区启动扇区或者无分区磁盘上(Grub Legacy 和 syslinux 相反)。这种安装方式不安全,当升级时可能会损坏。Arch 开发人员也 不支持 这种方式.

下面的命令将会将 GRUB 安装到分区扇区或者无分区磁盘(也称作超级软盘),或者安装到软盘上。下面例子中以 /dev/sdaX 作为 /boot 分区。

# chattr -i /boot/grub/i386-pc/core.img
# grub-install --target=i386-pc --debug --force /dev/sdaX
# chattr +i /boot/grub/i386-pc/core.img
注意:
  • /dev/sdaX 仅用作示例。
  • --target=i386-pcgrub-install 仅为 BIOS 系统安装。建议总是使用这个选项来排除 grub-install 命令中的模糊性。

你应该使用 --force 选项来启用对 blocklists(块列表)的支持,而不应该使用 --grub-setup=/bin/true,后者类似于单纯地生成 core.img

grub-install 会生成以下警告,来提醒你哪里有可能出现问题。

/sbin/grub-setup: warn: Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.
/sbin/grub-setup: warn: Embedding is not possible. GRUB can only be installed in this setup by using blocklists.
                        However, blocklists are UNRELIABLE and their use is discouraged.

不使用 --force 选项则可能会出现以下错误,并且 grub-setup 不会将启动代码安装到启动扇区上:

/sbin/grub-setup: error: will not proceed with blocklists

而指定了 --force,会出现:

Installation finished. No error reported.

grub-setup 默认不启用这个选项,是因为在分区或者无分区磁盘上,grub 依赖于嵌入分区引导扇区的块列表 (blocklists) 来定位 /boot/grub/i386-pc/core.img 和前缀目录 /boot/grub。而 core.img 在分区上的扇区位置很有可能随着分区文件系统的更改而变化(复制文件,删除文件等)。详情请参考 https://bugzilla.redhat.com/show_bug.cgi?id=728742https://bugzilla.redhat.com/show_bug.cgi?id=730915.

临时解决方案是给 /boot/grub/i386-pc/core.img 文件加“不可变”(immutable) 标志(按照上面提过的,使用 chattr 命令)。这样 core.img 文件的位置就不会变。只有当将 GRUB 安装到分区启动扇区或者无分区磁盘上时才需要给 /boot/grub/i386-pc/core.img 加上“不可变”标志,在安装到 MBR 或者单纯地生成 core.img 而不嵌入到其他引导扇区里的时候,就不用添加(正如上面所述)。

然而即使没有报错,生成的 grub.cfg 文件也不会包含正确的 UUID。参考 https://bbs.archlinux.org/viewtopic.php?pid=1294604#p1294604 。 要解决这个问题,使用如下命令:

# mount /dev/sdxY /mnt        #Your root partition.
# mount /dev/sdxZ /mnt/boot   #Your boot partition (if you have one).
# arch-chroot /mnt

现在,安装linux,然后:

# grub-mkconfig -o /boot/grub/grub.cfg

只生成 core.img

通过添加 --grub-setup=/bin/true 选项,grub-install 命令会填充 /boot/grub 文件夹并生成 /boot/grub/i386-pc/core.img,但是 不会 将 GRUB 启动引导代码嵌入到 MBR、MBR 后部区域或者分区引导扇区中。

# grub-install --target=i386-pc --grub-setup=/bin/true --debug /dev/sda
注意:
  • /dev/sda 仅是示例。
  • --target=i386-pcgrub-install 仅为 BIOS 系统安装。建议总是使用这个选项来排除 grub-install 命令中的模糊性。

生成后,Grub Legacy 或者 syslinux 就可以通过链式加载 GRUB 的 core.img 来间接加载 Linux 内核或者多启动内核了。参阅Syslinux (简体中文)#链式加载

图形化配置工具

  • grub-customizer — GRUB 或者 BURG 的 GTK 定制器
https://launchpad.net/grub-customizer || grub-customizer

视觉配置

GRUB 默认支持改变菜单外观。如果你没有初始化,请务必以视频模式 gfxmode 初始化 GRUB 图形终端 gfxterm。此视频模式由 GRUB 通过 gfxpayload 传递给 Linux 内核,任何视觉配置都需要这种模式才能够有效果。

设置帧缓冲分辨率

GRUB 既可以为自己,也可以为内核设定帧缓冲。现在已经不使用老的 vga= 配置了,推荐方法是在 /etc/default/grub 文件中按照下面的例子编辑,来设定宽度(像素)x高度(像素)x颜色深度

GRUB_GFXMODE=1024x768x32
GRUB_GFXPAYLOAD_LINUX=keep

可以指定多种分辨率,包括默认的 auto,所以建议你编辑成这个样:GRUB_GFXMODE=心仪的分辨率,后备分辨率比如 1024x768,auto。更多信息请见 GRUB gfxmode 文档gfxpayload 属性可以确保内核也保持该分辨率。

注意:
  • 只有显卡通过 VESA BIOS 拓展支持的模式才能用。要查看所支持的模式列表,安装 hwinfo 然后以 root 权限运行 hwinfo --framebuffer。或者进入 GRUB 命令行运行 videoinfo 命令。
  • 早期版本的 NVIDIA 专有驱动(使用显卡 GeForce GTX 970,驱动 nvidia 370 进行了测试)支持的 GRUB_GFXMODE 格式为 x-色深(例如 1920x1200-24,而不是 1920x1200x24)。这应该不会影响新的显卡和驱动。使用比较新的驱动的 Pascal 显卡(以 GeForce GTX 1060 显卡和 nvidia 381.22 驱动测试)没法使用上文建议的格式,而且会引发严重的问题,包括但不限于系统崩溃以及 hard lock。当前的驱动和显卡最好使用标准的 xx色深 格式来配置 GRUB_GFXMODE
  • 确保在修改完后运行 grub-mkconfig -o /boot/grub/grub.cfg

这种方法不管用的话,可以试试老的 vga= 方法。将它添加到 /etc/default/grub 文件中的 "GRUB_CMDLINE_LINUX_DEFAULT=" 一行就行了。比如 "GRUB_CMDLINE_LINUX_DEFAULT="quiet splash vga=792" 可以将系统的分辨率设定为 1024x768

915resolution 破解

有些时候,Intel 显卡无法通过 # hwinfo --framebuffervbeinfo 显示你需要的分辨率。这种情况下,你可以使用 915resolution 破解。这种破解会临时性的修改显卡 BIOS 来添加所需的分辨率。详情请参考915resolution 主页。这个包可以在这里找到:915resolutionAUR

首先,找一个你想要修改的视频模式。为此需要在 GRUB 命令行模式下运行:

sh:grub> 915resolution -l
Intel 800/900 Series VBIOS Hack : version 0.5.3
[...]
Mode 30 : 640x480, 8 bits/pixel
[...]

然后,使用 1440x900 分辨率覆盖 Mode 30

/etc/grub.d/00_header
[...]
915resolution 30 1440 900  # Inserted line
set gfxmode=${GRUB_GFXMODE}
[...]

最后按照之前描述的方式设置 GRUB_GFXMODE,再重新生成 GRUB 配置文件,重启并测试是否生效。

背景图像和点阵字体

GRUB 原生支持设置背景图像和 pf2 格式的点阵字体。grub 包中包含了 unifont 字体,名为unicode.pf2,(也有可能只包含名为 ascii.pf2 的ASCII字符字体),运行pacman -Ql grub | grep pf2来得到对应的文件路径。

在载入正确的模块之后,GRUB 支持的图像格式有 tga, png 和 jpeg。所支持的最大图像分辨率跟硬件有关。

请确保你已经设定了合适的帧缓冲分辨率

按如下方式编辑 /etc/default/grub

GRUB_BACKGROUND="/boot/grub/myimage"
#GRUB_THEME="/path/to/gfxtheme"
GRUB_FONT="/path/to/font.pf2"
注意: 如果你将 GRUB 安装在单独的分区上,grub.cfg 文件中会自动将 /boot/grub/myimage 改成 /grub/myimage

需要重新生成 grub.cfg 来让修改起作用。如果成功添加了背景图片,用户会在运行命令的终端中看到 "Found background image..."。如果句话没有出现,你设定的图像信息可能没有成功添加进 grub.cfg 文件。

如果图像没有正确显示,执行如下检查:

  • /etc/default/grub 文件中,图像的路径和名字要正确
  • 图像的大小和格式要合适 (tga, png, 8-bit jpg)
  • 图像需要以 RGB 模式存储,而且没有索引
  • /etc/default/grub 文件里面开启了 console 模式
  • 需要执行 grub-mkconfig 命令以将图像信息写入 /boot/grub/grub.cfg 文件
  • grub-mkconfig 脚本不会对 grub.cfg 文件中所写的文件名添加引号,所以要确保这些名字里没有空格

主题

下面的例子将展示如何使用 GRUB 包里面的 Starfield 主题:

编辑 /etc/default/grub

GRUB_THEME="/usr/share/grub/themes/starfield/theme.txt"

需要重新生成 grub.cfg 来让修改起作用。如果配置成功的话,在重生成配置过程中,会在终端里出现 Found theme: /usr/share/grub/themes/starfield/theme.txt

一旦使用了主题,你设置的背景图像通常就不起作用了。

菜单颜色

GRUB 支持设置菜单颜色。可使用的颜色能从 GRUB 手册里面找到。示例如下:

编辑 /etc/default/grub

GRUB_COLOR_NORMAL="light-blue/black"
GRUB_COLOR_HIGHLIGHT="light-cyan/blue"

隐藏菜单

GRUB 特性之一就是支持隐藏/跳过菜单,可以在需要的时候按 Esc 来取消隐藏/跳过。同时还支持设置是否显示 timeout 计时器。

按照你的想法来编辑 /etc/default/grub。添加下面的几行可以启动这个功能,其中计时器被设定为 5 秒钟,而且可以被用户看到:

GRUB_TIMEOUT=5
GRUB_TIMEOUT_STYLE='countdown'

GRUB_TIMEOUT 是设置显示菜单前等待几秒。

禁用 framebuffer

使用 NVIDIA 私有驱动的用户可能希望禁用 GRUB 的 framebuffer,因为它会导致驱动错误。

要禁用 framebuffer,只要在 /etc/default/grub 中取消下面这行的注释:

GRUB_TERMINAL_OUTPUT=console

如果你想保留 GRUB 的 framebuffer,解决方法是在 GRUB 载入内核前进入文字模式。可以通过在 /etc/default/grub 中进行如下修改:

GRUB_GFXPAYLOAD_LINUX=text

通过 GRUB 直接启动 ISO9660 映像文件

GRUB 支持通过 loopback 设备直接从 ISO 映像启动,例如参考 Multiboot USB drive#Using GRUB and loopback devices

用密码保护 GRUB 菜单

警告: 如果有人能对你的机器进行物理上的访问,而且可以使用 Live USB 或磁盘启动(例如 BIOS 允许从外接磁盘启动),而 /boot 又处于一个没有加密的分区上面,那他就可以非常简单地通过编辑 GRUB 设置文件来绕过下面的这些。参考GRUB (简体中文)#/boot 加密Security (简体中文)#磁盘加密

如果你想禁止其他人改变启动参数或者使用 GRUB 命令行,可以给 GRUB 的配置文件关联一个用户名/密码。只需 运行 grub-mkpasswd-pbkdf2,输入密码然后确认:

grub-mkpasswd-pbkdf2
[...]
Your PBKDF2 is grub.pbkdf2.sha512.10000.C8ABD3E93C4DFC83138B0C7A3D719BC650E6234310DA069E6FDB0DD4156313DA3D0D9BFFC2846C21D5A2DDA515114CF6378F8A064C94198D0618E70D23717E82.509BFA8A4217EAD0B33C87432524C0B6B64B34FBAD22D3E6E6874D9B101996C5F98AB1746FE7C7199147ECF4ABD8661C222EEEDB7D14A843261FFF2C07B1269A

修改/etc/grub.d/40_custom的权限以确保只有root能够查看该文件的内容,然后将下面的内容添加到此文件:

/etc/grub.d/40_custom
set superusers="用户名"
password_pbkdf2 用户名 密码

这里的 密码 是由 grub-mkpasswd_pbkdf2 所生成的那个字符串。

然后重新生成主配置文件,现在你的 GRUB 命令行、启动参数和所有的启动条目都得到保护了。

可以参考 GRUB 手册中的 "Security" 部分来将设置放宽或者针对多用户进行更复杂的定制。

只针对编辑 GRUB 和控制台选项进行密码保护

对一个菜单条目添加 --unrestricted 选项将会允许所有的用户启动这个操作系统,但却不能修改这个条目,也不能进入 GRUB 命令行控制台。 只有超级用户或者由 --user 开关指定的用户才能修改这个菜单条目。

/boot/grub/grub.cfg
menuentry 'Arch Linux' --unrestricted --class arch --class gnu-linux --class os ...

Tango-inaccurate.pngThe factual accuracy of this article or section is disputed.Tango-inaccurate.png

Reason: /etc/grub.d/10_linux 文件不应该被手工编辑,每次升级 grub 包都会自动把它覆盖掉。 (Discuss in Talk:GRUB (简体中文)/Tips and tricks (简体中文))

要给 Linux 启动条目添加 --unrestricted,可以修改 /etc/grub.d/10_linux 文件开头的 CLASS 变量。

/etc/grub.d/10_linux
CLASS="--class gnu-linux --class gnu --class os --unrestricted"

在没有按着 SHIFT 键时隐藏 GRUB 界面

为了获取更快的启动速度,而不用等 GRUB 倒计时,可以命令 GRUB 在启动时隐藏目录,仅在 Shift 被按住的时候才显示。

将如下行添加到/etc/default/grub来启动这个功能:

 GRUB_FORCE_HIDDEN_MENU="true"

然后创建/etc/grub.d/31_hold_shift 文件并写入以下链接中的内容:[1],给它可执行权限,然后重新生成主配置文件:

# chmod a+x /etc/grub.d/31_hold_shift
# grub-mkconfig -o /boot/grub/grub.cfg
注意: 这个设置使用 keystatus 来检测按键事件,所以可能在某些机器上不能用。

将 UUID 和基础脚本结合使用

如果你想要使用 UUID 来避免不可靠的 BIOS 设备命名或者正在研究 GRUB 语法,这里有个使用了 UUID 的启动菜单项,和一个让 GRUB 使用你系统中正确的磁盘分区的小脚本。如果你想要将其移植到自己的系统上,只需要把 UUID 改成你的系统上的就行了。这个例子假设系统的 boot 和 root 文件系统是在不同的分区上,如果你还有其他分区,请相应地修改 GRUB 设置。

menuentry "Arch Linux 64" {
    # Set the UUIDs for your boot and root partition respectively
    set the_boot_uuid=ece0448f-bb08-486d-9864-ac3271bd8d07
    set the_root_uuid=c55da16f-e2af-4603-9e0b-03f5f565ec4a

    # (Note: This may be the same as your boot partition)

    # Get the boot/root devices and set them in the root and grub_boot variables
    search --fs-uuid $the_root_uuid --set=root
    search --fs-uuid $the_boot_uuid --set=grub_boot

    # Check to see if boot and root are equal.
    # If they are, then append /boot to $grub_boot (Since $grub_boot is actually the root partition)
    if [ $the_boot_uuid == $the_root_uuid ] ; then
        set grub_boot=($grub_boot)/boot
    else
        set grub_boot=($grub_boot)
    fi

    # $grub_boot now points to the correct location, so the following will properly find the kernel and initrd
    linux $grub_boot/vmlinuz-linux root=/dev/disk/by-uuid/$the_root_uuid ro
    initrd $grub_boot/initramfs-linux.img
}

多个启动条目

取消子菜单

如果你安装了多个内核,比如说 linux 和 linux-lts,那么 grub-mkconfig 默认会把他们分成一组建立一个子菜单。如果你不想这样,可以在 /etc/default/grub 文件里添加下面这行来回到仅有一个菜单的情形:

 GRUB_DISABLE_SUBMENU=y

调用之前的启动条目

GRUB 能够记住你最近一次使用的启动项,并且在下次启动时将其作为默认项。当你使用多个内核或操作系统时(比如当前的 Arch 和一个用来做后备选项的 LTS 内核),这个特性很有用。要开启这个功能,编辑 /etc/default/grub 中的 GRUB_DEFAULT 选项:

GRUB_DEFAULT=saved

上面的命令会告诉 GRUB 使用记住的启动项为默认启动项。要想让 GRUB 记住当前选择的启动项,将下面的行添加到 /etc/default/grub

GRUB_SAVEDEFAULT=true

仅当 /boot 不是 btrfs 文件系统的时候才能用,因为 GRUB 没法对 btrfs 进行写入操作。但它会生成一个容易误导人的错误信息:"sparse file not allowed. Press any key to continue."

注意: 手动添加启动项到 /etc/grub.d/40_custom/boot/grub/custom.cfg中,比如添加 Windows 启动项,需要先添加savedefault选项。

修改默认菜单条目

可以通过修改 /etc/default/grub 中的 GRUB_DEFAULT 值来改变默认启动项:

使用菜单标题:

GRUB_DEFAULT='Advanced options for Arch Linux>Arch Linux, with Linux linux'

使用数字编号:

 GRUB_DEFAULT="1>2"

GRUB 启动项序号从 0 开始计数,0 代表第一个启动项,也是上述选项的默认值,1 表示第二个启动项,以此类推。主菜单和子菜单项之间用 > 隔开。

上面的例子启动的是主菜单项 'Advanced options for Arch Linux' 下子菜单的第三项。

自动启动非默认启动条目(仅一次)

如果你想在下一次启动的时候启动一个非默认的启动项,命令 grub-reboot 非常有用。当系统下一次启动时,GRUB 会自动载入这个命令后的第一个参数所指的那个启动项,而以后再次启动时,GRUB 会回到正常状态加载默认条目。这样就不用修改配置文件或者在启动时进行手动选择了。

注意: 这个功能需要在 /etc/default/grub 中设定 GRUB_DEFAULT=saved,然后重新生成grub.cfg;或者在手动生成的 grub.cfg 中, 使用 set default="${saved_entry}"

演奏一曲

通过修改 GRUB_INIT_TUNE 变量,你可以在启动时(在引导菜单显示之前)让扬声器播放音乐。比如要演奏柏辽兹《幻想交响曲》“妖魔夜宴”乐章片段(大管部分),你可以添加下面的设置:

GRUB_INIT_TUNE="312 262 3 247 3 262 3 220 3 247 3 196 3 220 3 220 3 262 3 262 3 294 3 262 3 247 3 220 3 196 3 247 3 262 3 247 5 220 1 220 5"

你可以通过创建以下文件,然后重新运行grub-mkconfig,添加一个菜单项来播放这些常见的GRUB_INIT_TUNE

/etc/grub.d/91_tune_demo
#!/bin/sh
exec tail -n +3 $0
menuentry "INIT_TUNE Demos" {
   echo "Close Encounters/5 Tone"
   play 480 900 2 1000 2 800 2 400 2 600 3
   echo "Fur Elise (note long)"
   play 480 420 1 400 1 420 1 400 1 420 1 315 1 370 1 335 1 282 3 180 1 215 1 282 1 315 3 213 1 262 1 315 1 335 3 213 1 420 1 400 1 420 1 400 1 420 1 315 1 370 1 335 1 282 3 180 1 215 1 282 1 315 3 213 1 330 1 315 1 282 3
   echo "Berlioz's extract from Sabbath Night of Symphonie Fantastique"
   play 312 262 3 247 3 262 3 220 3 247 3 196 3 220 3 220 3 262 3 262 3 294 3 262 3 247 3 220 3 196 3 247 3 262 3 247 5 220 1 220 5
   echo "Oldskool Batman tune"
   play 380 120 1 140 1 160 1 200 8 190 4
   echo "Legend of Zelda tune"
   play 12000 440 100 0 1 329 150 440 50 0 1 440 25 493 25 523 25 587 25 659 200
   echo "Super Mario"
   play 1000 334 1 334 1 0 1 334 1 0 1 261 1 334 1 0 1 392 2 0 4 196 2
   echo "Super Mario Alternate"
   play 480 165 2 165 2 165 3 554 1 587 1 554 2 370 1 554 1 523 2 349 1 523 1 494 3 165 2 165 2 165 2
   echo "Mario Mushroom"
   play 1750 523 1 392 1 523 1 659 1 784 1 1047 1 784 1 415 1 523 1 622 1 831 1 622 1 831 1 1046 1 1244 1 1661 1 1244 1 466 1 587 1 698 1 932 1 1175 1 1397 1 1865 1 1397 1
   echo "Star Wars Imperial Death March"
   play 480 440 4 440 4 440 4 349 3 523 1 440 4 349 3 523 1 440 8 659 4 659 4 659 4 698 3 523 1 415 4 349 3 523 1 440 8
   echo "My Little Pony"
   play 2400 587 18 554 4 587 8 659 12 587 16 0 10 587 4 659 4 740 8 587 4 784 12 740 8 659 8 587 4 740 20 587 40
   echo "Wolfenstein 3D"
   play 300 131 1 196 1 196 1 196 1 294 1 196 1 294 1 196 1 131 1
   echo "Mall (Nothing Special)"
   play 180 440 1 554 1 659 1
   echo "Final Countdown"
   play 480 554 1 494 1 554 4 370 6 10 3 587 1 554 1 587 2 554 2 494 6
   echo "Xie-Jelei's Tune"
   play 2000 400 4 0 1 500 4 0 1 600 4 0 1 800 6
   echo "Random tune"
   play 480 220 1 277 1 330 1 440 1 185 1 220 1 277 1 370 1 294 1 370 1 440 1 587 1 330 1 415 1 494 1 659 1
   echo "Fleetwood Mac: The Chain Bass Riff (about 5 seconds)"
   play 304 55 5 0 1 55 1 62 1 65 2 62 1 55 1 49 1 55 1 62 2 41 8
   echo "Fleetwood Mac: The Chain Bass Riff Extended Version (WARNING, 25 SECONDS)"
   play 9120 55 150 0 30 55 30 62 30 65 60 62 30 55 30 49 30 55 30 62 60 41 360 0 120 55 150 0 30 55 30 62 30 65 60 62 30 55 30 49 30 55 30 62 60 41 360 0 60 41 12 42 3 43 3 44 3 45 3 46 6 47 3 48 3 49 6 50 3 51 3 52 6 53 3 54 3 55 150 0 30 55 30 62 30 65 60 62 30 55 30 49 30 55 30 62 60 41 240 82 20 0 10 82 26 0 4 82 26 0 4 82 26 0 4 82 56 0 4 82 60 55 150 0 30 55 30 62 30 65 60 62 30 55 30 49 30 55 30 62 60 41 360 0 120
}

更多相关信息可以查看 info grub -n play

为早期启动手动配置核心映像

如果你需要用一个特殊的键盘布局,或者要让 GRUB 环境访问 /boot 的配置步骤太过复杂,导致 GRUB 没法自动配置,你可以自己生成一个核心映像。在 UEFI 系统上,核心映像就是在启动时需要被固件载入的 grubx64.efi 文件。自己建立一个核心映像,就可以嵌入在早期启动过程中需要用到的所有模块,以及用来引导 GRUB 配置脚本。

首先,假设在一个 UEFI 系统中,我们需要在早期启动过程中载入 dvorak 键盘布局,以输入 /boot 加密分区的密码。

从生成的 /boot/grub/grub.cfg 文件中查看需要使用哪些模块来挂载加密的 /boot 分区。例如在你的 menuentry 一项中你应该看到类似下面的内容:

insmod diskfilter cryptodisk luks gcry_rijndael gcry_rijndael gcry_sha256
insmod ext2
cryptomount -u 1234abcdef1234abcdef1234abcdef
set root='cryptouuid/1234abcdef1234abcdef1234abcdef'

把这些模块都记下来,他们都应该被包含到核心映像里面。现在把你的键盘布局打包,它应该作为一个 memdisk 来嵌入到核心映像里:

# grub-kbdcomp -o dvorak.gkb dvorak
# tar cf memdisk.tar dvorak.gkb

现在创建需要在 GRUB 核心映像中使用的配置文件。这和正常的 GRUB 配置文件的格式是一样的,但只需要简单几行来载入 /boot 分区里的主配置文件就可以了:

early-grub.cfg
set root=(memdisk)
set prefix=($root)/

terminal_input at_keyboard
keymap /dvorak.gkb

cryptomount -u 1234abcdef1234abcdef1234abcdef
set root='cryptouuid/1234abcdef1234abcdef1234abcdef'
set prefix=($root)/grub

configfile grub.cfg

最后,生成核心映像,列出在 grub.cfg 文件中所需要的所有模块,再加上 early-grub.cfg 脚本中所使用的模块。上例中需要的模块有 memdisk, tar, at_keyboard, keylayoutsconfigfile

# grub-mkimage -c early-grub.cfg -o grubx64.efi -O x86_64-efi -m memdisk.tar diskfilter cryptodisk luks gcry_rijndael gcry_sha256 ext2 memdisk tar at_keyboard keylayouts configfile

生成的 EFI 核心映像可以和由 grub-install 所自动生成的一样使用,把它放在你的 EFI 分区,然后使用 efibootmgr 来启用它,或者依照你的系统固件来适当地进行配置。

另请参阅 Debian cryptsetup docs.

UEFI 延伸阅读

Tango-edit-clear.pngThis article or section needs language, wiki syntax or style improvements. See Help:Style for reference.Tango-edit-clear.png

Reason: 本节还可以更加简明有序。 (Discuss in Talk:GRUB (简体中文)/Tips and tricks (简体中文))

下面是关于通过 UEFI 安装 Arch 的其他相关信息。

另一种安装方法

Tango-view-fullscreen.pngThis article or section needs expansion.Tango-view-fullscreen.png

Reason: 将GRUB的所有文件放在ESP中的原因是什么? (Discuss in Talk:GRUB (简体中文)/Tips and tricks (简体中文))

通常,不管 EFI 系统分区挂载到哪,GRUB 都会将所有文件包括配置文件放到 /boot

如果你想将所有的文件放在 EFI 系统分区中,请给 grub-install 命令添加 --boot-directory=esp 选项:

# grub-install --target=x86_64-efi --efi-directory=esp --bootloader-id=grub --boot-directory=esp --debug

这个命令会将 GRUB 文件放在 esp/grub 而不是 /boot/grub 中。使用这个方法,请确保 grub-mkconfig 将配置文件放在与上面一样的目录里:

# grub-mkconfig -o esp/grub/grub.cfg

其他的配置是完全一样的。

UEFI 固件解决方案

请参阅 GRUB (简体中文)#缺省/后备启动路径

在固件启动管理器中创建 GRUB 条目

grub-install 会自动尝试在启动管理器中创建 GRUB 条目。如果没有成功,请参考 Unified Extensible Firmware Interface (简体中文)#efibootmgr,里面有如何使用 efibootmgr 创建启动目录条目的介绍。一般来说,这个问题都是因为你没有以 UEFI 模式启动 CD/USB 造成的。请参考 Unified Extensible Firmware Interface (简体中文)#从 ISO 创建 UEFI 可启动 USB

独立的 GRUB

本节假设你要为 x86_64 系统 (x86_64-efi) 创建一个独立的 GRUB。至于 32 位 (IA32) EFI 系统,适当地将 x86_64-efi 修改成 i386-efi 就可以了。

你可以建立一个 grubx64_standalone.efi 应用,这个 UEFI 应用将所有的模组嵌入应用内部的一个 tar 包中,所以就不需要使用单独的目录来存放 GRUB UEFI 模组和其他相关文件了。使用 grub 包里的 grub-mkstandalone 命令按照下面的方法操作来实现这个功能:

# echo 'configfile ${cmdpath}/grub.cfg' > /tmp/grub.cfg
# grub-mkstandalone -d /usr/lib/grub/x86_64-efi/ -O x86_64-efi --modules="part_gpt part_msdos" --locales="en@quot" --themes="" -o "esp/EFI/grub/grubx64_standalone.efi" "boot/grub/grub.cfg=/tmp/grub.cfg" -v

然后把 GRUB 配置文件复制到 esp/EFI/grub/grub.cfg,再使用 efibootmgresp/EFI/grub/grubx64_standalone.efi 创建一个 UEFI 启动管理器条目。

注意: 要让 ${cmdpath} 功能正常工作,--modules="part_gpt part_msdos" 选项(包含引号)是必要的。
警告: 如果你在填写 ${cmdpath} 的时候漏掉一个斜杠(比如把 (hd1,msdos2)/EFI/Boot 写成 (hd1,msdos2)EFI/Boot),你就会发现 grub.cfg 文件没法读取,然后被迫进入 GRUB 命令行中。如果出现这样的问题,检查 ${cmdpath} 设置成了什么 (echo ${cmdpath} ),然后手工载入配置文件(例如 configfile (hd1,msdos2)/EFI/Boot/grub.cfg)。

技术信息

GRUB EFI 文件总是要配置文件放在 ${prefix}/grub.cfg。当然在独立的 GRUB EFI 文件中,${prefix} 位于一个 tar 包的内部,嵌入在 GRUB EFI 文件自身之中(在 GRUB 环境中,这被称作 (memdisk))。这个 tar 包包含了所有在正常的 GRUB EFI 下存储在 /boot/grub 中的文件。

因为将 /boot/grub 中的内容嵌入到了独立映像的内部,它就不再对任何实际的(外部的) /boot/grub 有任何依赖了。因此在独立 GRUB EFI 文件的情形下 ${prefix}==(memdisk)/boot/grub,而且独立的 GRUB EFI 文件认为其配置文件存放于 ${prefix}/grub.cfg==(memdisk)/boot/grub/grub.cfg

因此要让独立的 GRUB EFI 文件读取存储在与 EFI 文件相同目录(在 GRUB 环境中用 ${cmdpath} 表示)下的外部 grub.cfg 时,我们创建一个简单的 /tmp/grub.cfg 来让 GRUB 使用 ${cmdpath}/grub.cfg 来做其配置文件。(在 (memdisk)/boot/grub/grub.cfg 中使用 configfile ${cmdpath}/grub.cfg 命令。)然后我们给 grub-mkstandalone 添加 "boot/grub/grub.cfg=/tmp/grub.cfg" 选项,把这个 /tmp/grub.cfg 文件复制到 ${prefix}/grub.cfg(事实上就是 (memdisk)/boot/grub/grub.cfg)。

这样,独立的 GRUB EFI 文件和这个 grub.cfg 可以存放在 EFI 系统分区中的任何一个目录里,只有它们处在同一个目录中就可以。这样它们就变得可移植了。

加快GRUB中的LUKS解密速度

警告: 在阅读本节之前,请确保你了解高熵密码的重要性。关于如何生成安全密码的信息可以在Wikipedia:Password strength找到。

在启动时,GRUB在某些情况下可能需要很长的时间来验证密码。这可能是由于PBKDF的迭代次数太多,你可以按以下方法检查:

# cryptsetup luksDump /dev/sda3

问题是,给定的密钥槽的迭代次数是在添加钥匙时产生的,这个迭代次数需要确保既足够高来防止暴力攻击,也要使你的计算机尽可能快的推导出密钥。然而,当GRUB启动时,它可能没有同样的计算资源在手,因此推导速度会大大降低。

如果你的密码本身能提供足够的熵来对抗常见的攻击,你可以降低迭代次数。

# cryptsetup luksChangeKey --pbkdf-force-iterations 1000 /dev/sda3

根据RFC 2898,建议至少1000次迭代,但如果可以的话,你应该尽可能使用更高的数值(攻击者的成本以及密钥推导的时间是线性扩展的)。

提示: GRUB依次尝试启用密钥槽。在添加密钥时,可以使用--key-slot选项来明确指定一个密钥槽。

参考资料