1
1
use alloc:: boxed:: Box ;
2
+ use alloc:: vec:: Vec ;
2
3
use elf_rs:: { ElfFile , ProgramHeaderEntry , ProgramType } ;
4
+ use log:: { debug, info} ;
3
5
use multiboot2:: {
4
- BootLoaderNameTag , CommandLineTag , MaybeDynSized , MemoryArea , MemoryAreaType , MemoryMapTag ,
5
- ModuleTag , SmbiosTag ,
6
+ BootLoaderNameTag , CommandLineTag , EFIMemoryAreaType , MaybeDynSized , MemoryArea ,
7
+ MemoryAreaType , MemoryMapTag , ModuleTag , SmbiosTag ,
6
8
} ;
7
9
10
+ fn get_free_mmap_areas (
11
+ mbi : & multiboot2:: BootInformation ,
12
+ ) -> Vec < ( u64 /* start */ , u64 /* size */ ) > {
13
+ match ( mbi. memory_map_tag ( ) , mbi. efi_memory_map_tag ( ) ) {
14
+ ( Some ( mmt) , None ) => mmt
15
+ . memory_areas ( )
16
+ . iter ( )
17
+ . filter ( |ma| ma. typ ( ) == MemoryAreaType :: Available )
18
+ . map ( |ma| ( ma. start_address ( ) , ma. size ( ) ) )
19
+ . collect :: < alloc:: vec:: Vec < _ > > ( ) ,
20
+ ( _, Some ( mmt) ) => mmt
21
+ . memory_areas ( )
22
+ . filter ( |ma| ma. ty == EFIMemoryAreaType :: CONVENTIONAL )
23
+ . map ( |ma| ( ma. phys_start , ma. page_count * 4096 ) )
24
+ . collect :: < alloc:: vec:: Vec < _ > > ( ) ,
25
+ _ => panic ! ( "No usable memory map" ) ,
26
+ }
27
+ }
28
+
29
+ fn assert_load_segment_fits_into_memory (
30
+ start : u64 ,
31
+ size : u64 ,
32
+ free_areas : & [ ( u64 /* start */ , u64 /* size */ ) ] ,
33
+ ) {
34
+ let end = start + size;
35
+ let range = free_areas
36
+ . iter ( )
37
+ . find ( |( a_start, a_size) | start >= * a_start && end <= a_start + a_size) ;
38
+ if let Some ( range) = range {
39
+ debug ! ( "Can load load segment (0x{start:x?}, {size:x?}) into free memory area {range:#x?}" ) ;
40
+ } else {
41
+ panic ! ( "Can't load load segment (0x{start:x?}, {size:x?}) into any area!" ) ;
42
+ }
43
+ }
44
+
8
45
/// Loads the first module into memory. Assumes that the module is a ELF file.
9
46
/// The handoff is performed according to the Multiboot2 spec.
10
- pub fn load_module ( mut modules : multiboot:: information:: ModuleIter ) -> ! {
47
+ pub fn load_module ( mbi : & multiboot2:: BootInformation ) -> ! {
48
+ let mut modules = mbi. module_tags ( ) ;
49
+
11
50
// Load the ELF from the Multiboot1 boot module.
12
51
let elf_mod = modules. next ( ) . expect ( "Should have payload" ) ;
13
52
let elf_bytes = unsafe {
14
53
core:: slice:: from_raw_parts (
15
- elf_mod. start as * const u64 as * const u8 ,
16
- ( elf_mod. end - elf_mod . start ) as usize ,
54
+ elf_mod. start_address ( ) as * const u64 as * const u8 ,
55
+ elf_mod. module_size ( ) as usize ,
17
56
)
18
57
} ;
19
58
let elf = elf_rs:: Elf32 :: from_bytes ( elf_bytes) . expect ( "Should be valid ELF" ) ;
@@ -28,10 +67,11 @@ pub fn load_module(mut modules: multiboot::information::ModuleIter) -> ! {
28
67
log:: info!( "Multiboot2 header:\n {hdr:#?}" ) ;
29
68
}
30
69
31
- // Map the load segments into memory (at their corresponding link).
70
+ // Load the load segments into memory (at their corresponding link address ).
32
71
{
33
- let elf = elf_rs :: Elf32 :: from_bytes ( elf_bytes ) . expect ( "Should be valid ELF" ) ;
72
+ let free_areas = get_free_mmap_areas ( mbi ) ;
34
73
elf. program_header_iter ( )
74
+ . inspect ( |ph| assert_load_segment_fits_into_memory ( ph. vaddr ( ) , ph. memsz ( ) , & free_areas) )
35
75
. filter ( |ph| ph. ph_type ( ) == ProgramType :: LOAD )
36
76
. for_each ( |ph| {
37
77
map_memory ( ph) ;
@@ -53,9 +93,9 @@ pub fn load_module(mut modules: multiboot::information::ModuleIter) -> ! {
53
93
MemoryAreaType :: Reserved ,
54
94
) ] ) )
55
95
. add_module ( ModuleTag :: new (
56
- elf_mod. start as u32 ,
57
- elf_mod. end as u32 ,
58
- elf_mod. string . unwrap ( ) ,
96
+ elf_mod. start_address ( ) ,
97
+ elf_mod. end_address ( ) ,
98
+ elf_mod. cmdline ( ) . unwrap ( ) ,
59
99
) )
60
100
// Test that we can add SmbiosTag multiple times.
61
101
. add_smbios ( SmbiosTag :: new ( 1 , 1 , & [ 1 , 2 , 3 ] ) )
@@ -66,7 +106,7 @@ pub fn load_module(mut modules: multiboot::information::ModuleIter) -> ! {
66
106
67
107
log:: info!(
68
108
"Handing over to ELF: {}" ,
69
- elf_mod. string . unwrap_or( "<unknown>" )
109
+ elf_mod. cmdline ( ) . unwrap_or( "<unknown>" )
70
110
) ;
71
111
72
112
// handoff
@@ -84,7 +124,7 @@ pub fn load_module(mut modules: multiboot::information::ModuleIter) -> ! {
84
124
/// address space. The loader assumes that the addresses to not clash with the
85
125
/// loader (or anything else).
86
126
fn map_memory ( ph : ProgramHeaderEntry ) {
87
- log :: debug!( "Mapping LOAD segment {ph:#?}" ) ;
127
+ debug ! ( "Mapping LOAD segment {ph:#?}" ) ;
88
128
let dest_ptr = ph. vaddr ( ) as * mut u8 ;
89
129
let content = ph. content ( ) . expect ( "Should have content" ) ;
90
130
unsafe { core:: ptr:: copy ( content. as_ptr ( ) , dest_ptr, content. len ( ) ) } ;
0 commit comments