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 vmod_crs.add_resource(&QwordMemory::new(low.start(), low.end() - low.start()));
237 vmod_crs.add_resource(&QwordMemory::new(high.start(), high.end() - high.start()));
238 vmod.add_object(&vmod_crs);
239 self.add_object(&vmod);
240 }
241
242 pub fn add_pci(
263 &mut self,
264 low: MemoryRange,
265 high: MemoryRange,
266 legacy_interrupts: &[((u8, Option<u8>), u32)],
268 ) {
269 let mut pci0 = Device::new(b"\\_SB.PCI0");
270 pci0.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0A03")));
271 let mut empty_os_method = Method::new(b"_OSC");
277 empty_os_method.set_arg_count(4);
278 empty_os_method.add_operation(&ReturnOp {
279 result: Buffer(0x10u64.to_le_bytes()).to_bytes(),
280 });
281 pci0.add_object(&empty_os_method);
282 let mut prt = PciRoutingTable::new();
283 for &((device, function), line) in legacy_interrupts {
284 prt.add_entry(PciRoutingTableEntry {
285 address: ((device as u32) << 16) | function.map(|x| x as u32).unwrap_or(0xffff),
286 pin: 0,
287 source: None,
288 source_index: line, });
290 }
291 pci0.add_object(&prt);
292 let mut crs = CurrentResourceSettings::new();
293 crs.add_resource(&BusNumber::new(0, 1));
294 crs.add_resource(&IoPort::new(0xcf8, 0xcf8, 8));
295 crs.add_resource(&QwordMemory::new(low.start(), low.end() - low.start()));
296 crs.add_resource(&QwordMemory::new(high.start(), high.end() - high.start()));
297 pci0.add_object(&crs);
298 self.add_object(&pci0);
299 }
300
301 pub fn add_vmbus(&mut self, in_pci: bool, interrupt_intid: Option<u32>) {
329 let name = if in_pci {
330 b"\\_SB.PCI0.VMBS"
331 } else {
332 b"\\_SB.VMOD.VMBS"
333 };
334 let mut vmbs = Device::new(name);
335 vmbs.add_object(&NamedInteger::new(b"STA", 0xf));
336 vmbs.add_object(&NamedInteger::new(b"_ADR", 0));
337 vmbs.add_object(&NamedString::new(b"_DDN", b"VMBUS"));
338 vmbs.add_object(&NamedString::new(b"_HID", b"VMBus"));
339 vmbs.add_object(&NamedInteger::new(b"_UID", 0));
340 let op = AndOp {
341 operand1: b"STA_".to_vec(),
342 operand2: encode_integer(13),
343 target_name: b"STA_".to_vec(),
344 };
345 let mut method = Method::new(b"_DIS");
346 method.add_operation(&op);
347 vmbs.add_object(&method);
348 let op = OrOp {
349 operand1: b"STA_".to_vec(),
350 operand2: encode_integer(15),
351 target_name: b"STA_".to_vec(),
352 };
353 let mut method = Method::new(b"_PS0");
354 method.add_operation(&op);
355 vmbs.add_object(&method);
356 let op = ReturnOp {
357 result: b"STA_".to_vec(),
358 };
359 let mut method = Method::new(b"_STA");
360 method.add_operation(&op);
361 vmbs.add_object(&method);
362 vmbs.add_object(&NamedInteger::new(b"_PS3", 0));
363 let mut crs = CurrentResourceSettings::new();
364 if let Some(intid) = interrupt_intid {
365 let mut intr = Interrupt::new(intid);
366 intr.is_edge_triggered = true;
367 crs.add_resource(&intr);
368 }
369 vmbs.add_object(&crs);
370 self.add_object(&vmbs);
371 }
372
373 pub fn add_rtc(&mut self) {
387 let mut rtc = Device::new(b"\\_SB.RTC0");
388 rtc.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0B00")));
389 rtc.add_object(&NamedInteger::new(b"_UID", 0));
390 let mut rtc_crs = CurrentResourceSettings::new();
391 let mut ioport = IoPort::new(0x70, 0x70, 2);
392 ioport.alignment = 0;
393 rtc_crs.add_resource(&ioport);
394 let mut intr = Interrupt::new(8);
395 intr.is_edge_triggered = true;
396 rtc_crs.add_resource(&intr);
397 rtc.add_object(&rtc_crs);
398 self.add_object(&rtc);
399 }
400}
401
402#[cfg(test)]
403mod tests {
404 use super::*;
405 use crate::aml::test_helpers::verify_expected_bytes;
406
407 pub fn verify_header(bytes: &[u8]) {
408 assert!(bytes.len() >= 36);
409
410 assert_eq!(bytes[0], b'D');
412 assert_eq!(bytes[1], b'S');
413 assert_eq!(bytes[2], b'D');
414 assert_eq!(bytes[3], b'T');
415
416 let dsdt_len = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
418 assert_eq!(dsdt_len as usize, bytes.len());
419
420 assert_eq!(bytes[8], 2);
422
423 let mut checksum: u8 = 0;
425 for byte in bytes.iter() {
426 checksum = checksum.wrapping_add(*byte);
427 }
428 assert_eq!(checksum, 0);
429
430 assert_eq!(bytes[10], b'M');
432 assert_eq!(bytes[11], b'S');
433 assert_eq!(bytes[12], b'F');
434 assert_eq!(bytes[13], b'T');
435 assert_eq!(bytes[14], b'V');
436 assert_eq!(bytes[15], b'M');
437
438 assert_eq!(bytes[16], b'D');
440 assert_eq!(bytes[17], b'S');
441 assert_eq!(bytes[18], b'D');
442 assert_eq!(bytes[19], b'T');
443 assert_eq!(bytes[20], b'0');
444 assert_eq!(bytes[21], b'1');
445 assert_eq!(bytes[22], 0);
446 assert_eq!(bytes[23], 0);
447
448 let oem_revision = u32::from_le_bytes(bytes[24..28].try_into().unwrap());
450 assert_eq!(oem_revision, 1);
451
452 assert_eq!(bytes[28], b'M');
454 assert_eq!(bytes[29], b'S');
455 assert_eq!(bytes[30], b'F');
456 assert_eq!(bytes[31], b'T');
457
458 let creator_rev = u32::from_le_bytes(bytes[32..36].try_into().unwrap());
460 assert_eq!(creator_rev, 0x5000000);
461 }
462
463 #[test]
464 fn verify_simple_table() {
465 let mut dsdt = Dsdt::new();
466 let nobj = NamedObject::new(b"_S0", &Package(vec![0, 0]));
467 dsdt.add_object(&nobj);
468 let bytes = dsdt.to_bytes();
469 verify_header(&bytes);
470 verify_expected_bytes(&bytes[36..], &[8, b'_', b'S', b'0', b'_', 0x12, 4, 2, 0, 0]);
471 }
472
473 #[test]
474 fn verify_table() {
475 let mut dsdt = Dsdt::new();
476 dsdt.add_object(&NamedObject::new(b"\\_S0", &Package(vec![0, 0])));
477 dsdt.add_object(&NamedObject::new(b"\\_S5", &Package(vec![0, 0])));
478
479 let mut apic = Device::new(b"\\_SB.APIC");
480 apic.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0003")));
481 let mut apic_crs = CurrentResourceSettings::new();
482 apic_crs.add_resource(&Memory32Fixed::new(0xfee00000, 0x1000, true));
483 apic_crs.add_resource(&Memory32Fixed::new(0xfec00000, 0x1000, true));
484 apic.add_object(&apic_crs);
485 dsdt.add_object(&apic);
486
487 let mut uart = Device::new(b"\\_SB.UAR1");
488 uart.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0501")));
489 uart.add_object(&NamedString::new(b"_DDN", b"COM1"));
490 uart.add_object(&NamedInteger::new(b"_UID", 1));
491 let mut uart_crs = CurrentResourceSettings::new();
492 uart_crs.add_resource(&IoPort::new(0x3f8, 0x3f8, 8));
493 let mut intr = Interrupt::new(4);
494 intr.is_edge_triggered = true;
495 uart_crs.add_resource(&intr);
496 uart.add_object(&uart_crs);
497 dsdt.add_object(&uart);
498
499 let mut vmod = Device::new(b"\\_SB.VMOD");
500 vmod.add_object(&NamedString::new(b"_HID", b"ACPI0004"));
501 vmod.add_object(&NamedInteger::new(b"_UID", 0));
502 let mut vmod_crs = CurrentResourceSettings::new();
503 vmod_crs.add_resource(&QwordMemory::new(0x100000000, 0x100000000));
504 vmod.add_object(&vmod_crs);
505 dsdt.add_object(&vmod);
506
507 let mut vmbs = Device::new(b"\\_SB.VMOD.VMBS");
508 vmbs.add_object(&NamedInteger::new(b"STA", 0xf));
509 vmbs.add_object(&NamedInteger::new(b"_ADR", 0));
510 vmbs.add_object(&NamedString::new(b"_DDN", b"VMBUS"));
511 vmbs.add_object(&NamedString::new(b"_HID", b"VMBus"));
512 vmbs.add_object(&NamedInteger::new(b"_UID", 0));
513 let op = AndOp {
514 operand1: vec![b'S', b'T', b'A', b'_'],
515 operand2: encode_integer(13),
516 target_name: vec![b'S', b'T', b'A', b'_'],
517 };
518 let mut method = Method::new(b"_DIS");
519 method.add_operation(&op);
520 vmbs.add_object(&method);
521 let op = OrOp {
522 operand1: vec![b'S', b'T', b'A', b'_'],
523 operand2: encode_integer(15),
524 target_name: vec![b'S', b'T', b'A', b'_'],
525 };
526 let mut method = Method::new(b"_PS0");
527 method.add_operation(&op);
528 vmbs.add_object(&method);
529 let op = ReturnOp {
530 result: vec![b'S', b'T', b'A', b'_'],
531 };
532 let mut method = Method::new(b"_STA");
533 method.add_operation(&op);
534 vmbs.add_object(&method);
535 vmbs.add_object(&NamedInteger::new(b"_PS3", 0));
536 dsdt.add_object(&vmbs);
537
538 let mut rtc = Device::new(b"\\_SB.RTC0");
539 rtc.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0B00")));
540 rtc.add_object(&NamedInteger::new(b"_UID", 0));
541 let mut rtc_crs = CurrentResourceSettings::new();
542 let mut ioport = IoPort::new(0x70, 0x70, 2);
543 ioport.alignment = 0;
544 rtc_crs.add_resource(&ioport);
545 let mut intr = Interrupt::new(8);
546 intr.is_edge_triggered = true;
547 rtc_crs.add_resource(&intr);
548 rtc.add_object(&rtc_crs);
549 dsdt.add_object(&rtc);
550
551 for proc_index in 1..3 {
552 let mut proc = Device::new(format!("P{:03}", proc_index).as_bytes());
553 proc.add_object(&NamedString::new(b"_HID", b"ACPI0007"));
554 proc.add_object(&NamedInteger::new(b"_UID", proc_index as u64));
555 let mut method = Method::new(b"_STA");
556 method.add_operation(&ReturnOp {
557 result: encode_integer(0xf),
558 });
559 proc.add_object(&method);
560 dsdt.add_object(&proc);
561 }
562
563 let bytes = dsdt.to_bytes();
564 verify_header(&bytes);
565 verify_expected_bytes(
566 &bytes[36..],
567 &[
568 0x08, 0x5C, 0x5F, 0x53, 0x30, 0x5F, 0x12, 0x04, 0x02, 0x00, 0x00, 0x08, 0x5C, 0x5F,
569 0x53, 0x35, 0x5F, 0x12, 0x04, 0x02, 0x00, 0x00, 0x5B, 0x82, 0x38, 0x5C, 0x2E, 0x5F,
570 0x53, 0x42, 0x5F, 0x41, 0x50, 0x49, 0x43, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0C, 0x41,
571 0xD0, 0x00, 0x03, 0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x1D, 0x0A, 0x1A, 0x86, 0x09,
572 0x00, 0x01, 0x00, 0x00, 0xE0, 0xFE, 0x00, 0x10, 0x00, 0x00, 0x86, 0x09, 0x00, 0x01,
573 0x00, 0x00, 0xC0, 0xFE, 0x00, 0x10, 0x00, 0x00, 0x79, 0x00, 0x5B, 0x82, 0x43, 0x04,
574 0x5C, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x55, 0x41, 0x52, 0x31, 0x08, 0x5F, 0x48, 0x49,
575 0x44, 0x0C, 0x41, 0xD0, 0x05, 0x01, 0x08, 0x5F, 0x44, 0x44, 0x4E, 0x0D, 0x43, 0x4F,
576 0x4D, 0x31, 0x00, 0x08, 0x5F, 0x55, 0x49, 0x44, 0x01, 0x08, 0x5F, 0x43, 0x52, 0x53,
577 0x11, 0x16, 0x0A, 0x13, 0x47, 0x01, 0xF8, 0x03, 0xF8, 0x03, 0x01, 0x08, 0x89, 0x06,
578 0x00, 0x03, 0x01, 0x04, 0x00, 0x00, 0x00, 0x79, 0x00, 0x5B, 0x82, 0x4A, 0x05, 0x5C,
579 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x56, 0x4D, 0x4F, 0x44, 0x08, 0x5F, 0x48, 0x49, 0x44,
580 0x0D, 0x41, 0x43, 0x50, 0x49, 0x30, 0x30, 0x30, 0x34, 0x00, 0x08, 0x5F, 0x55, 0x49,
581 0x44, 0x00, 0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x33, 0x0A, 0x30, 0x8A, 0x2B, 0x00,
582 0x00, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
585 0x00, 0x79, 0x00, 0x5B, 0x82, 0x42, 0x07, 0x5C, 0x2F, 0x03, 0x5F, 0x53, 0x42, 0x5F,
586 0x56, 0x4D, 0x4F, 0x44, 0x56, 0x4D, 0x42, 0x53, 0x08, 0x53, 0x54, 0x41, 0x5F, 0x0A,
587 0x0F, 0x08, 0x5F, 0x41, 0x44, 0x52, 0x00, 0x08, 0x5F, 0x44, 0x44, 0x4E, 0x0D, 0x56,
588 0x4D, 0x42, 0x55, 0x53, 0x00, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0D, 0x56, 0x4D, 0x42,
589 0x75, 0x73, 0x00, 0x08, 0x5F, 0x55, 0x49, 0x44, 0x00, 0x14, 0x11, 0x5F, 0x44, 0x49,
590 0x53, 0x00, 0x7B, 0x53, 0x54, 0x41, 0x5F, 0x0A, 0x0D, 0x53, 0x54, 0x41, 0x5F, 0x14,
591 0x11, 0x5F, 0x50, 0x53, 0x30, 0x00, 0x7D, 0x53, 0x54, 0x41, 0x5F, 0x0A, 0x0F, 0x53,
592 0x54, 0x41, 0x5F, 0x14, 0x0B, 0x5F, 0x53, 0x54, 0x41, 0x00, 0xA4, 0x53, 0x54, 0x41,
593 0x5F, 0x08, 0x5F, 0x50, 0x53, 0x33, 0x00, 0x5B, 0x82, 0x37, 0x5C, 0x2E, 0x5F, 0x53,
594 0x42, 0x5F, 0x52, 0x54, 0x43, 0x30, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0,
595 0x0B, 0x00, 0x08, 0x5F, 0x55, 0x49, 0x44, 0x00, 0x08, 0x5F, 0x43, 0x52, 0x53, 0x11,
596 0x16, 0x0A, 0x13, 0x47, 0x01, 0x70, 0x00, 0x70, 0x00, 0x00, 0x02, 0x89, 0x06, 0x00,
597 0x03, 0x01, 0x08, 0x00, 0x00, 0x00, 0x79, 0x00, 0x5B, 0x82, 0x24, 0x50, 0x30, 0x30,
598 0x31, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0D, 0x41, 0x43, 0x50, 0x49, 0x30, 0x30, 0x30,
599 0x37, 0x00, 0x08, 0x5F, 0x55, 0x49, 0x44, 0x01, 0x14, 0x09, 0x5F, 0x53, 0x54, 0x41,
600 0x00, 0xA4, 0x0A, 0x0F, 0x5B, 0x82, 0x25, 0x50, 0x30, 0x30, 0x32, 0x08, 0x5F, 0x48,
601 0x49, 0x44, 0x0D, 0x41, 0x43, 0x50, 0x49, 0x30, 0x30, 0x30, 0x37, 0x00, 0x08, 0x5F,
602 0x55, 0x49, 0x44, 0x0A, 0x02, 0x14, 0x09, 0x5F, 0x53, 0x54, 0x41, 0x00, 0xA4, 0x0A,
603 0x0F,
604 ],
605 );
606 }
607}