Skip to main content

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        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    /// Adds a PCI bus with the specified MMIO ranges.
247    ///
248    /// ```text
249    /// Device(\_SB.PCI0)
250    /// {
251    ///     Name(_HID, PNP0A03)
252    ///     Name(_CRS, ResourceTemplate()
253    ///     {
254    ///         WordBusNumber(...) // Bus translation info
255    ///         IO(Decode16, 0xcf8, 0xcf8) // IO port
256    ///         QWordMemory() // Low gap
257    ///         QWordMemory() // High gap
258    ///     })
259    ///     // PCI routing table
260    ///     Name(_PRT, Package{
261    ///         Package{<address>, <PCI pin>, 0, <interrupt>},
262    ///         ...
263    ///     })
264    /// }
265    /// ```
266    pub fn add_pci(
267        &mut self,
268        low: MemoryRange,
269        high: MemoryRange,
270        // array of ((device, function), line)
271        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        // FUTURE: when implementing PCIe, switch _HID over to "PNP0A08", and a
276        // _CID for "PNP0A03"
277
278        // 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
279        // TODO: Lots of work needed for _OSC.
280        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, // Interrupt line
293            });
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    /// Add a VMBUS device to the DSDT.
308    ///
309    /// If `in_pci`, then enumerate the device under PCI0. Otherwise, enumerate
310    /// it under the VMOD module created by `add_mmio_module`.
311    ///
312    /// If `interrupt` is provided, it is added as an Extended Interrupt resource
313    /// in `_CRS`. On ARM64 ACPI, the kernel reads the VMBus interrupt from this.
314    ///
315    /// ```text
316    /// Device(\_SB.VMOD.VMBS)
317    /// {
318    ///     Name(STA, 0xF)
319    ///     Name(_ADR, 0x00)
320    ///     Name(_DDN, "VMBUS")
321    ///     Name(_HID, "VMBus")
322    ///     Name(_UID, 0)
323    ///     Method(_DIS, 0) { And(STA, 0xD, STA) }
324    ///     Method(_PS0, 0) { Or(STA, 0xF, STA) }
325    ///     Method(_STA, 0)
326    ///     {
327    ///         return(STA)
328    ///     }
329    ///
330    ///     Name(_PS3, 0)
331    ///     Name(_CRS, ResourceTemplate() { ... })
332    /// }
333    /// ```
334    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    /// Add an RTC device with the following ASL code:
380    /// ```text
381    /// Device(\_SB.RTC0)
382    /// {
383    ///     Name(_HID, EISAID("PNP0B00")) // AT real-time clock
384    ///     Name(_UID, 0)
385    ///     Name(_CRS, ResourceTemplate()
386    ///     {
387    ///         IO(Decode16, 0x70, 0x70, 0, 0x2)
388    ///         Interrupt(ResourceConsumer, Edge, ActiveHigh, Exclusive) {8}
389    ///     })
390    /// }
391    /// ```
392    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        // signature
417        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        // length
423        let dsdt_len = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
424        assert_eq!(dsdt_len as usize, bytes.len());
425
426        // revision
427        assert_eq!(bytes[8], 2);
428
429        // Validate checksum bytes[9] by verifying content adds to zero.
430        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        // oem_id
437        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        // oem_table_id
445        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        // oem_revision
455        let oem_revision = u32::from_le_bytes(bytes[24..28].try_into().unwrap());
456        assert_eq!(oem_revision, 1);
457
458        // creator_id
459        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        // creator_rev
465        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}