mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 12:56:48 +00:00
Add protected mode sub-crate for Linux boot setup
This commit is contained in:
parent
7d5295ab25
commit
d0c84e0b6f
4
.github/workflows/cargo_check.yml
vendored
4
.github/workflows/cargo_check.yml
vendored
@ -10,9 +10,9 @@ on:
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
container: jinuxdev/jinux:0.1.1
|
||||
container: jinuxdev/jinux:0.1.2
|
||||
steps:
|
||||
- run: echo "Running in jinuxdev/jinux:0.1.1"
|
||||
- run: echo "Running in jinuxdev/jinux:0.1.2"
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
|
14
.github/workflows/syscall_test.yml
vendored
14
.github/workflows/syscall_test.yml
vendored
@ -10,9 +10,9 @@ on:
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
container: jinuxdev/jinux:0.1.1
|
||||
container: jinuxdev/jinux:0.1.2
|
||||
steps:
|
||||
- run: echo "Running in jinuxdev/jinux:0.1.1"
|
||||
- run: echo "Running in jinuxdev/jinux:0.1.2"
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
@ -20,8 +20,8 @@ jobs:
|
||||
id: syscall_test_mb2
|
||||
run: RUSTFLAGS="-C opt-level=1" make run AUTO_SYSCALL_TEST=1 ENABLE_KVM=0 SKIP_GRUB_MENU=1 BOOT_METHOD=grub-multiboot2
|
||||
|
||||
- name: Syscall Test (Linux Boot Protocol)
|
||||
id: syscall_test_lbp
|
||||
run: RUSTFLAGS="-C opt-level=1" make run AUTO_SYSCALL_TEST=1 ENABLE_KVM=0 SKIP_GRUB_MENU=1 BOOT_METHOD=grub-linux
|
||||
|
||||
# TODO: include the integration tests for Multiboot and MicroVM, which are not ready yet.
|
||||
# TODO: include the integration tests for Multiboot/MicroVM/Linux boot methods, which are not ready yet.
|
||||
|
||||
# - name: Syscall Test (Linux Boot Protocol)
|
||||
# id: syscall_test_lbp
|
||||
# run: RUSTFLAGS="-C opt-level=1" make run AUTO_SYSCALL_TEST=1 ENABLE_KVM=0 SKIP_GRUB_MENU=1 BOOT_METHOD=grub-linux
|
||||
|
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -599,7 +599,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "jinux"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"component",
|
||||
"jinux-frame",
|
||||
@ -659,6 +659,10 @@ dependencies = [
|
||||
"x86_64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jinux-frame-x86-boot-setup"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "jinux-framebuffer"
|
||||
version = "0.1.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "jinux"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
edition = "2021"
|
||||
|
||||
[[bin]]
|
||||
@ -22,6 +22,7 @@ jinux-framebuffer = { path = "services/comps/framebuffer" }
|
||||
members = [
|
||||
"build",
|
||||
"framework/jinux-frame",
|
||||
"framework/jinux-frame/src/arch/x86/boot/linux_boot/setup",
|
||||
"framework/libs/align_ext",
|
||||
"services/comps/virtio",
|
||||
"services/comps/input",
|
||||
|
3
Makefile
3
Makefile
@ -56,7 +56,8 @@ export
|
||||
|
||||
export JINUX_BOOT_PROTOCOL=$(BOOT_PROTOCOL)
|
||||
|
||||
# GNU toolchain variables
|
||||
# Toolchain variables
|
||||
export CARGO := cargo
|
||||
export AS := as
|
||||
export CC := gcc
|
||||
export OBJCOPY := objcopy
|
||||
|
@ -34,12 +34,12 @@ git clone [repository url]
|
||||
|
||||
2. After downloading the source code, run the following command to pull the development image.
|
||||
```bash
|
||||
docker pull jinuxdev/jinux:0.1.1
|
||||
docker pull jinuxdev/jinux:0.1.2
|
||||
```
|
||||
|
||||
3. Start the development container.
|
||||
```bash
|
||||
docker run -it --privileged --network=host --device=/dev/kvm -v `pwd`:/root/jinux jinuxdev/jinux:0.1.1
|
||||
docker run -it --privileged --network=host --device=/dev/kvm -v `pwd`:/root/jinux jinuxdev/jinux:0.1.2
|
||||
```
|
||||
|
||||
**All build and test commands should be run inside the development container.**
|
||||
|
17
build.rs
17
build.rs
@ -1,7 +1,7 @@
|
||||
use std::{error::Error, path::PathBuf};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
let linker_script_path = get_source_dir()
|
||||
let linker_script_path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap())
|
||||
.join("framework")
|
||||
.join("jinux-frame")
|
||||
.join("src")
|
||||
@ -9,19 +9,8 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
.join("x86")
|
||||
.join("boot")
|
||||
.join("linker.ld");
|
||||
println!(
|
||||
"cargo:rerun-if-changed={}",
|
||||
linker_script_path.to_str().unwrap()
|
||||
);
|
||||
println!(
|
||||
"cargo:rustc-link-arg=-T{}",
|
||||
linker_script_path.to_str().unwrap()
|
||||
);
|
||||
println!("cargo:rerun-if-changed={}", linker_script_path.display());
|
||||
println!("cargo:rustc-link-arg=-T{}", linker_script_path.display());
|
||||
println!("cargo:rerun-if-env-changed=CARGO_PKG_NAME");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_source_dir() -> PathBuf {
|
||||
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
PathBuf::from(manifest_dir)
|
||||
}
|
||||
|
@ -63,7 +63,9 @@ pub fn create_bootdev_image(
|
||||
// Find the setup header in the build script output directory.
|
||||
let out_dir = glob("target/x86_64-custom/debug/build/jinux-frame-*").unwrap();
|
||||
let header_bin = Path::new(out_dir.into_iter().next().unwrap().unwrap().as_path())
|
||||
.join("out/linux_header.bin");
|
||||
.join("out")
|
||||
.join("bin")
|
||||
.join("jinux-frame-x86-boot-setup.bin");
|
||||
|
||||
// Deliver the kernel image to the boot directory.
|
||||
match protocol {
|
||||
|
@ -5,59 +5,65 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_source_dir() -> PathBuf {
|
||||
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
PathBuf::from(manifest_dir)
|
||||
}
|
||||
|
||||
fn get_header_out_dir() -> PathBuf {
|
||||
PathBuf::from(std::env::var("OUT_DIR").unwrap())
|
||||
}
|
||||
|
||||
fn build_linux_setup_header() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
// Compile the header to raw binary.
|
||||
let linux_boot_header_asm_path = get_source_dir()
|
||||
// Build the setup header to raw binary.
|
||||
let source_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
let out_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
|
||||
let setup_crate_dir = source_dir
|
||||
.join("src")
|
||||
.join("arch")
|
||||
.join("x86")
|
||||
.join("boot")
|
||||
.join("linux_boot")
|
||||
.join("header.S");
|
||||
.join("setup");
|
||||
let target_json = setup_crate_dir.join("x86_64-i386_protected_mode.json");
|
||||
|
||||
println!(
|
||||
"cargo:rerun-if-changed={}",
|
||||
linux_boot_header_asm_path.to_str().unwrap()
|
||||
setup_crate_dir.to_str().unwrap()
|
||||
);
|
||||
let linux_boot_header_elf_path = get_header_out_dir().join("linux_header.o");
|
||||
let gas = std::env::var("AS").unwrap();
|
||||
let mut cmd = std::process::Command::new(gas);
|
||||
cmd.arg(linux_boot_header_asm_path);
|
||||
cmd.arg("-o")
|
||||
.arg(linux_boot_header_elf_path.to_str().unwrap());
|
||||
|
||||
let cargo = std::env::var("CARGO").unwrap();
|
||||
let mut cmd = std::process::Command::new(cargo);
|
||||
cmd.arg("install").arg("jinux-frame-x86-boot-setup");
|
||||
cmd.arg("--locked");
|
||||
cmd.arg("--path").arg(setup_crate_dir.to_str().unwrap());
|
||||
cmd.arg("--target").arg(target_json.as_os_str());
|
||||
cmd.arg("-Zbuild-std=core,compiler_builtins");
|
||||
cmd.arg("-Zbuild-std-features=compiler-builtins-mem");
|
||||
cmd.arg("--root").arg(out_dir.as_os_str());
|
||||
cmd.env_remove("RUSTFLAGS");
|
||||
cmd.env_remove("CARGO_ENCODED_RUSTFLAGS");
|
||||
let output = cmd.output()?;
|
||||
if !output.status.success() {
|
||||
std::io::stdout().write_all(&output.stdout).unwrap();
|
||||
std::io::stderr().write_all(&output.stderr).unwrap();
|
||||
panic!(
|
||||
"Failed to compile linux boot header:\n\tcommand `{:?}`\n\treturned {}",
|
||||
return Err(format!(
|
||||
"Failed to build linux x86 setup header::\n\tcommand `{:?}`\n\treturned {}",
|
||||
cmd, output.status
|
||||
);
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
// Strip the elf header to get the raw header.
|
||||
let linux_boot_header_bin_path = get_header_out_dir().join("linux_header.bin");
|
||||
let elf_path = out_dir.join("bin").join("jinux-frame-x86-boot-setup");
|
||||
let bin_path = out_dir.join("bin").join("jinux-frame-x86-boot-setup.bin");
|
||||
|
||||
let objcopy = std::env::var("OBJCOPY").unwrap();
|
||||
let mut cmd = std::process::Command::new(objcopy);
|
||||
cmd.arg("-O").arg("binary");
|
||||
cmd.arg("-j").arg(".boot_compatibility_bin");
|
||||
cmd.arg(linux_boot_header_elf_path.to_str().unwrap());
|
||||
cmd.arg(linux_boot_header_bin_path.to_str().unwrap());
|
||||
cmd.arg("-j").arg(".boot_real_mode");
|
||||
cmd.arg(elf_path.to_str().unwrap());
|
||||
cmd.arg(bin_path.to_str().unwrap());
|
||||
let output = cmd.output()?;
|
||||
if !output.status.success() {
|
||||
std::io::stdout().write_all(&output.stdout).unwrap();
|
||||
std::io::stderr().write_all(&output.stderr).unwrap();
|
||||
panic!(
|
||||
return Err(format!(
|
||||
"Failed to strip linux boot header:\n\tcommand `{:?}`\n\treturned {}",
|
||||
cmd, output.status
|
||||
);
|
||||
)
|
||||
.into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "jinux-frame-x86-boot-setup"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
@ -0,0 +1,9 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
let source_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
println!(
|
||||
"cargo:rustc-link-arg-bins=--script={}",
|
||||
source_dir.join("linker.ld").display()
|
||||
)
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
ENTRY(start_of_setup)
|
||||
OUTPUT_ARCH(i386:x86)
|
||||
OUTPUT_FORMAT(elf32-i386)
|
||||
|
||||
SETUP_LMA = 0x1000;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = SETUP_LMA;
|
||||
|
||||
.boot_real_mode : AT(ADDR(.boot_real_mode) - SETUP_LMA) { KEEP(*(.boot_real_mode)) }
|
||||
|
||||
.text : AT(ADDR(.text) - SETUP_LMA) { *(.text .text.*) }
|
||||
.rodata : AT(ADDR(.rodata) - SETUP_LMA) { *(.rodata .rodata.*) }
|
||||
|
||||
.data : AT(ADDR(.data) - SETUP_LMA) { *(.data .data.*) }
|
||||
.bss : AT(ADDR(.bss) - SETUP_LMA) {
|
||||
__bss = .;
|
||||
*(.bss .bss.*) *(COMMON)
|
||||
__bss_end = .;
|
||||
}
|
||||
}
|
@ -2,11 +2,9 @@
|
||||
// See https://www.kernel.org/doc/html/v5.6/x86/boot.html for
|
||||
// more information on the Linux x86 Boot Protocol.
|
||||
|
||||
.intel_syntax noprefix
|
||||
|
||||
// The section name is used by the build script to strip and make
|
||||
// the binary file.
|
||||
.section ".boot_compatibility_bin", "awx"
|
||||
.section ".boot_real_mode", "awx"
|
||||
|
||||
// The Linux x86 Boot Protocol header.
|
||||
//
|
||||
@ -68,7 +66,8 @@ kernel_info_offset: .long 0
|
||||
.align 16
|
||||
real_gdtr:
|
||||
.word gdt_end - gdt - 1
|
||||
.quad gdt
|
||||
.long 0 # upper 32-bit address of GDT
|
||||
.long gdt # lower 32-bit address of GDT
|
||||
|
||||
.align 16
|
||||
gdt:
|
@ -0,0 +1,11 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use core::arch::global_asm;
|
||||
|
||||
global_asm!(include_str!("header.S"));
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
{
|
||||
"llvm-target": "i386-unknown-none",
|
||||
"data-layout": "e-m:e-i32:32-f80:128-n8:16:32-S128-p:32:32",
|
||||
"cpu": "i386",
|
||||
"arch": "x86",
|
||||
"dynamic-linking": false,
|
||||
"executables": true,
|
||||
"linker-flavor": "ld.lld",
|
||||
"linker": "rust-lld",
|
||||
"max-atomic-width": 64,
|
||||
"position-independent-executables": false,
|
||||
"disable-redzone": true,
|
||||
"target-c-int-width": "32",
|
||||
"target-pointer-width": "32",
|
||||
"target-endian": "little",
|
||||
"panic-strategy": "abort",
|
||||
"os": "none",
|
||||
"relocation-model": "static",
|
||||
"features": "+soft-float,-sse,-mmx"
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(new_uninit)]
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(link_llvm_intrinsics)]
|
||||
//#![feature(link_llvm_intrinsics)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(generators)]
|
||||
#![feature(iter_from_generator)]
|
||||
|
@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "nightly-2023-08-01"
|
||||
channel = "nightly-2023-10-05"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
@ -24,7 +24,7 @@ static CARGO_COMPONENT_PATH: LazyLock<PathBuf> = LazyLock::new(|| {
|
||||
});
|
||||
|
||||
pub fn run_cargo_component(test_name: &str) -> String {
|
||||
let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let root_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
|
||||
let target_dir = root_dir.join("target").join(test_name);
|
||||
let cwd = root_dir.join("tests").join(test_name);
|
||||
let output = cargo_clean(&cwd, &target_dir);
|
||||
|
@ -199,7 +199,7 @@ fn calculate_priority(
|
||||
}
|
||||
|
||||
fn metadata() -> json::JsonValue {
|
||||
let mut cmd = Command::new(env!("CARGO"));
|
||||
let mut cmd = Command::new(std::env::var("CARGO").unwrap());
|
||||
cmd.arg("metadata");
|
||||
cmd.arg("--format-version").arg("1");
|
||||
let output = cmd.output().unwrap();
|
||||
|
Loading…
x
Reference in New Issue
Block a user