1
1
use frame_allocator:: FrameAllocator ;
2
- use x86_64:: { PhysAddr , VirtAddr } ;
2
+ use x86_64:: { PhysAddr , VirtAddr , align_up } ;
3
3
use x86_64:: structures:: paging:: { PAGE_SIZE , PageTable , PageTableFlags , PageTableEntry , Page , PhysFrame } ;
4
4
use usize_conversions:: usize_from;
5
5
use xmas_elf;
@@ -38,14 +38,19 @@ pub(crate) fn identity_map(frame: PhysFrame, flags: PageTableFlags, p4: &mut Pag
38
38
pub ( crate ) fn map_segment ( kernel_start : PhysAddr , program_header : ProgramHeader , p4 : & mut PageTable ,
39
39
frame_allocator : & mut FrameAllocator )
40
40
{
41
+ unsafe fn zero_frame ( frame : & PhysFrame ) {
42
+ let frame_ptr = frame. start_address ( ) . as_u64 ( ) as * mut [ u8 ; PAGE_SIZE as usize ] ;
43
+ * frame_ptr = [ 0 ; PAGE_SIZE as usize ] ;
44
+ }
45
+
41
46
let typ = program_header. get_type ( ) . unwrap ( ) ;
42
47
match typ {
43
48
program:: Type :: Load => {
49
+ let mem_size = program_header. mem_size ( ) ;
50
+ let file_size = program_header. file_size ( ) ;
44
51
let file_offset = program_header. offset ( ) ;
45
52
let phys_start_addr = kernel_start + file_offset;
46
- let size = program_header. mem_size ( ) ;
47
53
let virt_start_addr = VirtAddr :: new ( program_header. virtual_addr ( ) ) ;
48
- let virt_end_addr = virt_start_addr + size;
49
54
50
55
let flags = program_header. flags ( ) ;
51
56
let mut page_table_flags = PageTableFlags :: PRESENT ;
@@ -54,10 +59,30 @@ pub(crate) fn map_segment(kernel_start: PhysAddr, program_header: ProgramHeader,
54
59
55
60
for offset in ( 0 ..) . step_by ( usize_from ( PAGE_SIZE ) ) {
56
61
let page = Page :: containing_address ( virt_start_addr + offset) ;
57
- let frame = PhysFrame :: containing_address ( phys_start_addr + offset ) ;
58
- if page . start_address ( ) >= virt_end_addr {
62
+ let frame;
63
+ if offset >= mem_size {
59
64
break
60
65
}
66
+ if offset >= file_size {
67
+ // map to zeroed frame
68
+ frame = frame_allocator. allocate_frame ( ) ;
69
+ unsafe { zero_frame ( & frame) } ;
70
+ } else if align_up ( offset, u64:: from ( PAGE_SIZE ) ) - 1 >= file_size {
71
+ // part of the page should be zeroed
72
+ frame = frame_allocator. allocate_frame ( ) ;
73
+ unsafe { zero_frame ( & frame) } ;
74
+ // copy data from kernel image
75
+ let data_frame_start = PhysFrame :: containing_address ( phys_start_addr + offset) ;
76
+ let data_ptr = data_frame_start. start_address ( ) . as_u64 ( ) as * const u8 ;
77
+ let frame_ptr = frame. start_address ( ) . as_u64 ( ) as * mut u8 ;
78
+ for i in offset..file_size {
79
+ let i = i as isize ;
80
+ unsafe { frame_ptr. offset ( i) . write ( data_ptr. offset ( i) . read ( ) ) } ;
81
+ }
82
+ } else {
83
+ // map to part of kernel binary
84
+ frame = PhysFrame :: containing_address ( phys_start_addr + offset) ;
85
+ }
61
86
map_page ( page, frame, page_table_flags, p4, frame_allocator) ;
62
87
}
63
88
} ,
0 commit comments