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_mmio_module(&mut self, low: MemoryRange, high: MemoryRange) {
204 let mut vmod = Device::new(b"\\_SB.VMOD");
205 vmod.add_object(&NamedString::new(b"_HID", b"ACPI0004"));
206 vmod.add_object(&NamedInteger::new(b"_UID", 0));
207 let mut vmod_crs = CurrentResourceSettings::new();
208 vmod_crs.add_resource(&QwordMemory::new(low.start(), low.end() - low.start()));
209 vmod_crs.add_resource(&QwordMemory::new(high.start(), high.end() - high.start()));
210 vmod.add_object(&vmod_crs);
211 self.add_object(&vmod);
212 }
213
214 pub fn add_pci(
235 &mut self,
236 low: MemoryRange,
237 high: MemoryRange,
238 legacy_interrupts: &[((u8, Option<u8>), u32)],
240 ) {
241 let mut pci0 = Device::new(b"\\_SB.PCI0");
242 pci0.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0A03")));
243 let mut empty_os_method = Method::new(b"_OSC");
249 empty_os_method.set_arg_count(4);
250 empty_os_method.add_operation(&ReturnOp {
251 result: Buffer(0x10u64.to_le_bytes()).to_bytes(),
252 });
253 pci0.add_object(&empty_os_method);
254 let mut prt = PciRoutingTable::new();
255 for &((device, function), line) in legacy_interrupts {
256 prt.add_entry(PciRoutingTableEntry {
257 address: ((device as u32) << 16) | function.map(|x| x as u32).unwrap_or(0xffff),
258 pin: 0,
259 source: None,
260 source_index: line, });
262 }
263 pci0.add_object(&prt);
264 let mut crs = CurrentResourceSettings::new();
265 crs.add_resource(&BusNumber::new(0, 1));
266 crs.add_resource(&IoPort::new(0xcf8, 0xcf8, 8));
267 crs.add_resource(&QwordMemory::new(low.start(), low.end() - low.start()));
268 crs.add_resource(&QwordMemory::new(high.start(), high.end() - high.start()));
269 pci0.add_object(&crs);
270 self.add_object(&pci0);
271 }
272
273 pub fn add_vmbus(&mut self, in_pci: bool) {
297 let name = if in_pci {
298 b"\\_SB.PCI0.VMBS"
299 } else {
300 b"\\_SB.VMOD.VMBS"
301 };
302 let mut vmbs = Device::new(name);
303 vmbs.add_object(&NamedInteger::new(b"STA", 0xf));
304 vmbs.add_object(&NamedInteger::new(b"_ADR", 0));
305 vmbs.add_object(&NamedString::new(b"_DDN", b"VMBUS"));
306 vmbs.add_object(&NamedString::new(b"_HID", b"VMBus"));
307 vmbs.add_object(&NamedInteger::new(b"_UID", 0));
308 let op = AndOp {
309 operand1: b"STA_".to_vec(),
310 operand2: encode_integer(13),
311 target_name: b"STA_".to_vec(),
312 };
313 let mut method = Method::new(b"_DIS");
314 method.add_operation(&op);
315 vmbs.add_object(&method);
316 let op = OrOp {
317 operand1: b"STA_".to_vec(),
318 operand2: encode_integer(15),
319 target_name: b"STA_".to_vec(),
320 };
321 let mut method = Method::new(b"_PS0");
322 method.add_operation(&op);
323 vmbs.add_object(&method);
324 let op = ReturnOp {
325 result: b"STA_".to_vec(),
326 };
327 let mut method = Method::new(b"_STA");
328 method.add_operation(&op);
329 vmbs.add_object(&method);
330 vmbs.add_object(&NamedInteger::new(b"_PS3", 0));
331 vmbs.add_object(&CurrentResourceSettings::new());
333 self.add_object(&vmbs);
334 }
335
336 pub fn add_rtc(&mut self) {
350 let mut rtc = Device::new(b"\\_SB.RTC0");
351 rtc.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0B00")));
352 rtc.add_object(&NamedInteger::new(b"_UID", 0));
353 let mut rtc_crs = CurrentResourceSettings::new();
354 let mut ioport = IoPort::new(0x70, 0x70, 2);
355 ioport.alignment = 0;
356 rtc_crs.add_resource(&ioport);
357 let mut intr = Interrupt::new(8);
358 intr.is_edge_triggered = true;
359 rtc_crs.add_resource(&intr);
360 rtc.add_object(&rtc_crs);
361 self.add_object(&rtc);
362 }
363}
364
365#[cfg(test)]
366mod tests {
367 use super::*;
368 use crate::aml::test_helpers::verify_expected_bytes;
369
370 pub fn verify_header(bytes: &[u8]) {
371 assert!(bytes.len() >= 36);
372
373 assert_eq!(bytes[0], b'D');
375 assert_eq!(bytes[1], b'S');
376 assert_eq!(bytes[2], b'D');
377 assert_eq!(bytes[3], b'T');
378
379 let dsdt_len = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
381 assert_eq!(dsdt_len as usize, bytes.len());
382
383 assert_eq!(bytes[8], 2);
385
386 let mut checksum: u8 = 0;
388 for byte in bytes.iter() {
389 checksum = checksum.wrapping_add(*byte);
390 }
391 assert_eq!(checksum, 0);
392
393 assert_eq!(bytes[10], b'M');
395 assert_eq!(bytes[11], b'S');
396 assert_eq!(bytes[12], b'F');
397 assert_eq!(bytes[13], b'T');
398 assert_eq!(bytes[14], b'V');
399 assert_eq!(bytes[15], b'M');
400
401 assert_eq!(bytes[16], b'D');
403 assert_eq!(bytes[17], b'S');
404 assert_eq!(bytes[18], b'D');
405 assert_eq!(bytes[19], b'T');
406 assert_eq!(bytes[20], b'0');
407 assert_eq!(bytes[21], b'1');
408 assert_eq!(bytes[22], 0);
409 assert_eq!(bytes[23], 0);
410
411 let oem_revision = u32::from_le_bytes(bytes[24..28].try_into().unwrap());
413 assert_eq!(oem_revision, 1);
414
415 assert_eq!(bytes[28], b'M');
417 assert_eq!(bytes[29], b'S');
418 assert_eq!(bytes[30], b'F');
419 assert_eq!(bytes[31], b'T');
420
421 let creator_rev = u32::from_le_bytes(bytes[32..36].try_into().unwrap());
423 assert_eq!(creator_rev, 0x5000000);
424 }
425
426 #[test]
427 fn verify_simple_table() {
428 let mut dsdt = Dsdt::new();
429 let nobj = NamedObject::new(b"_S0", &Package(vec![0, 0]));
430 dsdt.add_object(&nobj);
431 let bytes = dsdt.to_bytes();
432 verify_header(&bytes);
433 verify_expected_bytes(&bytes[36..], &[8, b'_', b'S', b'0', b'_', 0x12, 4, 2, 0, 0]);
434 }
435
436 #[test]
437 fn verify_table() {
438 let mut dsdt = Dsdt::new();
439 dsdt.add_object(&NamedObject::new(b"\\_S0", &Package(vec![0, 0])));
440 dsdt.add_object(&NamedObject::new(b"\\_S5", &Package(vec![0, 0])));
441
442 let mut apic = Device::new(b"\\_SB.APIC");
443 apic.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0003")));
444 let mut apic_crs = CurrentResourceSettings::new();
445 apic_crs.add_resource(&Memory32Fixed::new(0xfee00000, 0x1000, true));
446 apic_crs.add_resource(&Memory32Fixed::new(0xfec00000, 0x1000, true));
447 apic.add_object(&apic_crs);
448 dsdt.add_object(&apic);
449
450 let mut uart = Device::new(b"\\_SB.UAR1");
451 uart.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0501")));
452 uart.add_object(&NamedString::new(b"_DDN", b"COM1"));
453 uart.add_object(&NamedInteger::new(b"_UID", 1));
454 let mut uart_crs = CurrentResourceSettings::new();
455 uart_crs.add_resource(&IoPort::new(0x3f8, 0x3f8, 8));
456 let mut intr = Interrupt::new(4);
457 intr.is_edge_triggered = true;
458 uart_crs.add_resource(&intr);
459 uart.add_object(&uart_crs);
460 dsdt.add_object(&uart);
461
462 let mut vmod = Device::new(b"\\_SB.VMOD");
463 vmod.add_object(&NamedString::new(b"_HID", b"ACPI0004"));
464 vmod.add_object(&NamedInteger::new(b"_UID", 0));
465 let mut vmod_crs = CurrentResourceSettings::new();
466 vmod_crs.add_resource(&QwordMemory::new(0x100000000, 0x100000000));
467 vmod.add_object(&vmod_crs);
468 dsdt.add_object(&vmod);
469
470 let mut vmbs = Device::new(b"\\_SB.VMOD.VMBS");
471 vmbs.add_object(&NamedInteger::new(b"STA", 0xf));
472 vmbs.add_object(&NamedInteger::new(b"_ADR", 0));
473 vmbs.add_object(&NamedString::new(b"_DDN", b"VMBUS"));
474 vmbs.add_object(&NamedString::new(b"_HID", b"VMBus"));
475 vmbs.add_object(&NamedInteger::new(b"_UID", 0));
476 let op = AndOp {
477 operand1: vec![b'S', b'T', b'A', b'_'],
478 operand2: encode_integer(13),
479 target_name: vec![b'S', b'T', b'A', b'_'],
480 };
481 let mut method = Method::new(b"_DIS");
482 method.add_operation(&op);
483 vmbs.add_object(&method);
484 let op = OrOp {
485 operand1: vec![b'S', b'T', b'A', b'_'],
486 operand2: encode_integer(15),
487 target_name: vec![b'S', b'T', b'A', b'_'],
488 };
489 let mut method = Method::new(b"_PS0");
490 method.add_operation(&op);
491 vmbs.add_object(&method);
492 let op = ReturnOp {
493 result: vec![b'S', b'T', b'A', b'_'],
494 };
495 let mut method = Method::new(b"_STA");
496 method.add_operation(&op);
497 vmbs.add_object(&method);
498 vmbs.add_object(&NamedInteger::new(b"_PS3", 0));
499 dsdt.add_object(&vmbs);
500
501 let mut rtc = Device::new(b"\\_SB.RTC0");
502 rtc.add_object(&NamedObject::new(b"_HID", &EisaId(*b"PNP0B00")));
503 rtc.add_object(&NamedInteger::new(b"_UID", 0));
504 let mut rtc_crs = CurrentResourceSettings::new();
505 let mut ioport = IoPort::new(0x70, 0x70, 2);
506 ioport.alignment = 0;
507 rtc_crs.add_resource(&ioport);
508 let mut intr = Interrupt::new(8);
509 intr.is_edge_triggered = true;
510 rtc_crs.add_resource(&intr);
511 rtc.add_object(&rtc_crs);
512 dsdt.add_object(&rtc);
513
514 for proc_index in 1..3 {
515 let mut proc = Device::new(format!("P{:03}", proc_index).as_bytes());
516 proc.add_object(&NamedString::new(b"_HID", b"ACPI0007"));
517 proc.add_object(&NamedInteger::new(b"_UID", proc_index as u64));
518 let mut method = Method::new(b"_STA");
519 method.add_operation(&ReturnOp {
520 result: encode_integer(0xf),
521 });
522 proc.add_object(&method);
523 dsdt.add_object(&proc);
524 }
525
526 let bytes = dsdt.to_bytes();
527 verify_header(&bytes);
528 verify_expected_bytes(
529 &bytes[36..],
530 &[
531 0x08, 0x5C, 0x5F, 0x53, 0x30, 0x5F, 0x12, 0x04, 0x02, 0x00, 0x00, 0x08, 0x5C, 0x5F,
532 0x53, 0x35, 0x5F, 0x12, 0x04, 0x02, 0x00, 0x00, 0x5B, 0x82, 0x38, 0x5C, 0x2E, 0x5F,
533 0x53, 0x42, 0x5F, 0x41, 0x50, 0x49, 0x43, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0C, 0x41,
534 0xD0, 0x00, 0x03, 0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x1D, 0x0A, 0x1A, 0x86, 0x09,
535 0x00, 0x01, 0x00, 0x00, 0xE0, 0xFE, 0x00, 0x10, 0x00, 0x00, 0x86, 0x09, 0x00, 0x01,
536 0x00, 0x00, 0xC0, 0xFE, 0x00, 0x10, 0x00, 0x00, 0x79, 0x00, 0x5B, 0x82, 0x43, 0x04,
537 0x5C, 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x55, 0x41, 0x52, 0x31, 0x08, 0x5F, 0x48, 0x49,
538 0x44, 0x0C, 0x41, 0xD0, 0x05, 0x01, 0x08, 0x5F, 0x44, 0x44, 0x4E, 0x0D, 0x43, 0x4F,
539 0x4D, 0x31, 0x00, 0x08, 0x5F, 0x55, 0x49, 0x44, 0x01, 0x08, 0x5F, 0x43, 0x52, 0x53,
540 0x11, 0x16, 0x0A, 0x13, 0x47, 0x01, 0xF8, 0x03, 0xF8, 0x03, 0x01, 0x08, 0x89, 0x06,
541 0x00, 0x03, 0x01, 0x04, 0x00, 0x00, 0x00, 0x79, 0x00, 0x5B, 0x82, 0x4A, 0x05, 0x5C,
542 0x2E, 0x5F, 0x53, 0x42, 0x5F, 0x56, 0x4D, 0x4F, 0x44, 0x08, 0x5F, 0x48, 0x49, 0x44,
543 0x0D, 0x41, 0x43, 0x50, 0x49, 0x30, 0x30, 0x30, 0x34, 0x00, 0x08, 0x5F, 0x55, 0x49,
544 0x44, 0x00, 0x08, 0x5F, 0x43, 0x52, 0x53, 0x11, 0x33, 0x0A, 0x30, 0x8A, 0x2B, 0x00,
545 0x00, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
546 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00,
547 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
548 0x00, 0x79, 0x00, 0x5B, 0x82, 0x42, 0x07, 0x5C, 0x2F, 0x03, 0x5F, 0x53, 0x42, 0x5F,
549 0x56, 0x4D, 0x4F, 0x44, 0x56, 0x4D, 0x42, 0x53, 0x08, 0x53, 0x54, 0x41, 0x5F, 0x0A,
550 0x0F, 0x08, 0x5F, 0x41, 0x44, 0x52, 0x00, 0x08, 0x5F, 0x44, 0x44, 0x4E, 0x0D, 0x56,
551 0x4D, 0x42, 0x55, 0x53, 0x00, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0D, 0x56, 0x4D, 0x42,
552 0x75, 0x73, 0x00, 0x08, 0x5F, 0x55, 0x49, 0x44, 0x00, 0x14, 0x11, 0x5F, 0x44, 0x49,
553 0x53, 0x00, 0x7B, 0x53, 0x54, 0x41, 0x5F, 0x0A, 0x0D, 0x53, 0x54, 0x41, 0x5F, 0x14,
554 0x11, 0x5F, 0x50, 0x53, 0x30, 0x00, 0x7D, 0x53, 0x54, 0x41, 0x5F, 0x0A, 0x0F, 0x53,
555 0x54, 0x41, 0x5F, 0x14, 0x0B, 0x5F, 0x53, 0x54, 0x41, 0x00, 0xA4, 0x53, 0x54, 0x41,
556 0x5F, 0x08, 0x5F, 0x50, 0x53, 0x33, 0x00, 0x5B, 0x82, 0x37, 0x5C, 0x2E, 0x5F, 0x53,
557 0x42, 0x5F, 0x52, 0x54, 0x43, 0x30, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0C, 0x41, 0xD0,
558 0x0B, 0x00, 0x08, 0x5F, 0x55, 0x49, 0x44, 0x00, 0x08, 0x5F, 0x43, 0x52, 0x53, 0x11,
559 0x16, 0x0A, 0x13, 0x47, 0x01, 0x70, 0x00, 0x70, 0x00, 0x00, 0x02, 0x89, 0x06, 0x00,
560 0x03, 0x01, 0x08, 0x00, 0x00, 0x00, 0x79, 0x00, 0x5B, 0x82, 0x24, 0x50, 0x30, 0x30,
561 0x31, 0x08, 0x5F, 0x48, 0x49, 0x44, 0x0D, 0x41, 0x43, 0x50, 0x49, 0x30, 0x30, 0x30,
562 0x37, 0x00, 0x08, 0x5F, 0x55, 0x49, 0x44, 0x01, 0x14, 0x09, 0x5F, 0x53, 0x54, 0x41,
563 0x00, 0xA4, 0x0A, 0x0F, 0x5B, 0x82, 0x25, 0x50, 0x30, 0x30, 0x32, 0x08, 0x5F, 0x48,
564 0x49, 0x44, 0x0D, 0x41, 0x43, 0x50, 0x49, 0x30, 0x30, 0x30, 0x37, 0x00, 0x08, 0x5F,
565 0x55, 0x49, 0x44, 0x0A, 0x02, 0x14, 0x09, 0x5F, 0x53, 0x54, 0x41, 0x00, 0xA4, 0x0A,
566 0x0F,
567 ],
568 );
569 }
570}