1use super::Table;
5use bitfield_struct::bitfield;
6use core::mem::size_of;
7use open_enum::open_enum;
8use size_of_val;
9use static_assertions::const_assert_eq;
10use thiserror::Error;
11use zerocopy::FromBytes;
12use zerocopy::FromZeros;
13use zerocopy::Immutable;
14use zerocopy::IntoBytes;
15use zerocopy::KnownLayout;
16use zerocopy::LE;
17use zerocopy::U16;
18use zerocopy::U32;
19use zerocopy::U64;
20use zerocopy::Unaligned;
21
22#[repr(C, packed)]
23#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned)]
24pub struct Madt {
25 pub apic_addr: u32,
26 pub flags: u32,
27}
28
29impl Table for Madt {
30 const SIGNATURE: [u8; 4] = *b"APIC";
31}
32
33pub const MADT_PCAT_COMPAT: u32 = 1 << 0;
34
35open_enum! {
36 #[derive(IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned)]
37 pub enum MadtType: u8 {
38 APIC = 0x0,
39 IO_APIC = 0x1,
40 INTERRUPT_SOURCE_OVERRIDE = 0x2,
41 LOCAL_NMI_SOURCE = 0x4,
42 X2APIC = 0x9,
43 GICC = 0xb,
44 GICD = 0xc,
45 GIC_MSI_FRAME = 0xd,
46 }
47}
48
49#[repr(C, packed)]
50#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
51pub struct MadtEntryHeader {
52 pub typ: MadtType,
53 pub length: u8,
54}
55
56#[repr(C, packed)]
57#[derive(Copy, Clone, Debug, PartialEq, Eq, IntoBytes, Immutable, KnownLayout, FromBytes)]
58pub struct MadtApic {
59 pub typ: MadtType,
60 pub length: u8,
61 pub acpi_processor_uid: u8,
62 pub apic_id: u8,
63 pub flags: u32,
64}
65
66const_assert_eq!(size_of::<MadtApic>(), 8);
67
68impl MadtApic {
69 pub fn new() -> Self {
70 Self {
71 typ: MadtType::APIC,
72 length: size_of::<Self>() as u8,
73 acpi_processor_uid: 0,
74 apic_id: 0,
75 flags: 0,
76 }
77 }
78}
79
80pub const MADT_APIC_ENABLED: u32 = 1 << 0;
81pub const MADT_APIC_ONLINE_CAPABLE: u32 = 1 << 1;
82
83#[repr(C, packed)]
84#[derive(Copy, Clone, Debug, PartialEq, Eq, IntoBytes, Immutable, KnownLayout, FromBytes)]
85pub struct MadtX2Apic {
86 pub typ: MadtType,
87 pub length: u8,
88 pub reserved: u16,
89 pub x2_apic_id: u32,
90 pub flags: u32,
91 pub acpi_processor_uid: u32,
92}
93
94const_assert_eq!(size_of::<MadtX2Apic>(), 16);
95
96impl MadtX2Apic {
97 pub fn new() -> Self {
98 Self {
99 typ: MadtType::X2APIC,
100 length: size_of::<Self>() as u8,
101 reserved: 0,
102 x2_apic_id: 0,
103 flags: 0,
104 acpi_processor_uid: 0,
105 }
106 }
107}
108
109#[repr(C, packed)]
110#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
111pub struct MadtIoApic {
112 pub typ: MadtType,
113 pub length: u8,
114 pub io_apic_id: u8,
115 pub rsvd: u8,
116 pub io_apic_address: u32,
117 pub global_system_interrupt_base: u32,
118}
119
120const_assert_eq!(size_of::<MadtIoApic>(), 12);
121
122impl MadtIoApic {
123 pub fn new() -> Self {
124 Self {
125 typ: MadtType::IO_APIC,
126 length: size_of::<Self>() as u8,
127 io_apic_id: 0,
128 rsvd: 0,
129 io_apic_address: 0,
130 global_system_interrupt_base: 0,
131 }
132 }
133}
134
135#[repr(C, packed)]
136#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
137pub struct MadtInterruptSourceOverride {
138 pub typ: MadtType,
139 pub length: u8,
140 pub bus: u8,
141 pub source: u8,
142 pub gsi: u32,
143 pub flags: u16,
144}
145
146const_assert_eq!(size_of::<MadtInterruptSourceOverride>(), 10);
147
148pub enum InterruptPolarity {
149 ActiveLow,
150 ActiveHigh,
151}
152
153pub enum InterruptTriggerMode {
154 Edge,
155 Level,
156}
157
158impl MadtInterruptSourceOverride {
159 pub fn new(
160 source: u8,
161 gsi: u32,
162 polarity: Option<InterruptPolarity>,
163 trigger_mode: Option<InterruptTriggerMode>,
164 ) -> Self {
165 Self {
166 typ: MadtType::INTERRUPT_SOURCE_OVERRIDE,
167 length: size_of::<Self>() as u8,
168 bus: 0,
169 source,
170 gsi,
171 flags: match polarity {
172 None => 0,
173 Some(InterruptPolarity::ActiveHigh) => 1,
174 Some(InterruptPolarity::ActiveLow) => 3,
175 } | (match trigger_mode {
176 None => 0,
177 Some(InterruptTriggerMode::Edge) => 1,
178 Some(InterruptTriggerMode::Level) => 3,
179 } << 2),
180 }
181 }
182}
183
184#[repr(C, packed)]
186#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
187pub struct MadtLocalNmiSource {
188 pub typ: MadtType,
189 pub length: u8,
190 pub acpi_processor_uid: u8,
191 pub flags: u16,
192 pub local_apic_lint: u8,
193}
194
195const_assert_eq!(size_of::<MadtLocalNmiSource>(), 6);
196
197impl MadtLocalNmiSource {
198 pub fn new() -> Self {
199 Self {
200 typ: MadtType::LOCAL_NMI_SOURCE,
201 length: size_of::<Self>() as u8,
202 acpi_processor_uid: 1, flags: 0,
204 local_apic_lint: 1,
205 }
206 }
207}
208
209#[repr(C)]
210#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
211pub struct MadtGicd {
212 pub typ: MadtType,
213 pub length: u8,
214 pub reserved: u16,
215 pub gic_id: u32,
216 pub base_address: u64,
217 pub reserved2: u32,
218 pub gic_version: u8,
219 pub reserved3: [u8; 3],
220}
221
222const_assert_eq!(size_of::<MadtGicd>(), 24);
223
224impl MadtGicd {
225 pub fn new(gic_id: u32, base_address: u64, gic_version: u8) -> Self {
226 Self {
227 typ: MadtType::GICD,
228 length: size_of::<Self>() as u8,
229 reserved: 0,
230 gic_id,
231 base_address,
232 reserved2: 0,
233 gic_version,
234 reserved3: [0; 3],
235 }
236 }
237}
238
239#[repr(C)]
241#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
242pub struct MadtGicMsiFrame {
243 pub typ: MadtType,
244 pub length: u8,
245 pub reserved: u16,
246 pub gic_msi_frame_id: u32,
247 pub base_address: u64,
248 pub flags: u32,
249 pub spi_count: u16,
250 pub spi_base: u16,
251}
252
253const_assert_eq!(size_of::<MadtGicMsiFrame>(), 24);
254
255pub const GIC_MSI_FRAME_FLAGS_SPI_SELECT: u32 = 1 << 0;
256
257impl MadtGicMsiFrame {
258 pub fn new(gic_msi_frame_id: u32, base_address: u64, spi_base: u16, spi_count: u16) -> Self {
259 Self {
260 typ: MadtType::GIC_MSI_FRAME,
261 length: size_of::<Self>() as u8,
262 reserved: 0,
263 gic_msi_frame_id,
264 base_address,
265 flags: GIC_MSI_FRAME_FLAGS_SPI_SELECT,
266 spi_count,
267 spi_base,
268 }
269 }
270}
271
272#[repr(C)]
275#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes, Unaligned)]
276pub struct MadtGicc {
277 pub typ: MadtType,
278 pub length: u8,
279 pub reserved: [u8; 2],
280 pub cpu_interface_number: U32<LE>,
281 pub acpi_processor_uid: U32<LE>,
282 pub flags: U32<LE>,
283 pub parking_protocol_version: U32<LE>,
284 pub performance_monitoring_gsiv: U32<LE>,
285 pub parked_address: U64<LE>,
286 pub base_address: U64<LE>,
287 pub gicv: U64<LE>,
288 pub gich: U64<LE>,
289 pub vgic_maintenance_interrupt: U32<LE>,
290 pub gicr_base_address: U64<LE>,
291 pub mpidr: U64<LE>,
292 pub processor_power_efficiency_class: u8,
293 pub reserved2: u8,
294 pub spe_overflow_interrupt: U16<LE>,
295}
296
297const_assert_eq!(size_of::<MadtGicc>(), 80);
298
299impl MadtGicc {
300 pub fn new(
301 acpi_processor_uid: u32,
302 mpidr: u64,
303 gicr: u64,
304 performance_monitoring_gsiv: u32,
305 ) -> Self {
306 Self {
307 typ: MadtType::GICC,
308 length: size_of::<Self>() as u8,
309 flags: u32::from(MadtGiccFlags::new().with_enabled(true)).into(),
310 acpi_processor_uid: acpi_processor_uid.into(),
311 mpidr: mpidr.into(),
312 gicr_base_address: gicr.into(),
313 performance_monitoring_gsiv: performance_monitoring_gsiv.into(),
314 ..Self::new_zeroed()
315 }
316 }
317}
318
319#[bitfield(u32)]
320pub struct MadtGiccFlags {
321 pub enabled: bool,
322 #[bits(31)]
323 _reserved: u32,
324}
325
326pub struct MadtParser<'a>(&'a [u8]);
328
329impl<'a> MadtParser<'a> {
330 pub fn new(table: &'a [u8]) -> Result<Self, ParserError> {
332 let header = crate::Header::read_from_prefix(table)
333 .map_err(|_| ParserError)?
334 .0; if (header.length.get() as usize) < size_of::<Madt>() {
336 return Err(ParserError);
337 }
338 let off = size_of_val(&header);
339 let table = table
340 .get(off..header.length.get() as usize)
341 .ok_or(ParserError)?;
342 Ok(Self(table))
343 }
344
345 pub fn entries(&self) -> MadtIter<'_> {
347 MadtIter {
348 entries: &self.0[size_of::<Madt>()..],
349 }
350 }
351
352 #[cfg(feature = "alloc")]
355 pub fn parse_apic_ids(&self) -> Result<alloc::vec::Vec<Option<u32>>, ParseApicIdError> {
356 use alloc::vec::Vec;
357
358 let mut apic_ids: Vec<Option<u32>> = Vec::new();
359
360 for entry in self.entries() {
361 let (uid, apic_id) = match entry.map_err(ParseApicIdError::Parser)? {
362 MadtEntry::Apic(apic) => {
363 if apic.flags & MADT_APIC_ENABLED == MADT_APIC_ENABLED {
364 (apic.acpi_processor_uid as u32, apic.apic_id as u32)
365 } else {
366 continue;
367 }
368 }
369 MadtEntry::X2Apic(x2apic) => {
370 if x2apic.flags & MADT_APIC_ENABLED == MADT_APIC_ENABLED {
371 (x2apic.acpi_processor_uid, x2apic.x2_apic_id)
372 } else {
373 continue;
374 }
375 }
376 };
377
378 let index = uid as usize - 1;
380
381 if apic_ids.get(index).is_none() {
382 apic_ids.resize(index + 1, None);
383 }
384
385 if apic_ids[index].replace(apic_id).is_some() {
386 return Err(ParseApicIdError::ProcessorNotUnique(uid));
387 }
388 }
389
390 Ok(apic_ids)
391 }
392}
393
394#[derive(Debug, Error)]
396#[error("madt parsing failed")]
397pub struct ParserError;
398
399#[derive(Debug, thiserror::Error)]
401pub enum ParseApicIdError {
402 #[error("error parsing entry")]
403 Parser(#[source] ParserError),
404 #[error("processor_acpi_uid specified more than once in the MADT")]
405 ProcessorNotUnique(u32),
406}
407
408#[derive(Debug, Clone, Copy, PartialEq, Eq)]
410pub enum MadtEntry {
411 Apic(MadtApic),
413 X2Apic(MadtX2Apic),
415}
416
417pub struct MadtIter<'a> {
419 entries: &'a [u8],
420}
421
422impl MadtIter<'_> {
423 fn parse(&mut self) -> Result<Option<MadtEntry>, ParserError> {
424 while let Ok((header, _)) = MadtEntryHeader::read_from_prefix(self.entries) {
426 if self.entries.len() < header.length as usize {
428 return Err(ParserError);
429 }
430 let (buf, rest) = self.entries.split_at(header.length as usize);
431 self.entries = rest;
432 let entry = match header.typ {
433 MadtType::APIC => {
434 MadtEntry::Apic(FromBytes::read_from_prefix(buf).map_err(|_| ParserError)?.0)
435 }
437 MadtType::X2APIC => {
438 MadtEntry::X2Apic(FromBytes::read_from_prefix(buf).map_err(|_| ParserError)?.0)
439 }
441 _ => continue,
442 };
443 return Ok(Some(entry));
444 }
445 Ok(None)
446 }
447}
448
449impl Iterator for MadtIter<'_> {
450 type Item = Result<MadtEntry, ParserError>;
451
452 fn next(&mut self) -> Option<Self::Item> {
453 self.parse().transpose()
454 }
455}
456
457#[cfg(test)]
459mod test {
460 use super::*;
461 #[cfg(feature = "alloc")]
462 use alloc::vec;
463 #[cfg(feature = "alloc")]
464 use alloc::vec::Vec;
465
466 #[test]
468 #[cfg(feature = "alloc")]
469 fn sparse_madt() {
470 const DATA: &[u8] = &[
471 65, 80, 73, 67, 194, 0, 0, 0, 5, 195, 72, 86, 76, 73, 84, 69, 72, 86, 76, 73, 84, 69,
472 84, 66, 0, 0, 0, 0, 77, 83, 72, 86, 0, 0, 0, 0, 0, 0, 224, 254, 0, 0, 0, 0, 1, 12, 16,
473 0, 0, 0, 192, 254, 0, 0, 0, 0, 2, 10, 0, 2, 2, 0, 0, 0, 13, 0, 0, 8, 1, 0, 1, 0, 0, 0,
474 0, 8, 4, 1, 1, 0, 0, 0, 0, 8, 6, 2, 1, 0, 0, 0, 0, 8, 8, 3, 1, 0, 0, 0, 0, 8, 10, 4, 1,
475 0, 0, 0, 0, 8, 12, 5, 1, 0, 0, 0, 0, 8, 14, 6, 1, 0, 0, 0, 0, 8, 16, 7, 1, 0, 0, 0, 0,
476 8, 18, 8, 1, 0, 0, 0, 0, 8, 20, 9, 1, 0, 0, 0, 0, 8, 22, 10, 1, 0, 0, 0, 0, 8, 24, 11,
477 1, 0, 0, 0, 0, 8, 26, 12, 1, 0, 0, 0, 0, 8, 28, 13, 1, 0, 0, 0, 0, 8, 30, 14, 1, 0, 0,
478 0, 0, 8, 32, 15, 1, 0, 0, 0,
479 ];
480
481 let madt = MadtParser::new(DATA).unwrap();
482 let entries = madt.parse_apic_ids().unwrap();
483
484 assert_eq!(
485 entries,
486 vec![
487 Some(0),
488 None,
489 None,
490 Some(1),
491 None,
492 Some(2),
493 None,
494 Some(3),
495 None,
496 Some(4),
497 None,
498 Some(5),
499 None,
500 Some(6),
501 None,
502 Some(7),
503 None,
504 Some(8),
505 None,
506 Some(9),
507 None,
508 Some(10),
509 None,
510 Some(11),
511 None,
512 Some(12),
513 None,
514 Some(13),
515 None,
516 Some(14),
517 None,
518 Some(15)
519 ]
520 );
521 }
522
523 #[test]
524 fn single_apic() {
525 const DATA: &[u8] = &[
527 0x41, 0x50, 0x49, 0x43, 0x50, 0x00, 0x00, 0x00, 0x04, 0x23, 0x56, 0x52, 0x54, 0x55,
528 0x41, 0x4c, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x46, 0x54, 0x01, 0x00, 0x00, 0x00,
529 0x4d, 0x53, 0x46, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfe, 0x00, 0x00,
530 0x00, 0x00, 0x01, 0x0c, 0x01, 0x00, 0x00, 0x00, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00,
531 0x02, 0x0a, 0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x04, 0x06, 0x01, 0x00,
532 0x00, 0x01, 0x00, 0x08, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
533 ];
534
535 let madt = MadtParser::new(DATA).unwrap();
536
537 let entries = madt.entries().collect::<Result<Vec<_>, _>>().unwrap();
538
539 assert_eq!(
540 entries[0],
541 MadtEntry::Apic(MadtApic {
542 typ: MadtType::APIC,
543 length: 8,
544 acpi_processor_uid: 1,
545 apic_id: 0,
546 flags: 1,
547 })
548 );
549 }
550
551 #[test]
552 #[cfg(feature = "alloc")]
553 fn madt_50_vps() {
554 const DATA: &[u8] = &[
555 0x41, 0x50, 0x49, 0x43, 0xd8, 0x01, 0x00, 0x00, 0x04, 0x06, 0x56, 0x52, 0x54, 0x55,
556 0x41, 0x4c, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x46, 0x54, 0x01, 0x00, 0x00, 0x00, 0x4d, 0x53,
558 0x46, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a,
560 0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x04, 0x06, 0x01, 0x00, 0x00, 0x01, 0x01, 0x0c,
562 0x32, 0x00, 0x00, 0x00, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x01, 0x00,
564 0x00, 0x00, 0x00, 0x08, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x02, 0x01, 0x00,
566 0x00, 0x00, 0x00, 0x08, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x05, 0x04, 0x01, 0x00,
568 0x00, 0x00, 0x00, 0x08, 0x06, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0x06, 0x01, 0x00,
570 0x00, 0x00, 0x00, 0x08, 0x08, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x08, 0x01, 0x00,
572 0x00, 0x00, 0x00, 0x08, 0x0a, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0b, 0x0a, 0x01, 0x00,
574 0x00, 0x00, 0x00, 0x08, 0x0c, 0x0b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0d, 0x0c, 0x01, 0x00,
576 0x00, 0x00, 0x00, 0x08, 0x0e, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0f, 0x11, 0x01, 0x00,
578 0x00, 0x00, 0x00, 0x08, 0x10, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x11, 0x13, 0x01, 0x00,
580 0x00, 0x00, 0x00, 0x08, 0x12, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x13, 0x15, 0x01, 0x00,
582 0x00, 0x00, 0x00, 0x08, 0x14, 0x16, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x15, 0x17, 0x01, 0x00,
584 0x00, 0x00, 0x00, 0x08, 0x16, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x17, 0x19, 0x01, 0x00,
586 0x00, 0x00, 0x00, 0x08, 0x18, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x19, 0x1b, 0x01, 0x00,
588 0x00, 0x00, 0x00, 0x08, 0x1a, 0x1c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1b, 0x20, 0x01, 0x00,
590 0x00, 0x00, 0x00, 0x08, 0x1c, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1d, 0x22, 0x01, 0x00,
592 0x00, 0x00, 0x00, 0x08, 0x1e, 0x23, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1f, 0x24, 0x01, 0x00,
594 0x00, 0x00, 0x00, 0x08, 0x20, 0x25, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x26, 0x01, 0x00,
596 0x00, 0x00, 0x00, 0x08, 0x22, 0x27, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x23, 0x28, 0x01, 0x00,
598 0x00, 0x00, 0x00, 0x08, 0x24, 0x29, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x2a, 0x01, 0x00,
600 0x00, 0x00, 0x00, 0x08, 0x26, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x27, 0x30, 0x01, 0x00,
602 0x00, 0x00, 0x00, 0x08, 0x28, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x29, 0x32, 0x01, 0x00,
604 0x00, 0x00, 0x00, 0x08, 0x2a, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x2b, 0x34, 0x01, 0x00,
606 0x00, 0x00, 0x00, 0x08, 0x2c, 0x35, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x2d, 0x36, 0x01, 0x00,
608 0x00, 0x00, 0x00, 0x08, 0x2e, 0x37, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x2f, 0x38, 0x01, 0x00,
610 0x00, 0x00, 0x00, 0x08, 0x30, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x31, 0x3a, 0x01, 0x00,
612 0x00, 0x00, 0x00, 0x08, 0x32, 0x3b, 0x01, 0x00, 0x00, 0x00, ];
615
616 let madt = MadtParser::new(DATA).unwrap();
617
618 let entries = madt.entries().collect::<Result<Vec<_>, _>>().unwrap();
619
620 assert_eq!(entries.len(), 50);
621 assert!(matches!(
622 entries[0],
623 MadtEntry::Apic(MadtApic {
624 typ: MadtType::APIC,
625 length: 8,
626 acpi_processor_uid: 1,
627 apic_id: 0,
628 flags: 1
629 })
630 ));
631 assert!(matches!(
632 entries[49],
633 MadtEntry::Apic(MadtApic {
634 typ: MadtType::APIC,
635 length: 8,
636 acpi_processor_uid: 50,
637 apic_id: 59,
638 flags: 1
639 })
640 ));
641
642 let entries = madt.parse_apic_ids().unwrap();
643
644 assert_eq!(
645 entries,
646 (0..13)
647 .chain(16..29)
648 .chain(32..44)
649 .chain(48..60)
650 .map(Some)
651 .collect::<Vec<_>>()
652 );
653 }
654
655 #[test]
656 #[cfg(feature = "alloc")]
657 fn madt_256() {
658 const DATA: &[u8] = &[
659 0x41, 0x50, 0x49, 0x43, 0x50, 0x08, 0x00, 0x00, 0x04, 0x14, 0x56, 0x52, 0x54, 0x55,
660 0x41, 0x4c, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x46, 0x54, 0x01, 0x00, 0x00, 0x00, 0x4d, 0x53,
662 0x46, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a,
664 0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x04, 0x06, 0x01, 0x00, 0x00, 0x01, 0x01, 0x0c,
666 0x00, 0x00, 0x00, 0x00, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x01, 0x00,
668 0x00, 0x00, 0x00, 0x08, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x02, 0x01, 0x00,
670 0x00, 0x00, 0x00, 0x08, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x05, 0x04, 0x01, 0x00,
672 0x00, 0x00, 0x00, 0x08, 0x06, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0x06, 0x01, 0x00,
674 0x00, 0x00, 0x00, 0x08, 0x08, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x08, 0x01, 0x00,
676 0x00, 0x00, 0x00, 0x08, 0x0a, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0b, 0x0a, 0x01, 0x00,
678 0x00, 0x00, 0x00, 0x08, 0x0c, 0x0b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0d, 0x0c, 0x01, 0x00,
680 0x00, 0x00, 0x00, 0x08, 0x0e, 0x0d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0f, 0x0e, 0x01, 0x00,
682 0x00, 0x00, 0x00, 0x08, 0x10, 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x11, 0x10, 0x01, 0x00,
684 0x00, 0x00, 0x00, 0x08, 0x12, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x13, 0x12, 0x01, 0x00,
686 0x00, 0x00, 0x00, 0x08, 0x14, 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x15, 0x14, 0x01, 0x00,
688 0x00, 0x00, 0x00, 0x08, 0x16, 0x15, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x17, 0x16, 0x01, 0x00,
690 0x00, 0x00, 0x00, 0x08, 0x18, 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x19, 0x18, 0x01, 0x00,
692 0x00, 0x00, 0x00, 0x08, 0x1a, 0x19, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1b, 0x1a, 0x01, 0x00,
694 0x00, 0x00, 0x00, 0x08, 0x1c, 0x1b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1d, 0x1c, 0x01, 0x00,
696 0x00, 0x00, 0x00, 0x08, 0x1e, 0x1d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1f, 0x1e, 0x01, 0x00,
698 0x00, 0x00, 0x00, 0x08, 0x20, 0x1f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x21, 0x20, 0x01, 0x00,
700 0x00, 0x00, 0x00, 0x08, 0x22, 0x21, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x23, 0x22, 0x01, 0x00,
702 0x00, 0x00, 0x00, 0x08, 0x24, 0x23, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x25, 0x24, 0x01, 0x00,
704 0x00, 0x00, 0x00, 0x08, 0x26, 0x25, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x27, 0x26, 0x01, 0x00,
706 0x00, 0x00, 0x00, 0x08, 0x28, 0x27, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x29, 0x28, 0x01, 0x00,
708 0x00, 0x00, 0x00, 0x08, 0x2a, 0x29, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x2b, 0x2a, 0x01, 0x00,
710 0x00, 0x00, 0x00, 0x08, 0x2c, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x2d, 0x2c, 0x01, 0x00,
712 0x00, 0x00, 0x00, 0x08, 0x2e, 0x2d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x2f, 0x2e, 0x01, 0x00,
714 0x00, 0x00, 0x00, 0x08, 0x30, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x31, 0x30, 0x01, 0x00,
716 0x00, 0x00, 0x00, 0x08, 0x32, 0x31, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x33, 0x32, 0x01, 0x00,
718 0x00, 0x00, 0x00, 0x08, 0x34, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x35, 0x34, 0x01, 0x00,
720 0x00, 0x00, 0x00, 0x08, 0x36, 0x35, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x37, 0x36, 0x01, 0x00,
722 0x00, 0x00, 0x00, 0x08, 0x38, 0x37, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x39, 0x38, 0x01, 0x00,
724 0x00, 0x00, 0x00, 0x08, 0x3a, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3b, 0x3a, 0x01, 0x00,
726 0x00, 0x00, 0x00, 0x08, 0x3c, 0x3b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3d, 0x3c, 0x01, 0x00,
728 0x00, 0x00, 0x00, 0x08, 0x3e, 0x3d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3f, 0x3e, 0x01, 0x00,
730 0x00, 0x00, 0x00, 0x08, 0x40, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x41, 0x40, 0x01, 0x00,
732 0x00, 0x00, 0x00, 0x08, 0x42, 0x41, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x43, 0x42, 0x01, 0x00,
734 0x00, 0x00, 0x00, 0x08, 0x44, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x45, 0x44, 0x01, 0x00,
736 0x00, 0x00, 0x00, 0x08, 0x46, 0x45, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x47, 0x46, 0x01, 0x00,
738 0x00, 0x00, 0x00, 0x08, 0x48, 0x47, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x49, 0x48, 0x01, 0x00,
740 0x00, 0x00, 0x00, 0x08, 0x4a, 0x49, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x4b, 0x4a, 0x01, 0x00,
742 0x00, 0x00, 0x00, 0x08, 0x4c, 0x4b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x4d, 0x4c, 0x01, 0x00,
744 0x00, 0x00, 0x00, 0x08, 0x4e, 0x4d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x4f, 0x4e, 0x01, 0x00,
746 0x00, 0x00, 0x00, 0x08, 0x50, 0x4f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x51, 0x50, 0x01, 0x00,
748 0x00, 0x00, 0x00, 0x08, 0x52, 0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x53, 0x52, 0x01, 0x00,
750 0x00, 0x00, 0x00, 0x08, 0x54, 0x53, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x55, 0x54, 0x01, 0x00,
752 0x00, 0x00, 0x00, 0x08, 0x56, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x57, 0x56, 0x01, 0x00,
754 0x00, 0x00, 0x00, 0x08, 0x58, 0x57, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x59, 0x58, 0x01, 0x00,
756 0x00, 0x00, 0x00, 0x08, 0x5a, 0x59, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x5b, 0x5a, 0x01, 0x00,
758 0x00, 0x00, 0x00, 0x08, 0x5c, 0x5b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x5d, 0x5c, 0x01, 0x00,
760 0x00, 0x00, 0x00, 0x08, 0x5e, 0x5d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x5f, 0x5e, 0x01, 0x00,
762 0x00, 0x00, 0x00, 0x08, 0x60, 0x5f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x61, 0x60, 0x01, 0x00,
764 0x00, 0x00, 0x00, 0x08, 0x62, 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x63, 0x62, 0x01, 0x00,
766 0x00, 0x00, 0x00, 0x08, 0x64, 0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x65, 0x64, 0x01, 0x00,
768 0x00, 0x00, 0x00, 0x08, 0x66, 0x65, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x67, 0x66, 0x01, 0x00,
770 0x00, 0x00, 0x00, 0x08, 0x68, 0x67, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x69, 0x68, 0x01, 0x00,
772 0x00, 0x00, 0x00, 0x08, 0x6a, 0x69, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x6b, 0x6a, 0x01, 0x00,
774 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x6d, 0x6c, 0x01, 0x00,
776 0x00, 0x00, 0x00, 0x08, 0x6e, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x6f, 0x6e, 0x01, 0x00,
778 0x00, 0x00, 0x00, 0x08, 0x70, 0x6f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x71, 0x70, 0x01, 0x00,
780 0x00, 0x00, 0x00, 0x08, 0x72, 0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x73, 0x72, 0x01, 0x00,
782 0x00, 0x00, 0x00, 0x08, 0x74, 0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x75, 0x74, 0x01, 0x00,
784 0x00, 0x00, 0x00, 0x08, 0x76, 0x75, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x77, 0x76, 0x01, 0x00,
786 0x00, 0x00, 0x00, 0x08, 0x78, 0x77, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x79, 0x78, 0x01, 0x00,
788 0x00, 0x00, 0x00, 0x08, 0x7a, 0x79, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x7b, 0x7a, 0x01, 0x00,
790 0x00, 0x00, 0x00, 0x08, 0x7c, 0x7b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x7d, 0x7c, 0x01, 0x00,
792 0x00, 0x00, 0x00, 0x08, 0x7e, 0x7d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x7f, 0x7e, 0x01, 0x00,
794 0x00, 0x00, 0x00, 0x08, 0x80, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x81, 0x80, 0x01, 0x00,
796 0x00, 0x00, 0x00, 0x08, 0x82, 0x81, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x83, 0x82, 0x01, 0x00,
798 0x00, 0x00, 0x00, 0x08, 0x84, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x85, 0x84, 0x01, 0x00,
800 0x00, 0x00, 0x00, 0x08, 0x86, 0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x87, 0x86, 0x01, 0x00,
802 0x00, 0x00, 0x00, 0x08, 0x88, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x89, 0x88, 0x01, 0x00,
804 0x00, 0x00, 0x00, 0x08, 0x8a, 0x89, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x8b, 0x8a, 0x01, 0x00,
806 0x00, 0x00, 0x00, 0x08, 0x8c, 0x8b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x8d, 0x8c, 0x01, 0x00,
808 0x00, 0x00, 0x00, 0x08, 0x8e, 0x8d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x8f, 0x8e, 0x01, 0x00,
810 0x00, 0x00, 0x00, 0x08, 0x90, 0x8f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x91, 0x90, 0x01, 0x00,
812 0x00, 0x00, 0x00, 0x08, 0x92, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x93, 0x92, 0x01, 0x00,
814 0x00, 0x00, 0x00, 0x08, 0x94, 0x93, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x95, 0x94, 0x01, 0x00,
816 0x00, 0x00, 0x00, 0x08, 0x96, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x97, 0x96, 0x01, 0x00,
818 0x00, 0x00, 0x00, 0x08, 0x98, 0x97, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x99, 0x98, 0x01, 0x00,
820 0x00, 0x00, 0x00, 0x08, 0x9a, 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x9b, 0x9a, 0x01, 0x00,
822 0x00, 0x00, 0x00, 0x08, 0x9c, 0x9b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x9d, 0x9c, 0x01, 0x00,
824 0x00, 0x00, 0x00, 0x08, 0x9e, 0x9d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x9f, 0x9e, 0x01, 0x00,
826 0x00, 0x00, 0x00, 0x08, 0xa0, 0x9f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xa1, 0xa0, 0x01, 0x00,
828 0x00, 0x00, 0x00, 0x08, 0xa2, 0xa1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xa3, 0xa2, 0x01, 0x00,
830 0x00, 0x00, 0x00, 0x08, 0xa4, 0xa3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xa5, 0xa4, 0x01, 0x00,
832 0x00, 0x00, 0x00, 0x08, 0xa6, 0xa5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xa7, 0xa6, 0x01, 0x00,
834 0x00, 0x00, 0x00, 0x08, 0xa8, 0xa7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xa9, 0xa8, 0x01, 0x00,
836 0x00, 0x00, 0x00, 0x08, 0xaa, 0xa9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xab, 0xaa, 0x01, 0x00,
838 0x00, 0x00, 0x00, 0x08, 0xac, 0xab, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xad, 0xac, 0x01, 0x00,
840 0x00, 0x00, 0x00, 0x08, 0xae, 0xad, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xaf, 0xae, 0x01, 0x00,
842 0x00, 0x00, 0x00, 0x08, 0xb0, 0xaf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xb1, 0xb0, 0x01, 0x00,
844 0x00, 0x00, 0x00, 0x08, 0xb2, 0xb1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xb3, 0xb2, 0x01, 0x00,
846 0x00, 0x00, 0x00, 0x08, 0xb4, 0xb3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xb5, 0xb4, 0x01, 0x00,
848 0x00, 0x00, 0x00, 0x08, 0xb6, 0xb5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xb7, 0xb6, 0x01, 0x00,
850 0x00, 0x00, 0x00, 0x08, 0xb8, 0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xb9, 0xb8, 0x01, 0x00,
852 0x00, 0x00, 0x00, 0x08, 0xba, 0xb9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xbb, 0xba, 0x01, 0x00,
854 0x00, 0x00, 0x00, 0x08, 0xbc, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xbd, 0xbc, 0x01, 0x00,
856 0x00, 0x00, 0x00, 0x08, 0xbe, 0xbd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xbf, 0xbe, 0x01, 0x00,
858 0x00, 0x00, 0x00, 0x08, 0xc0, 0xbf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc1, 0xc0, 0x01, 0x00,
860 0x00, 0x00, 0x00, 0x08, 0xc2, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc3, 0xc2, 0x01, 0x00,
862 0x00, 0x00, 0x00, 0x08, 0xc4, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc5, 0xc4, 0x01, 0x00,
864 0x00, 0x00, 0x00, 0x08, 0xc6, 0xc5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc7, 0xc6, 0x01, 0x00,
866 0x00, 0x00, 0x00, 0x08, 0xc8, 0xc7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc9, 0xc8, 0x01, 0x00,
868 0x00, 0x00, 0x00, 0x08, 0xca, 0xc9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xcb, 0xca, 0x01, 0x00,
870 0x00, 0x00, 0x00, 0x08, 0xcc, 0xcb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xcd, 0xcc, 0x01, 0x00,
872 0x00, 0x00, 0x00, 0x08, 0xce, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xcf, 0xce, 0x01, 0x00,
874 0x00, 0x00, 0x00, 0x08, 0xd0, 0xcf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xd1, 0xd0, 0x01, 0x00,
876 0x00, 0x00, 0x00, 0x08, 0xd2, 0xd1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xd3, 0xd2, 0x01, 0x00,
878 0x00, 0x00, 0x00, 0x08, 0xd4, 0xd3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xd5, 0xd4, 0x01, 0x00,
880 0x00, 0x00, 0x00, 0x08, 0xd6, 0xd5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xd7, 0xd6, 0x01, 0x00,
882 0x00, 0x00, 0x00, 0x08, 0xd8, 0xd7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xd9, 0xd8, 0x01, 0x00,
884 0x00, 0x00, 0x00, 0x08, 0xda, 0xd9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xdb, 0xda, 0x01, 0x00,
886 0x00, 0x00, 0x00, 0x08, 0xdc, 0xdb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xdd, 0xdc, 0x01, 0x00,
888 0x00, 0x00, 0x00, 0x08, 0xde, 0xdd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xdf, 0xde, 0x01, 0x00,
890 0x00, 0x00, 0x00, 0x08, 0xe0, 0xdf, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe1, 0xe0, 0x01, 0x00,
892 0x00, 0x00, 0x00, 0x08, 0xe2, 0xe1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe3, 0xe2, 0x01, 0x00,
894 0x00, 0x00, 0x00, 0x08, 0xe4, 0xe3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe5, 0xe4, 0x01, 0x00,
896 0x00, 0x00, 0x00, 0x08, 0xe6, 0xe5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe7, 0xe6, 0x01, 0x00,
898 0x00, 0x00, 0x00, 0x08, 0xe8, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xe9, 0xe8, 0x01, 0x00,
900 0x00, 0x00, 0x00, 0x08, 0xea, 0xe9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xeb, 0xea, 0x01, 0x00,
902 0x00, 0x00, 0x00, 0x08, 0xec, 0xeb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xed, 0xec, 0x01, 0x00,
904 0x00, 0x00, 0x00, 0x08, 0xee, 0xed, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xef, 0xee, 0x01, 0x00,
906 0x00, 0x00, 0x00, 0x08, 0xf0, 0xef, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf1, 0xf0, 0x01, 0x00,
908 0x00, 0x00, 0x00, 0x08, 0xf2, 0xf1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf3, 0xf2, 0x01, 0x00,
910 0x00, 0x00, 0x00, 0x08, 0xf4, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf5, 0xf4, 0x01, 0x00,
912 0x00, 0x00, 0x00, 0x08, 0xf6, 0xf5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf7, 0xf6, 0x01, 0x00,
914 0x00, 0x00, 0x00, 0x08, 0xf8, 0xf7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf9, 0xf8, 0x01, 0x00,
916 0x00, 0x00, 0x00, 0x08, 0xfa, 0xf9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xfb, 0xfa, 0x01, 0x00,
918 0x00, 0x00, 0x00, 0x08, 0xfc, 0xfb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xfd, 0xfc, 0x01, 0x00,
920 0x00, 0x00, 0x00, 0x08, 0xfe, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0xff, 0xfe, 0x01, 0x00,
922 0x00, 0x00, 0x09, 0x10, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
924 0x00, 0x00, ];
926
927 let madt = MadtParser::new(DATA).unwrap();
928
929 let entries = madt.entries().collect::<Result<Vec<_>, _>>().unwrap();
930
931 assert!(entries.len() == 256);
932 assert!(matches!(
933 entries[0],
934 MadtEntry::Apic(MadtApic {
935 typ: MadtType::APIC,
936 length: 8,
937 acpi_processor_uid: 1,
938 apic_id: 0,
939 flags: 1
940 })
941 ));
942 assert!(matches!(
943 entries[255],
944 MadtEntry::X2Apic(MadtX2Apic {
945 typ: MadtType::X2APIC,
946 length: 16,
947 reserved: 0,
948 x2_apic_id: 255,
949 flags: 1,
950 acpi_processor_uid: 256
951 })
952 ));
953
954 let entries = madt.parse_apic_ids().unwrap();
955
956 assert_eq!(entries, (0..256).map(Some).collect::<Vec<_>>());
957 }
958}