refactored for architectures and added riscv support
This commit is contained in:
1166
runner/Cargo.lock
generated
Normal file
1166
runner/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
10
runner/Cargo.toml
Normal file
10
runner/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "runner"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.4.16", features = ["derive"] }
|
||||
ovmf-prebuilt = "0.1.0-alpha.1"
|
||||
bootloader = { version = "0.11.5" }
|
||||
|
||||
40
runner/src/boot.rs
Normal file
40
runner/src/boot.rs
Normal 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
63
runner/src/main.rs
Normal 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
87
runner/src/target.rs
Normal 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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user