【UEFI实战】LinuxBoot £神魔★判官ぃ 2023-10-02 21:45 2阅读 0赞 ## 综述 ## LinuxBoot是一个开源的固件,用来替代UEFI BIOS加载Linux的系统。 官网是[LinuxBoot][]。 对应的代码库位于[LinuxBoot · GitHub][LinuxBoot _ GitHub]。 另外,本文是在[【UEFI实战】LinuxBoot简介][UEFI_LinuxBoot]基础上完成的,增加了编译和执行部分。 ## 基础 ## 先通过几张图来说明LinuxBoot的基础。 ![在这里插入图片描述][2e98557a89f9427cbc21fbc6f82aa11e.png_pic_center] 这里实际上将固件分为了两个部分,分别是: 1. 用于处理特定硬件的部分; 2. 通用部分(Linux部分); 第一部分,因为CPU和PCH等都是特定厂商的,因此需要特定的初始化代码来完成这些组件的初始化,这个部分可以是原来就有的东西,比如UEFI的PEI阶段,coreboot的romstage阶段、SBL的Stage 1B阶段,等等。 第二部分实际上就是一个Linux的内核加文件系统,它在平台初始化之后加载,由于这些部分是通用的,原始的Linux代码就可以完成操作,因此在官网的开始就直接了当的写了:不要重复造轮子。 ![在这里插入图片描述][91908d20ba344917b85817c205d605e2.jpeg_pic_center] 上图的前面部分实际上是Intel的PI规范中定义的BIOS启动各个阶段,原始的是这样的: ![在这里插入图片描述][ab87954b697543e2a0b2f91d488d1f70.jpeg_pic_center] 也就是说LinuxBoot替代了UEFI启动过程中DXE之后的阶段,前面的两个图表达的意思其实是一样的:LinuxBoot可以认为是跑一部分SI(Silicon Initialization)代码然后加载LinuxBoot内核再加载真正的内核。 ## 优缺点 ## 优点主要来自Linux代码的引入: * 可复用的代码增加; * 安全性的提高; * 启动速度提高(这个存疑,其实没有完整的验证数据)。 缺点: * 只能加载Linux操作系统,也就是说Windows不行,这个感觉是个问题。 * 开源格式是GPL的,相比之下UEFI是BSD的。 ## 使用 ## 下载源码: git clone https://gitee.com/mirrors/LinuxBoot.git 此外,代码还依赖于额外的内容,这里简单介绍。 ### 额外依赖 ### #### kernel #### 内核会被包含到linuxboot.rom中,所以首先需要编译出内核。 注意编译内核的时候需要增加配置:CONFIG\_EFI\_BDS=y(在LinuxBoot的README中是这个,但是实际上需要使用的是`CONFIG_EFI_STUB=y`,该选项的作用是使UEFI可以直接启动内核而不需要BootLoader)。 内核编译成功之后可以在arch/x86/boot目录下找到,将文件bzImage放到LinuxBoot的根目录下。 这里需要注意的是由于linuxboot.rom的二进制大小有限,以及EDK的二进制的特性,必须保证bzImage足够小,这依赖于对内核的剪裁,不过这不在本文的讨论范围内。 #### u-root #### u-root是嵌入式的root文件系统,配合Linux内核使用,作为Linux的initramfs。 它是由Go语言写的,不过实现的内容还是普通的root文件系统的CONFIG\_EFI\_STUB=y内容。 包括一系列标准的Linux命令,比如ls、cp等。 对应的代码: git clone https://gitee.com/jiangwei0512/u-root.git 下载对应的代码到LinuxBoot目录,然后进入到u-root目录,之后就需要go编译器的操作了: 1. 下载安装go; 2. 通过go下载u-root命令,下载成功之后如下所示: jw@X1C:~/code/linux-boot/u-root$ ls $GOPATH/bin u-root 下载可能会遇到问题,可以更新代理: jw@X1C:~/code/linux-boot/u-root$ go env -w GO111MODULE=on jw@X1C:~/code/linux-boot/u-root$ go env -w GOPROXY=https://goproxy.cn,direct 1. 在u-root目录下执行u-root命令: jw@X1C:~/code/linux-boot/u-root$ u-root core 19:49:18 Disabling CGO for u-root... 19:49:18 Build environment: GOARCH=amd64 GOOS=linux GOROOT=/usr/local/go GOPATH=/home/jw/go CGO_ENABLED=0 19:49:18 WARNING: You are not using one of the recommended Go versions (have = go1.19, recommended = [go1.17]). Some packages may not compile. Go to https://golang.org/doc/install to find out how to install a newer version of Go, or use https://godoc.org/golang.org/dl/go1.17 to install an additional version of Go. 19:49:18 NOTE: building with the new gobusybox; to get the old behavior check out commit 8b790de 19:49:18 Skipping package "cmds/core/bind": no buildable Go source files in /home/jw/code/linux-boot/u-root/cmds/core/bind 19:49:18 Skipping package "cmds/core/bind": no buildable Go source files in /home/jw/code/linux-boot/u-root/cmds/core/bind 19:49:39 Successfully built "/tmp/initramfs.linux_amd64.cpio" (size 12668312). 完成之后将/tmp/initramfs.linux\_amd64.cpio压缩拷贝到LinuxBoot的根目录,并重命名为initrd.cpio.xz,压缩命令: xz --check=crc32 -9 --lzma2=dict=1MiB --stdout /tmp/initramfs.linux_amd64.cpio | dd conv=sync bs=512 of=/tmp/initramfs.linux_amd64.cpio.xz #### busybox #### u-root是LinuxBoot推荐的initramfs,但是实际上它还是太大了,后面编译linuxboot.rom的时候会因为尺寸太大而编译出错,这里这里推荐另外的initramfs,即使用busybox创建的initramfs。 可以在[Index of /downloads][Index of _downloads]下载到busybox的源码,这里下载的是1.29.1版本,解压到指定的目录: tar -xjvf busybox-1.29.2.tar.bz2 -C /home/jw/code 然后进入该目录进行配置(在源代码目录下执行make menuconfig): ![在这里插入图片描述][793fa91830ca4f40861ee48bb841db18.png_pic_center] 我们这里需要配置的是选择静态编译,位置在Settings项下。需要注意为了使用menuconfig,可能需要安装额外的库(`libncurses5-dev`)。配置之后就可以使用`make`进行编译。编译完成之后通过`make install`命令进行安装: make install 执行上述命令之后,会在当前目录生成一个新的目录称为\_install,我们需要这些文件生成initramfs,供内核使用,对应的文件如下: jw@X1C:~/code/busybox-1.29.2$ ls _install/ bin linuxrc sbin usr 创建initramfs的方法,这里使用最简单的,对应的命令如下: mkdir initramfs cd initramfs mkdir dev proc sys cp ../_install/* ./ -ra sudo cp -a /dev/{ null,console,tty1,tty2,tty3,tty4} dev/ touch init chmod a+x init 其中`init`的内容如下: mount -t proc none /proc mount -t sysfs none /sys mdev -s exec /sbin/init 最后再通过如下的命令打包: find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz 不过最后还需要改名为initrd.cpio.xz,并放到LinuxBoot的根目录。 #### cpu #### cpu更像是一个SSH,也是用Go语言实现的。 对应的代码下载: git clone https://gitee.com/jiangwei0512/cpu.git 相关的代码已经都上传至: https://gitee.com/jiangwei0512/linux-boot.git #### edk #### 这里使用可以通过QEMU测试的LinuxBoot,所以它依赖于OVMF,所以需要下载edk,可以使用默认的github代码: # If the edk2 directory doesn't exist, checkout a shallow branch of it # and build the various Dxe/Smm files edk2/.git: git clone --depth 1 --branch UDK2018 https://github.com/linuxboot/edk2 但是因为网络问题,也可以使用gitee版本: https://gitee.com/jiangwei0512/edk2.git 需要将代码下载到LinuxBoot根目录,并重命名为edk2。 默认情况下LinuxBoot使用的是UDK2018版本: # If the edk2 directory doesn't exist, checkout a shallow branch of it # and build the various Dxe/Smm files edk2/.git: git clone --depth 1 --branch UDK2018 https://github.com/linuxboot/edk2 编译会使用到的dsc是MdeModule.dsc和OvmfPkgX64.dsc,对应到Makefile里面: # 位于boards/qemu/Makefile.board: # We can build a firmware image from edk2 # it is not necessary to provide one boards/$(BOARD)/$(BOARD).rom: edk2/.git ( cd edk2/OvmfPkg ; ./build.sh ) cp edk2/Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd $@ # 位于Makefile: $(EDK2_OUTPUT_DIR)/DxeCore.efi: edk2/.git $(MAKE) -C edk2 ### 编译 ### 进入LinuxBoot根目录并执行`make`: jw@X1C:~/code/linux-boot$ make ./bin/create-ffs -o build/qemu/Initrd.ffs --name Initrd --version 1.0 --type FREEFORM --depex "" --guid "74696e69-6472-632e-7069-6f2f62696f73" initrd.cpio.xz ./bin/create-fv \ -v \ -o build/qemu/dxe.vol \ --size 0xA00000 \ --compress 0 \ build/qemu/DxeCore.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/fc510ee7-ffdc-11d4-bd41-0080c73c8881.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/d93ce3d8-a7eb-4730-8c8e-cc466a9ecc3c.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/6c2004ef-4e0e-4be4-b14c-340eb4aa5891.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/80cf7257-87ab-47f9-a3fe-d50b76d89541.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/b601f8c4-43b7-4784-95b1-f4226cb40cee.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/f80697e9-7fd6-4665-8646-88e33ef71dfc.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/13ac6dd0-73d0-11d4-b06b-00aa00bd6de7.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/245CB4DA-8E15-4A1B-87E3-9878FFA07520.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/a19b1fe7-c1bc-49f8-875f-54a5d542443f.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/1a1e4886-9517-440e-9fde-3be44cee2136.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/C190FE35-44AA-41A1-8AEA-4947BC60E09D.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/f6697ac4-a776-4ee1-b643-1feff2b615bb.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/11a6edf6-a9be-426d-a6cc-b22fe51d9224.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/128fb770-5e79-4176-9e51-9bb268a17dd1.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/93b80004-9fb3-11d4-9a3a-0090273fc14d.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/4b28e4c7-ff36-4e10-93cf-a82159e777c5.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/c8339973-a563-4561-b858-d8476f9defc4.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/378d7b65-8da9-4773-b6e4-a47826a833e1.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/f099d67f-71ae-4c36-b2a3-dceb0eb2b7d8.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/ad608272-d07f-4964-801e-7bd3b7888652.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/42857f0a-13f2-4b21-8a23-53d3f714b840.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/9b680fce-ad6b-4f3a-b60b-f59899003443.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/348c4d62-bfbd-4882-9ece-c80bb1c4783b.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/96b5c032-df4c-4b6e-8232-438dcf448d0e.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/f9d88642-0737-49bc-81b5-6889cd57d9ea.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/4110465d-5ff3-4f4b-b580-24ed0d06747a.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/9622e42c-8e38-4a08-9e8f-54f784652f6b.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/49970331-e3fa-4637-9abc-3b7868676970.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/7e374e25-8e01-4fee-87f2-390c23c606cd.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/bdce85bb-fbaa-4f4e-9264-501a2c249581.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/7C04A583-9E3E-4F1C-AD65-E05268D0B4D1.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/d9dcc5df-4007-435e-9098-8970935504b2.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/2ec9da37-ee35-4de9-86c5-6d9a81dc38a7.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/8657015b-ea43-440d-949a-af3be365c0fc.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/733cbac2-b23f-4b92-bc8e-fb01ce5907b7.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/22dc2b60-fe40-42ac-b01f-3ab1fad9aad8.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/fe5cea76-4f72-49e8-986f-2cd899dffe5d.ffs build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/cbd2e4d5-7068-4ff5-b462-9822b4ad8d60.ffs dxe/linuxboot.ffs build/qemu/Linux.ffs build/qemu/Initrd.ffs Can't open build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/245CB4DA-8E15-4A1B-87E3-9878FFA07520.ffs: 没有那个文件或目录 at ./bin/create-fv line 69, <> chunk 8. Can't open build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/C190FE35-44AA-41A1-8AEA-4947BC60E09D.ffs: 没有那个文件或目录 at ./bin/create-fv line 69, <> chunk 10. Can't open build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/1/7C04A583-9E3E-4F1C-AD65-E05268D0B4D1.ffs: 没有那个文件或目录 at ./bin/create-fv line 69, <> chunk 29. build/qemu/dxe.vol: 0x0071ed2e out of 00a00000 bytes in FV alignment attribute 05 alignment attribute 05 alignment attribute 05 alignment attribute 05 ./bin/create-ffs \ --compress \ --type FIRMWARE_VOLUME_IMAGE \ build/qemu/rom/0x00084000/9e21fd93-9c72-4c15-8c4b-e77f1db2d792/0.fv build/qemu/dxe.vol build/qemu/qemu.txt \ | ./bin/create-fv \ --size 0x748000 \ -o build/qemu/merged.vol alignment attribute 05 cat > build/qemu/linuxboot.rom.tmp build/qemu/rom/0x00000000.fv build/qemu/merged.vol build/qemu/rom/0x007cc000.fv mv build/qemu/linuxboot.rom.tmp build/qemu/linuxboot.rom 可以看到编译能够成功,不过还是会有报错。这是因为某些EDK模块并不存在,查看boards/qemu/image-files.txt文件可以看到这些模块是什么: 245CB4DA-8E15-4A1B-87E3-9878FFA07520 Legacy8259 C190FE35-44AA-41A1-8AEA-4947BC60E09D Timer 7C04A583-9E3E-4F1C-AD65-E05268D0B4D1 Shell 前面两个是必须的,并且在OvmfPkgX64.dsc中已经编译进去了,但是由于GUID不对(整个都不对或者大小写不对)导致异常,这里修改如下: ![在这里插入图片描述][f30533dd8f54498b9ce871942deebc80.png_pic_center] 这样就不会报错了。 ### 执行 ### 使用QEMU执行编译出来的linuxboot.rom,可以直接执行如下命令: make run 实际真正的命令就是QEMU操作: jw@X1C:~/code/linux-boot$ make run qemu-system-x86_64 \ -machine q35,smm=on \ -global ICH9-LPC.disable_s3=1 \ -global driver=cfi.pflash01,property=secure,value=on \ --serial stdio \ -drive if=pflash,format=raw,unit=0,file=build/qemu/linuxboot.rom 结果如下: ![在这里插入图片描述][79dfeb7c4fd54cdba615a9e367d8d09f.png_pic_center] 可以看到BIOS已经启动完成,不过内核启动还存在问题,一直是黑屏,应该是剪裁出问题了,这个需要后续解决,由于Linux水平有限,暂时不再这里讨论。 [LinuxBoot]: https://www.linuxboot.org/ [LinuxBoot _ GitHub]: https://github.com/linuxboot [UEFI_LinuxBoot]: https://blog.csdn.net/jiangwei0512/article/details/103396498?ops_request_misc=&request_id=&biz_id=102&utm_term=linuxboot&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-103396498.142%5Ev51%5Econtrol_1,201%5Ev3%5Eadd_ask&spm=1018.2226.3001.4187 [2e98557a89f9427cbc21fbc6f82aa11e.png_pic_center]: https://img-blog.csdnimg.cn/2e98557a89f9427cbc21fbc6f82aa11e.png#pic_center [91908d20ba344917b85817c205d605e2.jpeg_pic_center]: https://img-blog.csdnimg.cn/91908d20ba344917b85817c205d605e2.jpeg#pic_center [ab87954b697543e2a0b2f91d488d1f70.jpeg_pic_center]: https://img-blog.csdnimg.cn/ab87954b697543e2a0b2f91d488d1f70.jpeg#pic_center [Index of _downloads]: https://busybox.net/downloads/ [793fa91830ca4f40861ee48bb841db18.png_pic_center]: https://img-blog.csdnimg.cn/793fa91830ca4f40861ee48bb841db18.png#pic_center [f30533dd8f54498b9ce871942deebc80.png_pic_center]: https://img-blog.csdnimg.cn/f30533dd8f54498b9ce871942deebc80.png#pic_center [79dfeb7c4fd54cdba615a9e367d8d09f.png_pic_center]: https://img-blog.csdnimg.cn/79dfeb7c4fd54cdba615a9e367d8d09f.png#pic_center
还没有评论,来说两句吧...