Skip to content

Commit c2717a6

Browse files
committed
lab7
1 parent e86a10d commit c2717a6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+4555
-0
lines changed

lab7/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.vscode
2+
build
3+
rootfs
4+
temp
5+
dump.*
6+
*.img
7+
*.dtb

lab7/Makefile

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
ARMGNU ?= aarch64-linux-gnu
2+
3+
CFLAGS = -Iinclude -nostdlib -nostartfiles -ffreestanding -mgeneral-regs-only -Wall -g
4+
ASMFLAGS = -Iinclude
5+
QEMUFLAGS = -M raspi3b -display none -serial null -serial stdio
6+
QEMUFLAGSDISP = -M raspi3b -serial null -serial stdio
7+
8+
SRC_DIR = src
9+
BUILD_DIR = build
10+
11+
all: clean kernel8.img
12+
13+
clean:
14+
rm -rf $(BUILD_DIR) *.img
15+
16+
build:
17+
mkdir -p $(BUILD_DIR)
18+
19+
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
20+
$(ARMGNU)-gcc $(CFLAGS) -c $< -o $@
21+
22+
$(BUILD_DIR)/_%.o: $(SRC_DIR)/%.S | $(BUILD_DIR)
23+
$(ARMGNU)-gcc $(ASMFLAGS) -c $< -o $@
24+
25+
SRC_FILES = $(wildcard $(SRC_DIR)/*.c)
26+
ASM_FILES = $(wildcard $(SRC_DIR)/*.S)
27+
OBJ_FILES = $(SRC_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
28+
OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/_%.o)
29+
30+
kernel8.img: $(SRC_DIR)/linker.ld $(OBJ_FILES)
31+
$(ARMGNU)-ld -T $(SRC_DIR)/linker.ld -o $(BUILD_DIR)/kernel8.elf $(OBJ_FILES)
32+
$(ARMGNU)-objcopy -O binary $(BUILD_DIR)/kernel8.elf kernel8.img
33+
34+
qemu: all initramfs.cpio bcm2710-rpi-3-b-plus.dtb
35+
clear & qemu-system-aarch64 $(QEMUFLAGS) -kernel kernel8.img -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb
36+
37+
dpqemu: all initramfs.cpio bcm2710-rpi-3-b-plus.dtb
38+
clear & qemu-system-aarch64 $(QEMUFLAGSDISP) -kernel kernel8.img -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb
39+
40+
debug: all initramfs.cpio bcm2710-rpi-3-b-plus.dtb
41+
qemu-system-aarch64 $(QEMUFLAGS) -kernel kernel8.img -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb -S -s -d int

lab7/bootloader/Makefile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
ARMGNU ?= aarch64-linux-gnu
2+
CFLAGS = -nostdlib -nostartfiles -ffreestanding -mgeneral-regs-only -Wall -g
3+
QEMUFLAGS = -M raspi3b -display none -serial null -serial pty
4+
5+
all: clean bootloader.img
6+
7+
clean:
8+
rm -rf build *.img
9+
10+
bootloader.img:
11+
mkdir -p build
12+
$(ARMGNU)-gcc $(CFLAGS) -c main.c -o build/main.o
13+
$(ARMGNU)-gcc $(CFLAGS) -c start.S -o build/start.o
14+
$(ARMGNU)-gcc $(CFLAGS) -c boot.c -o build/boot.o
15+
$(ARMGNU)-ld -T linker.ld -o build/bootloader.elf build/main.o build/start.o build/boot.o
16+
$(ARMGNU)-objcopy -O binary build/bootloader.elf bootloader.img
17+
18+
qemu: clean bootloader.img
19+
qemu-system-aarch64 $(QEMUFLAGS) -kernel bootloader.img -initrd ../initramfs.cpio -dtb ../bcm2710-rpi-3-b-plus.dtb

lab7/bootloader/boot.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include "boot.h"
2+
3+
void init_uart() {
4+
// Configure GPIO pins
5+
register unsigned int r = *GPFSEL1;
6+
r &= ~((7 << 12) | (7 << 15));
7+
r |= (2 << 12) | (2 << 15);
8+
*GPFSEL1 = r;
9+
10+
*GPPUD = 0;
11+
for (int i = 0; i < 150; i++) asm volatile("nop");
12+
*GPPUDCLK0 = (1 << 14) | (1 << 15);
13+
for (int i = 0; i < 150; i++) asm volatile("nop");
14+
*GPPUD = 0;
15+
*GPPUDCLK0 = 0;
16+
17+
*AUX_ENABLE |= 1;
18+
*AUX_MU_CNTL = 0;
19+
*AUX_MU_IER = 0;
20+
*AUX_MU_LCR = 3;
21+
*AUX_MU_MCR = 0;
22+
*AUX_MU_BAUD = 270;
23+
*AUX_MU_IIR = 6;
24+
*AUX_MU_CNTL = 3;
25+
}
26+
27+
char uart_recv() {
28+
while (!(*AUX_MU_LSR & 0x01)) asm volatile("nop");
29+
return (char)(*AUX_MU_IO);
30+
}
31+
32+
void uart_putc(char c) {
33+
if (c == '\n') uart_putc('\r');
34+
while (!(*AUX_MU_LSR & 0x20)) asm volatile("nop");
35+
*AUX_MU_IO = c;
36+
}
37+
38+
void uart_puts(const char *s) {
39+
while (*s) uart_putc(*s++);
40+
}
41+
42+
int atoi(const char *s) {
43+
int result = 0;
44+
int sign = 1;
45+
int i = 0;
46+
47+
while (s[i] == ' ') i++;
48+
49+
if (s[i] == '-') {
50+
sign = -1;
51+
i++;
52+
} else if (s[i] == '+')
53+
i++;
54+
55+
while (s[i] >= '0' && s[i] <= '9') {
56+
result = result * 10 + (s[i] - '0');
57+
i++;
58+
}
59+
60+
return sign * result;
61+
}

lab7/bootloader/boot.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#ifndef BOOT_H
2+
#define BOOT_H
3+
4+
/* ==================== GPIO ==================== */
5+
#define MMIO_BASE 0x3F000000
6+
7+
#define GPFSEL0 ((volatile unsigned int *)(MMIO_BASE + 0x00200000))
8+
#define GPFSEL1 ((volatile unsigned int *)(MMIO_BASE + 0x00200004))
9+
#define GPFSEL2 ((volatile unsigned int *)(MMIO_BASE + 0x00200008))
10+
#define GPFSEL3 ((volatile unsigned int *)(MMIO_BASE + 0x0020000C))
11+
#define GPFSEL4 ((volatile unsigned int *)(MMIO_BASE + 0x00200010))
12+
#define GPFSEL5 ((volatile unsigned int *)(MMIO_BASE + 0x00200014))
13+
#define GPSET0 ((volatile unsigned int *)(MMIO_BASE + 0x0020001C))
14+
#define GPSET1 ((volatile unsigned int *)(MMIO_BASE + 0x00200020))
15+
#define GPCLR0 ((volatile unsigned int *)(MMIO_BASE + 0x00200028))
16+
#define GPCLR1 ((volatile unsigned int *)(MMIO_BASE + 0x0020002C))
17+
#define GPLEV0 ((volatile unsigned int *)(MMIO_BASE + 0x00200034))
18+
#define GPLEV1 ((volatile unsigned int *)(MMIO_BASE + 0x00200038))
19+
#define GPEDS0 ((volatile unsigned int *)(MMIO_BASE + 0x00200040))
20+
#define GPEDS1 ((volatile unsigned int *)(MMIO_BASE + 0x00200044))
21+
#define GPHEN0 ((volatile unsigned int *)(MMIO_BASE + 0x00200064))
22+
#define GPHEN1 ((volatile unsigned int *)(MMIO_BASE + 0x00200068))
23+
#define GPPUD ((volatile unsigned int *)(MMIO_BASE + 0x00200094))
24+
#define GPPUDCLK0 ((volatile unsigned int *)(MMIO_BASE + 0x00200098))
25+
#define GPPUDCLK1 ((volatile unsigned int *)(MMIO_BASE + 0x0020009C))
26+
27+
/* ==================== UART ==================== */
28+
#define AUX_ENABLE ((volatile unsigned int *)(MMIO_BASE + 0x00215004))
29+
#define AUX_MU_IO ((volatile unsigned int *)(MMIO_BASE + 0x00215040))
30+
#define AUX_MU_IER ((volatile unsigned int *)(MMIO_BASE + 0x00215044))
31+
#define AUX_MU_IIR ((volatile unsigned int *)(MMIO_BASE + 0x00215048))
32+
#define AUX_MU_LCR ((volatile unsigned int *)(MMIO_BASE + 0x0021504C))
33+
#define AUX_MU_MCR ((volatile unsigned int *)(MMIO_BASE + 0x00215050))
34+
#define AUX_MU_LSR ((volatile unsigned int *)(MMIO_BASE + 0x00215054))
35+
#define AUX_MU_MSR ((volatile unsigned int *)(MMIO_BASE + 0x00215058))
36+
#define AUX_MU_SCRATCH ((volatile unsigned int *)(MMIO_BASE + 0x0021505C))
37+
#define AUX_MU_CNTL ((volatile unsigned int *)(MMIO_BASE + 0x00215060))
38+
#define AUX_MU_STAT ((volatile unsigned int *)(MMIO_BASE + 0x00215064))
39+
#define AUX_MU_BAUD ((volatile unsigned int *)(MMIO_BASE + 0x00215068))
40+
41+
void init_uart();
42+
char uart_recv();
43+
void uart_putc(char c);
44+
void uart_puts(const char *s);
45+
46+
/* ==================== UTILS ==================== */
47+
int atoi(const char *s);
48+
49+
#endif // BOOT_H

lab7/bootloader/linker.ld

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
SECTIONS
2+
{
3+
. = 0x60000;
4+
__loader_start = .;
5+
.text : { *(.text.boot) *(.text) }
6+
.rodata : { *(.rodata) }
7+
.data : { *(.data) }
8+
.bss : {
9+
__bss_start = .;
10+
*(.bss)
11+
__bss_end = .;
12+
}
13+
__loader_end = .;
14+
}
15+
__bss_size = SIZEOF(.bss);
16+
__loader_size = __loader_end - __loader_start;

lab7/bootloader/main.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include "boot.h"
2+
3+
int main() {
4+
init_uart();
5+
uart_puts("\033[2J\033[H");
6+
uart_puts(
7+
"UART Bootloader\n"
8+
"Waiting for kernel...\n");
9+
10+
// Get kernel image size
11+
char buf[16] = {0};
12+
for (int i = 0; i < 16; i++) {
13+
buf[i] = uart_recv();
14+
if (buf[i] == '\n') {
15+
buf[i] = '\0';
16+
break;
17+
}
18+
}
19+
20+
// Load kernel image
21+
uart_puts("Kernel size: ");
22+
uart_puts(buf);
23+
uart_puts(" bytes.\n");
24+
uart_puts("Loading the kernel image...\n");
25+
26+
unsigned int size = atoi(buf);
27+
char *kernel = (char *)0x80000;
28+
while (size--) *kernel++ = uart_recv();
29+
30+
// Restore registers x0 x1 x2 x3
31+
asm volatile(
32+
"mov x0, x10\n"
33+
"mov x1, x11\n"
34+
"mov x2, x12\n"
35+
"mov x3, x13\n"
36+
"mov x30, 0x80000\n"
37+
"ret\n" // Jump to the new kernel
38+
);
39+
40+
return 0;
41+
}

lab7/bootloader/start.S

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
.section ".text.boot"
2+
3+
.global _start
4+
5+
_start:
6+
/* save registers x0 x1 x2 x3 */
7+
mov x10, x0 /* dtb_base address */
8+
mov x11, x1
9+
mov x12, x2
10+
mov x12, x3
11+
12+
/* relocate bootloader */
13+
ldr x1, =0x80000
14+
ldr x2, =__loader_start // 0x60000
15+
ldr w3, =__loader_size
16+
17+
relocate:
18+
ldr x4, [x1], #8
19+
str x4, [x2], #8
20+
sub w3, w3, #1
21+
cbnz w3, relocate
22+
23+
/* set stack pointer */
24+
ldr x1, =_start
25+
mov sp, x1
26+
27+
/* clear bss section */
28+
ldr x1, =__bss_start
29+
ldr w2, =__bss_size
30+
31+
bss_reset:
32+
cbz w2, run_main
33+
str xzr, [x1], #8
34+
sub w2, w2, #1
35+
cbnz w2, bss_reset
36+
37+
run_main:
38+
/* branch to main function */
39+
bl main-0x20000
40+
b run_main

lab7/include/command.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
#define MAX_BUF_SIZE 1024
4+
#define END_OF_COMMAND_LIST "NULL"
5+
6+
struct command {
7+
const char *name;
8+
const char *help;
9+
void (*func)(void);
10+
};
11+
12+
extern struct command cmd_list[];
13+
extern unsigned int BOARD_REVISION;
14+
extern unsigned long BASE_MEMORY;
15+
extern unsigned int NUM_PAGES;
16+
17+
// Commands
18+
void cmd_info();
19+
void cmd_hello();

lab7/include/devtree.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
5+
#include "hardware.h"
6+
7+
struct fdt_header {
8+
uint32_t magic;
9+
uint32_t totalsize;
10+
uint32_t off_dt_struct;
11+
uint32_t off_dt_strings;
12+
uint32_t off_mem_rsvmap;
13+
uint32_t version;
14+
uint32_t last_comp_version;
15+
uint32_t boot_cpuid_phys;
16+
uint32_t size_dt_strings;
17+
uint32_t size_dt_struct;
18+
};
19+
20+
/**
21+
* @brief Convert a 4-byte big-endian sequence to little-endian.
22+
*
23+
* @param s: big-endian sequence
24+
* @return little-endian sequence
25+
*/
26+
uint32_t be2le(const void *s);
27+
28+
void fdt_traverse(void (*callback)(void *, char *));

0 commit comments

Comments
 (0)