image.png

之前的文章XXX中我们提到了ATF基本概念和系统启动流程,然后搭建了qemu运行开源代码的基础。可以说是万事俱备只欠东风了。思考下一步怎么写这个系列,还是按照周贺贺老师的收费课程顺序来挑战下,不过其是收费的,笔者肯定是不会买的,找了一个知乎大神lgjjeff的芯片启动专栏文章:https://www.zhihu.com/column/c_1513091402841554944

然后结合我们的具体qemu运行代码,妥妥的在实践中学习。

福利:这里先给出一个周贺贺老师的完整资料: Armv8/armv9架构入门指南根据ARM官网DEN0024A_v8_architecture_PG_1.0.pdf翻译整理而来的,也可以去看英文的。

1. 大软件模型

周贺贺老师本小节的视频是免费公开的,大家可以自己去看: https://www.bilibili.com/cheese/play/ep92791?query_from=0&search_id=5894568997539276737&search_query=ATF+ARM&csource=common_hpsearch_null_null&spm_id_from=333.337.search-card.all.click

image.png

上图是目前流行的一个软件框架,不仅限于安卓和linux,底层还有很多其他固件,从而巩固安全的需求。

image.png

异常中断是ARM架构的重要内容。上图是异常等级的切换模型。

image.png

切程序地址需要异常向量表,需要异常指令触发异常。异常就会进入高级别再切回来,就像V字形。

image.png reset的时候也可以进行异常等级切换。这个是EL3,没有high level就需要使用warm reset。

image.png 对于64位系统,上层可以运行32位。但是上层64位,下层不可以32位。

image.png 上面是secure boot的过程,里面各个固件的异常等级不一样,就需要使用异常跳来跳去。

image.png 上图是一个设计的例子,里面uboot跳kernel需要smc到BL31再eret到kernel

2. 编译过程探究

2.1 log打印

image.png

按照之前的流程运行起来后,首先我们应该做点什么呢?

那必须上手改改代码打点log小试身手啊。然后再探索下这个代码是怎么编译运行的,这样就能完全控制了这套代码。

例如上面的打印:BL1: v2.10.0,我们使用vscode在atf代码里面搜索“BL1:”

image.png

NOTICE(FIRMWARE_WELCOME_STR);
NOTICE("hello BL1: %s\n", version_string);
NOTICE("BL1: %s\n", build_message);

修改代码加一个hello,然后make run后可以看到:

image.png

可见NOTICE进行了打印,但是我们下面的INFO并没有打印

#if LOG_LEVEL >= LOG_LEVEL_INFO
# define INFO(...)    tf_log(LOG_MARKER_INFO __VA_ARGS__)
#else
# define INFO(...)    no_tf_log(LOG_MARKER_INFO __VA_ARGS__)
#endif

LOG_LEVEL控制了打印级别,在根目录的Makefile文件中

ifneq (${DEBUG}, 0)
    BUILD_TYPE    :=    debug
    TF_CFLAGS    +=    -g -gdwarf-4
    ASFLAGS        +=    -g -Wa,-gdwarf-4

    # Use LOG_LEVEL_INFO by default for debug builds
    LOG_LEVEL    :=    40
else
    BUILD_TYPE    :=    release
    # Use LOG_LEVEL_NOTICE by default for release builds
    LOG_LEVEL    :=    20
endif #(Debug)

include/common/debug.h中的定义如下。可见编译atf的时候并没有打开${DEBUG},一个简单粗暴的方式就是在使用LOG_LEVEL的地方直接重定义

#define LOG_LEVEL_NONE            U(0)
#define LOG_LEVEL_ERROR            U(10)
#define LOG_LEVEL_NOTICE        U(20)
#define LOG_LEVEL_WARNING        U(30)
#define LOG_LEVEL_INFO            U(40)
#define LOG_LEVEL_VERBOSE        U(50)

#undef LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_INFO

这样重新make run下就可以看到:

image.png

2.2 去掉默认gdb

make run是先编译后运行, make -f qemu_v8.mk run-only是只运行

image.png

qemu运行gdb就需要加这个-s -S的参数,我们可以去掉:

image.png 这样一启动,不用输入c就可以直接启动了。

2.3 只编译atf

make run是全编,但是比较慢。比如我们只对atf关心,那么来一探究竟吧,在arm/optee/build/qemu_v8.mk中

115 TARGET_DEPS := arm-tf buildroot linux optee-os qemu

all: $(TARGET_DEPS)

487 run: all                
488     $(MAKE) run-only

arm-tf的编译如下:

218 arm-tf: $(BL32_DEPS) $(BL33_DEPS)
219     $(TF_A_EXPORTS) $(MAKE) -C $(TF_A_PATH) $(TF_A_FLAGS) all fip
220     mkdir -p $(BINARIES_PATH)

那么就直接:make arm-tf就可以了

在编译make all的依赖里面还有buildroot。这个东西有什么用?

大家都知道linux内核有make menuconfig的配置,非常方便裁剪,图形化的界面。但是对于大软件模型,除了Linux内核之外还有很多固件、应用、文件系统等软件,这些软件是否也可以有一个图形化的配置工具进行裁剪,这就诞生了buildroot。关于buildroot可以单独写一个文章,总之对于大软件系统,必须有一个这样的统一编译工具。

image.png 可以看到DEBUG的值是0,那么怎么改为1呢?

make arm-tf DEBUG=1

后记:

万事开头难,关于ATF有非常多的知识点。而且其跟secure boot联系紧密,这篇文章也只是开头的开头,还没到代码分析,下一篇开始代码分析。

虽然写的不太深入,但是跟着这系列文章去学习ATF,相信会有一个入门的效果。

results matching ""

    No results matching ""