UEFI之虚拟环境(OVMF)seabios --- ovmf

六月 25, 2024 [Linux 与系统] #obsidian #发行版 #硬件 #编译链接 #网络

UEFI之虚拟环境(OVMF)seabios --- ovmf

概要

模拟器平台介绍 : 一个仿真平台并不是一个实际的硬件平台 , 但它旨在证明 EDKII 核心模块的稳定性和独立于硬件可以开发模块。仿真平台和实际平台之间的差异是其加载器和仿真的硬件设备。 OvmfPkg 是基于qemu的虚拟环境,Linux 和 Windows都可以使用

源码

git clone https://github.com/tianocore/edk2.git
cd edk2
git submodule update --init
cd ..

qemu

需要安装qemu apt install qemu ubuntu 20.04 apt install qemu-system-x86

这里主要讲一些启动系统时可以使用的参数:

  1. -m x:用来指定虚拟系统的内存大小,x是一个数字,单位是MB;
  2. -bios x:用来指定使用的BIOS,默认使用的是seabios,也支持OVMF;
  3. -serial stdio:用来指定串口的输出,这里就是输出的标准输出;
  4. -hda:指定之前创建的虚拟盘;
  5. -cdrom:指定了安装的系统镜像;

制作挂载盘镜像 QEMU可以支持很多种文件格式,以qcow2和raw两种格式的镜像为例。需要特别注意的是,UEFI能识别到的文件系统类型比较有限,建议格式化镜像时都使用VFAT格式。注意这里的VFAT和前面说的qcow2和raw并不冲突,一个是镜像中的文件系统,一个是镜像的封装格式。

sudo modprobe nbd max_part=16
qemu-img create -f qcow2 hda.img 10M  #创建qcow2虚拟盘
sudo qemu-nbd -c /dev/nbd0 ~/hda.img    #映射nbd设备
mkfs -t vfat /dev/nbd0                           #格式化该设备为vfat格式
sudo mount /dev/nbd0 /mnt/image        #挂载nbd设备
......(work in mnt dir)
sudo umount /mnt/image                       #卸载nbd设备
sudo qemu-nbd -d /dev/nbd0               #解除nbd映射
dd if=/dev/zero of=~/hda.img bs=1 count=10M
mkfs -t vfat ~/hda.img
losetup /dev/loop0 ~/hda.img  #映射loop设备
sudo mount /dev/loop0 /mnt/image  #挂载loop设备
......(work in mnt dir)
umount /mnt/image              #卸载loop设备
losetup -d /dev/loop0           #解除loop映射
qemu-system-x86_64  -bios  "path/to/OVMF.fd" -hda hda.img
qemu-system-x86_64 -bios  "/path/OVMF.fd" -net none -hda fat:rw:/path/DEBUG_GCC5

fat:rw: 这个文件夹映射的关键 path 为绝对地址

编译环境

1.更新软件源,sudo apt-get update

2.安装gcc4.8 sudo apt-get install gcc-5 g++-5 如果已经安装gcc,可以使用下面命令切换

添加
   sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 40
   sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 50
切换
   sudo update-alternatives --config gcc

3.安装nasm sudo apt-get install nasm

4.安装build sudo apt-get install build-essential uuid-dev sudo apt-get install iasl

5.安装python

       sudo apt-get install python
       sudo apt-get install python-pip
       sudo apt-get install python3-distutils

6.在edk根目录执行 source edksetup.sh

7.在 BaseTools目录下编译工具 make 建立完成后,试试看能否编译。

source edksetup.sh
build -p MdeModulePkg/MdeModulePkg.dsc -t GCC5

8.编译 OvmfPkg OvmfPkg/build.sh 或者编译32bit build -p OvmfPkg/OvmfPkgIa32.dsc -t GCC5 -D SOURCE_DEBUG_ENABLE

SOURCE_DEBUG_ENABLE是编译开关参数,dsc中有定义

9.运行

OvmfPkg:

执行命令: qemu-system-x86_64 -bios OVMF.fd 没有UEFI的打印,为了能够有打印,首先需要添加编译选项并重新生成二进制 build -p OvmfPkg/OvmfPkgX64.dsc -a X64 -D DEBUG_ON_SERIAL_PORT 用qemu运行时,需要加入新的参数: qemu-system-x86_64 -bios OVMF.fd -serial stdio

qemu 下OVMF 网络

mkdir -p edk2/Intel3.5/EFIX64
cp E3522X2.EFI edk/edk2/Intel3.5/EFIX64/

如果不指定任何网络设置,Qemu将使用带有内置DHCP服务器的用户模式(user)网络。当虚拟机运行时,可设定为DHCP模式,它能够通过QEMU伪装的IP来访问物理主机的网络。 不过,这种情况下,能通信的仅限于TCP和UDP协议,因此ICMP协议(包括ping)将不起作用。因此,我们准备采用tap模式,使用桥接的方法,让虚拟机和外部通信起来。

-device e1000,netdev=mynet0 创建一个NIC(型号为e1000)并连接到由上一个参数创建的mynet0后端

整体的启动命令:

qemu-system-x86_64 -bios "/home/zhubo/00_loongson/02-code/edk/edk2/Build/OvmfX64/DEBUG_GCC5/FV/OVMF.fd" -serial stdio -hda fat:rw:Build/AppPkg -netdev user,id=mynet0,hostfwd=tcp::8080-:80 -device e1000,netdev=mynet0

具体可以查看这里:https://wiki.archlinux.org/index.php/QEMU_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)

编译AppPkg

EDK2 中新版本的AppPkg 和 StdLib 是分出去的 在这里放着 https://github.com/tianocore/edk2-libc.git 克隆到本地后将AppPkg、StdLib、StdLibPrivateInternalFiles 复制到edk2 的编译路径

查看发现确实没有定义,发现如下patch删除了,

commit 9c1f455f5f0ee63ce080940bf974aac4fefe526b
Author: Shenglei Zhang <shenglei.zhang@intel.com>
Date:   Wed Aug 5 14:08:03 2020 +0800

    MdePkg: Remove code wrapped by DISABLE_NEW_DEPRECATED_INTERFACES

    REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2777
    Code wrapped by DISABLE_NEW_DEPRECATED_INTERFACES is deprecated.
    So remove it.

    Cc: Michael D Kinney <michael.d.kinney@intel.com>
    Cc: Liming Gao <liming.gao@intel.com>
    Signed-off-by: Shenglei Zhang <shenglei.zhang@intel.com>
    Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>

最好的做法是将删除的文件恢复回来,找到上面patch的前一个patch,如下, 然后编译就没问题了

git reset cc942105ede58a300ba46f3df0edfa86b3abd4dd MdePkg/Include/Library/BaseLib.h
git reset cc942105ede58a300ba46f3df0edfa86b3abd4dd MdePkg/Library/BaseLib/String.c

问题

1、安装不了python3-distutils,提示无法定位

sudo vim /etc/apt/sources.list

添加源:

deb http://cn.archive.ubuntu.com/ubuntu bionic main multiverse restricted universe
deb http://cn.archive.ubuntu.com/ubuntu bionic-updates main multiverse restricted universe
deb http://cn.archive.ubuntu.com/ubuntu bionic-security main multiverse restricted universe
deb http://cn.archive.ubuntu.com/ubuntu bionic-proposed main multiverse restricted universe

再执行如下指令:

  sudo apt-get update
  sudo apt-get install python3-distutils

2、Trim.py: error: no such option: --asm-file 安装完如下3条命令问题就没有了,也不知道具体哪条解决的;

pip install brotli
sudo apt install build-essential uuid-dev
sudo apt install acpica-tools

3、 在编译AppPkg和Demo时,出现如下问题:

/usr/bin/ld: 并不支持从格式 pe-i386 (/edk2/Build/AppPkg/DEBUG_GCC5/IA32/StdLib/LibC/LibC/OUTPUT/LibC.lib(ftol2.obj)) 到格式 elf32-i386 (edk2/Build/AppPkg/DEBUG_GCC5/IA32/AppPkg/Applications/Sockets/SetHostName/SetHostName/DEBUG/SetHostName.dll) 的重寻址链结

是由于在ubuntu64上编译32位应用导致的,添加-a X64后正常了;

build -p AppPkg/AppPkg.dsc -t GCC5 -a X64

4、警告变error 可以在 Flags 加 -Wno-error 试试

5、编译报缺少东西,如brotli/c/enc/encoder_dict.o: 没有那个文件或目录 git submodule update --init