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