Write bootloader for raspberry pi 3
We need three files:
- kernel.ld: define the memory layout and tell the hardware where to find entry.S.
- entry.S: run on single core, do initialization and jump to start.c.
- start.c: first code.
Compile to the kernel image:
- Link
entry.S
andkernel.ld
to createkernel.elf
- Build
kernel.img
bykernel.elf
- Boot qemu with
kernel.img
kernel.ld #
- ENTRY( _xxx ): tell system to find _entry for the following execution
- 0x80000: first code will put at
0x800000
because 0 ~ 0x80000 are for io-mapping in arm64 - text: put codes
- data: initialized variable
- bss: uinitialized variable
ENTRY( _entry )
SECTIONS
{
. = 0x80000;
.text :
{
*(.text)
}
.data :
{
*(.data)
}
.bss ALIGN(16) (NOLOAD) :
{
__bss_start = .;
*(.bss)
__bss_end = .;
}
_end = .;
}
entry.S #
global _entry
: letkernel.ld
locate
.section .text
.global _entry
_entry:
mrs x1, MPIDR_EL1 // Read Register to x1
and x1, x1, #3 // Extract cpu_id from x1
cbz x1, 2f // If cpu=0, jump to 2
1:
wfe // Wait for Event instruction
b 1b // Jump to 1
2:
ldr x1, =_entry // Load the address of _entry to x1
mov sp, x1 // move stack pointer to x1
// clear bss
ldr x1, =__bss_start // Load __bss_start to x1
ldr x2, =__bss_end // Load __bss_end to x2
3:
cmp x1, x2 // Compare x1 and x2
beq 4f // if x1=x2, jump to 4
str xzr, [x1], #8
sub x2, x2, #1
cbnz x2, 3b
4:
bl start // Jump to start function in C
b 1b // Halt this core if return
start.c #
void
start()
{
while(1){}
}
Makefile #
TOOLCHAIN_PREFIX = aarch64-linux-gnu-
CC = $(TOOLCHAIN_PREFIX)gcc
LD = $(TOOLCHAIN_PREFIX)ld
OBJCPY = $(TOOLCHAIN_PREFIX)objcopy
CFLAGS = -Wall
SRCS = start.c
OBJS = $(SRCS:.c=.o)
all: clean kernel.img
entry.o: entry.S
$(CC) $(CFLAGS) -c entry.S -o entry.o
# Rule to compile .c files to .o files
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# Linking the object files to create kernel.elf
kernel.elf: entry.o
$(LD) -T kernel.ld -o kernel.elf entry.o
# Convert kernel.elf to kernel.img
kernel.img: kernel.elf
$(OBJCPY) -O binary kernel.elf kernel.img
clean:
rm -f *.o kernel.elf kernel.img
qemu: kernel.img
qemu-system-aarch64 -M raspi3b -kernel kernel.img -display none -serial null -serial stdio