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