forked from AbleOS/ableos
Moved hardcoded repbuild file includes to .
parent
43cc7ab636
commit
e75e5fdcff
|
@ -1,13 +1,34 @@
|
|||
use {
|
||||
derive_more::Display,
|
||||
error_stack::{bail, report, Context, Report, Result, ResultExt},
|
||||
fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek},
|
||||
error_stack::{
|
||||
bail,
|
||||
report,
|
||||
Context,
|
||||
Report,
|
||||
Result,
|
||||
ResultExt,
|
||||
},
|
||||
fatfs::{
|
||||
FileSystem,
|
||||
FormatVolumeOptions,
|
||||
FsOptions,
|
||||
ReadWriteSeek,
|
||||
},
|
||||
std::{
|
||||
fmt::Display,
|
||||
fs::{self, File},
|
||||
io::{self, Write},
|
||||
fs::{
|
||||
self,
|
||||
File,
|
||||
},
|
||||
io::{
|
||||
self,
|
||||
Write,
|
||||
},
|
||||
path::Path,
|
||||
process::{exit, Command},
|
||||
process::{
|
||||
exit,
|
||||
Command,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -15,14 +36,10 @@ fn main() -> Result<(), Error> {
|
|||
let mut args = std::env::args();
|
||||
args.next();
|
||||
|
||||
// let disk_meta = fs::metadata("target/disk.img").unwrap();
|
||||
// let config_meta = fs::metadata("system.toml").unwrap();
|
||||
|
||||
// if disk_meta.modified().unwrap() < config_meta.modified().unwrap() {
|
||||
// // TODO: work on adding in system.toml support
|
||||
// // TODO: rebuild the disk
|
||||
// }
|
||||
|
||||
// let disk_meta = fs::metadata("target/disk.img").unwrap(); let config_meta =
|
||||
// fs::metadata("system.toml").unwrap(); if disk_meta.modified().unwrap() <
|
||||
// config_meta.modified().unwrap() { // TODO: work on adding in system.toml
|
||||
// support // TODO: rebuild the disk }
|
||||
match args.next().as_deref() {
|
||||
Some("build" | "b") => {
|
||||
let mut release = false;
|
||||
|
@ -38,10 +55,9 @@ fn main() -> Result<(), Error> {
|
|||
return Err(report!(Error::InvalidSubCom));
|
||||
}
|
||||
}
|
||||
|
||||
assemble()?;
|
||||
build(release, target).change_context(Error::Build)
|
||||
}
|
||||
},
|
||||
Some("run" | "r") => {
|
||||
let mut release = false;
|
||||
let mut target = Target::X86_64;
|
||||
|
@ -56,24 +72,25 @@ fn main() -> Result<(), Error> {
|
|||
return Err(report!(Error::InvalidSubCom));
|
||||
}
|
||||
}
|
||||
|
||||
assemble()?;
|
||||
build(release, target)?;
|
||||
run(release, target)
|
||||
}
|
||||
},
|
||||
Some("help" | "h") => {
|
||||
println!(concat!(
|
||||
"AbleOS RepBuild\n",
|
||||
"Subcommands:\n",
|
||||
" build (b): Build a bootable disk image\n",
|
||||
" help (h): Print this message\n",
|
||||
" run (r): Build and run AbleOS in QEMU\n\n",
|
||||
"Options for build and run:\n",
|
||||
" -r: build in release mode",
|
||||
" [target]: sets target"
|
||||
),);
|
||||
println!(
|
||||
concat!(
|
||||
"AbleOS RepBuild\n",
|
||||
"Subcommands:\n",
|
||||
" build (b): Build a bootable disk image\n",
|
||||
" help (h): Print this message\n",
|
||||
" run (r): Build and run AbleOS in QEMU\n\n",
|
||||
"Options for build and run:\n",
|
||||
" -r: build in release mode",
|
||||
" [target]: sets target"
|
||||
)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
_ => Err(report!(Error::InvalidSubCom)),
|
||||
}
|
||||
}
|
||||
|
@ -84,65 +101,51 @@ fn assemble() -> Result<(), Error> {
|
|||
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
|
||||
Err(e) => return Err(Report::new(e).change_context(Error::Io)),
|
||||
}
|
||||
|
||||
for entry in std::fs::read_dir("sysdata/test-programs")
|
||||
.map_err(Report::from)
|
||||
.change_context(Error::Io)?
|
||||
{
|
||||
for entry in std::fs::read_dir("sysdata/test-programs").map_err(Report::from).change_context(Error::Io)? {
|
||||
let entry = entry.map_err(Report::from).change_context(Error::Io)?;
|
||||
if !entry
|
||||
.file_type()
|
||||
.map_err(Report::from)
|
||||
.change_context(Error::Io)?
|
||||
.is_file()
|
||||
{
|
||||
if !entry.file_type().map_err(Report::from).change_context(Error::Io)?.is_file() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = entry.file_name();
|
||||
let name = name.to_string_lossy();
|
||||
let name = name.trim_end_matches(".rhai");
|
||||
|
||||
let mut out = File::options()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(Path::new("target/test-programs").join(format!("{name}.hbf")))
|
||||
.map_err(Report::from)
|
||||
.change_context(Error::Io)?;
|
||||
|
||||
out.set_len(0)
|
||||
.map_err(Report::from)
|
||||
.change_context(Error::Io)?;
|
||||
|
||||
hbasm::assembler(&mut out, |engine| engine.run_file(entry.path()))
|
||||
.map_err(|e| report!(Error::Assembler).attach_printable(e.to_string()))?;
|
||||
let mut out =
|
||||
File::options()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(Path::new("target/test-programs").join(format!("{name}.hbf")))
|
||||
.map_err(Report::from)
|
||||
.change_context(Error::Io)?;
|
||||
out.set_len(0).map_err(Report::from).change_context(Error::Io)?;
|
||||
hbasm::assembler(
|
||||
&mut out,
|
||||
|engine| engine.run_file(entry.path()),
|
||||
).map_err(|e| report!(Error::Assembler).attach_printable(e.to_string()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_fs() -> Result<FileSystem<impl ReadWriteSeek>, io::Error> {
|
||||
let filename = "sysdata/system_config.toml";
|
||||
|
||||
// Read the contents of the file using a `match` block
|
||||
// to return the `data: Ok(c)` as a `String`
|
||||
// or handle any `errors: Err(_)`.
|
||||
// Read the contents of the file using a `match` block to return the `data: Ok(c)`
|
||||
// as a `String` or handle any `errors: Err(_)`.
|
||||
let contents = match fs::read_to_string(filename) {
|
||||
// If successful return the files text as `contents`.
|
||||
// `c` is a local variable.
|
||||
// If successful return the files text as `contents`. `c` is a local variable.
|
||||
Ok(c) => c,
|
||||
// Handle the `error` case.
|
||||
Err(_) => {
|
||||
// Write `msg` to `stderr`.
|
||||
eprintln!("Could not read file `{}`", filename);
|
||||
|
||||
// Exit the program with exit code `1`.
|
||||
exit(1);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
use toml::Value;
|
||||
|
||||
let mut limine_str = String::new();
|
||||
|
||||
let mut data: Value = toml::from_str(&contents).unwrap();
|
||||
let boot_table = data.get_mut("boot");
|
||||
let limine_table = boot_table.unwrap().get_mut("limine").unwrap();
|
||||
|
@ -151,16 +154,14 @@ fn get_fs() -> Result<FileSystem<impl ReadWriteSeek>, io::Error> {
|
|||
let interface_resolution = limine_table.get("interface_resolution").unwrap();
|
||||
let verbose = limine_table.get("verbose").unwrap();
|
||||
let term_wallpaper = limine_table.get("term_wallpaper").unwrap();
|
||||
|
||||
let vb_post = match verbose.as_bool().unwrap() {
|
||||
true => "yes",
|
||||
false => "no",
|
||||
};
|
||||
let term_background = limine_table
|
||||
.get("term_backdrop")
|
||||
.unwrap_or(&Value::Integer(0));
|
||||
let base = format!(
|
||||
"DEFAULT_ENTRY={}
|
||||
let term_background = limine_table.get("term_backdrop").unwrap_or(&Value::Integer(0));
|
||||
let base =
|
||||
format!(
|
||||
"DEFAULT_ENTRY={}
|
||||
TIMEOUT={}
|
||||
VERBOSE={}
|
||||
INTERFACE_RESOLUTION={}
|
||||
|
@ -168,15 +169,14 @@ INTERFACE_RESOLUTION={}
|
|||
TERM_WALLPAPER={}
|
||||
TERM_BACKDROP={}
|
||||
",
|
||||
default_entry,
|
||||
timeout,
|
||||
vb_post,
|
||||
interface_resolution,
|
||||
term_wallpaper.as_str().unwrap(),
|
||||
term_background
|
||||
);
|
||||
default_entry,
|
||||
timeout,
|
||||
vb_post,
|
||||
interface_resolution,
|
||||
term_wallpaper.as_str().unwrap(),
|
||||
term_background
|
||||
);
|
||||
limine_str.push_str(&base);
|
||||
|
||||
let boot_entries = limine_table.as_table_mut().unwrap();
|
||||
let mut real_boot_entries = boot_entries.clone();
|
||||
for (key, value) in boot_entries.into_iter() {
|
||||
|
@ -184,16 +184,15 @@ TERM_BACKDROP={}
|
|||
real_boot_entries.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
for (name, mut value) in real_boot_entries {
|
||||
let comment = value.get("comment").unwrap();
|
||||
let protocol = value.get("protocol").unwrap();
|
||||
let resolution = value.get("resolution").unwrap();
|
||||
let kernel_path = value.get("kernel_path").unwrap();
|
||||
let kernel_cmdline = value.get("kernel_cmdline").unwrap();
|
||||
|
||||
let text_entry = format!(
|
||||
"
|
||||
let text_entry =
|
||||
format!(
|
||||
"
|
||||
:{}
|
||||
COMMENT={}
|
||||
PROTOCOL={}
|
||||
|
@ -202,85 +201,56 @@ TERM_BACKDROP={}
|
|||
KERNEL_CMDLINE={}
|
||||
|
||||
",
|
||||
name,
|
||||
comment.as_str().unwrap(),
|
||||
protocol.as_str().unwrap(),
|
||||
resolution.as_str().unwrap(),
|
||||
kernel_path.as_str().unwrap(),
|
||||
kernel_cmdline,
|
||||
);
|
||||
|
||||
name,
|
||||
comment.as_str().unwrap(),
|
||||
protocol.as_str().unwrap(),
|
||||
resolution.as_str().unwrap(),
|
||||
kernel_path.as_str().unwrap(),
|
||||
kernel_cmdline
|
||||
);
|
||||
limine_str.push_str(&text_entry);
|
||||
|
||||
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
|
||||
// let mut real_modules = modules.clone();
|
||||
|
||||
// let mut real_modules = modules.clone();
|
||||
for (key, value) in modules.into_iter() {
|
||||
if value.is_table() {
|
||||
let path = value.get("path").unwrap();
|
||||
let cmd_line = value.get("cmd_line").unwrap();
|
||||
let a = format!(
|
||||
" MODULE_PATH={}
|
||||
MODULE_CMDLINE={}\n\n",
|
||||
path.as_str().unwrap(),
|
||||
cmd_line
|
||||
);
|
||||
let a = format!(" MODULE_PATH={}
|
||||
MODULE_CMDLINE={}\n\n", path.as_str().unwrap(), cmd_line);
|
||||
limine_str.push_str(&a);
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut img = File::options()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(Path::new("target/disk.img"))?;
|
||||
|
||||
let mut img = File::options().read(true).write(true).create(true).open(Path::new("target/disk.img"))?;
|
||||
img.set_len(1024 * 1024 * 64)?;
|
||||
|
||||
fatfs::format_volume(&mut img, FormatVolumeOptions::new())?;
|
||||
|
||||
let fs = FileSystem::new(img, FsOptions::new())?;
|
||||
|
||||
let bootdir = fs.root_dir().create_dir("efi")?.create_dir("boot")?;
|
||||
|
||||
let mut f = fs.root_dir().create_file("limine.cfg")?;
|
||||
let a = f.write(limine_str.as_bytes())?;
|
||||
drop(f);
|
||||
|
||||
io::copy(
|
||||
&mut File::open("limine/BOOTX64.EFI")
|
||||
.map_err(Report::from)
|
||||
.attach_printable("Copying Limine (x86_64): have you pulled the submodule?")?,
|
||||
&mut bootdir.create_file("bootx64.efi")?,
|
||||
)?;
|
||||
|
||||
io::copy(
|
||||
&mut File::open("limine/BOOTAA64.EFI")
|
||||
.map_err(Report::from)
|
||||
.attach_printable("Copying Limine (ARM): have you pulled the submodule?")?,
|
||||
&mut bootdir.create_file("bootaa64.efi")?,
|
||||
)?;
|
||||
// TODO: Remove this and replace it with pulling executables from the system_config
|
||||
for fpath in [
|
||||
"sysdata/background.bmp",
|
||||
"target/test-programs/failure.hbf",
|
||||
"target/test-programs/ecall.hbf",
|
||||
"target/test-programs/main.hbf",
|
||||
"target/test-programs/serial_driver.hbf",
|
||||
"target/test-programs/vfs_test.hbf",
|
||||
"target/test-programs/sds_test.hbf",
|
||||
"target/test-programs/limine_framebuffer_driver.hbf",
|
||||
"target/test-programs/keyboard_driver.hbf",
|
||||
] {
|
||||
|
||||
let to_copy = data.get("bundle").unwrap_or(Value::Array(vec![])).as_array().unwrap();
|
||||
for fpath in to_copy {
|
||||
let path = Path::new(fpath);
|
||||
io::copy(
|
||||
&mut File::open(path)?,
|
||||
&mut fs
|
||||
.root_dir()
|
||||
.create_file(&path.file_name().unwrap().to_string_lossy())?,
|
||||
&mut fs.root_dir().create_file(&path.file_name().unwrap().to_string_lossy())?,
|
||||
)?;
|
||||
}
|
||||
|
||||
drop(bootdir);
|
||||
Ok(fs)
|
||||
}
|
||||
|
@ -293,46 +263,36 @@ fn build(release: bool, target: Target) -> Result<(), Error> {
|
|||
if release {
|
||||
com.arg("-r");
|
||||
}
|
||||
|
||||
if target == Target::Riscv64Virt {
|
||||
com.args(["--target", "targets/riscv64-virt-ableos.json"]);
|
||||
}
|
||||
if target == Target::Aarch64 {
|
||||
com.args(["--target", "targets/aarch64-virt-ableos.json"]);
|
||||
}
|
||||
|
||||
match com.status() {
|
||||
Ok(s) if s.code() != Some(0) => bail!(Error::Build),
|
||||
Err(e) => bail!(report!(e).change_context(Error::Build)),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let mut path: String = "kernel".to_string();
|
||||
let kernel_dir = match target {
|
||||
Target::X86_64 => {
|
||||
path.push_str("_x86-64");
|
||||
"target/x86_64-ableos"
|
||||
}
|
||||
},
|
||||
Target::Riscv64Virt => "target/riscv64-virt-ableos",
|
||||
Target::Aarch64 => {
|
||||
path.push_str("_aarch64");
|
||||
"target/aarch64-virt-ableos"
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
(|| -> std::io::Result<_> {
|
||||
io::copy(
|
||||
&mut File::open(
|
||||
Path::new(kernel_dir)
|
||||
.join(if release { "release" } else { "debug" })
|
||||
.join("kernel"),
|
||||
)?,
|
||||
&mut fs.root_dir().create_file(&path)?,
|
||||
)
|
||||
.map(|_| ())
|
||||
})()
|
||||
.map_err(Report::from)
|
||||
.change_context(Error::Io)
|
||||
io::copy(&mut File::open(Path::new(kernel_dir).join(if release {
|
||||
"release"
|
||||
} else {
|
||||
"debug"
|
||||
}).join("kernel"))?, &mut fs.root_dir().create_file(&path)?).map(|_| ())
|
||||
})().map_err(Report::from).change_context(Error::Io)
|
||||
}
|
||||
|
||||
fn run(release: bool, target: Target) -> Result<(), Error> {
|
||||
|
@ -342,53 +302,56 @@ fn run(release: bool, target: Target) -> Result<(), Error> {
|
|||
Target::Aarch64 => Command::new("qemu-system-aarch64"),
|
||||
};
|
||||
let ovmf_path = fetch_ovmf(target);
|
||||
|
||||
match target {
|
||||
Target::X86_64 => {
|
||||
#[rustfmt::skip]
|
||||
com.args([
|
||||
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
|
||||
"-drive", "file=target/disk.img,format=raw",
|
||||
"-m", "4G",
|
||||
"-smp", "cores=4",
|
||||
"-bios",
|
||||
&ovmf_path.change_context(Error::OvmfFetch)?,
|
||||
"-drive",
|
||||
"file=target/disk.img,format=raw",
|
||||
"-m",
|
||||
"4G",
|
||||
"-smp",
|
||||
"cores=4",
|
||||
// "-enable-kvm",
|
||||
"-cpu", "Broadwell-v4"
|
||||
"-cpu",
|
||||
"Broadwell-v4",
|
||||
]);
|
||||
}
|
||||
},
|
||||
Target::Riscv64Virt => {
|
||||
#[rustfmt::skip]
|
||||
com.args([
|
||||
"-M", "virt",
|
||||
"-m", "128M",
|
||||
"-serial", "stdio",
|
||||
"-kernel",
|
||||
if release {
|
||||
"target/riscv64-virt-ableos/release/kernel"
|
||||
} else {
|
||||
"target/riscv64-virt-ableos/debug/kernel"
|
||||
}
|
||||
]);
|
||||
}
|
||||
com.args(["-M", "virt", "-m", "128M", "-serial", "stdio", "-kernel", if release {
|
||||
"target/riscv64-virt-ableos/release/kernel"
|
||||
} else {
|
||||
"target/riscv64-virt-ableos/debug/kernel"
|
||||
}]);
|
||||
},
|
||||
Target::Aarch64 => {
|
||||
#[rustfmt::skip]
|
||||
com.args([
|
||||
"-M", "virt",
|
||||
"-cpu", "cortex-a72",
|
||||
"-device", "ramfb",
|
||||
"-device", "qemu-xhci",
|
||||
"-device", "usb-kbd",
|
||||
"-m", "2G",
|
||||
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
|
||||
"-drive", "file=target/disk.img,format=raw",
|
||||
]);
|
||||
}
|
||||
com.args(
|
||||
[
|
||||
"-M",
|
||||
"virt",
|
||||
"-cpu",
|
||||
"cortex-a72",
|
||||
"-device",
|
||||
"ramfb",
|
||||
"-device",
|
||||
"qemu-xhci",
|
||||
"-device",
|
||||
"usb-kbd",
|
||||
"-m",
|
||||
"2G",
|
||||
"-bios",
|
||||
&ovmf_path.change_context(Error::OvmfFetch)?,
|
||||
"-drive",
|
||||
"file=target/disk.img,format=raw",
|
||||
],
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
match com
|
||||
.status()
|
||||
.map_err(Report::from)
|
||||
.change_context(Error::ProcessSpawn)?
|
||||
{
|
||||
match com.status().map_err(Report::from).change_context(Error::ProcessSpawn)? {
|
||||
s if s.success() => Ok(()),
|
||||
s => Err(report!(Error::Qemu(s.code()))),
|
||||
}
|
||||
|
@ -406,7 +369,6 @@ fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
|||
"target/RELEASEAARCH64_QEMU_EFI.fd",
|
||||
),
|
||||
};
|
||||
|
||||
let mut file = match std::fs::metadata(ovmf_path) {
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
|
@ -418,15 +380,8 @@ fn fetch_ovmf(target: Target) -> Result<String, OvmfFetchError> {
|
|||
Ok(_) => return Ok(ovmf_path.to_owned()),
|
||||
Err(e) => return Err(report!(e).change_context(OvmfFetchError::Io)),
|
||||
};
|
||||
let mut bytes = reqwest::blocking::get(ovmf_url)
|
||||
.map_err(Report::from)
|
||||
.change_context(OvmfFetchError::Fetch)?;
|
||||
|
||||
bytes
|
||||
.copy_to(&mut file)
|
||||
.map_err(Report::from)
|
||||
.change_context(OvmfFetchError::Io)?;
|
||||
|
||||
let mut bytes = reqwest::blocking::get(ovmf_url).map_err(Report::from).change_context(OvmfFetchError::Fetch)?;
|
||||
bytes.copy_to(&mut file).map_err(Report::from).change_context(OvmfFetchError::Io)?;
|
||||
Ok(ovmf_path.to_owned())
|
||||
}
|
||||
|
||||
|
@ -440,7 +395,7 @@ enum OvmfFetchError {
|
|||
Io,
|
||||
}
|
||||
|
||||
impl Context for OvmfFetchError {}
|
||||
impl Context for OvmfFetchError { }
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
enum Target {
|
||||
|
@ -467,10 +422,11 @@ enum Error {
|
|||
Qemu(Option<i32>),
|
||||
}
|
||||
|
||||
impl Context for Error {}
|
||||
impl Context for Error { }
|
||||
|
||||
fn fmt_qemu_err(e: Option<i32>) -> impl Display {
|
||||
struct W(Option<i32>);
|
||||
|
||||
impl Display for W {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if let Some(c) = self.0 {
|
||||
|
|
Loading…
Reference in New Issue