Skip to content

Commit

Permalink
lab4
Browse files Browse the repository at this point in the history
  • Loading branch information
ccyid committed Jun 12, 2024
1 parent 207c56d commit ebe13a3
Show file tree
Hide file tree
Showing 38 changed files with 2,337 additions and 0 deletions.
6 changes: 6 additions & 0 deletions lab4/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.vscode
build
rootfs
temp
*.img
*.dtb
36 changes: 36 additions & 0 deletions lab4/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
ARMGNU ?= aarch64-linux-gnu

CFLAGS = -Iinclude -nostdlib -nostartfiles -ffreestanding -mgeneral-regs-only -Wall -g
ASMFLAGS = -Iinclude
QEMUFLAGS = -M raspi3b -display none -serial null -serial stdio

SRC_DIR = src
BUILD_DIR = build

all: clean kernel8.img

clean:
rm -rf $(BUILD_DIR) *.img

$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
mkdir -p $(@D)
$(ARMGNU)-gcc $(CFLAGS) -c $< -o $@

$(BUILD_DIR)/_%.o: %.S
$(ARMGNU)-gcc $(ASMFLAGS) -c $< -o $@

SRC_FILES = $(wildcard $(SRC_DIR)/*.c)
ASM_FILES = $(wildcard *.S)
OBJ_FILES = $(SRC_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
OBJ_FILES += $(ASM_FILES:%.S=$(BUILD_DIR)/_%.o)

kernel8.img: linker.ld $(OBJ_FILES)
$(ARMGNU)-ld -T linker.ld -o $(BUILD_DIR)/kernel8.elf $(OBJ_FILES)
$(ARMGNU)-objcopy -O binary $(BUILD_DIR)/kernel8.elf kernel8.img

qemu: all kernel8.img initramfs.cpio bcm2710-rpi-3-b-plus.dtb
clear
qemu-system-aarch64 $(QEMUFLAGS) -kernel kernel8.img -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb

debug: all kernel8.img initramfs.cpio bcm2710-rpi-3-b-plus.dtb
qemu-system-aarch64 $(QEMUFLAGS) -kernel kernel8.img -initrd initramfs.cpio -dtb bcm2710-rpi-3-b-plus.dtb -S -s -d int
19 changes: 19 additions & 0 deletions lab4/bootloader/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
ARMGNU ?= aarch64-linux-gnu
CFLAGS = -nostdlib -nostartfiles -ffreestanding -mgeneral-regs-only -Wall -g
QEMUFLAGS = -M raspi3b -display none -serial null -serial pty

all: clean bootloader.img

clean:
rm -rf build *.img

bootloader.img:
mkdir -p build
$(ARMGNU)-gcc $(CFLAGS) -c main.c -o build/main.o
$(ARMGNU)-gcc $(CFLAGS) -c start.S -o build/start.o
$(ARMGNU)-gcc $(CFLAGS) -c boot.c -o build/boot.o
$(ARMGNU)-ld -T linker.ld -o build/bootloader.elf build/main.o build/start.o build/boot.o
$(ARMGNU)-objcopy -O binary build/bootloader.elf bootloader.img

qemu: clean bootloader.img
qemu-system-aarch64 $(QEMUFLAGS) -kernel bootloader.img -initrd ../initramfs.cpio -dtb ../bcm2710-rpi-3-b-plus.dtb
61 changes: 61 additions & 0 deletions lab4/bootloader/boot.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "boot.h"

void init_uart() {
// Configure GPIO pins
register unsigned int r = *GPFSEL1;
r &= ~((7 << 12) | (7 << 15));
r |= (2 << 12) | (2 << 15);
*GPFSEL1 = r;

*GPPUD = 0;
for (int i = 0; i < 150; i++) asm volatile("nop");
*GPPUDCLK0 = (1 << 14) | (1 << 15);
for (int i = 0; i < 150; i++) asm volatile("nop");
*GPPUD = 0;
*GPPUDCLK0 = 0;

*AUX_ENABLE |= 1;
*AUX_MU_CNTL = 0;
*AUX_MU_IER = 0;
*AUX_MU_LCR = 3;
*AUX_MU_MCR = 0;
*AUX_MU_BAUD = 270;
*AUX_MU_IIR = 6;
*AUX_MU_CNTL = 3;
}

char uart_recv() {
while (!(*AUX_MU_LSR & 0x01)) asm volatile("nop");
return (char)(*AUX_MU_IO);
}

void uart_putc(char c) {
if (c == '\n') uart_putc('\r');
while (!(*AUX_MU_LSR & 0x20)) asm volatile("nop");
*AUX_MU_IO = c;
}

void uart_puts(const char *s) {
while (*s) uart_putc(*s++);
}

int atoi(const char *s) {
int result = 0;
int sign = 1;
int i = 0;

while (s[i] == ' ') i++;

if (s[i] == '-') {
sign = -1;
i++;
} else if (s[i] == '+')
i++;

while (s[i] >= '0' && s[i] <= '9') {
result = result * 10 + (s[i] - '0');
i++;
}

return sign * result;
}
49 changes: 49 additions & 0 deletions lab4/bootloader/boot.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef BOOT_H
#define BOOT_H

/* ==================== GPIO ==================== */
#define MMIO_BASE 0x3F000000

#define GPFSEL0 ((volatile unsigned int *)(MMIO_BASE + 0x00200000))
#define GPFSEL1 ((volatile unsigned int *)(MMIO_BASE + 0x00200004))
#define GPFSEL2 ((volatile unsigned int *)(MMIO_BASE + 0x00200008))
#define GPFSEL3 ((volatile unsigned int *)(MMIO_BASE + 0x0020000C))
#define GPFSEL4 ((volatile unsigned int *)(MMIO_BASE + 0x00200010))
#define GPFSEL5 ((volatile unsigned int *)(MMIO_BASE + 0x00200014))
#define GPSET0 ((volatile unsigned int *)(MMIO_BASE + 0x0020001C))
#define GPSET1 ((volatile unsigned int *)(MMIO_BASE + 0x00200020))
#define GPCLR0 ((volatile unsigned int *)(MMIO_BASE + 0x00200028))
#define GPCLR1 ((volatile unsigned int *)(MMIO_BASE + 0x0020002C))
#define GPLEV0 ((volatile unsigned int *)(MMIO_BASE + 0x00200034))
#define GPLEV1 ((volatile unsigned int *)(MMIO_BASE + 0x00200038))
#define GPEDS0 ((volatile unsigned int *)(MMIO_BASE + 0x00200040))
#define GPEDS1 ((volatile unsigned int *)(MMIO_BASE + 0x00200044))
#define GPHEN0 ((volatile unsigned int *)(MMIO_BASE + 0x00200064))
#define GPHEN1 ((volatile unsigned int *)(MMIO_BASE + 0x00200068))
#define GPPUD ((volatile unsigned int *)(MMIO_BASE + 0x00200094))
#define GPPUDCLK0 ((volatile unsigned int *)(MMIO_BASE + 0x00200098))
#define GPPUDCLK1 ((volatile unsigned int *)(MMIO_BASE + 0x0020009C))

/* ==================== UART ==================== */
#define AUX_ENABLE ((volatile unsigned int *)(MMIO_BASE + 0x00215004))
#define AUX_MU_IO ((volatile unsigned int *)(MMIO_BASE + 0x00215040))
#define AUX_MU_IER ((volatile unsigned int *)(MMIO_BASE + 0x00215044))
#define AUX_MU_IIR ((volatile unsigned int *)(MMIO_BASE + 0x00215048))
#define AUX_MU_LCR ((volatile unsigned int *)(MMIO_BASE + 0x0021504C))
#define AUX_MU_MCR ((volatile unsigned int *)(MMIO_BASE + 0x00215050))
#define AUX_MU_LSR ((volatile unsigned int *)(MMIO_BASE + 0x00215054))
#define AUX_MU_MSR ((volatile unsigned int *)(MMIO_BASE + 0x00215058))
#define AUX_MU_SCRATCH ((volatile unsigned int *)(MMIO_BASE + 0x0021505C))
#define AUX_MU_CNTL ((volatile unsigned int *)(MMIO_BASE + 0x00215060))
#define AUX_MU_STAT ((volatile unsigned int *)(MMIO_BASE + 0x00215064))
#define AUX_MU_BAUD ((volatile unsigned int *)(MMIO_BASE + 0x00215068))

void init_uart();
char uart_recv();
void uart_putc(char c);
void uart_puts(const char *s);

/* ==================== UTILS ==================== */
int atoi(const char *s);

#endif // BOOT_H
16 changes: 16 additions & 0 deletions lab4/bootloader/linker.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
SECTIONS
{
. = 0x60000;
__loader_start = .;
.text : { *(.text.boot) *(.text) }
.rodata : { *(.rodata) }
.data : { *(.data) }
.bss : {
__bss_start = .;
*(.bss)
__bss_end = .;
}
__loader_end = .;
}
__bss_size = (__bss_end - __bss_start) >> 3;
__loader_size = (__loader_end - __loader_start) >> 3;
42 changes: 42 additions & 0 deletions lab4/bootloader/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "boot.h"

int main() {
init_uart();
uart_puts("\033[2J\033[H");
uart_puts(
"UART Bootloader\n"
"Waiting for kernel...\n");

// Get kernel image size
char buf[16] = {0};
for (int i = 0; i < 16; i++) {
buf[i] = uart_recv();
if (buf[i] == '\n') {
buf[i] = '\0';
break;
}
}

// Load kernel image
uart_puts("Kernel size: ");
uart_puts(buf);
uart_puts(" bytes.\n");
uart_puts("Loading the kernel image...\n");

unsigned int size = atoi(buf);
char *kernel = (char *)0x80000;
while (size--) *kernel++ = uart_recv();

// Restore registers x0 x1 x2 x3
// Jump to the new kernel
asm volatile(
""
"mov x0, x10;"
"mov x1, x11;"
"mov x2, x12;"
"mov x3, x13;"
"mov x30, 0x80000;"
"ret;");

return 0;
}
40 changes: 40 additions & 0 deletions lab4/bootloader/start.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.section ".text.boot"

.global _start

_start:
/* save registers x0 x1 x2 x3 */
mov x10, x0 /* dtb_base address */
mov x11, x1
mov x12, x2
mov x12, x3

/* relocate bootloader */
ldr x1, =0x80000
ldr x2, =__loader_start // 0x60000
ldr w3, =__loader_size

relocate:
ldr x4, [x1], #8
str x4, [x2], #8
sub w3, w3, #1
cbnz w3, relocate

/* set stack pointer */
ldr x1, =_start
mov sp, x1

/* clear bss section */
ldr x1, =__bss_start
ldr w2, =__bss_size

bss_reset:
cbz w2, run_main
str xzr, [x1], #8
sub w2, w2, #1
cbnz w2, bss_reset

run_main:
/* branch to main function */
bl main-0x20000
b run_main
31 changes: 31 additions & 0 deletions lab4/include/command.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#define MAX_BUF_SIZE 1024
#define END_OF_COMMAND_LIST "NULL"

struct command {
const char *name;
const char *help;
void (*func)(void);
};

extern struct command commands[];
extern unsigned int BOARD_REVISION;
extern unsigned int BASE_MEMORY;
extern unsigned int NUM_PAGES;

// Commands
void cmd_help();
void cmd_hello();
void cmd_reboot();
void cmd_cancel();
void cmd_info();
void cmd_cat();
void cmd_run();
void cmd_clear();
void cmd_timer();
void cmd_mem();
void cmd_bd();
void cmd_fm();
void cmd_ca();
void cmd_lab();
19 changes: 19 additions & 0 deletions lab4/include/devtree.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include <stdint.h>

struct fdt_header {
uint32_t magic;
uint32_t totalsize;
uint32_t off_dt_struct;
uint32_t off_dt_strings;
uint32_t off_mem_rsvmap;
uint32_t version;
uint32_t last_comp_version;
uint32_t boot_cpuid_phys;
uint32_t size_dt_strings;
uint32_t size_dt_struct;
};

uint32_t be2le(const void *s);
void fdt_traverse(void (*callback)(void *, char *));
Loading

0 comments on commit ebe13a3

Please sign in to comment.