@@ -13,8 +13,8 @@ use uefi::{
13
13
prelude:: { entry, Boot , Handle , Status , SystemTable } ,
14
14
proto:: {
15
15
console:: gop:: { GraphicsOutput , PixelFormat } ,
16
- device_path:: { self , DevicePath } ,
17
- loaded_image:: { self , LoadedImage } ,
16
+ device_path:: DevicePath ,
17
+ loaded_image:: LoadedImage ,
18
18
media:: {
19
19
file:: { File , FileAttribute , FileInfo , FileMode } ,
20
20
fs:: SimpleFileSystem ,
@@ -23,9 +23,11 @@ use uefi::{
23
23
pxe:: { BaseCode , DhcpV4Packet } ,
24
24
IpAddress ,
25
25
} ,
26
+ ProtocolPointer ,
26
27
} ,
27
28
table:: boot:: {
28
29
AllocateType , MemoryDescriptor , MemoryType , OpenProtocolAttributes , OpenProtocolParams ,
30
+ ScopedProtocol ,
29
31
} ,
30
32
CStr16 , CStr8 ,
31
33
} ;
@@ -37,8 +39,8 @@ use x86_64::{
37
39
mod memory_descriptor;
38
40
39
41
static SYSTEM_TABLE : RacyCell < Option < SystemTable < Boot > > > = RacyCell :: new ( None ) ;
40
- const KERNEL_FILENAME : & str = "kernel-x86_64" ;
41
- const RAMDISK_FILENAME : & str = "ramdisk-x86_64" ;
42
+ static KERNEL_FILENAME : & str = "kernel-x86_64\0 " ;
43
+ static RAMDISK_FILENAME : & str = "ramdisk-x86_64\0 " ;
42
44
43
45
struct RacyCell < T > ( UnsafeCell < T > ) ;
44
46
@@ -98,7 +100,7 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {
98
100
let ptr = st
99
101
. boot_services ( )
100
102
. allocate_pool ( MemoryType :: LOADER_DATA , max_mmap_size)
101
- . expect ( "Failed to allocate memory for memory map " ) ;
103
+ . expect ( "Failed to allocate memory for mmap storage " ) ;
102
104
unsafe { slice:: from_raw_parts_mut ( ptr, max_mmap_size) }
103
105
} ;
104
106
@@ -111,7 +113,12 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {
111
113
LegacyFrameAllocator :: new ( memory_map. copied ( ) . map ( UefiMemoryDescriptor ) ) ;
112
114
113
115
let page_tables = create_page_tables ( & mut frame_allocator) ;
114
-
116
+ let mut ramdisk_addr = 0u64 ;
117
+ let mut ramdisk_len = 0u64 ;
118
+ if let Some ( rd) = ramdisk {
119
+ ramdisk_len = rd. len ( ) as u64 ;
120
+ ramdisk_addr = rd. as_ptr ( ) as usize as u64 ;
121
+ }
115
122
let system_info = SystemInfo {
116
123
framebuffer,
117
124
rsdp_addr : {
@@ -124,14 +131,11 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {
124
131
. or_else ( || config_entries. find ( |entry| matches ! ( entry. guid, cfg:: ACPI_GUID ) ) ) ;
125
132
rsdp. map ( |entry| PhysAddr :: new ( entry. address as u64 ) )
126
133
} ,
127
- ramdisk_addr : match ramdisk {
128
- Some ( rd) => Some ( rd as * const _ as u64 ) ,
129
- None => None ,
130
- } ,
131
- ramdisk_len : match ramdisk {
132
- Some ( rd) => rd. len ( ) as u64 ,
133
- None => 0u64 ,
134
+ ramdisk_addr : match ramdisk_addr {
135
+ 0 => None ,
136
+ v => Some ( v) ,
134
137
} ,
138
+ ramdisk_len : ramdisk_len,
135
139
} ;
136
140
137
141
bootloader_x86_64_common:: load_and_switch_to_kernel (
@@ -142,100 +146,125 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {
142
146
) ;
143
147
}
144
148
145
- fn load_ramdisk ( image : Handle , st : & SystemTable < Boot > ) -> Option < & ' static [ u8 ] > {
149
+ fn load_ramdisk ( image : Handle , st : & SystemTable < Boot > ) -> Option < & ' static mut [ u8 ] > {
146
150
load_file_from_disk ( RAMDISK_FILENAME , image, st)
151
+ . or_else ( || load_file_from_tftp_boot_server ( RAMDISK_FILENAME , image, st) )
147
152
}
148
153
149
154
fn load_kernel ( image : Handle , st : & SystemTable < Boot > ) -> Kernel < ' static > {
150
155
let kernel_slice = load_file_from_disk ( KERNEL_FILENAME , image, st)
151
- . or_else ( || load_kernel_file_from_tftp_boot_server ( KERNEL_FILENAME , image, st) )
156
+ . or_else ( || load_file_from_tftp_boot_server ( KERNEL_FILENAME , image, st) )
152
157
. expect ( "couldn't find kernel" ) ;
153
158
Kernel :: parse ( kernel_slice)
154
159
}
155
160
156
- fn load_file_from_disk (
157
- name : & str ,
161
+ fn open_device_path_protocol (
158
162
image : Handle ,
159
163
st : & SystemTable < Boot > ,
160
- ) -> Option < & ' static mut [ u8 ] > {
161
- let file_system_raw = {
162
- let this = st . boot_services ( ) ;
163
- let loaded_image = this. open_protocol :: < LoadedImage > (
164
+ ) -> Option < ScopedProtocol < DevicePath > > {
165
+ let this = st . boot_services ( ) ;
166
+ let loaded_image = unsafe {
167
+ this. open_protocol :: < LoadedImage > (
164
168
OpenProtocolParams {
165
169
handle : image,
166
170
agent : image,
167
171
controller : None ,
168
172
} ,
169
173
OpenProtocolAttributes :: Exclusive ,
170
- ) ;
174
+ )
175
+ } ;
171
176
172
- if loaded_image. is_err ( ) {
173
- log:: error!( "Failed to open protocol SimpleFileSystem while attempting to load {name} " ) ;
174
- return None ;
175
- }
176
- let loaded_image = loaded_image. unwrap ( ) ;
177
- let loaded_image = unsafe { & * loaded_image. interface . get ( ) } ;
177
+ if loaded_image. is_err ( ) {
178
+ log:: error!( "Failed to open protocol LoadedImage " ) ;
179
+ return None ;
180
+ }
181
+ let loaded_image = loaded_image. unwrap ( ) ;
182
+ let loaded_image = unsafe { & * loaded_image. interface . get ( ) } ;
178
183
179
- let device_handle = loaded_image. device ( ) ;
184
+ let device_handle = loaded_image. device ( ) ;
180
185
181
- let device_path = this. open_protocol :: < DevicePath > (
186
+ let device_path = unsafe {
187
+ this. open_protocol :: < DevicePath > (
182
188
OpenProtocolParams {
183
189
handle : device_handle,
184
190
agent : image,
185
191
controller : None ,
186
192
} ,
187
193
OpenProtocolAttributes :: Exclusive ,
188
- ) ;
189
- if device_path. is_err ( ) {
190
- log:: error!( "Failed to open protocol DevicePath while attempting to load {name}" ) ;
191
- return None ;
192
- }
193
- let device_path = device_path. unwrap ( ) ;
194
- let mut device_path = unsafe { & * device_path. interface . get ( ) } ;
194
+ )
195
+ } ;
196
+ if device_path. is_err ( ) {
197
+ log:: error!( "Failed to open protocol DevicePath" ) ;
198
+ return None ;
199
+ }
200
+ Some ( device_path. unwrap ( ) )
201
+ }
195
202
196
- let fs_handle = this. locate_device_path :: < SimpleFileSystem > ( & mut device_path) ;
197
- if fs_handle. is_err ( ) {
198
- log:: error!( "Failed to open device path while attempting to load {name}" ) ;
199
- return None ;
200
- }
203
+ fn locate_and_open_protocol < P : ProtocolPointer > (
204
+ image : Handle ,
205
+ st : & SystemTable < Boot > ,
206
+ ) -> Option < ScopedProtocol < P > > {
207
+ let this = st. boot_services ( ) ;
208
+ let device_path = open_device_path_protocol ( image, st) ;
209
+ if device_path. is_none ( ) {
210
+ log:: error!( "Unable to open device path protocol from boot services" ) ;
211
+ return None ;
212
+ }
213
+ let device_path = device_path. unwrap ( ) ;
214
+ let mut device_path = unsafe { & * device_path. interface . get ( ) } ;
201
215
202
- let fs_handle = fs_handle. unwrap ( ) ;
216
+ let fs_handle = this. locate_device_path :: < P > ( & mut device_path) ;
217
+ if fs_handle. is_err ( ) {
218
+ log:: error!( "Failed to open device path" ) ;
219
+ return None ;
220
+ }
203
221
204
- let opened_handle = this. open_protocol :: < SimpleFileSystem > (
222
+ let fs_handle = fs_handle. unwrap ( ) ;
223
+
224
+ let opened_handle = unsafe {
225
+ this. open_protocol :: < P > (
205
226
OpenProtocolParams {
206
227
handle : fs_handle,
207
228
agent : image,
208
229
controller : None ,
209
230
} ,
210
231
OpenProtocolAttributes :: Exclusive ,
211
- ) ;
212
-
213
- if opened_handle. is_err ( ) {
214
- log:: error!( "Failed to open file system while attempting to load {name}" ) ;
215
- return None ;
216
- }
217
- Some ( opened_handle. unwrap ( ) )
232
+ )
218
233
} ;
219
234
235
+ if opened_handle. is_err ( ) {
236
+ log:: error!( "Failed to open protocol {}" , core:: any:: type_name:: <P >( ) ) ;
237
+ return None ;
238
+ }
239
+ Some ( opened_handle. unwrap ( ) )
240
+ }
241
+
242
+ fn load_file_from_disk (
243
+ name : & str ,
244
+ image : Handle ,
245
+ st : & SystemTable < Boot > ,
246
+ ) -> Option < & ' static mut [ u8 ] > {
247
+ let file_system_raw = locate_and_open_protocol :: < SimpleFileSystem > ( image, st) ;
248
+
220
249
if file_system_raw. is_none ( ) {
221
- return None ( ) ;
250
+ return None ;
222
251
}
223
252
let file_system_raw = file_system_raw. unwrap ( ) ;
224
253
let file_system = unsafe { & mut * file_system_raw. interface . get ( ) } ;
225
254
226
255
let mut root = file_system. open_volume ( ) . unwrap ( ) ;
227
- if ( name . len ( ) > 255 ) {
228
- panic ! ( "File name {}, exceeds maximum length!" , name ) ;
229
- }
230
- let mut buf = [ 0 ; 512 ] ;
231
- let filename = CStr16 :: from_str_with_buf ( name , & mut buf ) . unwrap ( ) ;
232
- let kernel_file_handle_result = root. open ( filename, FileMode :: Read , FileAttribute :: empty ( ) ) ;
256
+ let mut buf = [ 0u16 ; 256 ] ;
257
+ assert ! ( name. len ( ) < 256 ) ;
258
+ let filename = CStr16 :: from_str_with_buf ( name . trim_end_matches ( '\0' ) , & mut buf )
259
+ . expect ( "Failed to convert string to utf16" ) ;
260
+
261
+ let file_handle_result = root. open ( filename, FileMode :: Read , FileAttribute :: empty ( ) ) ;
233
262
234
- if kernel_file_handle_result . is_err ( ) {
263
+ if file_handle_result . is_err ( ) {
235
264
return None ;
236
265
}
237
266
238
- let file_handle = kernel_file_handle_result . unwrap ( ) ;
267
+ let file_handle = file_handle_result . unwrap ( ) ;
239
268
240
269
let mut file = match file_handle. into_type ( ) . unwrap ( ) {
241
270
uefi:: proto:: media:: file:: FileType :: Regular ( f) => f,
@@ -262,90 +291,52 @@ fn load_file_from_disk(
262
291
}
263
292
264
293
/// Try to load a kernel from a TFTP boot server.
265
- fn load_kernel_file_from_tftp_boot_server (
294
+ fn load_file_from_tftp_boot_server (
266
295
name : & str ,
267
296
image : Handle ,
268
297
st : & SystemTable < Boot > ,
269
298
) -> Option < & ' static mut [ u8 ] > {
270
- let this = st. boot_services ( ) ;
271
-
272
- // Try to locate a `BaseCode` protocol on the boot device.
273
-
274
- let loaded_image = unsafe { this
275
- . open_protocol :: < LoadedImage > (
276
- OpenProtocolParams {
277
- handle : image,
278
- agent : image,
279
- controller : None ,
280
- } ,
281
- OpenProtocolAttributes :: Exclusive ,
282
- )
283
- . expect ( "Failed to retrieve `LoadedImage` protocol from handle" )
284
- } ;
285
- let loaded_image = unsafe { & * loaded_image. interface . get ( ) } ;
286
-
287
- let device_handle = loaded_image. device ( ) ;
288
-
289
- let device_path = unsafe { this
290
- . open_protocol :: < DevicePath > (
291
- OpenProtocolParams {
292
- handle : device_handle,
293
- agent : image,
294
- controller : None ,
295
- } ,
296
- OpenProtocolAttributes :: Exclusive ,
297
- )
298
- . expect ( "Failed to retrieve `DevicePath` protocol from image's device handle" )
299
- } ;
300
- let mut device_path = unsafe { & * device_path. interface . get ( ) } ;
301
-
302
- let base_code_handle = this. locate_device_path :: < BaseCode > ( & mut device_path) . ok ( ) ?;
303
-
304
- let base_code_raw = unsafe { this
305
- . open_protocol :: < BaseCode > (
306
- OpenProtocolParams {
307
- handle : base_code_handle,
308
- agent : image,
309
- controller : None ,
310
- } ,
311
- OpenProtocolAttributes :: Exclusive ,
312
- )
313
- . unwrap ( )
314
- } ;
299
+ let base_code_raw = locate_and_open_protocol :: < BaseCode > ( image, st) ;
300
+ if base_code_raw. is_none ( ) {
301
+ // The previous code will log errors along the way, we do not need to.
302
+ return None ;
303
+ }
304
+ let base_code_raw = base_code_raw. unwrap ( ) ;
315
305
let base_code = unsafe { & mut * base_code_raw. interface . get ( ) } ;
316
306
317
307
// Find the TFTP boot server.
318
308
let mode = base_code. mode ( ) ;
319
309
assert ! ( mode. dhcp_ack_received) ;
320
310
let dhcpv4: & DhcpV4Packet = mode. dhcp_ack . as_ref ( ) ;
321
311
let server_ip = IpAddress :: new_v4 ( dhcpv4. bootp_si_addr ) ;
312
+ let mut buf = [ 0u8 ; 256 ] ;
313
+ assert ! ( name. len( ) < 256 ) ;
322
314
323
- let filename = CStr8 :: from_bytes_with_nul ( b"kernel-x86_64 \0 " ) . unwrap ( ) ;
315
+ let filename = CStr8 :: from_bytes_with_nul ( name . as_bytes ( ) ) . unwrap ( ) ;
324
316
325
317
// Determine the kernel file size.
326
318
let file_size = base_code
327
- . tftp_get_file_size ( & server_ip, filename)
328
- . expect ( "Failed to query the kernel file size" ) ;
329
- let kernel_size =
330
- usize:: try_from ( file_size) . expect ( "The kernel file size should fit into usize" ) ;
319
+ . tftp_get_file_size ( & server_ip, & filename)
320
+ . expect ( "Failed to query the file size" ) ;
321
+ let kernel_size = usize:: try_from ( file_size) . expect ( "The file size should fit into usize" ) ;
331
322
332
323
// Allocate some memory for the kernel file.
333
- let kernel_ptr = st
324
+ let ptr = st
334
325
. boot_services ( )
335
326
. allocate_pages (
336
327
AllocateType :: AnyPages ,
337
328
MemoryType :: LOADER_DATA ,
338
329
( ( kernel_size - 1 ) / 4096 ) + 1 ,
339
330
)
340
- . expect ( "Failed to allocate memory for the kernel file" ) as * mut u8 ;
341
- let kernel_slice = unsafe { slice:: from_raw_parts_mut ( kernel_ptr , kernel_size) } ;
331
+ . expect ( "Failed to allocate memory for the file" ) as * mut u8 ;
332
+ let slice = unsafe { slice:: from_raw_parts_mut ( ptr , kernel_size) } ;
342
333
343
334
// Load the kernel file.
344
335
base_code
345
- . tftp_read_file ( & server_ip, filename, Some ( kernel_slice ) )
336
+ . tftp_read_file ( & server_ip, & filename, Some ( slice ) )
346
337
. expect ( "Failed to read kernel file from the TFTP boot server" ) ;
347
338
348
- Some ( kernel_slice )
339
+ Some ( slice )
349
340
}
350
341
351
342
/// Creates page table abstraction types for both the bootloader and kernel page tables.
@@ -415,10 +406,10 @@ fn create_page_tables(
415
406
}
416
407
417
408
fn init_logger ( st : & SystemTable < Boot > , config : BootloaderConfig ) -> Option < RawFrameBufferInfo > {
418
- let gop = unsafe { st
419
- . boot_services ( )
420
- . locate_protocol :: < GraphicsOutput > ( )
421
- . ok ( ) ?
409
+ let gop = unsafe {
410
+ st . boot_services ( )
411
+ . locate_protocol :: < GraphicsOutput > ( )
412
+ . ok ( ) ?
422
413
} ;
423
414
let gop = unsafe { & mut * gop. get ( ) } ;
424
415
0 commit comments