refactored for architectures and added riscv support

This commit is contained in:
Bryan McShea
2024-01-24 00:41:51 -05:00
parent e5a6b6073f
commit 461269ed32
30 changed files with 683 additions and 425 deletions

40
runner/src/boot.rs Normal file
View File

@@ -0,0 +1,40 @@
use bootloader::DiskImageBuilder;
use clap::ValueEnum;
use std::{path::PathBuf, process};
use crate::target::Target;
#[derive(Copy, Clone, ValueEnum)]
pub enum Bootloader {
UEFI,
BIOS,
}
impl Bootloader {
pub fn to_str(&self) -> &'static str {
match self {
Self::UEFI => "UEFI",
Self::BIOS => "BIOS",
}
}
}
pub fn build_bootloader_img(bootloader: &Bootloader) {
let target = Target::X86_64 {
bootloader: *bootloader,
};
let kernel_path = PathBuf::from(target.binary_path());
let disk_builder = DiskImageBuilder::new(kernel_path.clone());
let img_path = PathBuf::from(target.qemu_bin_path());
let result = match bootloader {
Bootloader::UEFI => disk_builder.create_uefi_image(&img_path),
Bootloader::BIOS => disk_builder.create_bios_image(&img_path),
};
if let Err(err) = result {
println!("Failed to build bootloader: {}", err);
process::exit(1);
}
}

63
runner/src/main.rs Normal file
View File

@@ -0,0 +1,63 @@
use clap::Parser;
use std::process::{self, Command, Stdio};
use target::Target;
mod boot;
mod target;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Args {
/// what architecture / machine to target
#[command(subcommand)]
target: Option<Target>,
/// whether to use gdb
#[arg(long, short, id = "port")]
gdb: Option<Option<u16>>,
}
fn main() {
let args = Args::parse();
let target = args.target.unwrap_or(Target::default());
std::env::set_current_dir("../kernel").expect("uh oh");
build(&target);
run_qemu(&target, args.gdb);
}
fn run_qemu(target: &Target, gdb: Option<Option<u16>>) {
let mut qemu = target.qemu();
if let Some(port) = gdb {
let port = port.unwrap_or(1234);
qemu.arg("-S");
qemu.args(["-gdb", &format!("tcp::{}", port)]);
let mut gdb = target.gdb();
gdb.arg("-q");
gdb.args(["-ex", &format!("target remote :{}", port)]);
// gdb.args(["-ex", "b kernel::kernel_main"]);
// gdb.args(["-ex", "c"]);
let handle = std::thread::spawn(move || {
qemu.stdin(Stdio::null());
qemu.stdout(Stdio::null());
let exit_status = qemu.status().unwrap();
});
gdb.status().unwrap();
handle.join().unwrap();
} else {
let exit_status = qemu.status().unwrap();
// process::exit(exit_status.code().unwrap_or(-1));
}
}
fn build(target: &Target) {
let mut cargo = Command::new("cargo");
cargo.arg("build");
cargo.args(["--package", "kernel"]);
cargo.args(["--target", target.rust_target()]);
let status = cargo.status().expect("uh oh");
if !status.success() {
process::exit(status.code().unwrap_or(-1));
}
if let Target::X86_64 { bootloader } = target {
boot::build_bootloader_img(bootloader);
}
}

87
runner/src/target.rs Normal file
View File

@@ -0,0 +1,87 @@
use std::process::Command;
use clap::Subcommand;
use crate::boot::Bootloader;
#[derive(Copy, Clone, Subcommand)]
pub enum Target {
X86_64 {
#[arg(long, short, id = "type", default_value = "bios")]
bootloader: Bootloader,
},
Riscv64,
}
impl Default for Target {
fn default() -> Self {
Self::Riscv64
}
}
impl Target {
pub const X86_64_RUST_TARGET: &'static str = "x86_64-unknown-none";
pub fn qemu(&self) -> Command {
match self {
Self::X86_64 { bootloader } => {
let mut cmd = Command::new("qemu-system-x86_64");
if let Bootloader::UEFI = bootloader {
cmd.arg("-bios").arg(ovmf_prebuilt::ovmf_pure_efi());
}
cmd.args([
"-drive",
&format!("format=raw,file={}", self.qemu_bin_path()),
]);
cmd.args(["-device", "isa-debug-exit,iobase=0xf4,iosize=0x04"]);
cmd.args(["-serial", "stdio"]);
cmd
}
Self::Riscv64 => {
let mut cmd = Command::new("qemu-system-riscv64");
cmd.arg("-nographic");
cmd.arg("-semihosting");
cmd.args(["-machine", "sifive_u"]);
cmd.args(["-bios", "none"]);
cmd.args(["-kernel", &self.qemu_bin_path()]);
cmd
}
}
}
pub fn gdb(&self) -> Command {
match self {
Self::X86_64 { .. } => {
let mut cmd = Command::new("rust-gdb");
cmd.args([
"-ex",
&format!("symbol-file {} -o 0x8000000000", self.qemu_bin_path()),
]);
cmd
}
Self::Riscv64 => {
let mut cmd = Command::new("gdb");
cmd.arg(self.qemu_bin_path());
cmd
}
}
}
pub fn rust_target(&self) -> &'static str {
match self {
Self::X86_64 { .. } => Self::X86_64_RUST_TARGET,
Self::Riscv64 => "riscv64gc-unknown-none-elf",
}
}
pub fn target_folder(&self) -> String {
format!("target/{}/debug", self.rust_target())
}
pub fn binary_path(&self) -> String {
format!("{}/kernel", self.target_folder())
}
pub fn qemu_bin_path(&self) -> String {
match self {
Self::X86_64 { bootloader } => {
self.binary_path() + &format!("-{}.img", bootloader.to_str().to_lowercase())
}
Self::Riscv64 => self.binary_path(),
}
}
}