ARM TZ学习与实验(一)

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…

猜你喜欢

转载自blog.csdn.net/weixin_47139576/article/details/131739927