1. 概述
在linaro官网看到一个很好的git,里边的代码量不大,但是是一个很好的学习用例,下边记录一下学习的过程。
2. 代码下载
链接: 代码链接
https://git.linaro.org/virtualization/qemu-tztest.git/
3. 编译运行
3.1 安装相关工具
sudo apt-get install qemu-system-aarch64
3.2 配置
在源码目录下运行:
./configure --arch=aarch64
自动生成aarch64.mk
CFLAGS += -DFORMAT="elf64-littleaarch64" -mcmodel=large
CFLAGS += -DARCH="aarch64"
CFLAGS += -DAARCH64
3.3 编译
在源码目录下执行make
3.4 运行
在根目录的Makefile文件中加入如下内容(复制的时候去掉"+"号):
diff --git a/Makefile b/Makefile
index dbdc10a..f5e63aa 100644
--- a/Makefile
+++ b/Makefile
@@ -31,7 +31,7 @@ CFLAGS += -I$(ARCH) -I../common/$(ARCH) -I../common
CFLAGS += $(call cc-option, -fomit-frame-pointer, "")
CFLAGS += $(call cc-option, -fno-stack-protector, "")
CFLAGS += $(call cc-option, -fno-stack-protector-all, "")
-
+CFLAGS += -DDEBUG
export CFLAGS
BIOS_IMAGE = tztest.img
@@ -71,6 +71,11 @@ $(EL0_S_IMAGE):
$(EL0_NS_IMAGE):
$(MAKE) -C el0/nonsecure all
+run:
+ qemu-system-aarch64 -bios tztest.img -machine virt,secure=on -cpu cortex-a57 -serial stdio
+
clean:
$(MAKE) -C libcflat clean
$(MAKE) -C el3 clean
执行:
make run
运行LOG如下:
qemu-system-aarch64 -bios tztest.img -machine virt,secure=on -cpu cortex-a57 -serial stdio
VNC server running on 127.0.0.1:5900
#EL3 started...350377984
rambase:40000000, ptbase:40040000
[DEBUG] mem_unmap_va (secure): unmapped PTE 0x40043000 (VA:0x0, PA:0x0)
[DEBUG] mem_map_pa (secure): mapped VA:0x40055000 to PA:0x40055000 - PTE:0x400512a8 (0x40055443)
[DEBUG] mem_map_pa (secure): mapped VA:0xf001000000 to PA:0x40054000 - PTE:0x40055000 (0x40054443)
[DEBUG] mem_map_pa (secure): mapped VA:0xf001001000 to PA:0x40056000 - PTE:0x40055008 (0x40056443)EL1 (�e) started...
[DEBUG] mem_unmap_va (secure): unmapped PTE 0x41043080 (VA:0x10000, PA:0x10000)
[DEBUG] mem_map_pa (secure): mapped VA:0x41058000 to PA:0x41058000 - PTE:0x410552c0 (0x41058443)
[DEBUG] mem_map_pa (secure): mapped VA:0xc001000000 to PA:0x41057000 - PTE:0x41058000 (0x41057443)
[DEBUG] mem_map_pa (secure): mapped VA:0xc001000000 to PA:0x40054000 - PTE:0x41058000 (0x40054443)
[DEBUG] mem_map_pa (secure): mapped VA:0x41059000 to PA:0x41059000 - PTE:0x410552c8 (0x41059443)
[DEBUG] mem_map_pa (secure): mapped VA:0x4105a000 to PA:0x4105a000 - PTE:0x410552d0 (0x4105a443)
[DEBUG] mem_map_pa (secure): mapped VA:0xf001001000 to PA:0x40056000 - PTE:0x4105a008 (0x40056443)
[DEBUG] mem_map_pa (secure): mapped VA:0x50000 to PA:0x50000 - PTE:0x41043280 (0x50443)
[DEBUG] el1_load_el0 (secure): Loading aarch64 EL0 test image...
[DEBUG] mem_map_pa (secure): mapped VA:0x51000 to PA:0x51000 - PTE:0x41043288 (0x51443)
[DEBUG] mem_map_pa (secure): mapped VA:0x52000 to PA:0x52000 - PTE:0x41043290 (0x52443)
[DEBUG] mem_map_pa (secure): mapped VA:0x53000 to PA:0x53000 - PTE:0x41043298 (0x53443)
[DEBUG] mem_map_pa (secure): mapped VA:0x54000 to PA:0x54000 - PTE:0x410432a0 (0x54443)
[DEBUG] mem_map_pa (secure): mapped VA:0x55000 to PA:0x55000 - PTE:0x410432a8 (0x55443)
[DEBUG] mem_map_pa (secure): mapped VA:0x56000 to PA:0x56000 - PTE:0x410432b0 (0x56443)
[DEBUG] mem_map_pa (secure): mapped VA:0x57000 to PA:0x57000 - PTE:0x410432b8 (0x57443)
[DEBUG] mem_map_pa (secure): mapped VA:0x58000 to PA:0x58000 - PTE:0x410432c0 (0x58443)
[DEBUG] mem_map_pa (secure): mapped VA:0x59000 to PA:0x59000 - PTE:0x410432c8 (0x59443)
[DEBUG] mem_map_pa (secure): mapped VA:0x5a000 to PA:0x5a000 - PTE:0x410432d0 (0x5a443)
4. 代码编译
4.1 根目录Makefile
# 定义目标对象
BIOS_IMAGE = tztest.img
LIBCFLAT = libcflat.a
EL3_IMAGE = el3/el3.bin
EL1_S_IMAGE = el1/secure/el1_sec.bin
EL1_NS_IMAGE = el1/nonsecure/el1_nsec.bin
EL0_S_IMAGE = el0/secure/el0_sec.elf
EL0_NS_IMAGE = el0/nonsecure/el0_nsec.elf
# tztest.img编译与依赖,将el3.bin el1_sec.bin等文件打包成tztest.img文件
$(BIOS_IMAGE): $(LIBCFLAT) $(EL3_IMAGE) $(EL1_S_IMAGE) $(EL1_NS_IMAGE) \
$(EL0_S_IMAGE) $(EL0_NS_IMAGE)
dd if=$(EL3_IMAGE) of=$@ 2> /dev/null
dd oflag=seek_bytes seek=65536 if=$(EL1_S_IMAGE) of=$@ 2> /dev/null
dd oflag=seek_bytes seek=131072 if=$(EL1_NS_IMAGE) of=$@ 2> /dev/null
dd oflag=seek_bytes seek=196608 if=$(EL0_NS_IMAGE) of=$@ 2> /dev/null
dd oflag=seek_bytes seek=327680 if=$(EL0_S_IMAGE) of=$@ 2> /dev/null
chmod +x $(BIOS_IMAGE)
# 编译一个轻量级的libc
$(LIBCFLAT):
$(MAKE) -C libcflat all
# 编译el3的image
$(EL3_IMAGE):
$(MAKE) -C el3 all
# 编译secure el1的image
$(EL1_S_IMAGE):
$(MAKE) -C el1/secure all
# 编译non secure el1的镜像
$(EL1_NS_IMAGE):
$(MAKE) -C el1/nonsecure all
# 编译secure el0的镜像
$(EL0_S_IMAGE):
$(MAKE) -C el0/secure all
# 编译non seucre el0的镜像
$(EL0_NS_IMAGE):
$(MAKE) -C el0/nonsecure all
4.1.1 shell中dd指令
dd if=$(EL3_IMAGE) of=$@ 2> /dev/null
2> /dev/null是将错误信息重定向,不输出,遇到报错,不在终端上输出错误信息
dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。
- if=文件名:输入文件名,缺省为标准输入。即指定源文件。< if=input file >
- of=文件名:输出文件名,缺省为标准输出。即指定目的文件。< of=output file >
- ibs=bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节。
obs=bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节。
bs=bytes:同时设置读入/输出的块大小为bytes个字节。 - cbs=bytes:一次转换bytes个字节,即指定转换缓冲区大小。
- skip=blocks:从输入文件开头跳过blocks个块后再开始复制。
- seek=blocks:从输出文件开头跳过blocks个块后再开始复制。
4.2 el3/Makefile
这个里边记录一个Makefile的VPATH,如下:
VPATH = $(ARCH):../common/$(ARCH):../common:../tztest/el3:../tztest
表示可以自动找到这些目录下边的.c和.S等源文件,不需要加入目录名,如下:
EL3_OBJS = el3_init.o \
el3_exception.o \
el3.o \
el3_monitor_asm.o \
mem_util.o \
builtins.o \
tztest.o \
tztest_el3.o
tztest_el3.c文件在./tztest/el3/tztest_el3.c路径下,我们加入VPATH路径后,就不需要在obj上加入文件夹的名字了,编译器会自动到这些目录下边搜索源码。
5. 汇编中加入打印LOG
virt平台的UART地址:
#define UART0_BASE 0x09000000
通过下边方法打印LOG
ldr x0, =0x09000000
ldr x1, =35 //printf "#"
str x1, [x0]
str x1, [x0]
str x1, [x0]
str x1, [x0]
str x1, [x0]
LOG打印如下:
多处的#####都是我们打印的(编译的时候记得make clean && make && make run,才能生效,Makefile写的不太好,导致根目录增量编译的时候不生效)
qemu-system-aarch64 -bios tztest.img -machine virt,secure=on -cpu cortex-a57 -serial stdio
VNC server running on 127.0.0.1:5900
#####EL3 started...23025664
in the end, have fun…