Skip to content

Commit 3f225e6

Browse files
committed
Rewrite the build system using a build script
1 parent a472a18 commit 3f225e6

File tree

8 files changed

+149
-12
lines changed

8 files changed

+149
-12
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ description = "An experimental pure-Rust x86 bootloader."
99
repository = "https://github.com/rust-osdev/bootloader"
1010
publish-lockfile = true
1111
edition = "2018"
12+
build = "build.rs"
1213

1314
[dependencies]
1415
xmas-elf = "0.6.2"

build.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
use std::{env, path::{Path, PathBuf}, process::{self, Command}};
2+
3+
fn main() {
4+
let target = env::var("TARGET").expect("TARGET not set");
5+
if Path::new(&target)
6+
.file_stem()
7+
.expect("target has no file stem")
8+
!= "x86_64-bootloader"
9+
{
10+
return;
11+
}
12+
13+
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR not set"));
14+
let kernel = PathBuf::from(match env::var("KERNEL") {
15+
Ok(kernel) => kernel,
16+
Err(_) => {
17+
eprintln!(
18+
"The KERNEL environment variable must be set for building the bootloader."
19+
);
20+
process::exit(1);
21+
}
22+
});
23+
let kernel_file_name = kernel.file_name().expect("KERNEL has no valid file name").to_str().expect("kernel file name not valid utf8");
24+
let kernel_out_path = out_dir.join(format!("kernel_bin-{}.o", kernel_file_name));
25+
let kernel_archive_path = out_dir.join(format!("libkernel_bin-{}.a", kernel_file_name));
26+
27+
28+
let bin_dir = BinDir::new();
29+
let objcopy = bin_dir.tool(&LlvmTool::tool_name("objcopy")).expect("llvm-objcopy not found in llvm-tools");
30+
31+
let mut cmd = Command::new(objcopy.path());
32+
cmd.arg("-I").arg("binary");
33+
cmd.arg("-O").arg("elf64-x86-64");
34+
cmd.arg("--binary-architecture=i386:x86-64");
35+
cmd.arg("--rename-section").arg(".data=.kernel");
36+
cmd.arg("--redefine-sym").arg(format!("_binary_{}_start=_kernel_start_addr", kernel_file_name));
37+
cmd.arg("--redefine-sym").arg(format!("_binary_{}_end=_kernel_end_addr", kernel_file_name));
38+
cmd.arg("--redefine-sym").arg(format!("_binary_{}_size=_kernel_size", kernel_file_name));
39+
cmd.current_dir(kernel.parent().expect("KERNEL has no valid parent dir"));
40+
cmd.arg(&kernel_file_name);
41+
cmd.arg(&kernel_out_path);
42+
let exit_status = cmd.status().expect("failed to run objcopy");
43+
if !exit_status.success() {
44+
eprintln!("Error: Running objcopy failed");
45+
process::exit(1);
46+
}
47+
48+
let ar = bin_dir.tool(&LlvmTool::tool_name("ar")).expect("llvm-ar not found in llvm-tools");
49+
let mut cmd = Command::new(ar.path());
50+
cmd.arg("crs");
51+
cmd.arg(&kernel_archive_path);
52+
cmd.arg(&kernel_out_path);
53+
let exit_status = cmd.status().expect("failed to run ar");
54+
if !exit_status.success() {
55+
eprintln!("Error: Running ar failed");
56+
process::exit(1);
57+
}
58+
59+
println!("cargo:rerun-if-changed={}", kernel.display());
60+
println!("cargo:rerun-if-changed=build.rs");
61+
println!("cargo:rustc-link-search=native={}", out_dir.display());
62+
println!("cargo:rustc-link-lib=static=kernel_bin-{}", kernel_file_name);
63+
}
64+
65+
#[derive(Debug)]
66+
struct BinDir {
67+
bin_dir: PathBuf,
68+
}
69+
70+
impl BinDir {
71+
fn new() -> Self {
72+
let example_tool_name = LlvmTool::tool_name("objdump");
73+
let output = Command::new("rustc")
74+
.arg("--print")
75+
.arg("sysroot")
76+
.output()
77+
.expect("failed to print sysroot");
78+
if !output.status.success() {
79+
eprintln!("Failed to execute `rustc --print sysroot`");
80+
eprintln!("Stderr: {}", String::from_utf8(output.stderr).expect("error not valid unicode"));
81+
process::exit(1);
82+
}
83+
84+
let sysroot = PathBuf::from(String::from_utf8(output.stdout).expect("sysroot not valid unicode").trim());
85+
86+
let rustlib = sysroot.join("lib").join("rustlib");
87+
for entry in rustlib.read_dir().expect("read_dir on sysroot dir failed") {
88+
let bin_dir = entry.expect("failed to read sysroot dir entry").path().join("bin");
89+
let tool_path = bin_dir.join(&example_tool_name);
90+
if tool_path.exists() {
91+
return Self { bin_dir };
92+
}
93+
}
94+
95+
eprintln!("Error: llvm-tools not found");
96+
eprintln!("Maybe the rustup component `llvm-tools-preview` is missing?");
97+
eprintln!(" Install it through: `rustup component add llvm-tools-preview`");
98+
process::exit(1);
99+
}
100+
101+
fn tool(&self, tool_name: &str) -> Option<LlvmTool> {
102+
let tool_path = self.bin_dir.join(&tool_name);
103+
104+
if tool_path.exists() {
105+
Some(LlvmTool {
106+
name: tool_name.to_owned(),
107+
path: tool_path,
108+
})
109+
} else {
110+
None
111+
}
112+
}
113+
}
114+
115+
#[derive(Debug)]
116+
struct LlvmTool {
117+
name: String,
118+
path: PathBuf,
119+
}
120+
121+
impl LlvmTool {
122+
fn path(&self) -> &Path {
123+
&self.path
124+
}
125+
126+
#[cfg(target_os = "windows")]
127+
fn tool_name(tool: &str) -> String {
128+
format!("llvm-{}.exe", tool)
129+
}
130+
131+
#[cfg(not(target_os = "windows"))]
132+
fn tool_name(tool: &str) -> String {
133+
format!("llvm-{}", tool)
134+
}
135+
}

builder/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ fn run_xbuild(args: &[String]) -> io::Result<process::ExitStatus> {
152152
command.args(args);
153153
let exit_status = command.status()?;
154154

155+
155156
if !exit_status.success() {
156157
let mut help_command = process::Command::new("cargo");
157158
help_command.arg("xbuild").arg("--help");

linker.ld

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,11 @@ SECTIONS {
4040
*(.got)
4141
. = ALIGN(512);
4242
_rest_of_bootloader_end_addr = .;
43+
__bootloader_end = .;
4344
}
4445

45-
_kernel_info_block_start = .;
46-
_kib_kernel_size = .;
47-
. += 512; /* kernel info block */
48-
_kernel_info_block_end = .;
49-
50-
__bootloader_end = .;
51-
_kernel_start_addr = .;
46+
.kernel :
47+
{
48+
KEEP(*(.kernel))
49+
}
5250
}

src/main.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ impl IdentityMappedAddr {
6363
extern "C" {
6464
static mmap_ent: usize;
6565
static _memory_map: usize;
66-
static _kib_kernel_size: usize;
66+
static _kernel_start_addr: usize;
67+
static _kernel_end_addr: usize;
68+
static _kernel_size: usize;
6769
static __page_table_start: usize;
6870
static __page_table_end: usize;
6971
static __bootloader_end: usize;
@@ -77,7 +79,7 @@ pub unsafe extern "C" fn stage_4() -> ! {
7779
mov ss, bx" ::: "bx" : "intel");
7880

7981
let kernel_start = 0x400000;
80-
let kernel_size = _kib_kernel_size as u64;
82+
let kernel_size = &_kernel_size as *const _ as u64;
8183
let memory_map_addr = &_memory_map as *const _ as u64;
8284
let memory_map_entry_count = (mmap_ent & 0xff) as u64; // Extract lower 8 bits
8385
let page_table_start = &__page_table_start as *const _ as u64;

src/stage_1.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ load_rest_of_bootloader_from_disk:
8484
mov [dap_buffer_addr], ax
8585

8686
# number of disk blocks to load
87-
lea ebx, _kernel_info_block_end
87+
lea ebx, _rest_of_bootloader_end_addr
8888
sub ebx, eax # end - start
8989
shr ebx, 9 # divide by 512 (block size)
9090
mov [dap_blocks], bx

src/stage_2.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ load_kernel_from_disk:
5050
mov edi, 0x400000
5151

5252
# block count
53-
mov ecx, _kib_kernel_size
53+
lea ecx, _kernel_size
5454
add ecx, 511 # align up
5555
shr ecx, 9
5656

src/stage_3.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ set_up_page_tables:
5252
mov [_p2], eax
5353
mov eax, (0x400000 | 1 | 2 | (1 << 7))
5454
mov ecx, 2
55-
mov edx, _kib_kernel_size
55+
lea edx, _kernel_size
5656
add edx, 0x400000 # start address
5757
add edx, 0x200000 - 1 # align up
5858
shr edx, 12 + 9 # end huge page number

0 commit comments

Comments
 (0)