mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +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:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: jinuxdev/jinux:0.1.1
|
container: jinuxdev/jinux:0.1.2
|
||||||
steps:
|
steps:
|
||||||
- run: echo "Running in jinuxdev/jinux:0.1.1"
|
- run: echo "Running in jinuxdev/jinux:0.1.2"
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
12
.github/workflows/syscall_test.yml
vendored
12
.github/workflows/syscall_test.yml
vendored
@ -10,9 +10,9 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: jinuxdev/jinux:0.1.1
|
container: jinuxdev/jinux:0.1.2
|
||||||
steps:
|
steps:
|
||||||
- run: echo "Running in jinuxdev/jinux:0.1.1"
|
- run: echo "Running in jinuxdev/jinux:0.1.2"
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
@ -20,8 +20,8 @@ jobs:
|
|||||||
id: syscall_test_mb2
|
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
|
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)
|
# TODO: include the integration tests for Multiboot/MicroVM/Linux boot methods, which are not ready yet.
|
||||||
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.
|
# - 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]]
|
[[package]]
|
||||||
name = "jinux"
|
name = "jinux"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"component",
|
"component",
|
||||||
"jinux-frame",
|
"jinux-frame",
|
||||||
@ -659,6 +659,10 @@ dependencies = [
|
|||||||
"x86_64",
|
"x86_64",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jinux-frame-x86-boot-setup"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jinux-framebuffer"
|
name = "jinux-framebuffer"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "jinux"
|
name = "jinux"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
@ -22,6 +22,7 @@ jinux-framebuffer = { path = "services/comps/framebuffer" }
|
|||||||
members = [
|
members = [
|
||||||
"build",
|
"build",
|
||||||
"framework/jinux-frame",
|
"framework/jinux-frame",
|
||||||
|
"framework/jinux-frame/src/arch/x86/boot/linux_boot/setup",
|
||||||
"framework/libs/align_ext",
|
"framework/libs/align_ext",
|
||||||
"services/comps/virtio",
|
"services/comps/virtio",
|
||||||
"services/comps/input",
|
"services/comps/input",
|
||||||
|
3
Makefile
3
Makefile
@ -56,7 +56,8 @@ export
|
|||||||
|
|
||||||
export JINUX_BOOT_PROTOCOL=$(BOOT_PROTOCOL)
|
export JINUX_BOOT_PROTOCOL=$(BOOT_PROTOCOL)
|
||||||
|
|
||||||
# GNU toolchain variables
|
# Toolchain variables
|
||||||
|
export CARGO := cargo
|
||||||
export AS := as
|
export AS := as
|
||||||
export CC := gcc
|
export CC := gcc
|
||||||
export OBJCOPY := objcopy
|
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.
|
2. After downloading the source code, run the following command to pull the development image.
|
||||||
```bash
|
```bash
|
||||||
docker pull jinuxdev/jinux:0.1.1
|
docker pull jinuxdev/jinux:0.1.2
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Start the development container.
|
3. Start the development container.
|
||||||
```bash
|
```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.**
|
**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};
|
use std::{error::Error, path::PathBuf};
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
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("framework")
|
||||||
.join("jinux-frame")
|
.join("jinux-frame")
|
||||||
.join("src")
|
.join("src")
|
||||||
@ -9,19 +9,8 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
|||||||
.join("x86")
|
.join("x86")
|
||||||
.join("boot")
|
.join("boot")
|
||||||
.join("linker.ld");
|
.join("linker.ld");
|
||||||
println!(
|
println!("cargo:rerun-if-changed={}", linker_script_path.display());
|
||||||
"cargo:rerun-if-changed={}",
|
println!("cargo:rustc-link-arg=-T{}", linker_script_path.display());
|
||||||
linker_script_path.to_str().unwrap()
|
|
||||||
);
|
|
||||||
println!(
|
|
||||||
"cargo:rustc-link-arg=-T{}",
|
|
||||||
linker_script_path.to_str().unwrap()
|
|
||||||
);
|
|
||||||
println!("cargo:rerun-if-env-changed=CARGO_PKG_NAME");
|
println!("cargo:rerun-if-env-changed=CARGO_PKG_NAME");
|
||||||
Ok(())
|
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.
|
// Find the setup header in the build script output directory.
|
||||||
let out_dir = glob("target/x86_64-custom/debug/build/jinux-frame-*").unwrap();
|
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())
|
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.
|
// Deliver the kernel image to the boot directory.
|
||||||
match protocol {
|
match protocol {
|
||||||
|
@ -5,59 +5,65 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
|||||||
Ok(())
|
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>> {
|
fn build_linux_setup_header() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
// Compile the header to raw binary.
|
// Build the setup header to raw binary.
|
||||||
let linux_boot_header_asm_path = get_source_dir()
|
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("src")
|
||||||
.join("arch")
|
.join("arch")
|
||||||
.join("x86")
|
.join("x86")
|
||||||
.join("boot")
|
.join("boot")
|
||||||
.join("linux_boot")
|
.join("linux_boot")
|
||||||
.join("header.S");
|
.join("setup");
|
||||||
|
let target_json = setup_crate_dir.join("x86_64-i386_protected_mode.json");
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"cargo:rerun-if-changed={}",
|
"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 cargo = std::env::var("CARGO").unwrap();
|
||||||
let mut cmd = std::process::Command::new(gas);
|
let mut cmd = std::process::Command::new(cargo);
|
||||||
cmd.arg(linux_boot_header_asm_path);
|
cmd.arg("install").arg("jinux-frame-x86-boot-setup");
|
||||||
cmd.arg("-o")
|
cmd.arg("--locked");
|
||||||
.arg(linux_boot_header_elf_path.to_str().unwrap());
|
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()?;
|
let output = cmd.output()?;
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
std::io::stdout().write_all(&output.stdout).unwrap();
|
std::io::stdout().write_all(&output.stdout).unwrap();
|
||||||
std::io::stderr().write_all(&output.stderr).unwrap();
|
std::io::stderr().write_all(&output.stderr).unwrap();
|
||||||
panic!(
|
return Err(format!(
|
||||||
"Failed to compile linux boot header:\n\tcommand `{:?}`\n\treturned {}",
|
"Failed to build linux x86 setup header::\n\tcommand `{:?}`\n\treturned {}",
|
||||||
cmd, output.status
|
cmd, output.status
|
||||||
);
|
)
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strip the elf header to get the raw header.
|
// 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 objcopy = std::env::var("OBJCOPY").unwrap();
|
||||||
let mut cmd = std::process::Command::new(objcopy);
|
let mut cmd = std::process::Command::new(objcopy);
|
||||||
cmd.arg("-O").arg("binary");
|
cmd.arg("-O").arg("binary");
|
||||||
cmd.arg("-j").arg(".boot_compatibility_bin");
|
cmd.arg("-j").arg(".boot_real_mode");
|
||||||
cmd.arg(linux_boot_header_elf_path.to_str().unwrap());
|
cmd.arg(elf_path.to_str().unwrap());
|
||||||
cmd.arg(linux_boot_header_bin_path.to_str().unwrap());
|
cmd.arg(bin_path.to_str().unwrap());
|
||||||
let output = cmd.output()?;
|
let output = cmd.output()?;
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
std::io::stdout().write_all(&output.stdout).unwrap();
|
std::io::stdout().write_all(&output.stdout).unwrap();
|
||||||
std::io::stderr().write_all(&output.stderr).unwrap();
|
std::io::stderr().write_all(&output.stderr).unwrap();
|
||||||
panic!(
|
return Err(format!(
|
||||||
"Failed to strip linux boot header:\n\tcommand `{:?}`\n\treturned {}",
|
"Failed to strip linux boot header:\n\tcommand `{:?}`\n\treturned {}",
|
||||||
cmd, output.status
|
cmd, output.status
|
||||||
);
|
)
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
Ok(())
|
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
|
// See https://www.kernel.org/doc/html/v5.6/x86/boot.html for
|
||||||
// more information on the Linux x86 Boot Protocol.
|
// 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 section name is used by the build script to strip and make
|
||||||
// the binary file.
|
// the binary file.
|
||||||
.section ".boot_compatibility_bin", "awx"
|
.section ".boot_real_mode", "awx"
|
||||||
|
|
||||||
// The Linux x86 Boot Protocol header.
|
// The Linux x86 Boot Protocol header.
|
||||||
//
|
//
|
||||||
@ -68,7 +66,8 @@ kernel_info_offset: .long 0
|
|||||||
.align 16
|
.align 16
|
||||||
real_gdtr:
|
real_gdtr:
|
||||||
.word gdt_end - gdt - 1
|
.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
|
.align 16
|
||||||
gdt:
|
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(core_intrinsics)]
|
||||||
#![feature(new_uninit)]
|
#![feature(new_uninit)]
|
||||||
#![feature(strict_provenance)]
|
#![feature(strict_provenance)]
|
||||||
#![feature(link_llvm_intrinsics)]
|
//#![feature(link_llvm_intrinsics)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
#![feature(generators)]
|
#![feature(generators)]
|
||||||
#![feature(iter_from_generator)]
|
#![feature(iter_from_generator)]
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2023-08-01"
|
channel = "nightly-2023-10-05"
|
||||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
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 {
|
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 target_dir = root_dir.join("target").join(test_name);
|
||||||
let cwd = root_dir.join("tests").join(test_name);
|
let cwd = root_dir.join("tests").join(test_name);
|
||||||
let output = cargo_clean(&cwd, &target_dir);
|
let output = cargo_clean(&cwd, &target_dir);
|
||||||
|
@ -199,7 +199,7 @@ fn calculate_priority(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn metadata() -> json::JsonValue {
|
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("metadata");
|
||||||
cmd.arg("--format-version").arg("1");
|
cmd.arg("--format-version").arg("1");
|
||||||
let output = cmd.output().unwrap();
|
let output = cmd.output().unwrap();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user