介绍
俗称万事开头难,最麻烦的确实也是第一步启动,关于启动相关的实际上可以说很多,但是由于篇幅原因以及作者自身水平有限就不过多展开。在本系列文章只需要知道有bootloader
或者bios
会负责将编译好的kernel
代码放到指定的位置,PC指向起始代码并且开始执行即可。
所以我们的第一个目标就是搭建一个代码框架,编写启动代码,并且能顺利跳到我们的main
函数。
主要涉及到的文件及其作用
-
- boot.S 启动代码,跳转到我们真正的入口函数
-
- kernel.ld gcc链接脚本,负责将目标文件按脚本链接成为一个可执行文件
-
- main.c 真正的入口函数所在的源文件
涉及到的工具
-
- make
-
- gcc/ld
-
- qemu
核心代码
arch/arm/boot/boot.S
:
.section ".text.boot"
.p2align 2
.global _start
_start:
// shut off extra cores
mrc p15, 0, r5, c0, c0, 5
and r5, r5, #3
cmp r5, #0
bne halt
ldr r5, =_start
mov sp, r5
ldr r3, =kernel_main
blx r3
halt:
wfe
b halt
简单说明:因为raspi2b使用的bcm2709为4核cpu,在这里仅使用cpu0,所以启动代码中将其他核进入死循环,而将cpu0的pc指向kernel_main
处并且运行
运行结果
为了便于观察实验结果,x86会预先在vga上打印调试信息,raspi2b会在串口上打印调试信息。相关代码是直接拷贝其他教程,仅作为临时使用。
执行以下命令:
. set_raspi2b.sh
make
make qemu
如果执行无意外的话,会出现如下输出:
...(省略编译过程信息输出)
arm-linux-gnueabihf-objcopy -O binary image.elf image
arm-linux-gnueabihf-objdump -S image.elf > image.asm
qemu-system-aarch64 -M raspi2b -kernel image -serial null -serial stdio
Hello World!