@@ -10,35 +10,71 @@ fn main() {
10
10
compile_error ! ( "This crate only supports the x86_64 architecture." ) ;
11
11
}
12
12
13
+ #[ derive( Default ) ]
14
+ struct BootloaderConfig {
15
+ physical_memory_offset : Option < u64 > ,
16
+ kernel_stack_address : Option < u64 > ,
17
+ kernel_stack_size : Option < u64 > ,
18
+ }
19
+
13
20
#[ cfg( feature = "binary" ) ]
14
- fn num_from_env ( env : & ' static str , aligned : bool ) -> Option < u64 > {
15
- use std:: env;
16
- match env:: var ( env) {
17
- Err ( env:: VarError :: NotPresent ) => None ,
18
- Err ( env:: VarError :: NotUnicode ( _) ) => {
19
- panic ! ( "The `{}` environment variable must be valid unicode" , env, )
20
- }
21
- Ok ( s) => {
22
- let num = if s. starts_with ( "0x" ) {
23
- u64:: from_str_radix ( & s[ 2 ..] , 16 )
24
- } else {
25
- u64:: from_str_radix ( & s, 10 )
26
- } ;
27
-
28
- let num = num. expect ( & format ! (
29
- "The `{}` environment variable must be an integer\
30
- (is `{}`).",
31
- env, s
32
- ) ) ;
21
+ fn parse_aligned_addr ( key : & str , value : & str ) -> u64 {
22
+ let num = if value. starts_with ( "0x" ) {
23
+ u64:: from_str_radix ( & value[ 2 ..] , 16 )
24
+ } else {
25
+ u64:: from_str_radix ( & value, 10 )
26
+ } ;
27
+
28
+ let num = num. expect ( & format ! (
29
+ "`{}` in the kernel manifest must be an integer (is `{}`)" ,
30
+ key, value
31
+ ) ) ;
33
32
34
- if aligned && num % 0x1000 != 0 {
33
+ if num % 0x1000 != 0 {
34
+ panic ! (
35
+ "`{}` in the kernel manifest must be aligned to 4KiB (is `{}`)" ,
36
+ key, value
37
+ ) ;
38
+ } else {
39
+ num
40
+ }
41
+ }
42
+
43
+ #[ cfg( feature = "binary" ) ]
44
+ fn parse_to_config ( cfg : & mut BootloaderConfig , table : & toml:: value:: Table ) {
45
+ use toml:: Value ;
46
+
47
+ for ( key, value) in table {
48
+ match ( key. as_str ( ) , value. clone ( ) ) {
49
+ ( "kernel-stack-address" , Value :: Integer ( i) )
50
+ | ( "physical-memory-offset" , Value :: Integer ( i) ) => {
35
51
panic ! (
36
- "The `{}` environment variable must be aligned to 0x1000 (is `{:#x}`)." ,
37
- env, num
52
+ "`{0}` in the kernel manifest must be given as a string, \
53
+ as toml does not support unsigned 64-bit integers (try `{0} = \" {1}\" `)",
54
+ key. as_str( ) ,
55
+ i
56
+ ) ;
57
+ }
58
+ ( "kernel-stack-address" , Value :: String ( s) ) => {
59
+ cfg. kernel_stack_address = Some ( parse_aligned_addr ( key. as_str ( ) , & s) ) ;
60
+ }
61
+ ( "physical-memory-offset" , Value :: String ( s) ) => {
62
+ cfg. physical_memory_offset = Some ( parse_aligned_addr ( key. as_str ( ) , & s) ) ;
63
+ }
64
+ ( "kernel-stack-size" , Value :: Integer ( i) ) => {
65
+ if i <= 0 {
66
+ panic ! ( "`kernel-stack-size` in kernel manifest must be positive" ) ;
67
+ } else {
68
+ cfg. kernel_stack_size = Some ( i as u64 ) ;
69
+ }
70
+ }
71
+ ( s, _) => {
72
+ panic ! (
73
+ "unknown key '{}' in kernel manifest \
74
+ - you may need to update the bootloader crate",
75
+ s
38
76
) ;
39
77
}
40
-
41
- Some ( num)
42
78
}
43
79
}
44
80
}
@@ -47,11 +83,12 @@ fn num_from_env(env: &'static str, aligned: bool) -> Option<u64> {
47
83
fn main ( ) {
48
84
use std:: {
49
85
env,
50
- fs:: File ,
86
+ fs:: { self , File } ,
51
87
io:: Write ,
52
88
path:: { Path , PathBuf } ,
53
89
process:: { self , Command } ,
54
90
} ;
91
+ use toml:: Value ;
55
92
56
93
let target = env:: var ( "TARGET" ) . expect ( "TARGET not set" ) ;
57
94
if Path :: new ( & target)
@@ -185,22 +222,55 @@ fn main() {
185
222
process:: exit ( 1 ) ;
186
223
}
187
224
225
+ // Parse the kernel's Cargo.toml which is given to us by bootimage
226
+ let mut bootloader_config = BootloaderConfig :: default ( ) ;
227
+
228
+ match env:: var ( "KERNEL_MANIFEST" ) {
229
+ Err ( env:: VarError :: NotPresent ) => {
230
+ panic ! ( "The KERNEL_MANIFEST environment variable must be set for building the bootloader.\n \n \
231
+ If you use `bootimage` for building you need at least version PLACEHOLDER. You can \
232
+ update `bootimage` by running `cargo install bootimage --force`.") ;
233
+ }
234
+ Err ( env:: VarError :: NotUnicode ( _) ) => {
235
+ panic ! ( "The KERNEL_MANIFEST environment variable contains invalid unicode" )
236
+ }
237
+ Ok ( path) => {
238
+ println ! ( "cargo:rerun-if-changed={}" , path) ;
239
+
240
+ let contents = fs:: read_to_string ( & path) . expect ( & format ! (
241
+ "failed to read kernel manifest file (path: {})" ,
242
+ path
243
+ ) ) ;
244
+
245
+ let manifest = contents
246
+ . parse :: < Value > ( )
247
+ . expect ( "failed to parse kernel's Cargo.toml" ) ;
248
+
249
+ let table = manifest
250
+ . get ( "package" )
251
+ . and_then ( |table| table. get ( "metadata" ) )
252
+ . and_then ( |table| table. get ( "bootloader" ) )
253
+ . and_then ( |table| table. as_table ( ) ) ;
254
+
255
+ if let Some ( table) = table {
256
+ parse_to_config ( & mut bootloader_config, table) ;
257
+ }
258
+ }
259
+ }
260
+
188
261
// Configure constants for the bootloader
189
262
// We leave some variables as Option<T> rather than hardcoding their defaults so that they
190
263
// can be calculated dynamically by the bootloader.
191
264
let file_path = out_dir. join ( "bootloader_config.rs" ) ;
192
265
let mut file = File :: create ( file_path) . expect ( "failed to create bootloader_config.rs" ) ;
193
- let physical_memory_offset = num_from_env ( "BOOTLOADER_PHYSICAL_MEMORY_OFFSET" , true ) ;
194
- let kernel_stack_address = num_from_env ( "BOOTLOADER_KERNEL_STACK_ADDRESS" , true ) ;
195
- let kernel_stack_size = num_from_env ( "BOOTLOADER_KERNEL_STACK_SIZE" , false ) ;
196
266
file. write_all (
197
267
format ! (
198
268
"const PHYSICAL_MEMORY_OFFSET: Option<u64> = {:?};
199
269
const KERNEL_STACK_ADDRESS: Option<u64> = {:?};
200
270
const KERNEL_STACK_SIZE: u64 = {};" ,
201
- physical_memory_offset,
202
- kernel_stack_address,
203
- kernel_stack_size. unwrap_or( 512 ) , // size is in number of pages
271
+ bootloader_config . physical_memory_offset,
272
+ bootloader_config . kernel_stack_address,
273
+ bootloader_config . kernel_stack_size. unwrap_or( 512 ) , // size is in number of pages
204
274
)
205
275
. as_bytes ( ) ,
206
276
)
@@ -214,9 +284,7 @@ fn main() {
214
284
) ;
215
285
216
286
println ! ( "cargo:rerun-if-env-changed=KERNEL" ) ;
217
- println ! ( "cargo:rerun-if-env-changed=BOOTLOADER_PHYSICAL_MEMORY_OFFSET" ) ;
218
- println ! ( "cargo:rerun-if-env-changed=BOOTLOADER_KERNEL_STACK_ADDRESS" ) ;
219
- println ! ( "cargo:rerun-if-env-changed=BOOTLOADER_KERNEL_STACK_SIZE" ) ;
287
+ println ! ( "cargo:rerun-if-env-changed=KERNEL_MANIFEST" ) ;
220
288
println ! ( "cargo:rerun-if-changed={}" , kernel. display( ) ) ;
221
289
println ! ( "cargo:rerun-if-changed=build.rs" ) ;
222
290
}
0 commit comments