7
7
#[ repr( align( 4096 ) ) ]
8
8
struct PageAligned < T > ( T ) ;
9
9
10
- use bootloader:: binary:: { legacy_memory_region:: LegacyFrameAllocator , SystemInfo } ;
11
- use bootloader_api:: info:: FrameBufferInfo ;
12
- use core:: { arch:: asm, mem, panic:: PanicInfo , slice} ;
10
+ use bootloader:: binary:: { legacy_memory_region:: LegacyFrameAllocator , Kernel , SystemInfo } ;
11
+ use bootloader_api:: { info:: FrameBufferInfo , BootloaderConfig } ;
12
+ use core:: { arch:: asm, mem, panic:: PanicInfo , ptr , slice} ;
13
13
use uefi:: {
14
14
prelude:: { entry, Boot , Handle , ResultExt , Status , SystemTable } ,
15
- proto:: console:: gop:: { GraphicsOutput , PixelFormat } ,
16
- table:: boot:: { MemoryDescriptor , MemoryType } ,
17
- Completion ,
15
+ proto:: {
16
+ console:: gop:: { GraphicsOutput , PixelFormat } ,
17
+ device_path:: DevicePath ,
18
+ loaded_image:: LoadedImage ,
19
+ media:: {
20
+ file:: { File , FileAttribute , FileInfo , FileMode } ,
21
+ fs:: SimpleFileSystem ,
22
+ } ,
23
+ } ,
24
+ table:: boot:: { AllocateType , MemoryDescriptor , MemoryType } ,
25
+ CStr16 , Completion ,
18
26
} ;
19
27
use x86_64:: {
20
28
structures:: paging:: { FrameAllocator , OffsetPageTable , PageTable , PhysFrame , Size4KiB } ,
21
29
PhysAddr , VirtAddr ,
22
30
} ;
31
+ use xmas_elf:: ElfFile ;
23
32
24
33
#[ entry]
25
34
fn efi_main ( image : Handle , st : SystemTable < Boot > ) -> Status {
26
- let ( framebuffer_addr, framebuffer_info) = init_logger ( & st) ;
27
- log:: info!( "Hello World from UEFI bootloader!" ) ;
35
+ main_inner ( image, st)
36
+ }
37
+
38
+ fn main_inner ( image : Handle , mut st : SystemTable < Boot > ) -> Status {
39
+ let mut buf = [ 0 ; 100 ] ;
40
+ st. stdout ( )
41
+ . output_string (
42
+ CStr16 :: from_str_with_buf ( "UEFI bootloader started; trying to load kernel" , & mut buf)
43
+ . unwrap ( ) ,
44
+ )
45
+ . unwrap ( )
46
+ . unwrap ( ) ;
47
+
48
+ let file_system_raw = {
49
+ let ref this = st. boot_services ( ) ;
50
+ let loaded_image = this
51
+ . handle_protocol :: < LoadedImage > ( image) ?
52
+ . expect ( "Failed to retrieve `LoadedImage` protocol from handle" ) ;
53
+ let loaded_image = unsafe { & * loaded_image. get ( ) } ;
54
+
55
+ let device_handle = loaded_image. device ( ) ;
56
+
57
+ let device_path = this
58
+ . handle_protocol :: < DevicePath > ( device_handle) ?
59
+ . expect ( "Failed to retrieve `DevicePath` protocol from image's device handle" ) ;
60
+ let mut device_path = unsafe { & * device_path. get ( ) } ;
61
+
62
+ let device_handle = this
63
+ . locate_device_path :: < SimpleFileSystem > ( & mut device_path) ?
64
+ . expect ( "Failed to locate `SimpleFileSystem` protocol on device path" ) ;
65
+
66
+ this. handle_protocol :: < SimpleFileSystem > ( device_handle)
67
+ }
68
+ . unwrap ( )
69
+ . unwrap ( ) ;
70
+ let file_system = unsafe { & mut * file_system_raw. get ( ) } ;
71
+
72
+ let mut root = file_system. open_volume ( ) . unwrap ( ) . unwrap ( ) ;
73
+ let kernel_file_handle = root
74
+ . open ( "kernel-x86_64" , FileMode :: Read , FileAttribute :: empty ( ) )
75
+ . unwrap ( )
76
+ . unwrap ( ) ;
77
+ let mut kernel_file = match kernel_file_handle. into_type ( ) . unwrap ( ) . unwrap ( ) {
78
+ uefi:: proto:: media:: file:: FileType :: Regular ( f) => f,
79
+ uefi:: proto:: media:: file:: FileType :: Dir ( _) => panic ! ( ) ,
80
+ } ;
81
+
82
+ let mut buf = [ 0 ; 100 ] ;
83
+ let kernel_info: & mut FileInfo = kernel_file. get_info ( & mut buf) . unwrap ( ) . unwrap ( ) ;
84
+ let kernel_size = usize:: try_from ( kernel_info. file_size ( ) ) . unwrap ( ) ;
85
+
86
+ let kernel_ptr = st
87
+ . boot_services ( )
88
+ . allocate_pages (
89
+ AllocateType :: AnyPages ,
90
+ MemoryType :: LOADER_DATA ,
91
+ ( ( kernel_size - 1 ) / 4096 ) + 1 ,
92
+ )
93
+ . unwrap ( )
94
+ . unwrap ( ) as * mut u8 ;
95
+ unsafe { ptr:: write_bytes ( kernel_ptr, 0 , kernel_size) } ;
96
+ let kernel_slice = unsafe { slice:: from_raw_parts_mut ( kernel_ptr, kernel_size) } ;
97
+ kernel_file. read ( kernel_slice) . unwrap ( ) . unwrap ( ) ;
98
+
99
+ let kernel_elf = ElfFile :: new ( kernel_slice) . unwrap ( ) ;
100
+
101
+ let config = {
102
+ let section = kernel_elf
103
+ . find_section_by_name ( ".bootloader-config" )
104
+ . unwrap ( ) ;
105
+ let raw = section. raw_data ( & kernel_elf) ;
106
+ BootloaderConfig :: deserialize ( raw) . unwrap ( )
107
+ } ;
108
+
109
+ let kernel = Kernel {
110
+ elf : kernel_elf,
111
+ config,
112
+ } ;
113
+
114
+ let ( framebuffer_addr, framebuffer_info) = init_logger ( & st, config) ;
115
+ log:: info!( "UEFI bootloader started" ) ;
116
+ log:: info!( "Reading kernel and configuration from disk was successful" ) ;
28
117
log:: info!( "Using framebuffer at {:#x}" , framebuffer_addr) ;
29
118
30
119
let mmap_storage = {
@@ -62,7 +151,7 @@ fn efi_main(image: Handle, st: SystemTable<Boot>) -> Status {
62
151
} ;
63
152
64
153
bootloader:: binary:: load_and_switch_to_kernel (
65
- & KERNEL . 0 ,
154
+ kernel ,
66
155
frame_allocator,
67
156
page_tables,
68
157
system_info,
@@ -135,7 +224,7 @@ fn create_page_tables(
135
224
}
136
225
}
137
226
138
- fn init_logger ( st : & SystemTable < Boot > ) -> ( PhysAddr , FrameBufferInfo ) {
227
+ fn init_logger ( st : & SystemTable < Boot > , config : BootloaderConfig ) -> ( PhysAddr , FrameBufferInfo ) {
139
228
let gop = st
140
229
. boot_services ( )
141
230
. locate_protocol :: < GraphicsOutput > ( )
@@ -145,8 +234,14 @@ fn init_logger(st: &SystemTable<Boot>) -> (PhysAddr, FrameBufferInfo) {
145
234
let mode = {
146
235
let modes = gop. modes ( ) . map ( Completion :: unwrap) ;
147
236
match (
148
- CONFIG . minimum_framebuffer_height ,
149
- CONFIG . minimum_framebuffer_width ,
237
+ config
238
+ . frame_buffer
239
+ . minimum_framebuffer_height
240
+ . map ( |v| usize:: try_from ( v) . unwrap ( ) ) ,
241
+ config
242
+ . frame_buffer
243
+ . minimum_framebuffer_width
244
+ . map ( |v| usize:: try_from ( v) . unwrap ( ) ) ,
150
245
) {
151
246
( Some ( height) , Some ( width) ) => modes
152
247
. filter ( |m| {
0 commit comments