commit 63a2a76b0befca2040260f18e49ad95834fa1cfc Author: gil Date: Mon May 13 17:31:37 2024 -0500 Initial commit diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..8f40bd6 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,13 @@ +# .cargo/config.toml + +[build] +target = "riscv32imac-unknown-none-elf" + +[target.riscv32imac-unknown-none-elf] +runner = """ qemu-system-riscv32 + -cpu rv32 + -machine virt + -m 150M + -s + -nographic + -bios """ \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..c4fb7e1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "rust-analyzer.check.allTargets": false, + "rust-analyzer.check.targets": [ + "riscv32imac-unknown-none-elf" + ] +} \ No newline at end of file diff --git a/.vscode/workspace.code-snippets b/.vscode/workspace.code-snippets new file mode 100644 index 0000000..ab5cd7f --- /dev/null +++ b/.vscode/workspace.code-snippets @@ -0,0 +1,26 @@ +{ + "Current Timestamp": { + "scope": "markdown,plaintext,yaml", + "prefix": "date", + "body": [ + "$CURRENT_YEAR-$CURRENT_MONTH-${CURRENT_DATE}T$CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND-05:00" + ], + "description": "Add Current date & time" + } + // Place your journal workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and + // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope + // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is + // used to trigger the snippet and the body will be expanded and inserted. Possible variables are: + // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. + // Placeholders with the same ids are connected. + // Example: + // "Print to console": { + // "scope": "javascript,typescript", + // "prefix": "log", + // "body": [ + // "console.log('$1');", + // "$2" + // ], + // "description": "Log output to console" + // } +} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0acf8e8 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "riscv-uefi" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..cac17e8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "riscv-uefi" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/README.md b/README.md new file mode 100644 index 0000000..903457a --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +--- +created: 2024-05-13T14:28:49-05:00 +modified: 2024-05-13T14:28:52-05:00 +--- + +Started here: https://www.meyerzinn.tech/posts/2023/03/05/running-rust-code-on-risc-v-in-qemu/ + +Then here: https://www.meyerzinn.tech/posts/2023/03/08/p1-printing-and-allocating/ \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..16ab199 --- /dev/null +++ b/build.rs @@ -0,0 +1,8 @@ +// build.rs + +fn main() { + // Use the linker script. + println!("cargo:rustc-link-arg=-Tsrc/script.ld"); + // Don't do any magic linker stuff. + println!("cargo:rustc-link-arg=--omagic"); +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b5d269c --- /dev/null +++ b/src/main.rs @@ -0,0 +1,53 @@ +#![no_std] +#![no_main] +#![feature(naked_functions)] + +use core::panic::PanicInfo; + +#[naked] +#[no_mangle] +#[link_section = ".text.init"] +unsafe extern "C" fn _start() -> ! { + use core::arch::asm; + asm!( + // before we use the `la` pseudo-instruction for the first time, + // we need to set `gp` (google linker relaxation) + ".option push", + ".option norelax", + "la gp, _global_pointer", + ".option pop", + + // set the stack pointer + "la sp, _init_stack_top", + + // "tail-call" to {entry} (call without saving a return address) + "tail {entry}", + entry = sym entry, // {entry} refers to the function [entry] below + options(noreturn) // we must handle "returning" from assembly + ); +} + +extern "C" fn entry() -> ! { + use core::ptr::write_volatile; + let addr = 0x1000_0000 as *mut u8; + { + // Set data size to 8 bits. + unsafe { write_volatile(addr.offset(3), 0b11) }; + // Enable FIFO. + unsafe { write_volatile(addr.offset(2), 0b1) }; + // Enable receiver buffer interrupts. + unsafe { write_volatile(addr.offset(1), 0b1) }; + } + + // UART is now set up! Let's print a message. + for byte in "Hello, world!\n".bytes() { + unsafe { write_volatile(addr, byte) }; + } + + loop {} +} + +#[panic_handler] +fn on_panic(_info: &PanicInfo) -> ! { + loop {} +} diff --git a/src/script.ld b/src/script.ld new file mode 100644 index 0000000..8d718c1 --- /dev/null +++ b/src/script.ld @@ -0,0 +1,42 @@ +# src/script.ld + +OUTPUT_ARCH("riscv") +ENTRY(_start) + +MEMORY { + ram (wxa) : ORIGIN = 0x80000000, LENGTH = 128M +} + +PHDRS { + text PT_LOAD; + data PT_LOAD; + bss PT_LOAD; +} + +SECTIONS { + . = ORIGIN(ram); # start at 0x8000_0000 + + .text : { # put code first + *(.text.init) # start with anything in the .text.init section + *(.text .text.*) # then put anything else in .text + } >ram AT>ram :text # put this section into the text segment + + PROVIDE(_global_pointer = .); # this is magic, google "linker relaxation" + + .rodata : { # next, read-only data + *(.rodata .rodata.*) + } >ram AT>ram :text # goes into the text segment as well (since instructions are generally read-only) + + .data : { # and the data section + *(.sdata .sdata.*) *(.data .data.*) + } >ram AT>ram :data # this will go into the data segment + + .bss :{ # finally, the BSS + PROVIDE(_bss_start = .); # define a variable for the start of this section + *(.sbss .sbss.*) *(.bss .bss.*) + PROVIDE(_bss_end = .); # ... and one at the end + } >ram AT>ram :bss # and this goes into the bss segment + + . = ALIGN(16) # our stack needs to be 16-byte aligned, per the C calling convention + PROVIDE(_init_stack_top = . + 0x1000) # reserve 0x1000 bytes for the initialisation stack +} \ No newline at end of file