我发现,大部分玩linux的人,出现问题的主要原因都是卡在安装系统这个门槛上。因此,决定彻底的研究和解决这个问题,让大家能够愉快的使用linux,投入开源的怀抱。
本文假设你具备如下知识:
硬件开机需要经过自检过程,自检程序bios固化到主板里面,从bios时代 到uefi 的转变,让启动系统变得更加强大(虽然也不是很智能)。
CSM 兼容性支持模块,uefi兼容老bios的手段,应该关闭,因为这个会出现问题。
UEFI很多改进,但对我们关心的启动问题而言,它比BIOS进步的地方是:
启动管理器功能:
启动步骤:
windows 支持uefi的版本是从win7开始,记住只选64位。现在很多整合的启动u盘印象还是32位的,不建议使用。
命令工具虽然能够使用,但是不太友好,要求用户背指令,因此可以选择一些图形化的工具来辅助解决问题。
这一步用diskgenius操作比较舒服.下面用diskpart 演示一下:
diskpart
进入磁盘管理模式list disk
列出磁盘,可以查看磁盘信息:
我的磁盘都是Gpt格式的了,只有磁盘4不是,磁盘4是我刚插进用来演示的u盘.diskpart的使用逻辑是你想操作什么,要先选中该对象,从选中磁盘,到选中分区,一层一层进行.转换分区是对整个磁盘的分区表进行操作的,所以应该选中磁盘。
select disk 4
选中磁盘4.
convert gpt
将选中的磁盘转换为gpt分区表格式。
看来u盘是无法演示下去了。在磁盘管理模式用exit
可以退出.
那么用diskgenius继续演示:
对磁盘4右键菜单,选中“转换分区类型为GUID格式”这个菜单项,即是转换gpt的另一种说法。
遇到问题不要惊慌,都是很正常的。转换需要空间,怎么腾出空间?这个都是dg磁盘工具可以实现的功能。
用过磁盘工具的朋友都知道,磁盘是以一个陌生的单位来计算容量的,那就是扇区,那么一个扇区等于多少个字节呢?一般是512Byte,也就是半K,逼死强迫症。33除以2等于20k左右,非常小的一个容量需求。只要调整分区大小,前后腾出空间即可。
先划分1000mb空余在前端,100mb空余在后端,压压惊。
顺利转换后,新手朋友一定要学会观察信息,不要因为陌生就忽略:
可以看到磁盘类型变成gpt了,理论上,这时候你的磁盘就能被uefi识别,并用来引导。
但是,你应该建立一个专门用来放引导文件的分区,它叫esp分区,格式是非常通用的fat格式,因为不同系统支持的分区格式不相同,uefi不可能每一种都能操作,因此它就选择了最简单的分区格式,让操作系统们将引导文件放里面。
因为我们刚才预留了很多前端空间,这时候就派上用场了。右键选择磁盘4下面的F:分区,选择菜单:建立ESP/MSR分区:
因为刚才gpt分区表用了一点点,所以分了个998mb的esp分区。
最后是保存改动,一切才会生效。如果你误操作,可以别保存关闭,再打开重来一遍。
到此,磁盘转换完毕!
如果不复制启动文件到磁盘4的esp分区,是否就无法启动磁盘4上面的系统?
非也! 因为你可以在其他磁盘,甚至是主板上面的引导菜单(需要用工具建立)启动磁盘4。因此最关键是磁盘的gpt格式。那么esp分区相对一个磁盘来说它是怎样的作用呢?它是为了让该磁盘独立引导的时候,uefi可以在此找到bootx64.efi 文件。
esp默认是被系统隐藏的,diskpart可以解除这个限制:
同理,diskpart
进入磁盘工具,select disk 4
选择磁盘4,list partition
查看分区信息:
显示系统即esp分区,这时候应该先选中这个分区,然后才能进行操作:select par 2
,然后分配个z:盘符给它assign letter=z
。
这时候,你实际上可以访问它,但是默认权限不是管理员权限的,用管理员权限打开cmd,通过命令行来打开z:盘,或者,直接用diskgenius来操作。
其实你需要分配一个盘符,也能通过diskgenius操作esp盘,问题你只能手工复制相关文件,其实还是用命令行高效,而且有保证一些,因为你不清楚下一代windows会怎么修改启动文件的配置,用命令行可以保证你的操作兼容性更高一些。
重要命令:
bcdboot d:\windows /l zh-cn /s z: /f UEFI /addlast /d /v
基本格式就是bcdboot 系统 /l 语言 /s esp所在分区 /f uefi启动 /addlast 添加菜单项放在后面 /d 保留默认启动项 /v输出详细信息。当然这里面有些参数不是必要的。
这个命令最终的结果是什么?
他就是复制了 bootx64.efi、bcd、bootmgfw.efi、bootmgr.efi、memtest.efi还有一堆语言包。
前面也说了,最关键的是 bootmgfw.efi和bcd。bootx64.efi 只是一个占位文件,bcdboot直接就是把bootmgfw.efi改名成bootx64.efi而已。其他都不是关键的。
但是,放的位置是至关重要!
只需要如此安放,即可完成启动文件的配置了。
但是,uefi怎么知道我们需要启动哪个硬盘的esp分区呢?经过我测试,如果是外置的u盘,uefi会自动增加启动项,如果是内置硬盘,uefi就比较傻,这里面的设计似乎不是很完善,也许不同厂家有不同的设计方案,所以下一步,我们来实现怎样增加启动选项在主板中,彻底解决些模糊的地方。
这里应该明确两个引导菜单,一个是主板里面的,我的主板需要按F11才会弹出这个菜单,或者直接进入bios内部设置启动顺序。这个我称为主板引导菜单。
另一个是操作系统生成的引导菜单,在这里就是存放在esp分区里面的bcd文件。这个bcd是windows专用的引导菜单,如果用linux,它可能用的是grub的引导菜单。windows的引导菜单是不会理会linux的,非常傲娇,而linux的grub引导菜单则可以引导windows。
明显的,我们如果操作的是主板的引导菜单,无疑是最高层级的,因为它是uefi自身的引导菜单,而不是某种操作系统自带的。只要兼容uefi,不管是linux,或者windows,或者chinaOS都没问题的。
然后,我这里首先介绍的是怎么操作bcd引导菜单:
bcdedit /store z:\efi\microsfot\boot\bcd
这里的bcdedit就是操作bcd菜单的系统自带工具,/store是指定bcd文件,如果你不是修改当前系统的。整个命令会列出bcd菜单的内容:
第一条{bootmgr}是windows 启动管理器,即bootmgfw.efi。 第二条是windows 启动加载器,即\windows\system32\winload.efi。比如你装了两个windows,一个在c盘,一个在d盘,那么两个系统的加载器就分别在自己的windows目录下面。而device指定了盘符。
总的流程就是bootmgfw.efi 打印出引导菜单bcd,用户选择某个菜单项,它即调用该项的系统加载器来装载系统。
明白这个过程,对于若干个windows来说,我们只需要添加对应的菜单项即可,用bcdboot 可以实现,因为它添加新菜单项并不会覆盖旧的bcd,而会智能处理每一次的变更。
如果不想使用命令行,可以借助bootice这个工具来编辑菜单,新版1.3.4甚至还能修改主板的菜单,非常强大。
选择修改z:\efi\microsoft\boot\bcd 引导菜单。
我现在c盘里面有一个win10,d盘有个win7,e盘有个deepin,现在我增加win10的启动项:
发现还支持所谓的实模式,试一下能不能加载deepin:
选择uefi页,修改启动序列,可以对主板菜单做修改,推荐这个方式去实现引导!:
好,uefi引导windows部分到此结束。
因为,linux一般能够比较好的协调和windows的并存关系,当你正确安装windows(用第三节的知识),linux的安装就是水到渠成的事情。
如果是全新安装,同样的,进入bios改成uefi启动,关闭csm兼容模式,关闭安全启动secure boot。
注意磁盘分区表格式为gpt。安装镜像版本比较新,能够支持uefi,然后正常安装即可。
如果你想深入定制linux的引导,请参考第七节 grub的使用说明。
有一点需要明确,u盘,光盘等即插即用设备,它的引导方式和硬盘有所区别。
尤其是光盘,它使用的是专门的光盘格式,即.iso结尾的镜像,而硬盘的镜像是没有这种法则的。
当然,现在(2019年)我们更加常见的设备是u盘。因此我们主要是和各种硬盘镜像,或者虚拟机硬盘镜像打交道。
当然,我们下载的镜像,却经常是.iso结尾的。因此也要求我们对此有所掌握。
硬盘分区结构有bmr和gpt两种,文件系统有windows 的 fat,ntfs;linux 的ext;苹果Mac OS的hfs。
光盘文件格式:
以linux为例:
光盘也好,u盘也好,总的来说,只需要借助工具生成可引导格式便可。对u盘来说,基本就是复制硬盘启动的思路,只有细微差别。对于光盘来说,需要满足iso格式的特殊规定,启动区空间和容量有所限制。
所谓可引导设备,说到底就是让uefi能够在特定位置读取里面的引导管理器,如bootx64.efi等文件,所做的必要布局而已。
对不同文件系统之间的数据操作过程是:
整体来说,数据操作就是简单的复制文件,而启动镜像的制作在准备数据文件的基础上,使用特定的制作工具,加特定的引导文件即可。
其实可以直接对u盘进行操作。如第三节演示的那样。但这里还是按照 先准备数据,启动文件,然后制作镜像,然后写入u盘这个思路进行演练。
以debian linux 最小镜像mini.iso为例,下载地址:http://ftp.nl.debian.org/debian/dists/stretch/main/installer-amd64/current/images/netboot/ 。
这是一个可以启动的光盘镜像,里面的内容是这样的:
当然,我们可以简单的提取文件,但是linux支持挂载iso文件系统,先挂载了再操作也是挺方便的。
sudo apt install udftools #安装udf光盘文件系统工具套件,安装完就有mkfs.udf了
sudo apt install mkisofs #安装通用光盘制作工具,比上一个强大,建议使用
file mini.iso
显示这个镜像并非光盘镜像,而是一个硬盘镜像,很多时候下载的镜像,虽然是iso结尾,但是却并不一定是光盘文件系统的,这有点奇葩。
为了提取里面的引导文件,我想提取里面的启动数据,因此就必须要挂载这个硬盘镜像,根据信息,是这个硬盘有三个分区,如果你用mount
直接挂载它,是挂载第一个分区,其他两个分区需要使用losetup
命令。
这里需要了解一下linux的设备和文件系统基本知识。
linux中的设备被虚拟成一个文件,放在/dev/目录下,通过一个/dev/loop# (#是数字)的设备,可以将一个普通文件模拟成硬盘,然后对该文件进行读写,分区,格式化文件系统等操作。
因此,通过这个手段,可以不刻录到实际设备上,也能够装载镜像文件。但是如何读取镜像中的分区信息,并挂载其中一个分区呢?这就是losetup工具的能力。
losetup -f # 查看还没有被使用的loop设备
fdisk -l mini.iso #fdisk是一个分区工具,这命令列出镜像的分区情况
sudo losetup -o 122880 /dev/loop0 mini.iso #根据信息,扇区240开始是efi分区,每个扇区512字节,240*512=122880 ,设置装载的偏移开始点在这里。然后这个loop0就是建立在该分区上的虚拟设备了
sudo mount /dev/loop0 mini #将设备装载入本地文件系统中的mini目录,mini目录内的内容就是分区的内容。然后就能通过普通的文件操作,执行数据任务了。
这个分区只有一个文件:efi/boot/bootx64.efi . 接下来就是准备好我们要建立的镜像的内容。
总结一下,因为这部分的操作细节和顺序很重要!很容易出错。如果你想打开镜像的某一个分区:
如果你想制作镜像:
dd
建立一个大文件,可以装载整个文件系统大小的。fdisk
或者 gdisk
分区,设置好分区类型(注意),记住每个分区的起始位置,和计算偏移量(字节)losetup
装载指定偏移位置(字节)的镜像到设备/dev/loop#,记住这个设备和分区的对应关系mkfs -t 文件系统
格式化设备,即是格式化了对应分区mount
装载设备内容到指定的目录下,然后就可以复制到这个分区了。EDK(EFI开发工具包)子项目。shell即命令行。uefi shell很重要,因为不需要启动进入系统,它就可以让你执行很多命令,从而可以修复引导程序。
memmap 1> Foo.txt #标准输出重定向,unicode编码
memmap >a Foo.txt #标准输出重定向,ASCII编码
memmap 2>> Foo.txt #错误输出追加,unicode编码
shell 命令:
dmen
drivers
dh
dmpstore
devtree
help
?
err 错误级别
devices
map 映射
guid 显示guid
connect
mount 块设备安装文件系统
pci 配置pci
disconnect
load 加载驱动
mm 设置mem/io/pci
openinfo
unload 卸载映像
reset 重置系统
reconnect
loadbmp
stall 停顿
drvcfg
nshell
getmtc
drvdiag
ver 版本
hexedit
loadpcirom
memmap 内存映射
Setsize
bcfg 显示配置
Set 设置环境变量
Dblk 显示块设备
alias 别名
shell 内部命令:
help
dh 显示句柄
map
guid
alias
set
exit
cd 进入目录
type
shell 外部命令:
attrib 属性
date 时间
edit
time
break
cls 清屏
mode
vol
ls 列出文件
rm 删除
cp 复制
mv 移动
mkdir 新建文件夹
type
alias
set
touch
.nsh 批处理命令:
echo 回显
exit 退出
for
goto
if
pause 暂停
startup.nsh 自动运行批处理
技巧:
命令:
cp
复制/rm
删除/del
删除/ls
显示文件列表/comp
比较文件内容/edit
编辑/eficompress
压缩/efidecompress
解压缩/mkdir
新建文件夹/mv
移动/parse
检索内容/setsize
设置文件大小/touch
跟新文件时间/type
显示内容/map -r
:刷新识别的fat文件系统BLK0:
:进入BLK0盘cd
: 进入目录connect 17 19
将19驱动连接到17设备dblk blk0 2 1
打印块设备第2块的1块内容devices
输出设备列表:1.设备编号/2.设备类型(R.控制器、B.总控制器、D.设备控制器)/3.配置协议/4.诊断协议/5.父控制器数/6.设备数量/7.子控制器数/8.设备名称devtree
树状图输出设备dh 52
显示52号设备信息。-p 协议,-d 显示驱动, -v 详细信息。disconnect
断开驱动dmem 2 1
显示内存地址2的1byte内容drivers
驱动列表:1.驱动编号/2.版本/3.类型/4.配置协议/5.驱动协议/6.设备数/7.子设备数/8.驱动名称/9.设备路径ifconfig -l
列出网络配置load file
加载驱动,-nc 不自动连接设备。memmap
内存信息openinfo 90
显示和句柄关联的信息pci
列出pci信息:1.段号/2.总线号/3.设备号/4.功能号/名称-类别 设备smbiosview
显示smbios信息vol
文件系统的卷信息grub 是开源世界一个流行的引导管理器,它有点过于强大,不但能引导各种各样的linux,还能引导windows。即支持bmr又支持uefi,甚至支持各种各样的文件系统,还能增加字体,美化菜单。这简直就是个微型操作系统,也正是如此,导致它也过于复杂。但不管怎么说,grub还是开源世界最流行的引导管理器。
主文件夹:
默认菜单:
Linux内核和镜像:
grub能力列表:
设备和路径语法:
(fd0)
软盘驱动设备,第一个编号0(hd0,msdos2)
硬盘1,msdos分区2,分区从1开始编号,扩展分区从5开始编号。msdos是一个分区方案,另一个是gpt(hd1,gpt2)/boot/a.txt
路径格式/boot/
unix 路径\\?\c:\
windows UNC表示路径grub引导镜像:
/usr/lib/grub/x86_64-efi*
新式efi/usr/lib/grub/i386-pc
传统bios网络引导:
com串行终端:
构建命令:
grub-install 设备
: --boot-directory=
启动根目录,grub默认复制内容到此 --recheck
重建设备映射,/boot/grub/device.map;--no-rs-codes
关闭bios启动模式的引导记录备份;--compress=no|xz|gz|lzo
压缩选项;--directory=
模块目录;--fonts=
字体文件名;--install-modules=
安装的模块;--pubkey=
嵌入的公钥;--locale-directory=/usr/share/locale
本地化文件;--modules=
预载模块;--themes=starfield
主题;--allow-floppy
软盘引导格式;--bootloader-id=
efi下的子目录名;--core-compress=xz|none|auto
内核映像压缩选项;--disk-module=
bios模式下的磁盘选项;--efi-directory=
efi根目录;--force
强制;--force-extra-removable
强制安装到移动设备;--force-file-id
强制不使用uuid;--label-bgcolor=
背景色;--label-color=
前景色;--label-font=
字体;--macppc-directory=
mac ppc;--no-bootsector=
不要安装启动扇区,bios;--no-nvram
不要更新主板的启动菜单;--no-uefi-secure-boot
不要安装安全启动映像;--product-version=
发行版本;--removable
启动镜像可用于移动设备;--skip-fs-probe
不检索其他系统;--target=x86_64-efi
镜像类型;--uefi-secure-boot
安装安全启动镜像。grub-mkconfig -o /boot/grub/grub.cfg
: 生成配置文件,通过系统/etc/grub.d/下的脚本,和/etc/default/grub脚本生成。grub-mkpasswd-pbkdf2
:生成密码grub-mkrelpath 路径
:生成相对启动根的路径。grub-mkrescue -o grub.iso
生成grub急救盘,通过调用grub-mkimage,xorriso,mkisofs生成。--modules=
模块;--xorriso=xorriso
;--grub-mkimage=grub-miimage
;grub-mount 设备 挂载点
可用来检查镜像内容grub-probe 路径|-d 设备
得到设备的一些信息,--target=fs
文件系统,fs_uuid
文件系统通用唯一标识,fs_label
分区标签,drive
grub表示的设备名,device
系统设备名,partmap
分区映射模块,hints_string
适用search的搜索提示。--device-map=
/boot/grub/device.mapgrub-script-check /boot/grub/grub.cfg
检查脚本是否存在语法错误grub-editenv 文件名 命令
:修改环境块,用来保存用户设置。create
新建空环境块;list
列出当前环境块。set 变量=值
设置变量;unset 变量
删除变量;grub-file --is-x86_64-efi 文件
:测试文件是否为参数指定类型grub-fstest 映像 命令
:blocklist 文件
显示块列表;cat 文件
;cmp 文件 本地文件
比较;cp 文件 本地文件
;crc 文件
;hex 文件
;ls 路径
;xnu_uuid 设备
。--diskcount=;--crypto 加密;--zfs-key;--length=;--root=根设备;--uncompress;grub-glue-efi
转换成apple格式grub-kbdcomp
制作键盘映射grub-macbless
苹果系统blessgrub-menulst2cfg
旧版菜单转为新版grub-mkdevicemap -m /boot/grub/device.map
输出磁盘映射文件grub-mkfont -o grub.pf2 字体文件
:将普通字体转换为grub专用pf2格式字体文件grub-mkimage -o 镜像 模块
:制作grub镜像。--config=
内嵌配置文件;--compression=xz|none|auto
压缩;--directory=/usr/lib/grub/x86_64-efi
;--publikey=
内嵌签名文件;--memdisk=
内嵌内存盘文件;--note
IEEE1275使用;--format=
镜像格式(x86_64-efi等);--prefix=/boot/grub
,主目录;grub-mklayout
键盘映射grub-mknetdir
创建网络镜像目录,TFTP使用grub-mkstandalone -o 镜像 源
:创建全模块版本镜像gurb-reboot 菜单项
: 设置下次启动的菜单项。--boot-directory=/boot/gurbgurb-render-label
苹果.disk_labelgurb-set-default 菜单项
:设置默认启动项gurb-syslinux2cfg
转换syslinux菜单成grub菜单。os-prober
搜索其他系统信息efibootmgr
演练:
#1. 安装
sudo apt install grub-efi-amd64 #uefi版grub
sudo apt install efibootmgr #编辑主板中的UEFI引导菜单
#2. 查看信息
lsblk #查看分区和挂载(比较清晰)
sudo blkid #查看设备和分区信息
sudo fdisk -l #查看设备和分区情况
df -Th #查看空间和挂载点
sudo grub-probe -t device /boot/grub #查找grub 位置
#根据大小等信息获取各个系统所在分区,并记录下对应信息,系统:分区:uuid:文件系统。
#3. 简易安装
sudo grub-install --target=x86_64-efi /dev/sda1 #将grub安装到串口硬盘1分区1,默认安装目录是/boot下的grub文件夹,efi镜像默认安装在/boot/efi下的efi/grub文件夹。可以用--boot-directory=参数指定boot根文件夹,--efi-directory=参数指定efi根文件夹。对移动设备需用--removable并指定两者。grub-install实际通过调用其他工具来完成任务。
sudo update-grub #自动更新grub引导信息,这实际是一个脚本,它调用grub-mkconfig更新/boot/grub/grub.cfg
变量(/etc/default/grub):
脚本语法:
{} | & $ ; <>
元字符! [[ ]] {} case do done elif else esac fi for function if in menuentry select then time until while
关键字\ '' ""
转义序列$(变量)
得到变量的值,$1
第一个参数#注释内容
注释menuentry “win10”{
insmod ntfs
search --set=root --label win10 --hint hd2,gpt2
configfile /boot/grub/grub.cfg
}
menuentry "winxp"{
insmod ntfs
search --set=root -fs-uuid {} winxp --hint hd0,msdos2
ntldr /ntldr
}
主题资源:
__timeout__
id值为这个将由grub更新对grub.cfg脚本的简单分析:
默认的启动过程是:
引导进入grub命令行,即出现grub>
可以输入grub 命令行工具,来修复引导。类似bash,可以使用TAB补全和上下按键寻找历史命令。
ls
列出分区。ls (hd2,gpt1)
显示分区类型ls (hd2,gpt1)/
显示分区内容set pager=1
设置信息滚动一屏暂停set
显示环境变量,重要信息set root=(hd2,gpt1)
设置根目录位置insmod 路径
装载模块,模块一般在/boot/grub/x86_64-efi/目录下,如果没有装载模块,很多命令都不能正常使用
minicmd.mod
很多命令在这个模块normal.mod
基本模块,增加normal命令,进入正常模式。linux.mod
linux内核装载模块congfigfile 路径
装载grub目录文件,确保首先正确加载了相关mod,否则启动菜单也无法引导系统linux 路径
装载linux内核linux16 路径
旧款linux内核initrd 路径
装载系统映像initrd16 路径
配合linux16使用set prefix=(hd2,gpt1)/boot/grub/
设置grub目录位置boot
启动linux系统映像,多重引导规范chainloader (hd2,gpt2) +1
调到下一个引导管理器,链式引导chainloader /efi/microsoft/boot/bootmgfw.efi
启动gpt模式的windows引导管理器。drivemap -s (hd0) (hd1)
安装dos需要在第一个设备,drivemap交换映射parttool
隐藏分区,安装dos用可用命令列表:
特殊环境变量:
biosnum:
bios启动设备号check_signatures:
数字签名验证chosen:
选择的菜单项cmdpath:
定位于引导映像启动的路径color_highlight:
高亮时前景色/背景色color_normal:
前景色/背景色config_directory:
配置文件目录config_file:
配置文件debug:
启用调试信息输出default:
默认菜单项,参考grub-set-default/grub-rebootfallback:
备用菜单项gfxmode:
使用gfxterm图形终端gfxpayload:
linux内核视频模式gfxterm_font:
gfxterm字体grub_cpu:
构建的cpu类型grub_platform:
pc/efiicondir:
图标目录lang:
zh_CNlocale_dir:
本地化目录/boot/grub/localemenu_color_highlight:
菜单项高亮模式前景色/背景色menu_color_normal:
菜单项前景色/背景色net_<interface>_boot_file:
net_<interface>_dhcp_server_name
:net_<interface>_domain:
net_<interface>_extensionspath:
net_<interface>_hostname:
net_<interface>_ip:
net_<interface>_mac:
net_<interface>_next_server:
net_<interface>_rootpath:
net_default_interface:
net_default_ip:
net_default_mac:
net_default_server:
pager:
显示信息长度(/页)暂停prefix:
/boot/grubpxe_blksize:
pxe_default_gateway:
pxe_default_server:
root:
根目录所在位置superusers:
超级用户theme:
主题timeout:
倒计时timeout_style:
倒计时显示方式环境储存块:
busyBox 是一个微型linux系统,一般用在救援系统。
grub的内容相当杂乱,庞大而复杂,所以整理起来也是非常艰难。如果实在看不懂,那么就照以下步骤进行即可(所有步骤皆实际操作):
#系统默认已经安装grub,uefi环境下,也就是我推荐的方式,安装的grub组件包括:grub-common、grub-efi-amd64、grub-efi-amd64-bin、grub2-common
# 首先切换到root 管理账号,得到管理权限
sudo passwd root
su
apt list grub* #列出grub相关包,可以看出已经安装的grub包,确认是否uefi环境,然后继续
#1. 简单安装
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=mygrub #x86_64-efi就是grub 的uefi引导框架,--efi-directory这个指示了esp挂载的根在哪里。因为我的esp分区挂载在/boot/efi目录,所以选择在哪里,因此你也可以根据自己的实际情况设置esp分区的根。--bootloader-id 这个参数会在esp分区的/efi/目录下生成对应的文件夹。和mircosoft,ubuntu等文件夹平级。这个命令并不会生成esp分区的/efi/boot/bootx64.efi 默认启动器,只会生成对应文件夹的/efi/mygrub/grubx64.efi启动器,这个时候就没有默认的启动器,如果你想要,可以复制:
mkdir /boot/efi/efi/boot
mv /boot/efi/efi/mygrub/grubx64.efi /boot/efi/efi/boot
#2. 定制安装
# 自动生成的启动器,符合大多数要求,为了演示,接下来对其中某些过程进行定制
# 首先要理解grub-install干了什么,它首先调用了grub-mkconfig生成了菜单,然后调用grub-mkimage生成启动映像
#2.1 生成菜单,会自动调用os-prober搜索磁盘的其他系统,生成菜单
mkdir -p /boot/efi/efi/grub2
grub-mkconfig -o /boot/efi/efi/grub2/grub.cfg
# 自动生成的菜单是根据/etc/grub.d/ 下的脚本,和/etc/default/grub来生成的。因为要定制,所以可以对这个生成后的脚本直接进行编辑。
cd /boot/efi/efi/grub2
nano grub.cfg
#一般只需要增加或删减菜单项即可
#2.2 生成启动映像
grub-mkimage -o grub2.efi --prefix=/efi/grub2 --format=x86_64-efi fat.mod part_gpt.mod #必须要带这俩个模块,否则无法读取gpt分区和fat文件系统的内容,映像必须要读取菜单文件grub.cfg,--prefix指明grub目录位置,另外,菜单用的命令模块也在x86_64-efi目录下面。
cp grub2.efi /boot/efi/efi/boot/bootx64.efi #这个是磁盘默认启动的efi
cp grub2.efi /boot/efi/efi/grub2 #我自定义的grub目录,即现在这个目录已经有grub2.efi 和grub.cfg ,注意grub.cfg的名字是不能改的,已经被固定了,grub2.efi会在设定的目录自动找这个文件。
cp /usr/lib/grub/x86_64-efi /boot/efi/efi/grub2 -r #复制所有模块到目录下面
#重启即可使用自定义菜单启动系统。
cp /boot/vmlinuzxxx /boot/efi/efi/debian/vmlinuz
cp /boot/initrd.imgxxx /boot/efi/efi/debian/initrd.img
#复制默认在/boot目录下的内核和映像盘到我想要的目录下,因为我在grub.cfg新增了一个测试菜单项,路径就指向那里,演示的是debian系统,所以里面已经有debian目录,就复制到那里即可。
#2.3 修改主板菜单
# 最好是从主板菜单启动,因为bootx64.efi会被其他系统抢用。
efibootmgr -c -d /dev/sda -p 1 -l /efi/grub2/grub2.efi -L grub2-debian -g #-c新建,-d 磁盘;-p 分区;-l 启动路径;-L 菜单标题; -g gpt分区。
efibootmgr -b 0005 -B #删除编号0005的菜单项
#以上在debian虚拟机中测试通过,但是这里是手写的,所以也许有纰漏。