1#![allow(clippy::useless_conversion)]
9
10use core::mem;
11use core::ops::{Deref, Range};
12use core::slice;
13
14use sel4_config::sel4_cfg;
15
16use crate::{cap_type, init_thread::SlotRegion, newtype_methods, sys, FrameObjectType, IpcBuffer};
17
18#[repr(transparent)]
22#[derive(Debug)]
23pub struct BootInfoPtr {
24 ptr: *const BootInfo,
25}
26
27impl BootInfoPtr {
28 #[allow(clippy::missing_safety_doc)]
29 pub unsafe fn new(ptr: *const BootInfo) -> Self {
30 assert_eq!(
31 ptr.cast::<()>()
32 .align_offset(FrameObjectType::GRANULE.bytes()),
33 0
34 ); Self { ptr }
36 }
37
38 pub fn ptr(&self) -> *const BootInfo {
39 self.ptr
40 }
41
42 fn extra_ptr(&self) -> *const u8 {
43 self.ptr
44 .cast::<u8>()
45 .wrapping_offset(Self::EXTRA_OFFSET.try_into().unwrap())
46 }
47
48 fn extra_slice(&self) -> &[u8] {
49 unsafe { slice::from_raw_parts(self.extra_ptr(), self.extra_len()) }
50 }
51
52 pub fn extra(&self) -> BootInfoExtraIter {
53 BootInfoExtraIter::new(self)
54 }
55
56 pub fn footprint_size(&self) -> usize {
57 Self::EXTRA_OFFSET + self.extra_len()
58 }
59
60 const EXTRA_OFFSET: usize = FrameObjectType::GRANULE.bytes();
61}
62
63impl Deref for BootInfoPtr {
64 type Target = BootInfo;
65
66 fn deref(&self) -> &Self::Target {
67 unsafe { self.ptr().as_ref().unwrap() }
68 }
69}
70
71#[repr(transparent)]
73#[derive(Debug)]
74pub struct BootInfo(sys::seL4_BootInfo);
75
76impl BootInfo {
77 newtype_methods!(pub sys::seL4_BootInfo);
78
79 fn extra_len(&self) -> usize {
80 self.inner().extraLen.try_into().unwrap()
81 }
82
83 pub fn ipc_buffer(&self) -> *mut IpcBuffer {
84 self.inner().ipcBuffer.cast()
85 }
86
87 pub fn empty(&self) -> SlotRegion<cap_type::Null> {
88 SlotRegion::from_sys(self.inner().empty)
89 }
90
91 pub fn user_image_frames(&self) -> SlotRegion<cap_type::Granule> {
92 SlotRegion::from_sys(self.inner().userImageFrames)
93 }
94
95 #[sel4_cfg(KERNEL_MCS)]
96 pub fn sched_control(&self) -> SlotRegion<cap_type::SchedControl> {
97 SlotRegion::from_sys(self.inner().schedcontrol)
98 }
99
100 pub fn untyped(&self) -> SlotRegion<cap_type::Untyped> {
101 SlotRegion::from_sys(self.inner().untyped)
102 }
103
104 fn untyped_list_inner(&self) -> &[sys::seL4_UntypedDesc] {
105 &self.inner().untypedList[..self.untyped().len()]
106 }
107
108 pub fn untyped_list(&self) -> &[UntypedDesc] {
109 let inner = self.untyped_list_inner();
110 unsafe { slice::from_raw_parts(inner.as_ptr().cast(), inner.len()) }
112 }
113
114 fn untyped_list_partition_point(&self) -> usize {
115 self.untyped_list().partition_point(|ut| ut.is_device())
116 }
117
118 pub fn device_untyped_range(&self) -> Range<usize> {
119 0..self.untyped_list_partition_point()
120 }
121
122 pub fn kernel_untyped_range(&self) -> Range<usize> {
123 self.untyped_list_partition_point()..self.untyped_list().len()
124 }
125}
126
127#[repr(transparent)]
129#[derive(Debug, Clone, PartialEq, Eq)]
130pub struct UntypedDesc(sys::seL4_UntypedDesc);
131
132impl UntypedDesc {
133 newtype_methods!(pub sys::seL4_UntypedDesc);
134
135 pub fn paddr(&self) -> usize {
136 self.inner().paddr.try_into().unwrap()
137 }
138
139 pub fn size_bits(&self) -> usize {
140 self.inner().sizeBits.into()
141 }
142
143 pub fn is_device(&self) -> bool {
144 self.inner().isDevice != 0
145 }
146}
147
148#[derive(Clone, Debug, PartialEq, Eq)]
150pub struct BootInfoExtra<'a> {
151 pub id: BootInfoExtraId,
152 pub content_with_header: &'a [u8],
153}
154
155impl BootInfoExtra<'_> {
156 pub fn content_with_header(&self) -> &[u8] {
157 self.content_with_header
158 }
159
160 pub fn content(&self) -> &[u8] {
161 let content_with_header = self.content_with_header();
162 &content_with_header[mem::size_of::<sys::seL4_BootInfoHeader>()..]
163 }
164}
165
166#[derive(Clone, Debug, PartialEq, Eq)]
168pub enum BootInfoExtraId {
169 Padding,
170 Fdt,
171}
172
173impl BootInfoExtraId {
174 pub fn from_sys(id: sys::seL4_BootInfoID::Type) -> Option<Self> {
175 match id {
176 sys::seL4_BootInfoID::SEL4_BOOTINFO_HEADER_PADDING => Some(BootInfoExtraId::Padding),
177 sys::seL4_BootInfoID::SEL4_BOOTINFO_HEADER_FDT => Some(BootInfoExtraId::Fdt),
178 _ => None,
179 }
180 }
181}
182
183pub struct BootInfoExtraIter<'a> {
185 bootinfo: &'a BootInfoPtr,
186 cursor: usize,
187}
188
189impl<'a> BootInfoExtraIter<'a> {
190 fn new(bootinfo: &'a BootInfoPtr) -> Self {
191 Self {
192 bootinfo,
193 cursor: 0,
194 }
195 }
196}
197
198impl<'a> Iterator for BootInfoExtraIter<'a> {
199 type Item = BootInfoExtra<'a>;
200
201 fn next(&mut self) -> Option<Self::Item> {
202 while self.cursor < self.bootinfo.extra_slice().len() {
203 let header = {
204 let mut it = self.bootinfo.extra_slice()[self.cursor..]
205 .chunks(mem::size_of::<sys::seL4_Word>());
206 let mut munch_word =
207 || sys::seL4_Word::from_ne_bytes(it.next().unwrap().try_into().unwrap());
208 let id = munch_word();
209 let len = munch_word();
210 sys::seL4_BootInfoHeader { id, len }
211 };
212 let id = BootInfoExtraId::from_sys(header.id);
213 let len = usize::try_from(header.len).unwrap();
214 let content_with_header_start = self.cursor;
215 let content_with_header_end = content_with_header_start + len;
216 self.cursor = content_with_header_end;
217 if let Some(id) = id {
218 return Some(BootInfoExtra {
219 id,
220 content_with_header: &self.bootinfo.extra_slice()
221 [content_with_header_start..content_with_header_end],
222 });
223 }
224 }
225 None
226 }
227}