aarch64-rt
The aarch64-rt
crate provides the assembly entry point and exception vector
that we implemented before. We just need to mark our main function with the
entry!
macro.
It also provides the initial_pagetable!
macro to let us define an initial
static pagetable in Rust, rather than in assembly code like we did before.
We can also use the UART driver from the arm-pl011-uart
crate rather than
writing our own.
#![no_main] #![no_std] mod exceptions; use aarch64_paging::paging::Attributes; use aarch64_rt::{InitialPagetable, entry, initial_pagetable}; use arm_pl011_uart::{PL011Registers, Uart, UniqueMmioPointer}; use core::fmt::Write; use core::panic::PanicInfo; use core::ptr::NonNull; use smccc::Hvc; use smccc::psci::system_off; /// Base address of the primary PL011 UART. const PL011_BASE_ADDRESS: NonNull<PL011Registers> = NonNull::new(0x900_0000 as _).unwrap(); /// Attributes to use for device memory in the initial identity map. const DEVICE_ATTRIBUTES: Attributes = Attributes::VALID .union(Attributes::ATTRIBUTE_INDEX_0) .union(Attributes::ACCESSED) .union(Attributes::UXN); /// Attributes to use for normal memory in the initial identity map. const MEMORY_ATTRIBUTES: Attributes = Attributes::VALID .union(Attributes::ATTRIBUTE_INDEX_1) .union(Attributes::INNER_SHAREABLE) .union(Attributes::ACCESSED) .union(Attributes::NON_GLOBAL); initial_pagetable!({ let mut idmap = [0; 512]; // 1 GiB of device memory. idmap[0] = DEVICE_ATTRIBUTES.bits(); // 1 GiB of normal memory. idmap[1] = MEMORY_ATTRIBUTES.bits() | 0x40000000; // Another 1 GiB of device memory starting at 256 GiB. idmap[256] = DEVICE_ATTRIBUTES.bits() | 0x4000000000; InitialPagetable(idmap) }); entry!(main); fn main(x0: u64, x1: u64, x2: u64, x3: u64) -> ! { // SAFETY: `PL011_BASE_ADDRESS` is the base address of a PL011 device, and // nothing else accesses that address range. let mut uart = unsafe { Uart::new(UniqueMmioPointer::new(PL011_BASE_ADDRESS)) }; writeln!(uart, "main({x0:#x}, {x1:#x}, {x2:#x}, {x3:#x})").unwrap(); system_off::<Hvc>().unwrap(); panic!("system_off returned"); } #[panic_handler] fn panic(_info: &PanicInfo) -> ! { system_off::<Hvc>().unwrap(); loop {} }
- Run the example in QEMU with
make qemu_rt
undersrc/bare-metal/aps/examples
.