somehal 0.4.5

Boot kernel code with mmu.
Documentation

SomeHAL

Test Crates.io License

SomeHAL is a hardware abstraction layer library designed specifically for AArch64 chips with MMU functionality. It provides bootloader capabilities to complete MMU initialization and run code at specified virtual addresses.

Features

  • 🚀 Dynamic MMU Initialization: Automatically configures page tables, enables MMU, and redirects to virtual addresses
  • 📱 Multi-Privilege Level Support: Supports both EL1 and EL2 (hypervisor) privilege levels
  • 🔧 Position Independent Boot: Uses PIE (Position Independent Executable) bootloader
  • 💾 Memory Management: Automatically parses device tree and manages memory regions
  • 🐛 Early Debug Support: Provides early debug output functionality
  • Multi-Core Support: Supports multi-core CPU boot

Architecture Support

  • AArch64: ✅ Full support
    • EL1 (Exception Level 1)
    • EL2 (Exception Level 2, Hypervisor)

Getting Started

Adding Dependencies

Add to your Cargo.toml:

[dependencies]
somehal = "0.3"

Basic Usage

#![no_std]
#![no_main]

use somehal::{entry, BootInfo};

#[entry]
fn main(boot_info: &BootInfo) -> ! {
    // Your kernel main function
    println!("Hello from virtual address!");
    
    // Access boot information
    println!("FDT address: {:p}", boot_info.fdt);
    println!("Memory regions: {}", boot_info.memory_regions.len());
    
    // Your kernel logic
    loop {}
}

Multi-Core Support

use somehal::{entry, secondary_entry, BootInfo};

#[entry]
fn main(boot_info: &BootInfo) -> ! {
    // Primary CPU startup logic
    println!("Primary CPU started");
    
    // Start other cores
    let secondary_addr = somehal::secondary_entry_addr();
    // Start other cores through your method...
    
    loop {}
}

#[secondary_entry]
fn secondary_main(cpu_id: usize) -> ! {
    // Secondary CPU startup logic
    println!("Secondary CPU {} started", cpu_id);
    loop {}
}

Core Concepts

Boot Process

  1. Kernel Entry (_start) - Save boot parameters
  2. PIE Bootloader - Position-independent bootloader responsible for:
    • Parsing device tree (FDT)
    • Configuring page table mappings
    • Enabling MMU
    • Redirecting to virtual addresses
  3. Virtual Entry - Call user's main function

Memory Layout

Virtual Address Space:
0xffff_0000_0000_0000  +----------------+
                       |   Kernel Space |
                       |                |
0xffff_8000_0000_0000  +----------------+
                       |  Linear Mapping|
                       | (Physical Mem) |
0xffff_0000_0000_0000  +----------------+

BootInfo Structure

BootInfo provides important boot-time information:

pub struct BootInfo {
    pub fdt: Option<NonNull<u8>>,           // Device tree pointer
    pub memory_regions: MemoryRegions,      // Memory region list
    pub kimage_start_lma: u64,              // Kernel load address
    pub kimage_start_vma: u64,              // Kernel virtual address
    pub free_memory_start: *mut u8,         // Free memory start address
    pub pg_start: u64,                      // Page table start address
    pub cpu_id: usize,                      // CPU ID
}

Feature Flags

  • hv: Enable hypervisor mode (EL2) support

Hypervisor Mode Example

[dependencies]
somehal = { version = "0.3", features = ["hv"] }

Memory Management

Getting Memory Region Information

use somehal::{BootInfo, MemoryRegionKind};

#[entry]
fn main(boot_info: &BootInfo) -> ! {
    for region in boot_info.memory_regions.iter() {
        match region.kind {
            MemoryRegionKind::Ram => {
                println!("RAM: {:#x} - {:#x}", region.start, region.end);
            }
            MemoryRegionKind::Reserved => {
                println!("Reserved: {:#x} - {:#x}", region.start, region.end);
            }
        }
    }
    
    loop {}
}

I/O Memory Mapping

use somehal::mem::iomap;

// Map I/O device memory
let device_base = 0x1000_0000;
let device_size = 0x1000;

match iomap(device_base, device_size) {
    Ok(virt_addr) => {
        println!("Device mapped at {:p}", virt_addr);
        // Use virtual address to access device
    }
    Err(e) => {
        println!("Failed to map device: {:?}", e);
    }
}

Debug Features

Early Debug Output

use somehal::*;

println!("Early boot message");

Build Configuration

Linker Script

SomeHAL requires specific linker script configuration. Create link.ld in your project:

STACK_SIZE = 0x40000;

INCLUDE "somehal.x"

SECTIONS
{
   # other sections...
}

Build Script

In build.rs:

fn main() {
    // SomeHAL will automatically configure necessary linking parameters
    println!("cargo:rustc-link-arg=-Tlink.ld");
}

Platform Testing

The project provides test configurations for multiple platforms:

# Test runtime
cargo test --target aarch64-unknown-none-softfloat -p test-some-rt

# Test configuration with VM functionality
cargo test --target aarch64-unknown-none-softfloat -p test-some-rt --features hv

Example Projects

Check the tests/test-some-rt directory for complete usage examples.

Important Notes

  1. Target Architecture: Currently only supports aarch64-unknown-none-softfloat target
  2. no_std: This is a no_std library for bare-metal environments
  3. MMU Requirement: Requires hardware MMU support
  4. Device Tree: Requires a valid device tree (FDT) to obtain hardware information

License

This project is licensed under the MIT License. See the LICENSE file for details.

Contributing

Issues and pull requests are welcome!