limine_protocol_for_rust/
lib.rs1#![no_std]
49
50mod util;
51
52use crate::util::null_terminated_string;
53use core::mem::MaybeUninit;
54use core::slice::from_raw_parts;
55
56pub const REQUEST_START_MARKER: [u64; 4] = [ 0xf6b8f4b39de7d1ae, 0xfab91a6940fcb9cf, 0x785c6ed015d3e316, 0x181e920a7852b9d9 ];
57pub const REQUEST_END_MARKER: [u64; 2] = [ 0xadc0e0531bb10d03, 0x9572709f31764c62 ];
58
59
60pub const fn use_base_revision(revision: u64) -> [u64; 4]{
62 [ 0xf9562b2d5c95a6c8, 0x6a7b384944536bdc, revision, 0 ]
63}
64
65#[repr(C, align(8))]
66struct LimineReqId {
67 common_magic: [u64; 2],
68 other: [u64; 2]
69}
70
71impl LimineReqId {
72 const fn new(other: [u64; 2]) -> Self {
73 Self {
74 common_magic: [0xc7b1dd30df4c8b88, 0x0a82e883a194f07b],
75 other
76 }
77 }
78}
79
80macro_rules! gen_get_response {
81 ($get:ty) => {
82 pub fn get_response(&self) -> Option<&$get> {
83 unsafe {
84 if self.resp.assume_init() == 0 {
85 return None
86 }
87 (self.resp.assume_init() as *const $get).as_ref()
88 }
89 }
90 };
91}
92
93
94#[repr(C, align(8))]
95pub struct MemoryMapRequest {
96 id: LimineReqId,
97 revision: u64,
98 resp: MaybeUninit<usize>
99}
100
101impl MemoryMapRequest {
102 pub const fn new(revision: u64) -> Self {
103 Self {
104 id: LimineReqId::new([0x67cf3d9d378a806f, 0xe304acdfc50c3c62]),
105 revision,
106 resp: MaybeUninit::uninit()
107 }
108 }
109
110 gen_get_response!(MemoryMapResponse);
111}
112
113
114#[repr(C, align(8))]
115pub struct MemoryMapResponse {
116 revision: u64,
117 entry_count: u64,
118 entries: *const *const MemoryMapEntry
119}
120
121impl MemoryMapResponse {
122 fn get_entries(&self) -> &[*const MemoryMapEntry] {
123 unsafe {
124 from_raw_parts(self.entries, self.entry_count as usize)
125 }
126 }
127
128 pub fn get_entry(&self, entry: usize) -> Option<&MemoryMapEntry> {
129 if (0..self.entry_count).contains(&(entry as u64)) {
130 unsafe {
131 self.get_entries()[entry].as_ref()
132 }
133 } else {
134 None
135 }
136 }
137}
138
139#[repr(C, align(8))]
140pub struct MemoryMapEntry {
141 base: u64,
142 length: u64,
143 memmap_type: u64
144}
145
146impl MemoryMapEntry {
147 pub fn type_as_enum(&self) -> MemoryMapType {
148 match self.memmap_type {
149 0 => MemoryMapType::Usable,
150 1 => MemoryMapType::Reserved,
151 2 => MemoryMapType::AcpiReclaimable,
152 3 => MemoryMapType::AcpiNvs,
153 4 => MemoryMapType::BadMemory,
154 5 => MemoryMapType::BootloaderReclaimable,
155 6 => MemoryMapType::ExecutableAndModules,
156 7 => MemoryMapType::Framebuffer,
157 8 => MemoryMapType::AcpiTables,
158 _ => panic!("Obtained invalid MemoryMap Type")
159 }
160 }
161}
162
163pub enum MemoryMapType {
164 Usable,
165 Reserved,
166 AcpiReclaimable,
167 AcpiNvs,
168 BadMemory,
169 BootloaderReclaimable,
170 ExecutableAndModules,
171 Framebuffer,
172 AcpiTables
173}
174
175#[repr(C, align(8))]
176pub struct FramebufferRequest {
177 id: LimineReqId,
178 revision: u64,
179 resp: MaybeUninit<usize>
180}
181
182impl FramebufferRequest {
183 pub const fn new(revision: u64) -> Self {
184 Self {
185 id: LimineReqId::new([0x9d5827dcd881dd75, 0xa3148604f6fab11b]),
186 revision,
187 resp: MaybeUninit::uninit()
188 }
189 }
190
191 gen_get_response!(FramebufferResponse);
192}
193
194
195#[repr(C, align(8))]
196pub struct FramebufferResponse {
197 revision: u64,
198 entry_count: u64,
199 entries: *const *const Framebuffer
200}
201
202impl FramebufferResponse {
203 fn get_framebuffers(&self) -> &[*const Framebuffer] {
204 unsafe {
205 from_raw_parts(self.entries, self.entry_count as usize)
206 }
207 }
208
209 pub fn get_framebuffer(&self, index: usize) -> Option<&Framebuffer> {
210 if (0..self.entry_count).contains(&(index as u64)) {
211 unsafe {
212 self.get_framebuffers()[index].as_ref()
213 }
214 } else {
215 None
216 }
217 }
218}
219
220#[repr(C, align(8))]
221#[derive(Debug)]
222pub struct Framebuffer {
223 pub address: usize,
224 pub width: u64,
225 pub height: u64,
226 pub pitch: u64,
227 pub bpp: u16,
228 pub memory_model: u8,
229 pub red_mask_size: u8,
230 pub red_mask_shift: u8,
231 pub green_mask_size: u8,
232 pub green_mask_shift: u8,
233 pub blue_mask_size: u8,
234 pub blue_mask_shift: u8,
235 _unused: [u8; 7],
236 pub edid_size: u64,
237 pub edid_address: usize,
238
239 pub mode_count: u64,
241 modes: *const *const VideoMode
242}
243
244impl Framebuffer {
245 fn get_modes(&self) -> &[*const VideoMode] {
246 unsafe {
247 from_raw_parts(self.modes, self.mode_count as usize)
248 }
249 }
250
251 pub fn get_mode(&self, mode: usize) -> Option<&VideoMode> {
252 if (0..self.mode_count).contains(&(mode as u64)) {
253 unsafe {
254 self.get_modes()[mode].as_ref()
255 }
256 } else {
257 None
258 }
259 }
260}
261
262#[repr(C, align(8))]
263pub struct VideoMode {
264 pitch: u64,
265 width: u64,
266 height: u64,
267 bpp: u16,
268 memory_model: u8,
269 red_mask_size: u8,
270 red_mask_shift: u8,
271 green_mask_size: u8,
272 green_mask_shift: u8,
273 blue_mask_size: u8,
274 blue_mask_shift: u8,
275}
276
277#[repr(C, align(8))]
278pub struct BootloaderInfoRequest{
279 id: LimineReqId,
280 revision: u64,
281 resp: MaybeUninit<usize>
282}
283
284impl BootloaderInfoRequest {
285 pub const fn new(revision: u64) -> Self {
286 Self {
287 id: LimineReqId::new([0xf55038d8e2a1202f, 0x279426fcf5f59740]),
288 revision,
289 resp: MaybeUninit::uninit()
290 }
291 }
292
293 gen_get_response!(BootloaderInfoResponse);
294}
295
296#[repr(C, align(8))]
297pub struct BootloaderInfoResponse {
298 revision: u64,
299 name: *const u8,
300 version: *const u8
301}
302
303impl BootloaderInfoResponse {
304 pub fn get_name(&self) -> &str {
305 null_terminated_string(self.name).unwrap()
306 }
307
308 pub fn get_version(&self) -> &str {
309 null_terminated_string(self.version).unwrap()
310 }
311}
312