|
| 1 | +use core::mem; |
| 2 | + |
| 3 | +use crate::common; |
| 4 | + |
| 5 | +// Common data needed for all boot paths |
| 6 | +pub trait Info { |
| 7 | + // Starting address of the Root System Descriptor Pointer |
| 8 | + fn rsdp_addr(&self) -> u64; |
| 9 | + // The kernel command line (not including null terminator) |
| 10 | + fn cmdline(&self) -> &[u8]; |
| 11 | + // Methods to access the E820 Memory map |
| 12 | + fn num_entries(&self) -> u8; |
| 13 | + fn entry(&self, idx: u8) -> E820Entry; |
| 14 | +} |
| 15 | + |
| 16 | +#[derive(Clone, Copy, Debug)] |
| 17 | +#[repr(C, packed)] |
| 18 | +pub struct E820Entry { |
| 19 | + pub addr: u64, |
| 20 | + pub size: u64, |
| 21 | + pub entry_type: u32, |
| 22 | +} |
| 23 | + |
| 24 | +impl E820Entry { |
| 25 | + pub const RAM_TYPE: u32 = 1; |
| 26 | +} |
| 27 | + |
| 28 | +// The so-called "zeropage" |
| 29 | +#[derive(Clone, Copy)] |
| 30 | +#[repr(C, packed)] |
| 31 | +pub struct Params { |
| 32 | + screen_info: ScreenInfo, // 0x000 |
| 33 | + apm_bios_info: ApmBiosInfo, // 0x040 |
| 34 | + _pad2: [u8; 4], // 0x054 |
| 35 | + tboot_addr: u64, // 0x058 |
| 36 | + ist_info: IstInfo, // 0x060 |
| 37 | + pub acpi_rsdp_addr: u64, // 0x070 |
| 38 | + _pad3: [u8; 8], // 0x078 |
| 39 | + hd0_info: HdInfo, // 0x080 - obsolete |
| 40 | + hd1_info: HdInfo, // 0x090 - obsolete |
| 41 | + sys_desc_table: SysDescTable, // 0x0a0 - obsolete |
| 42 | + olpc_ofw_header: OlpcOfwHeader, // 0x0b0 |
| 43 | + ext_ramdisk_image: u32, // 0x0c0 |
| 44 | + ext_ramdisk_size: u32, // 0x0c4 |
| 45 | + ext_cmd_line_ptr: u32, // 0x0c8 |
| 46 | + _pad4: [u8; 0x74], // 0x0cc |
| 47 | + edd_info: EdidInfo, // 0x140 |
| 48 | + efi_info: EfiInfo, // 0x1c0 |
| 49 | + alt_mem_k: u32, // 0x1e0 |
| 50 | + scratch: u32, // 0x1e4 |
| 51 | + e820_entries: u8, // 0x1e8 |
| 52 | + eddbuf_entries: u8, // 0x1e9 |
| 53 | + edd_mbr_sig_buf_entries: u8, // 0x1ea |
| 54 | + kbd_status: u8, // 0x1eb |
| 55 | + secure_boot: u8, // 0x1ec |
| 56 | + _pad5: [u8; 2], // 0x1ed |
| 57 | + sentinel: u8, // 0x1ef |
| 58 | + _pad6: [u8; 1], // 0x1f0 |
| 59 | + pub hdr: Header, // 0x1f1 |
| 60 | + _pad7: [u8; 0x290 - HEADER_END], |
| 61 | + edd_mbr_sig_buffer: [u32; 16], // 0x290 |
| 62 | + e820_table: [E820Entry; 128], // 0x2d0 |
| 63 | + _pad8: [u8; 0x30], // 0xcd0 |
| 64 | + eddbuf: [EddInfo; 6], // 0xd00 |
| 65 | + _pad9: [u8; 0x114], // 0xeec |
| 66 | +} |
| 67 | + |
| 68 | +impl Default for Params { |
| 69 | + fn default() -> Self { |
| 70 | + // SAFETY: Struct consists entirely of primitive integral types. |
| 71 | + unsafe { mem::zeroed() } |
| 72 | + } |
| 73 | +} |
| 74 | + |
| 75 | +impl Params { |
| 76 | + pub fn set_entries(&mut self, info: &dyn Info) { |
| 77 | + self.e820_entries = info.num_entries(); |
| 78 | + for i in 0..self.e820_entries { |
| 79 | + self.e820_table[i as usize] = info.entry(i); |
| 80 | + } |
| 81 | + } |
| 82 | +} |
| 83 | + |
| 84 | +impl Info for Params { |
| 85 | + fn rsdp_addr(&self) -> u64 { |
| 86 | + self.acpi_rsdp_addr |
| 87 | + } |
| 88 | + fn cmdline(&self) -> &[u8] { |
| 89 | + unsafe { common::from_cstring(self.hdr.cmd_line_ptr as u64) } |
| 90 | + } |
| 91 | + fn num_entries(&self) -> u8 { |
| 92 | + self.e820_entries |
| 93 | + } |
| 94 | + fn entry(&self, idx: u8) -> E820Entry { |
| 95 | + assert!(idx < self.num_entries()); |
| 96 | + self.e820_table[idx as usize] |
| 97 | + } |
| 98 | +} |
| 99 | + |
| 100 | +const HEADER_START: usize = 0x1f1; |
| 101 | +const HEADER_END: usize = HEADER_START + mem::size_of::<Header>(); |
| 102 | + |
| 103 | +#[derive(Clone, Copy, Debug)] |
| 104 | +#[repr(C, packed)] |
| 105 | +pub struct Header { |
| 106 | + pub setup_sects: u8, |
| 107 | + pub root_flags: u16, |
| 108 | + pub syssize: u32, |
| 109 | + pub ram_size: u16, |
| 110 | + pub vid_mode: u16, |
| 111 | + pub root_dev: u16, |
| 112 | + pub boot_flag: u16, |
| 113 | + pub jump: u16, |
| 114 | + pub header: [u8; 4], |
| 115 | + pub version: u16, |
| 116 | + pub realmode_swtch: u32, |
| 117 | + pub start_sys_seg: u16, |
| 118 | + pub kernel_version: u16, |
| 119 | + pub type_of_loader: u8, |
| 120 | + pub loadflags: u8, |
| 121 | + pub setup_move_size: u16, |
| 122 | + pub code32_start: u32, |
| 123 | + pub ramdisk_image: u32, |
| 124 | + pub ramdisk_size: u32, |
| 125 | + pub bootsect_kludge: u32, |
| 126 | + pub heap_end_ptr: u16, |
| 127 | + pub ext_loader_ver: u8, |
| 128 | + pub ext_loader_type: u8, |
| 129 | + pub cmd_line_ptr: u32, |
| 130 | + pub initrd_addr_max: u32, |
| 131 | + pub kernel_alignment: u32, |
| 132 | + pub relocatable_kernel: u8, |
| 133 | + pub min_alignment: u8, |
| 134 | + pub xloadflags: u16, |
| 135 | + pub cmdline_size: u32, |
| 136 | + pub hardware_subarch: u32, |
| 137 | + pub hardware_subarch_data: u64, |
| 138 | + pub payload_offset: u32, |
| 139 | + pub payload_length: u32, |
| 140 | + pub setup_data: u64, |
| 141 | + pub pref_address: u64, |
| 142 | + pub init_size: u32, |
| 143 | + pub handover_offset: u32, |
| 144 | +} |
| 145 | + |
| 146 | +// Right now the stucts below are unused, so we only need them to be the correct |
| 147 | +// size. Update test_size_and_offset if a struct's real definition is added. |
| 148 | +#[derive(Clone, Copy)] |
| 149 | +#[repr(C, packed)] |
| 150 | +struct ScreenInfo([u8; 0x40]); |
| 151 | +#[derive(Clone, Copy)] |
| 152 | +#[repr(C, packed)] |
| 153 | +struct ApmBiosInfo([u8; 0x14]); |
| 154 | +#[derive(Clone, Copy)] |
| 155 | +#[repr(C, packed)] |
| 156 | +struct IstInfo([u8; 0x10]); |
| 157 | +#[derive(Clone, Copy)] |
| 158 | +#[repr(C, packed)] |
| 159 | +struct HdInfo([u8; 0x10]); |
| 160 | +#[derive(Clone, Copy)] |
| 161 | +#[repr(C, packed)] |
| 162 | +struct SysDescTable([u8; 0x10]); |
| 163 | +#[derive(Clone, Copy)] |
| 164 | +#[repr(C, packed)] |
| 165 | +struct OlpcOfwHeader([u8; 0x10]); |
| 166 | +#[derive(Clone, Copy)] |
| 167 | +#[repr(C, packed)] |
| 168 | +struct EdidInfo([u8; 0x80]); |
| 169 | +#[derive(Clone, Copy)] |
| 170 | +#[repr(C, packed)] |
| 171 | +struct EfiInfo([u8; 0x20]); |
| 172 | +#[derive(Clone, Copy)] |
| 173 | +#[repr(C, packed)] |
| 174 | +struct EddInfo([u8; 0x52]); |
| 175 | + |
| 176 | +#[cfg(test)] |
| 177 | +mod tests { |
| 178 | + use super::*; |
| 179 | + #[test] |
| 180 | + fn test_size_and_offset() { |
| 181 | + assert_eq!(mem::size_of::<Header>(), 119); |
| 182 | + assert_eq!(mem::size_of::<E820Entry>(), 20); |
| 183 | + assert_eq!(mem::size_of::<Params>(), 4096); |
| 184 | + |
| 185 | + assert_eq!(offset_of!(Params, hdr), HEADER_START); |
| 186 | + } |
| 187 | +} |
0 commit comments