1#![no_std]
2
3use core::{mem, ptr};
4
5pub use self::cb64::Cb64;
6pub use self::cmos::{Cmos, CmosEntry, CmosEnum, CmosRecord};
7pub use self::forward::Forward;
8pub use self::framebuffer::Framebuffer;
9pub use self::header::Header;
10pub use self::mapper::{Mapper, PhysicalAddress, VirtualAddress};
11pub use self::memory::{Memory, MemoryRange, MemoryRangeKind};
12pub use self::record::{Record, RecordKind};
13pub use self::serial::Serial;
14
15mod cb64;
16mod cmos;
17mod forward;
18mod framebuffer;
19mod header;
20mod mapper;
21mod memory;
22mod record;
23mod serial;
24
25#[derive(Debug)]
26pub enum Table<'a> {
27 Cmos(&'a Cmos),
28 Framebuffer(&'a Framebuffer),
29 Memory(&'a Memory),
30 Serial(&'a Serial),
31 Other(&'a Record),
32}
33
34pub fn tables<F: FnMut(Table) -> Result<(), &'static str>, M: Mapper>(callback: F, mapper: &mut M) -> Result<(), &'static str> {
35 let mut env = Env {
36 callback,
37 mapper
38 };
39 env.tables()
40}
41
42struct Env<'m, F: FnMut(Table) -> Result<(), &'static str>, M: Mapper> {
43 callback: F,
44 mapper: &'m mut M,
45}
46
47impl<'m, F: FnMut(Table) -> Result<(), &'static str>, M: Mapper> Env<'m, F, M> {
48 fn forward(&mut self, forward: &Forward) -> Result<(), &'static str> {
49 let page_size = self.mapper.page_size();
50
51 let header_physical = PhysicalAddress(forward.forward as usize);
52 let header_address = unsafe { self.mapper.map(header_physical, page_size)? };
53
54 let header = unsafe { ptr::read((header_address.0) as *const Header) };
55
56 unsafe { self.mapper.unmap(header_address)? };
57
58 if header.is_valid() {
59 self.header(header, PhysicalAddress(header_physical.0))
60 } else {
61 Err("Forward header invalid")
62 }
63 }
64
65 fn header(&mut self, header: Header, header_physical: PhysicalAddress) -> Result<(), &'static str> {
66 let mut result = Ok(());
67
68 let table_physical = PhysicalAddress(header_physical.0 + header.header_bytes as usize);
69 let table_size = header.table_bytes as usize;
70 let table_address = unsafe { self.mapper.map(table_physical, table_size)? };
71 let table_entries = header.table_entries as usize;
72 {
73 let mut i = 0;
74 let mut entries = 0;
75 while i + mem::size_of::<Record>() <= table_size && entries < table_entries {
76 let record_address = table_address.0 + i;
77 let record = unsafe { &*(record_address as *const Record) };
78
79 result = match record.kind {
80 RecordKind::CmosOptionTable => {
81 (self.callback)(Table::Cmos(
82 unsafe { &*(record_address as *const Cmos) }
83 ))
84 },
85 RecordKind::Forward => {
86 let forward = unsafe { &*(record_address as *const Forward) };
87 self.forward(forward)
88 },
89 RecordKind::Framebuffer => (self.callback)(Table::Framebuffer(
90 unsafe { &*(record_address as *const Framebuffer) }
91 )),
92 RecordKind::Memory => (self.callback)(Table::Memory(
93 unsafe { &*(record_address as *const Memory) }
94 )),
95 RecordKind::Serial => (self.callback)(Table::Serial (
96 unsafe { &*(record_address as *const Serial) }
97 )),
98 _ => (self.callback)(Table::Other(record)),
99 };
100
101 if ! result.is_ok() {
102 break;
103 }
104
105 i += record.size as usize;
106 entries += 1;
107 }
108 }
109
110 unsafe { self.mapper.unmap(table_address)? };
111
112 return result;
113 }
114
115 pub fn tables(&mut self) -> Result<(), &'static str> {
116 let page_size = self.mapper.page_size();
117
118 let low_memory = 1024 * 1024;
120 for header_page in 0..(low_memory / page_size) {
121 let header_physical = PhysicalAddress(header_page * page_size);
122 let header_address = unsafe { self.mapper.map(header_physical, page_size)? };
123
124 {
125 let mut i = 0;
126 while i + mem::size_of::<Header>() <= page_size {
127 let header = unsafe { ptr::read((header_address.0 + i) as *const Header) };
128
129 if header.is_valid() {
130 unsafe { self.mapper.unmap(header_address)? };
131
132 return self.header(header, PhysicalAddress(header_physical.0 + i));
133 }
134
135 i += 4;
136 }
137 }
138
139 unsafe { self.mapper.unmap(header_address)? };
140 }
141
142 Err("Header not found")
144 }
145}