#![no_std]
#![deny(warnings, missing_docs)]
mod app;
pub use app::{AppIterator, AppMeta};
pub const SCRIPT: &[u8] = b"\
OUTPUT_ARCH(riscv)
SECTIONS {
.text 0x80200000 : {
__start = .;
*(.text.entry)
*(.text .text.*)
}
.rodata : ALIGN(4K) {
__rodata = .;
*(.rodata .rodata.*)
*(.srodata .srodata.*)
}
.data : ALIGN(4K) {
__data = .;
*(.data .data.*)
*(.sdata .sdata.*)
}
.bss : ALIGN(8) {
__sbss = .;
*(.bss .bss.*)
*(.sbss .sbss.*)
__ebss = .;
}
.boot : ALIGN(4K) {
__boot = .;
KEEP(*(.boot.stack))
}
__end = .;
}";
pub const NOBIOS_SCRIPT: &[u8] = b"\
OUTPUT_ARCH(riscv)
ENTRY(_m_start)
M_BASE_ADDRESS = 0x80000000;
S_BASE_ADDRESS = 0x80200000;
SECTIONS {
. = M_BASE_ADDRESS;
.text.m_entry : {
*(.text.m_entry)
}
.text.m_trap : {
*(.text.m_trap)
}
.bss.m_stack : {
*(.bss.m_stack)
}
.bss.m_data : {
*(.bss.m_data)
}
. = S_BASE_ADDRESS;
.text : {
__start = .;
*(.text.entry)
*(.text .text.*)
}
.rodata : ALIGN(4K) {
__rodata = .;
*(.rodata .rodata.*)
*(.srodata .srodata.*)
}
.data : ALIGN(4K) {
__data = .;
*(.data .data.*)
*(.sdata .sdata.*)
}
.bss : ALIGN(8) {
__sbss = .;
*(.bss .bss.*)
*(.sbss .sbss.*)
__ebss = .;
}
.boot : ALIGN(4K) {
__boot = .;
KEEP(*(.boot.stack))
}
__end = .;
}";
#[macro_export]
macro_rules! boot0 {
($entry:ident; stack = $stack:expr) => {
#[cfg(target_arch = "riscv64")]
#[unsafe(naked)]
#[no_mangle]
#[link_section = ".text.entry"]
unsafe extern "C" fn _start() -> ! {
#[link_section = ".boot.stack"]
static mut STACK: [u8; $stack] = [0u8; $stack];
core::arch::naked_asm!(
"la sp, __end",
"j {main}",
main = sym rust_main,
)
}
#[cfg(not(target_arch = "riscv64"))]
#[no_mangle]
unsafe extern "C" fn _start() -> ! {
unimplemented!("_start() is only supported on riscv64")
}
};
}
#[derive(Debug)]
pub struct KernelLayout {
text: usize,
rodata: usize,
data: usize,
sbss: usize,
ebss: usize,
boot: usize,
end: usize,
}
impl KernelLayout {
pub const INIT: Self = Self {
text: usize::MAX,
rodata: usize::MAX,
data: usize::MAX,
sbss: usize::MAX,
ebss: usize::MAX,
boot: usize::MAX,
end: usize::MAX,
};
#[inline]
pub fn locate() -> Self {
unsafe extern "C" {
fn __start();
fn __rodata();
fn __data();
fn __sbss();
fn __ebss();
fn __boot();
fn __end();
}
Self {
text: __start as *const () as _,
rodata: __rodata as *const () as _,
data: __data as *const () as _,
sbss: __sbss as *const () as _,
ebss: __ebss as *const () as _,
boot: __boot as *const () as _,
end: __end as *const () as _,
}
}
#[inline]
pub const fn start(&self) -> usize {
self.text
}
#[inline]
pub const fn end(&self) -> usize {
self.end
}
#[inline]
pub const fn len(&self) -> usize {
self.end - self.text
}
#[inline]
pub unsafe fn zero_bss(&self) {
let mut ptr = self.sbss as *mut u8;
let end = self.ebss as *mut u8;
while ptr < end {
unsafe { ptr.write_volatile(0) };
ptr = unsafe { ptr.add(1) };
}
}
#[inline]
pub fn iter(&self) -> KernelRegionIterator<'_> {
KernelRegionIterator {
layout: self,
next: Some(KernelRegionTitle::Text),
}
}
}
use core::{fmt, ops::Range};
pub struct KernelRegionIterator<'a> {
layout: &'a KernelLayout,
next: Option<KernelRegionTitle>,
}
#[derive(Clone, Copy)]
pub enum KernelRegionTitle {
Text,
Rodata,
Data,
Boot,
}
pub struct KernelRegion {
pub title: KernelRegionTitle,
pub range: Range<usize>,
}
impl fmt::Display for KernelRegion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.title {
KernelRegionTitle::Text => write!(f, ".text ----> ")?,
KernelRegionTitle::Rodata => write!(f, ".rodata --> ")?,
KernelRegionTitle::Data => write!(f, ".data ----> ")?,
KernelRegionTitle::Boot => write!(f, ".boot ----> ")?,
}
write!(f, "{:#10x}..{:#10x}", self.range.start, self.range.end)
}
}
impl Iterator for KernelRegionIterator<'_> {
type Item = KernelRegion;
fn next(&mut self) -> Option<Self::Item> {
use KernelRegionTitle::*;
match self.next? {
Text => {
self.next = Some(Rodata);
Some(KernelRegion {
title: Text,
range: self.layout.text..self.layout.rodata,
})
}
Rodata => {
self.next = Some(Data);
Some(KernelRegion {
title: Rodata,
range: self.layout.rodata..self.layout.data,
})
}
Data => {
self.next = Some(Boot);
Some(KernelRegion {
title: Data,
range: self.layout.data..self.layout.ebss,
})
}
Boot => {
self.next = None;
Some(KernelRegion {
title: Boot,
range: self.layout.boot..self.layout.end,
})
}
}
}
}