UEFI开发探索56-使用WSL编译Arm架构的UEFI镜像

(请保留-> 作者: 罗冰   https://blog.csdn.net/luobing4365)

这篇本想讨论USB的,学习过程中不小心迷上了WSL,又正好想在树莓派上折腾点UEFI的软件,顺理成章地就用WSL搭建了Arm架构的编译环境。

从结论来说,还不错,省得打开虚拟机了,编译速度也很快,有空把X86架构的编译环境也在WSL上搭建起来。

搭建WSL

个人比较喜欢用Ubuntu18.04,很多软件都在上面写的。搭建方法就不具体描述了,可以参考我的另外一篇博客:

https://blog.csdn.net/luobing4365/article/details/105752549

所需下载的代码

可以从github的仓库上下载以下开源代码,准备用来搭建开发环境。不过,github像乌龟一样的速度,如果不是为了修心养性,还是建议用gitee来下载。至于如何将github的库转到gitee上,同样可以参考我之前写的博客:

http://yiiyee.cn/blog/2020/04/21/%e4%bd%bf%e7%94%a8gitee%e4%b8%8b%e8%bd%bdgithub%e9%a1%b9%e7%9b%ae/

或者https://blog.csdn.net/luobing4365/article/details/105658274

1) edk2  仓库tianocore\edk2   仓库地址:https://github.com/tianocore/edk2.git
         这是包含固件开发环境的仓库,编译UEFI固件所需要的库都在其中。
2) edk2-platforms 仓库:tianocore\edk2-platforms
                仓库地址:https://github.com/tianocore/edk2-platforms.git
         各种平台的工作环境和相关的模块
3) ACPICA 仓库acpica\acpica  仓库地址:https://github.com/acpica/acpica.git
          ACPI组件框架(ACPI Component Architecture)工具,提供开源的iASL编译工具。

后面的这个是非必需的,不过建议下载,编程比较方便。
4) edk2-libc 仓库:tianocore\edk2-libc
           仓库地址:https://github.com/tianocore/edk2-libc.git
           UEFI下的StdLib库,可以使用C标准库进行UEFI的编程。

打开WSL(我的环境是Ubuntu18.04),建立工作目录,比如取名为MyWorkspce。并把上述需要的仓库代码git到本地,示例如下:

$ mkdir Myworkspace
$ git clone –recursive https://github.com/tianocore/edk2.git
$ git clone https://github.com/tianocore/edk2-platforms.git
$ git clone 
https://github.com/acpica/acpica.git

如需要编译使用StdLib库的程序,把edk2-libc库也git下来:

$ git clone https://github.com/tianocore/edk2-libc.git

下载后,我的目录夹如下所示:

UEFI开发探索56-使用WSL编译Arm架构的UEFI镜像_第1张图片

图1 EDK2的工作目录

安装编译所需工具

编译所需的工具如下:

1) Python2.7/Python3  Python解释器,我使用的是Python3;
2) uuid-dev 需要头文件uuid/uuid.h;
3) build-essential  包含make、gcc、g++等工具;
4) bison  词法生成器,用于GNU编译工具包的语法生成,acpica工具需要它;
5) flex  词法分析器,acpica工具需要它;

安装命令如下:

$ sudo apt install bison build-essential flex uuid-dev
$ sudo apt install python3 python3-distutils

检查安装的工具,在我的环境中是这样的:

$ make -v
GNU Make 4.1
$ gcc –version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
$ g++ –version
g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
$ python3 -V
Python 3.6.9

4 Arm跨平台编译工具链

在x86_64-linux上,可编译aarch64-elf的跨平台工具链可以这里下载:https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads。

可选择最新的编译器下载,带有’AArch64 ELF bare-metal target (aarch64-elf)’字样的是我们所需要的,注意是x86_64 Linux为host。

比如可以下载这个:gcc-arm-8.2-2019.01-x86_64-aarch64-elf.tar.xz,下载地址为https://developer.arm.com/-/media/Files/downloads/gnu-a/8.2-2019.01/gcc-arm-8.2-2019.01-x86_64-aarch64-elf.tar.xz。

在工作目录下建立文件夹toolchain,如图1,把跨平台编译解压到此处。

$ cd toolchain
$ tar xf gcc-arm-8.2-2019.01-x86_64-aarch64-elf.tar.xz

准备acpica工具和BaseTools

进入工作目录,编译acpica工具

$ make -C acpica/

在工作目录下,新建myexport.sh的批处理文件,写入如下内容:

export WORKSPACE=$PWD
export GCC5_AARCH64_PREFIX=$PWD/toolchain/gcc-arm-8.2-2019.01-x86_64-aarch64-elf/bin/aarch64-elf-
export PACKAGES_PATH=$PWD/edk2:$PWD/edk2-platforms:$PWD/edk2-libc
export IASL_PREFIX=$PWD/acpica/generate/unix/bin/
export PYTHON_COMMAND=/usr/bin/python3

将此批处理文件设置为可执行(chmod +x),然后编译BaseTools工具集:

$ source ./myexport.sh
$ source edk2/edksetup.sh
$ make -C edk2/BaseTools

编译所需要的固件和UEFI程序

为FVP AEMv8A平台编译固件:

$ build -a AARCH64 -t GCC5 -p edk2-platforms/Platform/ARM/VExpressPkg/ArmVExpress-FVP-AArch64.dsc -b DEBUG

为Arm Juno平台编译固件:

$ build -a AARCH64 -t GCC5 -p edk2-platforms/Platform/ARM/JunoPkg/ArmJuno.dsc -b DEBUG

我自己建立的、常用的包RobinPkg,将其拷贝到edk2-libc目录下,也可以编译里面的代码了,比如:

$ build -a AARCH64 -t GCC5 -p edk2-libc/RobinPkg/RobinPkg.dsc -m edk2-libc/RobinPkg/Applications/Luo2/Luo2.inf

所有生成的文件都在工作目录下的Build文件夹中。


补充一个小故事。

昨天下午,和同事调试飞腾的问题,我们想把现有的UEFI代码移植到飞腾FT-2000的平台上。

调试到一半,接到报告说,在UEFI driver中,PCIIO的protocol调用,放在mian函数中能正常工作;另外写了个函数,把这个调用放在函数中,由main函数调用,就无法正常工作了。

???,还有这种事?!

我看了下调试现场,还确实是。再看代码,读了几分钟,也看不出什么错误。

一瞬间,冒出了各种想法:驱动的回调函数在不同阶段被调用,全局变量在栈上被清除了?调用过程中,被其他事件打断,用了核心变量?……

尝试着把核心变量的地址和值打印出来,也没有错。

那种心情到现在我还记得非常清楚,好像之前搭建的对计算机的理解、对语言的理解、对UEFI体系的理解,在逐渐解体,出现裂痕,开始崩塌…

我实在无法理解,同样的调用,加一层函数就无法工作了?

兴趣突然高涨,我一定要找到我理解的盲点。抛弃看到的代码,根据需要的功能,自己重新实现了一遍。

编译,没有出错;找U盘拷贝文件,开机运行;进入UEFI Shell,加载执行:

工作正常!

想象中的大厦好像开始自动弥补裂缝,重新站好了。

还是同事眼神好,比较了新写的代码和原来的代码,发现某个参数多加了取值符,导致存入的位置全是错的。

在这个小插曲后,终于解决了飞腾遇到的所有设备访问问题,后续只要继续构建代码,调整细节就可以了。

感谢飞腾的张老师、合作厂商的兄弟以及这两周陪着我们调试的外协兄弟们,长沙见!

你可能感兴趣的:(UEFI开发)