Actually get it working

This commit is contained in:
ProtoByter 2022-12-11 22:01:27 +00:00
parent 1b7ef1454e
commit 23c4f42eb4
18 changed files with 262 additions and 139 deletions

4
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "raspi_fw"]
path = raspi_fw
[submodule "third-party/raspi-firmware"]
path = third-party/raspi-firmware
url = https://github.com/raspberrypi/firmware

103
Makefile
View File

@ -1,38 +1,83 @@
CC := $(PREFIX)gcc
AS := $(PREFIX)as
OBJCPY := $(PREFIX)objcopy
boot.o: src/boot.S
$(AS) -c src/boot.S -o boot.o
CC := clang
OBJCPY := llvm-objcopy
LD := ld.lld
kernel.o: src/kernel.c
$(CC) -ffreestanding -c src/kernel.c -o kernel.o -O2 -Wall -Wextra
BUILD_DIR = build
SRC_DIR = src
os.elf: boot.o kernel.o src/linker.ld
$(CC) -T src/linker.ld -o os.elf -ffreestanding -O2 -nostdlib boot.o kernel.o -lgcc
GENERAL_OPTIONS =
kernel8.img: os.elf
$(OBJCPY) os.elf -O binary kernel8.img
CLANGOPS = -Wall -nostdlib -ffreestanding -mgeneral-regs-only -Iinclude -mcpu=cortex-a72+nosimd --target=aarch64-elf
ASMOPS = $(CLANGOPS)
COPS = $(CLANGOPS)
.PHONY: image kernel
C_FILES = $(wildcard $(SRC_DIR)/*.c)
ASM_FILES = $(wildcard $(SRC_DIR)/*.S)
OBJ_FILES = $(C_FILES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%_c.o)
OBJ_FILES += $(ASM_FILES:$(SRC_DIR)/%.S=$(BUILD_DIR)/%_s.o)
image: kernel8.img
ifndef VERBOSE
VERB := @
endif
kernel: os.elf
$(BUILD_DIR)/%_c.o: $(SRC_DIR)/%.c
$(VERB) echo Compiling $<
$(VERB) mkdir -p $(@D)
$(VERB) $(CC) $(COPS) -MMD -c $< -o $@
real_hardware: kernel8.img
mkdir -p staging
cp -v raspi_fw/boot/bcm2710-rpi-3-b.dtb staging
cp -v raspi_fw/boot/bcm2710-rpi-3-b-plus.dtb staging
cp -v raspi_fw/boot/bcm2710-rpi-cm3.dtb staging
cp -v raspi_fw/boot/bcm2711-rpi-4-b.dtb staging
cp -v raspi_fw/boot/bcm2711-rpi-400.dtb staging
cp -v raspi_fw/boot/bcm2711-rpi-cm4.dtb staging
cp -v raspi_fw/boot/bcm2711-rpi-cm4s.dtb staging
cp -v raspi_fw/boot/*.dat staging
cp -v raspi_fw/boot/*.elf staging
cp -v raspi_fw/boot/bootcode.bin staging
cp -v kernel8.img staging
$(BUILD_DIR)/%_s.o: $(SRC_DIR)/%.S
$(VERB) echo Compiling $<
$(VERB) mkdir -p $(@D)
$(VERB) $(CC) $(ASMOPS) -MMD -c $< -o $@
$(BUILD_DIR)/kernel8.elf: $(SRC_DIR)/linker.ld $(OBJ_FILES)
$(VERB) echo Linking kernel8.elf
$(VERB) $(LD) -T $(SRC_DIR)/linker.ld -o $(BUILD_DIR)/kernel8.elf $(OBJ_FILES)
$(BUILD_DIR)/kernel8.img: $(BUILD_DIR)/kernel8.elf
$(VERB) echo Building kernel8.img
$(VERB) $(OBJCPY) $(BUILD_DIR)/kernel8.elf -O binary $(BUILD_DIR)/kernel8.img
.PHONY: image kernel real_hardware
flat: $(BUILD_DIR)/kernel8.img
kernel: $(BUILD_DIR)/kernel8.elf
$(BUILD_DIR)/r4.img: $(BUILD_DIR)/kernel8.img src/config.txt third-party/raspi-firmware/boot/*
$(VERB) echo Building the image
$(VERB) echo -- Making the image file \($(BUILD_DIR)/tmp.img\)
$(VERB) dd if=/dev/zero of=$(BUILD_DIR)/tmp.img count=64 bs=1M
$(VERB) echo -e "unit: sectors\n/dev/hdc1 : Id=0c" | sfdisk $(BUILD_DIR)/tmp.img > /dev/null
$(VERB) mkfs.vfat -F 32 $(BUILD_DIR)/tmp.img > /dev/null
$(VERB) echo -- Copying files to `$(BUILD_DIR)/staging`
$(VERB) mkdir -p $(BUILD_DIR)/staging
$(VERB) cp third-party/raspi-firmware/boot/bcm2710-rpi-3-b.dtb $(BUILD_DIR)/staging/
$(VERB) cp third-party/raspi-firmware/boot/bcm2710-rpi-3-b-plus.dtb $(BUILD_DIR)/staging/
$(VERB) cp third-party/raspi-firmware/boot/bcm2710-rpi-cm3.dtb $(BUILD_DIR)/staging/
$(VERB) cp third-party/raspi-firmware/boot/bcm2711-rpi-4-b.dtb $(BUILD_DIR)/staging/
$(VERB) cp third-party/raspi-firmware/boot/bcm2711-rpi-400.dtb $(BUILD_DIR)/staging/
$(VERB) cp third-party/raspi-firmware/boot/bcm2711-rpi-cm4.dtb $(BUILD_DIR)/staging/
$(VERB) cp third-party/raspi-firmware/boot/bcm2711-rpi-cm4s.dtb $(BUILD_DIR)/staging/
$(VERB) cp third-party/raspi-firmware/boot/*.dat $(BUILD_DIR)/staging/
$(VERB) cp third-party/raspi-firmware/boot/*.elf $(BUILD_DIR)/staging/
$(VERB) cp third-party/raspi-firmware/boot/bootcode.bin $(BUILD_DIR)/staging/
$(VERB) cp src/config.txt $(BUILD_DIR)/staging/
$(VERB) cp $(BUILD_DIR)/kernel8.img $(BUILD_DIR)/staging/kernel8.img
$(VERB) echo -- Gzipping the kernel
$(VERB) gzip $(BUILD_DIR)/staging/kernel8.img
$(VERB) mv $(BUILD_DIR)/staging/kernel8.img.gz $(BUILD_DIR)/staging/kernel8.img
$(VERB) echo -- Copying files into the image
$(VERB) mcopy -i $(BUILD_DIR)/tmp.img $(BUILD_DIR)/staging/* ::/
$(VERB) mv $(BUILD_DIR)/tmp.img $(BUILD_DIR)/r4.img
$(VERB) echo Done!
real_hardware: $(BUILD_DIR)/r4.img
clean:
rm boot.o kernel.o os.elf kernel8.img
rm -rf staging
rm -rf $(BUILD_DIR) *.img

9
include/mini_uart.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _MINI_UART_H
#define _MINI_UART_H
void uart_init ( void );
char uart_recv ( void );
void uart_send ( char c );
void uart_send_string(char* str);
#endif /*_MINI_UART_H */

19
include/mm.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef _MM_H
#define _MM_H
#define PAGE_SHIFT 12
#define TABLE_SHIFT 9
#define SECTION_SHIFT (PAGE_SHIFT + TABLE_SHIFT)
#define PAGE_SIZE (1 << PAGE_SHIFT)
#define SECTION_SIZE (1 << SECTION_SHIFT)
#define LOW_MEMORY (2 * SECTION_SIZE)
#ifndef __ASSEMBLER__
void memzero(unsigned long src, unsigned long n);
#endif
#endif /*_MM_H */

View File

@ -0,0 +1,6 @@
#ifndef _P_BASE_H
#define _P_BASE_H
#define PBASE 0xFE000000
#endif /*_P_BASE_H */

View File

@ -0,0 +1,12 @@
#ifndef _P_GPIO_H
#define _P_GPIO_H
#include "peripherals/base.h"
#define GPFSEL1 (PBASE+0x00200004)
#define GPSET0 (PBASE+0x0020001C)
#define GPCLR0 (PBASE+0x00200028)
#define GPPUD (PBASE+0x00200094)
#define GPPUDCLK0 (PBASE+0x00200098)
#endif /*_P_GPIO_H */

View File

@ -0,0 +1,19 @@
#ifndef _P_MINI_UART_H
#define _P_MINI_UART_H
#include "peripherals/base.h"
#define AUX_ENABLES (PBASE+0x00215004)
#define AUX_MU_IO_REG (PBASE+0x00215040)
#define AUX_MU_IER_REG (PBASE+0x00215044)
#define AUX_MU_IIR_REG (PBASE+0x00215048)
#define AUX_MU_LCR_REG (PBASE+0x0021504C)
#define AUX_MU_MCR_REG (PBASE+0x00215050)
#define AUX_MU_LSR_REG (PBASE+0x00215054)
#define AUX_MU_MSR_REG (PBASE+0x00215058)
#define AUX_MU_SCRATCH (PBASE+0x0021505C)
#define AUX_MU_CNTL_REG (PBASE+0x00215060)
#define AUX_MU_STAT_REG (PBASE+0x00215064)
#define AUX_MU_BAUD_REG (PBASE+0x00215068)
#endif /*_P_MINI_UART_H */

8
include/utils.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef _BOOT_H
#define _BOOT_H
extern void delay ( unsigned long);
extern void put32 ( unsigned long, unsigned int );
extern unsigned int get32 ( unsigned long );
#endif /*_BOOT_H */

View File

@ -1,33 +1,24 @@
// AArch64 mode
// To keep this in the first portion of the binary.
#include "mm.h"
.section ".text.boot"
// Make _start global.
.globl _start
// Entry point for the kernel. Registers:
// x0 -> 32 bit pointer to DTB in memory (primary core only) / 0 (secondary cores)
// x1 -> 0
// x2 -> 0
// x3 -> 0
// x4 -> 32 bit kernel entry point, _start location
.global _start
_start:
// set stack before our code
ldr x5, =_start
mov sp, x5
mrs x0, mpidr_el1
and x0, x0,#0xFF // Check processor id
cbz x0, master // Hang for all non-primary CPU
b proc_hang
// clear bss
ldr x5, =__bss_start
ldr w6, =__bss_size
1: cbz w6, 2f
str xzr, [x5], #8
sub w6, w6, #1
cbnz w6, 1b
proc_hang:
b proc_hang
// jump to C code, should not return
2: bl kernel_main
// for failsafe, halt this core
halt:
wfe
b halt
master:
adr x0, bss_begin
adr x1, bss_end
sub x1, x1, x0
bl memzero
mov sp, #LOW_MEMORY
bl kernel_main
b proc_hang // should never come here

3
src/config.txt Normal file
View File

@ -0,0 +1,3 @@
disable_commandline_tags=1
core_freq_min=500

View File

@ -1,45 +1,11 @@
#include <stddef.h>
#include <stdint.h>
#include "mmio.h"
#include "uart.h"
#include "mini_uart.h"
volatile uint64_t** core_1 = (void*)0xE0;
volatile uint64_t** core_2 = (void*)0xE8;
volatile uint64_t** core_3 = (void*)0xF0;
void _start_core_1(void* addr) {
*core_1 = (uint64_t*)addr;
}
void _start_core_2(void* addr) {
*core_2 = (uint64_t*)addr;
}
void _start_core_3(void* addr) {
*core_3 = (uint64_t*)addr;
}
void kernel_main(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3) {
uint32_t reg;
char *board;
asm volatile ("mrs %x0, midr_el1" : "=r" (reg));
switch ((reg >> 4) & 0xFFF) {
case 0xD03:
board = "Raspberry Pi 3\0";
MMIO_BASE = 0x3F000000;
break;
case 0xD08:
board = "Raspberry Pi 4\0";
MMIO_BASE = 0xFE000000;
break;
}
void kernel_main(void)
{
uart_init();
uart_puts(board);
uart_send_string("Hello, world!\r\n");
return;
while (1) {
uart_send(uart_recv() + 1);
}
}

View File

@ -1,44 +1,12 @@
ENTRY(_start)
SECTIONS
{
/* Starts at LOADER_ADDR. */
. = 0x80000;
/* For AArch64, use . = 0x80000; */
__start = .;
__text_start = .;
.text :
{
KEEP(*(.text.boot))
*(.text)
}
. = ALIGN(4096); /* align to page size */
__text_end = .;
__rodata_start = .;
.rodata :
{
*(.rodata)
}
. = ALIGN(4096); /* align to page size */
__rodata_end = .;
__data_start = .;
.data :
{
*(.data)
}
. = ALIGN(4096); /* align to page size */
__data_end = .;
__bss_start = .;
.bss :
{
bss = .;
*(.bss)
}
. = ALIGN(4096); /* align to page size */
__bss_end = .;
__bss_size = __bss_end - __bss_start;
__end = .;
.text.boot : { *(.text.boot) }
.text : { *(.text) }
.rodata : { *(.rodata*) }
.data : { *(.data) }
. = ALIGN(0x8);
bss_begin = .;
.bss : { *(.bss*) }
bss_end = .;
}

56
src/mini_uart.c Normal file
View File

@ -0,0 +1,56 @@
#include "utils.h"
#include "peripherals/mini_uart.h"
#include "peripherals/gpio.h"
void uart_send ( char c )
{
while(1) {
if(get32(AUX_MU_LSR_REG)&0x20)
break;
}
put32(AUX_MU_IO_REG,c);
}
char uart_recv ( void )
{
while(1) {
if(get32(AUX_MU_LSR_REG)&0x01)
break;
}
return(get32(AUX_MU_IO_REG)&0xFF);
}
void uart_send_string(char* str)
{
for (int i = 0; str[i] != '\0'; i ++) {
uart_send((char)str[i]);
}
}
void uart_init ( void )
{
unsigned int selector;
selector = get32(GPFSEL1);
selector &= ~(7<<12); // clean gpio14
selector |= 2<<12; // set alt5 for gpio14
selector &= ~(7<<15); // clean gpio15
selector |= 2<<15; // set alt5 for gpio15
put32(GPFSEL1,selector);
put32(GPPUD,0);
delay(150);
put32(GPPUDCLK0,(1<<14)|(1<<15));
delay(150);
put32(GPPUDCLK0,0);
put32(AUX_ENABLES,1); //Enable mini uart (this also enables access to its registers)
put32(AUX_MU_CNTL_REG,0); //Disable auto flow control and disable receiver and transmitter (for now)
put32(AUX_MU_IER_REG,0); //Disable receive and transmit interrupts
put32(AUX_MU_LCR_REG,3); //Enable 8 bit mode
put32(AUX_MU_MCR_REG,0); //Set RTS line to be always high
put32(AUX_MU_BAUD_REG,((500000000/(115200*8))-1)); //Set baud rate to 115200
put32(AUX_MU_IIR_REG,0);
put32(AUX_MU_CNTL_REG,3); //Finally, enable transmitter and receiver
}

6
src/mm.S Normal file
View File

@ -0,0 +1,6 @@
.globl memzero
memzero:
str xzr, [x0], #8
subs x1, x1, #8
b.gt memzero
ret

15
src/utils.S Normal file
View File

@ -0,0 +1,15 @@
.globl put32
put32:
str w1,[x0]
ret
.globl get32
get32:
ldr w0,[x0]
ret
.globl delay
delay:
subs x0, x0, #1
bne delay
ret