Build custom root image with ext2 FS, drop BIOS support

This commit is contained in:
pjht 2024-09-04 10:47:47 -05:00
parent fc4301f132
commit 0f6bad1b2d
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
9 changed files with 174 additions and 1167 deletions

View File

@ -1,2 +1,7 @@
[unstable] [unstable]
# enable the unstable artifact-dependencies feature, see
# https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dependencies
bindeps = true bindeps = true
[target.x86-64-unknown-none]
rustflags = ["-C", "force-unwind-tables", "-C", "link-args=/home/pterpstra/projects/os-rust/kernel/eh_frame.ld"]

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ initrd_path
kernel_path kernel_path
out_dir_path out_dir_path
capture.pcapng capture.pcapng
root.img

1128
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@ edition = "2021"
resolver = "2" resolver = "2"
[build-dependencies] [build-dependencies]
bootloader = { version = "0.11.7" } gpt = "4.0.0-rc.3"
kernel = { path = "../kernel", artifact = "bin", target = "x86_64-unknown-none" } kernel = { path = "../kernel", artifact = "bin", target = "x86_64-unknown-none" }
[dependencies] [dependencies]
@ -17,9 +17,9 @@ panic = "abort"
[profile.release] [profile.release]
panic = "abort" panic = "abort"
strip = false lto = true
debug = 2
# [workspace] [profile.release.package.kernel]
# members = ["kernel", "init", "test_proc", "toolchain_test"] strip = true
# exclude = ["x86_64", "rust"] opt-level = "z"
codegen-units=1

BIN
bootloader-x86_64-uefi.efi Executable file

Binary file not shown.

169
build.rs
View File

@ -1,54 +1,167 @@
use std::{ use std::{
env,
fs,
os::unix::ffi::OsStrExt, os::unix::ffi::OsStrExt,
path::{Path, PathBuf}, path::PathBuf,
process::Command, process::Command,
}; };
extern crate bootloader; use gpt::{mbr::ProtectiveMBR, GptConfig};
use bootloader::{BiosBoot, UefiBoot}; const ROOT_DISK_SIZE_MB: usize = 256;
fn main() { fn main() {
println!("cargo:rerun-if-changed=sysroot"); println!("cargo:rerun-if-changed=sysroot");
println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=initrd_file_list");
println!("cargo:rerun-if-changed=bootloader-x86_64-uefi.efi");
// set by cargo, build scripts should use this directory for output files // set by cargo, build scripts should use this directory for output files
let out_dir = std::env::var_os("OUT_DIR").unwrap(); let out_dir = std::env::var_os("OUT_DIR").unwrap();
std::fs::write("out_dir_path", out_dir.as_os_str().as_bytes()).unwrap();
let mut initrd_path = out_dir.clone(); let mut initrd_path = out_dir.clone();
initrd_path.push("/initrd.tar"); initrd_path.push("/initrd.tar");
Command::new("sh") Command::new("bash")
.arg("-c") .arg("-c")
.arg(format!("cd sysroot; tar cvf {:?} *", initrd_path)) .arg(format!(
.spawn() "cd sysroot; tar cvf {:?} $(cat ../initrd_file_list)",
.unwrap() initrd_path
.wait() ))
.output()
.unwrap(); .unwrap();
// set by cargo's artifact dependency feature, see let kernel = PathBuf::from(env::var_os("CARGO_BIN_FILE_KERNEL_kernel").unwrap());
// https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dependencies
let kernel = PathBuf::from(std::env::var_os("CARGO_BIN_FILE_KERNEL_kernel").unwrap());
// create an UEFI disk image (optional) let mut disk_path = out_dir.clone();
let mut uefi_path = out_dir.clone(); disk_path.push("/root.img");
uefi_path.push("/uefi.img");
UefiBoot::new(&kernel) Command::new("dd")
.set_ramdisk(Path::new(&initrd_path)) .arg("if=/dev/zero")
.create_disk_image(Path::new(&uefi_path)) .arg(format!("of={}", disk_path.to_str().unwrap()))
.arg("bs=1M")
.arg(format!("count={}", ROOT_DISK_SIZE_MB))
.output()
.unwrap(); .unwrap();
// create a BIOS disk image (optional) let mut disk = GptConfig::new().writable(true).create(&disk_path).unwrap();
let mut bios_path = out_dir.clone();
bios_path.push("/bios.img"); ProtectiveMBR::new()
BiosBoot::new(&kernel) .overwrite_lba0(disk.device_mut())
.set_ramdisk(Path::new(&initrd_path))
.create_disk_image(Path::new(&bios_path))
.unwrap(); .unwrap();
println!("cargo:rustc-env=UEFI_PATH={}", uefi_path.to_string_lossy()); let boot_part_id = disk
println!("cargo:rustc-env=BIOS_PATH={}", bios_path.to_string_lossy()); .add_partition("boot", 32 * 1024 * 1024, gpt::partition_types::EFI, 0, None)
.unwrap();
let root_part_id = disk
.add_partition(
"root",
disk.find_free_sectors()[1].1 * disk.logical_block_size().as_u64(),
gpt::partition_types::LINUX_FS,
0,
None,
)
.unwrap();
std::fs::write("kernel_path", kernel.as_os_str().as_bytes()).unwrap(); disk.write_inplace().unwrap();
std::fs::write("initrd_path", initrd_path.as_os_str().as_bytes()).unwrap();
std::fs::write("out_dir_path", out_dir.as_bytes()).unwrap(); let boot_part = &disk.partitions()[&boot_part_id];
let root_part = &disk.partitions()[&root_part_id];
Command::new("dd")
.arg(format!("if={}", disk_path.to_str().unwrap()))
.arg("of=tmp_ext2.img")
.arg(format!("bs={}", disk.logical_block_size().as_u64()))
.arg(format!("skip={}", root_part.first_lba))
.arg(format!("count={}", root_part.sectors_len().unwrap()))
.output()
.unwrap();
Command::new("mkfs.ext2")
.arg("-O")
.arg("^resize_inode")
.arg("-d")
.arg("sysroot")
.arg("tmp_ext2.img")
.output()
.unwrap();
Command::new("dd")
.arg("if=tmp_ext2.img")
.arg(format!("of={}", disk_path.to_str().unwrap()))
.arg(format!("bs={}", disk.logical_block_size().as_u64()))
.arg(format!("seek={}", root_part.first_lba))
.arg("conv=notrunc")
.output()
.unwrap();
fs::remove_file("tmp_ext2.img").unwrap();
Command::new("dd")
.arg(format!("if={}", disk_path.to_str().unwrap()))
.arg("of=tmp_esp.img")
.arg(format!("bs={}", disk.logical_block_size().as_u64()))
.arg(format!("skip={}", boot_part.first_lba))
.arg(format!("count={}", boot_part.sectors_len().unwrap()))
.output()
.unwrap();
Command::new("mkfs.fat")
.arg("-g")
.arg("64/32")
.arg("-i")
.arg("12345678")
.arg("-n")
.arg("kernel-bd3a")
.arg("tmp_esp.img")
.output()
.unwrap();
Command::new("mmd")
.arg("-i")
.arg("tmp_esp.img")
.arg("efi")
.output()
.unwrap();
Command::new("mmd")
.arg("-i")
.arg("tmp_esp.img")
.arg("efi/boot")
.output()
.unwrap();
Command::new("mcopy")
.arg("-i")
.arg("tmp_esp.img")
.arg("bootloader-x86_64-uefi.efi")
.arg("::efi/boot/bootx64.efi")
.output()
.unwrap();
Command::new("mcopy")
.arg("-i")
.arg("tmp_esp.img")
.arg(&kernel)
.arg("::kernel-x86_64")
.output()
.unwrap();
Command::new("mcopy")
.arg("-i")
.arg("tmp_esp.img")
.arg(&initrd_path)
.arg("::ramdisk")
.output()
.unwrap();
Command::new("dd")
.arg("if=tmp_esp.img")
.arg(format!("of={}", disk_path.to_str().unwrap()))
.arg(format!("bs={}", disk.logical_block_size().as_u64()))
.arg(format!("seek={}", boot_part.first_lba))
.arg("conv=notrunc")
.output()
.unwrap();
fs::remove_file("tmp_esp.img").unwrap();
println!("cargo:rustc-env=DISK_PATH={}", disk_path.to_string_lossy());
} }

BIN
ext2.img

Binary file not shown.

11
initrd_file_list Normal file
View File

@ -0,0 +1,11 @@
bin/init
bin/syslog
bin/vfs
bin/devfs
bin/tarfs
bin/initrd_driver
bin/pci
bin/partserv
bin/ext2
bin/ahci
etc/pci_config

View File

@ -1,7 +1,5 @@
fn main() { fn main() {
// read env variables that were set in build script let disk_path = env!("DISK_PATH");
let uefi_path = env!("UEFI_PATH");
//let bios_path = env!("BIOS_PATH");
let mut cmd = std::process::Command::new("qemu-system-x86_64"); let mut cmd = std::process::Command::new("qemu-system-x86_64");
cmd.arg("-nographic"); cmd.arg("-nographic");
@ -16,16 +14,9 @@ fn main() {
cmd.arg("-device").arg("ahci,id=ahci"); cmd.arg("-device").arg("ahci,id=ahci");
//cmd.arg("-device").arg("VGA"); //cmd.arg("-device").arg("VGA");
cmd.arg("-blockdev").arg(format!( cmd.arg("-blockdev").arg(format!(
"driver=raw,node-name=boot,file.driver=file,file.filename={uefi_path}" "driver=raw,node-name=disk,file.driver=file,file.filename={disk_path}"
)); ));
//cmd.arg("-blockdev").arg(format!( cmd.arg("-device").arg("ide-hd,drive=disk,bus=ahci.0");
// "driver=raw,node-name=boot,file.driver=file,file.filename={bios_path}"
//));
cmd.arg("-device").arg("ide-hd,drive=boot,bus=ahci.0");
cmd.arg("-blockdev").arg(format!(
"driver=raw,node-name=fs,file.driver=file,file.filename=ext2.img"
));
cmd.arg("-device").arg("ide-hd,drive=fs,bus=ahci.1");
cmd.arg("-device") cmd.arg("-device")
.arg("isa-debug-exit,iobase=0xf4,iosize=0x04"); .arg("isa-debug-exit,iobase=0xf4,iosize=0x04");
let mut child = cmd.spawn().unwrap(); let mut child = cmd.spawn().unwrap();