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 ACPI module device to describe the low and high MMIO regions.
180    /// This is used when PCI is not present so that VMBus can find MMIO space.
181    ///
182    /// ```text
183    /// Device(\_SB.VMOD)
184    /// {
185    ///     Name(_HID, "ACPI0004")
186    ///     Name(_UID, 0)
187    ///     Name(_CRS, ResourceTemplate()
188    ///     {
189    ///         // Low gap
190    ///         QWORDMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
191    ///         // Granularity Min          Max T       Translation Range (Length = Max-Min+1)
192    ///             0,         <low_min>,   <low_max>,  0,          <dynamic>,,,
193    ///             MEM6)   // Name declaration for this descriptor
194    ///
195    ///         // High gap
196    ///         QWORDMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
197    ///         // Granularity Min          Max T       Translation Range (Length = Max-Min+1)
198    ///             0,         <high_min>,  <high_max>, 0,          <dynamic>,,,
199    ///             MEM6)   // Name declaration for this descriptor
200    ///     })
201    /// }
202    /// ```
203    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    /// Adds a PCI bus with the specified MMIO ranges.
215    ///
216    /// ```text
217    /// Device(\_SB.PCI0)
218    /// {
219    ///     Name(_HID, PNP0A03)
220    ///     Name(_CRS, ResourceTemplate()
221    ///     {
222    ///         WordBusNumber(...) // Bus translation info
223    ///         IO(Decode16, 0xcf8, 0xcf8) // IO port
224    ///         QWordMemory() // Low gap
225    ///         QWordMemory() // High gap
226    ///     })
227    ///     // PCI routing table
228    ///     Name(_PRT, Package{
229    ///         Package{<address>, <PCI pin>, 0, <interrupt>},
230    ///         ...
231    ///     })
232    /// }
233    /// ```
234    pub fn add_pci(
235        &mut self,
236        low: MemoryRange,
237        high: MemoryRange,
238        // array of ((device, function), line)
239        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        // FUTURE: when implementing PCIe, switch _HID over to "PNP0A08", and a
244        // _CID for "PNP0A03"
245
246        // 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
247        // TODO: Lots of work needed for _OSC.
248        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, // Interrupt line
261            });
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    /// Add a VMBUS device to the DSDT.
274    ///
275    /// If `in_pci`, then enumerate the device under PCI0. Otherwise, enumerate
276    /// it under the VMOD module created by `add_mmio_module`.
277    ///
278    /// ```text
279    /// Device(\_SB.VMOD.VMBS)
280    /// {
281    ///     Name(STA, 0xF)
282    ///     Name(_ADR, 0x00)
283    ///     Name(_DDN, "VMBUS")
284    ///     Name(_HID, "VMBus")
285    ///     Name(_UID, 0)
286    ///     Method(_DIS, 0) { And(STA, 0xD, STA) }
287    ///     Method(_PS0, 0) { Or(STA, 0xF, STA) }
288    ///     Method(_STA, 0)
289    ///     {
290    ///         return(STA)
291    ///     }
292    ///
293    ///     Name(_PS3, 0)
294    /// }
295    /// ```
296    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        // On linux, the vmbus driver will fail if the _CRS section is not present.
332        vmbs.add_object(&CurrentResourceSettings::new());
333        self.add_object(&vmbs);
334    }
335
336    /// Add an RTC device with the following ASL code:
337    /// ```text
338    /// Device(\_SB.RTC0)
339    /// {
340    ///     Name(_HID, EISAID("PNP0B00")) // AT real-time clock
341    ///     Name(_UID, 0)
342    ///     Name(_CRS, ResourceTemplate()
343    ///     {
344    ///         IO(Decode16, 0x70, 0x70, 0, 0x2)
345    ///         Interrupt(ResourceConsumer, Edge, ActiveHigh, Exclusive) {8}
346    ///     })
347    /// }
348    /// ```
349    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        // signature
374        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        // length
380        let dsdt_len = u32::from_le_bytes(bytes[4..8].try_into().unwrap());
381        assert_eq!(dsdt_len as usize, bytes.len());
382
383        // revision
384        assert_eq!(bytes[8], 2);
385
386        // Validate checksum bytes[9] by verifying content adds to zero.
387        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        // oem_id
394        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        // oem_table_id
402        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        // oem_revision
412        let oem_revision = u32::from_le_bytes(bytes[24..28].try_into().unwrap());
413        assert_eq!(oem_revision, 1);
414
415        // creator_id
416        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        // creator_rev
422        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}