Skip to content

Commit

Permalink
Add ramdisk support
Browse files Browse the repository at this point in the history
This adds support for loading a ramdisk/initrd, and an API to add one to the boot image.
  • Loading branch information
jasoncouture committed Jan 9, 2023
1 parent 94c71d5 commit 3262d16
Show file tree
Hide file tree
Showing 26 changed files with 586 additions and 196 deletions.
18 changes: 14 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ members = [
"tests/test_kernels/higher_half",
"tests/test_kernels/pie",
"tests/test_kernels/lto",
"tests/test_kernels/ramdisk"
]
exclude = ["examples/basic", "examples/test_framework"]

Expand Down Expand Up @@ -50,6 +51,7 @@ test_kernel_default_settings = { path = "tests/test_kernels/default_settings", a
test_kernel_higher_half = { path = "tests/test_kernels/higher_half", artifact = "bin", target = "x86_64-unknown-none" }
test_kernel_map_phys_mem = { path = "tests/test_kernels/map_phys_mem", artifact = "bin", target = "x86_64-unknown-none" }
test_kernel_pie = { path = "tests/test_kernels/pie", artifact = "bin", target = "x86_64-unknown-none" }
test_kernel_ramdisk = { path = "tests/test_kernels/ramdisk", artifact = "bin", target = "x86_64-unknown-none" }

[profile.dev]
panic = "abort"
Expand Down
7 changes: 4 additions & 3 deletions api/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ fn main() {
(88, 9),
(97, 9),
(106, 9),
(115, 1),
(116, 1),
(117, 1),
(115, 9),
(124, 1),
(125, 1),
(126, 1),
];

let mut code = String::new();
Expand Down
22 changes: 16 additions & 6 deletions api/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl BootloaderConfig {
0x3D,
];
#[doc(hidden)]
pub const SERIALIZED_LEN: usize = 118;
pub const SERIALIZED_LEN: usize = 127;

/// Creates a new default configuration with the following values:
///
Expand Down Expand Up @@ -97,6 +97,7 @@ impl BootloaderConfig {
aslr,
dynamic_range_start,
dynamic_range_end,
ramdisk_memory,
} = mappings;
let FrameBuffer {
minimum_framebuffer_height,
Expand Down Expand Up @@ -145,28 +146,30 @@ impl BootloaderConfig {
},
);

let buf = concat_97_9(
let buf = concat_97_9(buf, ramdisk_memory.serialize());

let buf = concat_106_9(
buf,
match minimum_framebuffer_height {
Option::None => [0; 9],
Option::Some(addr) => concat_1_8([1], addr.to_le_bytes()),
},
);

let buf = concat_106_9(
let buf = concat_115_9(
buf,
match minimum_framebuffer_width {
Option::None => [0; 9],
Option::Some(addr) => concat_1_8([1], addr.to_le_bytes()),
},
);

let log_level = concat_115_1(buf, (*log_level as u8).to_le_bytes());
let log_level = concat_124_1(buf, (*log_level as u8).to_le_bytes());

let frame_buffer_logger_status =
concat_116_1(log_level, (*frame_buffer_logger_status as u8).to_le_bytes());
concat_125_1(log_level, (*frame_buffer_logger_status as u8).to_le_bytes());

concat_117_1(
concat_126_1(
frame_buffer_logger_status,
(*serial_logger_status as u8).to_le_bytes(),
)
Expand Down Expand Up @@ -227,6 +230,7 @@ impl BootloaderConfig {
let (&dynamic_range_start, s) = split_array_ref(s);
let (&dynamic_range_end_some, s) = split_array_ref(s);
let (&dynamic_range_end, s) = split_array_ref(s);
let (&ramdisk_memory, s) = split_array_ref(s);

let mappings = Mappings {
kernel_stack: Mapping::deserialize(&kernel_stack)?,
Expand Down Expand Up @@ -257,6 +261,7 @@ impl BootloaderConfig {
[1] => Option::Some(u64::from_le_bytes(dynamic_range_end)),
_ => return Err("invalid dynamic range end value"),
},
ramdisk_memory: Mapping::deserialize(&ramdisk_memory)?,
};
(mappings, s)
};
Expand Down Expand Up @@ -439,6 +444,9 @@ pub struct Mappings {
///
/// Defaults to `0xffff_ffff_ffff_f000`.
pub dynamic_range_end: Option<u64>,
/// Virtual address to map ramdisk image, if present on disk
/// Defaults to dynamic
pub ramdisk_memory: Mapping,
}

impl Mappings {
Expand All @@ -455,6 +463,7 @@ impl Mappings {
aslr: false,
dynamic_range_start: None,
dynamic_range_end: None,
ramdisk_memory: Mapping::new_default(),
}
}

Expand Down Expand Up @@ -487,6 +496,7 @@ impl Mappings {
} else {
Option::None
},
ramdisk_memory: Mapping::random(),
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions api/src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ pub struct BootInfo {
pub rsdp_addr: Optional<u64>,
/// The thread local storage (TLS) template of the kernel executable, if present.
pub tls_template: Optional<TlsTemplate>,
/// Ramdisk address, if loaded
pub ramdisk_addr: Optional<u64>,
/// Ramdisk image size, set to 0 if addr is None
pub ramdisk_len: u64,
}

impl BootInfo {
Expand All @@ -67,6 +71,8 @@ impl BootInfo {
recursive_index: Optional::None,
rsdp_addr: Optional::None,
tls_template: Optional::None,
ramdisk_addr: Optional::None,
ramdisk_len: 0,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions bios/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub mod racy_cell;
pub struct BiosInfo {
pub stage_4: Region,
pub kernel: Region,
pub ramdisk: Region,
pub framebuffer: BiosFramebufferInfo,
pub memory_map_addr: u32,
pub memory_map_len: u16,
Expand Down
37 changes: 31 additions & 6 deletions bios/stage-2/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const BOOTLOADER_SECOND_STAGE_PARTITION_TYPE: u8 = 0x20;
const STAGE_3_DST: *mut u8 = 0x0010_0000 as *mut u8; // 1MiB (typically 14MiB accessible here)
const STAGE_4_DST: *mut u8 = 0x0020_0000 as *mut u8; // 2MiB (typically still 13MiB accessible here)
const KERNEL_DST: *mut u8 = 0x0100_0000 as *mut u8; // 16MiB
const RAMDISK_DST: *mut u8 = 0x0400_0000 as *mut u8; // 64MiB

static mut DISK_BUFFER: AlignedArrayBuffer<0x4000> = AlignedArrayBuffer {
buffer: [0; 0x4000],
Expand Down Expand Up @@ -98,6 +99,17 @@ fn start(disk_number: u16, partition_table_start: *const u8) -> ! {
writeln!(screen::Writer, "loading kernel...").unwrap();
let kernel_len = load_file("kernel-x86_64", KERNEL_DST, &mut fs, &mut disk, disk_buffer);
writeln!(screen::Writer, "kernel loaded at {KERNEL_DST:#p}").unwrap();
writeln!(screen::Writer, "Loading ramdisk...").unwrap();
let ramdisk_len = match try_load_file("ramdisk", RAMDISK_DST, &mut fs, &mut disk, disk_buffer) {
Some(s) => s,
None => 0u64,
};

if ramdisk_len == 0 {
writeln!(screen::Writer, "No ramdisk found, skipping.").unwrap();
} else {
writeln!(screen::Writer, "Loaded ramdisk at {RAMDISK_DST:#p}").unwrap();
}

let memory_map = unsafe { memory_map::query_memory_map() }.unwrap();
writeln!(screen::Writer, "{memory_map:x?}").unwrap();
Expand Down Expand Up @@ -129,6 +141,10 @@ fn start(disk_number: u16, partition_table_start: *const u8) -> ! {
start: KERNEL_DST as u64,
len: kernel_len,
},
ramdisk: Region {
start: RAMDISK_DST as u64,
len: ramdisk_len,
},
memory_map_addr: memory_map.as_mut_ptr() as u32,
memory_map_len: memory_map.len().try_into().unwrap(),
framebuffer: BiosFramebufferInfo {
Expand All @@ -151,17 +167,16 @@ fn start(disk_number: u16, partition_table_start: *const u8) -> ! {
}
}

fn load_file(
fn try_load_file(
file_name: &str,
dst: *mut u8,
fs: &mut fat::FileSystem<disk::DiskAccess>,
disk: &mut disk::DiskAccess,
disk_buffer: &mut AlignedArrayBuffer<16384>,
) -> u64 {
) -> Option<u64> {
let disk_buffer_size = disk_buffer.buffer.len();
let file = fs
.find_file_in_root_dir(file_name, disk_buffer)
.expect("file not found");
let file = fs.find_file_in_root_dir(file_name, disk_buffer)?;

let file_size = file.file_size().into();

let mut total_offset = 0;
Expand Down Expand Up @@ -195,7 +210,17 @@ fn load_file(
total_offset += usize::try_from(len).unwrap();
}
}
file_size
Some(file_size)
}

fn load_file(
file_name: &str,
dst: *mut u8,
fs: &mut fat::FileSystem<disk::DiskAccess>,
disk: &mut disk::DiskAccess,
disk_buffer: &mut AlignedArrayBuffer<16384>,
) -> u64 {
try_load_file(file_name, dst, fs, disk, disk_buffer).expect("file not found")
}

/// Taken from https://github.com/rust-lang/rust/blob/e100ec5bc7cd768ec17d75448b29c9ab4a39272b/library/core/src/slice/mod.rs#L1673-L1677
Expand Down
15 changes: 14 additions & 1 deletion bios/stage-4/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,21 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! {
PhysAddr::new(info.kernel.start)
};
let kernel_size = info.kernel.len;
let mut frame_allocator = {
let mut frame_allocator = if info.ramdisk.start == 0 {
let kernel_end = PhysFrame::containing_address(kernel_start + kernel_size - 1u64);
let next_free = kernel_end + 1;
LegacyFrameAllocator::new_starting_at(
next_free,
memory_map.iter().copied().map(MemoryRegion),
)
} else {
let ramdisk_end =
PhysFrame::containing_address(PhysAddr::new(info.ramdisk.start + info.ramdisk.len));
let next_free = ramdisk_end + 1;
LegacyFrameAllocator::new_starting_at(
next_free,
memory_map.iter().copied().map(MemoryRegion),
)
};

// We identity-mapped all memory, so the offset between physical and virtual addresses is 0
Expand Down Expand Up @@ -126,6 +134,11 @@ pub extern "C" fn _start(info: &mut BiosInfo) -> ! {
info: framebuffer_info,
}),
rsdp_addr: detect_rsdp(),
ramdisk_addr: match info.ramdisk.len {
0 => None,
_ => Some(info.ramdisk.start),
},
ramdisk_len: info.ramdisk.len,
};

load_and_switch_to_kernel(kernel, frame_allocator, page_tables, system_info);
Expand Down
Loading

0 comments on commit 3262d16

Please sign in to comment.