Add protected mode sub-crate for Linux boot setup

This commit is contained in:
Zhang Junyang
2023-10-06 22:08:20 +08:00
committed by Tate, Hongliang Tian
parent 7d5295ab25
commit d0c84e0b6f
20 changed files with 138 additions and 66 deletions

View File

@ -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(())
}

View File

@ -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]

View File

@ -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()
)
}

View File

@ -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 = .;
}
}

View File

@ -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:

View File

@ -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 {}
}

View File

@ -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"
}

View File

@ -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)]