Skip to content

Commit c5617fd

Browse files
authored
Integrate os_bootinfo 0.3.0 as a submodule (with some changes) (#23)
- Remove VERSION constant: The kernel can no longer have a separate dependency on os_bootinfo, so it is guaranteed that the bootinfo versions match. - Implement the From trait to convert between the frame range types of bootinfo and x86_64.
1 parent bce6f1a commit c5617fd

File tree

9 files changed

+305
-24
lines changed

9 files changed

+305
-24
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ publish-lockfile = true
1212
xmas-elf = "0.6.2"
1313
x86_64 = "0.2.7"
1414
usize_conversions = "0.2.0"
15-
os_bootinfo = "0.2.0"
1615
fixedvec = "0.2.3"
1716

1817
[profile.dev]

src/boot_info.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use core::slice;
22

3-
use os_bootinfo::{E820MemoryRegion, MemoryMap, MemoryRegion, MemoryRegionType};
3+
use bootloader::bootinfo::{E820MemoryRegion, MemoryMap, MemoryRegion, MemoryRegionType};
44
use usize_conversions::usize_from;
55
use x86_64::VirtAddr;
66

src/bootinfo/memory_map.rs

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
use core::fmt;
2+
use core::ops::{Deref, DerefMut};
3+
4+
const PAGE_SIZE: u64 = 4096;
5+
6+
#[repr(C)]
7+
pub struct MemoryMap {
8+
entries: [MemoryRegion; 32],
9+
// u64 instead of usize so that the structure layout is platform
10+
// independent
11+
next_entry_index: u64,
12+
}
13+
14+
impl MemoryMap {
15+
pub fn new() -> Self {
16+
MemoryMap {
17+
entries: [MemoryRegion::empty(); 32],
18+
next_entry_index: 0,
19+
}
20+
}
21+
22+
pub fn add_region(&mut self, region: MemoryRegion) {
23+
self.entries[self.next_entry_index()] = region;
24+
self.next_entry_index += 1;
25+
self.sort();
26+
}
27+
28+
pub fn sort(&mut self) {
29+
use core::cmp::Ordering;
30+
31+
self.entries.sort_unstable_by(|r1, r2| {
32+
if r1.range.is_empty() {
33+
Ordering::Greater
34+
} else if r2.range.is_empty() {
35+
Ordering::Less
36+
} else {
37+
let ordering = r1
38+
.range
39+
.start_frame_number
40+
.cmp(&r2.range.start_frame_number);
41+
42+
if ordering == Ordering::Equal {
43+
r1.range.end_frame_number.cmp(&r2.range.end_frame_number)
44+
} else {
45+
ordering
46+
}
47+
}
48+
});
49+
if let Some(first_zero_index) = self.entries.iter().position(|r| r.range.is_empty()) {
50+
self.next_entry_index = first_zero_index as u64;
51+
}
52+
}
53+
54+
fn next_entry_index(&self) -> usize {
55+
self.next_entry_index as usize
56+
}
57+
}
58+
59+
impl Deref for MemoryMap {
60+
type Target = [MemoryRegion];
61+
62+
fn deref(&self) -> &Self::Target {
63+
&self.entries[0..self.next_entry_index()]
64+
}
65+
}
66+
67+
impl DerefMut for MemoryMap {
68+
fn deref_mut(&mut self) -> &mut Self::Target {
69+
let next_index = self.next_entry_index();
70+
&mut self.entries[0..next_index]
71+
}
72+
}
73+
74+
impl fmt::Debug for MemoryMap {
75+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76+
f.debug_list().entries(self.iter()).finish()
77+
}
78+
}
79+
80+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
81+
#[repr(C)]
82+
pub struct MemoryRegion {
83+
pub range: FrameRange,
84+
pub region_type: MemoryRegionType,
85+
}
86+
87+
impl MemoryRegion {
88+
pub fn empty() -> Self {
89+
MemoryRegion {
90+
range: FrameRange {
91+
start_frame_number: 0,
92+
end_frame_number: 0,
93+
},
94+
region_type: MemoryRegionType::Empty,
95+
}
96+
}
97+
}
98+
99+
#[derive(Clone, Copy, PartialEq, Eq)]
100+
#[repr(C)]
101+
pub struct FrameRange {
102+
pub start_frame_number: u64,
103+
// exclusive
104+
pub end_frame_number: u64,
105+
}
106+
107+
impl FrameRange {
108+
/// Create a new FrameRange from the passed start_addr and end_addr.
109+
///
110+
/// The end_addr is exclusive.
111+
pub fn new(start_addr: u64, end_addr: u64) -> Self {
112+
let last_byte = end_addr - 1;
113+
FrameRange {
114+
start_frame_number: start_addr / PAGE_SIZE,
115+
end_frame_number: (last_byte / PAGE_SIZE) + 1,
116+
}
117+
}
118+
119+
pub fn is_empty(&self) -> bool {
120+
self.start_frame_number == self.end_frame_number
121+
}
122+
123+
pub fn start_addr(&self) -> u64 {
124+
self.start_frame_number * PAGE_SIZE
125+
}
126+
127+
pub fn end_addr(&self) -> u64 {
128+
self.end_frame_number * PAGE_SIZE
129+
}
130+
}
131+
132+
impl fmt::Debug for FrameRange {
133+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134+
write!(
135+
f,
136+
"FrameRange({:#x}..{:#x})",
137+
self.start_addr(),
138+
self.end_addr()
139+
)
140+
}
141+
}
142+
143+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
144+
#[repr(C)]
145+
pub enum MemoryRegionType {
146+
/// free RAM
147+
Usable,
148+
/// used RAM
149+
InUse,
150+
/// unusable
151+
Reserved,
152+
/// ACPI reclaimable memory
153+
AcpiReclaimable,
154+
/// ACPI NVS memory
155+
AcpiNvs,
156+
/// Area containing bad memory
157+
BadMemory,
158+
/// kernel memory
159+
Kernel,
160+
/// kernel stack memory
161+
KernelStack,
162+
/// memory used by page tables
163+
PageTable,
164+
/// memory used by the bootloader
165+
Bootloader,
166+
/// frame at address zero
167+
///
168+
/// (shouldn't be used because it's easy to make mistakes related to null pointers)
169+
FrameZero,
170+
/// an empty region with size 0
171+
Empty,
172+
/// used for storing the boot information
173+
BootInfo,
174+
/// used for storing the supplied package
175+
Package,
176+
}
177+
178+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
179+
#[repr(C)]
180+
pub struct E820MemoryRegion {
181+
pub start_addr: u64,
182+
pub len: u64,
183+
pub region_type: u32,
184+
pub acpi_extended_attributes: u32,
185+
}
186+
187+
impl From<E820MemoryRegion> for MemoryRegion {
188+
fn from(region: E820MemoryRegion) -> MemoryRegion {
189+
let region_type = match region.region_type {
190+
1 => MemoryRegionType::Usable,
191+
2 => MemoryRegionType::Reserved,
192+
3 => MemoryRegionType::AcpiReclaimable,
193+
4 => MemoryRegionType::AcpiNvs,
194+
5 => MemoryRegionType::BadMemory,
195+
t => panic!("invalid region type {}", t),
196+
};
197+
MemoryRegion {
198+
range: FrameRange::new(region.start_addr, region.start_addr + region.len),
199+
region_type,
200+
}
201+
}
202+
}
203+
204+
extern "C" {
205+
fn _improper_ctypes_check(_boot_info: MemoryMap);
206+
}

src/bootinfo/mod.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#![deny(improper_ctypes)]
2+
3+
pub use self::memory_map::*;
4+
use core::ops::Deref;
5+
use core::slice;
6+
7+
mod memory_map;
8+
9+
#[derive(Debug)]
10+
#[repr(C)]
11+
pub struct BootInfo {
12+
pub p4_table_addr: u64,
13+
pub memory_map: MemoryMap,
14+
pub package: Package,
15+
}
16+
17+
#[derive(Debug)]
18+
#[repr(C)]
19+
pub struct Package {
20+
ptr: *const u8,
21+
len: u64,
22+
}
23+
24+
impl Deref for Package {
25+
type Target = [u8];
26+
fn deref(&self) -> &[u8] {
27+
unsafe { slice::from_raw_parts(self.ptr, self.len as usize) }
28+
}
29+
}
30+
31+
impl BootInfo {
32+
pub fn new(p4_table_addr: u64, memory_map: MemoryMap, package: &'static [u8]) -> Self {
33+
BootInfo {
34+
p4_table_addr,
35+
memory_map,
36+
package: Package {
37+
ptr: package.as_ptr(),
38+
len: package.len() as u64,
39+
},
40+
}
41+
}
42+
}
43+
44+
extern "C" {
45+
fn _improper_ctypes_check(_boot_info: BootInfo);
46+
}
47+
48+
use x86_64::{
49+
structures::paging::{PhysFrame, PhysFrameRange},
50+
PhysAddr,
51+
};
52+
53+
impl From<FrameRange> for PhysFrameRange {
54+
fn from(range: FrameRange) -> Self {
55+
PhysFrameRange {
56+
start: PhysFrame::from_start_address(PhysAddr::new(range.start_addr())).unwrap(),
57+
end: PhysFrame::from_start_address(PhysAddr::new(range.end_addr())).unwrap(),
58+
}
59+
}
60+
}
61+
62+
impl From<PhysFrameRange> for FrameRange {
63+
fn from(range: PhysFrameRange) -> Self {
64+
FrameRange::new(
65+
range.start.start_address().as_u64(),
66+
range.end.start_address().as_u64(),
67+
)
68+
}
69+
}

src/frame_allocator.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use os_bootinfo::{MemoryMap, MemoryRegion, MemoryRegionType};
1+
use bootloader::bootinfo::{MemoryMap, MemoryRegion, MemoryRegionType};
22
use x86_64::structures::paging::{PhysFrame, PhysFrameRange};
33

44
pub(crate) struct FrameAllocator<'a> {
@@ -52,8 +52,10 @@ impl<'a> FrameAllocator<'a> {
5252
};
5353

5454
if let Some((frame, range)) = result {
55-
self.memory_map
56-
.add_region(MemoryRegion { range: range.into(), region_type });
55+
self.memory_map.add_region(MemoryRegion {
56+
range: range.into(),
57+
region_type,
58+
});
5759
Some(frame)
5860
} else {
5961
None

src/lib.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
#![no_std]
22

3-
extern crate os_bootinfo;
3+
extern crate x86_64;
44

5-
pub mod bootinfo {
6-
pub use os_bootinfo::*;
7-
}
5+
pub mod bootinfo;
86

97
/// Defines the entry point function.
108
///

src/main.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@
99
#![no_std]
1010
#![no_main]
1111

12-
extern crate os_bootinfo;
12+
extern crate bootloader;
1313
extern crate usize_conversions;
1414
extern crate x86_64;
1515
extern crate xmas_elf;
1616
#[macro_use]
1717
extern crate fixedvec;
1818

19-
use core::slice;
19+
use bootloader::bootinfo::BootInfo;
2020
use core::panic::PanicInfo;
21-
use os_bootinfo::BootInfo;
21+
use core::slice;
2222
use usize_conversions::usize_from;
2323
use x86_64::structures::paging::{Mapper, RecursivePageTable};
2424
use x86_64::structures::paging::{Page, PageTableFlags, PhysFrame, Size2MiB};
@@ -67,8 +67,8 @@ pub extern "C" fn load_elf(
6767
bootloader_start: PhysAddr,
6868
bootloader_end: PhysAddr,
6969
) -> ! {
70+
use bootloader::bootinfo::{MemoryRegion, MemoryRegionType};
7071
use fixedvec::FixedVec;
71-
use os_bootinfo::{MemoryRegion, MemoryRegionType};
7272
use xmas_elf::program::{ProgramHeader, ProgramHeader64};
7373

7474
printer::Printer.clear_screen();
@@ -117,7 +117,6 @@ pub extern "C" fn load_elf(
117117
memory_map: &mut memory_map,
118118
};
119119

120-
121120
// Mark already used memory areas in frame allocator.
122121
{
123122
let zero_frame: PhysFrame = PhysFrame::from_start_address(PhysAddr::new(0)).unwrap();
@@ -151,7 +150,6 @@ pub extern "C" fn load_elf(
151150
});
152151
}
153152

154-
155153
// Unmap the ELF file.
156154
let kernel_start_page: Page<Size2MiB> = Page::containing_address(kernel_start.virt());
157155
let kernel_end_page: Page<Size2MiB> =
@@ -181,12 +179,17 @@ pub extern "C" fn load_elf(
181179
flags,
182180
&mut rec_page_table,
183181
&mut frame_allocator,
184-
).expect("Mapping of bootinfo page failed").flush();
182+
).expect("Mapping of bootinfo page failed")
183+
.flush();
185184
page
186185
};
187186

188187
// Construct boot info structure.
189-
let mut boot_info = BootInfo::new(recursive_page_table_addr.start_address().as_u64(), memory_map);
188+
let mut boot_info = BootInfo::new(
189+
recursive_page_table_addr.start_address().as_u64(),
190+
memory_map,
191+
&[],
192+
);
190193
boot_info.memory_map.sort();
191194

192195
// Write boot info to boot info page.

0 commit comments

Comments
 (0)