https://github.com/tianocore/edk2
https://github.com/tianocore/edk2-platforms
https://github.com/tianocore/edk2-non-osi
除此之外,还可以使用Linaro的efi编译脚本:
https://git.linaro.org/uefi/uefi-tools.git/
- . edk2/edksetup.sh
- make -C edk2/BaseTools
- $ build -n $NUM_CPUS -a AARCH64 -t GCC5 -p Platform/ARM/JunoPkg/ArmJuno.dsc
-
主要过程就是加载编译的变量,然后编译好efi工具,efi工具用来编译固件(包含固件生成工具等等),最后就是使用build命令编译某个平台的pkg,build命令行的参数也可以在配置文件指定。具体的参考github了。
脚本更简单一些,一条命令类似于./uefi-tools/edk2-build.sh juno这样就好了,因为脚本里面有个配置文件uefi-tools/edk2-platforms.config写好了每一个板子的配置,当然也可以自己添加自己的板子配置进去。
几个仓库里面,基本上是以模块(module)包(pkg)这两种单位为基本结构,
飞腾E2000Q开发板的UEFI固件编译:
- edk2-platforms/Platform/Phytium/CherryPkg/CherryPkg.dsc
- #注释掉下面一行
- MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
-
- edk2-platforms/Platform/Phytium/CherryPkg/CherryPkg.fdf
- #注释掉下面一行
- INF MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
-
可以看出,其实edk2的编译和qt cmake makefile编译方法类似了。
其他未总结的,比如开机热键修改,BIOS菜单修改等等,未完待续(弄驱动这种我肯定是没能力也没精力去写的,改一改配置设置还行)。
- /home/user/Documents/e2000/e2000-v1.5_20230608/Build/ArmVirtQemu-AARCH64/DEBUG_GCC5/FV/QEMU_EFI.fd
- /home/user/Documents/e2000/e2000-v1.5_20230608/Build/ArmVirtQemu-AARCH64/DEBUG_GCC5/FV/QEMU_VARS.fd
-
下面是日志
-
- Fd File Name:QEMU_EFI (/home/user/Documents/e2000/e2000-v1.5_20230608/Build/ArmVirtQemu-AARCH64/DEBUG_GCC5/FV/QEMU_EFI.fd)
-
- Generate Region at Offset 0x0
- Region Size = 0x1000
- Region Name = DATA
-
- Generate Region at Offset 0x1000
- Region Size = 0x1FF000
- Region Name = FV
-
- Generating FVMAIN_COMPACT FV
-
- Generating FVMAIN FV
- #######
- Fd File Name:QEMU_VARS (/home/user/Documents/e2000/e2000-v1.5_20230608/Build/ArmVirtQemu-AARCH64/DEBUG_GCC5/FV/QEMU_VARS.fd)
-
- Generate Region at Offset 0x0
- Region Size = 0x40000
- Region Name = DATA
-
- Generate Region at Offset 0x40000
- Region Size = 0x40000
- Region Name = DATA
-
- Generate Region at Offset 0x80000
- Region Size = 0x40000
- Region Name = None
-
- GUID cross reference file can be found at /home/user/Documents/e2000/e2000-v1.5_20230608/Build/ArmVirtQemu-AARCH64/DEBUG_GCC5/FV/Guid.xref
-
- FV Space Information
- FVMAIN [99%Full] 6865920 (0x68c400) total, 6865880 (0x68c3d8) used, 40 (0x28) free
- FVMAIN_COMPACT [58%Full] 2093056 (0x1ff000) total, 1217000 (0x1291e8) used, 876056 (0xd5e18) free
-
- - Done -
- Build end time: 14:38:52, Jun.17 2023
- Build total time: 00:03:00
-
- ------------------------------------------------------------
- ArmVirtPkg QEMU (AARCH64) DEBUG pass
- ------------------------------------------------------------
- pass 1
- fail 0
-
然后要使用qemu+kvm测试还需要把这两个文件坐下扩容,不然启动失败
- qemu-img resize -f raw QEMU_VARS.fd 64M
- qemu-img resize -f raw QEMU_EFI.fd 64M
-
测试命令
- sudo qemu-system-aarch64 -m 4096M \
- -machine virt-3.1,accel=kvm,usb=off,dump-guest-core=off,gic-version=3 \
- -cpu host \
- -drive file=/home/user/temp/QEMU_EFI.fd,if=pflash,format=raw,unit=0,readonly=on \
- -drive file=/home/user/temp/QEMU_VARS.fd,if=pflash,format=raw,unit=1 \
- -device pcie-root-port,port=0x8,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,addr=0x1 \
- -device pcie-root-port,port=0x9,chassis=2,id=pci.2,bus=pcie.0,addr=0x1.0x1 \
- -device pcie-root-port,port=0xa,chassis=3,id=pci.3,bus=pcie.0,addr=0x1.0x2 \
- -device pcie-root-port,port=0xb,chassis=4,id=pci.4,bus=pcie.0,addr=0x1.0x3 \
- -device pcie-root-port,port=0xc,chassis=5,id=pci.5,bus=pcie.0,addr=0x1.0x4 \
- -device pcie-root-port,port=0xd,chassis=6,id=pci.6,bus=pcie.0,addr=0x1.0x5 \
- -device virtio-gpu-pci,id=video0,max_outputs=1,bus=pci.5,addr=0x0 \
- -netdev tap,id=hostnet0,vhost=on \
- -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:54:fb:35,bus=pci.1,addr=0x0 \
- -device qemu-xhci,p2=15,p3=15,id=usb,bus=pci.2,addr=0x0 \
- -device usb-kbd,id=input0,bus=usb.0,port=1 \
- -device usb-mouse,id=input1,bus=usb.0,port=2
-
可以直接图形和串口2个窗口查看启动过程。
- build-qemu-efi-aarch64:
- $(MAKE) -f debian/rules build-qemu-efi EDK2_ARCH_DIR=AArch64 EDK2_HOST_ARCH=AARCH64 FW_NAME=AAVMF
- build-qemu-efi: setup-build
- mkdir -p ShellBinPkg/UefiShell/$(EDK2_ARCH_DIR) FatBinPkg/EnhancedFatDxe/$(EDK2_ARCH_DIR)
- set -e; . ./edksetup.sh; \
- build -a $(EDK2_HOST_ARCH) -p ShellPkg/ShellPkg.dsc \
- -b RELEASE -t $(EDK2_TOOLCHAIN); \
- cp -a Build/Shell/RELEASE_$(EDK2_TOOLCHAIN)/$(EDK2_HOST_ARCH)/Shell.efi \
- ShellBinPkg/UefiShell/$(EDK2_ARCH_DIR)/Shell.efi; \
- build -a $(EDK2_HOST_ARCH) -p FatPkg/FatPkg.dsc \
- -m FatPkg/EnhancedFatDxe/Fat.inf \
- -t $(EDK2_TOOLCHAIN) -b RELEASE; \
- cp -a Build/Fat/RELEASE_$(EDK2_TOOLCHAIN)/$(EDK2_HOST_ARCH)/Fat.efi \
- FatBinPkg/EnhancedFatDxe/$(EDK2_ARCH_DIR)/Fat.efi; \
- build -a $(EDK2_HOST_ARCH) \
- -t $(EDK2_TOOLCHAIN) \
- -p ArmVirtPkg/ArmVirtQemu.dsc \
- $(AAVMF_FLAGS) -b RELEASE
- dd if=/dev/zero of=Build/ArmVirtQemu-$(EDK2_HOST_ARCH)/RELEASE_$(EDK2_TOOLCHAIN)/FV/$(FW_NAME)_CODE.fd bs=1M seek=64 count=0
- dd if=Build/ArmVirtQemu-$(EDK2_HOST_ARCH)/RELEASE_$(EDK2_TOOLCHAIN)/FV/QEMU_EFI.fd of=Build/ArmVirtQemu-$(EDK2_HOST_ARCH)/RELEASE_$(EDK2_TOOLCHAIN)/FV/$(FW_NAME)_CODE.fd conv=notrunc
- dd if=/dev/zero of=Build/ArmVirtQemu-$(EDK2_HOST_ARCH)/RELEASE_$(EDK2_TOOLCHAIN)/FV/$(FW_NAME)_VARS.fd bs=1M seek=64 count=0
-
最后dd那两下差点没看懂,仔细想了下,才发现是直接把文件增大到64M(seek是dd对目标文件跳过多少个bs开始写),debian的这个rules这里发现两个文件也需要扩容到64M。
这里摘抄一张大神书里面的图片,整个启动过程还是比较清晰的,对我目前来说,我就是想改个LOGO,然后BIOS配置界面
稍微做点文字上的自定义(功能就算了,精力跟不上,开发基础也不够)
于是乎,最有用的应该就是BDS阶段,BDS作为一个特殊的DEX加载后,应该就是我的切入点。
查看edk2/ArmVirtPkg/ArmVirtQemu.dsc固件的包描述文件 Bds部分。
- #
- # Bds
- #
- MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf {
- <LibraryClasses>
- DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
- PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
- }
- MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
- MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
- MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
- MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
- MdeModulePkg/Logo/LogoDxe.inf
- MdeModulePkg/Application/UiApp/UiApp.inf {
- <LibraryClasses>
- NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
- NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
- NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
- }
- OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf {
- <LibraryClasses>
- NULL|OvmfPkg/Library/BlobVerifierLibNull/BlobVerifierLibNull.inf
- }
-
盲猜这部分我需要去查看的有
- MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
- MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
- MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
- MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
- MdeModulePkg/Logo/LogoDxe.inf
- MdeModulePkg/Application/UiApp/UiApp.inf
-
这几个模块,通过启动过程的debug日志字符串查找
edk2/MdeModulePkg/Universal/BdsDxe/BdsEntry.c这个文件在UEFI显卡界面显示LOGO并走进度条的时候串口打印
- DEBUG ((DEBUG_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN)TimeoutRemain));
-
对于BIOS配置界面,盲猜应该在edk2/MdeModulePkg/Application/UiApp这个模块内,具体看了下代码,dsc文件定义了入口函数是ENTRY_POINT = InitializeUserInterface直接在edk2/MdeModulePkg/Application/UiApp/FrontPage.c文件搜索,这个函数内的UiEntry函数就有 InitializeFrontPage(); 来初始化配置页面,继续跟下去,InitializeFrontPage里面UpdateFrontPageBannerStrings里面读取了smibios来配置bios配置界面的顶部banner,就是下面这个图里面的 CPU 内存
查看文件,发现BIOS配置界面总共有5行,第四第五行都是空的,前面几行都是从SMBIOS接口获取的数据,动态,暂时不研究咋修改,尝试给第四行的空字符串加上自定义的,在文件edk2/MdeModulePkg/Application/UiApp/FrontPageStrings.uni中修改字符串如下:
- #string STR_CUSTOMIZE_BANNER_LINE4_LEFT #language en-US "Made by Actionchen"
- #language fr-FR ""
- #string STR_CUSTOMIZE_BANNER_LINE4_RIGHT #language en-US "2023-06-07"
-
重新编译固件后再测试,已经显示为自定义的字符串了。
这个其他部分有时间页面慢慢研究,没有开发能力折腾这个是缓慢的。