Skip to content

Commit 36da929

Browse files
bors[bot]phil-opp
andauthored
Merge #113
113: Make bootsector a staticlib r=rybot666 a=phil-opp Makes the bootsector self-contained by making it a staticlib. This ensures that we don't accidentally use functions from stage_2. The `stage_2` crate is now the main executable, which links the bootsector through a build script. Co-authored-by: Philipp Oppermann <dev@phil-opp.com>
2 parents c2c1681 + 0630857 commit 36da929

File tree

21 files changed

+198
-100
lines changed

21 files changed

+198
-100
lines changed

.cargo/config

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
[build]
2-
target = "x86_64-real_mode.json"
3-
rustflags = ["-C", "link-arg=-Tlinker.ld"]
1+
[alias]
2+
xbuild = "build -Zbuild-std=core"

.github/workflows/build.yml

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,15 @@ jobs:
4141
4242
- name: "Install Rustup Components"
4343
run: rustup component add rust-src llvm-tools-preview
44-
- name: "Install cargo-xbuild"
45-
run: cargo install cargo-xbuild --debug
4644
- name: "Install cargo-binutils"
4745
run: cargo install cargo-binutils --version 0.1.7 --debug
4846

49-
- run: cargo xbuild
50-
working-directory: test-kernel
51-
name: 'Build Test Kernel'
52-
5347
- name: 'Build Bootloader'
5448
run: cargo xbuild --release
49+
working-directory: src/stage_2
5550

5651
- name: 'Convert Bootloader ELF to Binary'
57-
run: cargo objcopy -- -I elf64-i386 -O binary --binary-architecture=i386:x86-64 target/x86_64-real_mode/release/bootsector target/x86_64-real_mode/release/bootsector.bin
52+
run: cargo objcopy -- -I elf64-i386 -O binary --binary-architecture=i386:x86-64 target/x86_64-real_mode/release/stage_2 target/x86_64-real_mode/release/image.bin
5853

5954
# # install QEMU
6055
# - name: Install QEMU (Linux)
@@ -108,8 +103,6 @@ jobs:
108103
if: runner.os == 'macOS'
109104
- name: "Install Rustup Components"
110105
run: rustup component add rust-src llvm-tools-preview
111-
- name: "Install cargo-xbuild"
112-
run: cargo install cargo-xbuild --debug
113106
- name: 'Build Example Kernel'
114107
run: cargo xbuild
115108
working-directory: example-kernel

Cargo.lock

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@ members = [
44
"src/v86",
55
"src/bootsector",
66
"src/stage_2",
7-
# "example-kernel",
8-
# "test-kernel",
7+
"example-kernel",
8+
"test-kernel",
99
]
1010

1111
[profile.release]
1212
opt-level = "z"
13-
panic = "abort"
13+
panic = "abort"
14+
lto = true
15+
16+
[profile.release.package.bootsector]
17+
opt-level = "s"
18+
codegen-units = 1

src/bootsector/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ edition = "2018"
66

77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

9+
[lib]
10+
name = "bootsector"
11+
crate-type = ["staticlib"]
12+
913
[dependencies]
1014
shared = { path = "../shared" }
11-
stage_2 = { path = "../stage_2" }

src/bootsector/src/console.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
#[inline(never)]
2-
pub fn println(s: &[u8]) {
1+
#[no_mangle]
2+
pub fn real_mode_println(s: &[u8]) {
33
print(s);
44
print_char(b'\n');
55
}
66

77
pub fn print(s: &[u8]) {
8-
let mut i = 0;
8+
let mut i = 0;
99

10-
while i < s.len() {
11-
print_char(s[i]);
12-
i += 1;
13-
}
10+
while i < s.len() {
11+
print_char(s[i]);
12+
i += 1;
13+
}
1414
}
1515

1616
#[inline(always)]
@@ -19,4 +19,4 @@ pub fn print_char(c: u8) {
1919
unsafe {
2020
llvm_asm!("int 0x10" :: "{ax}"(ax) :: "intel" );
2121
}
22-
}
22+
}

src/bootsector/src/errors.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1+
use super::console::real_mode_println;
12
use shared::utils;
2-
use super::console::println;
33

44
#[no_mangle]
5-
pub extern "C" fn dap_load_failed() -> ! {
6-
println(b"[!] DAP Load Failed");
5+
extern "C" fn dap_load_failed() -> ! {
6+
real_mode_println(b"[!] DAP Load Failed");
77
loop {
88
utils::hlt()
99
}
1010
}
1111

1212
#[no_mangle]
13-
pub extern "C" fn no_int13h_extensions() -> ! {
14-
println(b"[!] No int13h Extensions");
13+
extern "C" fn no_int13h_extensions() -> ! {
14+
real_mode_println(b"[!] No int13h Extensions");
1515
loop {
1616
utils::hlt()
1717
}
18-
}
18+
}

src/bootsector/src/lib.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#![feature(llvm_asm, global_asm)]
2+
#![no_std]
3+
#![allow(dead_code)]
4+
5+
mod console;
6+
mod errors;
7+
8+
use self::console::real_mode_println;
9+
use core::panic::PanicInfo;
10+
use shared::{dap, linker_symbol, utils};
11+
12+
extern "C" {
13+
fn second_stage();
14+
}
15+
global_asm!(include_str!("bootstrap.s"));
16+
17+
#[no_mangle]
18+
extern "C" fn rust_start(disk_number: u16) -> ! {
19+
real_mode_println(b"Stage 1");
20+
21+
check_int13h_extensions(disk_number);
22+
23+
let dap = dap::DiskAddressPacket::new(
24+
linker_symbol!(_rest_of_bootloader_start) as u16,
25+
(linker_symbol!(_rest_of_bootloader_start) - linker_symbol!(_bootloader_start)) as u64,
26+
linker_symbol!(_rest_of_bootloader_end) - linker_symbol!(_rest_of_bootloader_start),
27+
);
28+
29+
unsafe { dap.perform_load(disk_number) };
30+
31+
unsafe { second_stage() };
32+
33+
loop {
34+
utils::hlt();
35+
}
36+
}
37+
38+
fn check_int13h_extensions(disk_number: u16) {
39+
unsafe {
40+
llvm_asm!("
41+
int 0x13
42+
jc no_int13h_extensions
43+
" :: "{ah}"(0x41), "{bx}"(0x55aa), "{dl}"(disk_number) :: "intel", "volatile");
44+
}
45+
}
46+
47+
#[panic_handler]
48+
fn panic(_info: &PanicInfo) -> ! {
49+
real_mode_println(b"[Panic]");
50+
51+
loop {
52+
utils::hlt()
53+
}
54+
}

src/bootsector/src/main.rs

Lines changed: 0 additions & 46 deletions
This file was deleted.

src/shared/src/console.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,4 @@ impl Writer {
3636
llvm_asm!("int 0x10" :: "{ax}"(ax), "{bx}"(0) :: "intel", "volatile");
3737
}
3838
}
39-
}
39+
}

src/shared/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44
pub mod console;
55
pub mod dap;
66
pub mod utils;
7-
#[macro_use] pub mod macros;
7+
#[macro_use]
8+
pub mod macros;

src/shared/src/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ macro_rules! linker_symbol {
99

1010
symbol_value
1111
}};
12-
}
12+
}

src/shared/src/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ pub fn hlt() {
33
unsafe {
44
llvm_asm!("hlt" :::: "intel","volatile");
55
}
6-
}
6+
}

src/stage_2/.cargo/config

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[build]
2+
target = "../../x86_64-real_mode.json"
3+
rustflags = ["-C", "link-arg=-Tlinker.ld"]

src/stage_2/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,7 @@ v86 = { path = "../v86" }
1212

1313
[dependencies.lazy_static]
1414
version = "1.0"
15-
features = ["spin_no_std"]
15+
features = ["spin_no_std"]
16+
17+
[build-dependencies]
18+
llvm-tools = "0.1.1"

src/stage_2/build.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use llvm_tools::{exe, LlvmTools};
2+
use std::env;
3+
use std::path::Path;
4+
use std::process::Command;
5+
6+
fn main() {
7+
let out_dir = env::var("OUT_DIR").unwrap();
8+
let llvm_tools = LlvmTools::new().expect("LLVM tools not found");
9+
let objcopy = llvm_tools
10+
.tool(&exe("llvm-objcopy"))
11+
.expect("llvm-objcopy not found");
12+
13+
build_subproject(
14+
Path::new("../bootsector"),
15+
&[
16+
"_start",
17+
"real_mode_println",
18+
"no_int13h_extensions",
19+
"dap_load_failed",
20+
],
21+
"x86_64-real_mode.json",
22+
&out_dir,
23+
&objcopy,
24+
);
25+
}
26+
27+
fn build_subproject(
28+
dir: &Path,
29+
global_symbols: &[&str],
30+
target: &str,
31+
out_dir: &str,
32+
objcopy: &Path,
33+
) {
34+
let dir_name = dir.file_name().unwrap().to_str().unwrap();
35+
let manifest_path = dir.join("Cargo.toml");
36+
let out_path = Path::new(&out_dir);
37+
assert!(
38+
global_symbols.len() > 0,
39+
"must have at least one global symbol"
40+
);
41+
42+
// build
43+
let mut cmd = Command::new("cargo");
44+
cmd.arg("xbuild").arg("--release");
45+
cmd.arg("--verbose");
46+
cmd.arg(format!("--manifest-path={}", manifest_path.display()));
47+
cmd.arg(format!(
48+
"--target={}",
49+
dir.join("../..").join(target).display()
50+
));
51+
cmd.arg("-Z").arg("unstable-options");
52+
cmd.arg("--out-dir").arg(&out_dir);
53+
cmd.arg("--target-dir")
54+
.arg(out_path.join("target").join(dir_name));
55+
cmd.env_remove("RUSTFLAGS");
56+
cmd.env(
57+
"XBUILD_SYSROOT_PATH",
58+
out_path.join("target").join(dir_name).join("sysroot"),
59+
);
60+
let status = cmd.status().unwrap();
61+
assert!(status.success());
62+
63+
// localize symbols
64+
let mut cmd = Command::new(objcopy);
65+
for symbol in global_symbols {
66+
cmd.arg("-G").arg(symbol);
67+
}
68+
cmd.arg(out_path.join(format!("lib{}.a", dir_name)));
69+
let status = cmd.status().unwrap();
70+
assert!(status.success());
71+
72+
// emit linker flags
73+
println!("cargo:rustc-link-search=native={}", out_dir);
74+
println!("cargo:rustc-link-lib=static={}", dir_name);
75+
}

0 commit comments

Comments
 (0)