forked from AbleOS/ableos
Rewrote RepBuild
This commit is contained in:
parent
8d640b6a9b
commit
b802732acf
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -1,8 +1 @@
|
||||||
target/
|
target/
|
||||||
.gdb_history
|
|
||||||
!*/.gitkeep
|
|
||||||
__pycache__/
|
|
||||||
debug.log
|
|
||||||
/disk/
|
|
||||||
/limine/
|
|
||||||
/disk.img
|
|
||||||
|
|
5
.gitmodules
vendored
Normal file
5
.gitmodules
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[submodule "limine"]
|
||||||
|
path = limine
|
||||||
|
url = https://github.com/limine-bootloader/limine.git
|
||||||
|
branch = v4.x-branch-binary
|
||||||
|
shallow = true
|
976
Cargo.lock
generated
976
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,4 +0,0 @@
|
||||||
# Base Root Filesystem
|
|
||||||
|
|
||||||
This is the base root filesystem for ableOS. It's used by tepbuild while
|
|
||||||
building the disk image.
|
|
Binary file not shown.
|
@ -1,7 +0,0 @@
|
||||||
[logging]
|
|
||||||
enabled = true
|
|
||||||
level = "Trace"
|
|
||||||
log_to_serial = true
|
|
||||||
log_to_vterm = false
|
|
||||||
filter = ["ableos::ps2_mouse", "ableos::vterm", "ableos::devices::pci"]
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,252 +0,0 @@
|
||||||
# Able doesn't have a full keyboard
|
|
||||||
0-NONE
|
|
||||||
1-
|
|
||||||
2-
|
|
||||||
3-BACKSPACE
|
|
||||||
4-
|
|
||||||
5-
|
|
||||||
6-
|
|
||||||
7-
|
|
||||||
8-
|
|
||||||
9-TAB
|
|
||||||
10-
|
|
||||||
11-
|
|
||||||
12-
|
|
||||||
13-ENTER
|
|
||||||
14-
|
|
||||||
15-
|
|
||||||
16-SHIFT
|
|
||||||
17-CONTROL
|
|
||||||
18-ALT
|
|
||||||
19-PAUSE
|
|
||||||
20-CAPS_LOCK
|
|
||||||
21-
|
|
||||||
22-
|
|
||||||
23-
|
|
||||||
24-
|
|
||||||
25-
|
|
||||||
26-
|
|
||||||
27-
|
|
||||||
28-
|
|
||||||
29-
|
|
||||||
30-
|
|
||||||
31-
|
|
||||||
32-SPACE
|
|
||||||
33-PAGE_UP
|
|
||||||
34-PAGE_DOWN
|
|
||||||
35-END
|
|
||||||
36-HOME
|
|
||||||
37-ARROW_LEFT
|
|
||||||
38-ARROW_UP
|
|
||||||
39-ARROW_RIGHT
|
|
||||||
40-ARROW_DOWN
|
|
||||||
41-
|
|
||||||
42-
|
|
||||||
43-
|
|
||||||
44-
|
|
||||||
45-INSERT
|
|
||||||
46-DELETE
|
|
||||||
47-
|
|
||||||
48-0
|
|
||||||
49-1
|
|
||||||
50-2
|
|
||||||
51-3
|
|
||||||
52-4
|
|
||||||
53-5
|
|
||||||
54-6
|
|
||||||
55-7
|
|
||||||
56-8
|
|
||||||
57-9
|
|
||||||
58-
|
|
||||||
59-SEMICOLON
|
|
||||||
60-
|
|
||||||
61-EQUAL
|
|
||||||
62-
|
|
||||||
63-
|
|
||||||
64-
|
|
||||||
65-a
|
|
||||||
66-b
|
|
||||||
67-c
|
|
||||||
68-d
|
|
||||||
69-e
|
|
||||||
70-f
|
|
||||||
71-g
|
|
||||||
72-h
|
|
||||||
73-i
|
|
||||||
74-j
|
|
||||||
75-k
|
|
||||||
76-l
|
|
||||||
77-m
|
|
||||||
78-n
|
|
||||||
79-o
|
|
||||||
80-p
|
|
||||||
81-q
|
|
||||||
82-r
|
|
||||||
83-s
|
|
||||||
84-t
|
|
||||||
85-u
|
|
||||||
86-v
|
|
||||||
87-w
|
|
||||||
88-x
|
|
||||||
89-y
|
|
||||||
90-z
|
|
||||||
91-
|
|
||||||
92-
|
|
||||||
93-
|
|
||||||
94-
|
|
||||||
95-
|
|
||||||
96-
|
|
||||||
97-
|
|
||||||
98-
|
|
||||||
99-
|
|
||||||
100-
|
|
||||||
101-
|
|
||||||
102-
|
|
||||||
103-
|
|
||||||
106-
|
|
||||||
107-
|
|
||||||
108-
|
|
||||||
109-
|
|
||||||
110-
|
|
||||||
111-
|
|
||||||
112-FUNCTION_1
|
|
||||||
113-FUNCTION_2
|
|
||||||
114-FUNCTION_3
|
|
||||||
115-FUNCTION_4
|
|
||||||
116-FUNCTION_5
|
|
||||||
117-FUNCTION_6
|
|
||||||
118-FUNCTION_7
|
|
||||||
119-FUNCTION_8
|
|
||||||
120-FUNCTION_9
|
|
||||||
121-FUNCTION_10
|
|
||||||
122-FUNCTION_11
|
|
||||||
123-FUNCTION_12
|
|
||||||
124-
|
|
||||||
125-
|
|
||||||
126-
|
|
||||||
127-
|
|
||||||
128-
|
|
||||||
129-
|
|
||||||
130-
|
|
||||||
131-
|
|
||||||
132-
|
|
||||||
134-
|
|
||||||
135-
|
|
||||||
136-
|
|
||||||
137-
|
|
||||||
138-
|
|
||||||
139-
|
|
||||||
140-
|
|
||||||
141-
|
|
||||||
142-
|
|
||||||
143-
|
|
||||||
145-SCROLL_LOCK
|
|
||||||
146-
|
|
||||||
147-
|
|
||||||
148-
|
|
||||||
149-
|
|
||||||
150-
|
|
||||||
151-
|
|
||||||
152-
|
|
||||||
153-
|
|
||||||
154-
|
|
||||||
155-
|
|
||||||
156-
|
|
||||||
157-
|
|
||||||
158-
|
|
||||||
159-
|
|
||||||
160-
|
|
||||||
161-
|
|
||||||
162-
|
|
||||||
163-
|
|
||||||
164-
|
|
||||||
165-
|
|
||||||
166-
|
|
||||||
167-
|
|
||||||
168-
|
|
||||||
169-
|
|
||||||
170-
|
|
||||||
171-
|
|
||||||
172-
|
|
||||||
173-MINUS
|
|
||||||
174-
|
|
||||||
175-
|
|
||||||
176-
|
|
||||||
177-
|
|
||||||
178-
|
|
||||||
179-
|
|
||||||
180-
|
|
||||||
181-
|
|
||||||
182-
|
|
||||||
183-
|
|
||||||
184-
|
|
||||||
185-
|
|
||||||
186-
|
|
||||||
187-
|
|
||||||
188-COMMA
|
|
||||||
189-
|
|
||||||
190-PERIOD
|
|
||||||
191-FORWARD_SLASH
|
|
||||||
192-GRAVE
|
|
||||||
193-
|
|
||||||
194-
|
|
||||||
195-
|
|
||||||
196-
|
|
||||||
197-
|
|
||||||
198-
|
|
||||||
199-
|
|
||||||
200-
|
|
||||||
201-
|
|
||||||
202-
|
|
||||||
203-
|
|
||||||
204-
|
|
||||||
205-
|
|
||||||
206-
|
|
||||||
207-
|
|
||||||
208-
|
|
||||||
209-
|
|
||||||
210-
|
|
||||||
211-
|
|
||||||
212-
|
|
||||||
213-
|
|
||||||
214-
|
|
||||||
215-
|
|
||||||
216-
|
|
||||||
218-
|
|
||||||
219-BRACKET_LEFT
|
|
||||||
220-BACK_SLASH
|
|
||||||
221-BRACKET_RIGHT
|
|
||||||
222-QUOTE
|
|
||||||
223-
|
|
||||||
224-
|
|
||||||
225-
|
|
||||||
226-
|
|
||||||
227-
|
|
||||||
228-
|
|
||||||
229-
|
|
||||||
230-
|
|
||||||
231-
|
|
||||||
232-
|
|
||||||
233-
|
|
||||||
234-
|
|
||||||
235-
|
|
||||||
236-
|
|
||||||
237-
|
|
||||||
238-
|
|
||||||
239-
|
|
||||||
240-
|
|
||||||
241-
|
|
||||||
242-
|
|
||||||
243-
|
|
||||||
244-
|
|
||||||
245-
|
|
||||||
246-
|
|
||||||
247-
|
|
||||||
248-
|
|
||||||
249-
|
|
||||||
250-
|
|
||||||
251-
|
|
||||||
252-
|
|
||||||
253-
|
|
||||||
254-
|
|
||||||
255-
|
|
|
@ -1,14 +0,0 @@
|
||||||
boot/
|
|
||||||
├─ kernel.img
|
|
||||||
home/
|
|
||||||
├─ able/
|
|
||||||
│ ├─ bins/
|
|
||||||
│ ├─ config/
|
|
||||||
│ │ ├─ able_edit/
|
|
||||||
│ │ │ ├─ config.toml
|
|
||||||
│ ├─ irl_pic.png
|
|
||||||
│ ├─ password.txt
|
|
||||||
system/
|
|
||||||
├─ bins/
|
|
||||||
├─ configs/
|
|
||||||
│ ├─ kernel.toml
|
|
1
limine
Submodule
1
limine
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 83e6e5b4da7791ade3b367ceec8ce82c469d06db
|
|
@ -1,11 +1,15 @@
|
||||||
[package]
|
[package]
|
||||||
name = "repbuild"
|
name = "repbuild"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
colored = "2.0"
|
env_logger = "0.10"
|
||||||
udisks = "0.1"
|
error-stack = "0.2"
|
||||||
zbus = "2.3"
|
fatfs = "0.3"
|
||||||
|
log = "0.4"
|
||||||
|
|
||||||
|
[dependencies.nix]
|
||||||
|
version = "0.26"
|
||||||
|
default-features = false
|
||||||
|
features = ["fs"]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
${ABLEOS_KERNEL}=boot:///boot/kernel
|
${ABLEOS_KERNEL}=boot:///kernel
|
||||||
# TODO: Make a boot background image for ableOS
|
# TODO: Make a boot background image for ableOS
|
||||||
# ${WALLPAPER_PATH}=boot:///boot/bg.bmp
|
# ${WALLPAPER_PATH}=boot:///boot/bg.bmp
|
||||||
|
|
||||||
|
@ -18,5 +18,5 @@ TERM_BACKDROP=008080
|
||||||
# Setting a default resolution for the framebuffer
|
# Setting a default resolution for the framebuffer
|
||||||
RESOLUTION=800x600x24
|
RESOLUTION=800x600x24
|
||||||
|
|
||||||
MODULE_PATH=boot:///boot/initrd.tar
|
# MODULE_PATH=boot:///boot/initrd.tar
|
||||||
MODULE_CMDLINE=This is the first module.
|
# MODULE_CMDLINE=This is the first module.
|
|
@ -1,539 +1,170 @@
|
||||||
/*
|
use error_stack::{bail, report, Context, IntoReport, Result, ResultExt};
|
||||||
* Copyright (c) 2022, Umut İnan Erdoğan <umutinanerdogan@pm.me>
|
use fatfs::{FileSystem, FormatVolumeOptions, FsOptions, ReadWriteSeek};
|
||||||
* Copyright (c) 2022, able <abl3theabove@gmail.com>
|
use nix::fcntl::FallocateFlags;
|
||||||
*
|
use std::{fmt::Display, fs::File, io, os::fd::AsRawFd, path::Path, process::Command};
|
||||||
* SPDX-License-Identifier: MPL-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
use colored::*;
|
fn main() -> Result<(), Error> {
|
||||||
use std::{
|
env_logger::init();
|
||||||
fs::{self, File},
|
let mut args = std::env::args();
|
||||||
os::fd::AsRawFd,
|
args.next();
|
||||||
process::Command,
|
|
||||||
};
|
|
||||||
use udisks::{
|
|
||||||
filesystem::{MountOptions, UnMountOptions},
|
|
||||||
manager::LoopSetupOptions,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Options {
|
match args.next().as_deref() {
|
||||||
pub subcommand: Subcommand,
|
Some("build" | "b") => build(
|
||||||
pub arguments: Vec<String>,
|
args.next()
|
||||||
}
|
.map(|x| x == "-r" || x == "--release")
|
||||||
|
.unwrap_or_default(),
|
||||||
enum Subcommand {
|
)
|
||||||
BuildImage,
|
.change_context(Error::Build),
|
||||||
Doc,
|
Some("run" | "r") => {
|
||||||
Help,
|
build(
|
||||||
Run,
|
args.next()
|
||||||
Empty,
|
.map(|x| x == "-r" || x == "--release")
|
||||||
/// Run all tests for all architectures
|
.unwrap_or_default(),
|
||||||
Test,
|
|
||||||
Unknown(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Subcommand {
|
|
||||||
fn from_str<S: AsRef<str>>(str: S) -> Subcommand {
|
|
||||||
match str.as_ref() {
|
|
||||||
"build-image" => Subcommand::BuildImage,
|
|
||||||
"doc" => Subcommand::Doc,
|
|
||||||
"help" => Subcommand::Help,
|
|
||||||
"run" | "r" => Subcommand::Run,
|
|
||||||
"test" | "t" => Subcommand::Test,
|
|
||||||
"" => Subcommand::Empty,
|
|
||||||
unknown => Subcommand::Unknown(unknown.to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum MachineType {
|
|
||||||
X86_64,
|
|
||||||
RiscV64,
|
|
||||||
AArch64,
|
|
||||||
Unknown(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
let options = options();
|
|
||||||
|
|
||||||
match options.subcommand {
|
|
||||||
Subcommand::BuildImage => {
|
|
||||||
let machine_text = options.arguments.get(0).cloned().unwrap_or_default();
|
|
||||||
|
|
||||||
match machine(machine_text) {
|
|
||||||
MachineType::X86_64 => {
|
|
||||||
// Cleanup
|
|
||||||
// NOTE: we are not unwrapping these, as we don't want this to fail if they
|
|
||||||
// don't exist yet, probably not the best idea tho.
|
|
||||||
// FIXME: figure out a better way to ignore errors about these not existing
|
|
||||||
#[allow(unused_must_use)]
|
|
||||||
{
|
|
||||||
fs::remove_dir_all("./limine");
|
|
||||||
fs::remove_dir_all("./disk");
|
|
||||||
fs::remove_file("./target/disk.img");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build ableOS in release mode
|
|
||||||
Command::new("cargo")
|
|
||||||
.args(["build", "--release"])
|
|
||||||
.current_dir(fs::canonicalize("./kernel").unwrap())
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Create disk directory
|
|
||||||
fs::create_dir("./disk").unwrap();
|
|
||||||
|
|
||||||
// Clone limine 4.x binaries
|
|
||||||
Command::new("git")
|
|
||||||
.arg("clone")
|
|
||||||
.arg("https://github.com/limine-bootloader/limine.git")
|
|
||||||
.arg("--branch=v4.x-branch-binary")
|
|
||||||
.arg("--depth=1")
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("{}", "Building limine".bold());
|
|
||||||
Command::new("make")
|
|
||||||
.args(["-C", "limine"])
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("{}", "Allocating new disk image".bold());
|
|
||||||
Command::new("fallocate")
|
|
||||||
.args(["-l", "256M", "./target/disk.img"])
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("{}", "Partitioning disk image".bold());
|
|
||||||
let dbus_conn = zbus::blocking::Connection::system()?;
|
|
||||||
|
|
||||||
// Setup loop device
|
|
||||||
let disk_img = File::options()
|
|
||||||
.read(true)
|
|
||||||
.write(true)
|
|
||||||
.open("./target/disk.img")?;
|
|
||||||
let loopdev = udisks::manager::UDisks2ManagerProxyBlocking::new(&dbus_conn)?
|
|
||||||
.loop_setup(
|
|
||||||
disk_img.as_raw_fd().into(),
|
|
||||||
LoopSetupOptions {
|
|
||||||
no_user_interaction: true,
|
|
||||||
offset: 0,
|
|
||||||
size: 0,
|
|
||||||
readonly: false,
|
|
||||||
no_part_scan: false,
|
|
||||||
},
|
|
||||||
)?;
|
)?;
|
||||||
|
run()
|
||||||
// Create MBR
|
|
||||||
udisks::block::BlockProxyBlocking::builder(&dbus_conn)
|
|
||||||
.path(&loopdev)?
|
|
||||||
.build()?
|
|
||||||
.format("dos", Default::default())?;
|
|
||||||
|
|
||||||
// Create and format partition
|
|
||||||
let filesystem =
|
|
||||||
udisks::partition::PartitionTableProxyBlocking::builder(&dbus_conn)
|
|
||||||
.destination("org.freedesktop.UDisks2")?
|
|
||||||
.path(&loopdev)?
|
|
||||||
.build()?
|
|
||||||
.create_partition_and_format(
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
Default::default(),
|
|
||||||
"ext2",
|
|
||||||
[("take-ownership", true.into())].into_iter().collect(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let fsproxy = udisks::filesystem::FilesystemProxyBlocking::builder(&dbus_conn)
|
|
||||||
.path(&filesystem)?
|
|
||||||
.build()?;
|
|
||||||
|
|
||||||
// Mount the filesystem
|
|
||||||
let mountpoint = fsproxy
|
|
||||||
.mount(MountOptions {
|
|
||||||
no_user_interaction: true,
|
|
||||||
fs_type: String::new(),
|
|
||||||
mount_options: String::new(),
|
|
||||||
})
|
|
||||||
.or_else(|_| {
|
|
||||||
Ok::<String, zbus::Error>(loop {
|
|
||||||
if let Some(m) = fsproxy.mount_points()?.get(0) {
|
|
||||||
break m.to_string();
|
|
||||||
}
|
}
|
||||||
})
|
Some("help" | "h") => {
|
||||||
})?;
|
println!(
|
||||||
|
concat!(
|
||||||
// copy ./base/* over to ./disk
|
"AbleOS RepBuild\n",
|
||||||
Command::new("sh")
|
"Subcommands:\n",
|
||||||
.arg("-c")
|
" build (b): Build a bootable disk image\n",
|
||||||
.arg(format!("cp -r ./base/* {mountpoint}"))
|
" help (h): Print this message\n",
|
||||||
.status()?;
|
" run (r): Build and run AbleOS in QEMU\n\n",
|
||||||
|
"Options for build and run:\n",
|
||||||
// copy ./limine/limine.sys over to ./disk/boot
|
" -r: build in release mode",
|
||||||
Command::new("cp")
|
),
|
||||||
.args(["./limine/limine.sys", &format!("{mountpoint}/boot")])
|
|
||||||
.status()?;
|
|
||||||
|
|
||||||
// copy the kernel over to ./disk/boot/kernel
|
|
||||||
Command::new("cp")
|
|
||||||
.arg("./target/x86_64-ableos/release/kernel")
|
|
||||||
.arg(&format!("{mountpoint}/boot/kernel"))
|
|
||||||
.status()?;
|
|
||||||
|
|
||||||
// Unmount the filesystem (and the rest of things will follow)
|
|
||||||
fsproxy.unmount(UnMountOptions {
|
|
||||||
no_user_interaction: true,
|
|
||||||
force: false,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
println!("{}", "Deploying limine".bold());
|
|
||||||
Command::new("./limine/limine-deploy")
|
|
||||||
.arg("./target/disk.img")
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
MachineType::Unknown(unknown) => {
|
|
||||||
eprintln!(
|
|
||||||
"{}: unknown machine type `{}`",
|
|
||||||
"error".red().bold(),
|
|
||||||
unknown.bold(),
|
|
||||||
);
|
);
|
||||||
eprintln!("expected one of x86_64, riscv64 or aarch64");
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
eprintln!(
|
|
||||||
"{}: build-image not implemented for this machine type",
|
|
||||||
"error".red().bold(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Subcommand::Test => {
|
|
||||||
Command::new("cargo")
|
|
||||||
.args(["test", "--target=json_targets/x86_64-ableos.json"])
|
|
||||||
.current_dir(fs::canonicalize("./ableos").unwrap())
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// panic!("Test Infrastructure missing");
|
|
||||||
}
|
|
||||||
Subcommand::Doc => {
|
|
||||||
let machine_text = options.arguments.get(0).cloned().unwrap_or_default();
|
|
||||||
|
|
||||||
match machine(machine_text) {
|
|
||||||
MachineType::X86_64 => {
|
|
||||||
Command::new("cargo")
|
|
||||||
.args(["doc", "--open"])
|
|
||||||
.current_dir(fs::canonicalize("./ableos").unwrap())
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
MachineType::RiscV64 => {
|
|
||||||
Command::new("cargo")
|
|
||||||
.args(["doc", "--open", "--target=riscv64gc-unknown-none-elf"])
|
|
||||||
.current_dir(fs::canonicalize("./ableos").unwrap())
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
MachineType::AArch64 => {
|
|
||||||
Command::new("cargo")
|
|
||||||
.args(["doc", "--open", "--target=json_targets/aarch64-ableos.json"])
|
|
||||||
.current_dir(fs::canonicalize("./ableos").unwrap())
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
MachineType::Unknown(unknown) => {
|
|
||||||
eprintln!(
|
|
||||||
"{}: unknown machine type `{}`",
|
|
||||||
"error".red().bold(),
|
|
||||||
unknown.bold(),
|
|
||||||
);
|
|
||||||
eprintln!("expected one of x86_64, riscv64 or aarch64");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Subcommand::Help => help(),
|
|
||||||
Subcommand::Run => {
|
|
||||||
let machine_text = options.arguments.get(0).cloned().unwrap_or_default();
|
|
||||||
let debug = options.arguments.get(1).cloned().unwrap_or_default();
|
|
||||||
let debug = matches!(debug.as_str(), "--debug" | "--dbg" | "-d");
|
|
||||||
|
|
||||||
match machine(machine_text) {
|
|
||||||
MachineType::X86_64 if debug => {
|
|
||||||
// Build ableOS
|
|
||||||
Command::new("cargo")
|
|
||||||
.arg("build")
|
|
||||||
.current_dir(fs::canonicalize("./kernel").unwrap())
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Setup loopback device for disk.img, with partitions
|
|
||||||
// FIXME: don't do ths if running without changes
|
|
||||||
// Setup loop device
|
|
||||||
let disk_img = File::options()
|
|
||||||
.read(true)
|
|
||||||
.write(true)
|
|
||||||
.open("./target/disk.img")?;
|
|
||||||
let dbus_conn = zbus::blocking::Connection::system()?;
|
|
||||||
let loopdev = udisks::manager::UDisks2ManagerProxyBlocking::new(&dbus_conn)?
|
|
||||||
.loop_setup(
|
|
||||||
disk_img.as_raw_fd().into(),
|
|
||||||
LoopSetupOptions {
|
|
||||||
no_user_interaction: true,
|
|
||||||
offset: 0,
|
|
||||||
size: 0,
|
|
||||||
readonly: false,
|
|
||||||
no_part_scan: false,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let parts = udisks::partition::PartitionTableProxyBlocking::builder(&dbus_conn)
|
|
||||||
.destination("org.freedesktop.UDisks2")?
|
|
||||||
.path(loopdev)?
|
|
||||||
.build()?
|
|
||||||
.partitions()?;
|
|
||||||
|
|
||||||
let fsobjpath = parts.get(0).ok_or("missing boot partition")?;
|
|
||||||
let mountpoint =
|
|
||||||
udisks::filesystem::FilesystemProxyBlocking::builder(&dbus_conn)
|
|
||||||
.path(fsobjpath)?
|
|
||||||
.build()?
|
|
||||||
.mount(MountOptions {
|
|
||||||
no_user_interaction: true,
|
|
||||||
fs_type: String::new(),
|
|
||||||
mount_options: String::new(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// copy the kernel over to ./disk/boot/kernel
|
|
||||||
Command::new("cp")
|
|
||||||
.arg("./target/x86_64-ableos/debug/kernel")
|
|
||||||
.arg(format!("{mountpoint}/boot/kernel"))
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
udisks::filesystem::FilesystemProxyBlocking::builder(&dbus_conn)
|
|
||||||
.path(fsobjpath)?
|
|
||||||
.build()?
|
|
||||||
.unmount(UnMountOptions {
|
|
||||||
no_user_interaction: true,
|
|
||||||
force: false,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// run qemu with "-S", "-gdb", "tcp:9000"
|
|
||||||
Command::new("qemu-system-x86_64")
|
|
||||||
.args(["-device", "piix4-ide,id=ide"])
|
|
||||||
.arg("-drive")
|
|
||||||
.arg("file=./target/disk.img,format=raw,if=none,id=disk")
|
|
||||||
.args(["-device", "ide-hd,drive=disk,bus=ide.0"])
|
|
||||||
// .arg("--nodefaults")
|
|
||||||
.args(["-cpu", "Broadwell-v3"])
|
|
||||||
.args(["-m", "4G"])
|
|
||||||
.args(["-serial", "stdio"])
|
|
||||||
.args(["-smp", "cores=2"])
|
|
||||||
// .args(["-soundhw", "pcspk"])
|
|
||||||
// .args(["-device", "VGA"])
|
|
||||||
// .args(["-device", "virtio-gpu-pci"])
|
|
||||||
.args(["-device", "vmware-svga"])
|
|
||||||
.args(["-device", "sb16"])
|
|
||||||
// .args(["-machine", "pcspk-audiodev=0"])
|
|
||||||
// .args(["-qmp", "unix:../qmp-sock,server,nowait"])
|
|
||||||
.args(["-S", "-gdb", "tcp:9000"])
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
MachineType::X86_64 => {
|
|
||||||
// Build ableOS
|
|
||||||
Command::new("cargo")
|
|
||||||
.args(["build", "--release"])
|
|
||||||
.current_dir(fs::canonicalize("./kernel").unwrap())
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Setup loopback device for disk.img, with partitions
|
|
||||||
// FIXME: don't do ths if running without changes
|
|
||||||
let disk_img = File::options()
|
|
||||||
.read(true)
|
|
||||||
.write(true)
|
|
||||||
.open("./target/disk.img")?;
|
|
||||||
let dbus_conn = zbus::blocking::Connection::system()?;
|
|
||||||
let loopdev = udisks::manager::UDisks2ManagerProxyBlocking::new(&dbus_conn)?
|
|
||||||
.loop_setup(
|
|
||||||
disk_img.as_raw_fd().into(),
|
|
||||||
LoopSetupOptions {
|
|
||||||
no_user_interaction: true,
|
|
||||||
offset: 0,
|
|
||||||
size: 0,
|
|
||||||
readonly: false,
|
|
||||||
no_part_scan: false,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let parts = udisks::partition::PartitionTableProxyBlocking::builder(&dbus_conn)
|
|
||||||
.destination("org.freedesktop.UDisks2")?
|
|
||||||
.path(loopdev)?
|
|
||||||
.build()?
|
|
||||||
.partitions()?;
|
|
||||||
|
|
||||||
let fsproxy = udisks::filesystem::FilesystemProxyBlocking::builder(&dbus_conn)
|
|
||||||
.path(&parts[0])?
|
|
||||||
.build()?;
|
|
||||||
|
|
||||||
// Mount the filesystem
|
|
||||||
let mountpoint = fsproxy
|
|
||||||
.mount(MountOptions {
|
|
||||||
no_user_interaction: true,
|
|
||||||
fs_type: String::new(),
|
|
||||||
mount_options: String::new(),
|
|
||||||
})
|
|
||||||
.or_else(|_| {
|
|
||||||
Ok::<String, zbus::Error>(loop {
|
|
||||||
if let Some(m) = fsproxy.mount_points()?.get(0) {
|
|
||||||
break m.to_string();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// copy the kernel over to ./disk/boot/kernel
|
|
||||||
Command::new("cp")
|
|
||||||
.arg("./target/x86_64-ableos/release/kernel")
|
|
||||||
.arg(format!("{mountpoint}/boot/kernel"))
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
fsproxy.unmount(UnMountOptions {
|
|
||||||
no_user_interaction: true,
|
|
||||||
force: false,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// run qemu
|
|
||||||
Command::new("qemu-system-x86_64")
|
|
||||||
.args(["-device", "piix4-ide,id=ide"])
|
|
||||||
.arg("-drive")
|
|
||||||
.arg("file=./target/disk.img,format=raw,if=none,id=disk")
|
|
||||||
.args(["-device", "ide-hd,drive=disk,bus=ide.0"])
|
|
||||||
// .arg("--nodefaults")
|
|
||||||
.args(["-cpu", "Broadwell-v3"])
|
|
||||||
.args(["-m", "4G"])
|
|
||||||
.args(["-serial", "stdio"])
|
|
||||||
.args(["-smp", "cores=2"])
|
|
||||||
// .args(["-soundhw", "pcspk"])
|
|
||||||
// .args(["-device", "VGA"])
|
|
||||||
// .args(["-device", "virtio-gpu-pci"])
|
|
||||||
.args(["-device", "vmware-svga"])
|
|
||||||
.args(["-device", "sb16"])
|
|
||||||
// .args(["-machine", "pcspk-audiodev=0"])
|
|
||||||
// .args(["-qmp", "unix:../qmp-sock,server,nowait"])
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
MachineType::RiscV64 if debug => {
|
|
||||||
eprintln!(
|
|
||||||
"{}: debug is not implemented for riscv64",
|
|
||||||
"error".red().bold()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
MachineType::RiscV64 => {
|
|
||||||
Command::new("cargo")
|
|
||||||
.args(["build", "--release", "--target=riscv64gc-unknown-none-elf"])
|
|
||||||
.current_dir(fs::canonicalize("./ableos").unwrap())
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Command::new("qemu-system-riscv64")
|
|
||||||
.args(["-machine", "virt"])
|
|
||||||
.args(["-cpu", "rv64"])
|
|
||||||
.args(["-smp", "8"])
|
|
||||||
.args(["-m", "128M"])
|
|
||||||
.arg("-bios")
|
|
||||||
.arg("src/arch/riscv/firmwear/opensbi-riscv64-generic-fw_jump.bin")
|
|
||||||
.arg("-kernel")
|
|
||||||
.arg("target/riscv64gc-unknown-none-elf/release/ableos")
|
|
||||||
.current_dir(fs::canonicalize("./ableos").unwrap())
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
MachineType::AArch64 if debug => {
|
|
||||||
eprintln!(
|
|
||||||
"{}: debug is not implemented for aarch64",
|
|
||||||
"error".red().bold()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
MachineType::AArch64 => {
|
|
||||||
Command::new("cargo")
|
|
||||||
.args([
|
|
||||||
"build",
|
|
||||||
"--release",
|
|
||||||
"--target=json_targets/aarch64-ableos.json",
|
|
||||||
])
|
|
||||||
.current_dir(fs::canonicalize("./ableos").unwrap())
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Command::new("qemu-system-aarch64")
|
|
||||||
.args(["-machine", "virt"])
|
|
||||||
.args(["-m", "1024M"])
|
|
||||||
.args(["-cpu", "cortex-a53"])
|
|
||||||
.args(["-kernel", "target/aarch64-ableos/release/ableos"])
|
|
||||||
.args(["-device", "virtio-keyboard"])
|
|
||||||
.current_dir(fs::canonicalize("./ableos").unwrap())
|
|
||||||
.status()
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
MachineType::Unknown(unknown) => {
|
|
||||||
eprintln!(
|
|
||||||
"{}: unknown machine type `{}`",
|
|
||||||
"error".red().bold(),
|
|
||||||
unknown.bold(),
|
|
||||||
);
|
|
||||||
eprintln!("expected one of x86_64, riscv64 or aarch64");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Subcommand::Empty => {
|
|
||||||
eprintln!("{}: no subcommand passed", "error".red().bold());
|
|
||||||
help();
|
|
||||||
}
|
|
||||||
Subcommand::Unknown(unknown) => {
|
|
||||||
eprintln!(
|
|
||||||
"{}: unknown subcommand `{}`",
|
|
||||||
"error".red().bold(),
|
|
||||||
unknown.bold()
|
|
||||||
);
|
|
||||||
help();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
_ => Err(report!(Error::InvalidSubCom)),
|
||||||
fn options() -> Options {
|
|
||||||
let subcommand = std::env::args().nth(1).unwrap_or_default();
|
|
||||||
let arguments = std::env::args().skip(2).collect();
|
|
||||||
|
|
||||||
Options {
|
|
||||||
subcommand: Subcommand::from_str(subcommand),
|
|
||||||
arguments,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn machine<S: AsRef<str>>(text: S) -> MachineType {
|
fn get_fs() -> Result<FileSystem<impl ReadWriteSeek>, io::Error> {
|
||||||
match text.as_ref() {
|
let path = Path::new("target/disk.img");
|
||||||
"x86" | "x86_64" => MachineType::X86_64,
|
|
||||||
"riscv" | "riscv64" => MachineType::RiscV64,
|
match std::fs::metadata(path) {
|
||||||
"arm" | "arm64" | "aarch64" => MachineType::AArch64,
|
Err(e) if e.kind() == io::ErrorKind::NotFound => (),
|
||||||
"" => {
|
Err(e) => bail!(e),
|
||||||
eprintln!(
|
Ok(_) => {
|
||||||
"{}: no machine type passed, defaulting to x86_64",
|
return FileSystem::new(
|
||||||
"warning".yellow().bold()
|
File::options().read(true).write(true).open(path)?,
|
||||||
);
|
FsOptions::new(),
|
||||||
MachineType::X86_64
|
)
|
||||||
|
.into_report()
|
||||||
}
|
}
|
||||||
unknown => MachineType::Unknown(unknown.to_string()),
|
}
|
||||||
|
|
||||||
|
let mut img = File::options()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(path)?;
|
||||||
|
|
||||||
|
{
|
||||||
|
#[cfg(unix)]
|
||||||
|
nix::fcntl::fallocate(
|
||||||
|
img.as_raw_fd(),
|
||||||
|
FallocateFlags::from_bits(0).unwrap(),
|
||||||
|
0,
|
||||||
|
1024 * 1024 * 64,
|
||||||
|
)
|
||||||
|
.map_err(|e| std::io::Error::from_raw_os_error(e as i32))?;
|
||||||
|
|
||||||
|
#[cfg(not(any(unix)))]
|
||||||
|
compile_error!("unsupported platform");
|
||||||
|
}
|
||||||
|
|
||||||
|
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")?;
|
||||||
|
|
||||||
|
io::copy(
|
||||||
|
&mut File::open("limine/BOOTX64.EFI")?,
|
||||||
|
&mut bootdir.create_file("bootx64.efi")?,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
io::copy(
|
||||||
|
&mut File::open(Path::new("repbuild/limine.cfg"))?,
|
||||||
|
&mut fs.root_dir().create_file("limine.cfg")?,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
drop(bootdir);
|
||||||
|
Ok(fs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build(release: bool) -> Result<(), Error> {
|
||||||
|
let fs = get_fs().change_context(Error::Io)?;
|
||||||
|
let mut com = Command::new("cargo");
|
||||||
|
com.current_dir("kernel");
|
||||||
|
com.args(["b"]);
|
||||||
|
if release {
|
||||||
|
com.arg("-r");
|
||||||
|
}
|
||||||
|
|
||||||
|
com.status().into_report().change_context(Error::Build)?;
|
||||||
|
|
||||||
|
(|| -> std::io::Result<_> {
|
||||||
|
io::copy(
|
||||||
|
&mut File::open(
|
||||||
|
Path::new("target/x86_64-ableos")
|
||||||
|
.join(if release { "release" } else { "debug" })
|
||||||
|
.join("kernel"),
|
||||||
|
)?,
|
||||||
|
&mut fs.root_dir().create_file("kernel")?,
|
||||||
|
)
|
||||||
|
.map(|_| ())
|
||||||
|
})()
|
||||||
|
.into_report()
|
||||||
|
.change_context(Error::Io)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run() -> Result<(), Error> {
|
||||||
|
#[rustfmt::skip]
|
||||||
|
let args = [
|
||||||
|
"-bios", "/usr/share/OVMF/OVMF_CODE.fd",
|
||||||
|
"-enable-kvm",
|
||||||
|
"-cpu", "host",
|
||||||
|
"-drive", "file=target/disk.img,format=raw",
|
||||||
|
"-m", "4G",
|
||||||
|
"-serial", "stdio",
|
||||||
|
"-smp", "cores=2",
|
||||||
|
];
|
||||||
|
|
||||||
|
match Command::new("qemu-system-x86_64")
|
||||||
|
.args(args)
|
||||||
|
.status()
|
||||||
|
.into_report()
|
||||||
|
.change_context(Error::ProcessSpawn)?
|
||||||
|
{
|
||||||
|
s if s.success() => Ok(()),
|
||||||
|
s => Err(report!(Error::Qemu(s.code()))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn help() {
|
#[derive(Debug)]
|
||||||
todo!("`help`")
|
enum Error {
|
||||||
|
Build,
|
||||||
|
InvalidSubCom,
|
||||||
|
Io,
|
||||||
|
ProcessSpawn,
|
||||||
|
Qemu(Option<i32>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Context for Error {}
|
||||||
|
impl Display for Error {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Build => f.write_str("failed to build the kernel"),
|
||||||
|
Self::InvalidSubCom => {
|
||||||
|
f.write_str("missing or invalid subcommand (available: build, run)")
|
||||||
|
}
|
||||||
|
Self::Io => f.write_str("IO error"),
|
||||||
|
Self::ProcessSpawn => f.write_str("failed to spawn a process"),
|
||||||
|
Self::Qemu(Some(c)) => write!(f, "QEMU Error: {c}"),
|
||||||
|
Self::Qemu(None) => write!(f, "QEMU Error: interrupted by signal"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue