Skip to content

Commit e318de5

Browse files
committed
Add bios support for loading a ramdisk
1 parent 555769c commit e318de5

File tree

7 files changed

+93
-25
lines changed

7 files changed

+93
-25
lines changed

api/src/config.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ impl BootloaderConfig {
231231
[1] => Option::Some(u64::from_le_bytes(dynamic_range_end)),
232232
_ => return Err("invalid dynamic range end value"),
233233
},
234-
ramdisk_memory: Mapping::deserialize(&ramdisk_memory)?
234+
ramdisk_memory: Mapping::deserialize(&ramdisk_memory)?,
235235
};
236236
(mappings, s)
237237
};
@@ -388,7 +388,7 @@ pub struct Mappings {
388388
pub dynamic_range_end: Option<u64>,
389389
/// Virtual address to map ramdisk image, if present on disk
390390
/// Defaults to dynamic
391-
pub ramdisk_memory: Mapping
391+
pub ramdisk_memory: Mapping,
392392
}
393393

394394
impl Mappings {
@@ -405,7 +405,7 @@ impl Mappings {
405405
aslr: false,
406406
dynamic_range_start: None,
407407
dynamic_range_end: None,
408-
ramdisk_memory: Mapping::new_default()
408+
ramdisk_memory: Mapping::new_default(),
409409
}
410410
}
411411

@@ -438,7 +438,7 @@ impl Mappings {
438438
} else {
439439
Option::None
440440
},
441-
ramdisk_memory: Mapping::random()
441+
ramdisk_memory: Mapping::random(),
442442
}
443443
}
444444
}

api/src/info.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ pub struct BootInfo {
5252
pub rsdp_addr: Optional<u64>,
5353
/// The thread local storage (TLS) template of the kernel executable, if present.
5454
pub tls_template: Optional<TlsTemplate>,
55+
/// Ramdisk address, if loaded
56+
pub ramdisk_addr: Optional<u64>,
57+
/// Ramdisk image size, set to 0 if addr is None
58+
pub ramdisk_len: u64,
5559
}
5660

5761
impl BootInfo {
@@ -67,6 +71,8 @@ impl BootInfo {
6771
recursive_index: Optional::None,
6872
rsdp_addr: Optional::None,
6973
tls_template: Optional::None,
74+
ramdisk_addr: Optional::None,
75+
ramdisk_len: 0,
7076
}
7177
}
7278
}

bios/common/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub mod racy_cell;
77
pub struct BiosInfo {
88
pub stage_4: Region,
99
pub kernel: Region,
10+
pub ramdisk: Region,
1011
pub framebuffer: BiosFramebufferInfo,
1112
pub memory_map_addr: u32,
1213
pub memory_map_len: u16,

bios/stage-2/src/main.rs

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const BOOTLOADER_SECOND_STAGE_PARTITION_TYPE: u8 = 0x20;
2727
const STAGE_3_DST: *mut u8 = 0x0010_0000 as *mut u8; // 1MiB (typically 14MiB accessible here)
2828
const STAGE_4_DST: *mut u8 = 0x0020_0000 as *mut u8; // 2MiB (typically still 13MiB accessible here)
2929
const KERNEL_DST: *mut u8 = 0x0100_0000 as *mut u8; // 16MiB
30+
const RAMDISK_DST: *mut u8 = 0x0400_0000 as *mut u8; // 64MiB
3031

3132
static mut DISK_BUFFER: AlignedArrayBuffer<0x4000> = AlignedArrayBuffer {
3233
buffer: [0; 0x4000],
@@ -98,6 +99,23 @@ fn start(disk_number: u16, partition_table_start: *const u8) -> ! {
9899
writeln!(screen::Writer, "loading kernel...").unwrap();
99100
let kernel_len = load_file("kernel-x86_64", KERNEL_DST, &mut fs, &mut disk, disk_buffer);
100101
writeln!(screen::Writer, "kernel loaded at {KERNEL_DST:#p}").unwrap();
102+
writeln!(screen::Writer, "Loading ramdisk...").unwrap();
103+
let ramdisk_len = match try_load_file(
104+
"ramdisk-x86_64",
105+
RAMDISK_DST,
106+
&mut fs,
107+
&mut disk,
108+
disk_buffer,
109+
) {
110+
Some(s) => s,
111+
None => 0u64,
112+
};
113+
114+
if ramdisk_len == 0 {
115+
writeln!(screen::Writer, "No ramdisk found, skipping.").unwrap();
116+
} else {
117+
writeln!(screen::Writer, "Loaded ramdisk at {RAMDISK_DST:#p}").unwrap();
118+
}
101119

102120
let memory_map = unsafe { memory_map::query_memory_map() }.unwrap();
103121
writeln!(screen::Writer, "{memory_map:x?}").unwrap();
@@ -129,6 +147,10 @@ fn start(disk_number: u16, partition_table_start: *const u8) -> ! {
129147
start: KERNEL_DST as u64,
130148
len: kernel_len,
131149
},
150+
ramdisk: Region {
151+
start: RAMDISK_DST as u64,
152+
len: ramdisk_len,
153+
},
132154
memory_map_addr: memory_map.as_mut_ptr() as u32,
133155
memory_map_len: memory_map.len().try_into().unwrap(),
134156
framebuffer: BiosFramebufferInfo {
@@ -151,17 +173,21 @@ fn start(disk_number: u16, partition_table_start: *const u8) -> ! {
151173
}
152174
}
153175

154-
fn load_file(
176+
fn try_load_file(
155177
file_name: &str,
156178
dst: *mut u8,
157179
fs: &mut fat::FileSystem<disk::DiskAccess>,
158180
disk: &mut disk::DiskAccess,
159181
disk_buffer: &mut AlignedArrayBuffer<16384>,
160-
) -> u64 {
182+
) -> Option<u64> {
161183
let disk_buffer_size = disk_buffer.buffer.len();
162-
let file = fs
163-
.find_file_in_root_dir(file_name, disk_buffer)
164-
.expect("file not found");
184+
let optional_file = fs.find_file_in_root_dir(file_name, disk_buffer);
185+
if optional_file.is_none() {
186+
return None;
187+
}
188+
189+
let file = optional_file.unwrap();
190+
165191
let file_size = file.file_size().into();
166192

167193
let mut total_offset = 0;
@@ -195,7 +221,17 @@ fn load_file(
195221
total_offset += usize::try_from(len).unwrap();
196222
}
197223
}
198-
file_size
224+
Some(file_size)
225+
}
226+
227+
fn load_file(
228+
file_name: &str,
229+
dst: *mut u8,
230+
fs: &mut fat::FileSystem<disk::DiskAccess>,
231+
disk: &mut disk::DiskAccess,
232+
disk_buffer: &mut AlignedArrayBuffer<16384>,
233+
) -> u64 {
234+
try_load_file(file_name, dst, fs, disk, disk_buffer).expect("file not found")
199235
}
200236

201237
/// Taken from https://github.com/rust-lang/rust/blob/e100ec5bc7cd768ec17d75448b29c9ab4a39272b/library/core/src/slice/mod.rs#L1673-L1677

bios/stage-4/src/main.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! {
118118
info: framebuffer_info,
119119
}),
120120
rsdp_addr: detect_rsdp(),
121+
ramdisk_addr: match info.ramdisk.len {
122+
0 => None,
123+
_ => Some(info.ramdisk.start)
124+
},
125+
ramdisk_len: info.ramdisk.len
121126
};
122127

123128
load_and_switch_to_kernel(kernel, frame_allocator, page_tables, system_info);

common/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ pub struct SystemInfo {
4949
pub framebuffer: Option<RawFrameBufferInfo>,
5050
/// Address of the _Root System Description Pointer_ structure of the ACPI standard.
5151
pub rsdp_addr: Option<PhysAddr>,
52+
pub ramdisk_addr: Option<u64>,
53+
pub ramdisk_len: u64,
5254
}
5355

5456
/// The physical address of the framebuffer and information about the framebuffer.
@@ -464,6 +466,8 @@ where
464466
info.recursive_index = mappings.recursive_index.map(Into::into).into();
465467
info.rsdp_addr = system_info.rsdp_addr.map(|addr| addr.as_u64()).into();
466468
info.tls_template = mappings.tls_template.into();
469+
info.ramdisk_addr = system_info.ramdisk_addr.into();
470+
info.ramdisk_len = system_info.ramdisk_len;
467471
info
468472
});
469473

uefi/src/main.rs

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use x86_64::{
3737
mod memory_descriptor;
3838

3939
static SYSTEM_TABLE: RacyCell<Option<SystemTable<Boot>>> = RacyCell::new(None);
40+
const KERNEL_FILENAME: &str = "kernel-x86_64";
4041

4142
struct RacyCell<T>(UnsafeCell<T>);
4243

@@ -120,6 +121,8 @@ fn main_inner(image: Handle, mut st: SystemTable<Boot>) -> Status {
120121
.or_else(|| config_entries.find(|entry| matches!(entry.guid, cfg::ACPI_GUID)));
121122
rsdp.map(|entry| PhysAddr::new(entry.address as u64))
122123
},
124+
ramdisk_addr: None,
125+
ramdisk_len: 0
123126
};
124127

125128
bootloader_x86_64_common::load_and_switch_to_kernel(
@@ -141,7 +144,7 @@ fn load_kernel_file(image: Handle, st: &SystemTable<Boot>) -> Option<&'static mu
141144
.or_else(|| load_kernel_file_from_tftp_boot_server(image, st))
142145
}
143146

144-
fn load_kernel_file_from_disk(image: Handle, st: &SystemTable<Boot>) -> Option<&'static mut [u8]> {
147+
fn load_file_from_disk(name: &str, image: Handle, st: &SystemTable<Boot>) -> Option<&'static mut [u8]>{
145148
let file_system_raw = {
146149
let this = st.boot_services();
147150
let loaded_image = this
@@ -187,33 +190,46 @@ fn load_kernel_file_from_disk(image: Handle, st: &SystemTable<Boot>) -> Option<&
187190
let file_system = unsafe { &mut *file_system_raw.interface.get() };
188191

189192
let mut root = file_system.open_volume().unwrap();
190-
let mut buf = [0; 14 * 2];
191-
let filename = CStr16::from_str_with_buf("kernel-x86_64", &mut buf).unwrap();
192-
let kernel_file_handle = root
193-
.open(filename, FileMode::Read, FileAttribute::empty())
194-
.expect("Failed to load kernel (expected file named `kernel-x86_64`)");
195-
let mut kernel_file = match kernel_file_handle.into_type().unwrap() {
193+
if(name.len() > 255) {
194+
panic!("File name {}, exceeds maximum length!", name);
195+
}
196+
let mut buf = [0; 512];
197+
let filename = CStr16::from_str_with_buf(name, &mut buf).unwrap();
198+
let kernel_file_handle_result = root
199+
.open(filename, FileMode::Read, FileAttribute::empty());
200+
201+
if kernel_file_handle_result.is_err() {
202+
return None;
203+
}
204+
205+
let file_handle = kernel_file_handle_result.unwrap();
206+
207+
let mut file = match file_handle.into_type().unwrap() {
196208
uefi::proto::media::file::FileType::Regular(f) => f,
197209
uefi::proto::media::file::FileType::Dir(_) => panic!(),
198210
};
199211

200212
let mut buf = [0; 500];
201-
let kernel_info: &mut FileInfo = kernel_file.get_info(&mut buf).unwrap();
202-
let kernel_size = usize::try_from(kernel_info.file_size()).unwrap();
213+
let file_info: &mut FileInfo = file.get_info(&mut buf).unwrap();
214+
let file_size = usize::try_from(file_info.file_size()).unwrap();
203215

204-
let kernel_ptr = st
216+
let file_ptr = st
205217
.boot_services()
206218
.allocate_pages(
207219
AllocateType::AnyPages,
208220
MemoryType::LOADER_DATA,
209-
((kernel_size - 1) / 4096) + 1,
221+
((file_size - 1) / 4096) + 1,
210222
)
211223
.unwrap() as *mut u8;
212-
unsafe { ptr::write_bytes(kernel_ptr, 0, kernel_size) };
213-
let kernel_slice = unsafe { slice::from_raw_parts_mut(kernel_ptr, kernel_size) };
214-
kernel_file.read(kernel_slice).unwrap();
224+
unsafe { ptr::write_bytes(file_ptr, 0, file_size) };
225+
let file_slice = unsafe { slice::from_raw_parts_mut(file_ptr, file_size) };
226+
file.read(file_slice).unwrap();
215227

216-
Some(kernel_slice)
228+
Some(file_slice)
229+
}
230+
231+
fn load_kernel_file_from_disk(image: Handle, st: &SystemTable<Boot>) -> Option<&'static mut [u8]> {
232+
Some(load_file_from_disk(KERNEL_FILENAME, image, st).expect("Failed to load kernel (expected file named `kernel-x86_64`)"))
217233
}
218234

219235
/// Try to load a kernel from a TFTP boot server.

0 commit comments

Comments
 (0)