1pub use crate::aml::*;
5use memory_range::MemoryRange;
6use x86defs::apic::APIC_BASE_ADDRESS;
7use zerocopy::FromBytes;
8use zerocopy::Immutable;
9use zerocopy::IntoBytes;
10use zerocopy::KnownLayout;
11
12#[repr(C, packed)]
13#[derive(Copy, Clone, Debug, IntoBytes, Immutable, KnownLayout, FromBytes)]
14pub struct DescriptionHeader {
15 pub signature: u32,
16 _length: u32, pub revision: u8,
18 _checksum: u8, pub oem_id: [u8; 6],
20 pub oem_table_id: u64,
21 pub oem_revision: u32,
22 pub creator_id: u32,
23 pub creator_rev: u32,
24}
25
26pub struct PciRoutingTableEntry {
27 pub address: u32,
28 pub pin: u8,
29 pub source: Option<Vec<u8>>,
30 pub source_index: u32,
31}
32
33pub struct PciRoutingTable {
34 entries: Vec<PciRoutingTableEntry>,
35}
36
37impl PciRoutingTable {
38 pub fn new() -> Self {
39 Self {
40 entries: Vec::new(),
41 }
42 }
43
44 pub fn add_entry(&mut self, entry: PciRoutingTableEntry) {
45 self.entries.push(entry);
46 }
47}
48
49impl AmlObject for PciRoutingTable {
50 fn append_to_vec(&self, byte_stream: &mut Vec<u8>) {
51 let mut table_data: Vec<u8> = Vec::with_capacity(self.entries.len() * 10);
52 for entry in self.entries.iter() {
53 let mut elem_data: Vec<u8> = Vec::with_capacity(
54 9 + match &entry.source {
55 Some(name) => name.len(),
56 None => 1,
57 },
58 );
59 elem_data.extend_from_slice(&encode_dword(entry.address));
60 elem_data.push(entry.pin);
61 match &entry.source {
62 Some(name) => elem_data.extend_from_slice(name),
63 None => elem_data.push(0),
64 }
65 elem_data.extend_from_slice(&encode_dword(entry.source_index));
66 StructuredPackage {
67 elem_count: 4,
68 elem_data,
69 }
70 .append_to_vec(&mut table_data);
71 }
72
73 NamedObject::new(
74 b"_PRT",
75 &StructuredPackage {
76 elem_count: self.entries.len() as u8,
77 elem_data: table_data,
78 },
79 )
80 .append_to_vec(byte_stream);
81 }
82}
83
84pub struct Dsdt {
85 description_header: DescriptionHeader,
86 objects: Vec<u8>,
87}
88
89impl Dsdt {
90 pub fn new() -> Self {
91 Self {
92 description_header: DescriptionHeader {
93 signature: u32::from_le_bytes(*b"DSDT"),
94 _length: 0,
95 revision: 2,
96 _checksum: 0,
97 oem_id: *b"MSFTVM",
98 oem_table_id: 0x313054445344, oem_revision: 1,
100 creator_id: u32::from_le_bytes(*b"MSFT"),
101 creator_rev: 0x5000000,
102 },
103 objects: vec![],
104 }
105 }
106
107 pub fn to_bytes(&self) -> Vec<u8> {
108 let mut byte_stream = Vec::new();
109 byte_stream.extend_from_slice(self.description_header.as_bytes());
110 byte_stream.extend_from_slice(&self.objects);
111
112 let length = byte_stream.len();
113 byte_stream[4..8].copy_from_slice(&u32::try_from(length).unwrap().to_le_bytes());
114 let mut checksum: u8 = 0;
115 for byte in &byte_stream {
116 checksum = checksum.wrapping_add(*byte);
117 }
118
119 byte_stream[9] = (!checksum).wrapping_add(1);
120 byte_stream
121 }
122
123 pub fn add_object(&mut self, obj: &impl AmlObject) {
124 obj.append_to_vec(&mut self.objects);
125 }
126
127 pub fn add_apic(&mut self) {
141 let mut apic = Device::new(b"\\_SB.APIC");
142 apic.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0003")));
143 let mut apic_crs = CurrentResourceSettings::new();
144 apic_crs.add_resource(&Memory32Fixed::new(APIC_BASE_ADDRESS, 0x1000, true));
145 apic_crs.add_resource(&Memory32Fixed::new(0xfec00000, 0x1000, true));
146 apic.add_object(&apic_crs);
147 self.add_object(&apic);
148 }
149
150 pub fn add_uart(&mut self, name: &[u8], ddn: &[u8], uid: u64, io_base: u16, irq: u32) {
166 let mut uart = Device::new(name);
167 uart.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0501")));
168 uart.add_object(&NamedString::new(b"_DDN", ddn));
169 uart.add_object(&NamedInteger::new(b"_UID", uid));
170 let mut uart_crs = CurrentResourceSettings::new();
171 uart_crs.add_resource(&IoPort::new(io_base, io_base, 8));
172 let mut intr = Interrupt::new(irq);
173 intr.is_edge_triggered = true;
174 uart_crs.add_resource(&intr);
175 uart.add_object(&uart_crs);
176 self.add_object(&uart);
177 }
178
179 pub fn add_sbsa_uart(&mut self, name: &[u8], uid: u64, base_addr: u64, size: u64, gsiv: u32) {
195 let mut uart = Device::new(name);
196 uart.add_object(&NamedString::new(b"_HID", b"ARMH0011"));
197 uart.add_object(&NamedInteger::new(b"_UID", uid));
198 let mut crs = CurrentResourceSettings::new();
199 crs.add_resource(&QwordMemory::new(base_addr, size));
200 let mut intr = Interrupt::new(gsiv);
201 intr.is_edge_triggered = false; crs.add_resource(&intr);
203 uart.add_object(&crs);
204 self.add_object(&uart);
205 }
206
207 pub fn add_mmio_module(&mut self, low: MemoryRange, high: MemoryRange) {
232 let mut vmod = Device::new(b"\\_SB.VMOD");
233 vmod.add_object(&NamedString::new(b"_HID", b"ACPI0004"));
234 vmod.add_object(&NamedInteger::new(b"_UID", 0));
235 let mut vmod_crs = CurrentResourceSettings::new();
236 if !low.is_empty() {
237 vmod_crs.add_resource(&QwordMemory::new(low.start(), low.len()));
238 }
239 if !high.is_empty() {
240 vmod_crs.add_resource(&QwordMemory::new(high.start(), high.len()));
241 }
242 vmod.add_object(&vmod_crs);
243 self.add_object(&vmod);
244 }
245
246 pub fn add_pci(
267 &mut self,
268 low: MemoryRange,
269 high: MemoryRange,
270 legacy_interrupts: &[((u8, Option<u8>), u32)],
272 ) {
273 let mut pci0 = Device::new(b"\\_SB.PCI0");
274 pci0.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0A03")));
275 let mut empty_os_method = Method::new(b"_OSC");
281 empty_os_method.set_arg_count(4);
282 empty_os_method.add_operation(&ReturnOp {
283 result: Buffer(0x10u64.to_le_bytes()).to_bytes(),
284 });
285 pci0.add_object(&empty_os_method);
286 let mut prt = PciRoutingTable::new();
287 for &((device, function), line) in legacy_interrupts {
288 prt.add_entry(PciRoutingTableEntry {
289 address: ((device as u32) << 16) | function.map(|x| x as u32).unwrap_or(0xffff),
290 pin: 0,
291 source: None,
292 source_index: line, });
294 }
295 pci0.add_object(&prt);
296 let mut crs = CurrentResourceSettings::new();
297 crs.add_resource(&BusNumber::new(0, 1));
298 crs.add_resource(&IoPort::new(0xcf8, 0xcf8, 8));
299 crs.add_resource(&QwordMemory::new(low.start(), low.len()));
300 if !high.is_empty() {
301 crs.add_resource(&QwordMemory::new(high.start(), high.len()));
302 }
303 pci0.add_object(&crs);
304 self.add_object(&pci0);
305 }
306
307 pub fn add_vmbus(&mut self, in_pci: bool, interrupt_intid: Option<u32>) {
335 let name = if in_pci {
336 b"\\_SB.PCI0.VMBS"
337 } else {
338 b"\\_SB.VMOD.VMBS"
339 };
340 let mut vmbs = Device::new(name);
341 vmbs.add_object(&NamedInteger::new(b"STA", 0xf));
342 vmbs.add_object(&NamedInteger::new(b"_ADR", 0));
343 vmbs.add_object(&NamedString::new(b"_DDN", b"VMBUS"));
344 vmbs.add_object(&NamedString::new(b"_HID", b"VMBus"));
345 vmbs.add_object(&NamedInteger::new(b"_UID", 0));
346 let op = AndOp {
347 operand1: b"STA_".to_vec(),
348 operand2: encode_integer(13),
349 target_name: b"STA_".to_vec(),
350 };
351 let mut method = Method::new(b"_DIS");
352 method.add_operation(&op);
353 vmbs.add_object(&method);
354 let op = OrOp {
355 operand1: b"STA_".to_vec(),
356 operand2: encode_integer(15),
357 target_name: b"STA_".to_vec(),
358 };
359 let mut method = Method::new(b"_PS0");
360 method.add_operation(&op);
361 vmbs.add_object(&method);
362 let op = ReturnOp {
363 result: b"STA_".to_vec(),
364 };
365 let mut method = Method::new(b"_STA");
366 method.add_operation(&op);
367 vmbs.add_object(&method);
368 vmbs.add_object(&NamedInteger::new(b"_PS3", 0));
369 let mut crs = CurrentResourceSettings::new();
370 if let Some(intid) = interrupt_intid {
371 let mut intr = Interrupt::new(intid);
372 intr.is_edge_triggered = true;
373 crs.add_resource(&intr);
374 }
375 vmbs.add_object(&crs);
376 self.add_object(&vmbs);
377 }
378
379 pub fn add_rtc(&mut self) {
393 let mut rtc = Device::new(b"\\_SB.RTC0");
394 rtc.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0B00")));
395 rtc.add_object(&NamedInteger::new(b"_UID", 0));
396 let mut rtc_crs = CurrentResourceSettings::new();
397 let mut ioport = IoPort::new(0x70, 0x70, 2);
398 ioport.alignment = 0;
399 rtc_crs.add_resource(&ioport);
400 let mut intr = Interrupt::new(8);
401 intr.is_edge_triggered = true;
402 rtc_crs.add_resource(&intr);
403 rtc.add_object(&rtc_crs);
404 self.add_object(&rtc);
405 }
406}
407
408#[cfg(test)]
409mod tests {
410 use super::*;
411 use crate::aml::test_helpers::verify_expected_bytes;
412
413 pub fn verify_header(bytes: &[u8]) {
414 assert!(bytes.len() >= 36);
415
416 assert_eq!(bytes[0], b'D');
418 assert_eq!(bytes[1], b'S');
419 assert_eq!(bytes[2], b'D');
420 assert_eq!(bytes[3], b'T');
421
422 let dsdt_len = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
424 assert_eq!(dsdt_len as usize, bytes.len());
425
426 assert_eq!(bytes[8], 2);
428
429 let mut checksum: u8 = 0;
431 for byte in bytes.iter() {
432 checksum = checksum.wrapping_add(*byte);
433 }
434 assert_eq!(checksum, 0);
435
436 assert_eq!(bytes[10], b'M');
438 assert_eq!(bytes[11], b'S');
439 assert_eq!(bytes[12], b'F');
440 assert_eq!(bytes[13], b'T');
441 assert_eq!(bytes[14], b'V');
442 assert_eq!(bytes[15], b'M');
443
444 assert_eq!(bytes[16], b'D');
446 assert_eq!(bytes[17], b'S');
447 assert_eq!(bytes[18], b'D');
448 assert_eq!(bytes[19], b'T');
449 assert_eq!(bytes[20], b'0');
450 assert_eq!(bytes[21], b'1');
451 assert_eq!(bytes[22], 0);
452 assert_eq!(bytes[23], 0);
453
454 let oem_revision = u32::from_le_bytes(bytes[24..28].try_into().unwrap());
456 assert_eq!(oem_revision, 1);
457
458 assert_eq!(bytes[28], b'M');
460 assert_eq!(bytes[29], b'S');
461 assert_eq!(bytes[30], b'F');
462 assert_eq!(bytes[31], b'T');
463
464 let creator_rev = u32::from_le_bytes(bytes[32..36].try_into().unwrap());
466 assert_eq!(creator_rev, 0x5000000);
467 }
468
469 #[test]
470 fn verify_simple_table() {
471 let mut dsdt = Dsdt::new();
472 let nobj = NamedObject::new(b"_S0", &Package(vec![0, 0]));
473 dsdt.add_object(&nobj);
474 let bytes = dsdt.to_bytes();
475 verify_header(&bytes);
476 verify_expected_bytes(&bytes[36..], &[8, b'_', b'S', b'0', b'_', 0x12, 4, 2, 0, 0]);
477 }
478
479 #[test]
480 fn verify_table() {
481 let mut dsdt = Dsdt::new();
482 dsdt.add_object(&NamedObject::new(b"\\_S0", &Package(vec![0, 0])));
483 dsdt.add_object(&NamedObject::new(b"\\_S5", &Package(vec![0, 0])));
484
485 let mut apic = Device::new(b"\\_SB.APIC");
486 apic.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0003")));
487 let mut apic_crs = CurrentResourceSettings::new();
488 apic_crs.add_resource(&Memory32Fixed::new(0xfee00000, 0x1000, true));
489 apic_crs.add_resource(&Memory32Fixed::new(0xfec00000, 0x1000, true));
490 apic.add_object(&apic_crs);
491 dsdt.add_object(&apic);
492
493 let mut uart = Device::new(b"\\_SB.UAR1");
494 uart.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0501")));
495 uart.add_object(&NamedString::new(b"_DDN", b"COM1"));
496 uart.add_object(&NamedInteger::new(b"_UID", 1));
497 let mut uart_crs = CurrentResourceSettings::new();
498 uart_crs.add_resource(&IoPort::new(0x3f8, 0x3f8, 8));
499 let mut intr = Interrupt::new(4);
500 intr.is_edge_triggered = true;
501 uart_crs.add_resource(&intr);
502 uart.add_object(&uart_crs);
503 dsdt.add_object(&uart);
504
505 let mut vmod = Device::new(b"\\_SB.VMOD");
506 vmod.add_object(&NamedString::new(b"_HID", b"ACPI0004"));
507 vmod.add_object(&NamedInteger::new(b"_UID", 0));
508 let mut vmod_crs = CurrentResourceSettings::new();
509 vmod_crs.add_resource(&QwordMemory::new(0x100000000, 0x100000000));
510 vmod.add_object(&vmod_crs);
511 dsdt.add_object(&vmod);
512
513 let mut vmbs = Device::new(b"\\_SB.VMOD.VMBS");
514 vmbs.add_object(&NamedInteger::new(b"STA", 0xf));
515 vmbs.add_object(&NamedInteger::new(b"_ADR", 0));
516 vmbs.add_object(&NamedString::new(b"_DDN", b"VMBUS"));
517 vmbs.add_object(&NamedString::new(b"_HID", b"VMBus"));
518 vmbs.add_object(&NamedInteger::new(b"_UID", 0));
519 let op = AndOp {
520 operand1: vec![b'S', b'T', b'A', b'_'],
521 operand2: encode_integer(13),
522 target_name: vec![b'S', b'T', b'A', b'_'],
523 };
524 let mut method = Method::new(b"_DIS");
525 method.add_operation(&op);
526 vmbs.add_object(&method);
527 let op = OrOp {
528 operand1: vec![b'S', b'T', b'A', b'_'],
529 operand2: encode_integer(15),
530 target_name: vec![b'S', b'T', b'A', b'_'],
531 };
532 let mut method = Method::new(b"_PS0");
533 method.add_operation(&op);
534 vmbs.add_object(&method);
535 let op = ReturnOp {
536 result: vec![b'S', b'T', b'A', b'_'],
537 };
538 let mut method = Method::new(b"_STA");
539 method.add_operation(&op);
540 vmbs.add_object(&method);
541 vmbs.add_object(&NamedInteger::new(b"_PS3", 0));
542 dsdt.add_object(&vmbs);
543
544 let mut rtc = Device::new(b"\\_SB.RTC0");
545 rtc.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0B00")));
546 rtc.add_object(&NamedInteger::new(b"_UID", 0));
547 let mut rtc_crs = CurrentResourceSettings::new();
548 let mut ioport = IoPort::new(0x70, 0x70, 2);
549 ioport.alignment = 0;
550 rtc_crs.add_resource(&ioport);
551 let mut intr = Interrupt::new(8);
552 intr.is_edge_triggered = true;
553 rtc_crs.add_resource(&intr);
554 rtc.add_object(&rtc_crs);
555 dsdt.add_object(&rtc);
556
557 for proc_index in 1..3 {
558 let mut proc = Device::new(format!("P{:03}", proc_index).as_bytes());
559 proc.add_object(&NamedString::new(b"_HID", b"ACPI0007"));
560 proc.add_object(&NamedInteger::new(b"_UID", proc_index as u64));
561 let mut method = Method::new(b"_STA");
562 method.add_operation(&ReturnOp {
563 result: encode_integer(0xf),
564 });
565 proc.add_object(&method);
566 dsdt.add_object(&proc);
567 }
568
569 let bytes = dsdt.to_bytes();
570 verify_header(&bytes);
571 verify_expected_bytes(
572 &bytes[36..],
573 &[
574 0x08, 0x5C, 0x5F, 0x53, 0x30, 0x5F, 0x12, 0x04, 0x02, 0x00, 0x00, 0x08, 0x5C, 0x5F,
575 0x53, 0x35, 0x5F, 0x12, 0x04, 0x02, 0x00, 0x00, 0x5B, 0x82, 0x38, 0x5C, 0x2E, 0x5F,
576 0x53, 0x42, 0x5F, 0x41, 0x50, 0x49, 0x43, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0C, 0x41,
577 0xD0, 0x00, 0x03, 0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x1D, 0x0A, 0x1A, 0x86, 0x09,
578 0x00, 0x01, 0x00, 0x00, 0xE0, 0xFE, 0x00, 0x10, 0x00, 0x00, 0x86, 0x09, 0x00, 0x01,
579 0x00, 0x00, 0xC0, 0xFE, 0x00, 0x10, 0x00, 0x00, 0x79, 0x00, 0x5B, 0x82, 0x43, 0x04,
580 0x5C, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x55, 0x41, 0x52, 0x31, 0x08, 0x5F, 0x48, 0x49,
581 0x44, 0x0C, 0x41, 0xD0, 0x05, 0x01, 0x08, 0x5F, 0x44, 0x44, 0x4E, 0x0D, 0x43, 0x4F,
582 0x4D, 0x31, 0x00, 0x08, 0x5F, 0x55, 0x49, 0x44, 0x01, 0x08, 0x5F, 0x43, 0x52, 0x53,
583 0x11, 0x16, 0x0A, 0x13, 0x47, 0x01, 0xF8, 0x03, 0xF8, 0x03, 0x01, 0x08, 0x89, 0x06,
584 0x00, 0x03, 0x01, 0x04, 0x00, 0x00, 0x00, 0x79, 0x00, 0x5B, 0x82, 0x4A, 0x05, 0x5C,
585 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x56, 0x4D, 0x4F, 0x44, 0x08, 0x5F, 0x48, 0x49, 0x44,
586 0x0D, 0x41, 0x43, 0x50, 0x49, 0x30, 0x30, 0x30, 0x34, 0x00, 0x08, 0x5F, 0x55, 0x49,
587 0x44, 0x00, 0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x33, 0x0A, 0x30, 0x8A, 0x2B, 0x00,
588 0x00, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
591 0x00, 0x79, 0x00, 0x5B, 0x82, 0x42, 0x07, 0x5C, 0x2F, 0x03, 0x5F, 0x53, 0x42, 0x5F,
592 0x56, 0x4D, 0x4F, 0x44, 0x56, 0x4D, 0x42, 0x53, 0x08, 0x53, 0x54, 0x41, 0x5F, 0x0A,
593 0x0F, 0x08, 0x5F, 0x41, 0x44, 0x52, 0x00, 0x08, 0x5F, 0x44, 0x44, 0x4E, 0x0D, 0x56,
594 0x4D, 0x42, 0x55, 0x53, 0x00, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0D, 0x56, 0x4D, 0x42,
595 0x75, 0x73, 0x00, 0x08, 0x5F, 0x55, 0x49, 0x44, 0x00, 0x14, 0x11, 0x5F, 0x44, 0x49,
596 0x53, 0x00, 0x7B, 0x53, 0x54, 0x41, 0x5F, 0x0A, 0x0D, 0x53, 0x54, 0x41, 0x5F, 0x14,
597 0x11, 0x5F, 0x50, 0x53, 0x30, 0x00, 0x7D, 0x53, 0x54, 0x41, 0x5F, 0x0A, 0x0F, 0x53,
598 0x54, 0x41, 0x5F, 0x14, 0x0B, 0x5F, 0x53, 0x54, 0x41, 0x00, 0xA4, 0x53, 0x54, 0x41,
599 0x5F, 0x08, 0x5F, 0x50, 0x53, 0x33, 0x00, 0x5B, 0x82, 0x37, 0x5C, 0x2E, 0x5F, 0x53,
600 0x42, 0x5F, 0x52, 0x54, 0x43, 0x30, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0,
601 0x0B, 0x00, 0x08, 0x5F, 0x55, 0x49, 0x44, 0x00, 0x08, 0x5F, 0x43, 0x52, 0x53, 0x11,
602 0x16, 0x0A, 0x13, 0x47, 0x01, 0x70, 0x00, 0x70, 0x00, 0x00, 0x02, 0x89, 0x06, 0x00,
603 0x03, 0x01, 0x08, 0x00, 0x00, 0x00, 0x79, 0x00, 0x5B, 0x82, 0x24, 0x50, 0x30, 0x30,
604 0x31, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0D, 0x41, 0x43, 0x50, 0x49, 0x30, 0x30, 0x30,
605 0x37, 0x00, 0x08, 0x5F, 0x55, 0x49, 0x44, 0x01, 0x14, 0x09, 0x5F, 0x53, 0x54, 0x41,
606 0x00, 0xA4, 0x0A, 0x0F, 0x5B, 0x82, 0x25, 0x50, 0x30, 0x30, 0x32, 0x08, 0x5F, 0x48,
607 0x49, 0x44, 0x0D, 0x41, 0x43, 0x50, 0x49, 0x30, 0x30, 0x30, 0x37, 0x00, 0x08, 0x5F,
608 0x55, 0x49, 0x44, 0x0A, 0x02, 0x14, 0x09, 0x5F, 0x53, 0x54, 0x41, 0x00, 0xA4, 0x0A,
609 0x0F,
610 ],
611 );
612 }
613}