mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-26 19:03:27 +00:00
Overhaul OSDK
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
735d7b7b11
commit
33c53dcf2b
@ -14,7 +14,7 @@ use crate::{
|
||||
bin::{AsterBin, AsterBinType, AsterBzImageMeta, AsterElfMeta},
|
||||
file::BundleFile,
|
||||
},
|
||||
config_manager::boot::BootProtocol,
|
||||
config_manager::action::BootProtocol,
|
||||
util::get_current_crate_info,
|
||||
};
|
||||
|
||||
@ -153,7 +153,6 @@ fn install_setup_with_arch(
|
||||
cmd.arg("install").arg("linux-bzimage-setup");
|
||||
cmd.arg("--force");
|
||||
cmd.arg("--root").arg(install_dir.as_ref());
|
||||
// TODO: Use the latest revision when modifications on the `osdk` branch is merged.
|
||||
cmd.arg("--git").arg(crate::util::ASTER_GIT_LINK);
|
||||
cmd.arg("--rev").arg(crate::util::ASTER_GIT_REV);
|
||||
cmd.arg("--target").arg(match arch {
|
||||
|
@ -12,7 +12,7 @@ use crate::{
|
||||
file::BundleFile,
|
||||
vm_image::{AsterGrubIsoImageMeta, AsterVmImage, AsterVmImageType},
|
||||
},
|
||||
config_manager::{boot::BootProtocol, BuildConfig},
|
||||
config_manager::{action::BootProtocol, BuildConfig},
|
||||
util::get_current_crate_info,
|
||||
};
|
||||
|
||||
@ -24,7 +24,7 @@ pub fn create_bootdev_image(
|
||||
) -> AsterVmImage {
|
||||
let target_name = get_current_crate_info().name;
|
||||
let iso_root = &target_dir.as_ref().join("iso_root");
|
||||
let protocol = &config.manifest.boot.protocol;
|
||||
let protocol = &config.settings.boot_protocol;
|
||||
|
||||
// Clear or make the iso dir.
|
||||
if iso_root.exists() {
|
||||
@ -43,10 +43,15 @@ pub fn create_bootdev_image(
|
||||
|
||||
// Make the kernel image and place it in the boot directory.
|
||||
match protocol {
|
||||
BootProtocol::LinuxLegacy32 | BootProtocol::LinuxEfiHandover64 => {
|
||||
make_install_bzimage(iso_root.join("boot"), &target_dir, aster_bin, protocol);
|
||||
Some(BootProtocol::LinuxLegacy32) | Some(BootProtocol::LinuxEfiHandover64) => {
|
||||
make_install_bzimage(
|
||||
iso_root.join("boot"),
|
||||
&target_dir,
|
||||
aster_bin,
|
||||
&protocol.clone().unwrap(),
|
||||
);
|
||||
}
|
||||
BootProtocol::Multiboot | BootProtocol::Multiboot2 => {
|
||||
_ => {
|
||||
// Copy the kernel image to the boot directory.
|
||||
let target_path = iso_root.join("boot").join(&target_name);
|
||||
fs::copy(aster_bin.path(), target_path).unwrap();
|
||||
@ -60,17 +65,21 @@ pub fn create_bootdev_image(
|
||||
None
|
||||
};
|
||||
let grub_cfg = generate_grub_cfg(
|
||||
&config.manifest.kcmd_args.join(" "),
|
||||
&config.settings.combined_kcmd_args().join(" "),
|
||||
true,
|
||||
initramfs_in_image,
|
||||
protocol,
|
||||
&protocol.clone().unwrap_or(BootProtocol::Multiboot2),
|
||||
);
|
||||
let grub_cfg_path = iso_root.join("boot").join("grub").join("grub.cfg");
|
||||
fs::write(grub_cfg_path, grub_cfg).unwrap();
|
||||
|
||||
// Make the boot device CDROM image using `grub-mkrescue`.
|
||||
let iso_path = &target_dir.as_ref().join(target_name.to_string() + ".iso");
|
||||
let grub_mkrescue_bin = &config.manifest.boot.grub_mkrescue.clone().unwrap();
|
||||
let grub_mkrescue_bin = &config
|
||||
.settings
|
||||
.grub_mkrescue
|
||||
.clone()
|
||||
.unwrap_or_else(|| PathBuf::from("grub-mkrescue"));
|
||||
let mut grub_mkrescue_cmd = std::process::Command::new(grub_mkrescue_bin.as_os_str());
|
||||
grub_mkrescue_cmd
|
||||
.arg(iso_root.as_os_str())
|
||||
|
@ -13,11 +13,10 @@ use crate::{
|
||||
base_crate::new_base_crate,
|
||||
bundle::{
|
||||
bin::{AsterBin, AsterBinType, AsterElfMeta},
|
||||
file::Initramfs,
|
||||
Bundle,
|
||||
},
|
||||
cli::CargoArgs,
|
||||
config_manager::{qemu::QemuMachine, BuildConfig},
|
||||
config_manager::{action::Bootloader, BuildConfig},
|
||||
error::Errno,
|
||||
error_msg,
|
||||
util::{get_current_crate_info, get_target_directory},
|
||||
@ -79,20 +78,10 @@ pub fn do_build(
|
||||
}
|
||||
let mut bundle = Bundle::new(
|
||||
&bundle_path,
|
||||
config.manifest.kcmd_args.clone(),
|
||||
config.manifest.boot.clone(),
|
||||
config.manifest.qemu.clone(),
|
||||
config.settings.clone(),
|
||||
config.cargo_args.clone(),
|
||||
);
|
||||
|
||||
if let Some(ref initramfs) = config.manifest.initramfs {
|
||||
if !initramfs.exists() {
|
||||
error_msg!("initramfs file not found: {}", initramfs.display());
|
||||
process::exit(Errno::BuildCrate as _);
|
||||
}
|
||||
bundle.add_initramfs(Initramfs::new(initramfs));
|
||||
};
|
||||
|
||||
info!("Building kernel ELF");
|
||||
let aster_elf = build_kernel_elf(
|
||||
&config.arch,
|
||||
@ -101,20 +90,17 @@ pub fn do_build(
|
||||
rustflags,
|
||||
);
|
||||
|
||||
if matches!(config.manifest.qemu.machine, QemuMachine::Microvm) {
|
||||
if matches!(config.settings.bootloader, Some(Bootloader::Qemu)) {
|
||||
let stripped_elf = strip_elf_for_qemu(&osdk_target_directory, &aster_elf);
|
||||
bundle.consume_aster_bin(stripped_elf);
|
||||
}
|
||||
|
||||
// TODO: A boot device is required if we use GRUB. Actually you can boot
|
||||
// a multiboot kernel with Q35 machine directly without a bootloader.
|
||||
// We are currently ignoring this case.
|
||||
if matches!(config.manifest.qemu.machine, QemuMachine::Q35) {
|
||||
if matches!(config.settings.bootloader, Some(Bootloader::Grub)) {
|
||||
info!("Building boot device image");
|
||||
let bootdev_image = grub::create_bootdev_image(
|
||||
&osdk_target_directory,
|
||||
&aster_elf,
|
||||
config.manifest.initramfs.as_ref(),
|
||||
config.settings.initramfs.as_ref(),
|
||||
config,
|
||||
);
|
||||
bundle.consume_vm_image(bootdev_image);
|
||||
@ -134,7 +120,7 @@ fn build_kernel_elf(
|
||||
|
||||
let env_rustflags = std::env::var("RUSTFLAGS").unwrap_or_default();
|
||||
let mut rustflags = Vec::from(rustflags);
|
||||
// We disable RELRO and PIC here because they cause link failures
|
||||
// Asterinas does not support PIC yet.
|
||||
rustflags.extend(vec![
|
||||
&env_rustflags,
|
||||
&rustc_linker_script_arg,
|
||||
|
18
osdk/src/commands/new/kernel.OSDK.toml.template
Normal file
18
osdk/src/commands/new/kernel.OSDK.toml.template
Normal file
@ -0,0 +1,18 @@
|
||||
[project]
|
||||
type = "kernel"
|
||||
|
||||
[run]
|
||||
bootloader = "grub"
|
||||
ovmf = "/usr/share/OVMF"
|
||||
qemu_args = [
|
||||
"-machine q35,kernel-irqchip=split",
|
||||
"-cpu Icelake-Server,+x2apic",
|
||||
"--no-reboot",
|
||||
"-m 2G",
|
||||
"-nographic",
|
||||
"-serial chardev:mux",
|
||||
"-monitor chardev:mux",
|
||||
"-chardev stdio,id=mux,mux=on,signal=off",
|
||||
"-display none",
|
||||
"-device isa-debug-exit,iobase=0xf4,iosize=0x04",
|
||||
]
|
17
osdk/src/commands/new/lib.OSDK.toml.template
Normal file
17
osdk/src/commands/new/lib.OSDK.toml.template
Normal file
@ -0,0 +1,17 @@
|
||||
[project]
|
||||
type = "library"
|
||||
|
||||
[test]
|
||||
bootloader = "qemu"
|
||||
qemu_args = [
|
||||
"-machine q35,kernel-irqchip=split",
|
||||
"-cpu Icelake-Server,+x2apic",
|
||||
"--no-reboot",
|
||||
"-m 2G",
|
||||
"-nographic",
|
||||
"-serial chardev:mux",
|
||||
"-monitor chardev:mux",
|
||||
"-chardev stdio,id=mux,mux=on,signal=off",
|
||||
"-display none",
|
||||
"-device isa-debug-exit,iobase=0xf4,iosize=0x04",
|
||||
]
|
@ -4,6 +4,7 @@ use std::{fs, path::PathBuf, process, str::FromStr};
|
||||
|
||||
use crate::{
|
||||
cli::NewArgs,
|
||||
config_manager::manifest::ProjectType,
|
||||
error::Errno,
|
||||
error_msg,
|
||||
util::{aster_crate_dep, cargo_new_lib, get_cargo_metadata},
|
||||
@ -13,13 +14,9 @@ pub fn execute_new_command(args: &NewArgs) {
|
||||
cargo_new_lib(&args.crate_name);
|
||||
let cargo_metadata = get_cargo_metadata(Some(&args.crate_name), None::<&[&str]>).unwrap();
|
||||
add_manifest_dependencies(&cargo_metadata, &args.crate_name);
|
||||
create_osdk_manifest(&cargo_metadata);
|
||||
create_osdk_manifest(&cargo_metadata, &args.type_);
|
||||
exclude_osdk_base(&cargo_metadata);
|
||||
if args.kernel {
|
||||
write_kernel_template(&cargo_metadata, &args.crate_name);
|
||||
} else {
|
||||
write_library_template(&cargo_metadata, &args.crate_name);
|
||||
}
|
||||
write_src_template(&cargo_metadata, &args.crate_name, &args.type_);
|
||||
add_rust_toolchain(&cargo_metadata);
|
||||
}
|
||||
|
||||
@ -83,7 +80,7 @@ fn exclude_osdk_base(metadata: &serde_json::Value) {
|
||||
fs::write(workspace_manifest_path, content).unwrap();
|
||||
}
|
||||
|
||||
fn create_osdk_manifest(cargo_metadata: &serde_json::Value) {
|
||||
fn create_osdk_manifest(cargo_metadata: &serde_json::Value, type_: &ProjectType) {
|
||||
let osdk_manifest_path = {
|
||||
let workspace_root = get_workspace_root(cargo_metadata);
|
||||
PathBuf::from(workspace_root).join("OSDK.toml")
|
||||
@ -95,42 +92,34 @@ fn create_osdk_manifest(cargo_metadata: &serde_json::Value) {
|
||||
}
|
||||
|
||||
// Create `OSDK.toml` for the workspace
|
||||
// FIXME: we need ovmf for grub-efi, the user may not have it.
|
||||
// The apt OVMF repo installs to `/usr/share/OVMF`
|
||||
fs::write(
|
||||
osdk_manifest_path,
|
||||
r#"
|
||||
[boot]
|
||||
ovmf = "/usr/share/OVMF"
|
||||
protocol = "multiboot"
|
||||
[qemu]
|
||||
machine = "q35"
|
||||
args = [
|
||||
"--no-reboot",
|
||||
"-m 2G",
|
||||
"-nographic",
|
||||
"-serial chardev:mux",
|
||||
"-monitor chardev:mux",
|
||||
"-chardev stdio,id=mux,mux=on,signal=off",
|
||||
"-display none",
|
||||
"-device isa-debug-exit,iobase=0xf4,iosize=0x04",
|
||||
]
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/// Write the default content of `src/kernel.rs`, with contents in provided template.
|
||||
fn write_kernel_template(cargo_metadata: &serde_json::Value, crate_name: &str) {
|
||||
let src_path = get_src_path(cargo_metadata, crate_name);
|
||||
let contents = include_str!("kernel.template");
|
||||
fs::write(src_path, contents).unwrap();
|
||||
let contents = match type_ {
|
||||
ProjectType::Kernel => {
|
||||
include_str!("kernel.OSDK.toml.template")
|
||||
}
|
||||
ProjectType::Library => {
|
||||
include_str!("lib.OSDK.toml.template")
|
||||
}
|
||||
ProjectType::Module => {
|
||||
todo!()
|
||||
}
|
||||
};
|
||||
fs::write(osdk_manifest_path, contents).unwrap();
|
||||
}
|
||||
|
||||
/// Write the default content of `src/lib.rs`, with contents in provided template.
|
||||
fn write_library_template(cargo_metadata: &serde_json::Value, crate_name: &str) {
|
||||
fn write_src_template(cargo_metadata: &serde_json::Value, crate_name: &str, type_: &ProjectType) {
|
||||
let src_path = get_src_path(cargo_metadata, crate_name);
|
||||
let contents = include_str!("lib.template");
|
||||
let contents = match type_ {
|
||||
ProjectType::Kernel => {
|
||||
include_str!("kernel.template")
|
||||
}
|
||||
ProjectType::Library => {
|
||||
include_str!("lib.template")
|
||||
}
|
||||
ProjectType::Module => {
|
||||
todo!()
|
||||
}
|
||||
};
|
||||
fs::write(src_path, contents).unwrap();
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ pub fn execute_run_command(config: &RunConfig) {
|
||||
let existing_bundle = Bundle::load(&default_bundle_directory);
|
||||
|
||||
let config = RunConfig {
|
||||
manifest: {
|
||||
settings: {
|
||||
if config.gdb_server_args.is_gdb_enabled {
|
||||
let qemu_gdb_args: Vec<_> = {
|
||||
let gdb_stub_addr = config.gdb_server_args.gdb_server_addr.as_str();
|
||||
@ -55,14 +55,14 @@ pub fn execute_run_command(config: &RunConfig) {
|
||||
|
||||
let qemu_gdb_args: Vec<_> = qemu_gdb_args
|
||||
.into_iter()
|
||||
.filter(|arg| !config.manifest.qemu.args.iter().any(|x| x == arg))
|
||||
.filter(|arg| !config.settings.qemu_args.iter().any(|x| x == arg))
|
||||
.map(|x| x.to_string())
|
||||
.collect();
|
||||
let mut manifest = config.manifest.clone();
|
||||
manifest.qemu.args.extend(qemu_gdb_args);
|
||||
manifest
|
||||
let mut settings = config.settings.clone();
|
||||
settings.qemu_args.extend(qemu_gdb_args);
|
||||
settings
|
||||
} else {
|
||||
config.manifest.clone()
|
||||
config.settings.clone()
|
||||
}
|
||||
},
|
||||
..config.clone()
|
||||
@ -95,8 +95,8 @@ pub fn execute_run_command(config: &RunConfig) {
|
||||
}
|
||||
|
||||
let required_build_config = BuildConfig {
|
||||
arch: config.arch.clone(),
|
||||
manifest: config.manifest.clone(),
|
||||
arch: config.arch,
|
||||
settings: config.settings.clone(),
|
||||
cargo_args: config.cargo_args.clone(),
|
||||
};
|
||||
|
||||
|
@ -56,8 +56,8 @@ pub static KTEST_CRATE_WHITELIST: Option<&[&str]> = Some(&{:#?});
|
||||
let target_name = get_current_crate_info().name;
|
||||
let default_bundle_directory = osdk_target_directory.join(target_name);
|
||||
let required_build_config = BuildConfig {
|
||||
arch: config.arch.clone(),
|
||||
manifest: config.manifest.clone(),
|
||||
arch: config.arch,
|
||||
settings: config.settings.clone(),
|
||||
cargo_args: config.cargo_args.clone(),
|
||||
};
|
||||
let original_dir = std::env::current_dir().unwrap();
|
||||
@ -73,8 +73,8 @@ pub static KTEST_CRATE_WHITELIST: Option<&[&str]> = Some(&{:#?});
|
||||
std::env::set_current_dir(original_dir).unwrap();
|
||||
|
||||
let required_run_config = RunConfig {
|
||||
arch: config.arch.clone(),
|
||||
manifest: required_build_config.manifest.clone(),
|
||||
arch: config.arch,
|
||||
settings: required_build_config.settings.clone(),
|
||||
cargo_args: required_build_config.cargo_args.clone(),
|
||||
gdb_server_args: GdbServerArgs::default(),
|
||||
};
|
||||
|
Reference in New Issue
Block a user