acpi/
dsdt.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4pub 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, // placeholder, filled in during serialization to bytes
17    pub revision: u8,
18    _checksum: u8, // placeholder, filled in during serialization to bytes
19    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, // b'DSDT01'
99                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    /// Add an APIC device to the DSDT with the following ASL code:
128    /// ```text
129    /// Device(\_SB.APIC)
130    /// {
131    ///     Name(_HID, EISAID("PNP0003"))
132    ///     Name(_CRS,
133    ///         ResourceTemplate()
134    ///         {
135    ///             Memory32Fixed(ReadWrite, 0xfee00000, 0x1000)
136    ///             Memory32Fixed(ReadWrite, 0xfec00000, 0x1000)
137    ///         })
138    /// }
139    /// ```
140    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    /// Add a 16650A compatible UART to the DSDT with the following ASL code:
151    /// ```text
152    /// Device(<name>)
153    /// {
154    ///     Name(_HID, EISAID("PNP0501")) // 16550A-compatible COM port
155    ///     Name(_DDN, <ddn>)
156    ///     Name(_UID, <uid>)
157    ///     Name(_CRS, ResourceTemplate()
158    ///     {
159    ///         IO(Decode16, <io_base>, <io_base>, 1, 8)
160    ///         Interrupt(ResourceConsumer, Edge, ActiveHigh, Exclusive)
161    ///             {<irq>}
162    ///     })
163    /// }
164    /// ```
165    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    /// Add an ARM SBSA Generic UART to the DSDT for ACPI-based boot.
180    ///
181    /// ```text
182    /// Device(<name>)
183    /// {
184    ///     Name(_HID, "ARMH0011")
185    ///     Name(_UID, <uid>)
186    ///     Name(_CRS, ResourceTemplate()
187    ///     {
188    ///         QWORDMemory(..., <base_addr>, <size>)
189    ///         Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive)
190    ///             {<gsiv>}
191    ///     })
192    /// }
193    /// ```
194    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; // level-triggered
202        crs.add_resource(&intr);
203        uart.add_object(&crs);
204        self.add_object(&uart);
205    }
206
207    /// Add an ACPI module device to describe the low and high MMIO regions.
208    /// This is used when PCI is not present so that VMBus can find MMIO space.
209    ///
210    /// ```text
211    /// Device(\_SB.VMOD)
212    /// {
213    ///     Name(_HID, "ACPI0004")
214    ///     Name(_UID, 0)
215    ///     Name(_CRS, ResourceTemplate()
216    ///     {
217    ///         // Low gap
218    ///         QWORDMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
219    ///         // Granularity Min          Max T       Translation Range (Length = Max-Min+1)
220    ///             0,         <low_min>,   <low_max>,  0,          <dynamic>,,,
221    ///             MEM6)   // Name declaration for this descriptor
222    ///
223    ///         // High gap
224    ///         QWORDMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
225    ///         // Granularity Min          Max T       Translation Range (Length = Max-Min+1)
226    ///             0,         <high_min>,  <high_max>, 0,          <dynamic>,,,
227    ///             MEM6)   // Name declaration for this descriptor
228    ///     })
229    /// }
230    /// ```
231    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    /// Adds a PCI bus with the specified MMIO ranges.
243    ///
244    /// ```text
245    /// Device(\_SB.PCI0)
246    /// {
247    ///     Name(_HID, PNP0A03)
248    ///     Name(_CRS, ResourceTemplate()
249    ///     {
250    ///         WordBusNumber(...) // Bus translation info
251    ///         IO(Decode16, 0xcf8, 0xcf8) // IO port
252    ///         QWordMemory() // Low gap
253    ///         QWordMemory() // High gap
254    ///     })
255    ///     // PCI routing table
256    ///     Name(_PRT, Package{
257    ///         Package{<address>, <PCI pin>, 0, <interrupt>},
258    ///         ...
259    ///     })
260    /// }
261    /// ```
262    pub fn add_pci(
263        &mut self,
264        low: MemoryRange,
265        high: MemoryRange,
266        // array of ((device, function), line)
267        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        // FUTURE: when implementing PCIe, switch _HID over to "PNP0A08", and a
272        // _CID for "PNP0A03"
273
274        // OS negotiation for control of the bus. See https://uefi.org/specs/ACPI/6.4/06_Device_Configuration/Device_Configuration.html#osc-operating-system-capabilities
275        // TODO: Lots of work needed for _OSC.
276        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, // Interrupt line
289            });
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    /// Add a VMBUS device to the DSDT.
302    ///
303    /// If `in_pci`, then enumerate the device under PCI0. Otherwise, enumerate
304    /// it under the VMOD module created by `add_mmio_module`.
305    ///
306    /// If `interrupt` is provided, it is added as an Extended Interrupt resource
307    /// in `_CRS`. On ARM64 ACPI, the kernel reads the VMBus interrupt from this.
308    ///
309    /// ```text
310    /// Device(\_SB.VMOD.VMBS)
311    /// {
312    ///     Name(STA, 0xF)
313    ///     Name(_ADR, 0x00)
314    ///     Name(_DDN, "VMBUS")
315    ///     Name(_HID, "VMBus")
316    ///     Name(_UID, 0)
317    ///     Method(_DIS, 0) { And(STA, 0xD, STA) }
318    ///     Method(_PS0, 0) { Or(STA, 0xF, STA) }
319    ///     Method(_STA, 0)
320    ///     {
321    ///         return(STA)
322    ///     }
323    ///
324    ///     Name(_PS3, 0)
325    ///     Name(_CRS, ResourceTemplate() { ... })
326    /// }
327    /// ```
328    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    /// Add an RTC device with the following ASL code:
374    /// ```text
375    /// Device(\_SB.RTC0)
376    /// {
377    ///     Name(_HID, EISAID("PNP0B00")) // AT real-time clock
378    ///     Name(_UID, 0)
379    ///     Name(_CRS, ResourceTemplate()
380    ///     {
381    ///         IO(Decode16, 0x70, 0x70, 0, 0x2)
382    ///         Interrupt(ResourceConsumer, Edge, ActiveHigh, Exclusive) {8}
383    ///     })
384    /// }
385    /// ```
386    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        // signature
411        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        // length
417        let dsdt_len = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
418        assert_eq!(dsdt_len as usize, bytes.len());
419
420        // revision
421        assert_eq!(bytes[8], 2);
422
423        // Validate checksum bytes[9] by verifying content adds to zero.
424        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        // oem_id
431        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        // oem_table_id
439        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        // oem_revision
449        let oem_revision = u32::from_le_bytes(bytes[24..28].try_into().unwrap());
450        assert_eq!(oem_revision, 1);
451
452        // creator_id
453        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        // creator_rev
459        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}