From 99553732492c7b5231e1776eb06120cba8458f18 Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Thu, 14 Mar 2024 19:30:34 +0800 Subject: [PATCH 01/34] KAF is very very cute. --- .gitignore | 4 + Cargo.lock | 25 ++++ Cargo.toml | 27 +++++ Makefile | 90 +++++++++++++++ build.rs | 21 ++++ rust-toolchain.toml | 4 + src/_arch/aarch64/cpu.rs | 24 ++++ src/_arch/aarch64/cpu/boot.rs | 16 +++ src/_arch/aarch64/cpu/boot.s | 51 ++++++++ src/_arch/aarch64/cpu/boot_tmp.s | 65 +++++++++++ src/_arch/aarch64/cpu/regs.rs | 2 + src/bsp.rs | 3 + src/bsp/raspberrypi.rs | 1 + src/bsp/raspberrypi/cpu.rs | 7 ++ src/bsp/raspberrypi/kernel.ld | 36 ++++++ src/bsp/raspberrypi/kernel_tmp.ld | 79 +++++++++++++ src/cpu.rs | 8 ++ src/cpu/boot.rs | 3 + src/main.rs | 80 +++++++++++++ src/my_string.rs | 14 +++ src/my_string/my_string | 0 src/panic_wait.rs | 7 ++ src/uart.rs | 185 ++++++++++++++++++++++++++++++ 23 files changed, 752 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 Makefile create mode 100644 build.rs create mode 100644 rust-toolchain.toml create mode 100644 src/_arch/aarch64/cpu.rs create mode 100644 src/_arch/aarch64/cpu/boot.rs create mode 100644 src/_arch/aarch64/cpu/boot.s create mode 100644 src/_arch/aarch64/cpu/boot_tmp.s create mode 100644 src/_arch/aarch64/cpu/regs.rs create mode 100644 src/bsp.rs create mode 100644 src/bsp/raspberrypi.rs create mode 100644 src/bsp/raspberrypi/cpu.rs create mode 100644 src/bsp/raspberrypi/kernel.ld create mode 100644 src/bsp/raspberrypi/kernel_tmp.ld create mode 100644 src/cpu.rs create mode 100644 src/cpu/boot.rs create mode 100644 src/main.rs create mode 100644 src/my_string.rs create mode 100644 src/my_string/my_string create mode 100644 src/panic_wait.rs create mode 100644 src/uart.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..ed28b5dcc --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.git +target +kernel8.img + diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..531d09f14 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aarch64-cpu" +version = "9.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac42a04a61c19fc8196dd728022a784baecc5d63d7e256c01ad1b3fbfab26287" +dependencies = [ + "tock-registers", +] + +[[package]] +name = "lab1" +version = "0.1.0" +dependencies = [ + "aarch64-cpu", +] + +[[package]] +name = "tock-registers" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..80a050269 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "lab1" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[profile.release] +lto = true + + +[features] +default = [] +bsp_rpi3 = [] + +# specify bin +[[bin]] +name = "kernel" +path = "src/main.rs" + + +[dependencies] + +# Platform specific dependencies +[target.'cfg(target_arch = "aarch64")'.dependencies] +aarch64-cpu = {version = "9.x.x"} + diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..9fae78723 --- /dev/null +++ b/Makefile @@ -0,0 +1,90 @@ + +BSP = rpi3 + +TARGET = aarch64-unknown-none-softfloat +KERNEL_BIN = kernel8.img +QEMU_BINARY = qemu-system-aarch64 +QEMU_MACHINE_TYPE = raspi3b +QEMU_RELEASE_ARGS = -display none -serial null -serial stdio +QEMU_DEBUG_ARGS = -display none -S -s -serial null -serial stdio +OBJDUMP_BINARY = aarch64-none-elf-objdump +NM_BINARY = aarch64-none-elf-mn +READELF_BINARY = aarch64-none-elf-readelf +LD_SCRIPT_PATH = $(shell pwd)/src/bsp/raspberrypi +RUSTC_MISC_ARGS = -C target-cpu=cortex-a53 + +export LD_SCRIPT_PATH + +KERNEL_MANIFEST = Cargo.toml +KERNEL_LINKER_SCRIPT = kernel.ld +LAST_BUILD_CONFIG = target/$(TARGET).build_config + +KERNEL_ELF = target/$(TARGET)/release/kernel + +# parses cargo's dep-info file. +KERNEL_ELF_DEPS = $(filter-out %: ,$(file < $(KERNEL_ELF).d)) $(KERNEL_MANIFEST) $(LAST_BUILD_CONFIG) + + +# command building blocks + +RUSTFLAGS = $(RUSTC_MISC_ARGS) \ + -C link-arg=--library-path=$(LD_SCRIPT_PATH) \ + -C link-arg=--script=$(KERNEL_LINKER_SCRIPT) + +#RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) \ +# -D warnings \ +# -D missing_docs + +RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) +# -D warnings \ +# -D missing_docs + +FEATURE = --features bsp_$(BSP) +COMPILER_ARGS = --target=$(TARGET) \ + $(FEATURES) \ + --release + +RUSTC_CMD = cargo rustc $(COMPILER_ARGS) +CLIPPY_CMD = cargo clippy $(COMPILER_ARGS) +OBJCOPY_CMD = rust-objcopy \ + --strip-all \ + -O binary + +EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE) + +.PHONY: all doc qemu clippy clean readelf objdump nm check + +all: $(KERNEL_BIN) + +# Save the configuration as a file + +$(LAST_BUILD_CONFIG): + @rm -f target/*.build_config + @mkdir -p target + @touch $(LAST_BUILD_CONFIG) + +$(KERNEL_ELF): $(KERNEL_ELF_DEPS) + RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(RUSTC_CMD) + +# -- -C panic=abort -C panic=abort -C opt-level=3 + +$(KERNEL_BIN):$(KERNEL_ELF) + $(call color_header, "Generating stripped binary") + @$(OBJCOPY_CMD) $(KERNEL_ELF) $(KERNEL_BIN) + $(call color_progress_prefix, "Name") + @echo $(KERNEL_BIN) + $(call color_progress_prefix, "Size") + $(call disk_usage_KiB, $(KERNEL_BIN)) + +qemu: $(KERNEL_BIN) + $(call color_header, "Launching QEMU") + $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) + +gdb: $(KERNEL_BIN) + $(call color_header, "Launching QEMU in background") + $(EXEC_QEMU) $(QEMU_DEBUG_ARGS) -kernel $(KERNEL_BIN) + +clean: + rm -r target + rm $(KERNEL_BIN) + diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..a6234085a --- /dev/null +++ b/build.rs @@ -0,0 +1,21 @@ +use std::{env, fs, process}; + +fn main() { + let ld_script_path = match env::var("LD_SCRIPT_PATH") { + Ok(var) => var, + _ => process::exit(0), + }; + + let files = fs::read_dir(ld_script_path).unwrap(); + files + .filter_map(Result::ok) + .filter(|d| { + if let Some(e) = d.path().extension() { + e == "ld" + } + else { + false + } + }) + .for_each(|f| println!("cargo:rerun-if-changed={}", f.path().display())); +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 000000000..a554c0a98 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2022-10-13" +components = ["rust-src", "llvm-tools-preview", "rustfmt"] +targets = ["aarch64-unknown-none-softfloat"] diff --git a/src/_arch/aarch64/cpu.rs b/src/_arch/aarch64/cpu.rs new file mode 100644 index 000000000..8b5266023 --- /dev/null +++ b/src/_arch/aarch64/cpu.rs @@ -0,0 +1,24 @@ +use aarch64_cpu::asm; + +// public code +/// pause execution on the core + + +#[inline(always)] +pub fn wait_forever() -> ! { + loop { + asm::wfe(); + } +} + +/* +const int PM_RSTC = 0x2010001c; +const int PM_WDOG = 0x20100024; +const int PM_PASSWORD = 0x5a000000; +const int PM_RSTC_WRCFG_FULL_RESET = 0x00000020; + +PUT32(PM_WDOG, PM_PASSWORD | 1); // timeout = 1/16th of a second? (whatever) +PUT32(PM_RSTC, PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); +*/ + + diff --git a/src/_arch/aarch64/cpu/boot.rs b/src/_arch/aarch64/cpu/boot.rs new file mode 100644 index 000000000..d63a91db7 --- /dev/null +++ b/src/_arch/aarch64/cpu/boot.rs @@ -0,0 +1,16 @@ + +use core::arch::global_asm; +use core::arch::asm; + +global_asm!( + include_str!("boot.s") , + CONST_CORE_ID_MASK = const 0b11 +); + +// mod uart; + +#[no_mangle] +pub unsafe fn _start_rust(){ + crate::kernel_init() + +} diff --git a/src/_arch/aarch64/cpu/boot.s b/src/_arch/aarch64/cpu/boot.s new file mode 100644 index 000000000..ad63ef33d --- /dev/null +++ b/src/_arch/aarch64/cpu/boot.s @@ -0,0 +1,51 @@ + +.macro ADR_REL register, symbol + adrp \register, \symbol + add \register, \register, #:lo12:\symbol +.endm + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- +.section .text._start + +//------------------------------------------------------------------------------ +// fn _start() +//------------------------------------------------------------------------------ +_start: + // Only proceed on the boot core. Park it otherwise. + mrs x0, MPIDR_EL1 + and x0, x0, {CONST_CORE_ID_MASK} + ldr x1, BOOT_CORE_ID // provided by bsp/__board_name__/cpu.rs + cmp x0, x1 + b.ne .L_parking_loop + + // If execution reaches here, it is the boot core. + + // Initialize DRAM. + ADR_REL x0, __bss_start + ADR_REL x1, __bss_end_exclusive + +.L_bss_init_loop: + cmp x0, x1 + b.eq .L_prepare_rust + stp xzr, xzr, [x0], #16 + b .L_bss_init_loop + + + // Prepare the jump to Rust code. +.L_prepare_rust: + // Set the stack pointer. + mov sp, 0x80000 + + // Jump to Rust code. + b _start_rust + + // Infinitely wait for events (aka "park the core"). +.L_parking_loop: + wfe + b .L_parking_loop + +.size _start, . - _start +.type _start, function +.global _start diff --git a/src/_arch/aarch64/cpu/boot_tmp.s b/src/_arch/aarch64/cpu/boot_tmp.s new file mode 100644 index 000000000..0011c6074 --- /dev/null +++ b/src/_arch/aarch64/cpu/boot_tmp.s @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2021-2022 Andre Richter + +//-------------------------------------------------------------------------------------------------- +// Definitions +//-------------------------------------------------------------------------------------------------- + +// Load the address of a symbol into a register, PC-relative. +// +// The symbol must lie within +/- 4 GiB of the Program Counter. +// +// # Resources +// +// - https://sourceware.org/binutils/docs-2.36/as/AArch64_002dRelocations.html +.macro ADR_REL register, symbol + adrp \register, \symbol + add \register, \register, #:lo12:\symbol +.endm + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- +.section .text._start + +//------------------------------------------------------------------------------ +// fn _start() +//------------------------------------------------------------------------------ +_start: + // Only proceed on the boot core. Park it otherwise. + mrs x0, MPIDR_EL1 + and x0, x0, {CONST_CORE_ID_MASK} + ldr x1, BOOT_CORE_ID // provided by bsp/__board_name__/cpu.rs + cmp x0, x1 + b.ne .L_parking_loop + + // If execution reaches here, it is the boot core. + + // Initialize DRAM. + ADR_REL x0, __bss_start + ADR_REL x1, __bss_end_exclusive + +.L_bss_init_loop: + cmp x0, x1 + b.eq .L_prepare_rust + stp xzr, xzr, [x0], #16 + b .L_bss_init_loop + + // Prepare the jump to Rust code. +.L_prepare_rust: + // Set the stack pointer. + ADR_REL x0, __boot_core_stack_end_exclusive + mov sp, x0 + + // Jump to Rust code. + b _start_rust + + // Infinitely wait for events (aka "park the core"). +.L_parking_loop: + wfe + b .L_parking_loop + +.size _start, . - _start +.type _start, function +.global _start diff --git a/src/_arch/aarch64/cpu/regs.rs b/src/_arch/aarch64/cpu/regs.rs new file mode 100644 index 000000000..d0a094e32 --- /dev/null +++ b/src/_arch/aarch64/cpu/regs.rs @@ -0,0 +1,2 @@ +// enum of all the address to the registers + diff --git a/src/bsp.rs b/src/bsp.rs new file mode 100644 index 000000000..a0751c7ec --- /dev/null +++ b/src/bsp.rs @@ -0,0 +1,3 @@ +mod raspberrypi; +pub use raspberrypi::*; + diff --git a/src/bsp/raspberrypi.rs b/src/bsp/raspberrypi.rs new file mode 100644 index 000000000..3bfb62f3d --- /dev/null +++ b/src/bsp/raspberrypi.rs @@ -0,0 +1 @@ +pub mod cpu; diff --git a/src/bsp/raspberrypi/cpu.rs b/src/bsp/raspberrypi/cpu.rs new file mode 100644 index 000000000..e899e2c00 --- /dev/null +++ b/src/bsp/raspberrypi/cpu.rs @@ -0,0 +1,7 @@ + +// boot core id +#[no_mangle] +#[link_section = ".text._start_arguments"] +pub static BOOT_CORE_ID: u64 = 0; + + diff --git a/src/bsp/raspberrypi/kernel.ld b/src/bsp/raspberrypi/kernel.ld new file mode 100644 index 000000000..e48ede7c1 --- /dev/null +++ b/src/bsp/raspberrypi/kernel.ld @@ -0,0 +1,36 @@ + +__rpi_phys_dram_start_addr = 0; + +__rpi_phys_binary_load_addr = 0x80000; + + +ENTRY(__rpi_phys_binary_load_addr) + + +SECTIONS +{ + + . = __rpi_phys_binary_load_addr; + .text : + { + KEEP(*(.text._start)) + *(.text._start_arguments) /* Constants (or statics in Rust speak) read by _start(). */ + *(.text._start_rust) /* The Rust entry point */ + *(.text*) /* Everything else */ + } :segment_code + + .rodata : ALIGN(8) { *(.rodata*) } :segment_code + + .data : { *(.data*) } + + /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */ + + .bss (NOLOAD): ALIGN(16) + { + __bss_start = .; + *(.bss*); + . = ALIGN(16); + __bss_end_exclusive = .; + } + +} diff --git a/src/bsp/raspberrypi/kernel_tmp.ld b/src/bsp/raspberrypi/kernel_tmp.ld new file mode 100644 index 000000000..f6c188434 --- /dev/null +++ b/src/bsp/raspberrypi/kernel_tmp.ld @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: MIT OR Apache-2.0 + * + * Copyright (c) 2018-2022 Andre Richter + */ + +__rpi_phys_dram_start_addr = 0; + +/* The physical address at which the the kernel binary will be loaded by the Raspberry's firmware */ +__rpi_phys_binary_load_addr = 0x80000; + + +ENTRY(__rpi_phys_binary_load_addr) + +/* Flags: + * 4 == R + * 5 == RX + * 6 == RW + * + * Segments are marked PT_LOAD below so that the ELF file provides virtual and physical addresses. + * It doesn't mean all of them need actually be loaded. + */ +PHDRS +{ + segment_boot_core_stack PT_LOAD FLAGS(6); + segment_code PT_LOAD FLAGS(5); + segment_data PT_LOAD FLAGS(6); +} + +SECTIONS +{ + . = __rpi_phys_dram_start_addr; + + /*********************************************************************************************** + * Boot Core Stack + ***********************************************************************************************/ + .boot_core_stack (NOLOAD) : + { + /* ^ */ + /* | stack */ + . += __rpi_phys_binary_load_addr; /* | growth */ + /* | direction */ + __boot_core_stack_end_exclusive = .; /* | */ + } :segment_boot_core_stack + + /*********************************************************************************************** + * Code + RO Data + Global Offset Table + ***********************************************************************************************/ + .text : + { + KEEP(*(.text._start)) + *(.text._start_arguments) /* Constants (or statics in Rust speak) read by _start(). */ + *(.text._start_rust) /* The Rust entry point */ + *(.text*) /* Everything else */ + } :segment_code + + .rodata : ALIGN(8) { *(.rodata*) } :segment_code + + /*********************************************************************************************** + * Data + BSS + ***********************************************************************************************/ + .data : { *(.data*) } :segment_data + + /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */ + .bss (NOLOAD) : ALIGN(16) + { + __bss_start = .; + *(.bss*); + . = ALIGN(16); + __bss_end_exclusive = .; + } :segment_data + + /*********************************************************************************************** + * Misc + ***********************************************************************************************/ + .got : { *(.got*) } + ASSERT(SIZEOF(.got) == 0, "Relocation support not expected") + + /DISCARD/ : { *(.comment*) } +} diff --git a/src/cpu.rs b/src/cpu.rs new file mode 100644 index 000000000..c029d9b00 --- /dev/null +++ b/src/cpu.rs @@ -0,0 +1,8 @@ +#[cfg(target_arch = "aarch64")] +#[path = "_arch/aarch64/cpu.rs"] +mod arch_cpu; + +mod boot; + +pub use arch_cpu::wait_forever; + diff --git a/src/cpu/boot.rs b/src/cpu/boot.rs new file mode 100644 index 000000000..b244f2185 --- /dev/null +++ b/src/cpu/boot.rs @@ -0,0 +1,3 @@ +#[cfg(target_arch = "aarch64")] +#[path = "../_arch/aarch64/cpu/boot.rs"] +mod arch_boot; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 000000000..e0b8603fb --- /dev/null +++ b/src/main.rs @@ -0,0 +1,80 @@ +#![feature(asm_const)] +#![no_main] +#![no_std] + +use crate::uart::strcmp; +use core::{ + ptr::{read_volatile, write_volatile}, + usize, +}; + +mod bsp; +mod cpu; +mod panic_wait; +mod uart; + +#[no_mangle] +unsafe fn kernel_init() -> ! { + uart::init_uart(); + + // loop { + // uart::write_char(65); + // core::arch::asm!("nop"); + // } + + let mut out_buf: [u8; 128] = [0; 128]; + let mut in_buf: [u8; 128] = [0; 128]; + let out_buf_len: usize = 2; + out_buf[0] = 62; + out_buf[1] = 62; + + let mut hello_str: [u8; 128] = [0; 128]; + hello_str[..5].copy_from_slice(b"hello"); + let hello_len = 5; + + let mut reboot_str: [u8; 128] = [0; 128]; + reboot_str[..6].copy_from_slice(b"reboot"); + + /*help = + " + help : print this help menu\n + hello : print Hello World!\n + reboot : reboot the device\n + " + */ + let mut help_str: [u8; 128] = [0; 128]; + help_str[..4].copy_from_slice(b"help"); + let help_len = 4; + + let mut hello_world_str: [u8; 128] = [0; 128]; + + let hello_world_len = 10; + + loop { + uart::print_str(&out_buf, out_buf_len); + let in_buf_len = uart::get_line(&mut in_buf, true); + if strcmp(&in_buf, in_buf_len, &hello_str, hello_len) { + for i in b"Hello World!\r\n" { + uart::write_char(*i); + } + uart::write_char(10); + } else if strcmp(&in_buf, in_buf_len, &help_str, help_len) { + + for i in b"help : print this help menu\r\nhello : print Hello World!\r\nreboot : reboot the device\r\n" { + uart::write_char(*i); + } + uart::write_char(10); + } else if strcmp(&in_buf, in_buf_len, &reboot_str, 6) { + // print reboot + + const PM_PASSWORD: u32 = 0x5a000000; + const PM_RSTC: u32 = 0x3F10001c; + const PM_WDOG: u32 = 0x3F100024; + const PM_RSTC_WRCFG_FULL_RESET: u32 = 0x00000020; + write_volatile(PM_WDOG as *mut u32, PM_PASSWORD | 1); + write_volatile(PM_RSTC as *mut u32, PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); + } + uart::nops(); + } + panic!() +} diff --git a/src/my_string.rs b/src/my_string.rs new file mode 100644 index 000000000..b3001cb6f --- /dev/null +++ b/src/my_string.rs @@ -0,0 +1,14 @@ +use core::usize; + + +const MY_STRING_LEN : usize = 128; + +#[derive(Debug)] +struct MyString { + arr: [u8 ; MY_STRING_LEN], + len: usize, +} +impl MyString { +} + + diff --git a/src/my_string/my_string b/src/my_string/my_string new file mode 100644 index 000000000..e69de29bb diff --git a/src/panic_wait.rs b/src/panic_wait.rs new file mode 100644 index 000000000..c297b7a74 --- /dev/null +++ b/src/panic_wait.rs @@ -0,0 +1,7 @@ +use crate::cpu; +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + cpu::wait_forever() +} diff --git a/src/uart.rs b/src/uart.rs new file mode 100644 index 000000000..9403e981a --- /dev/null +++ b/src/uart.rs @@ -0,0 +1,185 @@ +use core::arch::asm; +use core::{ + ptr::{read_volatile, write_volatile}, + usize, +}; + +const AUXENB: u32 = 0x3F215004; +const AUX_MU_CNTL_REG: u32 = 0x3F215060; +const AUX_MU_IER_REG: u32 = 0x3F215044; +const AUX_MU_LCR_REG: u32 = 0x3F21504C; +const AUX_MU_MCR_REG: u32 = 0x3F215050; +const AUX_MU_BAUD_REG: u32 = 0x3F215068; +const AUX_MU_IIR_REG: u32 = 0x3F215048; +const AUX_MU_IO_REG: u32 = 0x3F215040; +const AUX_MU_LSR_REG: u32 = 0x3F215054; + +const GPFSEL_BASE: u32 = 0x3F200000; +const GPFSEL0: u32 = 0x3F200000; +const GPFSEL1: u32 = 0x3F200004; + +const GPPUD: u32 = 0x3F200094; +const GPPUDCLK0: u32 = 0x3F200098; +const GPPUDCLK1: u32 = 0x3F20009C; + +// Initialize the UART +#[no_mangle] +#[inline(never)] +pub fn init_uart() { + unsafe { + // configure GPFSEL1 register to set FSEL14 FSEL15 to ALT5 + let fsel = read_volatile(GPFSEL1 as *mut u32); + let fsel_mask = !(0b111111 << 12); + let fsel_set = 0b010010 << 12; + write_volatile(GPFSEL1 as *mut u32, (fsel & fsel_mask) | fsel_set); + + // configure pull up/down register to disable GPIO pull up/down + let pud = 0b0; + write_volatile(GPPUD as *mut u32, pud); + + // wait 150 cycles + nops(); + + // configure pull up/down clock register to disable GPIO pull up/down + let pudclk0 = !(0b11 << 14); + write_volatile(GPPUDCLK0 as *mut u32, pudclk0); + let pudclk1 = 0; + write_volatile(GPPUDCLK1 as *mut u32, pudclk1); + // wait 150 cycles + nops(); + + // Write to GPPUD to remove the control signal + write_volatile(GPPUD as *mut u32, 0); + // Write to GPPUDCLK0 to remove the clock + write_volatile(GPPUDCLK0 as *mut u32, 0); + + // write some word to uart to initialize it + // Set AUXENB register to enable mini UART + write_volatile(AUXENB as *mut u32, 1); + + // Set AUX_MU_CNTL_REG to 0 + write_volatile(AUX_MU_CNTL_REG as *mut u32, 0); + // Set AUX_MU_IER_REG to 0 + write_volatile(AUX_MU_IER_REG as *mut u32, 0); + // Set AUX_MU_LCR_REG to 3 + write_volatile(AUX_MU_LCR_REG as *mut u32, 3); + // Set AUX_MU_MCR_REG to 0 + write_volatile(AUX_MU_MCR_REG as *mut u32, 0); + // Set AUX_MU_BAUD_REG to 270 + write_volatile(AUX_MU_BAUD_REG as *mut u32, 270); + // Set AUX_MU_IIR_REG to 6 + write_volatile(AUX_MU_IIR_REG as *mut u32, 6); + // Set AUX_MU_CNTL_REG to 3 + write_volatile(AUX_MU_CNTL_REG as *mut u32, 3); + } +} + +#[no_mangle] +#[inline(never)] +pub fn print_hello() { + unsafe { + let hello: [u8; 5] = [72, 101, 108, 108, 111]; + write_volatile(AUX_MU_IO_REG as *mut u32, 72); + write_volatile(AUX_MU_IO_REG as *mut u32, 101); + write_volatile(AUX_MU_IO_REG as *mut u32, 108); + write_volatile(AUX_MU_IO_REG as *mut u32, 108); + write_volatile(AUX_MU_IO_REG as *mut u32, 111); + } +} + +#[no_mangle] +#[inline(never)] +pub unsafe fn print_str(buf: &[u8; 128], buf_len: usize) { + let mut ptr: usize = 0; + while ptr < buf_len { + write_char(buf[ptr]); + ptr = ptr + 1; + } +} + +#[no_mangle] +#[inline(never)] +pub unsafe fn strcmp(s1: &[u8; 128], l1: usize, s2: &[u8; 128], l2: usize) -> bool { + if l1 != l2 { + return false; + } + let mut idx: usize = 0; + while idx < l1 { + if s1[idx] != s2[idx] { + return false; + } + idx = idx + 1; + } + true +} + +#[no_mangle] +#[inline(never)] +pub unsafe fn get_line(s: &mut [u8; 128], is_echo: bool) -> usize { + let mut ptr: usize = 0; + loop { + let c: Option = read_char(); + match c { + Some(i) => { + if is_echo { + write_char(i as u8); + } + if i == 13 { + write_char(10); + break; + } + s[ptr] = i as u8; + ptr = ptr + 1; + } + None => {} + } + asm!("nop"); + } + ptr +} + +#[no_mangle] +pub unsafe fn nops() { + for _ in 0..150 { + asm!("nop"); + } +} + +// Function to print something using the UART +#[no_mangle] +pub unsafe fn write_char(s: u8) { + // Add your UART printing code here + // Example: write to UART buffer or transmit data + // check if the UART is ready to transmit + loop { + if (read_volatile(AUX_MU_LSR_REG as *mut u32) & 0b100000) != 0 { + break; + } + } + write_volatile(AUX_MU_IO_REG as *mut u8, s as u8); +} + +#[no_mangle] +#[inline(never)] +pub unsafe fn read_char() -> Option { + let lsr: u32 = read_volatile(AUX_MU_LSR_REG as *mut u32) & 0b1; + if lsr != 0 { + Some(read_volatile(AUX_MU_IO_REG as *mut u32)) + } else { + None + } +} + +// // Create a global instance of the UART +// pub static mut UART: Uart = Uart {}; + +// // UART struct +// pub struct Uart {} + +// // Example usage +// fn main() { +// unsafe { +// init_uart(); +// writeln!(UART, "Hello, world!").unwrap(); +// } +// } From 4c0133249a520d730fece3b62d666c17aa3e2910 Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Thu, 14 Mar 2024 21:32:37 +0800 Subject: [PATCH 02/34] Mailbox Ok, KAF is cute. --- README.md | 39 +++++++++++++++++++++++ src/mailbox.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 54 +++++++++++++++++++++++--------- src/uart.rs | 21 +++++++++++++ 4 files changed, 184 insertions(+), 14 deletions(-) create mode 100644 README.md create mode 100644 src/mailbox.rs diff --git a/README.md b/README.md new file mode 100644 index 000000000..50c5d4048 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ + +# OSC2024 + +| Github Account | Student ID | Name | +|----------------|------------|---------------| +| cfmc30 | 109350078 | Erh-Tai Huang | + +## Requirements + +- Install Rust + ``` + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + source $HOME/.cargo/env + ``` + +- Tool Chain + ``` + cargo install cargo-binutils rustfilt + ``` + +- Others are specified in [rust-toolchain.toml](rust-toolchain.toml) which will be configured by cargo. + +## Things that can be improved + +- The structure of the project +- Rust code but with C style +- String with fixed size + +## Build + +``` +make +``` + +## Test With QEMU + +``` +make qemu +``` diff --git a/src/mailbox.rs b/src/mailbox.rs new file mode 100644 index 000000000..e3a570ec2 --- /dev/null +++ b/src/mailbox.rs @@ -0,0 +1,84 @@ +const MMIO_BASE: u32 = 0x3f000000; +const MAILBOX_BASE: u32 = MMIO_BASE + 0xb880; + +const MAILBOX_READ: u32 = MAILBOX_BASE; +const MAILBOX_STATUS: u32 = MAILBOX_BASE + 0x18; +const MAILBOX_WRITE: u32 = MAILBOX_BASE + 0x20; + +const MAILBOX_EMPTY: u32 = 0x40000000; +const MAILBOX_FULL: u32 = 0x80000000; + +use core::ptr::{read_volatile, write_volatile}; + +unsafe fn mailbox_call(mailbox: &mut [u32]) { + // check if the mailbox is full + let mut status: u32; + loop { + status = read_volatile(MAILBOX_STATUS as *const u32); + if (status & MAILBOX_FULL) == 0 { + // mailbox is not full, we can write the message + break; + } + } + // Combine the message address (upper 28 bits) with channel number (lower 4 bits) + let channel = 8; + let message_address = mailbox.as_ptr() as u32; + let combined_address = (message_address & 0xFFFFFFF0) | (channel & 0xF); + write_volatile(MAILBOX_WRITE as *mut u32, combined_address as u32); + + // check if the mailbox is empty + loop { + status = read_volatile(MAILBOX_STATUS as *const u32); + if (status & MAILBOX_EMPTY) == 0 { + // mailbox is not empty, we can read the message + break; + } + } + if read_volatile(MAILBOX_READ as *const u32) != (message_address as u32) {} +} + +const GET_BOARD_REVISION: u32 = 0x00010002; +const REQUEST_CODE: u32 = 0x00000000; +const REQUEST_SUCCEED: u32 = 0x80000000; +const REQUEST_FAILED: u32 = 0x80000001; +const TAG_REQUEST_CODE: u32 = 0x00000000; +const END_TAG: u32 = 0x00000000; + +pub unsafe fn get_board_revisioin() -> u32 { + let mut mailbox: [u32; 32] = [0; 32]; + let idx_offset:usize = (0x10 - mailbox.as_ptr() as u32 & 0xf) as usize; + + + mailbox[0 + idx_offset] = 7 * 4; + mailbox[1 + idx_offset] = REQUEST_CODE; + mailbox[2 + idx_offset] = GET_BOARD_REVISION; + mailbox[3 + idx_offset] = 4; + mailbox[4 + idx_offset] = TAG_REQUEST_CODE; + mailbox[5 + idx_offset] = 0; + mailbox[6 + idx_offset] = END_TAG; + + + mailbox_call(&mut mailbox[idx_offset..(idx_offset + 7)]); + + mailbox[5] +} + +// Get ARM memory base address and size using mailbox +const GET_ARM_MEMORY: u32 = 0x00010005; +pub unsafe fn get_arm_memory() -> (u32, u32) { + let mut mailbox: [u32; 32] = [0; 32]; + let idx_offset:usize = (0x10 - mailbox.as_ptr() as u32 & 0xf) as usize; + + mailbox[0 + idx_offset] = 8 * 4; + mailbox[1 + idx_offset] = REQUEST_CODE; + mailbox[2 + idx_offset] = GET_ARM_MEMORY; + mailbox[3 + idx_offset] = 8; + mailbox[4 + idx_offset] = TAG_REQUEST_CODE; + mailbox[5 + idx_offset] = 0; + mailbox[6 + idx_offset] = 0; + mailbox[7 + idx_offset] = END_TAG; + + mailbox_call(&mut mailbox[idx_offset..(idx_offset + 8)]); + + (mailbox[5], mailbox[6]) +} diff --git a/src/main.rs b/src/main.rs index e0b8603fb..fd90eab8d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,15 +12,48 @@ mod bsp; mod cpu; mod panic_wait; mod uart; +mod mailbox; #[no_mangle] unsafe fn kernel_init() -> ! { uart::init_uart(); - // loop { - // uart::write_char(65); - // core::arch::asm!("nop"); - // } + for i in b"Revision: " { + uart::write_char(*i); + } + + // get board revision + let revision = mailbox::get_board_revisioin(); + + // convert revision to string + let mut rev_str: [u8; 128] = [0; 128]; + let mut rev_str_len = 0; + + // print hex of revision + uart::print_hex(revision); + + uart::write_char(b'\n'); + uart::write_char(b'\r'); + + // get ARM memory base address and size + let (base, size) = mailbox::get_arm_memory(); + + // print ARM memory base address and size + for i in b"ARM memory base address: " { + uart::write_char(*i); + } + uart::print_hex(base); + uart::write_char(b'\n'); + uart::write_char(b'\r'); + + for i in b"ARM memory size: " { + uart::write_char(*i); + } + uart::print_hex(size); + uart::write_char(b'\n'); + uart::write_char(b'\r'); + + let mut out_buf: [u8; 128] = [0; 128]; let mut in_buf: [u8; 128] = [0; 128]; @@ -35,20 +68,13 @@ unsafe fn kernel_init() -> ! { let mut reboot_str: [u8; 128] = [0; 128]; reboot_str[..6].copy_from_slice(b"reboot"); - /*help = - " - help : print this help menu\n - hello : print Hello World!\n - reboot : reboot the device\n - " - */ let mut help_str: [u8; 128] = [0; 128]; help_str[..4].copy_from_slice(b"help"); let help_len = 4; let mut hello_world_str: [u8; 128] = [0; 128]; - let hello_world_len = 10; + let hello_world_len = 1010; loop { uart::print_str(&out_buf, out_buf_len); @@ -65,14 +91,14 @@ unsafe fn kernel_init() -> ! { } uart::write_char(10); } else if strcmp(&in_buf, in_buf_len, &reboot_str, 6) { - // print reboot const PM_PASSWORD: u32 = 0x5a000000; const PM_RSTC: u32 = 0x3F10001c; const PM_WDOG: u32 = 0x3F100024; const PM_RSTC_WRCFG_FULL_RESET: u32 = 0x00000020; - write_volatile(PM_WDOG as *mut u32, PM_PASSWORD | 1); + write_volatile(PM_WDOG as *mut u32, PM_PASSWORD | 100); write_volatile(PM_RSTC as *mut u32, PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); + break; } uart::nops(); } diff --git a/src/uart.rs b/src/uart.rs index 9403e981a..5526101f8 100644 --- a/src/uart.rs +++ b/src/uart.rs @@ -170,6 +170,27 @@ pub unsafe fn read_char() -> Option { } } +// print u32 in hex +#[no_mangle] +pub unsafe fn print_hex(n: u32) { + let mut buf: [u8; 8] = [0; 8]; + let mut ptr: usize = 0; + let mut num: u32 = n; + for _ in 0..8 { + let rem: u8 = (num % 16) as u8; + if rem < 10 { + buf[ptr] = (rem + b'0') as u8; + } else { + buf[ptr] = (rem - 10 + b'A') as u8; + } + ptr = ptr + 1; + num = num / 16; + } + for i in buf.iter().take(8).rev(){ + write_char(*i); + } +} + // // Create a global instance of the UART // pub static mut UART: Uart = Uart {}; From 2265a6ea6a030fddadd1374e8254cacd7ff402ce Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Sun, 24 Mar 2024 00:02:04 +0800 Subject: [PATCH 03/34] =?UTF-8?q?New=20Project=20Layout,=20=E4=BB=8A?= =?UTF-8?q?=E6=97=A5=E3=82=82=E3=81=8B=E3=82=8F=E3=81=84=E3=81=84=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +- Cargo.lock | 18 +- Cargo.toml | 32 +-- Makefile | 70 ++---- bootloader/Cargo.lock | 25 +++ bootloader/Cargo.toml | 28 +++ bootloader/Makefile | 64 ++++++ bootloader/README.md | 39 ++++ build.rs => bootloader/build.rs | 0 bootloader/rust-toolchain.toml | 4 + {src => bootloader/src}/_arch/aarch64/cpu.rs | 0 bootloader/src/_arch/aarch64/cpu/boot.rs | 15 ++ .../src/_arch/aarch64/cpu/boot.s | 36 ++- {src => bootloader/src}/bsp.rs | 0 {src => bootloader/src}/bsp/raspberrypi.rs | 0 bootloader/src/bsp/raspberrypi/bootloader.ld | 39 ++++ .../src}/bsp/raspberrypi/cpu.rs | 0 {src => bootloader/src}/cpu.rs | 0 {src => bootloader/src}/cpu/boot.rs | 0 bootloader/src/main.rs | 56 +++++ {src => bootloader/src}/panic_wait.rs | 0 driver | 1 + kernel/Cargo.lock | 25 +++ kernel/Cargo.toml | 28 +++ kernel/Makefile | 70 ++++++ kernel/README.md | 39 ++++ kernel/build.rs | 21 ++ kernel/rust-toolchain.toml | 4 + kernel/src/_arch/aarch64/cpu.rs | 24 ++ {src => kernel/src}/_arch/aarch64/cpu/boot.rs | 2 - {src => kernel/src}/_arch/aarch64/cpu/boot.s | 0 kernel/src/bsp.rs | 3 + kernel/src/bsp/raspberrypi.rs | 1 + kernel/src/bsp/raspberrypi/cpu.rs | 7 + {src => kernel/src}/bsp/raspberrypi/kernel.ld | 1 - kernel/src/cpu.rs | 8 + kernel/src/cpu/boot.rs | 3 + {src => kernel/src}/main.rs | 70 ++---- kernel/src/panic_wait.rs | 7 + src/_arch/aarch64/cpu/regs.rs | 2 - src/bsp/raspberrypi/kernel_tmp.ld | 79 ------- src/mailbox.rs | 84 ------- src/my_string.rs | 14 -- src/my_string/my_string | 0 src/uart.rs | 206 ------------------ 45 files changed, 586 insertions(+), 543 deletions(-) create mode 100644 bootloader/Cargo.lock create mode 100644 bootloader/Cargo.toml create mode 100644 bootloader/Makefile create mode 100644 bootloader/README.md rename build.rs => bootloader/build.rs (100%) create mode 100644 bootloader/rust-toolchain.toml rename {src => bootloader/src}/_arch/aarch64/cpu.rs (100%) create mode 100644 bootloader/src/_arch/aarch64/cpu/boot.rs rename src/_arch/aarch64/cpu/boot_tmp.s => bootloader/src/_arch/aarch64/cpu/boot.s (60%) rename {src => bootloader/src}/bsp.rs (100%) rename {src => bootloader/src}/bsp/raspberrypi.rs (100%) create mode 100644 bootloader/src/bsp/raspberrypi/bootloader.ld rename {src => bootloader/src}/bsp/raspberrypi/cpu.rs (100%) rename {src => bootloader/src}/cpu.rs (100%) rename {src => bootloader/src}/cpu/boot.rs (100%) create mode 100644 bootloader/src/main.rs rename {src => bootloader/src}/panic_wait.rs (100%) create mode 160000 driver create mode 100644 kernel/Cargo.lock create mode 100644 kernel/Cargo.toml create mode 100644 kernel/Makefile create mode 100644 kernel/README.md create mode 100644 kernel/build.rs create mode 100644 kernel/rust-toolchain.toml create mode 100644 kernel/src/_arch/aarch64/cpu.rs rename {src => kernel/src}/_arch/aarch64/cpu/boot.rs (89%) rename {src => kernel/src}/_arch/aarch64/cpu/boot.s (100%) create mode 100644 kernel/src/bsp.rs create mode 100644 kernel/src/bsp/raspberrypi.rs create mode 100644 kernel/src/bsp/raspberrypi/cpu.rs rename {src => kernel/src}/bsp/raspberrypi/kernel.ld (99%) create mode 100644 kernel/src/cpu.rs create mode 100644 kernel/src/cpu/boot.rs rename {src => kernel/src}/main.rs (51%) create mode 100644 kernel/src/panic_wait.rs delete mode 100644 src/_arch/aarch64/cpu/regs.rs delete mode 100644 src/bsp/raspberrypi/kernel_tmp.ld delete mode 100644 src/mailbox.rs delete mode 100644 src/my_string.rs delete mode 100644 src/my_string/my_string delete mode 100644 src/uart.rs diff --git a/.gitignore b/.gitignore index ed28b5dcc..2236371cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -.git target +*/target kernel8.img - +.vscode diff --git a/Cargo.lock b/Cargo.lock index 531d09f14..498db9cb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,10 +12,26 @@ dependencies = [ ] [[package]] -name = "lab1" +name = "bootloader" version = "0.1.0" dependencies = [ "aarch64-cpu", + "driver", +] + +[[package]] +name = "driver" +version = "0.1.0" +dependencies = [ + "aarch64-cpu", +] + +[[package]] +name = "kernel" +version = "0.1.0" +dependencies = [ + "aarch64-cpu", + "driver", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 80a050269..5cc67823b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,27 +1,7 @@ -[package] -name = "lab1" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[profile.release] -lto = true - - -[features] -default = [] -bsp_rpi3 = [] - -# specify bin -[[bin]] -name = "kernel" -path = "src/main.rs" - - -[dependencies] - -# Platform specific dependencies -[target.'cfg(target_arch = "aarch64")'.dependencies] -aarch64-cpu = {version = "9.x.x"} +[workspace] +members = [ + "driver", + "kernel", + "bootloader", +] diff --git a/Makefile b/Makefile index 9fae78723..2dac5dd9e 100644 --- a/Makefile +++ b/Makefile @@ -1,74 +1,35 @@ - BSP = rpi3 TARGET = aarch64-unknown-none-softfloat KERNEL_BIN = kernel8.img +# QEMU QEMU_BINARY = qemu-system-aarch64 QEMU_MACHINE_TYPE = raspi3b QEMU_RELEASE_ARGS = -display none -serial null -serial stdio QEMU_DEBUG_ARGS = -display none -S -s -serial null -serial stdio +EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE) + OBJDUMP_BINARY = aarch64-none-elf-objdump NM_BINARY = aarch64-none-elf-mn READELF_BINARY = aarch64-none-elf-readelf -LD_SCRIPT_PATH = $(shell pwd)/src/bsp/raspberrypi RUSTC_MISC_ARGS = -C target-cpu=cortex-a53 -export LD_SCRIPT_PATH - -KERNEL_MANIFEST = Cargo.toml -KERNEL_LINKER_SCRIPT = kernel.ld -LAST_BUILD_CONFIG = target/$(TARGET).build_config - -KERNEL_ELF = target/$(TARGET)/release/kernel - -# parses cargo's dep-info file. -KERNEL_ELF_DEPS = $(filter-out %: ,$(file < $(KERNEL_ELF).d)) $(KERNEL_MANIFEST) $(LAST_BUILD_CONFIG) - - -# command building blocks - -RUSTFLAGS = $(RUSTC_MISC_ARGS) \ - -C link-arg=--library-path=$(LD_SCRIPT_PATH) \ - -C link-arg=--script=$(KERNEL_LINKER_SCRIPT) -#RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) \ -# -D warnings \ -# -D missing_docs -RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) -# -D warnings \ -# -D missing_docs +KERNEL_PATH = $(shell pwd)/kernel -FEATURE = --features bsp_$(BSP) -COMPILER_ARGS = --target=$(TARGET) \ - $(FEATURES) \ - --release +KERNEL_ELF = target/$(TARGET)/release/kernel +BOOTLOADER_ELF = target/$(TARGET)/release/bootloader -RUSTC_CMD = cargo rustc $(COMPILER_ARGS) -CLIPPY_CMD = cargo clippy $(COMPILER_ARGS) OBJCOPY_CMD = rust-objcopy \ - --strip-all \ - -O binary - -EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE) + --strip-all \ + -O binary -.PHONY: all doc qemu clippy clean readelf objdump nm check +.PHONY: all doc qemu clippy clean readelf objdump nm check all: $(KERNEL_BIN) -# Save the configuration as a file - -$(LAST_BUILD_CONFIG): - @rm -f target/*.build_config - @mkdir -p target - @touch $(LAST_BUILD_CONFIG) - -$(KERNEL_ELF): $(KERNEL_ELF_DEPS) - RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(RUSTC_CMD) - -# -- -C panic=abort -C panic=abort -C opt-level=3 - -$(KERNEL_BIN):$(KERNEL_ELF) +$(KERNEL_BIN): kernel_elf $(call color_header, "Generating stripped binary") @$(OBJCOPY_CMD) $(KERNEL_ELF) $(KERNEL_BIN) $(call color_progress_prefix, "Name") @@ -76,6 +37,9 @@ $(KERNEL_BIN):$(KERNEL_ELF) $(call color_progress_prefix, "Size") $(call disk_usage_KiB, $(KERNEL_BIN)) +kernel_elf: + make -C $(KERNEL_PATH) all + qemu: $(KERNEL_BIN) $(call color_header, "Launching QEMU") $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) @@ -83,8 +47,8 @@ qemu: $(KERNEL_BIN) gdb: $(KERNEL_BIN) $(call color_header, "Launching QEMU in background") $(EXEC_QEMU) $(QEMU_DEBUG_ARGS) -kernel $(KERNEL_BIN) - -clean: - rm -r target - rm $(KERNEL_BIN) +clean: + make -C $(KERNEL_PATH) clean + -rm -r target + -rm $(KERNEL_BIN) diff --git a/bootloader/Cargo.lock b/bootloader/Cargo.lock new file mode 100644 index 000000000..531d09f14 --- /dev/null +++ b/bootloader/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aarch64-cpu" +version = "9.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac42a04a61c19fc8196dd728022a784baecc5d63d7e256c01ad1b3fbfab26287" +dependencies = [ + "tock-registers", +] + +[[package]] +name = "lab1" +version = "0.1.0" +dependencies = [ + "aarch64-cpu", +] + +[[package]] +name = "tock-registers" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" diff --git a/bootloader/Cargo.toml b/bootloader/Cargo.toml new file mode 100644 index 000000000..88d388523 --- /dev/null +++ b/bootloader/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "bootloader" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[profile.release] +lto = true + + +[features] +default = [] +bsp_rpi3 = [] + +# specify bin +[[bin]] +name = "bootloader" +path = "src/main.rs" + +[dependencies] +driver = { path = "../driver" } + + +# Platform specific dependencies +[target.'cfg(target_arch = "aarch64")'.dependencies] +aarch64-cpu = {version = "9.x.x"} + diff --git a/bootloader/Makefile b/bootloader/Makefile new file mode 100644 index 000000000..79842a74a --- /dev/null +++ b/bootloader/Makefile @@ -0,0 +1,64 @@ +BSP = rpi3 + +TARGET = aarch64-unknown-none-softfloat +BL_BIN = bootloader.img + +OBJDUMP_BINARY = aarch64-none-elf-objdump +NM_BINARY = aarch64-none-elf-mn +READELF_BINARY = aarch64-none-elf-readelf + +LD_SCRIPT_PATH = $(shell pwd)/src/bsp/raspberrypi +RUSTC_MISC_ARGS = -C target-cpu=cortex-a53 + +export LD_SCRIPT_PATH + +BL_MANIFEST = Cargo.toml +BL_LINKER_SCRIPT = bootloader.ld +LAST_BUILD_CONFIG = target/$(TARGET).build_config + +BL_ELF = ../target/$(TARGET)/release/bootloader + +# parses cargo's dep-info file. +BL_ELF_DEPS = $(filter-out %: ,$(file < $(BL_ELF).d)) $(BL_MANIFEST) $(LAST_BUILD_CONFIG) + + +# command building blocks + +RUSTFLAGS = $(RUSTC_MISC_ARGS) \ + -C link-arg=--library-path=$(LD_SCRIPT_PATH) \ + -C link-arg=--script=$(BL_LINKER_SCRIPT) + + +#RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) \ +# -D warnings \ +# -D missing_docs + +RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) +# -D warnings \ +# -D missing_docs + +FEATURES = --features bsp_$(BSP) +COMPILER_ARGS = --target=$(TARGET) \ + $(FEATURES) \ + --release + +RUSTC_CMD = cargo rustc $(COMPILER_ARGS) --bin kernel +CLIPPY_CMD = cargo clippy $(COMPILER_ARGS) + + +.PHONY: all doc qemu clippy clean readelf objdump nm check + +all: $(BL_ELF) + +$(LAST_BUILD_CONFIG): + @rm -f target/*.build_config + @mkdir -p target + @touch $(LAST_BUILD_CONFIG) + +$(BL_ELF): $(BL_ELF_DEPS) + RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(RUSTC_CMD) + +clean: + -rm -r target + -rm $(BL_BIN) + diff --git a/bootloader/README.md b/bootloader/README.md new file mode 100644 index 000000000..50c5d4048 --- /dev/null +++ b/bootloader/README.md @@ -0,0 +1,39 @@ + +# OSC2024 + +| Github Account | Student ID | Name | +|----------------|------------|---------------| +| cfmc30 | 109350078 | Erh-Tai Huang | + +## Requirements + +- Install Rust + ``` + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + source $HOME/.cargo/env + ``` + +- Tool Chain + ``` + cargo install cargo-binutils rustfilt + ``` + +- Others are specified in [rust-toolchain.toml](rust-toolchain.toml) which will be configured by cargo. + +## Things that can be improved + +- The structure of the project +- Rust code but with C style +- String with fixed size + +## Build + +``` +make +``` + +## Test With QEMU + +``` +make qemu +``` diff --git a/build.rs b/bootloader/build.rs similarity index 100% rename from build.rs rename to bootloader/build.rs diff --git a/bootloader/rust-toolchain.toml b/bootloader/rust-toolchain.toml new file mode 100644 index 000000000..a554c0a98 --- /dev/null +++ b/bootloader/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2022-10-13" +components = ["rust-src", "llvm-tools-preview", "rustfmt"] +targets = ["aarch64-unknown-none-softfloat"] diff --git a/src/_arch/aarch64/cpu.rs b/bootloader/src/_arch/aarch64/cpu.rs similarity index 100% rename from src/_arch/aarch64/cpu.rs rename to bootloader/src/_arch/aarch64/cpu.rs diff --git a/bootloader/src/_arch/aarch64/cpu/boot.rs b/bootloader/src/_arch/aarch64/cpu/boot.rs new file mode 100644 index 000000000..058c5e2d8 --- /dev/null +++ b/bootloader/src/_arch/aarch64/cpu/boot.rs @@ -0,0 +1,15 @@ + +use core::arch::global_asm; +use core::arch::asm; + +global_asm!( + include_str!("boot.s") , + CONST_CORE_ID_MASK = const 0b11 +); + +// mod uart; + +#[no_mangle] +pub unsafe fn _start_rust(){ + crate::bootloader() +} diff --git a/src/_arch/aarch64/cpu/boot_tmp.s b/bootloader/src/_arch/aarch64/cpu/boot.s similarity index 60% rename from src/_arch/aarch64/cpu/boot_tmp.s rename to bootloader/src/_arch/aarch64/cpu/boot.s index 0011c6074..e08bbbfd5 100644 --- a/src/_arch/aarch64/cpu/boot_tmp.s +++ b/bootloader/src/_arch/aarch64/cpu/boot.s @@ -1,18 +1,4 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -// -// Copyright (c) 2021-2022 Andre Richter -//-------------------------------------------------------------------------------------------------- -// Definitions -//-------------------------------------------------------------------------------------------------- - -// Load the address of a symbol into a register, PC-relative. -// -// The symbol must lie within +/- 4 GiB of the Program Counter. -// -// # Resources -// -// - https://sourceware.org/binutils/docs-2.36/as/AArch64_002dRelocations.html .macro ADR_REL register, symbol adrp \register, \symbol add \register, \register, #:lo12:\symbol @@ -27,6 +13,9 @@ // fn _start() //------------------------------------------------------------------------------ _start: + b _bootloader + +_bootloader: // Only proceed on the boot core. Park it otherwise. mrs x0, MPIDR_EL1 and x0, x0, {CONST_CORE_ID_MASK} @@ -38,22 +27,25 @@ _start: // Initialize DRAM. ADR_REL x0, __bss_start - ADR_REL x1, __bss_end_exclusive + ADR_REL x1, __bss_end_exclusive .L_bss_init_loop: - cmp x0, x1 - b.eq .L_prepare_rust - stp xzr, xzr, [x0], #16 - b .L_bss_init_loop + cmp x0, x1 + b.eq .L_prepare_rust + stp xzr, xzr, [x0], #16 + b .L_bss_init_loop + // Prepare the jump to Rust code. .L_prepare_rust: // Set the stack pointer. - ADR_REL x0, __boot_core_stack_end_exclusive - mov sp, x0 + mov sp, 0x80000 // Jump to Rust code. - b _start_rust + bl _start_rust + + // After loaded the kernel jump to _start aka 0x80000 + b _start // Infinitely wait for events (aka "park the core"). .L_parking_loop: diff --git a/src/bsp.rs b/bootloader/src/bsp.rs similarity index 100% rename from src/bsp.rs rename to bootloader/src/bsp.rs diff --git a/src/bsp/raspberrypi.rs b/bootloader/src/bsp/raspberrypi.rs similarity index 100% rename from src/bsp/raspberrypi.rs rename to bootloader/src/bsp/raspberrypi.rs diff --git a/bootloader/src/bsp/raspberrypi/bootloader.ld b/bootloader/src/bsp/raspberrypi/bootloader.ld new file mode 100644 index 000000000..66b9d4b11 --- /dev/null +++ b/bootloader/src/bsp/raspberrypi/bootloader.ld @@ -0,0 +1,39 @@ +__rpi_phys_dram_start_addr = 0; +__rpi_bootloader_addr = 0x60000; +__rpi_phys_binary_load_addr = 0x80000; + +ENTRY(__rpi_phys_binary_load_addr) + + +SECTIONS +{ + . = __rpi_bootloader_addr + .text : + { + KEEP(*(.text._bootloader)) + *(.text._bootloader_arguments) /* Constants (or statics in Rust speak) read by _start(). */ + *(.text._start_rust) /* The Rust entry point */ + *(.text*) /* Everything else */ + } :segment_code + + . = __rpi_phys_binary_load_addr; + .text : + { + KEEP(*(.text._start)) + } + + .rodata : ALIGN(8) { *(.rodata*) } :segment_code + + .data : { *(.data*) } + + /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */ + + .bss (NOLOAD): ALIGN(16) + { + __bss_start = .; + *(.bss*); + . = ALIGN(16); + __bss_end_exclusive = .; + } + +} diff --git a/src/bsp/raspberrypi/cpu.rs b/bootloader/src/bsp/raspberrypi/cpu.rs similarity index 100% rename from src/bsp/raspberrypi/cpu.rs rename to bootloader/src/bsp/raspberrypi/cpu.rs diff --git a/src/cpu.rs b/bootloader/src/cpu.rs similarity index 100% rename from src/cpu.rs rename to bootloader/src/cpu.rs diff --git a/src/cpu/boot.rs b/bootloader/src/cpu/boot.rs similarity index 100% rename from src/cpu/boot.rs rename to bootloader/src/cpu/boot.rs diff --git a/bootloader/src/main.rs b/bootloader/src/main.rs new file mode 100644 index 000000000..17871c4aa --- /dev/null +++ b/bootloader/src/main.rs @@ -0,0 +1,56 @@ +#![feature(asm_const)] +#![no_main] +#![no_std] + +mod bsp; +mod cpu; +mod panic_wait; + + +use core::{ + ptr::{read_volatile, write_volatile}, + usize, +}; + +use driver::uart; +use driver::mailbox; + +const KERNEL_LOAD_ADDR: u64 = 0x80000; + + +// load the kernel from uart +#[no_mangle] +unsafe fn bootloader() -> ! { + // initialize uart + uart::init_uart(); + uart::_print("Bootloader started\r\n"); + + // read kernel size + let mut kernel_size: u32 = 0; + + // read kernel size (4 bytes) from uart + uart::read(&mut kernel_size as *mut u32 as *mut u8 /*(uint8_t)(&kernel_size) */, 4); + uart::_print("Kernel size: "); + uart::print_hex(kernel_size); + uart::_print("\r\n"); + + // start to read kernel + let mut kernel_addr: u64 = KERNEL_LOAD_ADDR; + let mut read_size: u32 = 0; + while read_size < kernel_size { + let mut read_buf: [u8; 128] = [0; 128]; + let mut read_len: usize = 128; + if kernel_size - read_size < 128 { + read_len = (kernel_size - read_size) as usize; + } + uart::read(read_buf.as_mut_ptr(), read_len); + for i in 0..read_len { + write_volatile(kernel_addr as *mut u8, read_buf[i]); + kernel_addr += 1; + } + read_size += read_len as u32; + } + + // jump to kernel + uart::_print("Jump to kernel\r\n"); +} diff --git a/src/panic_wait.rs b/bootloader/src/panic_wait.rs similarity index 100% rename from src/panic_wait.rs rename to bootloader/src/panic_wait.rs diff --git a/driver b/driver new file mode 160000 index 000000000..4c0133249 --- /dev/null +++ b/driver @@ -0,0 +1 @@ +Subproject commit 4c0133249a520d730fece3b62d666c17aa3e2910 diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock new file mode 100644 index 000000000..531d09f14 --- /dev/null +++ b/kernel/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aarch64-cpu" +version = "9.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac42a04a61c19fc8196dd728022a784baecc5d63d7e256c01ad1b3fbfab26287" +dependencies = [ + "tock-registers", +] + +[[package]] +name = "lab1" +version = "0.1.0" +dependencies = [ + "aarch64-cpu", +] + +[[package]] +name = "tock-registers" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml new file mode 100644 index 000000000..087da813f --- /dev/null +++ b/kernel/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "kernel" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[profile.release] +lto = true + + +[features] +default = [] +bsp_rpi3 = [] + +# specify bin +[[bin]] +name = "kernel" +path = "src/main.rs" + +[dependencies] +driver = { path = "../driver" } + + +# Platform specific dependencies +[target.'cfg(target_arch = "aarch64")'.dependencies] +aarch64-cpu = {version = "9.x.x"} + diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 000000000..7b19ef7c7 --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,70 @@ + +BSP = rpi3 + +TARGET = aarch64-unknown-none-softfloat +KERNEL_BIN = kernel8.img +QEMU_BINARY = qemu-system-aarch64 +QEMU_MACHINE_TYPE = raspi3b +QEMU_RELEASE_ARGS = -display none -serial null -serial stdio +QEMU_DEBUG_ARGS = -display none -S -s -serial null -serial stdio +OBJDUMP_BINARY = aarch64-none-elf-objdump +NM_BINARY = aarch64-none-elf-mn +READELF_BINARY = aarch64-none-elf-readelf +LD_SCRIPT_PATH = $(shell pwd)/src/bsp/raspberrypi +RUSTC_MISC_ARGS = -C target-cpu=cortex-a53 + +export LD_SCRIPT_PATH + +KERNEL_MANIFEST = Cargo.toml +KERNEL_LINKER_SCRIPT = kernel.ld +LAST_BUILD_CONFIG = target/$(TARGET).build_config + +KERNEL_ELF = ../target/$(TARGET)/release/kernel + +# parses cargo's dep-info file. +KERNEL_ELF_DEPS = $(filter-out %: ,$(file < $(KERNEL_ELF).d)) $(KERNEL_MANIFEST) $(LAST_BUILD_CONFIG) + + +# command building blocks + +RUSTFLAGS = $(RUSTC_MISC_ARGS) \ + -C link-arg=--library-path=$(LD_SCRIPT_PATH) \ + -C link-arg=--script=$(KERNEL_LINKER_SCRIPT) + + +#RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) \ +# -D warnings \ +# -D missing_docs + +RUSTFLAGS_PEDANTIC = $(RUSTFLAGS) +# -D warnings \ +# -D missing_docs + +FEATURES = --features bsp_$(BSP) +COMPILER_ARGS = --target=$(TARGET) \ + $(FEATURES) \ + --release + +RUSTC_CMD = cargo rustc $(COMPILER_ARGS) --bin kernel +CLIPPY_CMD = cargo clippy $(COMPILER_ARGS) + + +.PHONY: all doc qemu clippy clean readelf objdump nm check + +all: $(KERNEL_ELF) + +$(LAST_BUILD_CONFIG): + @rm -f target/*.build_config + @mkdir -p target + @touch $(LAST_BUILD_CONFIG) + +$(KERNEL_ELF): $(KERNEL_ELF_DEPS) + RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(RUSTC_CMD) + +# -- -C panic=abort -C panic=abort -C opt-level=3 + + +clean: + -rm -r target + -rm $(KERNEL_BIN) + diff --git a/kernel/README.md b/kernel/README.md new file mode 100644 index 000000000..50c5d4048 --- /dev/null +++ b/kernel/README.md @@ -0,0 +1,39 @@ + +# OSC2024 + +| Github Account | Student ID | Name | +|----------------|------------|---------------| +| cfmc30 | 109350078 | Erh-Tai Huang | + +## Requirements + +- Install Rust + ``` + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + source $HOME/.cargo/env + ``` + +- Tool Chain + ``` + cargo install cargo-binutils rustfilt + ``` + +- Others are specified in [rust-toolchain.toml](rust-toolchain.toml) which will be configured by cargo. + +## Things that can be improved + +- The structure of the project +- Rust code but with C style +- String with fixed size + +## Build + +``` +make +``` + +## Test With QEMU + +``` +make qemu +``` diff --git a/kernel/build.rs b/kernel/build.rs new file mode 100644 index 000000000..a6234085a --- /dev/null +++ b/kernel/build.rs @@ -0,0 +1,21 @@ +use std::{env, fs, process}; + +fn main() { + let ld_script_path = match env::var("LD_SCRIPT_PATH") { + Ok(var) => var, + _ => process::exit(0), + }; + + let files = fs::read_dir(ld_script_path).unwrap(); + files + .filter_map(Result::ok) + .filter(|d| { + if let Some(e) = d.path().extension() { + e == "ld" + } + else { + false + } + }) + .for_each(|f| println!("cargo:rerun-if-changed={}", f.path().display())); +} diff --git a/kernel/rust-toolchain.toml b/kernel/rust-toolchain.toml new file mode 100644 index 000000000..a554c0a98 --- /dev/null +++ b/kernel/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2022-10-13" +components = ["rust-src", "llvm-tools-preview", "rustfmt"] +targets = ["aarch64-unknown-none-softfloat"] diff --git a/kernel/src/_arch/aarch64/cpu.rs b/kernel/src/_arch/aarch64/cpu.rs new file mode 100644 index 000000000..8b5266023 --- /dev/null +++ b/kernel/src/_arch/aarch64/cpu.rs @@ -0,0 +1,24 @@ +use aarch64_cpu::asm; + +// public code +/// pause execution on the core + + +#[inline(always)] +pub fn wait_forever() -> ! { + loop { + asm::wfe(); + } +} + +/* +const int PM_RSTC = 0x2010001c; +const int PM_WDOG = 0x20100024; +const int PM_PASSWORD = 0x5a000000; +const int PM_RSTC_WRCFG_FULL_RESET = 0x00000020; + +PUT32(PM_WDOG, PM_PASSWORD | 1); // timeout = 1/16th of a second? (whatever) +PUT32(PM_RSTC, PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); +*/ + + diff --git a/src/_arch/aarch64/cpu/boot.rs b/kernel/src/_arch/aarch64/cpu/boot.rs similarity index 89% rename from src/_arch/aarch64/cpu/boot.rs rename to kernel/src/_arch/aarch64/cpu/boot.rs index d63a91db7..699482d4d 100644 --- a/src/_arch/aarch64/cpu/boot.rs +++ b/kernel/src/_arch/aarch64/cpu/boot.rs @@ -1,6 +1,5 @@ use core::arch::global_asm; -use core::arch::asm; global_asm!( include_str!("boot.s") , @@ -12,5 +11,4 @@ global_asm!( #[no_mangle] pub unsafe fn _start_rust(){ crate::kernel_init() - } diff --git a/src/_arch/aarch64/cpu/boot.s b/kernel/src/_arch/aarch64/cpu/boot.s similarity index 100% rename from src/_arch/aarch64/cpu/boot.s rename to kernel/src/_arch/aarch64/cpu/boot.s diff --git a/kernel/src/bsp.rs b/kernel/src/bsp.rs new file mode 100644 index 000000000..a0751c7ec --- /dev/null +++ b/kernel/src/bsp.rs @@ -0,0 +1,3 @@ +mod raspberrypi; +pub use raspberrypi::*; + diff --git a/kernel/src/bsp/raspberrypi.rs b/kernel/src/bsp/raspberrypi.rs new file mode 100644 index 000000000..3bfb62f3d --- /dev/null +++ b/kernel/src/bsp/raspberrypi.rs @@ -0,0 +1 @@ +pub mod cpu; diff --git a/kernel/src/bsp/raspberrypi/cpu.rs b/kernel/src/bsp/raspberrypi/cpu.rs new file mode 100644 index 000000000..e899e2c00 --- /dev/null +++ b/kernel/src/bsp/raspberrypi/cpu.rs @@ -0,0 +1,7 @@ + +// boot core id +#[no_mangle] +#[link_section = ".text._start_arguments"] +pub static BOOT_CORE_ID: u64 = 0; + + diff --git a/src/bsp/raspberrypi/kernel.ld b/kernel/src/bsp/raspberrypi/kernel.ld similarity index 99% rename from src/bsp/raspberrypi/kernel.ld rename to kernel/src/bsp/raspberrypi/kernel.ld index e48ede7c1..360d2a863 100644 --- a/src/bsp/raspberrypi/kernel.ld +++ b/kernel/src/bsp/raspberrypi/kernel.ld @@ -9,7 +9,6 @@ ENTRY(__rpi_phys_binary_load_addr) SECTIONS { - . = __rpi_phys_binary_load_addr; .text : { diff --git a/kernel/src/cpu.rs b/kernel/src/cpu.rs new file mode 100644 index 000000000..c029d9b00 --- /dev/null +++ b/kernel/src/cpu.rs @@ -0,0 +1,8 @@ +#[cfg(target_arch = "aarch64")] +#[path = "_arch/aarch64/cpu.rs"] +mod arch_cpu; + +mod boot; + +pub use arch_cpu::wait_forever; + diff --git a/kernel/src/cpu/boot.rs b/kernel/src/cpu/boot.rs new file mode 100644 index 000000000..b244f2185 --- /dev/null +++ b/kernel/src/cpu/boot.rs @@ -0,0 +1,3 @@ +#[cfg(target_arch = "aarch64")] +#[path = "../_arch/aarch64/cpu/boot.rs"] +mod arch_boot; diff --git a/src/main.rs b/kernel/src/main.rs similarity index 51% rename from src/main.rs rename to kernel/src/main.rs index fd90eab8d..c27cd6a96 100644 --- a/src/main.rs +++ b/kernel/src/main.rs @@ -2,62 +2,41 @@ #![no_main] #![no_std] -use crate::uart::strcmp; -use core::{ - ptr::{read_volatile, write_volatile}, - usize, -}; - mod bsp; mod cpu; mod panic_wait; -mod uart; -mod mailbox; + +use core::ptr::write_volatile; + +use driver::uart; +use driver::mailbox; #[no_mangle] unsafe fn kernel_init() -> ! { uart::init_uart(); - - for i in b"Revision: " { - uart::write_char(*i); - } - + uart::_print("Revision: "); // get board revision let revision = mailbox::get_board_revisioin(); - // convert revision to string - let mut rev_str: [u8; 128] = [0; 128]; - let mut rev_str_len = 0; - // print hex of revision uart::print_hex(revision); - - uart::write_char(b'\n'); - uart::write_char(b'\r'); + uart::println(""); // get ARM memory base address and size let (base, size) = mailbox::get_arm_memory(); // print ARM memory base address and size - for i in b"ARM memory base address: " { - uart::write_char(*i); - } + uart::_print("ARM memory base address: "); uart::print_hex(base); - uart::write_char(b'\n'); - uart::write_char(b'\r'); + uart::_print("\r\n"); - for i in b"ARM memory size: " { - uart::write_char(*i); - } - uart::print_hex(size); - uart::write_char(b'\n'); - uart::write_char(b'\r'); - + uart::_print("ARM memory size: "); + uart::print_hex(size); + uart::_print("\r\n"); let mut out_buf: [u8; 128] = [0; 128]; let mut in_buf: [u8; 128] = [0; 128]; - let out_buf_len: usize = 2; out_buf[0] = 62; out_buf[1] = 62; @@ -72,25 +51,14 @@ unsafe fn kernel_init() -> ! { help_str[..4].copy_from_slice(b"help"); let help_len = 4; - let mut hello_world_str: [u8; 128] = [0; 128]; - - let hello_world_len = 1010; - loop { - uart::print_str(&out_buf, out_buf_len); + uart::_print(">> "); let in_buf_len = uart::get_line(&mut in_buf, true); - if strcmp(&in_buf, in_buf_len, &hello_str, hello_len) { - for i in b"Hello World!\r\n" { - uart::write_char(*i); - } - uart::write_char(10); - } else if strcmp(&in_buf, in_buf_len, &help_str, help_len) { - - for i in b"help : print this help menu\r\nhello : print Hello World!\r\nreboot : reboot the device\r\n" { - uart::write_char(*i); - } - uart::write_char(10); - } else if strcmp(&in_buf, in_buf_len, &reboot_str, 6) { + if uart::strcmp(&in_buf, in_buf_len, &hello_str, hello_len) { + uart::_print("Hello World!\r\n"); + } else if uart::strcmp(&in_buf, in_buf_len, &help_str, help_len) { + uart::_print("help : print this help menu\r\nhello : print Hello World!\r\nreboot : reboot the device\r\n"); + } else if uart::strcmp(&in_buf, in_buf_len, &reboot_str, 6) { const PM_PASSWORD: u32 = 0x5a000000; const PM_RSTC: u32 = 0x3F10001c; @@ -100,7 +68,7 @@ unsafe fn kernel_init() -> ! { write_volatile(PM_RSTC as *mut u32, PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); break; } - uart::nops(); + uart::uart_nops(); } panic!() } diff --git a/kernel/src/panic_wait.rs b/kernel/src/panic_wait.rs new file mode 100644 index 000000000..c297b7a74 --- /dev/null +++ b/kernel/src/panic_wait.rs @@ -0,0 +1,7 @@ +use crate::cpu; +use core::panic::PanicInfo; + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + cpu::wait_forever() +} diff --git a/src/_arch/aarch64/cpu/regs.rs b/src/_arch/aarch64/cpu/regs.rs deleted file mode 100644 index d0a094e32..000000000 --- a/src/_arch/aarch64/cpu/regs.rs +++ /dev/null @@ -1,2 +0,0 @@ -// enum of all the address to the registers - diff --git a/src/bsp/raspberrypi/kernel_tmp.ld b/src/bsp/raspberrypi/kernel_tmp.ld deleted file mode 100644 index f6c188434..000000000 --- a/src/bsp/raspberrypi/kernel_tmp.ld +++ /dev/null @@ -1,79 +0,0 @@ -/* SPDX-License-Identifier: MIT OR Apache-2.0 - * - * Copyright (c) 2018-2022 Andre Richter - */ - -__rpi_phys_dram_start_addr = 0; - -/* The physical address at which the the kernel binary will be loaded by the Raspberry's firmware */ -__rpi_phys_binary_load_addr = 0x80000; - - -ENTRY(__rpi_phys_binary_load_addr) - -/* Flags: - * 4 == R - * 5 == RX - * 6 == RW - * - * Segments are marked PT_LOAD below so that the ELF file provides virtual and physical addresses. - * It doesn't mean all of them need actually be loaded. - */ -PHDRS -{ - segment_boot_core_stack PT_LOAD FLAGS(6); - segment_code PT_LOAD FLAGS(5); - segment_data PT_LOAD FLAGS(6); -} - -SECTIONS -{ - . = __rpi_phys_dram_start_addr; - - /*********************************************************************************************** - * Boot Core Stack - ***********************************************************************************************/ - .boot_core_stack (NOLOAD) : - { - /* ^ */ - /* | stack */ - . += __rpi_phys_binary_load_addr; /* | growth */ - /* | direction */ - __boot_core_stack_end_exclusive = .; /* | */ - } :segment_boot_core_stack - - /*********************************************************************************************** - * Code + RO Data + Global Offset Table - ***********************************************************************************************/ - .text : - { - KEEP(*(.text._start)) - *(.text._start_arguments) /* Constants (or statics in Rust speak) read by _start(). */ - *(.text._start_rust) /* The Rust entry point */ - *(.text*) /* Everything else */ - } :segment_code - - .rodata : ALIGN(8) { *(.rodata*) } :segment_code - - /*********************************************************************************************** - * Data + BSS - ***********************************************************************************************/ - .data : { *(.data*) } :segment_data - - /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */ - .bss (NOLOAD) : ALIGN(16) - { - __bss_start = .; - *(.bss*); - . = ALIGN(16); - __bss_end_exclusive = .; - } :segment_data - - /*********************************************************************************************** - * Misc - ***********************************************************************************************/ - .got : { *(.got*) } - ASSERT(SIZEOF(.got) == 0, "Relocation support not expected") - - /DISCARD/ : { *(.comment*) } -} diff --git a/src/mailbox.rs b/src/mailbox.rs deleted file mode 100644 index e3a570ec2..000000000 --- a/src/mailbox.rs +++ /dev/null @@ -1,84 +0,0 @@ -const MMIO_BASE: u32 = 0x3f000000; -const MAILBOX_BASE: u32 = MMIO_BASE + 0xb880; - -const MAILBOX_READ: u32 = MAILBOX_BASE; -const MAILBOX_STATUS: u32 = MAILBOX_BASE + 0x18; -const MAILBOX_WRITE: u32 = MAILBOX_BASE + 0x20; - -const MAILBOX_EMPTY: u32 = 0x40000000; -const MAILBOX_FULL: u32 = 0x80000000; - -use core::ptr::{read_volatile, write_volatile}; - -unsafe fn mailbox_call(mailbox: &mut [u32]) { - // check if the mailbox is full - let mut status: u32; - loop { - status = read_volatile(MAILBOX_STATUS as *const u32); - if (status & MAILBOX_FULL) == 0 { - // mailbox is not full, we can write the message - break; - } - } - // Combine the message address (upper 28 bits) with channel number (lower 4 bits) - let channel = 8; - let message_address = mailbox.as_ptr() as u32; - let combined_address = (message_address & 0xFFFFFFF0) | (channel & 0xF); - write_volatile(MAILBOX_WRITE as *mut u32, combined_address as u32); - - // check if the mailbox is empty - loop { - status = read_volatile(MAILBOX_STATUS as *const u32); - if (status & MAILBOX_EMPTY) == 0 { - // mailbox is not empty, we can read the message - break; - } - } - if read_volatile(MAILBOX_READ as *const u32) != (message_address as u32) {} -} - -const GET_BOARD_REVISION: u32 = 0x00010002; -const REQUEST_CODE: u32 = 0x00000000; -const REQUEST_SUCCEED: u32 = 0x80000000; -const REQUEST_FAILED: u32 = 0x80000001; -const TAG_REQUEST_CODE: u32 = 0x00000000; -const END_TAG: u32 = 0x00000000; - -pub unsafe fn get_board_revisioin() -> u32 { - let mut mailbox: [u32; 32] = [0; 32]; - let idx_offset:usize = (0x10 - mailbox.as_ptr() as u32 & 0xf) as usize; - - - mailbox[0 + idx_offset] = 7 * 4; - mailbox[1 + idx_offset] = REQUEST_CODE; - mailbox[2 + idx_offset] = GET_BOARD_REVISION; - mailbox[3 + idx_offset] = 4; - mailbox[4 + idx_offset] = TAG_REQUEST_CODE; - mailbox[5 + idx_offset] = 0; - mailbox[6 + idx_offset] = END_TAG; - - - mailbox_call(&mut mailbox[idx_offset..(idx_offset + 7)]); - - mailbox[5] -} - -// Get ARM memory base address and size using mailbox -const GET_ARM_MEMORY: u32 = 0x00010005; -pub unsafe fn get_arm_memory() -> (u32, u32) { - let mut mailbox: [u32; 32] = [0; 32]; - let idx_offset:usize = (0x10 - mailbox.as_ptr() as u32 & 0xf) as usize; - - mailbox[0 + idx_offset] = 8 * 4; - mailbox[1 + idx_offset] = REQUEST_CODE; - mailbox[2 + idx_offset] = GET_ARM_MEMORY; - mailbox[3 + idx_offset] = 8; - mailbox[4 + idx_offset] = TAG_REQUEST_CODE; - mailbox[5 + idx_offset] = 0; - mailbox[6 + idx_offset] = 0; - mailbox[7 + idx_offset] = END_TAG; - - mailbox_call(&mut mailbox[idx_offset..(idx_offset + 8)]); - - (mailbox[5], mailbox[6]) -} diff --git a/src/my_string.rs b/src/my_string.rs deleted file mode 100644 index b3001cb6f..000000000 --- a/src/my_string.rs +++ /dev/null @@ -1,14 +0,0 @@ -use core::usize; - - -const MY_STRING_LEN : usize = 128; - -#[derive(Debug)] -struct MyString { - arr: [u8 ; MY_STRING_LEN], - len: usize, -} -impl MyString { -} - - diff --git a/src/my_string/my_string b/src/my_string/my_string deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/uart.rs b/src/uart.rs deleted file mode 100644 index 5526101f8..000000000 --- a/src/uart.rs +++ /dev/null @@ -1,206 +0,0 @@ -use core::arch::asm; -use core::{ - ptr::{read_volatile, write_volatile}, - usize, -}; - -const AUXENB: u32 = 0x3F215004; -const AUX_MU_CNTL_REG: u32 = 0x3F215060; -const AUX_MU_IER_REG: u32 = 0x3F215044; -const AUX_MU_LCR_REG: u32 = 0x3F21504C; -const AUX_MU_MCR_REG: u32 = 0x3F215050; -const AUX_MU_BAUD_REG: u32 = 0x3F215068; -const AUX_MU_IIR_REG: u32 = 0x3F215048; -const AUX_MU_IO_REG: u32 = 0x3F215040; -const AUX_MU_LSR_REG: u32 = 0x3F215054; - -const GPFSEL_BASE: u32 = 0x3F200000; -const GPFSEL0: u32 = 0x3F200000; -const GPFSEL1: u32 = 0x3F200004; - -const GPPUD: u32 = 0x3F200094; -const GPPUDCLK0: u32 = 0x3F200098; -const GPPUDCLK1: u32 = 0x3F20009C; - -// Initialize the UART -#[no_mangle] -#[inline(never)] -pub fn init_uart() { - unsafe { - // configure GPFSEL1 register to set FSEL14 FSEL15 to ALT5 - let fsel = read_volatile(GPFSEL1 as *mut u32); - let fsel_mask = !(0b111111 << 12); - let fsel_set = 0b010010 << 12; - write_volatile(GPFSEL1 as *mut u32, (fsel & fsel_mask) | fsel_set); - - // configure pull up/down register to disable GPIO pull up/down - let pud = 0b0; - write_volatile(GPPUD as *mut u32, pud); - - // wait 150 cycles - nops(); - - // configure pull up/down clock register to disable GPIO pull up/down - let pudclk0 = !(0b11 << 14); - write_volatile(GPPUDCLK0 as *mut u32, pudclk0); - let pudclk1 = 0; - write_volatile(GPPUDCLK1 as *mut u32, pudclk1); - // wait 150 cycles - nops(); - - // Write to GPPUD to remove the control signal - write_volatile(GPPUD as *mut u32, 0); - // Write to GPPUDCLK0 to remove the clock - write_volatile(GPPUDCLK0 as *mut u32, 0); - - // write some word to uart to initialize it - // Set AUXENB register to enable mini UART - write_volatile(AUXENB as *mut u32, 1); - - // Set AUX_MU_CNTL_REG to 0 - write_volatile(AUX_MU_CNTL_REG as *mut u32, 0); - // Set AUX_MU_IER_REG to 0 - write_volatile(AUX_MU_IER_REG as *mut u32, 0); - // Set AUX_MU_LCR_REG to 3 - write_volatile(AUX_MU_LCR_REG as *mut u32, 3); - // Set AUX_MU_MCR_REG to 0 - write_volatile(AUX_MU_MCR_REG as *mut u32, 0); - // Set AUX_MU_BAUD_REG to 270 - write_volatile(AUX_MU_BAUD_REG as *mut u32, 270); - // Set AUX_MU_IIR_REG to 6 - write_volatile(AUX_MU_IIR_REG as *mut u32, 6); - // Set AUX_MU_CNTL_REG to 3 - write_volatile(AUX_MU_CNTL_REG as *mut u32, 3); - } -} - -#[no_mangle] -#[inline(never)] -pub fn print_hello() { - unsafe { - let hello: [u8; 5] = [72, 101, 108, 108, 111]; - write_volatile(AUX_MU_IO_REG as *mut u32, 72); - write_volatile(AUX_MU_IO_REG as *mut u32, 101); - write_volatile(AUX_MU_IO_REG as *mut u32, 108); - write_volatile(AUX_MU_IO_REG as *mut u32, 108); - write_volatile(AUX_MU_IO_REG as *mut u32, 111); - } -} - -#[no_mangle] -#[inline(never)] -pub unsafe fn print_str(buf: &[u8; 128], buf_len: usize) { - let mut ptr: usize = 0; - while ptr < buf_len { - write_char(buf[ptr]); - ptr = ptr + 1; - } -} - -#[no_mangle] -#[inline(never)] -pub unsafe fn strcmp(s1: &[u8; 128], l1: usize, s2: &[u8; 128], l2: usize) -> bool { - if l1 != l2 { - return false; - } - let mut idx: usize = 0; - while idx < l1 { - if s1[idx] != s2[idx] { - return false; - } - idx = idx + 1; - } - true -} - -#[no_mangle] -#[inline(never)] -pub unsafe fn get_line(s: &mut [u8; 128], is_echo: bool) -> usize { - let mut ptr: usize = 0; - loop { - let c: Option = read_char(); - match c { - Some(i) => { - if is_echo { - write_char(i as u8); - } - if i == 13 { - write_char(10); - break; - } - s[ptr] = i as u8; - ptr = ptr + 1; - } - None => {} - } - asm!("nop"); - } - ptr -} - -#[no_mangle] -pub unsafe fn nops() { - for _ in 0..150 { - asm!("nop"); - } -} - -// Function to print something using the UART -#[no_mangle] -pub unsafe fn write_char(s: u8) { - // Add your UART printing code here - // Example: write to UART buffer or transmit data - // check if the UART is ready to transmit - loop { - if (read_volatile(AUX_MU_LSR_REG as *mut u32) & 0b100000) != 0 { - break; - } - } - write_volatile(AUX_MU_IO_REG as *mut u8, s as u8); -} - -#[no_mangle] -#[inline(never)] -pub unsafe fn read_char() -> Option { - let lsr: u32 = read_volatile(AUX_MU_LSR_REG as *mut u32) & 0b1; - if lsr != 0 { - Some(read_volatile(AUX_MU_IO_REG as *mut u32)) - } else { - None - } -} - -// print u32 in hex -#[no_mangle] -pub unsafe fn print_hex(n: u32) { - let mut buf: [u8; 8] = [0; 8]; - let mut ptr: usize = 0; - let mut num: u32 = n; - for _ in 0..8 { - let rem: u8 = (num % 16) as u8; - if rem < 10 { - buf[ptr] = (rem + b'0') as u8; - } else { - buf[ptr] = (rem - 10 + b'A') as u8; - } - ptr = ptr + 1; - num = num / 16; - } - for i in buf.iter().take(8).rev(){ - write_char(*i); - } -} - -// // Create a global instance of the UART -// pub static mut UART: Uart = Uart {}; - -// // UART struct -// pub struct Uart {} - -// // Example usage -// fn main() { -// unsafe { -// init_uart(); -// writeln!(UART, "Hello, world!").unwrap(); -// } -// } From 041b93a79bde3612a867a9e0a0fd54ae04b1eb81 Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Sun, 24 Mar 2024 00:04:23 +0800 Subject: [PATCH 04/34] Driver --- driver | 1 - driver/Cargo.lock | 25 ++++++ driver/Cargo.toml | 18 ++++ driver/src/lib.rs | 4 + driver/src/mailbox.rs | 84 ++++++++++++++++++ driver/src/uart.rs | 195 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 326 insertions(+), 1 deletion(-) delete mode 160000 driver create mode 100644 driver/Cargo.lock create mode 100644 driver/Cargo.toml create mode 100644 driver/src/lib.rs create mode 100644 driver/src/mailbox.rs create mode 100644 driver/src/uart.rs diff --git a/driver b/driver deleted file mode 160000 index 4c0133249..000000000 --- a/driver +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4c0133249a520d730fece3b62d666c17aa3e2910 diff --git a/driver/Cargo.lock b/driver/Cargo.lock new file mode 100644 index 000000000..531d09f14 --- /dev/null +++ b/driver/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aarch64-cpu" +version = "9.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac42a04a61c19fc8196dd728022a784baecc5d63d7e256c01ad1b3fbfab26287" +dependencies = [ + "tock-registers", +] + +[[package]] +name = "lab1" +version = "0.1.0" +dependencies = [ + "aarch64-cpu", +] + +[[package]] +name = "tock-registers" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" diff --git a/driver/Cargo.toml b/driver/Cargo.toml new file mode 100644 index 000000000..3c7f6d9f7 --- /dev/null +++ b/driver/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "driver" +version = "0.1.0" +edition = "2021" + +[profile.release] +lto = true + +[features] +default = [] +bsp_rpi3 = [] + +[dependencies] + +# Platform specific dependencies +aarch64-cpu = {version = "9.x.x"} + +[target.'cfg(target_arch = "aarch64")'.dependencies] diff --git a/driver/src/lib.rs b/driver/src/lib.rs new file mode 100644 index 000000000..6bf9030bd --- /dev/null +++ b/driver/src/lib.rs @@ -0,0 +1,4 @@ +#![allow(dead_code)] +#![no_std] +pub mod uart; +pub mod mailbox; \ No newline at end of file diff --git a/driver/src/mailbox.rs b/driver/src/mailbox.rs new file mode 100644 index 000000000..e3a570ec2 --- /dev/null +++ b/driver/src/mailbox.rs @@ -0,0 +1,84 @@ +const MMIO_BASE: u32 = 0x3f000000; +const MAILBOX_BASE: u32 = MMIO_BASE + 0xb880; + +const MAILBOX_READ: u32 = MAILBOX_BASE; +const MAILBOX_STATUS: u32 = MAILBOX_BASE + 0x18; +const MAILBOX_WRITE: u32 = MAILBOX_BASE + 0x20; + +const MAILBOX_EMPTY: u32 = 0x40000000; +const MAILBOX_FULL: u32 = 0x80000000; + +use core::ptr::{read_volatile, write_volatile}; + +unsafe fn mailbox_call(mailbox: &mut [u32]) { + // check if the mailbox is full + let mut status: u32; + loop { + status = read_volatile(MAILBOX_STATUS as *const u32); + if (status & MAILBOX_FULL) == 0 { + // mailbox is not full, we can write the message + break; + } + } + // Combine the message address (upper 28 bits) with channel number (lower 4 bits) + let channel = 8; + let message_address = mailbox.as_ptr() as u32; + let combined_address = (message_address & 0xFFFFFFF0) | (channel & 0xF); + write_volatile(MAILBOX_WRITE as *mut u32, combined_address as u32); + + // check if the mailbox is empty + loop { + status = read_volatile(MAILBOX_STATUS as *const u32); + if (status & MAILBOX_EMPTY) == 0 { + // mailbox is not empty, we can read the message + break; + } + } + if read_volatile(MAILBOX_READ as *const u32) != (message_address as u32) {} +} + +const GET_BOARD_REVISION: u32 = 0x00010002; +const REQUEST_CODE: u32 = 0x00000000; +const REQUEST_SUCCEED: u32 = 0x80000000; +const REQUEST_FAILED: u32 = 0x80000001; +const TAG_REQUEST_CODE: u32 = 0x00000000; +const END_TAG: u32 = 0x00000000; + +pub unsafe fn get_board_revisioin() -> u32 { + let mut mailbox: [u32; 32] = [0; 32]; + let idx_offset:usize = (0x10 - mailbox.as_ptr() as u32 & 0xf) as usize; + + + mailbox[0 + idx_offset] = 7 * 4; + mailbox[1 + idx_offset] = REQUEST_CODE; + mailbox[2 + idx_offset] = GET_BOARD_REVISION; + mailbox[3 + idx_offset] = 4; + mailbox[4 + idx_offset] = TAG_REQUEST_CODE; + mailbox[5 + idx_offset] = 0; + mailbox[6 + idx_offset] = END_TAG; + + + mailbox_call(&mut mailbox[idx_offset..(idx_offset + 7)]); + + mailbox[5] +} + +// Get ARM memory base address and size using mailbox +const GET_ARM_MEMORY: u32 = 0x00010005; +pub unsafe fn get_arm_memory() -> (u32, u32) { + let mut mailbox: [u32; 32] = [0; 32]; + let idx_offset:usize = (0x10 - mailbox.as_ptr() as u32 & 0xf) as usize; + + mailbox[0 + idx_offset] = 8 * 4; + mailbox[1 + idx_offset] = REQUEST_CODE; + mailbox[2 + idx_offset] = GET_ARM_MEMORY; + mailbox[3 + idx_offset] = 8; + mailbox[4 + idx_offset] = TAG_REQUEST_CODE; + mailbox[5 + idx_offset] = 0; + mailbox[6 + idx_offset] = 0; + mailbox[7 + idx_offset] = END_TAG; + + mailbox_call(&mut mailbox[idx_offset..(idx_offset + 8)]); + + (mailbox[5], mailbox[6]) +} diff --git a/driver/src/uart.rs b/driver/src/uart.rs new file mode 100644 index 000000000..e38add2f9 --- /dev/null +++ b/driver/src/uart.rs @@ -0,0 +1,195 @@ + +use core::arch::asm; +use core::{ + ptr::{read_volatile, write_volatile}, + usize, +}; + + +const AUXENB: u32 = 0x3F215004; +const AUX_MU_CNTL_REG: u32 = 0x3F215060; +const AUX_MU_IER_REG: u32 = 0x3F215044; +const AUX_MU_LCR_REG: u32 = 0x3F21504C; +const AUX_MU_MCR_REG: u32 = 0x3F215050; +const AUX_MU_BAUD_REG: u32 = 0x3F215068; +const AUX_MU_IIR_REG: u32 = 0x3F215048; +const AUX_MU_IO_REG: u32 = 0x3F215040; +const AUX_MU_LSR_REG: u32 = 0x3F215054; + +const GPFSEL_BASE: u32 = 0x3F200000; +const GPFSEL0: u32 = 0x3F200000; +const GPFSEL1: u32 = 0x3F200004; + +const GPPUD: u32 = 0x3F200094; +const GPPUDCLK0: u32 = 0x3F200098; +const GPPUDCLK1: u32 = 0x3F20009C; + +// Initialize the UART +#[no_mangle] +#[inline(never)] +pub fn init_uart() { + unsafe { + // configure GPFSEL1 register to set FSEL14 FSEL15 to ALT5 + let fsel = read_volatile(GPFSEL1 as *mut u32); + let fsel_mask = !(0b111111 << 12); + let fsel_set = 0b010010 << 12; + write_volatile(GPFSEL1 as *mut u32, (fsel & fsel_mask) | fsel_set); + + // configure pull up/down register to disable GPIO pull up/down + let pud = 0b0; + write_volatile(GPPUD as *mut u32, pud); + + // wait 150 cycles + uart_nops(); + + // configure pull up/down clock register to disable GPIO pull up/down + let pudclk0 = !(0b11 << 14); + write_volatile(GPPUDCLK0 as *mut u32, pudclk0); + let pudclk1 = 0; + write_volatile(GPPUDCLK1 as *mut u32, pudclk1); + // wait 150 cycles + uart_nops(); + + // Write to GPPUD to remove the control signal + write_volatile(GPPUD as *mut u32, 0); + // Write to GPPUDCLK0 to remove the clock + write_volatile(GPPUDCLK0 as *mut u32, 0); + + // write some word to uart to initialize it + // Set AUXENB register to enable mini UART + write_volatile(AUXENB as *mut u32, 1); + + // Set AUX_MU_CNTL_REG to 0 + write_volatile(AUX_MU_CNTL_REG as *mut u32, 0); + // Set AUX_MU_IER_REG to 0 + write_volatile(AUX_MU_IER_REG as *mut u32, 0); + // Set AUX_MU_LCR_REG to 3 + write_volatile(AUX_MU_LCR_REG as *mut u32, 3); + // Set AUX_MU_MCR_REG to 0 + write_volatile(AUX_MU_MCR_REG as *mut u32, 0); + // Set AUX_MU_BAUD_REG to 270 + write_volatile(AUX_MU_BAUD_REG as *mut u32, 270); + // Set AUX_MU_IIR_REG to 6 + write_volatile(AUX_MU_IIR_REG as *mut u32, 6); + // Set AUX_MU_CNTL_REG to 3 + write_volatile(AUX_MU_CNTL_REG as *mut u32, 3); + } +} + +#[no_mangle] +#[inline(never)] +pub unsafe fn _print(s: &str) { + for i in s.bytes() { + write_u8(i); + } +} + +#[no_mangle] +pub unsafe fn strcmp(s1: &[u8; 128], l1: usize, s2: &[u8; 128], l2: usize) -> bool { + if l1 != l2 { + return false; + } + let mut idx: usize = 0; + while idx < l1 { + if s1[idx] != s2[idx] { + return false; + } + idx = idx + 1; + } + true +} + +#[no_mangle] +pub unsafe fn get_line(s: &mut [u8; 128], is_echo: bool) -> usize { + let mut ptr: usize = 0; + loop { + let c = read_u8(); + match c { + Some(i) => { + if is_echo { + write_u8(i as u8); + } + if i == 13 { + write_u8(10); + break; + } + s[ptr] = i as u8; + ptr = ptr + 1; + } + None => {} + } + asm!("nop"); + } + ptr +} + +#[no_mangle] +pub unsafe fn uart_nops() { + for _ in 0..150 { + asm!("nop"); + } +} + +// Function to print something using the UART +#[no_mangle] +pub unsafe fn write_u8(s: u8) { + loop { + if (read_volatile(AUX_MU_LSR_REG as *mut u32) & 0b100000) != 0 { + break; + } + } + write_volatile(AUX_MU_IO_REG as *mut u8, s as u8); +} + +#[no_mangle] +pub unsafe fn read_u8() -> Option { + let lsr: u32 = read_volatile(AUX_MU_LSR_REG as *mut u32) & 0b1; + if lsr != 0 { + Some(read_volatile(AUX_MU_IO_REG as *mut u8)) + } else { + None + } +} + +pub unsafe fn read(s: *mut u8, len: usize) { + let mut ptr: usize = 0; + while ptr < len { + let c = read_u8(); + match c { + Some(i) => { + write_volatile(s.add(ptr), i as u8); + ptr = ptr + 1; + } + None => {} + } + } +} + +// print u32 in hex +#[no_mangle] +pub unsafe fn print_hex(n: u32) { + let mut buf: [u8; 8] = [0; 8]; + let mut ptr: usize = 0; + let mut num: u32 = n; + for _ in 0..8 { + let rem: u8 = (num % 16) as u8; + if rem < 10 { + buf[ptr] = (rem + b'0') as u8; + } else { + buf[ptr] = (rem - 10 + b'A') as u8; + } + ptr = ptr + 1; + num = num / 16; + } + for i in buf.iter().take(8).rev() { + write_u8(*i); + } +} + + +// println +#[no_mangle] +pub unsafe fn println(s: &str) { + _print(s); + _print("\n\r"); +} From 8ef4c75dcd35777cdfac5163c35848522871a33e Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Mon, 25 Mar 2024 14:29:04 +0800 Subject: [PATCH 05/34] bootloader ok, KAF still cute --- .gdbinit | 4 ++ .gitignore | 3 +- Makefile | 35 +++++++++++++--- bootloader/Makefile | 2 +- bootloader/src/_arch/aarch64/cpu/boot.rs | 5 ++- bootloader/src/_arch/aarch64/cpu/boot.s | 12 +++--- bootloader/src/bsp/raspberrypi/bootloader.ld | 20 ++++----- bootloader/src/main.rs | 5 +-- initramfs.cpio | Bin 0 -> 1024 bytes kernel_sender.py | 42 +++++++++++++++++++ 10 files changed, 98 insertions(+), 30 deletions(-) create mode 100644 .gdbinit create mode 100644 initramfs.cpio create mode 100644 kernel_sender.py diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 000000000..c70dd37ff --- /dev/null +++ b/.gdbinit @@ -0,0 +1,4 @@ +file target/aarch64-unknown-none-softfloat/release/bootloader +target remote :1234 +layout asm +layout regs \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2236371cb..b2cbaeae3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ target */target -kernel8.img +*.img .vscode +rootfs \ No newline at end of file diff --git a/Makefile b/Makefile index 2dac5dd9e..ddd6c4643 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,17 @@ BSP = rpi3 TARGET = aarch64-unknown-none-softfloat + KERNEL_BIN = kernel8.img +BOOTLOADER_BIN = bootloader.img + # QEMU QEMU_BINARY = qemu-system-aarch64 QEMU_MACHINE_TYPE = raspi3b QEMU_RELEASE_ARGS = -display none -serial null -serial stdio QEMU_DEBUG_ARGS = -display none -S -s -serial null -serial stdio +QEMU_TTY_ARGS = -display none -serial null -serial pty +QEMU_TTY_DEBUG_ARGS = -display none -S -s -serial null -serial pty EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE) OBJDUMP_BINARY = aarch64-none-elf-objdump @@ -14,9 +19,8 @@ NM_BINARY = aarch64-none-elf-mn READELF_BINARY = aarch64-none-elf-readelf RUSTC_MISC_ARGS = -C target-cpu=cortex-a53 - - KERNEL_PATH = $(shell pwd)/kernel +BOOTLOADER_PATH = $(shell pwd)/bootloader KERNEL_ELF = target/$(TARGET)/release/kernel BOOTLOADER_ELF = target/$(TARGET)/release/bootloader @@ -27,7 +31,7 @@ OBJCOPY_CMD = rust-objcopy \ .PHONY: all doc qemu clippy clean readelf objdump nm check -all: $(KERNEL_BIN) +all: $(KERNEL_BIN) $(BOOTLOADER_BIN) $(KERNEL_BIN): kernel_elf $(call color_header, "Generating stripped binary") @@ -37,18 +41,39 @@ $(KERNEL_BIN): kernel_elf $(call color_progress_prefix, "Size") $(call disk_usage_KiB, $(KERNEL_BIN)) +$(BOOTLOADER_BIN): bootloader_elf + $(call color_header, "Generating stripped binary") + @$(OBJCOPY_CMD) $(BOOTLOADER_ELF) $(BOOTLOADER_BIN) + $(call color_progress_prefix, "Name") + @echo $(BOOTLOADER_BIN) + $(call color_progress_prefix, "Size") + $(call disk_usage_KiB, $(BOOTLOADER_BIN)) + kernel_elf: make -C $(KERNEL_PATH) all -qemu: $(KERNEL_BIN) +bootloader_elf: + make -C $(BOOTLOADER_PATH) all + +kernel_qemu: $(KERNEL_BIN) $(call color_header, "Launching QEMU") $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) -gdb: $(KERNEL_BIN) +kernel_gdb: $(KERNEL_BIN) $(call color_header, "Launching QEMU in background") $(EXEC_QEMU) $(QEMU_DEBUG_ARGS) -kernel $(KERNEL_BIN) +bootloader_qemu: $(BOOTLOADER_BIN) + $(call color_header, "Launching QEMU") + $(EXEC_QEMU) $(QEMU_TTY_ARGS) -device loader,file=$(BOOTLOADER_BIN),addr=0x60000,cpu-num=0 + +bootloader_gdb: $(BOOTLOADER_BIN) + $(call color_header, "Launching QEMU in background") + $(EXEC_QEMU) $(QEMU_TTY_DEBUG_ARGS) -device loader,file=$(BOOTLOADER_BIN),addr=0x60000,cpu-num=0 + clean: + make -C $(KERNEL_PATH) clean make -C $(KERNEL_PATH) clean -rm -r target -rm $(KERNEL_BIN) + -rm $(BOOTLOADER_BIN) diff --git a/bootloader/Makefile b/bootloader/Makefile index 79842a74a..b85fa988f 100644 --- a/bootloader/Makefile +++ b/bootloader/Makefile @@ -42,7 +42,7 @@ COMPILER_ARGS = --target=$(TARGET) \ $(FEATURES) \ --release -RUSTC_CMD = cargo rustc $(COMPILER_ARGS) --bin kernel +RUSTC_CMD = cargo rustc $(COMPILER_ARGS) --bin bootloader CLIPPY_CMD = cargo clippy $(COMPILER_ARGS) diff --git a/bootloader/src/_arch/aarch64/cpu/boot.rs b/bootloader/src/_arch/aarch64/cpu/boot.rs index 058c5e2d8..76a8b1253 100644 --- a/bootloader/src/_arch/aarch64/cpu/boot.rs +++ b/bootloader/src/_arch/aarch64/cpu/boot.rs @@ -2,6 +2,8 @@ use core::arch::global_asm; use core::arch::asm; +use driver::uart; + global_asm!( include_str!("boot.s") , CONST_CORE_ID_MASK = const 0b11 @@ -11,5 +13,6 @@ global_asm!( #[no_mangle] pub unsafe fn _start_rust(){ - crate::bootloader() + crate::bootloader(); + uart::_print("Bootloader finished\r\n"); } diff --git a/bootloader/src/_arch/aarch64/cpu/boot.s b/bootloader/src/_arch/aarch64/cpu/boot.s index e08bbbfd5..fde403418 100644 --- a/bootloader/src/_arch/aarch64/cpu/boot.s +++ b/bootloader/src/_arch/aarch64/cpu/boot.s @@ -13,9 +13,6 @@ // fn _start() //------------------------------------------------------------------------------ _start: - b _bootloader - -_bootloader: // Only proceed on the boot core. Park it otherwise. mrs x0, MPIDR_EL1 and x0, x0, {CONST_CORE_ID_MASK} @@ -39,13 +36,14 @@ _bootloader: // Prepare the jump to Rust code. .L_prepare_rust: // Set the stack pointer. - mov sp, 0x80000 + mov sp, 0x60000 // Jump to Rust code. bl _start_rust - - // After loaded the kernel jump to _start aka 0x80000 - b _start + + // jump to 0x80000 + ldr x0, =0x80000 + br x0 // Infinitely wait for events (aka "park the core"). .L_parking_loop: diff --git a/bootloader/src/bsp/raspberrypi/bootloader.ld b/bootloader/src/bsp/raspberrypi/bootloader.ld index 66b9d4b11..251bf33c6 100644 --- a/bootloader/src/bsp/raspberrypi/bootloader.ld +++ b/bootloader/src/bsp/raspberrypi/bootloader.ld @@ -1,26 +1,22 @@ + __rpi_phys_dram_start_addr = 0; -__rpi_bootloader_addr = 0x60000; -__rpi_phys_binary_load_addr = 0x80000; + +__rpi_phys_binary_load_addr = 0x60000; + ENTRY(__rpi_phys_binary_load_addr) SECTIONS { - . = __rpi_bootloader_addr + . = __rpi_phys_binary_load_addr; .text : { - KEEP(*(.text._bootloader)) - *(.text._bootloader_arguments) /* Constants (or statics in Rust speak) read by _start(). */ + KEEP(*(.text._start)) + *(.text._start_arguments) /* Constants (or statics in Rust speak) read by _start(). */ *(.text._start_rust) /* The Rust entry point */ *(.text*) /* Everything else */ } :segment_code - - . = __rpi_phys_binary_load_addr; - .text : - { - KEEP(*(.text._start)) - } .rodata : ALIGN(8) { *(.rodata*) } :segment_code @@ -36,4 +32,4 @@ SECTIONS __bss_end_exclusive = .; } -} +} \ No newline at end of file diff --git a/bootloader/src/main.rs b/bootloader/src/main.rs index 17871c4aa..83c8a47f2 100644 --- a/bootloader/src/main.rs +++ b/bootloader/src/main.rs @@ -13,18 +13,17 @@ use core::{ }; use driver::uart; -use driver::mailbox; const KERNEL_LOAD_ADDR: u64 = 0x80000; // load the kernel from uart #[no_mangle] -unsafe fn bootloader() -> ! { +unsafe fn bootloader(){ // initialize uart uart::init_uart(); uart::_print("Bootloader started\r\n"); - + // read kernel size let mut kernel_size: u32 = 0; diff --git a/initramfs.cpio b/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..0081bb7d2b163c0ac240cafb79f40610abceb4a8 GIT binary patch literal 1024 zcmeH@-422v6vufKd;xbbQ@lij&DE9j1zfY`a%(GR_4WaRA9HDU-NYE@a6b6`IS@h! z1k@IcgIqr0J7rBItfK>&nAUZms0(bdWP5Sn;>+(nXRc#^nPRg^GaSI>FG@VY#J z<*xApOFz2Jvq34YuWgAF7oia!L@XtI!KaBZ@9Fud7IW|aW$xB6>zt~(Bw9m$uI^aw zE;7|25>>xC2g=RAh}NxI4Cj*$n} Date: Mon, 25 Mar 2024 14:29:59 +0800 Subject: [PATCH 06/34] bootloader ok, KAF still cute --- .gitignore | 3 ++- initramfs.cpio | Bin 1024 -> 0 bytes 2 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 initramfs.cpio diff --git a/.gitignore b/.gitignore index b2cbaeae3..99351c370 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ target */target *.img .vscode -rootfs \ No newline at end of file +rootfs +.gdbinit \ No newline at end of file diff --git a/initramfs.cpio b/initramfs.cpio deleted file mode 100644 index 0081bb7d2b163c0ac240cafb79f40610abceb4a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmeH@-422v6vufKd;xbbQ@lij&DE9j1zfY`a%(GR_4WaRA9HDU-NYE@a6b6`IS@h! z1k@IcgIqr0J7rBItfK>&nAUZms0(bdWP5Sn;>+(nXRc#^nPRg^GaSI>FG@VY#J z<*xApOFz2Jvq34YuWgAF7oia!L@XtI!KaBZ@9Fud7IW|aW$xB6>zt~(Bw9m$uI^aw zE;7|25>>xC2g=RAh}NxI4Cj*$n} Date: Mon, 25 Mar 2024 14:34:18 +0800 Subject: [PATCH 07/34] utils --- kernel_sender.py => utils/kernel_sender.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename kernel_sender.py => utils/kernel_sender.py (100%) diff --git a/kernel_sender.py b/utils/kernel_sender.py similarity index 100% rename from kernel_sender.py rename to utils/kernel_sender.py From 0b78b5c45d572324f004dba908f1e14c2b94238e Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Mon, 25 Mar 2024 14:35:47 +0800 Subject: [PATCH 08/34] clean --- .gdbinit | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .gdbinit diff --git a/.gdbinit b/.gdbinit deleted file mode 100644 index c70dd37ff..000000000 --- a/.gdbinit +++ /dev/null @@ -1,4 +0,0 @@ -file target/aarch64-unknown-none-softfloat/release/bootloader -target remote :1234 -layout asm -layout regs \ No newline at end of file From b95fc31fef6c97d27b64d50c065b5955b08c0556 Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Thu, 28 Mar 2024 17:05:15 +0800 Subject: [PATCH 09/34] Fix: Relo, cpio --- Makefile | 13 +- bootloader/src/_arch/aarch64/cpu/boot.s | 26 +++- bootloader/src/_arch/aarch64/cpu/boot_bak.s | 55 ++++++++ bootloader/src/bsp/raspberrypi/bootloader.ld | 10 +- bootloader/src/main.rs | 8 ++ driver/src/cpio.rs | 135 +++++++++++++++++++ driver/src/devicetree.rs | 8 ++ driver/src/lib.rs | 3 +- driver/src/uart.rs | 53 +++----- initramfs.cpio | Bin 0 -> 1024 bytes kernel/src/allocator/memory.rs | 31 +++++ kernel/src/allocator/mod.rs | 34 +++++ kernel/src/bsp/raspberrypi/kernel.ld | 2 - kernel/src/main.rs | 74 +++++++--- kernel/src/print.rs | 3 + 15 files changed, 391 insertions(+), 64 deletions(-) create mode 100644 bootloader/src/_arch/aarch64/cpu/boot_bak.s create mode 100644 driver/src/cpio.rs create mode 100644 driver/src/devicetree.rs create mode 100644 initramfs.cpio create mode 100644 kernel/src/allocator/memory.rs create mode 100644 kernel/src/allocator/mod.rs create mode 100644 kernel/src/print.rs diff --git a/Makefile b/Makefile index ddd6c4643..dd9c37f59 100644 --- a/Makefile +++ b/Makefile @@ -63,13 +63,22 @@ kernel_gdb: $(KERNEL_BIN) $(call color_header, "Launching QEMU in background") $(EXEC_QEMU) $(QEMU_DEBUG_ARGS) -kernel $(KERNEL_BIN) +kernel_initramfs_qemu: $(KERNEL_BIN) + $(call color_header, "Launching QEMU") + $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) -initrd initramfs.cpio + bootloader_qemu: $(BOOTLOADER_BIN) $(call color_header, "Launching QEMU") - $(EXEC_QEMU) $(QEMU_TTY_ARGS) -device loader,file=$(BOOTLOADER_BIN),addr=0x60000,cpu-num=0 + $(EXEC_QEMU) $(QEMU_TTY_ARGS) -kernel $(BOOTLOADER_BIN) + +# -device loader,file=$(BOOTLOADER_BIN),addr=0x60000,cpu-num=0 bootloader_gdb: $(BOOTLOADER_BIN) $(call color_header, "Launching QEMU in background") - $(EXEC_QEMU) $(QEMU_TTY_DEBUG_ARGS) -device loader,file=$(BOOTLOADER_BIN),addr=0x60000,cpu-num=0 + $(EXEC_QEMU) $(QEMU_TTY_DEBUG_ARGS) -kernel $(BOOTLOADER_BIN) + +# -device loader,file=$(BOOTLOADER_BIN),addr=0x60000,cpu-num=0 + clean: make -C $(KERNEL_PATH) clean diff --git a/bootloader/src/_arch/aarch64/cpu/boot.s b/bootloader/src/_arch/aarch64/cpu/boot.s index fde403418..aacb4a4ab 100644 --- a/bootloader/src/_arch/aarch64/cpu/boot.s +++ b/bootloader/src/_arch/aarch64/cpu/boot.s @@ -20,18 +20,38 @@ _start: cmp x0, x1 b.ne .L_parking_loop - // If execution reaches here, it is the boot core. + // get addresses + ldr x0, =0x60000 + ADR_REL x1, __relo_start + ADR_REL x2, __relo_end +.L_relo_loop: + cmp x1, x2 + b.eq .L_relo_end + // load data from x1 + ldr x3, [x1] + // store into [x0] + str x3, [x0] + // move to next address + add x1, x1, #8 + add x0, x0, #8 + b .L_relo_loop + +.L_relo_end: + ldr x0, =.L_no_relo + br x0 + +.L_no_relo: // Initialize DRAM. ADR_REL x0, __bss_start ADR_REL x1, __bss_end_exclusive .L_bss_init_loop: cmp x0, x1 - b.eq .L_prepare_rust + b.eq .L_prepare_rust stp xzr, xzr, [x0], #16 b .L_bss_init_loop - + // Prepare the jump to Rust code. .L_prepare_rust: diff --git a/bootloader/src/_arch/aarch64/cpu/boot_bak.s b/bootloader/src/_arch/aarch64/cpu/boot_bak.s new file mode 100644 index 000000000..453dcd1f5 --- /dev/null +++ b/bootloader/src/_arch/aarch64/cpu/boot_bak.s @@ -0,0 +1,55 @@ + +.macro ADR_REL register, symbol + adrp \register, \symbol + add \register, \register, #:lo12:\symbol +.endm + +//-------------------------------------------------------------------------------------------------- +// Public Code +//-------------------------------------------------------------------------------------------------- +.section .text._start + +//------------------------------------------------------------------------------ +// fn _start() +//------------------------------------------------------------------------------ +_start: + // Only proceed on the boot core. Park it otherwise. + mrs x0, MPIDR_EL1 + and x0, x0, {CONST_CORE_ID_MASK} + ldr x1, BOOT_CORE_ID // provided by bsp/__board_name__/cpu.rs + cmp x0, x1 + b.ne .L_parking_loop + + // If execution reaches here, it is the boot core. + + // Initialize DRAM. + ADR_REL x0, __bss_start + ADR_REL x1, __bss_end_exclusive + +.L_bss_init_loop: + cmp x0, x1 + b.eq .L_prepare_rust + stp xzr, xzr, [x0], #16 + b .L_bss_init_loop + + + // Prepare the jump to Rust code. +.L_prepare_rust: + // Set the stack pointer. + mov sp, 0x60000 + + // Jump to Rust code. + bl _start_rust + + // jump to 0x80000 + ldr x0, =0x80000 + br x0 + + // Infinitely wait for events (aka "park the core"). +.L_parking_loop: + wfe + b .L_parking_loop + +.size _start, . - _start +.type _start, function +.global _start diff --git a/bootloader/src/bsp/raspberrypi/bootloader.ld b/bootloader/src/bsp/raspberrypi/bootloader.ld index 251bf33c6..d7b3db174 100644 --- a/bootloader/src/bsp/raspberrypi/bootloader.ld +++ b/bootloader/src/bsp/raspberrypi/bootloader.ld @@ -10,6 +10,7 @@ ENTRY(__rpi_phys_binary_load_addr) SECTIONS { . = __rpi_phys_binary_load_addr; + __relo_start = .; .text : { KEEP(*(.text._start)) @@ -17,10 +18,11 @@ SECTIONS *(.text._start_rust) /* The Rust entry point */ *(.text*) /* Everything else */ } :segment_code - - .rodata : ALIGN(8) { *(.rodata*) } :segment_code - - .data : { *(.data*) } + + .rodata : ALIGN(16) { *(.rodata*) } :segment_code + .data : ALIGN(16) { *(.data*) } + . = ALIGN(16); + __relo_end = .; /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */ diff --git a/bootloader/src/main.rs b/bootloader/src/main.rs index 83c8a47f2..36fdb8c3d 100644 --- a/bootloader/src/main.rs +++ b/bootloader/src/main.rs @@ -24,6 +24,14 @@ unsafe fn bootloader(){ uart::init_uart(); uart::_print("Bootloader started\r\n"); + // print current pc value + let mut pc: u64; + core::arch::asm!("adr {}, .", out(reg) pc); + uart::_print("Current PC: "); + uart::print_hex(pc as u32); + uart::_print("\r\n"); + + // read kernel size let mut kernel_size: u32 = 0; diff --git a/driver/src/cpio.rs b/driver/src/cpio.rs new file mode 100644 index 000000000..53722336e --- /dev/null +++ b/driver/src/cpio.rs @@ -0,0 +1,135 @@ +// a paraser to read cpio archive +#[repr(C, packed)] +struct CpioNewcHeader { + c_magic: [u8; 6], + c_ino: [u8; 8], + c_mode: [u8; 8], + c_uid: [u8; 8], + c_gid: [u8; 8], + c_nlink: [u8; 8], + c_mtime: [u8; 8], + c_filesize: [u8; 8], + c_devmajor: [u8; 8], + c_devminor: [u8; 8], + c_rdevmajor: [u8; 8], + c_rdevminor: [u8; 8], + c_namesize: [u8; 8], + c_check: [u8; 8], +} + +pub struct CpioHandler { + cpio_start: *mut CpioNewcHeader, + cpio_cur_pos: *mut CpioNewcHeader, +} + +impl CpioHandler { + // parse cpio in memory, with the start address of cpio + + pub fn new(cpio_start: *mut u8) -> CpioHandler { + CpioHandler { + cpio_start: cpio_start as *mut CpioNewcHeader, + cpio_cur_pos: cpio_start as *mut CpioNewcHeader, + } + } + + fn get_current_file_header(&self) -> &CpioNewcHeader { + unsafe { &*self.cpio_cur_pos } + } + + pub fn is_end(&self) -> bool { + let cur_header = self.get_current_file_header(); + let magic_slice = &cur_header.c_magic; + let magic = core::str::from_utf8(magic_slice).unwrap(); + magic == "TRAILER!!" + } + + pub fn get_current_file_name_len(&self) -> Option { + if !self.is_end() { + let cur_header = self.get_current_file_header(); + let namesize = hex_to_u64(&cur_header.c_namesize); + Some(namesize as usize) + } else { + None + } + } + + pub fn get_current_file_size(&self) -> Option { + if !self.is_end() { + let cur_header = self.get_current_file_header(); + let filesize = hex_to_u64(&cur_header.c_filesize); + Some(filesize as usize) + } else { + None + } + } + + pub fn get_current_header_magic(&self) -> &str { + let cur_header = self.get_current_file_header(); + let magic_slice = &cur_header.c_magic; + core::str::from_utf8(magic_slice).unwrap() + } + + pub fn get_current_file_name(&self) -> &str { + let cur_header = self.get_current_file_header(); + let namesize = hex_to_u64(&cur_header.c_namesize); + let cur_pos = self.cpio_cur_pos as *mut u8; + let name_ptr = (cur_pos as u64 + core::mem::size_of::() as u64) as *mut u8; + unsafe { + let name_slice = &core::slice::from_raw_parts(name_ptr, namesize as usize); + core::str::from_utf8(name_slice).unwrap() + } + } + + pub fn read_current_file(&self) -> &[u8] { + let cur_header = self.get_current_file_header(); + let filesize = hex_to_u64(&cur_header.c_filesize); + let cur_pos = self.cpio_cur_pos as *mut u8; + let name_size = hex_to_u64(&cur_header.c_namesize); + let mut offset = core::mem::size_of::() as u64 + name_size + cur_pos as u64; + if offset % 4 != 0 { + offset += 4 - offset % 4; + } + let file_ptr = offset as *mut u8; + unsafe { core::slice::from_raw_parts(file_ptr, filesize as usize) } + } + + pub fn next_file(&mut self) { + let mut cur_pos = self.cpio_cur_pos as *mut u8; + let cur_header = self.get_current_file_header(); + let mut offset = core::mem::size_of::() as u64; + let namesize = hex_to_u64(&cur_header.c_namesize); + offset += namesize; + if offset % 4 != 0 { + offset += 4 - offset % 4; + } + let filesize = hex_to_u64(&cur_header.c_filesize); + offset += filesize; + if offset % 4 != 0 { + offset += 4 - offset % 4; + } + cur_pos = (cur_pos as u64 + offset) as *mut u8; + self.cpio_cur_pos = cur_pos as *mut CpioNewcHeader; + } + + pub fn rewind(&mut self) { + self.cpio_cur_pos = self.cpio_start; + } +} + +fn hex_to_u64(hex: &[u8; 8]) -> u64 { + let mut result: u64 = 0; + for i in 0..8 { + result = result << 4; + let c = hex[i]; + if c >= b'0' && c <= b'9' { + result += (c - b'0') as u64; + } else if c >= b'a' && c <= b'f' { + result += (c - b'a' + 10) as u64; + } else if c >= b'A' && c <= b'F' { + result += (c - b'A' + 10) as u64; + } else { + break; + } + } + result +} diff --git a/driver/src/devicetree.rs b/driver/src/devicetree.rs new file mode 100644 index 000000000..16881efe1 --- /dev/null +++ b/driver/src/devicetree.rs @@ -0,0 +1,8 @@ +// A parser parse device tree + +struct + DeviceTreeParser +{ + buffer: *const u8, + cur_pos: *const u8, +} \ No newline at end of file diff --git a/driver/src/lib.rs b/driver/src/lib.rs index 6bf9030bd..dd1a1491e 100644 --- a/driver/src/lib.rs +++ b/driver/src/lib.rs @@ -1,4 +1,5 @@ #![allow(dead_code)] #![no_std] pub mod uart; -pub mod mailbox; \ No newline at end of file +pub mod mailbox; +pub mod cpio; \ No newline at end of file diff --git a/driver/src/uart.rs b/driver/src/uart.rs index e38add2f9..6df17f771 100644 --- a/driver/src/uart.rs +++ b/driver/src/uart.rs @@ -1,4 +1,6 @@ + + use core::arch::asm; use core::{ ptr::{read_volatile, write_volatile}, @@ -85,42 +87,30 @@ pub unsafe fn _print(s: &str) { } #[no_mangle] -pub unsafe fn strcmp(s1: &[u8; 128], l1: usize, s2: &[u8; 128], l2: usize) -> bool { - if l1 != l2 { - return false; - } - let mut idx: usize = 0; - while idx < l1 { - if s1[idx] != s2[idx] { - return false; - } - idx = idx + 1; - } - true -} - -#[no_mangle] -pub unsafe fn get_line(s: &mut [u8; 128], is_echo: bool) -> usize { +pub fn getline(s: &mut [u8; 128], is_echo: bool) -> &str { let mut ptr: usize = 0; - loop { - let c = read_u8(); - match c { - Some(i) => { - if is_echo { - write_u8(i as u8); + unsafe{ + loop { + let c = read_u8(); + match c { + Some(i) => { + if is_echo { + write_u8(i as u8); + } + if i == 13 { + write_u8(10); + break; + } + s[ptr] = i as u8; + ptr = ptr + 1; } - if i == 13 { - write_u8(10); - break; - } - s[ptr] = i as u8; - ptr = ptr + 1; + None => {} } - None => {} + asm!("nop"); } - asm!("nop"); + } - ptr + core::str::from_utf8(&s[0..ptr]).unwrap() } #[no_mangle] @@ -151,6 +141,7 @@ pub unsafe fn read_u8() -> Option { } } + pub unsafe fn read(s: *mut u8, len: usize) { let mut ptr: usize = 0; while ptr < len { diff --git a/initramfs.cpio b/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..7be26ca8ad04ee137d3ee496d30b4de878df7a34 GIT binary patch literal 1024 zcmc&yK~BRk5cE@$4@7IXanhrk+Ngq4)el5fN-ZiOfmPrMT;UH$aNxk7P}@hG+o~ z5z{&<=W6Vuf8ue(<9s5Tdw@yEI)o=f9IO&|@7O%rUhk@?NEkc92Qx(qf56WR6Y_a| z>L=mc{wtixDB7&;w&I?{a$|2JoQc(K542n^?b;Qk>(qj0GhgE&4Rorh2GoO;moy>i$x Self { + Self { + heap_start, + current: heap_start, + heap_size, + } + } +} + + +pub fn alloc(layout: Layout, memory: &mut HeapMemory) -> *mut u8 { + let size = layout.size(); + let align = layout.align(); + let new_current = (memory.current + align - 1) & !(align - 1); + if new_current + size > memory.heap_start + memory.heap_size { + return core::ptr::null_mut(); + } + memory.current = new_current + size; + new_current as *mut u8 +} diff --git a/kernel/src/allocator/mod.rs b/kernel/src/allocator/mod.rs new file mode 100644 index 000000000..cf4b85af4 --- /dev/null +++ b/kernel/src/allocator/mod.rs @@ -0,0 +1,34 @@ +const HEAP_SIZE: usize = 1024 * 1024; // 1 MB +const HEAP_START: usize = 0x60000; + +use core::cell::UnsafeCell; + +mod memory; + +use core::alloc::{GlobalAlloc, Layout}; +pub struct MyAllocator { + memory: UnsafeCell, +} + +impl MyAllocator { + pub const fn new() -> Self { + Self { + memory: UnsafeCell::new(memory::HeapMemory::new(HEAP_START, HEAP_SIZE)), + } + } + unsafe fn memory(&self) -> &mut memory::HeapMemory { + &mut *self.memory.get() + } +} + +unsafe impl Sync for MyAllocator {} + +unsafe impl GlobalAlloc for MyAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + memory::alloc(layout, self.memory()) + } + + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) { + // Implementation for dealloc + } +} diff --git a/kernel/src/bsp/raspberrypi/kernel.ld b/kernel/src/bsp/raspberrypi/kernel.ld index 360d2a863..7ac946b52 100644 --- a/kernel/src/bsp/raspberrypi/kernel.ld +++ b/kernel/src/bsp/raspberrypi/kernel.ld @@ -3,7 +3,6 @@ __rpi_phys_dram_start_addr = 0; __rpi_phys_binary_load_addr = 0x80000; - ENTRY(__rpi_phys_binary_load_addr) @@ -22,7 +21,6 @@ SECTIONS .data : { *(.data*) } - /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */ .bss (NOLOAD): ALIGN(16) { diff --git a/kernel/src/main.rs b/kernel/src/main.rs index c27cd6a96..3e0805d8c 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -1,22 +1,35 @@ #![feature(asm_const)] #![no_main] #![no_std] +#![feature(default_alloc_error_handler)] mod bsp; mod cpu; mod panic_wait; +mod allocator; -use core::ptr::write_volatile; +extern crate alloc; -use driver::uart; +use core::ptr::write_volatile; +use driver::cpio::CpioHandler; use driver::mailbox; +use driver::uart; +use allocator::MyAllocator; + +const QEMU_INITRD_START: u64 = 0x8000000; + +#[global_allocator] +static mut ALLOCATOR: MyAllocator = MyAllocator::new(); #[no_mangle] unsafe fn kernel_init() -> ! { + uart::init_uart(); uart::_print("Revision: "); // get board revision let revision = mailbox::get_board_revisioin(); + let h = alloc::string::String::from("Hello"); + // print hex of revision uart::print_hex(revision); @@ -24,12 +37,11 @@ unsafe fn kernel_init() -> ! { // get ARM memory base address and size let (base, size) = mailbox::get_arm_memory(); - + // print ARM memory base address and size uart::_print("ARM memory base address: "); uart::print_hex(base); uart::_print("\r\n"); - uart::_print("ARM memory size: "); uart::print_hex(size); @@ -37,29 +49,17 @@ unsafe fn kernel_init() -> ! { let mut out_buf: [u8; 128] = [0; 128]; let mut in_buf: [u8; 128] = [0; 128]; - out_buf[0] = 62; - out_buf[1] = 62; - - let mut hello_str: [u8; 128] = [0; 128]; - hello_str[..5].copy_from_slice(b"hello"); - let hello_len = 5; - let mut reboot_str: [u8; 128] = [0; 128]; - reboot_str[..6].copy_from_slice(b"reboot"); - - let mut help_str: [u8; 128] = [0; 128]; - help_str[..4].copy_from_slice(b"help"); - let help_len = 4; + let mut handler: CpioHandler = CpioHandler::new(QEMU_INITRD_START as *mut u8); loop { uart::_print(">> "); - let in_buf_len = uart::get_line(&mut in_buf, true); - if uart::strcmp(&in_buf, in_buf_len, &hello_str, hello_len) { + let inp = uart::getline(&mut in_buf, true); + if inp == "Hello" { uart::_print("Hello World!\r\n"); - } else if uart::strcmp(&in_buf, in_buf_len, &help_str, help_len) { + } else if inp == "help" { uart::_print("help : print this help menu\r\nhello : print Hello World!\r\nreboot : reboot the device\r\n"); - } else if uart::strcmp(&in_buf, in_buf_len, &reboot_str, 6) { - + } else if inp == "reboot" { const PM_PASSWORD: u32 = 0x5a000000; const PM_RSTC: u32 = 0x3F10001c; const PM_WDOG: u32 = 0x3F100024; @@ -67,7 +67,39 @@ unsafe fn kernel_init() -> ! { write_volatile(PM_WDOG as *mut u32, PM_PASSWORD | 100); write_volatile(PM_RSTC as *mut u32, PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); break; + } else if inp == "ls" { + loop { + let name = handler.get_current_file_name(); + if name == "TRAILER!!!\0" { + break; + } + uart::_print(name); + uart::_print("\r\n"); + + handler.next_file(); + } + handler.rewind(); + } else if inp == "cat"{ + loop { + let name = handler.get_current_file_name(); + if name == "TRAILER!!!\0" { + break; + } + uart::_print("File: "); + uart::_print(name); + uart::_print("\r\n"); + let contant =handler.read_current_file(); + uart::_print(core::str::from_utf8(contant).unwrap()); + uart::_print("\r\n"); + handler.next_file(); + } + handler.rewind(); + } + + else { + uart::_print("Command not found\r\n"); } + uart::uart_nops(); } panic!() diff --git a/kernel/src/print.rs b/kernel/src/print.rs new file mode 100644 index 000000000..b28b04f64 --- /dev/null +++ b/kernel/src/print.rs @@ -0,0 +1,3 @@ + + + From e38b56569cbf9ec2f973608dc97c8991f442f8e8 Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Thu, 28 Mar 2024 20:13:53 +0800 Subject: [PATCH 10/34] README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50c5d4048..7df1525a4 100644 --- a/README.md +++ b/README.md @@ -35,5 +35,5 @@ make ## Test With QEMU ``` -make qemu +make kernel_qemu ``` From 372bc5df1c8753e66698e9deac8b1ff0f2851e68 Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Thu, 28 Mar 2024 20:16:14 +0800 Subject: [PATCH 11/34] rm --- initramfs.cpio | Bin 1024 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 initramfs.cpio diff --git a/initramfs.cpio b/initramfs.cpio deleted file mode 100644 index 7be26ca8ad04ee137d3ee496d30b4de878df7a34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmc&yK~BRk5cE@$4@7IXanhrk+Ngq4)el5fN-ZiOfmPrMT;UH$aNxk7P}@hG+o~ z5z{&<=W6Vuf8ue(<9s5Tdw@yEI)o=f9IO&|@7O%rUhk@?NEkc92Qx(qf56WR6Y_a| z>L=mc{wtixDB7&;w&I?{a$|2JoQc(K542n^?b;Qk>(qj0GhgE&4Rorh2GoO;moy>i$x Date: Thu, 28 Mar 2024 20:21:22 +0800 Subject: [PATCH 12/34] initramfs --- initramfs/KAF.txt | 1 + initramfs/c.txt | 1 + initramfs/catGift.txt | 1 + initramfs/file1.txt | 1 + 4 files changed, 4 insertions(+) create mode 100644 initramfs/KAF.txt create mode 100644 initramfs/c.txt create mode 100644 initramfs/catGift.txt create mode 100644 initramfs/file1.txt diff --git a/initramfs/KAF.txt b/initramfs/KAF.txt new file mode 100644 index 000000000..4a34cdad9 --- /dev/null +++ b/initramfs/KAF.txt @@ -0,0 +1 @@ +KAF is very kawaii \ No newline at end of file diff --git a/initramfs/c.txt b/initramfs/c.txt new file mode 100644 index 000000000..01e8bba17 --- /dev/null +++ b/initramfs/c.txt @@ -0,0 +1 @@ +I love C. \ No newline at end of file diff --git a/initramfs/catGift.txt b/initramfs/catGift.txt new file mode 100644 index 000000000..ebc99f8d7 --- /dev/null +++ b/initramfs/catGift.txt @@ -0,0 +1 @@ +貓咪禮物 \ No newline at end of file diff --git a/initramfs/file1.txt b/initramfs/file1.txt new file mode 100644 index 000000000..b062f1906 --- /dev/null +++ b/initramfs/file1.txt @@ -0,0 +1 @@ +This is file1. \ No newline at end of file From ef607aa1ce36bb58cc7381447c1f677c6031568d Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Thu, 28 Mar 2024 21:56:35 +0800 Subject: [PATCH 13/34] cat --- Makefile | 5 ++++- bcm2710-rpi-3-b-plus.dtb | Bin 0 -> 34228 bytes driver/src/devicetree.rs | 28 ++++++++++++++++++++++------ driver/src/uart.rs | 10 ++++++++++ kernel/src/main.rs | 24 +++++++++++++++++------- 5 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 bcm2710-rpi-3-b-plus.dtb diff --git a/Makefile b/Makefile index dd9c37f59..b26cbb322 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ kernel_gdb: $(KERNEL_BIN) $(call color_header, "Launching QEMU in background") $(EXEC_QEMU) $(QEMU_DEBUG_ARGS) -kernel $(KERNEL_BIN) -kernel_initramfs_qemu: $(KERNEL_BIN) +kernel_initramfs_qemu: $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU") $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) -initrd initramfs.cpio @@ -79,6 +79,9 @@ bootloader_gdb: $(BOOTLOADER_BIN) # -device loader,file=$(BOOTLOADER_BIN),addr=0x60000,cpu-num=0 +cpio: + $(call color_header, "Creating initramfs") + @cd initramfs && find . | cpio -H newc -o > ../initramfs.cpio clean: make -C $(KERNEL_PATH) clean diff --git a/bcm2710-rpi-3-b-plus.dtb b/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 0000000000000000000000000000000000000000..c83b0817e2eb5295a3dfe6aafe3aa55d93e9785d GIT binary patch literal 34228 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 bool { + let mut i = 0; + while i < n { + if s1.as_bytes()[i] != s2.as_bytes()[i] { + return false; + } + i = i + 1; + } + true +} // println #[no_mangle] diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 3e0805d8c..4722a36fe 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -79,18 +79,28 @@ unsafe fn kernel_init() -> ! { handler.next_file(); } handler.rewind(); - } else if inp == "cat"{ + } else if uart::strncmp(inp, "cat", 3){ + let target = &inp[4..]; loop { let name = handler.get_current_file_name(); if name == "TRAILER!!!\0" { break; } - uart::_print("File: "); - uart::_print(name); - uart::_print("\r\n"); - let contant =handler.read_current_file(); - uart::_print(core::str::from_utf8(contant).unwrap()); - uart::_print("\r\n"); + let l = name.len(); + // if last char is \0, remove it + let name = if name.as_bytes()[l-1] == 0 { + &name[..l-1] + } else { + name + }; + if name == target { + uart::_print("File: "); + uart::_print(name); + uart::_print("\r\n"); + let contant =handler.read_current_file(); + uart::_print(core::str::from_utf8(contant).unwrap()); + uart::_print("\r\n"); + } handler.next_file(); } handler.rewind(); From 9990018f3475efa60685d31e1c104ee5d7b0e537 Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Thu, 28 Mar 2024 21:57:55 +0800 Subject: [PATCH 14/34] rm --- bcm2710-rpi-3-b-plus.dtb | Bin 34228 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 bcm2710-rpi-3-b-plus.dtb diff --git a/bcm2710-rpi-3-b-plus.dtb b/bcm2710-rpi-3-b-plus.dtb deleted file mode 100644 index c83b0817e2eb5295a3dfe6aafe3aa55d93e9785d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34228 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 Date: Sat, 30 Mar 2024 01:03:50 +0800 Subject: [PATCH 15/34] println!("KAF is very kawaii.") --- bootloader/src/main.rs | 12 ++++++------ driver/src/uart.rs | 43 ++++++++++++++++++++++++++++++++++++++--- initramfs.cpio | Bin 0 -> 1024 bytes kernel/src/main.rs | 38 +++++++++++++++--------------------- kernel/src/print.rs | 26 +++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 31 deletions(-) create mode 100644 initramfs.cpio diff --git a/bootloader/src/main.rs b/bootloader/src/main.rs index 36fdb8c3d..23b2d9e70 100644 --- a/bootloader/src/main.rs +++ b/bootloader/src/main.rs @@ -22,14 +22,14 @@ const KERNEL_LOAD_ADDR: u64 = 0x80000; unsafe fn bootloader(){ // initialize uart uart::init_uart(); - uart::_print("Bootloader started\r\n"); + uart::uart_write_str("Bootloader started\r\n"); // print current pc value let mut pc: u64; core::arch::asm!("adr {}, .", out(reg) pc); - uart::_print("Current PC: "); + uart::uart_write_str("Current PC: "); uart::print_hex(pc as u32); - uart::_print("\r\n"); + uart::uart_write_str("\r\n"); // read kernel size @@ -37,9 +37,9 @@ unsafe fn bootloader(){ // read kernel size (4 bytes) from uart uart::read(&mut kernel_size as *mut u32 as *mut u8 /*(uint8_t)(&kernel_size) */, 4); - uart::_print("Kernel size: "); + uart::uart_write_str("Kernel size: "); uart::print_hex(kernel_size); - uart::_print("\r\n"); + uart::uart_write_str("\r\n"); // start to read kernel let mut kernel_addr: u64 = KERNEL_LOAD_ADDR; @@ -59,5 +59,5 @@ unsafe fn bootloader(){ } // jump to kernel - uart::_print("Jump to kernel\r\n"); + uart::uart_write_str("Jump to kernel\r\n"); } diff --git a/driver/src/uart.rs b/driver/src/uart.rs index 43d5acf08..a0d44830d 100644 --- a/driver/src/uart.rs +++ b/driver/src/uart.rs @@ -78,9 +78,46 @@ pub fn init_uart() { } } + +pub struct Uart; + +use core::fmt::{self, Write}; + +pub struct UartWriter; +// core::fmt::write needs a mutable reference to the writer +// we create a UartWriter which is implemented for Write trait with write_str method +// write_str method writes the formatted string to the buffer +impl Write for UartWriter { + fn write_str(&mut self, s: &str) -> fmt::Result { + unsafe { + for i in s.bytes() { + write_u8(i); + } + } + Ok(()) + } + fn write_fmt(&mut self, args: core::fmt::Arguments) -> core::fmt::Result { + core::fmt::write(&mut UartWriter, args).unwrap(); + Ok(()) + } +} + +impl UartWriter { + pub fn new() -> UartWriter { + UartWriter + } +} + + +impl Uart { + pub fn new() -> Uart { + Uart + } +} + #[no_mangle] #[inline(never)] -pub unsafe fn _print(s: &str) { +pub unsafe fn uart_write_str(s: &str) { for i in s.bytes() { write_u8(i); } @@ -191,6 +228,6 @@ pub unsafe fn strncmp(s1: &str, s2: &str, n: usize) -> bool { // println #[no_mangle] pub unsafe fn println(s: &str) { - _print(s); - _print("\n\r"); + uart_write_str(s); + uart_write_str("\n\r"); } diff --git a/initramfs.cpio b/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..5c610c78fe82bc468f9183dc2a88208c74ef343b GIT binary patch literal 1024 zcmXpoH!wFaGyowtM{@%pFfnv>0nrA=t`;b?fq{{knSq&$qd8D93V^5s%A<%PIB;=2 z2B2*S`z%39EDRk@z)CUgGeolwtRAEVtRA<0W>9&9WWAD#5(ZC&ocyv>1!p}522}f< zLF!1b-xX>uA^RO+_NQg$q#A ! { uart::init_uart(); - uart::_print("Revision: "); + println!("Revision: {:#x}", mailbox::get_board_revisioin()); // get board revision let revision = mailbox::get_board_revisioin(); - let h = alloc::string::String::from("Hello"); - // print hex of revision - uart::print_hex(revision); - uart::println(""); // get ARM memory base address and size let (base, size) = mailbox::get_arm_memory(); // print ARM memory base address and size - uart::_print("ARM memory base address: "); - uart::print_hex(base); - uart::_print("\r\n"); + println!("ARM memory base address: {:#x}", base); - uart::_print("ARM memory size: "); - uart::print_hex(size); - uart::_print("\r\n"); + println!("ARM memory size: {:#x}", size); let mut out_buf: [u8; 128] = [0; 128]; let mut in_buf: [u8; 128] = [0; 128]; @@ -53,12 +47,12 @@ unsafe fn kernel_init() -> ! { let mut handler: CpioHandler = CpioHandler::new(QEMU_INITRD_START as *mut u8); loop { - uart::_print(">> "); + uart::uart_write_str(">> "); let inp = uart::getline(&mut in_buf, true); if inp == "Hello" { - uart::_print("Hello World!\r\n"); + uart::uart_write_str("Hello World!\r\n"); } else if inp == "help" { - uart::_print("help : print this help menu\r\nhello : print Hello World!\r\nreboot : reboot the device\r\n"); + uart::uart_write_str("help : print this help menu\r\nhello : print Hello World!\r\nreboot : reboot the device\r\n"); } else if inp == "reboot" { const PM_PASSWORD: u32 = 0x5a000000; const PM_RSTC: u32 = 0x3F10001c; @@ -73,8 +67,8 @@ unsafe fn kernel_init() -> ! { if name == "TRAILER!!!\0" { break; } - uart::_print(name); - uart::_print("\r\n"); + uart::uart_write_str(name); + uart::uart_write_str("\r\n"); handler.next_file(); } @@ -94,12 +88,12 @@ unsafe fn kernel_init() -> ! { name }; if name == target { - uart::_print("File: "); - uart::_print(name); - uart::_print("\r\n"); + uart::uart_write_str("File: "); + uart::uart_write_str(name); + uart::uart_write_str("\r\n"); let contant =handler.read_current_file(); - uart::_print(core::str::from_utf8(contant).unwrap()); - uart::_print("\r\n"); + uart::uart_write_str(core::str::from_utf8(contant).unwrap()); + uart::uart_write_str("\r\n"); } handler.next_file(); } @@ -107,7 +101,7 @@ unsafe fn kernel_init() -> ! { } else { - uart::_print("Command not found\r\n"); + uart::uart_write_str("Command not found\r\n"); } uart::uart_nops(); diff --git a/kernel/src/print.rs b/kernel/src/print.rs index b28b04f64..64da973cb 100644 --- a/kernel/src/print.rs +++ b/kernel/src/print.rs @@ -1,3 +1,29 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +// +// Copyright (c) 2018-2023 Andre Richter +//! Printing. +use driver::uart; +use core::fmt; + + +pub fn _print(args: fmt::Arguments) { + use core::fmt::Write; + let mut writer = uart::UartWriter::new(); + writer.write_fmt(args); +} + +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ($crate::print::_print(format_args!($($arg)*))); +} + +#[macro_export] +macro_rules! println { + () => ($crate::print!("\n")); + ($($arg:tt)*) => ({ + $crate::print::_print(format_args_nl!($($arg)*)); + }) +} From de782adde4b8be573484cb58a5fd7b65ae3a69ba Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Sat, 30 Mar 2024 01:31:05 +0800 Subject: [PATCH 16/34] Fix: kernelsender.py --- .gitignore | 3 ++- initramfs.cpio | Bin 1024 -> 0 bytes kernel/README.md | 41 +++++------------------------- utils/README.md | 3 +++ utils/kernel_sender.py | 55 +++++++++++++++++++---------------------- 5 files changed, 37 insertions(+), 65 deletions(-) delete mode 100644 initramfs.cpio create mode 100644 utils/README.md diff --git a/.gitignore b/.gitignore index 99351c370..953b31363 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ target *.img .vscode rootfs -.gdbinit \ No newline at end of file +.gdbinit +initramfs.cpio \ No newline at end of file diff --git a/initramfs.cpio b/initramfs.cpio deleted file mode 100644 index 5c610c78fe82bc468f9183dc2a88208c74ef343b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1024 zcmXpoH!wFaGyowtM{@%pFfnv>0nrA=t`;b?fq{{knSq&$qd8D93V^5s%A<%PIB;=2 z2B2*S`z%39EDRk@z)CUgGeolwtRAEVtRA<0W>9&9WWAD#5(ZC&ocyv>1!p}522}f< zLF!1b-xX>uA^RO+_NQg$q#A Date: Fri, 5 Apr 2024 00:24:08 +0800 Subject: [PATCH 17/34] Device Tree --- .gitignore | 4 +- .initgdb | 2 + Cargo.lock | 7 + Makefile | 17 +- bootloader/src/_arch/aarch64/cpu/boot.rs | 2 +- bootloader/src/_arch/aarch64/cpu/boot.s | 10 +- bootloader/src/bsp/raspberrypi/bootloader.ld | 2 +- driver/src/devicetree.rs | 24 -- driver/src/mailbox.rs | 19 +- driver/src/uart.rs | 27 +-- kernel/Cargo.toml | 1 + kernel/src/_arch/aarch64/cpu/boot.s | 4 + kernel/src/allocator/mod.rs | 3 +- kernel/src/bsp/raspberrypi/kernel.ld | 4 +- kernel/src/dtb.rs | 223 +++++++++++++++++++ kernel/src/main.rs | 112 ++++++---- utils/kernel_sender.py | 2 +- 17 files changed, 350 insertions(+), 113 deletions(-) create mode 100644 .initgdb delete mode 100644 driver/src/devicetree.rs create mode 100644 kernel/src/dtb.rs diff --git a/.gitignore b/.gitignore index 953b31363..b4d17f6b6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ target .vscode rootfs .gdbinit -initramfs.cpio \ No newline at end of file +initramfs.cpio +*.dtb +*.txt \ No newline at end of file diff --git a/.initgdb b/.initgdb new file mode 100644 index 000000000..07059ca94 --- /dev/null +++ b/.initgdb @@ -0,0 +1,2 @@ +file target/aarch64-unknown-none-softfloat/release/kernel +target remote :1234 diff --git a/Cargo.lock b/Cargo.lock index 498db9cb7..c48479853 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,12 +26,19 @@ dependencies = [ "aarch64-cpu", ] +[[package]] +name = "fdt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67" + [[package]] name = "kernel" version = "0.1.0" dependencies = [ "aarch64-cpu", "driver", + "fdt", ] [[package]] diff --git a/Makefile b/Makefile index b26cbb322..84e375dce 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,8 @@ QEMU_TTY_ARGS = -display none -serial null -serial pty QEMU_TTY_DEBUG_ARGS = -display none -S -s -serial null -serial pty EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE) +QEMU_DTB_PATH = -dtb $(shell pwd)/bcm2710-rpi-3-b-plus.dtb + OBJDUMP_BINARY = aarch64-none-elf-objdump NM_BINARY = aarch64-none-elf-mn READELF_BINARY = aarch64-none-elf-readelf @@ -57,23 +59,22 @@ bootloader_elf: kernel_qemu: $(KERNEL_BIN) $(call color_header, "Launching QEMU") - $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) + $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) $(QEMU_DTB_PATH) -kernel $(KERNEL_BIN) kernel_gdb: $(KERNEL_BIN) $(call color_header, "Launching QEMU in background") - $(EXEC_QEMU) $(QEMU_DEBUG_ARGS) -kernel $(KERNEL_BIN) + $(EXEC_QEMU) $(QEMU_DEBUG_ARGS) $(QEMU_DTB_PATH) -kernel $(KERNEL_BIN) kernel_initramfs_qemu: $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU") - $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN) -initrd initramfs.cpio - -bootloader_qemu: $(BOOTLOADER_BIN) + $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) $(QEMU_DTB_PATH) -kernel $(KERNEL_BIN) -initrd initramfs.cpio +bootloader_qemu:$(BOOTLOADER_BIN) $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU") - $(EXEC_QEMU) $(QEMU_TTY_ARGS) -kernel $(BOOTLOADER_BIN) - + $(EXEC_QEMU) $(QEMU_TTY_ARGS) -kernel $(BOOTLOADER_BIN) -initrd initramfs.cpio + # -device loader,file=$(BOOTLOADER_BIN),addr=0x60000,cpu-num=0 -bootloader_gdb: $(BOOTLOADER_BIN) +bootloader_gdb: $(BOOTLOADER_BIN) $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU in background") $(EXEC_QEMU) $(QEMU_TTY_DEBUG_ARGS) -kernel $(BOOTLOADER_BIN) diff --git a/bootloader/src/_arch/aarch64/cpu/boot.rs b/bootloader/src/_arch/aarch64/cpu/boot.rs index 76a8b1253..885ea465d 100644 --- a/bootloader/src/_arch/aarch64/cpu/boot.rs +++ b/bootloader/src/_arch/aarch64/cpu/boot.rs @@ -14,5 +14,5 @@ global_asm!( #[no_mangle] pub unsafe fn _start_rust(){ crate::bootloader(); - uart::_print("Bootloader finished\r\n"); + uart::uart_write_str("Bootloader finished\r\n"); } diff --git a/bootloader/src/_arch/aarch64/cpu/boot.s b/bootloader/src/_arch/aarch64/cpu/boot.s index aacb4a4ab..66ebc1881 100644 --- a/bootloader/src/_arch/aarch64/cpu/boot.s +++ b/bootloader/src/_arch/aarch64/cpu/boot.s @@ -13,6 +13,8 @@ // fn _start() //------------------------------------------------------------------------------ _start: + ADR_REL x1, __dtb_addr + str x0, [x1] // Only proceed on the boot core. Park it otherwise. mrs x0, MPIDR_EL1 and x0, x0, {CONST_CORE_ID_MASK} @@ -61,9 +63,13 @@ _start: // Jump to Rust code. bl _start_rust + // load __dtb_addr value + ADR_REL x1, __dtb_addr + ldr x0, [x1] + // jump to 0x80000 - ldr x0, =0x80000 - br x0 + ldr x1, =0x80000 + br x1 // Infinitely wait for events (aka "park the core"). .L_parking_loop: diff --git a/bootloader/src/bsp/raspberrypi/bootloader.ld b/bootloader/src/bsp/raspberrypi/bootloader.ld index d7b3db174..6e6eb21fc 100644 --- a/bootloader/src/bsp/raspberrypi/bootloader.ld +++ b/bootloader/src/bsp/raspberrypi/bootloader.ld @@ -24,7 +24,6 @@ SECTIONS . = ALIGN(16); __relo_end = .; - /* Section is zeroed in pairs of u64. Align start and end to 16 bytes */ .bss (NOLOAD): ALIGN(16) { @@ -33,5 +32,6 @@ SECTIONS . = ALIGN(16); __bss_end_exclusive = .; } + __dtb_addr = .; } \ No newline at end of file diff --git a/driver/src/devicetree.rs b/driver/src/devicetree.rs deleted file mode 100644 index 962047fdf..000000000 --- a/driver/src/devicetree.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::fs::File; -use std::io::Read; - -// A parser parse device tree - -struct FdtHeader { - magic: u32, - totalsize: u32, - off_dt_struct: u32, - off_dt_strings: u32, - off_mem_rsvmap: u32, - version: u32, - last_comp_version: u32, - boot_cpuid_phys: u32, - size_dt_strings: u32, - size_dt_struct: u32, -} - -struct FdtReserveEntry { - address: u64, - size: u64, -} - - diff --git a/driver/src/mailbox.rs b/driver/src/mailbox.rs index e3a570ec2..9cdf5f69d 100644 --- a/driver/src/mailbox.rs +++ b/driver/src/mailbox.rs @@ -44,10 +44,9 @@ const REQUEST_FAILED: u32 = 0x80000001; const TAG_REQUEST_CODE: u32 = 0x00000000; const END_TAG: u32 = 0x00000000; -pub unsafe fn get_board_revisioin() -> u32 { +pub fn get_board_revisioin() -> u32 { let mut mailbox: [u32; 32] = [0; 32]; - let idx_offset:usize = (0x10 - mailbox.as_ptr() as u32 & 0xf) as usize; - + let idx_offset: usize = (0x10 - mailbox.as_ptr() as u32 & 0xf) as usize; mailbox[0 + idx_offset] = 7 * 4; mailbox[1 + idx_offset] = REQUEST_CODE; @@ -57,17 +56,17 @@ pub unsafe fn get_board_revisioin() -> u32 { mailbox[5 + idx_offset] = 0; mailbox[6 + idx_offset] = END_TAG; - - mailbox_call(&mut mailbox[idx_offset..(idx_offset + 7)]); - + unsafe { + mailbox_call(&mut mailbox[idx_offset..(idx_offset + 7)]); + } mailbox[5] } // Get ARM memory base address and size using mailbox const GET_ARM_MEMORY: u32 = 0x00010005; -pub unsafe fn get_arm_memory() -> (u32, u32) { +pub fn get_arm_memory() -> (u32, u32) { let mut mailbox: [u32; 32] = [0; 32]; - let idx_offset:usize = (0x10 - mailbox.as_ptr() as u32 & 0xf) as usize; + let idx_offset: usize = (0x10 - mailbox.as_ptr() as u32 & 0xf) as usize; mailbox[0 + idx_offset] = 8 * 4; mailbox[1 + idx_offset] = REQUEST_CODE; @@ -78,7 +77,7 @@ pub unsafe fn get_arm_memory() -> (u32, u32) { mailbox[6 + idx_offset] = 0; mailbox[7 + idx_offset] = END_TAG; - mailbox_call(&mut mailbox[idx_offset..(idx_offset + 8)]); - + unsafe {mailbox_call(&mut mailbox[idx_offset..(idx_offset + 8)]); + } (mailbox[5], mailbox[6]) } diff --git a/driver/src/uart.rs b/driver/src/uart.rs index a0d44830d..248c18e8c 100644 --- a/driver/src/uart.rs +++ b/driver/src/uart.rs @@ -1,13 +1,9 @@ - - - use core::arch::asm; use core::{ ptr::{read_volatile, write_volatile}, usize, }; - const AUXENB: u32 = 0x3F215004; const AUX_MU_CNTL_REG: u32 = 0x3F215060; const AUX_MU_IER_REG: u32 = 0x3F215044; @@ -78,7 +74,6 @@ pub fn init_uart() { } } - pub struct Uart; use core::fmt::{self, Write}; @@ -108,7 +103,6 @@ impl UartWriter { } } - impl Uart { pub fn new() -> Uart { Uart @@ -124,9 +118,9 @@ pub unsafe fn uart_write_str(s: &str) { } #[no_mangle] -pub fn getline(s: &mut [u8; 128], is_echo: bool) -> &str { +pub fn getline(s: &mut [u8; 128], is_echo: bool) -> &str { let mut ptr: usize = 0; - unsafe{ + unsafe { loop { let c = read_u8(); match c { @@ -145,7 +139,6 @@ pub fn getline(s: &mut [u8; 128], is_echo: bool) -> &str { } asm!("nop"); } - } core::str::from_utf8(&s[0..ptr]).unwrap() } @@ -178,7 +171,6 @@ pub unsafe fn read_u8() -> Option { } } - pub unsafe fn read(s: *mut u8, len: usize) { let mut ptr: usize = 0; while ptr < len { @@ -195,7 +187,7 @@ pub unsafe fn read(s: *mut u8, len: usize) { // print u32 in hex #[no_mangle] -pub unsafe fn print_hex(n: u32) { +pub fn print_hex(n: u32) { let mut buf: [u8; 8] = [0; 8]; let mut ptr: usize = 0; let mut num: u32 = n; @@ -210,11 +202,13 @@ pub unsafe fn print_hex(n: u32) { num = num / 16; } for i in buf.iter().take(8).rev() { - write_u8(*i); + unsafe { + write_u8(*i); + } } } -pub unsafe fn strncmp(s1: &str, s2: &str, n: usize) -> bool { +pub fn strncmp(s1: &str, s2: &str, n: usize) -> bool { let mut i = 0; while i < n { if s1.as_bytes()[i] != s2.as_bytes()[i] { @@ -224,10 +218,3 @@ pub unsafe fn strncmp(s1: &str, s2: &str, n: usize) -> bool { } true } - -// println -#[no_mangle] -pub unsafe fn println(s: &str) { - uart_write_str(s); - uart_write_str("\n\r"); -} diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 087da813f..5e106f1e3 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -20,6 +20,7 @@ path = "src/main.rs" [dependencies] driver = { path = "../driver" } +fdt = "0.1.5" # Platform specific dependencies diff --git a/kernel/src/_arch/aarch64/cpu/boot.s b/kernel/src/_arch/aarch64/cpu/boot.s index ad63ef33d..a9b715476 100644 --- a/kernel/src/_arch/aarch64/cpu/boot.s +++ b/kernel/src/_arch/aarch64/cpu/boot.s @@ -14,6 +14,10 @@ //------------------------------------------------------------------------------ _start: // Only proceed on the boot core. Park it otherwise. + // save dtb address (x0) to uar + ADR_REL x1, __dtb_addr + str x0, [x1] + mrs x0, MPIDR_EL1 and x0, x0, {CONST_CORE_ID_MASK} ldr x1, BOOT_CORE_ID // provided by bsp/__board_name__/cpu.rs diff --git a/kernel/src/allocator/mod.rs b/kernel/src/allocator/mod.rs index cf4b85af4..bb5ec979b 100644 --- a/kernel/src/allocator/mod.rs +++ b/kernel/src/allocator/mod.rs @@ -1,5 +1,5 @@ const HEAP_SIZE: usize = 1024 * 1024; // 1 MB -const HEAP_START: usize = 0x60000; +const HEAP_START: usize = 0x210000; use core::cell::UnsafeCell; @@ -16,6 +16,7 @@ impl MyAllocator { memory: UnsafeCell::new(memory::HeapMemory::new(HEAP_START, HEAP_SIZE)), } } + unsafe fn memory(&self) -> &mut memory::HeapMemory { &mut *self.memory.get() } diff --git a/kernel/src/bsp/raspberrypi/kernel.ld b/kernel/src/bsp/raspberrypi/kernel.ld index 7ac946b52..260cb112e 100644 --- a/kernel/src/bsp/raspberrypi/kernel.ld +++ b/kernel/src/bsp/raspberrypi/kernel.ld @@ -29,5 +29,5 @@ SECTIONS . = ALIGN(16); __bss_end_exclusive = .; } - -} + __dtb_addr = .; +} diff --git a/kernel/src/dtb.rs b/kernel/src/dtb.rs new file mode 100644 index 000000000..a3f4b5acb --- /dev/null +++ b/kernel/src/dtb.rs @@ -0,0 +1,223 @@ +// A parser parse device tree; + +use alloc::vec::Vec; + +#[repr(C, packed)] +pub struct FdtHeader { + pub magic: u32, + pub totalsize: u32, + pub off_dt_struct: u32, + pub off_dt_strings: u32, + pub off_mem_rsvmap: u32, + pub version: u32, + pub last_comp_version: u32, + pub boot_cpuid_phys: u32, + pub size_dt_strings: u32, + pub size_dt_struct: u32, +} + +pub struct FdtReserveEntry { + address: u64, + size: u64, +} +impl FdtReserveEntry { + pub fn get_address(&self) -> u64 { + self.address + } + pub fn get_size(&self) -> u64 { + self.size + } +} + +#[repr(C, packed)] +struct FdtProp { + len: u32, + nameoff: u32, +} + +pub struct DtbParser { + pub header: *mut FdtHeader, + pub magic: u32, + pub totalsize: u32, + pub off_dt_struct: u32, + pub off_dt_strings: u32, + pub off_mem_rsvmap: u32, + pub version: u32, + pub last_comp_version: u32, + pub boot_cpuid_phys: u32, + pub size_dt_strings: u32, + pub size_dt_struct: u32, + pub fdt_reserve_entries: Vec, +} + +impl DtbParser { + pub fn new(dtb: *const u8) -> DtbParser { + let mut h: *mut FdtHeader = dtb as *mut FdtHeader; + unsafe { + DtbParser { + header: dtb as *mut FdtHeader, + magic: (*h).magic.swap_bytes(), + totalsize: (*h).totalsize.swap_bytes(), + off_dt_struct: (*h).off_dt_struct.swap_bytes(), + off_dt_strings: (*h).off_dt_strings.swap_bytes(), + off_mem_rsvmap: (*h).off_mem_rsvmap.swap_bytes(), + version: (*h).version.swap_bytes(), + last_comp_version: (*h).last_comp_version.swap_bytes(), + boot_cpuid_phys: (*h).boot_cpuid_phys.swap_bytes(), + size_dt_strings: (*h).size_dt_strings.swap_bytes(), + size_dt_struct: (*h).size_dt_struct.swap_bytes(), + fdt_reserve_entries: mem_rsvmap_paser(dtb, (*h).off_mem_rsvmap), + } + } + } + + pub fn get_fdt_reserve_entries(&self) -> &Vec { + &self.fdt_reserve_entries + } + // parse structure block + pub fn parse_struct_block(&self) { + let mut offset = self.off_dt_struct as usize; + let h: *mut u8 = self.header as *mut u8; + unsafe { + loop { + crate::println!("Offset: {:#x}", offset); + let token = (*(h.add(offset) as *const u32)).swap_bytes(); + match token { + FDT_BEGIN_NODE => { + crate::println!("Node: "); + offset += 4; + let name = c_str_to_str(h.add(offset)); + crate::println!("\tName: /{}", name); + crate::println!("\tName Length: {}", name.len()); + offset += name.len() + 1; + } + FDT_END_NODE => { + crate::println!("End Node"); + offset += 4; + } + FDT_PROP => { + offset += 4; + let prop = h.add(offset as usize) as *const FdtProp; + let len = (*prop).len.swap_bytes() as usize; + let nameoff = (*prop).nameoff.swap_bytes() as usize; + let name = h.add(nameoff + self.off_dt_strings as usize); + // print name of property + crate::println!("Property: "); + crate::println!("\tLength: {}", len); + crate::println!("\tName: {}", c_str_to_str(name)); + // print value + let value = h.add(offset + 8); + crate::println!("\tValue:"); + crate::print!("\t\t"); + for i in 0..len { + crate::print!("{:02x} ", *value.add(i)); + if i % 16 == 15 { + crate::println!(); + crate::print!("\t\t"); + } + } + crate::println!(); + crate::print!("\t\t"); + for i in 0..len { + let val = *value.add(i); + if val >= 32 && val <= 126 { + crate::print!("{}", val as char); + } else { + crate::print!("."); + } + } + crate::println!(); + offset += 8 + len; + } + FDT_NOP => { + crate::println!("NOP"); + offset += 4; + } + FDT_END => { + crate::println!("End"); + break; + } + _ => { + crate::println!("Unknown token: {:#x}", token); + break; + } + } + crate::println!(); + // next token + offset = (offset + 3) & !3; + } + } + } + + pub fn traverse(&self, callback: fn(&str, *const u8, usize) -> Option) -> Option { + let mut offset = self.off_dt_struct as usize; + let h: *mut u8 = self.header as *mut u8; + unsafe { + loop { + let token = (*(h.add(offset) as *const u32)).swap_bytes(); + match token { + FDT_BEGIN_NODE => { + offset += 4; + let name = c_str_to_str(h.add(offset)); + offset += name.len() + 1; + } + FDT_END_NODE => { + offset += 4; + } + FDT_PROP => { + offset += 4; + let prop = h.add(offset as usize) as *const FdtProp; + let len = (*prop).len.swap_bytes() as usize; + let nameoff = (*prop).nameoff.swap_bytes() as usize; + let name = h.add(nameoff + self.off_dt_strings as usize); + let value = h.add(offset + 8); + if let Some(ret) = callback(c_str_to_str(name), value, len) { + return Some(ret); + } + offset += 8 + len; + } + FDT_NOP => { + offset += 4; + } + FDT_END => { + break None; + } + _ => { + crate::println!("Unknown token: {:#x}", token); + break None; + } + } + // next token + offset = (offset + 3) & !3; + } + } + } +} + +fn mem_rsvmap_paser(dtb: *const u8, off_mem_rsvmap: u32) -> Vec { + let mut h: *mut FdtHeader = dtb as *mut FdtHeader; + let mut entries = Vec::new(); + let mut offset = off_mem_rsvmap.swap_bytes(); + unsafe { + loop { + let address = *(dtb.add(offset as usize) as *const u64); + let size = (*(dtb.add(offset as usize + 8) as *const u64)).swap_bytes(); + if address == 0 && size == 0 { + break; + } + entries.push(FdtReserveEntry { address, size }); + offset += 16; + } + } + entries +} + +const FDT_BEGIN_NODE: u32 = 0x00000001; +const FDT_END_NODE: u32 = 0x00000002; +const FDT_PROP: u32 = 0x00000003; +const FDT_NOP: u32 = 0x00000004; +const FDT_END: u32 = 0x00000009; + +fn c_str_to_str(s: *const u8) -> &'static str { + unsafe { core::str::from_utf8_unchecked(core::ffi::CStr::from_ptr(s as *const i8).to_bytes()) } +} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index a7a22f6f4..96b766395 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -4,76 +4,101 @@ #![feature(default_alloc_error_handler)] #![feature(format_args_nl)] +mod allocator; mod bsp; mod cpu; +mod dtb; mod panic_wait; -mod allocator; mod print; -extern crate alloc; +extern crate alloc; + +use fdt; +use allocator::MyAllocator; +use core::ptr::addr_of; use core::ptr::write_volatile; use driver::cpio::CpioHandler; use driver::mailbox; use driver::uart; -use allocator::MyAllocator; const QEMU_INITRD_START: u64 = 0x8000000; #[global_allocator] static mut ALLOCATOR: MyAllocator = MyAllocator::new(); +fn get_initrd_addr(name: &str, data: *const u8, len: usize) -> Option { + if name == "linux,initrd-start" { + unsafe { Some((*(data as *const u32)).swap_bytes()) } + } else { + None + } +} + #[no_mangle] -unsafe fn kernel_init() -> ! { - +fn kernel_init() -> ! { uart::init_uart(); - println!("Revision: {:#x}", mailbox::get_board_revisioin()); - // get board revision - let revision = mailbox::get_board_revisioin(); - - // print hex of revision - - // get ARM memory base address and size - let (base, size) = mailbox::get_arm_memory(); + // load device tree at symbol __dtb_addr + let mut dtb_addr: *mut u64; + let mut dtb_pos: *mut u8; + unsafe { + core::arch::asm!("ldr {}, =__dtb_addr", out(reg) dtb_addr); + dtb_pos = (*dtb_addr) as *mut u8; + } + let dtb_parser = dtb::DtbParser::new(dtb_pos); - // print ARM memory base address and size - println!("ARM memory base address: {:#x}", base); + let f = unsafe { fdt::Fdt::from_ptr(dtb_pos as *const u8).unwrap() }; - println!("ARM memory size: {:#x}", size); + let s = unsafe { + core::slice::from_raw_parts(dtb_pos.add(dtb_parser.off_dt_strings as usize), 100) + }; - let mut out_buf: [u8; 128] = [0; 128]; let mut in_buf: [u8; 128] = [0; 128]; + // find initrd value by dtb traverse + let mut initrd_start: *mut u8; + if let Some(addr) = dtb_parser.traverse(get_initrd_addr) { + initrd_start = addr as *mut u8; + } else { + initrd_start = 0 as *mut u8; + } - let mut handler: CpioHandler = CpioHandler::new(QEMU_INITRD_START as *mut u8); + loop { - uart::uart_write_str(">> "); + + println!("Initrd start: {:#x}", initrd_start as u64); + print!(">> "); let inp = uart::getline(&mut in_buf, true); - if inp == "Hello" { - uart::uart_write_str("Hello World!\r\n"); + if inp == "hello" { + println!("Hello World!"); } else if inp == "help" { - uart::uart_write_str("help : print this help menu\r\nhello : print Hello World!\r\nreboot : reboot the device\r\n"); + println!("help : print this help menu\r\nhello : print Hello World!\r\nreboot : reboot the device"); } else if inp == "reboot" { const PM_PASSWORD: u32 = 0x5a000000; const PM_RSTC: u32 = 0x3F10001c; const PM_WDOG: u32 = 0x3F100024; const PM_RSTC_WRCFG_FULL_RESET: u32 = 0x00000020; - write_volatile(PM_WDOG as *mut u32, PM_PASSWORD | 100); - write_volatile(PM_RSTC as *mut u32, PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); + unsafe { + write_volatile(PM_WDOG as *mut u32, PM_PASSWORD | 100); + write_volatile(PM_RSTC as *mut u32, PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); + } break; } else if inp == "ls" { + let mut handler: CpioHandler = CpioHandler::new(initrd_start as *mut u8); + loop { let name = handler.get_current_file_name(); if name == "TRAILER!!!\0" { break; } - uart::uart_write_str(name); - uart::uart_write_str("\r\n"); - + println!("{}", name); + handler.next_file(); } handler.rewind(); - } else if uart::strncmp(inp, "cat", 3){ + } else if uart::strncmp(inp, "cat", 3) { + let mut handler: CpioHandler = CpioHandler::new(initrd_start as *mut u8); + let target = &inp[4..]; loop { let name = handler.get_current_file_name(); @@ -82,29 +107,32 @@ unsafe fn kernel_init() -> ! { } let l = name.len(); // if last char is \0, remove it - let name = if name.as_bytes()[l-1] == 0 { - &name[..l-1] + let name = if name.as_bytes()[l - 1] == 0 { + &name[..l - 1] } else { name }; if name == target { - uart::uart_write_str("File: "); - uart::uart_write_str(name); - uart::uart_write_str("\r\n"); - let contant =handler.read_current_file(); - uart::uart_write_str(core::str::from_utf8(contant).unwrap()); - uart::uart_write_str("\r\n"); + println!("File: {}", name); + let content = handler.read_current_file(); + println!("{}", core::str::from_utf8(content).unwrap()); } handler.next_file(); } handler.rewind(); - } - - else { - uart::uart_write_str("Command not found\r\n"); + } else if inp == "dtb" { + dtb_parser.parse_struct_block(); + } else if inp == "mailbox" { + println!("Revision: {:#x}", mailbox::get_board_revisioin()); + let (base, size) = mailbox::get_arm_memory(); + println!("ARM memory base address: {:#x}", base); + println!("ARM memory size: {:#x}", size); + } else { + println!("Command not found\r\n"); + } + unsafe { + uart::uart_nops(); } - - uart::uart_nops(); } panic!() } diff --git a/utils/kernel_sender.py b/utils/kernel_sender.py index 3e8dee2c8..84d9b56d4 100644 --- a/utils/kernel_sender.py +++ b/utils/kernel_sender.py @@ -29,7 +29,7 @@ kernel_data = kernel.read() # Print the size of the kernel image print("Kernel size: ", len(kernel_data)) - with open(sys.argv[1], "wb", buffering = 0) as tty: + with open(args.device, "wb", buffering = 0) as tty: # Send kernel size to ttyUSB0 tty.write(len(kernel_data).to_bytes(4, byteorder='little')) # Write the kernel image to the ttyUSB0 port From 5adee877b3e44ae0e63aa6f9d045d7016b31675b Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Sat, 6 Apr 2024 21:58:56 +0800 Subject: [PATCH 18/34] Fix something --- .initgdb | 2 +- Makefile | 18 +-- bootloader/src/_arch/aarch64/cpu/boot.s | 8 +- driver/src/addr_loader.rs | 9 ++ driver/src/cpio.rs | 38 ++++++- driver/src/lib.rs | 3 +- driver/src/uart.rs | 15 ++- kernel/src/{dtb.rs => fdt.rs} | 0 kernel/src/main.rs | 140 ++++++++++-------------- kernel/src/print.rs | 2 +- 10 files changed, 130 insertions(+), 105 deletions(-) create mode 100644 driver/src/addr_loader.rs rename kernel/src/{dtb.rs => fdt.rs} (100%) diff --git a/.initgdb b/.initgdb index 07059ca94..65ac531dc 100644 --- a/.initgdb +++ b/.initgdb @@ -1,2 +1,2 @@ -file target/aarch64-unknown-none-softfloat/release/kernel +file target/aarch64-unknown-none-softfloat/release/bootloader target remote :1234 diff --git a/Makefile b/Makefile index 84e375dce..a56ea85eb 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ QEMU_TTY_ARGS = -display none -serial null -serial pty QEMU_TTY_DEBUG_ARGS = -display none -S -s -serial null -serial pty EXEC_QEMU = $(QEMU_BINARY) -M $(QEMU_MACHINE_TYPE) -QEMU_DTB_PATH = -dtb $(shell pwd)/bcm2710-rpi-3-b-plus.dtb +QEMU_DTB_PATH = $(shell pwd)/bcm2710-rpi-3-b-plus.dtb OBJDUMP_BINARY = aarch64-none-elf-objdump NM_BINARY = aarch64-none-elf-mn @@ -23,6 +23,7 @@ RUSTC_MISC_ARGS = -C target-cpu=cortex-a53 KERNEL_PATH = $(shell pwd)/kernel BOOTLOADER_PATH = $(shell pwd)/bootloader +INITRD_PATH = $(shell pwd)/initramfs.cpio KERNEL_ELF = target/$(TARGET)/release/kernel BOOTLOADER_ELF = target/$(TARGET)/release/bootloader @@ -59,26 +60,19 @@ bootloader_elf: kernel_qemu: $(KERNEL_BIN) $(call color_header, "Launching QEMU") - $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) $(QEMU_DTB_PATH) -kernel $(KERNEL_BIN) + $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -initrd $(INITRD_PATH) -dtb $(QEMU_DTB_PATH) -kernel $(KERNEL_BIN) kernel_gdb: $(KERNEL_BIN) $(call color_header, "Launching QEMU in background") - $(EXEC_QEMU) $(QEMU_DEBUG_ARGS) $(QEMU_DTB_PATH) -kernel $(KERNEL_BIN) + $(EXEC_QEMU) $(QEMU_DEBUG_ARGS) -dtb $(QEMU_DTB_PATH) -kernel $(KERNEL_BIN) -kernel_initramfs_qemu: $(KERNEL_BIN) cpio - $(call color_header, "Launching QEMU") - $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) $(QEMU_DTB_PATH) -kernel $(KERNEL_BIN) -initrd initramfs.cpio bootloader_qemu:$(BOOTLOADER_BIN) $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU") - $(EXEC_QEMU) $(QEMU_TTY_ARGS) -kernel $(BOOTLOADER_BIN) -initrd initramfs.cpio - -# -device loader,file=$(BOOTLOADER_BIN),addr=0x60000,cpu-num=0 + $(EXEC_QEMU) $(QEMU_TTY_ARGS) -dtb $(QEMU_DTB_PATH) -kernel $(BOOTLOADER_BIN) -initrd $(INITRD_PATH) bootloader_gdb: $(BOOTLOADER_BIN) $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU in background") - $(EXEC_QEMU) $(QEMU_TTY_DEBUG_ARGS) -kernel $(BOOTLOADER_BIN) - -# -device loader,file=$(BOOTLOADER_BIN),addr=0x60000,cpu-num=0 + $(EXEC_QEMU) $(QEMU_TTY_DEBUG_ARGS) $(QEMU_DTB_PATH) -kernel $(BOOTLOADER_BIN) -initrd $(INITRD_PATH) cpio: $(call color_header, "Creating initramfs") diff --git a/bootloader/src/_arch/aarch64/cpu/boot.s b/bootloader/src/_arch/aarch64/cpu/boot.s index 66ebc1881..86378bb5d 100644 --- a/bootloader/src/_arch/aarch64/cpu/boot.s +++ b/bootloader/src/_arch/aarch64/cpu/boot.s @@ -13,8 +13,10 @@ // fn _start() //------------------------------------------------------------------------------ _start: - ADR_REL x1, __dtb_addr + // Save the address of the device tree blob. + ldr x1, =__dtb_addr str x0, [x1] + // Only proceed on the boot core. Park it otherwise. mrs x0, MPIDR_EL1 and x0, x0, {CONST_CORE_ID_MASK} @@ -63,8 +65,8 @@ _start: // Jump to Rust code. bl _start_rust - // load __dtb_addr value - ADR_REL x1, __dtb_addr + // restore the address of the device tree blob. + ldr x1, =__dtb_addr ldr x0, [x1] // jump to 0x80000 diff --git a/driver/src/addr_loader.rs b/driver/src/addr_loader.rs new file mode 100644 index 000000000..98caddd4b --- /dev/null +++ b/driver/src/addr_loader.rs @@ -0,0 +1,9 @@ + + +pub fn load_dtb_addr() -> *mut u8 { + let dtb_addr: *mut u64; + unsafe { + core::arch::asm!("ldr {}, =__dtb_addr", out(reg) dtb_addr); + (*dtb_addr) as *mut u8 + } +} \ No newline at end of file diff --git a/driver/src/cpio.rs b/driver/src/cpio.rs index 53722336e..8f487855a 100644 --- a/driver/src/cpio.rs +++ b/driver/src/cpio.rs @@ -1,3 +1,9 @@ +extern crate alloc; + +use alloc::string::String; +use alloc::vec::Vec; +use crate::uart; + // a paraser to read cpio archive #[repr(C, packed)] struct CpioNewcHeader { @@ -63,20 +69,27 @@ impl CpioHandler { } } - pub fn get_current_header_magic(&self) -> &str { + fn get_current_header_magic(&self) -> &str { let cur_header = self.get_current_file_header(); let magic_slice = &cur_header.c_magic; core::str::from_utf8(magic_slice).unwrap() } - pub fn get_current_file_name(&self) -> &str { + pub fn get_current_file_name(&self) -> Option<&str> { let cur_header = self.get_current_file_header(); let namesize = hex_to_u64(&cur_header.c_namesize); let cur_pos = self.cpio_cur_pos as *mut u8; let name_ptr = (cur_pos as u64 + core::mem::size_of::() as u64) as *mut u8; - unsafe { - let name_slice = &core::slice::from_raw_parts(name_ptr, namesize as usize); - core::str::from_utf8(name_slice).unwrap() + let name = unsafe { + core::str::from_utf8_unchecked(core::slice::from_raw_parts( + name_ptr, + (namesize - 1) as usize, + )) + }; + if name == "TRAILER!!!" { + None + } else { + Some(name) } } @@ -114,6 +127,21 @@ impl CpioHandler { pub fn rewind(&mut self) { self.cpio_cur_pos = self.cpio_start; } + + pub fn list_all_files(&mut self) -> Vec { + uart::uart_write_str("Listing all files...\r\n"); + let mut files = Vec::new(); + loop { + if let Some(name) = self.get_current_file_name() { + files.push(String::from(name)); + } else { + break; + } + self.next_file(); + } + self.rewind(); + files + } } fn hex_to_u64(hex: &[u8; 8]) -> u64 { diff --git a/driver/src/lib.rs b/driver/src/lib.rs index dd1a1491e..068cda62f 100644 --- a/driver/src/lib.rs +++ b/driver/src/lib.rs @@ -2,4 +2,5 @@ #![no_std] pub mod uart; pub mod mailbox; -pub mod cpio; \ No newline at end of file +pub mod cpio; +pub mod addr_loader; \ No newline at end of file diff --git a/driver/src/uart.rs b/driver/src/uart.rs index 248c18e8c..7860b4ecb 100644 --- a/driver/src/uart.rs +++ b/driver/src/uart.rs @@ -111,9 +111,9 @@ impl Uart { #[no_mangle] #[inline(never)] -pub unsafe fn uart_write_str(s: &str) { +pub fn uart_write_str(s: &str) { for i in s.bytes() { - write_u8(i); + unsafe {write_u8(i)}; } } @@ -218,3 +218,14 @@ pub fn strncmp(s1: &str, s2: &str, n: usize) -> bool { } true } + +pub fn reboot() { + const PM_PASSWORD: u32 = 0x5a000000; + const PM_RSTC: u32 = 0x3F10001c; + const PM_WDOG: u32 = 0x3F100024; + const PM_RSTC_WRCFG_FULL_RESET: u32 = 0x00000020; + unsafe { + write_volatile(PM_WDOG as *mut u32, PM_PASSWORD | 100); + write_volatile(PM_RSTC as *mut u32, PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); + } +} diff --git a/kernel/src/dtb.rs b/kernel/src/fdt.rs similarity index 100% rename from kernel/src/dtb.rs rename to kernel/src/fdt.rs diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 96b766395..4817f1f81 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -7,20 +7,18 @@ mod allocator; mod bsp; mod cpu; -mod dtb; +mod fdt; mod panic_wait; mod print; extern crate alloc; -use fdt; - +use alloc::vec::Vec; use allocator::MyAllocator; -use core::ptr::addr_of; -use core::ptr::write_volatile; use driver::cpio::CpioHandler; use driver::mailbox; use driver::uart; +use driver::addr_loader; const QEMU_INITRD_START: u64 = 0x8000000; @@ -37,21 +35,12 @@ fn get_initrd_addr(name: &str, data: *const u8, len: usize) -> Option { #[no_mangle] fn kernel_init() -> ! { + let mut dtb_addr = addr_loader::load_dtb_addr(); + // init uart uart::init_uart(); - // load device tree at symbol __dtb_addr - let mut dtb_addr: *mut u64; - let mut dtb_pos: *mut u8; - unsafe { - core::arch::asm!("ldr {}, =__dtb_addr", out(reg) dtb_addr); - dtb_pos = (*dtb_addr) as *mut u8; - } - let dtb_parser = dtb::DtbParser::new(dtb_pos); - - let f = unsafe { fdt::Fdt::from_ptr(dtb_pos as *const u8).unwrap() }; - let s = unsafe { - core::slice::from_raw_parts(dtb_pos.add(dtb_parser.off_dt_strings as usize), 100) - }; + // println!("DTB address: {:#x}", dtb_pos as u64); + let dtb_parser = fdt::DtbParser::new(dtb_addr); let mut in_buf: [u8; 128] = [0; 128]; // find initrd value by dtb traverse @@ -59,79 +48,70 @@ fn kernel_init() -> ! { let mut initrd_start: *mut u8; if let Some(addr) = dtb_parser.traverse(get_initrd_addr) { initrd_start = addr as *mut u8; + println!("Initrd start address: {:#x}", initrd_start as u64) } else { initrd_start = 0 as *mut u8; } - + let mut handler: CpioHandler = CpioHandler::new(initrd_start as *mut u8); loop { - - println!("Initrd start: {:#x}", initrd_start as u64); - print!(">> "); - let inp = uart::getline(&mut in_buf, true); - if inp == "hello" { - println!("Hello World!"); - } else if inp == "help" { - println!("help : print this help menu\r\nhello : print Hello World!\r\nreboot : reboot the device"); - } else if inp == "reboot" { - const PM_PASSWORD: u32 = 0x5a000000; - const PM_RSTC: u32 = 0x3F10001c; - const PM_WDOG: u32 = 0x3F100024; - const PM_RSTC_WRCFG_FULL_RESET: u32 = 0x00000020; - unsafe { - write_volatile(PM_WDOG as *mut u32, PM_PASSWORD | 100); - write_volatile(PM_RSTC as *mut u32, PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); + print!("# "); + let inp = alloc::string::String::from(uart::getline(&mut in_buf, true)); + let cmd = inp.trim().split(' ').collect::>(); + // split the input string + match cmd[0] { + "hello" => println!("Hello World!"), + "help" => println!("help : print this help menu\r\nhello : print Hello World!\r\nreboot : reboot the device"), + "reboot" => { + uart::reboot(); + break; } - break; - } else if inp == "ls" { - let mut handler: CpioHandler = CpioHandler::new(initrd_start as *mut u8); - - loop { - let name = handler.get_current_file_name(); - if name == "TRAILER!!!\0" { - break; + "ls" => { + for name in handler.list_all_files() { + println!("{}", name); } - println!("{}", name); - - handler.next_file(); } - handler.rewind(); - } else if uart::strncmp(inp, "cat", 3) { - let mut handler: CpioHandler = CpioHandler::new(initrd_start as *mut u8); - - let target = &inp[4..]; - loop { - let name = handler.get_current_file_name(); - if name == "TRAILER!!!\0" { - break; + "cat" => { + if cmd.len() < 2 { + println!("Usage: cat "); + continue; } - let l = name.len(); - // if last char is \0, remove it - let name = if name.as_bytes()[l - 1] == 0 { - &name[..l - 1] - } else { - name - }; - if name == target { - println!("File: {}", name); - let content = handler.read_current_file(); - println!("{}", core::str::from_utf8(content).unwrap()); + let target = cmd[1]; + loop { + if let Some(name) = handler.get_current_file_name() { + if name == target { + println!("File: {}", name); + let content = handler.read_current_file(); + println!("{}", core::str::from_utf8(content).unwrap()); + break; + } + handler.next_file(); + } + else { + println!("File not found"); + break; + } } - handler.next_file(); + handler.rewind(); + } + "dtb" => { + unsafe { println!("Start address: {:#x}", dtb_addr as u64) }; + println!("dtb load address: {:#x}", dtb_addr as u64); + println!("dtb pos: {:#x}", unsafe {*(dtb_addr)}); + dtb_parser.parse_struct_block(); + } + "mailbox" => { + println!("Revision: {:#x}", mailbox::get_board_revisioin()); + let (base, size) = mailbox::get_arm_memory(); + println!("ARM memory base address: {:#x}", base); + println!("ARM memory size: {:#x}", size); + } + "" => { + println!(""); + } + _ => { + println!("Command not found\r\n"); } - handler.rewind(); - } else if inp == "dtb" { - dtb_parser.parse_struct_block(); - } else if inp == "mailbox" { - println!("Revision: {:#x}", mailbox::get_board_revisioin()); - let (base, size) = mailbox::get_arm_memory(); - println!("ARM memory base address: {:#x}", base); - println!("ARM memory size: {:#x}", size); - } else { - println!("Command not found\r\n"); - } - unsafe { - uart::uart_nops(); } } panic!() diff --git a/kernel/src/print.rs b/kernel/src/print.rs index 64da973cb..a49c804fe 100644 --- a/kernel/src/print.rs +++ b/kernel/src/print.rs @@ -21,7 +21,7 @@ macro_rules! print { #[macro_export] macro_rules! println { - () => ($crate::print!("\n")); + () => ($crate::print!("\r\n")); ($($arg:tt)*) => ({ $crate::print::_print(format_args_nl!($($arg)*)); }) From 77cea39e79e543e2537edd4c759990bc14f39b4c Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Mon, 8 Apr 2024 17:12:11 +0800 Subject: [PATCH 19/34] New CPIO, KAF is very kawaii! --- Makefile | 9 +- driver/src/cpio.rs | 183 ++++++++++++++++------------ driver/src/uart.rs | 1 - initramfs/catGift.txt | 39 +++++- kernel/src/_arch/aarch64/cpu.rs | 17 +-- kernel/src/_arch/aarch64/cpu/boot.s | 9 ++ kernel/src/main.rs | 36 +++--- 7 files changed, 185 insertions(+), 109 deletions(-) diff --git a/Makefile b/Makefile index a56ea85eb..094876f57 100644 --- a/Makefile +++ b/Makefile @@ -58,15 +58,15 @@ kernel_elf: bootloader_elf: make -C $(BOOTLOADER_PATH) all -kernel_qemu: $(KERNEL_BIN) +kernel_qemu: $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU") $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -initrd $(INITRD_PATH) -dtb $(QEMU_DTB_PATH) -kernel $(KERNEL_BIN) -kernel_gdb: $(KERNEL_BIN) +kernel_gdb: $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU in background") $(EXEC_QEMU) $(QEMU_DEBUG_ARGS) -dtb $(QEMU_DTB_PATH) -kernel $(KERNEL_BIN) -bootloader_qemu:$(BOOTLOADER_BIN) $(KERNEL_BIN) cpio +bootloader_qemu:$(BOOTLOADER_BIN) $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU") $(EXEC_QEMU) $(QEMU_TTY_ARGS) -dtb $(QEMU_DTB_PATH) -kernel $(BOOTLOADER_BIN) -initrd $(INITRD_PATH) @@ -74,7 +74,7 @@ bootloader_gdb: $(BOOTLOADER_BIN) $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU in background") $(EXEC_QEMU) $(QEMU_TTY_DEBUG_ARGS) $(QEMU_DTB_PATH) -kernel $(BOOTLOADER_BIN) -initrd $(INITRD_PATH) -cpio: +cpio: initramfs/* $(call color_header, "Creating initramfs") @cd initramfs && find . | cpio -H newc -o > ../initramfs.cpio @@ -84,3 +84,4 @@ clean: -rm -r target -rm $(KERNEL_BIN) -rm $(BOOTLOADER_BIN) + -rm $(INITRD_PATH) diff --git a/driver/src/cpio.rs b/driver/src/cpio.rs index 8f487855a..7e3deec5b 100644 --- a/driver/src/cpio.rs +++ b/driver/src/cpio.rs @@ -25,125 +25,156 @@ struct CpioNewcHeader { pub struct CpioHandler { cpio_start: *mut CpioNewcHeader, - cpio_cur_pos: *mut CpioNewcHeader, + pub files: CpioIterator, } impl CpioHandler { - // parse cpio in memory, with the start address of cpio - pub fn new(cpio_start: *mut u8) -> CpioHandler { CpioHandler { cpio_start: cpio_start as *mut CpioNewcHeader, - cpio_cur_pos: cpio_start as *mut CpioNewcHeader, + files: CpioIterator::new(&CpioHeaderWrapper::new(cpio_start as *mut CpioNewcHeader)), } } - fn get_current_file_header(&self) -> &CpioNewcHeader { - unsafe { &*self.cpio_cur_pos } + pub fn get_files(&self) -> CpioIterator { + CpioIterator::new(&CpioHeaderWrapper::new(self.cpio_start)) } +} - pub fn is_end(&self) -> bool { - let cur_header = self.get_current_file_header(); - let magic_slice = &cur_header.c_magic; - let magic = core::str::from_utf8(magic_slice).unwrap(); - magic == "TRAILER!!" - } +pub struct CpioIterator { + cur_header: CpioHeaderWrapper, +} - pub fn get_current_file_name_len(&self) -> Option { - if !self.is_end() { - let cur_header = self.get_current_file_header(); - let namesize = hex_to_u64(&cur_header.c_namesize); - Some(namesize as usize) - } else { - None +impl CpioIterator { + fn new(cpio_header: &CpioHeaderWrapper) -> CpioIterator { + CpioIterator { + cur_header: CpioHeaderWrapper::new(cpio_header.header), } } +} - pub fn get_current_file_size(&self) -> Option { - if !self.is_end() { - let cur_header = self.get_current_file_header(); - let filesize = hex_to_u64(&cur_header.c_filesize); - Some(filesize as usize) - } else { - None +impl Iterator for CpioIterator { + type Item = CpioFile; + + fn next(&mut self) -> Option { + if self.cur_header.get_file_name() == "TRAILER!!!" { + return None; } + let file_name = self.cur_header.get_file_name(); + let file_size = self.cur_header.get_file_size(); + let file_content = self.cur_header.get_current_file_content_ptr(); + let file = CpioFile::new(String::from(file_name), file_content, file_size); + self.cur_header = self.cur_header.get_next_file(); + Some(file) } + +} - fn get_current_header_magic(&self) -> &str { - let cur_header = self.get_current_file_header(); - let magic_slice = &cur_header.c_magic; - core::str::from_utf8(magic_slice).unwrap() +struct CpioHeaderWrapper { + header: *mut CpioNewcHeader, +} + +impl CpioHeaderWrapper { + pub fn new(header: *mut CpioNewcHeader) -> CpioHeaderWrapper { + CpioHeaderWrapper { + header, + } } - pub fn get_current_file_name(&self) -> Option<&str> { - let cur_header = self.get_current_file_header(); - let namesize = hex_to_u64(&cur_header.c_namesize); - let cur_pos = self.cpio_cur_pos as *mut u8; - let name_ptr = (cur_pos as u64 + core::mem::size_of::() as u64) as *mut u8; - let name = unsafe { + pub fn get_file_name(&self) -> &str { + let namesize = unsafe {hex_to_u64(&(*self.header).c_namesize)}; + let name_ptr = (self.header as u64 + core::mem::size_of::() as u64) as *mut u8; + unsafe { core::str::from_utf8_unchecked(core::slice::from_raw_parts( name_ptr, (namesize - 1) as usize, )) - }; - if name == "TRAILER!!!" { - None - } else { - Some(name) } } - - pub fn read_current_file(&self) -> &[u8] { - let cur_header = self.get_current_file_header(); - let filesize = hex_to_u64(&cur_header.c_filesize); - let cur_pos = self.cpio_cur_pos as *mut u8; - let name_size = hex_to_u64(&cur_header.c_namesize); - let mut offset = core::mem::size_of::() as u64 + name_size + cur_pos as u64; - if offset % 4 != 0 { - offset += 4 - offset % 4; - } - let file_ptr = offset as *mut u8; - unsafe { core::slice::from_raw_parts(file_ptr, filesize as usize) } + pub fn get_file_size(&self) -> usize { + let filesize = unsafe {hex_to_u64(&(*self.header).c_filesize)}; + filesize as usize } - - pub fn next_file(&mut self) { - let mut cur_pos = self.cpio_cur_pos as *mut u8; - let cur_header = self.get_current_file_header(); - let mut offset = core::mem::size_of::() as u64; - let namesize = hex_to_u64(&cur_header.c_namesize); + pub fn get_next_file(&mut self) -> CpioHeaderWrapper { + let mut offset = core::mem::size_of::() as usize; + let namesize = unsafe {hex_to_u64(&(*self.header).c_namesize)} as usize; offset += namesize; if offset % 4 != 0 { offset += 4 - offset % 4; } - let filesize = hex_to_u64(&cur_header.c_filesize); + let filesize = unsafe {hex_to_u64(&(*self.header).c_filesize)} as usize; offset += filesize; if offset % 4 != 0 { offset += 4 - offset % 4; } - cur_pos = (cur_pos as u64 + offset) as *mut u8; - self.cpio_cur_pos = cur_pos as *mut CpioNewcHeader; + self.header = ((self.header as u64) + offset as u64) as *mut CpioNewcHeader; + CpioHeaderWrapper::new(self.header) } - pub fn rewind(&mut self) { - self.cpio_cur_pos = self.cpio_start; + pub fn get_current_file_header(&self) -> *mut CpioNewcHeader{ + self.header } - pub fn list_all_files(&mut self) -> Vec { - uart::uart_write_str("Listing all files...\r\n"); - let mut files = Vec::new(); - loop { - if let Some(name) = self.get_current_file_name() { - files.push(String::from(name)); - } else { - break; - } - self.next_file(); + pub fn get_current_file_name_len(&self) -> usize { + let namesize = unsafe {hex_to_u64(&(*self.header).c_namesize)}; + namesize as usize + } + + pub fn get_current_file_content_ptr(&self) -> *const u8 { + let cur_pos = self.header as *mut u8; + let name_size = self.get_current_file_name_len(); + let mut offset = (core::mem::size_of::()+ name_size) as u64 + cur_pos as u64 ; + if offset % 4 != 0 { + offset += 4 - offset % 4; + } + let file_ptr = offset as *mut u8; + file_ptr + } + + pub fn get_current_file_size(&self) -> usize { + (unsafe {hex_to_u64(&(*self.header).c_filesize)} as usize) + } +} + +pub struct CpioFile { + name: String, + content: *const u8, + size: usize, + pos: usize, +} + +impl CpioFile { + pub fn new(name: String, content: *const u8, size: usize) -> CpioFile { + CpioFile { + name, + content, + size, + pos: 0, } - self.rewind(); - files } + + pub fn read(&mut self, max_size: usize) -> &[u8] { + let mut len = max_size; + if self.pos + len > self.size { + len = self.size - self.pos; + } + let slice = unsafe {core::slice::from_raw_parts(self.content.add(self.pos), len)}; + self.pos += len; + slice + } + + pub fn get_name(&self) -> &str { + &self.name + } + + pub fn get_size(&self) -> usize { + self.size + } + } + + fn hex_to_u64(hex: &[u8; 8]) -> u64 { let mut result: u64 = 0; for i in 0..8 { diff --git a/driver/src/uart.rs b/driver/src/uart.rs index 7860b4ecb..8730988c9 100644 --- a/driver/src/uart.rs +++ b/driver/src/uart.rs @@ -73,7 +73,6 @@ pub fn init_uart() { write_volatile(AUX_MU_CNTL_REG as *mut u32, 3); } } - pub struct Uart; use core::fmt::{self, Write}; diff --git a/initramfs/catGift.txt b/initramfs/catGift.txt index ebc99f8d7..3cba9a32c 100644 --- a/initramfs/catGift.txt +++ b/initramfs/catGift.txt @@ -1 +1,38 @@ -貓咪禮物 \ No newline at end of file +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift +catGift diff --git a/kernel/src/_arch/aarch64/cpu.rs b/kernel/src/_arch/aarch64/cpu.rs index 8b5266023..7c0b14ee8 100644 --- a/kernel/src/_arch/aarch64/cpu.rs +++ b/kernel/src/_arch/aarch64/cpu.rs @@ -11,14 +11,9 @@ pub fn wait_forever() -> ! { } } -/* -const int PM_RSTC = 0x2010001c; -const int PM_WDOG = 0x20100024; -const int PM_PASSWORD = 0x5a000000; -const int PM_RSTC_WRCFG_FULL_RESET = 0x00000020; - -PUT32(PM_WDOG, PM_PASSWORD | 1); // timeout = 1/16th of a second? (whatever) -PUT32(PM_RSTC, PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET); -*/ - - +// mode transition +pub fn el1_to_el0() { + unsafe { + asm::eret(); + } +} diff --git a/kernel/src/_arch/aarch64/cpu/boot.s b/kernel/src/_arch/aarch64/cpu/boot.s index a9b715476..78a4e0740 100644 --- a/kernel/src/_arch/aarch64/cpu/boot.s +++ b/kernel/src/_arch/aarch64/cpu/boot.s @@ -25,6 +25,7 @@ _start: b.ne .L_parking_loop // If execution reaches here, it is the boot core. + bl from_el2_to_el1 // Initialize DRAM. ADR_REL x0, __bss_start @@ -50,6 +51,14 @@ _start: wfe b .L_parking_loop +from_el2_to_el1: + mov x0, (1 << 31) // EL1 uses aarch64 + msr hcr_el2, x0 + mov x0, 0x3c5 // EL1h (SPSel = 1) with interrupt disabled + msr spsr_el2, x0 + msr elr_el2, lr + eret // return to EL1 + .size _start, . - _start .type _start, function .global _start diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 4817f1f81..fc3c9e012 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -67,32 +67,32 @@ fn kernel_init() -> ! { break; } "ls" => { - for name in handler.list_all_files() { - println!("{}", name); + for file in handler.get_files() { + println!("{}", file.get_name()); } } "cat" => { if cmd.len() < 2 { - println!("Usage: cat "); + println!("Usage: cat "); continue; } - let target = cmd[1]; - loop { - if let Some(name) = handler.get_current_file_name() { - if name == target { - println!("File: {}", name); - let content = handler.read_current_file(); - println!("{}", core::str::from_utf8(content).unwrap()); + let mut file = handler.get_files().find(|f| f.get_name() == cmd[1]); + if let Some(mut f) = file { + println!("File size: {}", f.get_size()); + loop { + let data = f.read(32); + if data.len() == 0 { break; } - handler.next_file(); - } - else { - println!("File not found"); - break; + for i in data { + unsafe { + uart::write_u8(*i); + } + } } + } else { + println!("File not found"); } - handler.rewind(); } "dtb" => { unsafe { println!("Start address: {:#x}", dtb_addr as u64) }; @@ -105,6 +105,9 @@ fn kernel_init() -> ! { let (base, size) = mailbox::get_arm_memory(); println!("ARM memory base address: {:#x}", base); println!("ARM memory size: {:#x}", size); + } + "exec" => { + } "" => { println!(""); @@ -114,5 +117,6 @@ fn kernel_init() -> ! { } } } + panic!() } From 4b1ed009ce59d5108104d147c94e0ed7c7dd3727 Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Wed, 10 Apr 2024 00:46:47 +0800 Subject: [PATCH 20/34] New exception handler and user program --- Makefile | 18 +++- bootloader/src/_arch/aarch64/cpu/boot.s | 8 +- bootloader/src/main.rs | 3 +- driver/src/addr_loader.rs | 1 - driver/src/lib.rs | 1 - driver/src/uart.rs | 1 - initramfs/prog | Bin 0 -> 24 bytes .../src/_arch/aarch64/cpu/exception_handler.s | 90 ++++++++++++++++++ {driver/src => kernel/src/fs}/cpio.rs | 6 -- kernel/src/fs/mod.rs | 1 + kernel/src/main.rs | 15 ++- kernel/src/print.rs | 1 + kernel/src/shell.rs | 0 userprog/prog/Makefile | 26 +++++ userprog/prog/src/prog.ld | 5 + userprog/prog/src/prog.s | 12 +++ utils/README.md | 3 - utils/format.mk | 12 +++ utils/os.mk | 9 ++ 19 files changed, 181 insertions(+), 31 deletions(-) create mode 100644 initramfs/prog create mode 100644 kernel/src/_arch/aarch64/cpu/exception_handler.s rename {driver/src => kernel/src/fs}/cpio.rs (96%) create mode 100644 kernel/src/fs/mod.rs create mode 100644 kernel/src/shell.rs create mode 100644 userprog/prog/Makefile create mode 100644 userprog/prog/src/prog.ld create mode 100644 userprog/prog/src/prog.s delete mode 100644 utils/README.md create mode 100644 utils/format.mk create mode 100644 utils/os.mk diff --git a/Makefile b/Makefile index 094876f57..1a79253d2 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,9 @@ TARGET = aarch64-unknown-none-softfloat KERNEL_BIN = kernel8.img BOOTLOADER_BIN = bootloader.img +include ./utils/format.mk +include ./utils/os.mk + # QEMU QEMU_BINARY = qemu-system-aarch64 QEMU_MACHINE_TYPE = raspi3b @@ -28,6 +31,9 @@ INITRD_PATH = $(shell pwd)/initramfs.cpio KERNEL_ELF = target/$(TARGET)/release/kernel BOOTLOADER_ELF = target/$(TARGET)/release/bootloader +USER_PROG_IMG = userprog/prog/target/prog +USER_PROG = userprog/prog + OBJCOPY_CMD = rust-objcopy \ --strip-all \ -O binary @@ -38,7 +44,7 @@ all: $(KERNEL_BIN) $(BOOTLOADER_BIN) $(KERNEL_BIN): kernel_elf $(call color_header, "Generating stripped binary") - @$(OBJCOPY_CMD) $(KERNEL_ELF) $(KERNEL_BIN) + $(OBJCOPY_CMD) $(KERNEL_ELF) $(KERNEL_BIN) $(call color_progress_prefix, "Name") @echo $(KERNEL_BIN) $(call color_progress_prefix, "Size") @@ -46,7 +52,7 @@ $(KERNEL_BIN): kernel_elf $(BOOTLOADER_BIN): bootloader_elf $(call color_header, "Generating stripped binary") - @$(OBJCOPY_CMD) $(BOOTLOADER_ELF) $(BOOTLOADER_BIN) + $(OBJCOPY_CMD) $(BOOTLOADER_ELF) $(BOOTLOADER_BIN) $(call color_progress_prefix, "Name") @echo $(BOOTLOADER_BIN) $(call color_progress_prefix, "Size") @@ -74,9 +80,13 @@ bootloader_gdb: $(BOOTLOADER_BIN) $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU in background") $(EXEC_QEMU) $(QEMU_TTY_DEBUG_ARGS) $(QEMU_DTB_PATH) -kernel $(BOOTLOADER_BIN) -initrd $(INITRD_PATH) -cpio: initramfs/* +$(USER_PROG_IMG): $(USER_PROG)/src/* + make -C userprog all + +cpio: initramfs/* $(USER_PROG_IMG) $(call color_header, "Creating initramfs") - @cd initramfs && find . | cpio -H newc -o > ../initramfs.cpio + cp $(USER_PROG_IMG) initramfs/ + cd initramfs && find . | cpio -H newc -o > ../initramfs.cpio clean: make -C $(KERNEL_PATH) clean diff --git a/bootloader/src/_arch/aarch64/cpu/boot.s b/bootloader/src/_arch/aarch64/cpu/boot.s index 86378bb5d..a27fb4827 100644 --- a/bootloader/src/_arch/aarch64/cpu/boot.s +++ b/bootloader/src/_arch/aarch64/cpu/boot.s @@ -14,8 +14,8 @@ //------------------------------------------------------------------------------ _start: // Save the address of the device tree blob. - ldr x1, =__dtb_addr - str x0, [x1] + ; ldr x1, =__dtb_addr + ; str x0, [x1] // Only proceed on the boot core. Park it otherwise. mrs x0, MPIDR_EL1 @@ -66,8 +66,8 @@ _start: bl _start_rust // restore the address of the device tree blob. - ldr x1, =__dtb_addr - ldr x0, [x1] + ; ldr x1, =__dtb_addr + ; ldr x0, [x1] // jump to 0x80000 ldr x1, =0x80000 diff --git a/bootloader/src/main.rs b/bootloader/src/main.rs index 23b2d9e70..261bfd17f 100644 --- a/bootloader/src/main.rs +++ b/bootloader/src/main.rs @@ -11,7 +11,6 @@ use core::{ ptr::{read_volatile, write_volatile}, usize, }; - use driver::uart; const KERNEL_LOAD_ADDR: u64 = 0x80000; @@ -36,7 +35,7 @@ unsafe fn bootloader(){ let mut kernel_size: u32 = 0; // read kernel size (4 bytes) from uart - uart::read(&mut kernel_size as *mut u32 as *mut u8 /*(uint8_t)(&kernel_size) */, 4); + uart::read(&mut kernel_size as *mut u32 as *mut u8 , 4); uart::uart_write_str("Kernel size: "); uart::print_hex(kernel_size); uart::uart_write_str("\r\n"); diff --git a/driver/src/addr_loader.rs b/driver/src/addr_loader.rs index 98caddd4b..c6f50daa1 100644 --- a/driver/src/addr_loader.rs +++ b/driver/src/addr_loader.rs @@ -1,5 +1,4 @@ - pub fn load_dtb_addr() -> *mut u8 { let dtb_addr: *mut u64; unsafe { diff --git a/driver/src/lib.rs b/driver/src/lib.rs index 068cda62f..b75ff74db 100644 --- a/driver/src/lib.rs +++ b/driver/src/lib.rs @@ -2,5 +2,4 @@ #![no_std] pub mod uart; pub mod mailbox; -pub mod cpio; pub mod addr_loader; \ No newline at end of file diff --git a/driver/src/uart.rs b/driver/src/uart.rs index 8730988c9..e65f05410 100644 --- a/driver/src/uart.rs +++ b/driver/src/uart.rs @@ -136,7 +136,6 @@ pub fn getline(s: &mut [u8; 128], is_echo: bool) -> &str { } None => {} } - asm!("nop"); } } core::str::from_utf8(&s[0..ptr]).unwrap() diff --git a/initramfs/prog b/initramfs/prog new file mode 100644 index 0000000000000000000000000000000000000000..1adf648a4c1b9d2d1b5e9fa08b84e52ef2fafc78 GIT binary patch literal 24 gcmZQzXt>0{!Z4AMf#Hh02*bzK|Nn CpioHandler { CpioHandler { cpio_start: cpio_start as *mut CpioNewcHeader, - files: CpioIterator::new(&CpioHeaderWrapper::new(cpio_start as *mut CpioNewcHeader)), } } @@ -173,8 +169,6 @@ impl CpioFile { } - - fn hex_to_u64(hex: &[u8; 8]) -> u64 { let mut result: u64 = 0; for i in 0..8 { diff --git a/kernel/src/fs/mod.rs b/kernel/src/fs/mod.rs new file mode 100644 index 000000000..234dfef2b --- /dev/null +++ b/kernel/src/fs/mod.rs @@ -0,0 +1 @@ +pub mod cpio; \ No newline at end of file diff --git a/kernel/src/main.rs b/kernel/src/main.rs index fc3c9e012..273a10809 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -10,18 +10,17 @@ mod cpu; mod fdt; mod panic_wait; mod print; +mod fs; extern crate alloc; use alloc::vec::Vec; use allocator::MyAllocator; -use driver::cpio::CpioHandler; +use fs::cpio::CpioHandler; use driver::mailbox; use driver::uart; use driver::addr_loader; -const QEMU_INITRD_START: u64 = 0x8000000; - #[global_allocator] static mut ALLOCATOR: MyAllocator = MyAllocator::new(); @@ -38,7 +37,7 @@ fn kernel_init() -> ! { let mut dtb_addr = addr_loader::load_dtb_addr(); // init uart uart::init_uart(); - + uart::uart_write_str("Kernel started\r\n"); // println!("DTB address: {:#x}", dtb_pos as u64); let dtb_parser = fdt::DtbParser::new(dtb_addr); @@ -55,7 +54,7 @@ fn kernel_init() -> ! { let mut handler: CpioHandler = CpioHandler::new(initrd_start as *mut u8); loop { - print!("# "); + print!("meow>> "); let inp = alloc::string::String::from(uart::getline(&mut in_buf, true)); let cmd = inp.trim().split(' ').collect::>(); // split the input string @@ -107,11 +106,9 @@ fn kernel_init() -> ! { println!("ARM memory size: {:#x}", size); } "exec" => { - - } - "" => { - println!(""); + } + "" => {} _ => { println!("Command not found\r\n"); } diff --git a/kernel/src/print.rs b/kernel/src/print.rs index a49c804fe..77712ddc2 100644 --- a/kernel/src/print.rs +++ b/kernel/src/print.rs @@ -24,6 +24,7 @@ macro_rules! println { () => ($crate::print!("\r\n")); ($($arg:tt)*) => ({ $crate::print::_print(format_args_nl!($($arg)*)); + $crate::print!("\r") }) } diff --git a/kernel/src/shell.rs b/kernel/src/shell.rs new file mode 100644 index 000000000..e69de29bb diff --git a/userprog/prog/Makefile b/userprog/prog/Makefile new file mode 100644 index 000000000..c320e51cc --- /dev/null +++ b/userprog/prog/Makefile @@ -0,0 +1,26 @@ +# This Makefile is used to compile the user program + +PROG_IMAGE = target/prog +PROG_ELF = target/prog.elf +PROG_SRC = src/prog.s +LD = src/prog.ld +SRC = $(PROG_SRC) $(LD) +CC = aarch64-linux-gnu-gcc + +.PHONY: all + +all: $(PROG_IMAGE) + +$(PROG_IMAGE): $(PROG_ELF) + @echo "Generating stripped binary" + rust-objcopy --strip-all -O binary $(PROG_ELF) $(PROG_IMAGE) + @echo "Name" + @echo $(PROG_IMAGE) + @echo "Size" + @du -h $(PROG_IMAGE) + +$(PROG_ELF): $(SRC) + $(CC) -c $(PROG_SRC) -o $(PROG_ELF) -T $(LD) + +clean: + rm -f target/* diff --git a/userprog/prog/src/prog.ld b/userprog/prog/src/prog.ld new file mode 100644 index 000000000..2be410356 --- /dev/null +++ b/userprog/prog/src/prog.ld @@ -0,0 +1,5 @@ +/* a simple linker script for user program */ +SECTIONS +{ + .text : { *(.text) } +} \ No newline at end of file diff --git a/userprog/prog/src/prog.s b/userprog/prog/src/prog.s new file mode 100644 index 000000000..14b62bb68 --- /dev/null +++ b/userprog/prog/src/prog.s @@ -0,0 +1,12 @@ + +.section ".text" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b diff --git a/utils/README.md b/utils/README.md deleted file mode 100644 index a3a72e49c..000000000 --- a/utils/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Kernel Sender - -A python script to send kernel. \ No newline at end of file diff --git a/utils/format.mk b/utils/format.mk new file mode 100644 index 000000000..e392304ad --- /dev/null +++ b/utils/format.mk @@ -0,0 +1,12 @@ +define color_header + @tput setaf 6 2> /dev/null || true + @printf '\n%s\n' $(1) + @tput sgr0 2> /dev/null || true +endef + +define color_progress_prefix + @tput setaf 2 2> /dev/null || true + @tput bold 2 2> /dev/null || true + @printf '%12s ' $(1) + @tput sgr0 2> /dev/null || true +endef diff --git a/utils/os.mk b/utils/os.mk new file mode 100644 index 000000000..90172f775 --- /dev/null +++ b/utils/os.mk @@ -0,0 +1,9 @@ +ifeq ($(shell uname -s),Linux) + DU_ARGUMENTS = --block-size=1024 --apparent-size +else ifeq ($(shell uname -s),Darwin) + DU_ARGUMENTS = -k -A +endif + +define disk_usage_KiB + @printf '%s KiB\n' `du $(DU_ARGUMENTS) $(1) | cut -f1` +endef From a7889f7318c09d8e19cd2d0def39808ba2dec9a3 Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Thu, 11 Apr 2024 20:57:33 +0800 Subject: [PATCH 21/34] Exception --- .gitignore | 3 +- .initgdb | 2 - Makefile | 4 +- driver/src/addr_loader.rs | 10 +++- kernel/src/_arch/aarch64/cpu/boot.rs | 4 ++ kernel/src/_arch/aarch64/cpu/boot.s | 4 ++ .../cpu/{exception_handler.s => exception.s} | 9 +-- kernel/src/allocator/memory.rs | 2 +- kernel/src/allocator/mod.rs | 5 +- kernel/src/bsp/raspberrypi/kernel.ld | 11 ++++ kernel/src/main.rs | 56 ++++++++++++++++++- kernel/src/panic_wait.rs | 3 +- userprog/prog/src/prog.s | 1 + 13 files changed, 98 insertions(+), 16 deletions(-) delete mode 100644 .initgdb rename kernel/src/_arch/aarch64/cpu/{exception_handler.s => exception.s} (94%) diff --git a/.gitignore b/.gitignore index b4d17f6b6..3fd6c8167 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ rootfs .gdbinit initramfs.cpio *.dtb -*.txt \ No newline at end of file +*.txt +.idea \ No newline at end of file diff --git a/.initgdb b/.initgdb deleted file mode 100644 index 65ac531dc..000000000 --- a/.initgdb +++ /dev/null @@ -1,2 +0,0 @@ -file target/aarch64-unknown-none-softfloat/release/bootloader -target remote :1234 diff --git a/Makefile b/Makefile index 1a79253d2..fa5d34714 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ kernel_qemu: $(KERNEL_BIN) cpio kernel_gdb: $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU in background") - $(EXEC_QEMU) $(QEMU_DEBUG_ARGS) -dtb $(QEMU_DTB_PATH) -kernel $(KERNEL_BIN) + $(EXEC_QEMU) $(QEMU_DEBUG_ARGS) -initrd $(INITRD_PATH) -dtb $(QEMU_DTB_PATH) -kernel $(KERNEL_BIN) bootloader_qemu:$(BOOTLOADER_BIN) $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU") @@ -81,7 +81,7 @@ bootloader_gdb: $(BOOTLOADER_BIN) $(KERNEL_BIN) cpio $(EXEC_QEMU) $(QEMU_TTY_DEBUG_ARGS) $(QEMU_DTB_PATH) -kernel $(BOOTLOADER_BIN) -initrd $(INITRD_PATH) $(USER_PROG_IMG): $(USER_PROG)/src/* - make -C userprog all + make -C $(USER_PROG) all cpio: initramfs/* $(USER_PROG_IMG) $(call color_header, "Creating initramfs") diff --git a/driver/src/addr_loader.rs b/driver/src/addr_loader.rs index c6f50daa1..ef2ac0c19 100644 --- a/driver/src/addr_loader.rs +++ b/driver/src/addr_loader.rs @@ -5,4 +5,12 @@ pub fn load_dtb_addr() -> *mut u8 { core::arch::asm!("ldr {}, =__dtb_addr", out(reg) dtb_addr); (*dtb_addr) as *mut u8 } -} \ No newline at end of file +} + +pub fn usr_load_prog_base() -> *mut u8 { + let addr: *mut u64; + unsafe { + core::arch::asm!("ldr {}, =__usr_prog_start", out(reg) addr); + addr as *mut u8 + } +} diff --git a/kernel/src/_arch/aarch64/cpu/boot.rs b/kernel/src/_arch/aarch64/cpu/boot.rs index 699482d4d..7ba9ee0ac 100644 --- a/kernel/src/_arch/aarch64/cpu/boot.rs +++ b/kernel/src/_arch/aarch64/cpu/boot.rs @@ -6,6 +6,10 @@ global_asm!( CONST_CORE_ID_MASK = const 0b11 ); +global_asm!( + include_str!("exception.s") +); + // mod uart; #[no_mangle] diff --git a/kernel/src/_arch/aarch64/cpu/boot.s b/kernel/src/_arch/aarch64/cpu/boot.s index 78a4e0740..615041f94 100644 --- a/kernel/src/_arch/aarch64/cpu/boot.s +++ b/kernel/src/_arch/aarch64/cpu/boot.s @@ -24,6 +24,10 @@ _start: cmp x0, x1 b.ne .L_parking_loop +set_exception_vector_table: + adr x0, exception_vector_table + msr vbar_el1, x0 + // If execution reaches here, it is the boot core. bl from_el2_to_el1 diff --git a/kernel/src/_arch/aarch64/cpu/exception_handler.s b/kernel/src/_arch/aarch64/cpu/exception.s similarity index 94% rename from kernel/src/_arch/aarch64/cpu/exception_handler.s rename to kernel/src/_arch/aarch64/cpu/exception.s index 7daf0084e..d2c8b573f 100644 --- a/kernel/src/_arch/aarch64/cpu/exception_handler.s +++ b/kernel/src/_arch/aarch64/cpu/exception.s @@ -1,4 +1,5 @@ // save general registers to stack + .macro save_all sub sp, sp, 32 * 8 stp x0, x1, [sp ,16 * 0] @@ -40,9 +41,10 @@ add sp, sp, 32 * 8 .endm +.section .text.exception exception_handler: save_all - bl exception_entry + bl rust_exception_handler load_all eret @@ -85,6 +87,5 @@ exception_vector_table: b exception_handler .align 7 -set_exception_vector_table: - adr x0, exception_vector_table - msr vbar_el1, x0 +exception_entry: + nop \ No newline at end of file diff --git a/kernel/src/allocator/memory.rs b/kernel/src/allocator/memory.rs index 9cdda6553..e151505e3 100644 --- a/kernel/src/allocator/memory.rs +++ b/kernel/src/allocator/memory.rs @@ -28,4 +28,4 @@ pub fn alloc(layout: Layout, memory: &mut HeapMemory) -> *mut u8 { } memory.current = new_current + size; new_current as *mut u8 -} +} \ No newline at end of file diff --git a/kernel/src/allocator/mod.rs b/kernel/src/allocator/mod.rs index bb5ec979b..ffeade152 100644 --- a/kernel/src/allocator/mod.rs +++ b/kernel/src/allocator/mod.rs @@ -1,5 +1,5 @@ -const HEAP_SIZE: usize = 1024 * 1024; // 1 MB -const HEAP_START: usize = 0x210000; +const HEAP_SIZE: usize = 1024 * 1024 * 10; // 10 MB +const HEAP_START: usize = 0x200000; use core::cell::UnsafeCell; @@ -33,3 +33,4 @@ unsafe impl GlobalAlloc for MyAllocator { // Implementation for dealloc } } + diff --git a/kernel/src/bsp/raspberrypi/kernel.ld b/kernel/src/bsp/raspberrypi/kernel.ld index 260cb112e..fd53d68b5 100644 --- a/kernel/src/bsp/raspberrypi/kernel.ld +++ b/kernel/src/bsp/raspberrypi/kernel.ld @@ -29,5 +29,16 @@ SECTIONS . = ALIGN(16); __bss_end_exclusive = .; } + . = ALIGN(8); + .usr_prog(NOLOAD): { + __usr_prog_start = .; + . = . + 0x1000; + __usr_prog_end = .; + } __dtb_addr = .; + + /* . = ALIGN(8); + heap_base = .; + . = . + 0x200000; + heap_limit = .; */ } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 273a10809..fcedae5b4 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -32,15 +32,27 @@ fn get_initrd_addr(name: &str, data: *const u8, len: usize) -> Option { } } +#[no_mangle] +#[inline(never)] +fn exec(addr: extern "C" fn() -> !) { + addr(); +} + +#[no_mangle] +#[inline(never)] +fn boink() { + unsafe{core::arch::asm!("nop")}; +} + #[no_mangle] fn kernel_init() -> ! { let mut dtb_addr = addr_loader::load_dtb_addr(); // init uart uart::init_uart(); + println!("dtb address: {:#x}", dtb_addr as u64); uart::uart_write_str("Kernel started\r\n"); - // println!("DTB address: {:#x}", dtb_pos as u64); - let dtb_parser = fdt::DtbParser::new(dtb_addr); + let dtb_parser = fdt::DtbParser::new(dtb_addr); let mut in_buf: [u8; 128] = [0; 128]; // find initrd value by dtb traverse @@ -53,6 +65,11 @@ fn kernel_init() -> ! { } let mut handler: CpioHandler = CpioHandler::new(initrd_start as *mut u8); + + // load symbol address usr_load_prog_base + let usr_load_prog_base = addr_loader::usr_load_prog_base(); + println!("usr_load_prog_base: {:#x}", usr_load_prog_base as u64); + loop { print!("meow>> "); let inp = alloc::string::String::from(uart::getline(&mut in_buf, true)); @@ -106,7 +123,36 @@ fn kernel_init() -> ! { println!("ARM memory size: {:#x}", size); } "exec" => { + boink(); + if cmd.len() < 2 { + println!("Usage: exec "); + continue; + } + let mut file = handler.get_files().find(|f| { + println!("{} {}", f.get_name(), cmd[1]); + f.get_name() == cmd[1]} + ); + boink(); + if let Some(mut f) = file { + let file_size = f.get_size(); + println!("File size: {}", file_size); + let mut data = f.read(file_size); + unsafe { + let mut addr = usr_load_prog_base as *mut u8; + for i in data { + *addr = *i; + addr = addr.add(1); + } + println!(); + let func: extern "C" fn() -> ! = core::mem::transmute(usr_load_prog_base); + boink(); + println!("Jump to user program at {:#x}", func as u64); + exec(func); + } + } else { + println!("File not found"); + } } "" => {} _ => { @@ -117,3 +163,9 @@ fn kernel_init() -> ! { panic!() } + +#[no_mangle] +fn rust_exception_handler() +{ + println!("You have an exception!"); +} diff --git a/kernel/src/panic_wait.rs b/kernel/src/panic_wait.rs index c297b7a74..43af6bfbf 100644 --- a/kernel/src/panic_wait.rs +++ b/kernel/src/panic_wait.rs @@ -1,7 +1,8 @@ -use crate::cpu; +use crate::{cpu}; use core::panic::PanicInfo; #[panic_handler] fn panic(_info: &PanicInfo) -> ! { + crate::println!("Kernel panic: {}", _info); cpu::wait_forever() } diff --git a/userprog/prog/src/prog.s b/userprog/prog/src/prog.s index 14b62bb68..363ae06ae 100644 --- a/userprog/prog/src/prog.s +++ b/userprog/prog/src/prog.s @@ -10,3 +10,4 @@ _start: blt 1b 1: b 1b + \ No newline at end of file From 523117af77cbe7c229fb25dbeb93aac807aa0a5d Mon Sep 17 00:00:00 2001 From: cfmc30 Date: Thu, 25 Apr 2024 02:01:33 +0800 Subject: [PATCH 22/34] Adv timer!, KAF, kawaii! --- .gitignore | 3 +- Makefile | 2 +- bootloader/src/main.rs | 2 +- driver/src/uart.rs | 189 ++++++++++++++++-- initramfs/prog | Bin 24 -> 0 bytes kernel/Cargo.toml | 1 - kernel/src/_arch/aarch64/cpu.rs | 8 - kernel/src/_arch/aarch64/cpu/boot.rs | 2 +- kernel/src/_arch/aarch64/cpu/boot.s | 13 +- .../aarch64/cpu/{exception.s => interrupt.s} | 66 ++++-- kernel/src/allocator/memory.rs | 2 - kernel/src/cpu.rs | 1 - kernel/src/interrupt/mod.rs | 86 ++++++++ kernel/src/main.rs | 133 ++++++++---- kernel/src/timer.rs | 151 ++++++++++++++ userprog/prog/src/prog.s | 18 +- 16 files changed, 573 insertions(+), 104 deletions(-) delete mode 100644 initramfs/prog rename kernel/src/_arch/aarch64/cpu/{exception.s => interrupt.s} (69%) create mode 100644 kernel/src/interrupt/mod.rs create mode 100644 kernel/src/timer.rs diff --git a/.gitignore b/.gitignore index 3fd6c8167..8aa8a46a9 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ rootfs initramfs.cpio *.dtb *.txt -.idea \ No newline at end of file +.idea +initramfs/prog diff --git a/Makefile b/Makefile index fa5d34714..3e4cb67b3 100644 --- a/Makefile +++ b/Makefile @@ -80,7 +80,7 @@ bootloader_gdb: $(BOOTLOADER_BIN) $(KERNEL_BIN) cpio $(call color_header, "Launching QEMU in background") $(EXEC_QEMU) $(QEMU_TTY_DEBUG_ARGS) $(QEMU_DTB_PATH) -kernel $(BOOTLOADER_BIN) -initrd $(INITRD_PATH) -$(USER_PROG_IMG): $(USER_PROG)/src/* +$(USER_PROG_IMG): make -C $(USER_PROG) all cpio: initramfs/* $(USER_PROG_IMG) diff --git a/bootloader/src/main.rs b/bootloader/src/main.rs index 261bfd17f..bd9ab3452 100644 --- a/bootloader/src/main.rs +++ b/bootloader/src/main.rs @@ -20,7 +20,7 @@ const KERNEL_LOAD_ADDR: u64 = 0x80000; #[no_mangle] unsafe fn bootloader(){ // initialize uart - uart::init_uart(); + uart::init_uart(false); uart::uart_write_str("Bootloader started\r\n"); // print current pc value diff --git a/driver/src/uart.rs b/driver/src/uart.rs index e65f05410..901933301 100644 --- a/driver/src/uart.rs +++ b/driver/src/uart.rs @@ -1,18 +1,19 @@ use core::arch::asm; +use core::u32; use core::{ ptr::{read_volatile, write_volatile}, usize, }; -const AUXENB: u32 = 0x3F215004; -const AUX_MU_CNTL_REG: u32 = 0x3F215060; -const AUX_MU_IER_REG: u32 = 0x3F215044; -const AUX_MU_LCR_REG: u32 = 0x3F21504C; -const AUX_MU_MCR_REG: u32 = 0x3F215050; -const AUX_MU_BAUD_REG: u32 = 0x3F215068; -const AUX_MU_IIR_REG: u32 = 0x3F215048; -const AUX_MU_IO_REG: u32 = 0x3F215040; -const AUX_MU_LSR_REG: u32 = 0x3F215054; +pub const AUXENB: u32 = 0x3F215004; +pub const AUX_MU_CNTL_REG: u32 = 0x3F215060; +pub const AUX_MU_IER_REG: u32 = 0x3F215044; +pub const AUX_MU_LCR_REG: u32 = 0x3F21504C; +pub const AUX_MU_MCR_REG: u32 = 0x3F215050; +pub const AUX_MU_BAUD_REG: u32 = 0x3F215068; +pub const AUX_MU_IIR_REG: u32 = 0x3F215048; +pub const AUX_MU_IO_REG: u32 = 0x3F215040; +pub const AUX_MU_LSR_REG: u32 = 0x3F215054; const GPFSEL_BASE: u32 = 0x3F200000; const GPFSEL0: u32 = 0x3F200000; @@ -22,10 +23,154 @@ const GPPUD: u32 = 0x3F200094; const GPPUDCLK0: u32 = 0x3F200098; const GPPUDCLK1: u32 = 0x3F20009C; +struct RingBuffer { + buffer: [u8; 1024], + head: usize, + tail: usize, +} + +impl RingBuffer{ + pub fn new() -> RingBuffer { + RingBuffer { + buffer: [0; 1024], + head: 0, + tail: 0, + } + } + + pub fn write(&mut self, c: u8) { + self.buffer[self.head] = c; + self.head = (self.head + 1) % 1024; + } + + pub fn read(&mut self) -> Option { + if self.head == self.tail { + None + } else { + let c = self.buffer[self.tail]; + self.tail = (self.tail + 1) % 1024; + Some(c) + } + } + + pub fn is_empty(&self) -> bool { + self.head == self.tail + } + + pub fn is_full(&self) -> bool { + (self.head + 1) % 1024 == self.tail + } +} + +static mut READ_RING_BUFFER: RingBuffer = RingBuffer { + buffer: [0; 1024], + head: 0, + tail: 0, +}; + +static mut WRITE_RING_BUFFER: RingBuffer = RingBuffer { + buffer: [0; 1024], + head: 0, + tail: 0, +}; + +#[no_mangle] +#[inline(never)] +pub fn push_read_buf(c: u8){ + unsafe { + READ_RING_BUFFER.write(c); + } +} + +#[no_mangle] +#[inline(never)] +pub fn pop_read_buf() -> Option { + unsafe { + READ_RING_BUFFER.read() + } +} + +#[no_mangle] +#[inline(never)] +pub fn pop_write_buf() -> Option { + unsafe { + WRITE_RING_BUFFER.read() + } +} + +#[no_mangle] +#[inline(never)] +pub fn push_write_buf(c: u8){ + unsafe { + WRITE_RING_BUFFER.write(c); + } +} + +#[no_mangle] +#[inline(never)] +pub fn async_getline(s: &mut [u8; 128], is_echo: bool) -> &str { + let mut ptr: usize = 0; + unsafe { + loop { + if let Some(i) = pop_read_buf() { + if is_echo { + write_u8_buf(i as u8); + flush(); + } + if i == 13 { + write_u8_buf(10); + break; + } + s[ptr] = i as u8; + ptr = ptr + 1; + } + } + } + core::str::from_utf8(&s[0..ptr]).unwrap() +} + +pub fn flush() { + write_int(true); +} + +pub fn write_u8_buf(c: u8) { + unsafe { + WRITE_RING_BUFFER.write(c); + } +} + + +#[no_mangle] +#[inline(never)] +pub fn write_int(enable: bool) { + unsafe { + // enable interrupt + if enable { + write_volatile(AUX_MU_IER_REG as *mut u32, 0b11); + } + else { + write_volatile(AUX_MU_IER_REG as *mut u32, 0b01); + } + } +} + +#[no_mangle] +#[inline(never)] +pub fn send_write_buf() { + loop { + if let Some(s) = pop_write_buf() { + unsafe {write_u8(s)}; + } + else { + break; + } + } + write_int(false); +} // Initialize the UART #[no_mangle] #[inline(never)] -pub fn init_uart() { +pub fn init_uart(int: bool) { unsafe { // configure GPFSEL1 register to set FSEL14 FSEL15 to ALT5 let fsel = read_volatile(GPFSEL1 as *mut u32); @@ -59,8 +204,21 @@ pub fn init_uart() { // Set AUX_MU_CNTL_REG to 0 write_volatile(AUX_MU_CNTL_REG as *mut u32, 0); - // Set AUX_MU_IER_REG to 0 - write_volatile(AUX_MU_IER_REG as *mut u32, 0); + if int { + // Set AUX_MU_IER_REG to 1 (enable receive interrupt) + write_volatile(AUX_MU_IER_REG as *mut u32, 0b1); + const IRQS1_ADDR: *mut u32 = 0x3f00b210 as *mut u32; + const IRQS2_ADDR: *mut u32 = 0x3f00b214 as *mut u32; + // Set IRQs1 register to enable mini UART interrupt + write_volatile(IRQS1_ADDR, 1 << 29); + // write_volatile(IRQS2_ADDR, 1 << 25); + + + } else { + // Set AUX_MU_IER_REG to 0 (disable interrupts) + write_volatile(AUX_MU_IER_REG as *mut u32, 0); + } + // Set AUX_MU_LCR_REG to 3 write_volatile(AUX_MU_LCR_REG as *mut u32, 3); // Set AUX_MU_MCR_REG to 0 @@ -71,6 +229,10 @@ pub fn init_uart() { write_volatile(AUX_MU_IIR_REG as *mut u32, 6); // Set AUX_MU_CNTL_REG to 3 write_volatile(AUX_MU_CNTL_REG as *mut u32, 3); + READ_RING_BUFFER.head = 0; + READ_RING_BUFFER.tail = 0; + WRITE_RING_BUFFER.head = 0; + WRITE_RING_BUFFER.tail = 0; } } pub struct Uart; @@ -85,8 +247,9 @@ impl Write for UartWriter { fn write_str(&mut self, s: &str) -> fmt::Result { unsafe { for i in s.bytes() { - write_u8(i); + write_u8_buf(i); } + write_int(true); } Ok(()) } diff --git a/initramfs/prog b/initramfs/prog deleted file mode 100644 index 1adf648a4c1b9d2d1b5e9fa08b84e52ef2fafc78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24 gcmZQzXt>0{!Z4AMf#Hh02*bzK|Nn ! { loop { asm::wfe(); } } - -// mode transition -pub fn el1_to_el0() { - unsafe { - asm::eret(); - } -} diff --git a/kernel/src/_arch/aarch64/cpu/boot.rs b/kernel/src/_arch/aarch64/cpu/boot.rs index 7ba9ee0ac..da707ee56 100644 --- a/kernel/src/_arch/aarch64/cpu/boot.rs +++ b/kernel/src/_arch/aarch64/cpu/boot.rs @@ -7,7 +7,7 @@ global_asm!( ); global_asm!( - include_str!("exception.s") + include_str!("interrupt.s") ); // mod uart; diff --git a/kernel/src/_arch/aarch64/cpu/boot.s b/kernel/src/_arch/aarch64/cpu/boot.s index 615041f94..780e1fe58 100644 --- a/kernel/src/_arch/aarch64/cpu/boot.s +++ b/kernel/src/_arch/aarch64/cpu/boot.s @@ -23,7 +23,13 @@ _start: ldr x1, BOOT_CORE_ID // provided by bsp/__board_name__/cpu.rs cmp x0, x1 b.ne .L_parking_loop - + + mov x0, 1 + msr cntp_ctl_el0, x0 // enable + mrs x0, cntfrq_el0 + //msr cntp_tval_el0, x0 // set expired time + // mov x0, 2 + set_exception_vector_table: adr x0, exception_vector_table msr vbar_el1, x0 @@ -40,7 +46,7 @@ set_exception_vector_table: b.eq .L_prepare_rust stp xzr, xzr, [x0], #16 b .L_bss_init_loop - + // Prepare the jump to Rust code. .L_prepare_rust: @@ -58,7 +64,8 @@ set_exception_vector_table: from_el2_to_el1: mov x0, (1 << 31) // EL1 uses aarch64 msr hcr_el2, x0 - mov x0, 0x3c5 // EL1h (SPSel = 1) with interrupt disabled + // mov x0, 0x3c5 // EL1h (SPSel = 1) with interrupt disabled + mov x0, 0x345 // EL1h (SPSel = 1) with interrupt enabled msr spsr_el2, x0 msr elr_el2, lr eret // return to EL1 diff --git a/kernel/src/_arch/aarch64/cpu/exception.s b/kernel/src/_arch/aarch64/cpu/interrupt.s similarity index 69% rename from kernel/src/_arch/aarch64/cpu/exception.s rename to kernel/src/_arch/aarch64/cpu/interrupt.s index d2c8b573f..d2083f6a0 100644 --- a/kernel/src/_arch/aarch64/cpu/exception.s +++ b/kernel/src/_arch/aarch64/cpu/interrupt.s @@ -42,49 +42,77 @@ .endm .section .text.exception -exception_handler: + +serr_handler: + save_all + bl rust_serr_handler + load_all + eret + +irq_handler: save_all - bl rust_exception_handler + bl rust_irq_handler load_all eret +frq_handler: + save_all + bl rust_frq_handler + load_all + eret + +core_timer_handler: + save_all + bl rust_core_timer_handler + load_all + mrs x0, cntfrq_el0 + lsl x0, x0, #1 + msr cntp_tval_el0, x0 + eret + +sync_handler: + save_all + bl rust_sync_handler + load_all + eret + .align 11 // vector table should be aligned to 0x800 .global exception_vector_table exception_vector_table: - b exception_handler // branch to a handler function. - .align 7 // entry size is 0x80, .align will pad 0 - b exception_handler + b sync_handler + .align 7 + b irq_handler .align 7 - b exception_handler + b frq_handler .align 7 - b exception_handler + b serr_handler .align 7 - b exception_handler + b sync_handler .align 7 - b exception_handler + b irq_handler .align 7 - b exception_handler + b frq_handler .align 7 - b exception_handler + b serr_handler .align 7 - b exception_handler + b sync_handler .align 7 - b exception_handler + b irq_handler .align 7 - b exception_handler + b frq_handler .align 7 - b exception_handler + b serr_handler .align 7 - b exception_handler + b sync_handler .align 7 - b exception_handler + b irq_handler .align 7 - b exception_handler + b frq_handler .align 7 - b exception_handler + b serr_handler .align 7 exception_entry: diff --git a/kernel/src/allocator/memory.rs b/kernel/src/allocator/memory.rs index e151505e3..4209a678b 100644 --- a/kernel/src/allocator/memory.rs +++ b/kernel/src/allocator/memory.rs @@ -1,5 +1,3 @@ - - use core::alloc::Layout; pub struct HeapMemory { diff --git a/kernel/src/cpu.rs b/kernel/src/cpu.rs index c029d9b00..bed0bb09c 100644 --- a/kernel/src/cpu.rs +++ b/kernel/src/cpu.rs @@ -1,4 +1,3 @@ -#[cfg(target_arch = "aarch64")] #[path = "_arch/aarch64/cpu.rs"] mod arch_cpu; diff --git a/kernel/src/interrupt/mod.rs b/kernel/src/interrupt/mod.rs new file mode 100644 index 000000000..64cdb23e8 --- /dev/null +++ b/kernel/src/interrupt/mod.rs @@ -0,0 +1,86 @@ +use crate::println; +use driver::uart; + +use core::ptr::read_volatile; + +#[no_mangle] +#[inline(never)] +pub fn rust_frq_handler() { + println!("FRQ interrupt!"); +} + +#[no_mangle] +#[inline(never)] +pub fn rust_sync_handler() { + let spsr_el1: u64; + let elr_el1: u64; + let esr_el1: u64; + unsafe { + core::arch::asm!("mrs {0}, spsr_el1", out(reg) spsr_el1); + core::arch::asm!("mrs {0}, elr_el1", out(reg) elr_el1); + core::arch::asm!("mrs {0}, esr_el1", out(reg) esr_el1); + } + println!("spsr_el1: {:#x}", spsr_el1); + println!("elr_el1: {:#x}", elr_el1); + println!("esr_el1: {:#x}", esr_el1); +} + +#[no_mangle] +#[inline(never)] +pub fn rust_core_timer_handler() { + // println!("Core timer interrupt!"); + // // read cntpct_el0 and cntfrq_el0 + // let mut cntpct_el0: u64; + // let mut cntfrq_el0: u64; + // unsafe { + // core::arch::asm!("mrs {0}, cntpct_el0", out(reg) cntpct_el0); + // core::arch::asm!("mrs {0}, cntfrq_el0", out(reg) cntfrq_el0); + // core::arch::asm!("msr cntp_tval_el0, {0}", in(reg) cntfrq_el0 << 1); + // } + // let mut seconds = cntpct_el0 / cntfrq_el0; + // println!("The seconds since boot: {}s", seconds); + crate::timer::timer_handler(); +} + +#[no_mangle] +fn rust_serr_handler() { + // print the content of spsr_el1, elr_el1, and esr_el1 + println!("SErr happened!"); +} + +#[no_mangle] +fn rust_irq_handler() { + // read IRQ basic pending register + let mut irq_basic_pending: u32; + const IRQ_BASE: *mut u64 = 0x3F00B000 as *mut u64; + const IRQ_BASIC_PENDING: *mut u32 = 0x3F00B200 as *mut u32; + const IRQ_PENDING_1: *mut u32 = 0x3F00B204 as *mut u32; + + let mut irq_pending_1: u32; + let mut irq_source: u32; + const CORE0_IRQ_SOURCE: u64 = 0x40000060; + unsafe { + irq_pending_1 = read_volatile(IRQ_PENDING_1 as *mut u32); + irq_source = read_volatile(CORE0_IRQ_SOURCE as *mut u32); + irq_basic_pending = read_volatile(IRQ_BASIC_PENDING); + } + // println!("IRQ basic pending register: {:#b}", irq_basic_pending); + + if irq_source & 0b10 != 0 { + rust_core_timer_handler(); + } + // there is a pending interrupt in the pending register 1 + if irq_basic_pending & (0b1 << 8) != 0 { + // interrupt from GPU + let iir = unsafe { read_volatile(uart::AUX_MU_IIR_REG as *mut u32) }; + if iir & 0b10 != 0 { + // Transmit holding register empty + uart::send_write_buf(); + } else if iir & 0b100 != 0 { + if let Some(u) = unsafe { uart::read_u8() } { + uart::push_read_buf(u); + }; + } + } +} + diff --git a/kernel/src/main.rs b/kernel/src/main.rs index fcedae5b4..e563ea33a 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -11,10 +11,19 @@ mod fdt; mod panic_wait; mod print; mod fs; +mod timer; + +mod interrupt; extern crate alloc; +use core::panic; + +use alloc::collections::binary_heap; +use alloc::string::String; +use alloc::string::ToString; use alloc::vec::Vec; +use alloc::collections::BinaryHeap; use allocator::MyAllocator; use fs::cpio::CpioHandler; use driver::mailbox; @@ -32,10 +41,20 @@ fn get_initrd_addr(name: &str, data: *const u8, len: usize) -> Option { } } -#[no_mangle] -#[inline(never)] fn exec(addr: extern "C" fn() -> !) { - addr(); + // set spsr_el1 to 0x3c0 and elr_el1 to the program’s start address. + // set the user program’s stack pointer to a proper position by setting sp_el0. + // issue eret to return to the user code. + unsafe { + // enable_timer(); + core::arch::asm!(" + msr spsr_el1, {k} + msr elr_el1, {a} + msr sp_el0, {s} + eret + ", k = in(reg) 0x3c0 as u64, a = in(reg) addr as u64, s = in(reg) 0x60000 as u64) ; + }; + println!(""); } #[no_mangle] @@ -44,35 +63,17 @@ fn boink() { unsafe{core::arch::asm!("nop")}; } -#[no_mangle] -fn kernel_init() -> ! { - let mut dtb_addr = addr_loader::load_dtb_addr(); - // init uart - uart::init_uart(); - println!("dtb address: {:#x}", dtb_addr as u64); - uart::uart_write_str("Kernel started\r\n"); - - let dtb_parser = fdt::DtbParser::new(dtb_addr); - let mut in_buf: [u8; 128] = [0; 128]; - // find initrd value by dtb traverse +fn timer_callback(message: String) { + let current_time = timer::get_current_time() / timer::get_timer_freq(); + println!("You have a timer after boot {}s, message: {}", current_time, message); - let mut initrd_start: *mut u8; - if let Some(addr) = dtb_parser.traverse(get_initrd_addr) { - initrd_start = addr as *mut u8; - println!("Initrd start address: {:#x}", initrd_start as u64) - } else { - initrd_start = 0 as *mut u8; - } - - let mut handler: CpioHandler = CpioHandler::new(initrd_start as *mut u8); - - // load symbol address usr_load_prog_base - let usr_load_prog_base = addr_loader::usr_load_prog_base(); - println!("usr_load_prog_base: {:#x}", usr_load_prog_base as u64); +} +fn shell(handler: CpioHandler) { + let mut in_buf: [u8; 128] = [0; 128]; loop { print!("meow>> "); - let inp = alloc::string::String::from(uart::getline(&mut in_buf, true)); + let inp = alloc::string::String::from(uart::async_getline(&mut in_buf, true)); let cmd = inp.trim().split(' ').collect::>(); // split the input string match cmd[0] { @@ -110,12 +111,12 @@ fn kernel_init() -> ! { println!("File not found"); } } - "dtb" => { - unsafe { println!("Start address: {:#x}", dtb_addr as u64) }; - println!("dtb load address: {:#x}", dtb_addr as u64); - println!("dtb pos: {:#x}", unsafe {*(dtb_addr)}); - dtb_parser.parse_struct_block(); - } + // "dtb" => { + // unsafe { println!("Start address: {:#x}", dtb_addr as u64) }; + // println!("dtb load address: {:#x}", dtb_addr as u64); + // println!("dtb pos: {:#x}", unsafe {*(dtb_addr)}); + // dtb_parser.parse_struct_block(); + // } "mailbox" => { println!("Revision: {:#x}", mailbox::get_board_revisioin()); let (base, size) = mailbox::get_arm_memory(); @@ -123,7 +124,7 @@ fn kernel_init() -> ! { println!("ARM memory size: {:#x}", size); } "exec" => { - boink(); + let usr_load_prog_base = addr_loader::usr_load_prog_base(); if cmd.len() < 2 { println!("Usage: exec "); continue; @@ -132,7 +133,6 @@ fn kernel_init() -> ! { println!("{} {}", f.get_name(), cmd[1]); f.get_name() == cmd[1]} ); - boink(); if let Some(mut f) = file { let file_size = f.get_size(); println!("File size: {}", file_size); @@ -145,8 +145,6 @@ fn kernel_init() -> ! { } println!(); let func: extern "C" fn() -> ! = core::mem::transmute(usr_load_prog_base); - boink(); - println!("Jump to user program at {:#x}", func as u64); exec(func); } @@ -154,18 +152,65 @@ fn kernel_init() -> ! { println!("File not found"); } } + "setTimeout" => { + if cmd.len() < 3 { + println!("Usage: setTimeout