@@ -17,9 +17,13 @@ use uefi::{
1717 file:: { File , FileAttribute , FileInfo , FileMode } ,
1818 fs:: SimpleFileSystem ,
1919 } ,
20+ network:: {
21+ pxe:: { BaseCode , DhcpV4Packet } ,
22+ IpAddress ,
23+ } ,
2024 } ,
2125 table:: boot:: { AllocateType , MemoryDescriptor , MemoryType } ,
22- CStr16 ,
26+ CStr16 , CStr8 ,
2327} ;
2428use x86_64:: {
2529 structures:: paging:: { FrameAllocator , OffsetPageTable , PageTable , PhysFrame , Size4KiB } ,
@@ -122,6 +126,16 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {
122126}
123127
124128fn 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 ] > {
125139 let file_system_raw = {
126140 let ref this = st. boot_services ( ) ;
127141 let loaded_image = this
@@ -138,7 +152,7 @@ fn load_kernel(image: Handle, st: &SystemTable<Boot>) -> Kernel<'static> {
138152
139153 let device_handle = this
140154 . locate_device_path :: < SimpleFileSystem > ( & mut device_path)
141- . expect ( "Failed to locate `SimpleFileSystem` protocol on device path" ) ;
155+ . ok ( ) ? ;
142156
143157 this. handle_protocol :: < SimpleFileSystem > ( device_handle)
144158 }
@@ -172,7 +186,64 @@ fn load_kernel(image: Handle, st: &SystemTable<Boot>) -> Kernel<'static> {
172186 let kernel_slice = unsafe { slice:: from_raw_parts_mut ( kernel_ptr, kernel_size) } ;
173187 kernel_file. read ( kernel_slice) . unwrap ( ) ;
174188
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)
176247}
177248
178249/// Creates page table abstraction types for both the bootloader and kernel page tables.
0 commit comments