@@ -17,9 +17,13 @@ use uefi::{
17
17
file:: { File , FileAttribute , FileInfo , FileMode } ,
18
18
fs:: SimpleFileSystem ,
19
19
} ,
20
+ network:: {
21
+ pxe:: { BaseCode , DhcpV4Packet } ,
22
+ IpAddress ,
23
+ } ,
20
24
} ,
21
25
table:: boot:: { AllocateType , MemoryDescriptor , MemoryType } ,
22
- CStr16 ,
26
+ CStr16 , CStr8 ,
23
27
} ;
24
28
use x86_64:: {
25
29
structures:: paging:: { FrameAllocator , OffsetPageTable , PageTable , PhysFrame , Size4KiB } ,
@@ -122,6 +126,16 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {
122
126
}
123
127
124
128
fn load_kernel ( image : Handle , st : & SystemTable < Boot > ) -> Kernel < ' static > {
129
+ let kernel_slice = load_kernel_file ( image, st) . expect ( "couldn't find kernel" ) ;
130
+ Kernel :: parse ( kernel_slice)
131
+ }
132
+
133
+ fn load_kernel_file ( image : Handle , st : & SystemTable < Boot > ) -> Option < & ' static mut [ u8 ] > {
134
+ load_kernel_file_from_disk ( image, st)
135
+ . or_else ( || load_kernel_file_from_tftp_boot_server ( image, st) )
136
+ }
137
+
138
+ fn load_kernel_file_from_disk ( image : Handle , st : & SystemTable < Boot > ) -> Option < & ' static mut [ u8 ] > {
125
139
let file_system_raw = {
126
140
let ref this = st. boot_services ( ) ;
127
141
let loaded_image = this
@@ -138,7 +152,7 @@ fn load_kernel(image: Handle, st: &SystemTable<Boot>) -> Kernel<'static> {
138
152
139
153
let device_handle = this
140
154
. locate_device_path :: < SimpleFileSystem > ( & mut device_path)
141
- . expect ( "Failed to locate `SimpleFileSystem` protocol on device path" ) ;
155
+ . ok ( ) ? ;
142
156
143
157
this. handle_protocol :: < SimpleFileSystem > ( device_handle)
144
158
}
@@ -172,7 +186,64 @@ fn load_kernel(image: Handle, st: &SystemTable<Boot>) -> Kernel<'static> {
172
186
let kernel_slice = unsafe { slice:: from_raw_parts_mut ( kernel_ptr, kernel_size) } ;
173
187
kernel_file. read ( kernel_slice) . unwrap ( ) ;
174
188
175
- Kernel :: parse ( kernel_slice)
189
+ Some ( kernel_slice)
190
+ }
191
+
192
+ fn load_kernel_file_from_tftp_boot_server (
193
+ image : Handle ,
194
+ st : & SystemTable < Boot > ,
195
+ ) -> Option < & ' static mut [ u8 ] > {
196
+ let ref this = st. boot_services ( ) ;
197
+
198
+ let file_system_raw = {
199
+ let ref this = st. boot_services ( ) ;
200
+ let loaded_image = this
201
+ . handle_protocol :: < LoadedImage > ( image)
202
+ . expect ( "Failed to retrieve `LoadedImage` protocol from handle" ) ;
203
+ let loaded_image = unsafe { & * loaded_image. get ( ) } ;
204
+
205
+ let device_handle = loaded_image. device ( ) ;
206
+
207
+ let device_path = this
208
+ . handle_protocol :: < DevicePath > ( device_handle)
209
+ . expect ( "Failed to retrieve `DevicePath` protocol from image's device handle" ) ;
210
+ let mut device_path = unsafe { & * device_path. get ( ) } ;
211
+
212
+ let device_handle = this
213
+ . locate_device_path :: < BaseCode > ( & mut device_path)
214
+ . expect ( "Failed to locate `BaseCode` protocol on device path" ) ;
215
+
216
+ this. handle_protocol :: < BaseCode > ( device_handle)
217
+ }
218
+ . unwrap ( ) ;
219
+ let base_code = unsafe { & mut * file_system_raw. get ( ) } ;
220
+
221
+ let mode = base_code. mode ( ) ;
222
+ assert ! ( mode. dhcp_ack_received) ;
223
+ let dhcpv4: & DhcpV4Packet = mode. dhcp_ack . as_ref ( ) ;
224
+ let server_ip = IpAddress :: new_v4 ( dhcpv4. bootp_si_addr ) ;
225
+
226
+ let filename = CStr8 :: from_bytes_with_nul ( b"kernel-x86_64\0 " ) . unwrap ( ) ;
227
+ let file_size = base_code. tftp_get_file_size ( & server_ip, filename) . unwrap ( ) ;
228
+
229
+ let kernel_size = usize:: try_from ( file_size) . unwrap ( ) ;
230
+
231
+ let kernel_ptr = st
232
+ . boot_services ( )
233
+ . allocate_pages (
234
+ AllocateType :: AnyPages ,
235
+ MemoryType :: LOADER_DATA ,
236
+ ( ( kernel_size - 1 ) / 4096 ) + 1 ,
237
+ )
238
+ . unwrap ( ) as * mut u8 ;
239
+ unsafe { ptr:: write_bytes ( kernel_ptr, 0 , kernel_size) } ;
240
+ let kernel_slice = unsafe { slice:: from_raw_parts_mut ( kernel_ptr, kernel_size) } ;
241
+
242
+ base_code
243
+ . tftp_read_file ( & server_ip, filename, Some ( kernel_slice) )
244
+ . unwrap ( ) ;
245
+
246
+ Some ( kernel_slice)
176
247
}
177
248
178
249
/// Creates page table abstraction types for both the bootloader and kernel page tables.
0 commit comments