VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/SystemTableBuilder.cpp@ 109112

Last change on this file since 109112 was 109112, checked in by vboxsync, 7 days ago

Main: bugref:10877 Expose an I/O remapping table with ITS and PCI root complex nodes to allow guests to potentially configure and use MBIs (message-based interrupts).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 64.1 KB
Line 
1/* $Id: SystemTableBuilder.cpp 109112 2025-04-30 07:02:09Z vboxsync $ */
2/** @file
3 * VirtualBox bus slots assignment manager
4 */
5
6/*
7 * Copyright (C) 2010-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_MAIN
33#include "LoggingNew.h"
34
35#include "SystemTableBuilder.h"
36
37#include <VBox/gic.h>
38
39#include <iprt/asm.h>
40#include <iprt/string.h>
41
42
43/*********************************************************************************************************************************
44* Defined Constants And Macros *
45*********************************************************************************************************************************/
46
47/** Locality CRB request register. */
48#define TPM_CRB_LOCALITY_REG_CTRL_REQ 0x40
49
50
51/*********************************************************************************************************************************
52* Structures and Typedefs *
53*********************************************************************************************************************************/
54/**
55 * A system table device.
56 */
57typedef struct SYSTEMTABLEDEVICE
58{
59 const char *pszVBoxName;
60 const char *pszFdtName;
61 const char *pszFdtCompatible;
62 const char *pszAcpiName;
63 const char *pszAcpiHid;
64 bool fEisaId;
65} SYSTEMTABLEDEVICE;
66typedef SYSTEMTABLEDEVICE *PSYSTEMTABLEDEVICE;
67typedef const SYSTEMTABLEDEVICE *PCSYSTEMTABLEDEVICE;
68
69
70/*********************************************************************************************************************************
71* Global Variables *
72*********************************************************************************************************************************/
73static const SYSTEMTABLEDEVICE g_aSysTblDevices[] =
74{
75 { "qemu-fw-cfg", "fw-cfg", "qemu,fw-cfg-mmio", "FWC", "QEMU0002", false },
76 { "arm-pl011", "pl011", "arm,pl011", "SRL", "ARMH0011", false },
77 { "arm-pl061-gpio", "pl061", "arm,pl061", "GPI", "ARMH0061", false },
78 { "pci-generic-ecam", "pcie", "pci-host-ecam-generic", "PCI", "PNP0A08", true },
79};
80
81
82static PCSYSTEMTABLEDEVICE systemTableVBoxDevName2SysTblDevice(const char *pszVBoxName)
83{
84 for (uint32_t i = 0; i < RT_ELEMENTS(g_aSysTblDevices); i++)
85 if (!strcmp(pszVBoxName, g_aSysTblDevices[i].pszVBoxName))
86 return &g_aSysTblDevices[i];
87
88 return NULL;
89}
90
91
92static int systemTableAcpiMmioDevResource(RTACPITBL hDsdt, RTACPIRES hAcpiRes, uint64_t u64AddrBase,
93 uint64_t cbMmio, uint32_t uIrq)
94{
95 uint32_t const fAddrSpace = RTACPI_RESOURCE_ADDR_RANGE_F_DECODE_TYPE_POS
96 | RTACPI_RESOURCE_ADDR_RANGE_F_MIN_ADDR_FIXED
97 | RTACPI_RESOURCE_ADDR_RANGE_F_MAX_ADDR_FIXED
98 | RTACPI_RESOURCE_ADDR_RANGE_F_PRODUCER;
99
100 RTAcpiResourceReset(hAcpiRes);
101 int vrc;
102 if (u64AddrBase + cbMmio <= _4G)
103 vrc = RTAcpiResourceAdd32BitFixedMemoryRange(hAcpiRes, u64AddrBase, cbMmio, true /*fRw*/);
104 else
105 vrc = RTAcpiResourceAddQWordMemoryRange(hAcpiRes, kAcpiResMemRangeCacheability_NonCacheable, kAcpiResMemType_Memory, true /*fRw*/,
106 fAddrSpace, u64AddrBase, u64AddrBase + cbMmio - 1, 0 /*u64OffTrans*/, 0 /*u64Granularity*/,
107 cbMmio);
108 if (RT_SUCCESS(vrc))
109 vrc = RTAcpiResourceAddExtendedInterrupt(hAcpiRes, true /*fConsumer*/, false /*fEdgeTriggered*/, false /*fActiveLow*/,
110 false /*fShared*/, false /*fWakeCapable*/, 1, &uIrq);
111 if (RT_SUCCESS(vrc))
112 {
113 vrc = RTAcpiResourceSeal(hAcpiRes);
114 if (RT_SUCCESS(vrc))
115 vrc = RTAcpiTblResourceAppend(hDsdt, hAcpiRes);
116 }
117
118 return vrc;
119}
120
121
122static int systemTableAcpiMmioDevResourceNoIrq(RTACPITBL hDsdt, RTACPIRES hAcpiRes, uint64_t u64AddrBase,
123 uint64_t cbMmio)
124{
125 uint32_t const fAddrSpace = RTACPI_RESOURCE_ADDR_RANGE_F_DECODE_TYPE_POS
126 | RTACPI_RESOURCE_ADDR_RANGE_F_MIN_ADDR_FIXED
127 | RTACPI_RESOURCE_ADDR_RANGE_F_MAX_ADDR_FIXED
128 | RTACPI_RESOURCE_ADDR_RANGE_F_PRODUCER;
129
130 RTAcpiResourceReset(hAcpiRes);
131 int vrc = RTAcpiResourceAddQWordMemoryRange(hAcpiRes, kAcpiResMemRangeCacheability_NonCacheable, kAcpiResMemType_Memory, true /*fRw*/,
132 fAddrSpace, u64AddrBase, u64AddrBase + cbMmio - 1, 0 /*u64OffTrans*/, 0 /*u64Granularity*/,
133 cbMmio);
134 if (RT_SUCCESS(vrc))
135 {
136 vrc = RTAcpiResourceSeal(hAcpiRes);
137 if (RT_SUCCESS(vrc))
138 vrc = RTAcpiTblResourceAppend(hDsdt, hAcpiRes);
139 }
140
141 return vrc;
142}
143
144
145int SystemTableBuilderAcpi::initInstance(void)
146{
147 m_fTpm20 = false;
148
149 int vrc = RTAcpiTblCreate(&m_hAcpiDsdt, ACPI_TABLE_HDR_SIGNATURE_DSDT, 6, "ORCL ", "VBOXDSDT", 1, "VBOX", 1);
150 AssertRCReturn(vrc, vrc);
151
152 vrc = RTAcpiResourceCreate(&m_hAcpiRes);
153 AssertRCReturn(vrc, vrc);
154
155 /* Append _SB Scope. */
156 return RTAcpiTblScopeStart(m_hAcpiDsdt, "\\_SB");
157}
158
159
160int SystemTableBuilderAcpi::finishTables(RTGCPHYS GCPhysTblsStart, RTVFSIOSTREAM hVfsIos,
161 PRTGCPHYS pGCPhysTblRoot, size_t *pcbTblRoot, size_t *pcbTbls)
162{
163 int vrc = RTAcpiTblScopeFinalize(m_hAcpiDsdt); /* End \_SB scope */
164 AssertRCReturn(vrc, vrc);
165
166 vrc = RTAcpiTblFinalize(m_hAcpiDsdt);
167 AssertRCReturn(vrc, vrc);
168
169 RTGCPHYS GCPhysDsdt = GCPhysTblsStart;
170
171 size_t cbAcpiTbls = RTAcpiTblGetSize(m_hAcpiDsdt);
172 Assert(cbAcpiTbls);
173
174 /* Write the DSDT. */
175 vrc = RTAcpiTblDumpToVfsIoStrm(m_hAcpiDsdt, RTACPITBLTYPE_AML, hVfsIos);
176 AssertRCReturn(vrc, vrc);
177
178 GCPhysTblsStart += cbAcpiTbls;
179
180 uint32_t cTbls = 0;
181 uint8_t abXsdt[36 + 32 * sizeof(uint64_t)]; RT_ZERO(abXsdt);
182 PACPIXSDT pXsdt = (PACPIXSDT)&abXsdt[0];
183
184 /* Build the FADT. */
185 size_t cbTbl = 0;
186 vrc = buildFadt(hVfsIos, GCPhysDsdt, &cbTbl);
187 AssertRCReturn(vrc, vrc);
188
189 pXsdt->au64AddrTbl[cTbls++] = GCPhysTblsStart;
190 cbAcpiTbls += cbTbl;
191 GCPhysTblsStart += cbTbl;
192
193 /* Build the GTDT. */
194 vrc = buildGtdt(hVfsIos, &cbTbl);
195 AssertRCReturn(vrc, vrc);
196
197 pXsdt->au64AddrTbl[cTbls++] = GCPhysTblsStart;
198 cbAcpiTbls += cbTbl;
199 GCPhysTblsStart += cbTbl;
200
201 /* Build the MADT. */
202 vrc = buildMadt(hVfsIos, &cbTbl);
203 AssertRCReturn(vrc, vrc);
204
205 pXsdt->au64AddrTbl[cTbls++] = GCPhysTblsStart;
206 cbAcpiTbls += cbTbl;
207 GCPhysTblsStart += cbTbl;
208
209 /* Build the MCFG. */
210 vrc = buildMcfg(hVfsIos, &cbTbl);
211 AssertRCReturn(vrc, vrc);
212
213 pXsdt->au64AddrTbl[cTbls++] = GCPhysTblsStart;
214 cbAcpiTbls += cbTbl;
215 GCPhysTblsStart += cbTbl;
216
217 /* Build TPM2 table if configured. */
218 if (m_fTpm20)
219 {
220 vrc = buildTpm20(hVfsIos, &cbTbl);
221 AssertRCReturn(vrc, vrc);
222
223 pXsdt->au64AddrTbl[cTbls++] = GCPhysTblsStart;
224 cbAcpiTbls += cbTbl;
225 GCPhysTblsStart += cbTbl;
226 }
227
228 /* Build the IORT if an ITS is configured. */
229 if (m_GCPhysIntcIts)
230 {
231 Assert(m_cbMmioIntcIts > 0);
232 Assert(m_GCPhysIntcIts != NIL_RTGCPHYS);
233 vrc = buildIort(hVfsIos, &cbTbl);
234 AssertRCReturn(vrc, vrc);
235
236 pXsdt->au64AddrTbl[cTbls++] = GCPhysTblsStart;
237 cbAcpiTbls += cbTbl;
238 GCPhysTblsStart += cbTbl;
239 }
240
241 /* Build XSDT. */
242 RTGCPHYS GCPhysXsdt = GCPhysTblsStart;
243 size_t const cbXsdt = RT_UOFFSETOF_DYN(ACPIXSDT, au64AddrTbl[cTbls]);
244 pXsdt->Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_XSDT;
245 pXsdt->Hdr.cbTbl = RT_UOFFSETOF_DYN(ACPIXSDT, au64AddrTbl[cTbls]);
246 pXsdt->Hdr.bRevision = 6;
247 pXsdt->Hdr.bChkSum = 0;
248 pXsdt->Hdr.u32OemRevision = 1;
249 pXsdt->Hdr.u32CreatorRevision = 1;
250
251 memcpy(&pXsdt->Hdr.abOemId[0], "ORCLVB", 6);
252 memcpy(&pXsdt->Hdr.abOemTblId[0], "ORCL", 4);
253 memcpy(&pXsdt->Hdr.abOemTblId[4], &pXsdt->Hdr.u32Signature, 4);
254 memcpy(&pXsdt->Hdr.abCreatorId[0], "ORCL", 4);
255 RTAcpiTblHdrChecksumGenerate(&pXsdt->Hdr, cbXsdt);
256 vrc = RTVfsIoStrmWrite(hVfsIos, &abXsdt[0], cbXsdt, true /*fBlocking*/, NULL /*pcbWritten*/);
257 AssertRCReturn(vrc, vrc);
258
259 GCPhysTblsStart += cbXsdt;
260 cbAcpiTbls += cbXsdt;
261
262 /* Build XSDP */
263 ACPIRSDP Xsdp; RT_ZERO(Xsdp);
264
265 /* ACPI 1.0 part (RSDP) */
266 memcpy(Xsdp.abSignature, "RSD PTR ", 8);
267 memcpy(Xsdp.abOemId, "ORCLVB", 6);
268 Xsdp.bRevision = 3;
269 Xsdp.u32AddrRsdt = 0;
270 Xsdp.bChkSum = RTAcpiChecksumGenerate(&Xsdp, RT_OFFSETOF(ACPIRSDP, cbRsdp));
271
272 /* ACPI 2.0 part (XSDP) */
273 Xsdp.cbRsdp = RT_H2LE_U32(sizeof(ACPIRSDP));
274 Xsdp.u64AddrXsdt = RT_H2LE_U64(GCPhysXsdt);
275 Xsdp.bExtChkSum = RTAcpiChecksumGenerate(&Xsdp, sizeof(ACPIRSDP));
276
277 vrc = RTVfsIoStrmWrite(hVfsIos, &Xsdp, sizeof(Xsdp), true /*fBlocking*/, NULL /*pcbWritten*/);
278 AssertRCReturn(vrc, vrc);
279 cbAcpiTbls += sizeof(Xsdp);
280
281 *pGCPhysTblRoot = GCPhysTblsStart;
282 *pcbTblRoot = sizeof(Xsdp);
283 *pcbTbls = cbAcpiTbls;
284
285 return VINF_SUCCESS;
286}
287
288
289int SystemTableBuilderAcpi::addCpu(uint32_t idCpu)
290{
291 RTAcpiTblDeviceStartF(m_hAcpiDsdt, "CP%02RX32", idCpu);
292
293 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
294 RTAcpiTblStringAppend(m_hAcpiDsdt, "ACPI0007");
295
296 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
297 RTAcpiTblIntegerAppend(m_hAcpiDsdt, idCpu);
298
299 return RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
300}
301
302
303int SystemTableBuilderAcpi::addMemory(RTGCPHYS GCPhysStart, RTGCPHYS cbMem)
304{
305 RT_NOREF(GCPhysStart, cbMem);
306 return VINF_SUCCESS;
307}
308
309
310int SystemTableBuilderAcpi::addMmioDeviceNoIrq(const char *pszVBoxName, uint32_t uInstance, RTGCPHYS GCPhysMmio, RTGCPHYS cbMmio)
311{
312 PCSYSTEMTABLEDEVICE pSysTblDev = systemTableVBoxDevName2SysTblDevice(pszVBoxName);
313 AssertPtrReturn(pSysTblDev, VERR_NOT_FOUND);
314
315 RTAcpiTblDeviceStartF(m_hAcpiDsdt, "%s%RX32", pSysTblDev->pszAcpiName, uInstance);
316
317 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
318 if (pSysTblDev->fEisaId)
319 RTAcpiTblEisaIdAppend(m_hAcpiDsdt, pSysTblDev->pszAcpiHid);
320 else
321 RTAcpiTblStringAppend(m_hAcpiDsdt, pSysTblDev->pszAcpiHid);
322
323 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
324 RTAcpiTblIntegerAppend(m_hAcpiDsdt, uInstance);
325
326 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CRS");
327 int vrc = systemTableAcpiMmioDevResourceNoIrq(m_hAcpiDsdt, m_hAcpiRes, GCPhysMmio, cbMmio);
328 AssertRCReturn(vrc, vrc);
329
330 return RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
331}
332
333
334int SystemTableBuilderAcpi::addMmioDevice(const char *pszVBoxName, uint32_t uInstance, RTGCPHYS GCPhysMmio, RTGCPHYS cbMmio,
335 uint32_t u32Irq)
336{
337 PCSYSTEMTABLEDEVICE pSysTblDev = systemTableVBoxDevName2SysTblDevice(pszVBoxName);
338 AssertPtrReturn(pSysTblDev, VERR_NOT_FOUND);
339
340 RTAcpiTblDeviceStartF(m_hAcpiDsdt, "%s%RX32", pSysTblDev->pszAcpiName, uInstance);
341
342 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
343 if (pSysTblDev->fEisaId)
344 RTAcpiTblEisaIdAppend(m_hAcpiDsdt, pSysTblDev->pszAcpiHid);
345 else
346 RTAcpiTblStringAppend(m_hAcpiDsdt, pSysTblDev->pszAcpiHid);
347
348 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
349 RTAcpiTblIntegerAppend(m_hAcpiDsdt, uInstance);
350
351 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CRS");
352 int vrc = systemTableAcpiMmioDevResource(m_hAcpiDsdt, m_hAcpiRes, GCPhysMmio, cbMmio, u32Irq + GIC_INTID_RANGE_SPI_START);
353 AssertRCReturn(vrc, vrc);
354
355 return RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
356}
357
358
359int SystemTableBuilderAcpi::configureGic(uint32_t cCpus, RTGCPHYS GCPhysIntcDist, RTGCPHYS cbMmioIntcDist, RTGCPHYS GCPhysIntcReDist,
360 RTGCPHYS cbMmioIntcReDist, RTGCPHYS GCPhysIntcIts, RTGCPHYS cbMmioIntcIts)
361{
362 m_cCpus = cCpus;
363 m_GCPhysIntcDist = GCPhysIntcDist;
364 m_cbMmioIntcDist = cbMmioIntcDist;
365 m_GCPhysIntcReDist = GCPhysIntcReDist;
366 m_cbMmioIntcReDist = cbMmioIntcReDist;
367 m_GCPhysIntcIts = GCPhysIntcIts;
368 m_cbMmioIntcIts = cbMmioIntcIts;
369 return VINF_SUCCESS;
370}
371
372
373int SystemTableBuilderAcpi::configureClock(void)
374{
375 return VINF_SUCCESS;
376}
377
378
379int SystemTableBuilderAcpi::configurePcieRootBus(const char *pszVBoxName, uint32_t aPinIrqs[4], RTGCPHYS GCPhysMmioPio, RTGCPHYS GCPhysMmioEcam, size_t cbPciMmioEcam,
380 RTGCPHYS GCPhysPciMmioBase, RTGCPHYS cbPciMmio, RTGCPHYS GCPhysPciMmio32Base, RTGCPHYS cbPciMmio32)
381{
382 PCSYSTEMTABLEDEVICE pSysTblDev = systemTableVBoxDevName2SysTblDevice(pszVBoxName);
383 AssertPtrReturn(pSysTblDev, VERR_NOT_FOUND);
384
385 m_GCPhysPciMmioEcam = GCPhysMmioEcam; /* Need that for MCFG later. */
386 m_bPciBusMax = 15; /** @todo Make parameter. */
387
388 RTAcpiTblDeviceStartF(m_hAcpiDsdt, "%s%RX32", pSysTblDev->pszAcpiName, 0);
389
390 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
391 RTAcpiTblStringAppend(m_hAcpiDsdt, pSysTblDev->pszAcpiHid);
392
393 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CID");
394 RTAcpiTblEisaIdAppend(m_hAcpiDsdt, "PNP0A03");
395
396 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
397 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
398
399 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CCA"); /* Cache coherency attribute. */
400 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1);
401
402 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CRS");
403
404 uint32_t const fAddrSpace = RTACPI_RESOURCE_ADDR_RANGE_F_DECODE_TYPE_POS
405 | RTACPI_RESOURCE_ADDR_RANGE_F_MIN_ADDR_FIXED
406 | RTACPI_RESOURCE_ADDR_RANGE_F_MAX_ADDR_FIXED
407 | RTACPI_RESOURCE_ADDR_RANGE_F_PRODUCER;
408
409 RTAcpiResourceReset(m_hAcpiRes);
410 int vrc = RTAcpiResourceAddWordBusNumber(m_hAcpiRes, fAddrSpace, 0 /*u16BusMin*/, m_bPciBusMax /*u16BusMax*/,
411 0 /*u16OffTrans*/, 0 /*u16Granularity*/, m_bPciBusMax + 1 /*u16Length*/);
412 AssertRCReturn(vrc, vrc);
413
414 vrc = RTAcpiResourceAddQWordIoRange(m_hAcpiRes, kAcpiResIoRangeType_Translation_Dense, kAcpiResIoRange_Whole,
415 fAddrSpace, 0 /*u64AddrMin*/, UINT16_MAX /*u64AddrMax*/, GCPhysMmioPio,
416 0 /*u64Granularity*/, _64K);
417 AssertRCReturn(vrc, vrc);
418
419 vrc = RTAcpiResourceAddDWordMemoryRange(m_hAcpiRes, kAcpiResMemRangeCacheability_NonCacheable, kAcpiResMemType_Memory, true /*fRw*/,
420 fAddrSpace, (uint32_t)GCPhysPciMmio32Base, (uint32_t)(GCPhysPciMmio32Base + cbPciMmio32 - 1),
421 0 /*u32OffTrans*/, 0 /*u32Granularity*/, (uint32_t)cbPciMmio32);
422 AssertRCReturn(vrc, vrc);
423
424 vrc = RTAcpiResourceAddQWordMemoryRange(m_hAcpiRes, kAcpiResMemRangeCacheability_NonCacheable, kAcpiResMemType_Memory, true /*fRw*/,
425 fAddrSpace, GCPhysPciMmioBase, GCPhysPciMmioBase + cbPciMmio - 1,
426 0 /*u64OffTrans*/, 0 /*u64Granularity*/, cbPciMmio);
427 if (RT_SUCCESS(vrc))
428 {
429 vrc = RTAcpiResourceSeal(m_hAcpiRes);
430 if (RT_SUCCESS(vrc))
431 vrc = RTAcpiTblResourceAppend(m_hAcpiDsdt, m_hAcpiRes);
432 }
433 AssertRCReturn(vrc, vrc);
434
435 /* For the ECAM base we need to define a new device with a new resource template inside the PCI device. */
436 RTAcpiTblDeviceStart(m_hAcpiDsdt, "RES0");
437
438 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
439 RTAcpiTblEisaIdAppend(m_hAcpiDsdt, "PNP0C02");
440
441 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CRS");
442 RTAcpiResourceReset(m_hAcpiRes);
443 vrc = RTAcpiResourceAddQWordMemoryRange(m_hAcpiRes, kAcpiResMemRangeCacheability_NonCacheable, kAcpiResMemType_Memory, true /*fRw*/,
444 fAddrSpace, GCPhysMmioEcam, GCPhysMmioEcam + cbPciMmioEcam - 1,
445 0 /*u64OffTrans*/, 0 /*u64Granularity*/, cbPciMmioEcam);
446 if (RT_SUCCESS(vrc))
447 {
448 vrc = RTAcpiResourceSeal(m_hAcpiRes);
449 if (RT_SUCCESS(vrc))
450 vrc = RTAcpiTblResourceAppend(m_hAcpiDsdt, m_hAcpiRes);
451 }
452 AssertRCReturn(vrc, vrc);
453
454 /* Finish RES0 device. */
455 vrc = RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
456 AssertRCReturn(vrc, vrc);
457
458 /* Build the PCI interrupt routing table (_PRT). */
459 RTAcpiTblNameAppend(m_hAcpiDsdt, "_PRT");
460 RTAcpiTblPackageStart(m_hAcpiDsdt, 32 * 4);
461
462 uint32_t iIrqPinSwizzle = 0;
463
464 for (uint32_t i = 0; i < 32; i++)
465 {
466 for (uint32_t iIrqPin = 0; iIrqPin < 4; iIrqPin++)
467 {
468 RTAcpiTblPackageStart(m_hAcpiDsdt, 4);
469 RTAcpiTblIntegerAppend(m_hAcpiDsdt, (i << 16) | 0xffff); /* ACPI PCI address. */
470 RTAcpiTblIntegerAppend(m_hAcpiDsdt, iIrqPin); /* Interrupt pin (INTA, INTB, ...). */
471 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0); /* Interrupt destination, unused. */
472 RTAcpiTblIntegerAppend(m_hAcpiDsdt, GIC_INTID_RANGE_SPI_START
473 + aPinIrqs[(iIrqPinSwizzle + iIrqPin) % 4]); /* GSI of the interrupt. */
474 RTAcpiTblPackageFinalize(m_hAcpiDsdt);
475 }
476
477 iIrqPinSwizzle++;
478 }
479
480 RTAcpiTblPackageFinalize(m_hAcpiDsdt);
481
482 /* Create _CBA for the ECAM base. */
483 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CBA");
484 RTAcpiTblIntegerAppend(m_hAcpiDsdt, GCPhysMmioEcam);
485
486 return RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
487}
488
489
490int SystemTableBuilderAcpi::dumpTables(const char *pszFilename)
491{
492 return RTAcpiTblDumpToFile(m_hAcpiDsdt, RTACPITBLTYPE_AML, pszFilename);
493}
494
495
496int SystemTableBuilderAcpi::buildIort(RTVFSIOSTREAM hVfsIos, size_t *pcbIort)
497{
498 uint8_t abIort[ sizeof(ACPIIORT)
499 + sizeof(ACPIIORTNODEITSGROUP)
500 + sizeof(ACPIIORTNODEPCIRC)
501 + sizeof(ACPIIIORTIDMAPPING)];
502 RT_ZERO(abIort);
503 uint32_t cbIort = 0;
504 uint8_t cNodes = 0;
505
506 PACPIIORT pIort = (PACPIIORT)&abIort[0];
507 PACPIIORTNODEITSGROUP pItsGroup = (PACPIIORTNODEITSGROUP)(pIort + 1);
508 PACPIIORTNODEPCIRC pPciRc = (PACPIIORTNODEPCIRC)(pItsGroup + 1);
509 PACPIIIORTIDMAPPING pPciRcMapping = (PACPIIIORTIDMAPPING)(pPciRc + 1);
510 cbIort += sizeof(*pIort);
511
512 /* Add ITS group node (we support only a single ITS). */
513 ++cNodes;
514 {
515 pItsGroup->Hdr.bType = ACPI_IORT_NODE_TYPE_ITS_GROUP;
516 pItsGroup->Hdr.cbThis = sizeof(*pItsGroup);
517 pItsGroup->cIts = 1;
518 cbIort += sizeof(*pItsGroup);
519 }
520
521 /* Add PCI root complex for a single ITS with a 1:1 mapping of IDs. */
522 ++cNodes;
523 {
524 pPciRc->Hdr.bType = ACPI_IORT_NODE_TYPE_ROOT_COMPLEX;
525 pPciRc->Hdr.cbThis = sizeof(*pPciRc) + sizeof(*pPciRcMapping);
526 pPciRc->Hdr.bRevision = 2;
527 pPciRc->Hdr.cIdMappings = 1;
528 pPciRc->Hdr.offIdArray = sizeof(*pPciRc);
529 pPciRc->bMemAddrSizeLimit = 64;
530 cbIort += sizeof(*pPciRc);
531
532 /* Add the ID mapping. */
533 pPciRcMapping->fFlags = ACPI_IORT_ID_MAPPING_SINGLE;
534 pPciRcMapping->offOutputRef = sizeof(*pIort); /** Offset from start of IORT to start of ITS GROUP 0. */
535 cbIort += sizeof(*pPciRcMapping);
536 }
537
538 /* Finalize the IORT. */
539 pIort->Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_RSVD_IORT;
540 pIort->Hdr.cbTbl = cbIort;
541 pIort->Hdr.bRevision = 1;
542 pIort->Hdr.bChkSum = 0;
543 pIort->Hdr.u32OemRevision = 1;
544 pIort->Hdr.u32CreatorRevision = 1;
545 pIort->cIortNodes = cNodes;
546 pIort->offFirstNode = sizeof(ACPIIORT);
547
548 memcpy(&pIort->Hdr.abOemId[0], "ORCLVB", 6);
549 memcpy(&pIort->Hdr.abOemTblId[0], "ORCL", 4);
550 memcpy(&pIort->Hdr.abOemTblId[4], &pIort->Hdr.u32Signature, 4);
551 memcpy(&pIort->Hdr.abCreatorId[0], "ORCL", 4);
552
553 RTAcpiTblHdrChecksumGenerate(&pIort->Hdr, cbIort);
554 *pcbIort = cbIort;
555 return RTVfsIoStrmWrite(hVfsIos, pIort, cbIort, true /*fBlocking*/, NULL /*pcbWritten*/);
556}
557
558
559int SystemTableBuilderAcpi::buildMadt(RTVFSIOSTREAM hVfsIos, size_t *pcbMadt)
560{
561 uint8_t abMadt[_4K];
562 uint32_t cbMadt = 0;
563
564 RT_ZERO(abMadt);
565
566 PACPIMADT pMadt = (PACPIMADT)&abMadt[0];
567 PACPIMADTGICC pGicc = (PACPIMADTGICC)(pMadt + 1);
568
569 cbMadt += sizeof(*pMadt);
570
571 /* Include a GIC CPU interface for each CPU. */
572 for (uint32_t i = 0; i < m_cCpus; i++)
573 {
574 pGicc->bType = ACPI_MADT_INTR_CTRL_TYPE_GICC;
575 pGicc->cbThis = sizeof(*pGicc);
576 pGicc->u32CpuId = i;
577 pGicc->u32AcpiCpuUid = i;
578 pGicc->fGicc = ACPI_MADT_GICC_F_ENABLED;
579 pGicc->u64Mpidr = i;
580
581 cbMadt += sizeof(*pGicc);
582 pGicc++;
583 }
584
585 /* Build the GICD. */
586 PACPIMADTGICD pGicd = (PACPIMADTGICD)pGicc;
587 pGicd->bType = ACPI_MADT_INTR_CTRL_TYPE_GICD;
588 pGicd->cbThis = sizeof(*pGicd);
589 pGicd->u64PhysAddrBase = m_GCPhysIntcDist;
590 pGicd->bGicVersion = ACPI_MADT_GICD_VERSION_GICv3;
591
592 cbMadt += sizeof(*pGicd);
593
594 /* Build the GICR. */
595 PACPIMADTGICR pGicr = (PACPIMADTGICR)(pGicd + 1);
596 pGicr->bType = ACPI_MADT_INTR_CTRL_TYPE_GICR;
597 pGicr->cbThis = sizeof(*pGicr);
598 pGicr->u64PhysAddrGicrRangeBase = m_GCPhysIntcReDist;
599 pGicr->cbGicrRange = m_cbMmioIntcReDist;
600
601 cbMadt += sizeof(*pGicr);
602
603 /* Build the GITS only if it's enabled for the VM. */
604 if (m_GCPhysIntcIts)
605 {
606 Assert(m_cbMmioIntcIts > 0);
607 Assert(m_GCPhysIntcIts != NIL_RTGCPHYS);
608 PACPIMADTGICITS pGits = (PACPIMADTGICITS)(pGicr + 1);
609 pGits->bType = ACPI_MADT_INTR_CTRL_TYPE_GIC_ITS;
610 pGits->cbThis = sizeof(*pGits);
611 pGits->u64PhysAddrBase = m_GCPhysIntcIts;
612 pGits->u32GicItsId = 0;
613
614 cbMadt += sizeof(*pGits);
615 }
616
617 /* Finalize the MADT. */
618 pMadt->Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_APIC;
619 pMadt->Hdr.cbTbl = cbMadt;
620 pMadt->Hdr.bRevision = 6;
621 pMadt->Hdr.bChkSum = 0;
622 pMadt->Hdr.u32OemRevision = 1;
623 pMadt->Hdr.u32CreatorRevision = 1;
624
625 memcpy(&pMadt->Hdr.abOemId[0], "ORCLVB", 6);
626 memcpy(&pMadt->Hdr.abOemTblId[0], "ORCL", 4);
627 memcpy(&pMadt->Hdr.abOemTblId[4], &pMadt->Hdr.u32Signature, 4);
628 memcpy(&pMadt->Hdr.abCreatorId[0], "ORCL", 4);
629 RTAcpiTblHdrChecksumGenerate(&pMadt->Hdr, cbMadt);
630 *pcbMadt = cbMadt;
631 return RTVfsIoStrmWrite(hVfsIos, pMadt, cbMadt, true /*fBlocking*/, NULL /*pcbWritten*/);
632}
633
634
635int SystemTableBuilderAcpi::buildMcfg(RTVFSIOSTREAM hVfsIos, size_t *pcbMcfg)
636{
637 uint8_t abMcfg[_1K];
638 uint32_t cbMcfg = 0;
639
640 RT_ZERO(abMcfg);
641
642 PACPIMCFG pMcfg = (PACPIMCFG)&abMcfg[0];
643 PACPIMCFGALLOC pAlloc = (PACPIMCFGALLOC)(pMcfg + 1);
644
645 cbMcfg += sizeof(*pMcfg) + sizeof(*pAlloc);
646
647 pAlloc->u64PhysAddrBase = m_GCPhysPciMmioEcam;
648 pAlloc->u16PciSegGrpNr = 0;
649 pAlloc->bPciBusFirst = 0;
650 pAlloc->bPciBusLast = m_bPciBusMax;
651
652 /* Finalize the MADT. */
653 pMcfg->Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_RSVD_MCFG;
654 pMcfg->Hdr.cbTbl = cbMcfg;
655 pMcfg->Hdr.bRevision = 6;
656 pMcfg->Hdr.bChkSum = 0;
657 pMcfg->Hdr.u32OemRevision = 1;
658 pMcfg->Hdr.u32CreatorRevision = 1;
659
660 memcpy(&pMcfg->Hdr.abOemId[0], "ORCLVB", 6);
661 memcpy(&pMcfg->Hdr.abOemTblId[0], "ORCL", 4);
662 memcpy(&pMcfg->Hdr.abOemTblId[4], &pMcfg->Hdr.u32Signature, 4);
663 memcpy(&pMcfg->Hdr.abCreatorId[0], "ORCL", 4);
664 RTAcpiTblHdrChecksumGenerate(&pMcfg->Hdr, cbMcfg);
665 *pcbMcfg = cbMcfg;
666 return RTVfsIoStrmWrite(hVfsIos, pMcfg, cbMcfg, true /*fBlocking*/, NULL /*pcbWritten*/);
667}
668
669
670int SystemTableBuilderAcpi::buildGtdt(RTVFSIOSTREAM hVfsIos, size_t *pcbGtdt)
671{
672 ACPIGTDT Gtdt; RT_ZERO(Gtdt);
673
674#if 1
675 Gtdt.u64PhysAddrCntControlBase = UINT64_MAX;
676 Gtdt.u32Rsvd = 0;
677 Gtdt.u32El1SecTimerGsiv = 0;
678 Gtdt.fEl1SecTimer = 0;
679 Gtdt.u32El1NonSecTimerGsiv = 0x1a; /** @todo */
680 Gtdt.fEl1NonSecTimer = ACPI_GTDT_TIMER_F_INTR_MODE_LEVEL | ACPI_GTDT_TIMER_F_INTR_POLARITY_ACTIVE_HIGH | ACPI_GTDT_TIMER_F_ALWAYS_ON_CAP;
681 Gtdt.u32El1VirtTimerGsiv = 0x1b; /** @todo */
682 Gtdt.fEl1VirtTimer = ACPI_GTDT_TIMER_F_INTR_MODE_LEVEL | ACPI_GTDT_TIMER_F_INTR_POLARITY_ACTIVE_HIGH;
683 Gtdt.u32El2TimerGsiv = 0x1e;
684 Gtdt.fEl2Timer = ACPI_GTDT_TIMER_F_INTR_MODE_LEVEL | ACPI_GTDT_TIMER_F_INTR_POLARITY_ACTIVE_HIGH;
685 Gtdt.u64PhysAddrCndReadBase = UINT64_MAX;
686 Gtdt.cPlatformTimers = 0;
687 Gtdt.offPlatformTimers = 0;
688 Gtdt.u32El2VirtTimerGsiv = 0;
689 Gtdt.fEl2VirtTimer = 0;
690#else /* Nested virt config on AppleSilicon. */
691 Gtdt.u64PhysAddrCntControlBase = UINT64_MAX;
692 Gtdt.u32Rsvd = 0;
693 Gtdt.u32El1SecTimerGsiv = 0;
694 Gtdt.fEl1SecTimer = 0;
695 Gtdt.u32El1NonSecTimerGsiv = 0x1e; /** @todo */
696 Gtdt.fEl1NonSecTimer = ACPI_GTDT_TIMER_F_INTR_MODE_LEVEL | ACPI_GTDT_TIMER_F_INTR_POLARITY_ACTIVE_HIGH | ACPI_GTDT_TIMER_F_ALWAYS_ON_CAP;
697 Gtdt.u32El1VirtTimerGsiv = 0x1b; /** @todo */
698 Gtdt.fEl1VirtTimer = ACPI_GTDT_TIMER_F_INTR_MODE_LEVEL | ACPI_GTDT_TIMER_F_INTR_POLARITY_ACTIVE_HIGH;
699 Gtdt.u32El2TimerGsiv = 0x1a;
700 Gtdt.fEl2Timer = ACPI_GTDT_TIMER_F_INTR_MODE_LEVEL | ACPI_GTDT_TIMER_F_INTR_POLARITY_ACTIVE_HIGH;
701 Gtdt.u64PhysAddrCndReadBase = UINT64_MAX;
702 Gtdt.cPlatformTimers = 0;
703 Gtdt.offPlatformTimers = 0;
704 Gtdt.u32El2VirtTimerGsiv = 0;
705 Gtdt.fEl2VirtTimer = 0;
706#endif
707
708 Gtdt.Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_GTDT;
709 Gtdt.Hdr.cbTbl = sizeof(Gtdt);
710 Gtdt.Hdr.bRevision = 6;
711 Gtdt.Hdr.bChkSum = 0;
712 Gtdt.Hdr.u32OemRevision = 1;
713 Gtdt.Hdr.u32CreatorRevision = 1;
714
715 memcpy(&Gtdt.Hdr.abOemId[0], "ORCLVB", 6);
716 memcpy(&Gtdt.Hdr.abOemTblId[0], "ORCL", 4);
717 memcpy(&Gtdt.Hdr.abOemTblId[4], &Gtdt.Hdr.u32Signature, 4);
718 memcpy(&Gtdt.Hdr.abCreatorId[0], "ORCL", 4);
719 RTAcpiTblHdrChecksumGenerate(&Gtdt.Hdr, sizeof(Gtdt));
720 *pcbGtdt = sizeof(Gtdt);
721 return RTVfsIoStrmWrite(hVfsIos, &Gtdt, sizeof(Gtdt), true /*fBlocking*/, NULL /*pcbWritten*/);
722}
723
724
725int SystemTableBuilderAcpi::buildFadt(RTVFSIOSTREAM hVfsIos, RTGCPHYS GCPhysXDsdt, size_t *pcbFadt)
726{
727 /* Build FADT. */
728 ACPIFADT Fadt; RT_ZERO(Fadt);
729
730 Fadt.fFeatures = ACPI_FADT_F_HW_REDUCED_ACPI;
731 Fadt.fArmBootArch = ACPI_FADT_ARM_BOOT_ARCH_F_PSCI_COMP
732 | ACPI_FADT_ARM_BOOT_ARCH_F_PSCI_USE_HVC;
733 Fadt.bFadtVersionMinor = 3;
734 Fadt.u64AddrXDsdt = GCPhysXDsdt;
735
736 Fadt.Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_FACP;
737 Fadt.Hdr.cbTbl = sizeof(Fadt);
738 Fadt.Hdr.bRevision = 6;
739 Fadt.Hdr.bChkSum = 0;
740 Fadt.Hdr.u32OemRevision = 1;
741 Fadt.Hdr.u32CreatorRevision = 1;
742
743 memcpy(&Fadt.Hdr.abOemId[0], "ORCLVB", 6);
744 memcpy(&Fadt.Hdr.abOemTblId[0], "ORCL", 4);
745 memcpy(&Fadt.Hdr.abOemTblId[4], &Fadt.Hdr.u32Signature, 4);
746 memcpy(&Fadt.Hdr.abCreatorId[0], "ORCL", 4);
747 RTAcpiTblHdrChecksumGenerate(&Fadt.Hdr, sizeof(Fadt));
748 *pcbFadt = sizeof(Fadt);
749 return RTVfsIoStrmWrite(hVfsIos, &Fadt, sizeof(Fadt), true /*fBlocking*/, NULL /*pcbWritten*/);
750}
751
752
753int SystemTableBuilderAcpi::buildTpm20(RTVFSIOSTREAM hVfsIos, size_t *pcbTpm20)
754{
755 Assert(m_fTpm20);
756
757 ACPITPM20 Tpm2;
758 RT_ZERO(Tpm2);
759
760 Tpm2.u32StartMethod = m_fCrb ? ACPITBL_TPM20_START_METHOD_CRB : ACPITBL_TPM20_START_METHOD_TIS12;
761 Tpm2.u64BaseAddrCrbOrFifo = m_fCrb ? m_GCPhysTpm20Mmio + TPM_CRB_LOCALITY_REG_CTRL_REQ : m_GCPhysTpm20Mmio;
762 Tpm2.u16PlatCls = ACPITBL_TPM20_PLAT_CLS_CLIENT;
763
764 Tpm2.Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_RSVD_TPM2;
765 Tpm2.Hdr.cbTbl = sizeof(Tpm2);
766 Tpm2.Hdr.bRevision = ACPI_TPM20_REVISION;
767 Tpm2.Hdr.bChkSum = 0;
768 Tpm2.Hdr.u32OemRevision = 1;
769 Tpm2.Hdr.u32CreatorRevision = 1;
770
771 memcpy(&Tpm2.Hdr.abOemId[0], "ORCLVB", 6);
772 memcpy(&Tpm2.Hdr.abOemTblId[0], "ORCL", 4);
773 memcpy(&Tpm2.Hdr.abOemTblId[4], &Tpm2.Hdr.u32Signature, 4);
774 memcpy(&Tpm2.Hdr.abCreatorId[0], "ORCL", 4);
775 RTAcpiTblHdrChecksumGenerate(&Tpm2.Hdr, sizeof(Tpm2));
776 *pcbTpm20 = sizeof(Tpm2);
777 return RTVfsIoStrmWrite(hVfsIos, &Tpm2, sizeof(Tpm2), true /*fBlocking*/, NULL /*pcbWritten*/);
778}
779
780
781int SystemTableBuilderAcpi::configureTpm2(bool fCrb, RTGCPHYS GCPhysMmioStart, RTGCPHYS cbMmio, uint32_t u32Irq)
782{
783 m_fTpm20 = true;
784 m_fCrb = fCrb;
785 m_GCPhysTpm20Mmio = GCPhysMmioStart;
786
787 RTAcpiTblDeviceStartF(m_hAcpiDsdt, "TPM0");
788
789 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
790 RTAcpiTblStringAppend(m_hAcpiDsdt, "MSFT0101");
791
792 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CID");
793 RTAcpiTblStringAppend(m_hAcpiDsdt, "MSFT0101");
794
795 RTAcpiTblNameAppend(m_hAcpiDsdt, "_STR");
796 RTAcpiTblStringAppend(m_hAcpiDsdt, "TPM 2.0 Device");
797
798 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
799 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
800
801 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CRS");
802 int vrc = systemTableAcpiMmioDevResource(m_hAcpiDsdt, m_hAcpiRes, GCPhysMmioStart, cbMmio, u32Irq + GIC_INTID_RANGE_SPI_START);
803 AssertRCReturn(vrc, vrc);
804
805 RTAcpiTblMethodStart(m_hAcpiDsdt, "_STA", 0, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
806 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
807 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x0f);
808 RTAcpiTblMethodFinalize(m_hAcpiDsdt);
809
810 /* Build the PPI interface (this is as a verbatim translation from src/VBox/Devices/PC/vbox-tpm.dsl as possible). */
811 RTAcpiTblMethodStart(m_hAcpiDsdt, "TPFS", 1, RTACPI_METHOD_F_SERIALIZED, 0 /*uSyncLvl*/);
812
813 RTAcpiTblIfStart(m_hAcpiDsdt);
814 /* LGreaterEqual(Arg0, 0x100). */
815 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LGreaterEqual);
816 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 0);
817 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x100);
818
819 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
820 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
821 RTAcpiTblIfFinalize(m_hAcpiDsdt);
822
823 RTAcpiTblOpRegionAppendEx(m_hAcpiDsdt, "TPP1", kAcpiOperationRegionSpace_SystemMemory);
824 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Add); /* Region offset */
825 RTAcpiTblIntegerAppend(m_hAcpiDsdt, m_GCPhysTpm20Mmio + 0x5000);
826 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 0); /* Arg0 */
827 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
828 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1); /* Region size */
829
830 /* Define the field accessor. */
831 const RTACPIFIELDENTRY aPpiTpp1Fields[] =
832 {
833 { "TPPF", 8 },
834 };
835 RTAcpiTblFieldAppend(m_hAcpiDsdt, "TPP1", kAcpiFieldAcc_Any, false /*fLock*/, kAcpiFieldUpdate_Preserve,
836 &aPpiTpp1Fields[0], RT_ELEMENTS(aPpiTpp1Fields));
837 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
838 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPPF");
839
840 RTAcpiTblMethodFinalize(m_hAcpiDsdt);
841
842
843 /* Device specific method. */
844 RTAcpiTblMethodStart(m_hAcpiDsdt, "_DSM", 4, RTACPI_METHOD_F_SERIALIZED, 0 /*uSyncLvl*/);
845
846 /* Define the MMIO region for the PPI interface. */
847 RTAcpiTblOpRegionAppend(m_hAcpiDsdt, "TPMP", kAcpiOperationRegionSpace_SystemMemory,
848 m_GCPhysTpm20Mmio + 0x5100, 0x5a /*cbRegion*/);
849
850 /* Define the field accessors for the PPI interface. */
851 const RTACPIFIELDENTRY aPpiFields[] =
852 {
853 { "PPIN", 8 },
854 { "PPIP", 32 },
855 { "PPRP", 32 },
856 { "PPRQ", 32 },
857 { "PPRM", 32 },
858 { "LPPR", 32 }
859 };
860 RTAcpiTblFieldAppend(m_hAcpiDsdt, "TPMP", kAcpiFieldAcc_Any, false /*fLock*/, kAcpiFieldUpdate_Preserve,
861 &aPpiFields[0], RT_ELEMENTS(aPpiFields));
862
863 /* Define some packages we need later on. */
864 RTAcpiTblNameAppend(m_hAcpiDsdt, "TPB2");
865 RTAcpiTblPackageStart(m_hAcpiDsdt, 2 /*cElements*/);
866 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
867 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
868 RTAcpiTblPackageFinalize(m_hAcpiDsdt);
869
870 RTAcpiTblNameAppend(m_hAcpiDsdt, "TPB3");
871 RTAcpiTblPackageStart(m_hAcpiDsdt, 3 /*cElements*/);
872 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
873 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
874 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
875 RTAcpiTblPackageFinalize(m_hAcpiDsdt);
876
877
878 /*
879 * Check that the UUID in Arg0 contains the Physical Presence Interface Specification UUID.
880 */
881 RTAcpiTblIfStart(m_hAcpiDsdt);
882
883 /* Predicate (LEqual(Arg0, ToUUID("3dddfaa6-361b-4eb4-a424-8d10089d1653")))*/
884 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
885 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 0);
886 RTAcpiTblUuidAppendFromStr(m_hAcpiDsdt, "3dddfaa6-361b-4eb4-a424-8d10089d1653");
887
888 /* Standard _DSM query function. */
889 RTAcpiTblIfStart(m_hAcpiDsdt);
890
891 /* LEqual(Arg2, Zero). */
892 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
893 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
894 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
895
896 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
897 uint8_t abDsmQuery[2] = { 0xff, 0x01 };
898 RTAcpiTblBufferAppend(m_hAcpiDsdt, &abDsmQuery[0], sizeof(abDsmQuery));
899
900 RTAcpiTblIfFinalize(m_hAcpiDsdt);
901
902 /* Query supported PPI revision . */
903 RTAcpiTblIfStart(m_hAcpiDsdt);
904
905 /* LEqual(Arg2, Zero). */
906 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
907 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
908 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1);
909
910 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
911 RTAcpiTblStringAppend(m_hAcpiDsdt, "1.3");
912
913 RTAcpiTblIfFinalize(m_hAcpiDsdt);
914
915
916 /* Submit TPM Operation Requested to pre-OS environment. */
917 RTAcpiTblIfStart(m_hAcpiDsdt);
918
919 /* LEqual(Arg2, Zero). */
920 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
921 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
922 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 2);
923
924 /* Store(DerefOf(Index(Arg3, Zero)), Local0) */
925 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
926 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_DerefOf);
927 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Index);
928 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 3); /* Arg3 */
929 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0); /* Zero */
930 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
931 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 0); /* Local0 */
932
933 /* Store (TPFS (Local0), Local1) */
934 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
935 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPFS");
936 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 0); /* Local0 */
937 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 1); /* Local1 */
938
939 /* If (LEqual (And (Local1, 0x07), Zero)) */
940 RTAcpiTblIfStart(m_hAcpiDsdt);
941 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
942 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_And);
943 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 1); /* Local1 */
944 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x7);
945 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
946 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
947
948 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
949 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1);
950
951 RTAcpiTblIfFinalize(m_hAcpiDsdt);
952
953 /* Store (Local0, PPRQ) */
954 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
955 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 0); /* Local0 */
956 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "PPRQ");
957 /* Store (Zero, PPRM) */
958 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
959 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
960 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "PPRM");
961
962 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
963 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
964
965 RTAcpiTblIfFinalize(m_hAcpiDsdt);
966
967
968 /* Get Pending TPM Operation Requested by the OS. */
969 RTAcpiTblIfStart(m_hAcpiDsdt);
970
971 /* LEqual(Arg2, Zero). */
972 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
973 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
974 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 3);
975
976 RTAcpiTblIfStart(m_hAcpiDsdt);
977
978 /* LEqual(Arg1, One). */
979 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
980 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 1);
981 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1);
982
983 /* Store (PPRQ, Index(TPB2, One) */
984 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
985 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "PPRQ");
986 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Index);
987 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPB2");
988 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1);
989 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
990
991 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
992 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPB2");
993
994 RTAcpiTblIfFinalize(m_hAcpiDsdt);
995
996 RTAcpiTblIfStart(m_hAcpiDsdt);
997
998 /* LEqual(Arg1, 0x02). */
999 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1000 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 1);
1001 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 2);
1002
1003 /* Store (PPRQ, Index(TPB3, One) */
1004 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1005 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "PPRQ");
1006 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Index);
1007 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPB3");
1008 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1);
1009 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
1010
1011 /* Store (PPRM, Index(TPB3, 0x2) */
1012 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1013 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "PPRM");
1014 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Index);
1015 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPB3");
1016 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 2);
1017 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
1018
1019 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1020 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPB2");
1021
1022 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1023
1024 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1025 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPB3");
1026
1027 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1028
1029
1030 /* Get Platform-specific Action to Transition to Pre-OS Environment. */
1031 RTAcpiTblIfStart(m_hAcpiDsdt);
1032
1033 /* LEqual(Arg2, Zero). */
1034 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1035 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
1036 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 4);
1037
1038 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1039 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 2); /* Reboot */
1040
1041 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1042
1043
1044 /* Return TPM Operation Response to OS Environment. */
1045 RTAcpiTblIfStart(m_hAcpiDsdt);
1046
1047 /* LEqual(Arg2, Zero). */
1048 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1049 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
1050 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 5);
1051
1052 /* Store (LPPR, Index(TPB3, One) */
1053 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1054 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "LPPR");
1055 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Index);
1056 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPB3");
1057 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1);
1058 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
1059
1060 /* Store (PPRP, Index(TPB3, 0x2) */
1061 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1062 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "PPRP");
1063 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Index);
1064 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPB3");
1065 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 2);
1066 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
1067
1068 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1069 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPB3");
1070
1071 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1072
1073
1074 /* Submit Preferred user language - deprecated. */
1075 RTAcpiTblIfStart(m_hAcpiDsdt);
1076
1077 /* LEqual(Arg2, Zero). */
1078 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1079 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
1080 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 6);
1081
1082 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1083 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 3); /* Not implemented */
1084
1085 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1086
1087
1088 /* Submit TPM Operation Request to Pre-OS Environment 2. */
1089 RTAcpiTblIfStart(m_hAcpiDsdt);
1090
1091 /* LEqual(Arg2, Zero). */
1092 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1093 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
1094 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 7);
1095
1096 /* Store(DerefOf(Index(Arg3, Zero)), Local0) */
1097 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1098 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_DerefOf);
1099 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Index);
1100 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 3); /* Arg3 */
1101 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0); /* Zero */
1102 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
1103 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 0); /* Local0 */
1104
1105 /* Store (TPFS (Local0), Local1) */
1106 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1107 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPFS");
1108 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 0); /* Local0 */
1109 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 1); /* Local1 */
1110
1111 /* Store(And(Local1, 0x07), Local1) */
1112 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1113 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_And);
1114 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 1); /* Local1 */
1115 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x7);
1116 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
1117 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 1); /* Local1 */
1118
1119 /* LEqual(Local1, Zero) */
1120 RTAcpiTblIfStart(m_hAcpiDsdt);
1121
1122 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1123 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 1);
1124 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
1125
1126 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1127 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1);
1128
1129 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1130
1131 /* LEqual(Local1, 2) */
1132 RTAcpiTblIfStart(m_hAcpiDsdt);
1133
1134 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1135 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 1);
1136 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 2);
1137
1138 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1139 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 3);
1140
1141 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1142
1143 /* LEqual(Arg1, One) */
1144 RTAcpiTblIfStart(m_hAcpiDsdt);
1145
1146 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1147 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 1);
1148 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1);
1149
1150 /* Store(Local0, PPRQ) */
1151 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1152 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 0);
1153 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "PPRQ");
1154
1155 /* Store(Zero, PPRM) */
1156 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1157 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
1158 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "PPRM");
1159
1160 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1161
1162 /* LEqual(Arg1, 2) */
1163 RTAcpiTblIfStart(m_hAcpiDsdt);
1164
1165 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1166 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 1);
1167 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 2);
1168
1169 /* Store(DerefOf(Index(Arg3, One)), Local2) */
1170 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1171 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_DerefOf);
1172 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Index);
1173 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 3); /* Arg3 */
1174 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1); /* ONe */
1175 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
1176 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 2); /* Local2 */
1177
1178 /* Store(Local0, PPRQ) */
1179 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1180 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 0);
1181 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "PPRQ");
1182
1183 /* Store(Local2, PPRM) */
1184 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1185 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 2);
1186 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "PPRM");
1187
1188 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1189
1190 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1191 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
1192
1193 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1194
1195
1196 /* Get User Confirmation Status for Operation. */
1197 RTAcpiTblIfStart(m_hAcpiDsdt);
1198
1199 /* LEqual(Arg2, Zero). */
1200 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1201 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
1202 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 8);
1203
1204 /* Store(DerefOf(Index(Arg3, Zero)), Local0) */
1205 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1206 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_DerefOf);
1207 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Index);
1208 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 3); /* Arg3 */
1209 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0); /* Zero */
1210 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
1211 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 0); /* Local0 */
1212
1213 /* Store (TPFS (Local0), Local1) */
1214 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Store);
1215 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "TPFS");
1216 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 0); /* Local0 */
1217 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 1); /* Local1 */
1218
1219 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1220 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_And);
1221 RTAcpiTblLocalOpAppend(m_hAcpiDsdt, 1); /* Local1 */
1222 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x7);
1223 RTAcpiTblNullNameAppend(m_hAcpiDsdt); /* Target -> NullName */
1224
1225 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1226
1227
1228 /* Return Unknown function. */
1229 uint8_t bUnkFunc = 0x00;
1230 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1231 RTAcpiTblBufferAppend(m_hAcpiDsdt, &bUnkFunc, sizeof(bUnkFunc));
1232
1233 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1234
1235
1236 /*
1237 * TCG Platform Reset Attack Mitigation Specification interface.
1238 */
1239 RTAcpiTblIfStart(m_hAcpiDsdt);
1240
1241 /* Predicate (LEqual(Arg0, ToUUID("376054ed-cc13-4675-901c-4756d7f2d45d")))*/
1242 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1243 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 0);
1244 RTAcpiTblUuidAppendFromStr(m_hAcpiDsdt, "376054ed-cc13-4675-901c-4756d7f2d45d");
1245
1246 /* Standard _DSM query function. */
1247 RTAcpiTblIfStart(m_hAcpiDsdt);
1248
1249 /* LEqual(Arg2, Zero). */
1250 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1251 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
1252 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
1253
1254 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1255 uint8_t bBuf = 0x03;
1256 RTAcpiTblBufferAppend(m_hAcpiDsdt, &bBuf, sizeof(bBuf));
1257
1258 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1259
1260 /* Set Memory Overwrite Request (MOR) bit to specified value. */
1261 RTAcpiTblIfStart(m_hAcpiDsdt);
1262
1263 /* LEqual(Arg2, Zero). */
1264 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1265 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
1266 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1);
1267
1268 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1269 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0); /* Memory always zeroed on reset. */
1270
1271 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1272
1273 /* Return Unknown function. */
1274 bUnkFunc = 0x00;
1275 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1276 RTAcpiTblBufferAppend(m_hAcpiDsdt, &bUnkFunc, sizeof(bUnkFunc));
1277
1278 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1279
1280 /* Return Unknown function. */
1281 bUnkFunc = 0x00;
1282 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1283 RTAcpiTblBufferAppend(m_hAcpiDsdt, &bUnkFunc, sizeof(bUnkFunc));
1284
1285 RTAcpiTblMethodFinalize(m_hAcpiDsdt);
1286
1287 return RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
1288}
1289
1290
1291int SystemTableBuilderAcpi::configureGpioDevice(const char *pszVBoxName, uint32_t uInstance, RTGCPHYS GCPhysMmio, RTGCPHYS cbMmio, uint32_t u32Irq,
1292 uint16_t u16PinShutdown, uint16_t u16PinSuspend)
1293{
1294 PCSYSTEMTABLEDEVICE pSysTblDev = systemTableVBoxDevName2SysTblDevice(pszVBoxName);
1295 AssertPtrReturn(pSysTblDev, VERR_NOT_FOUND);
1296
1297 RTAcpiTblDeviceStartF(m_hAcpiDsdt, "%s%RX32", pSysTblDev->pszAcpiName, uInstance);
1298
1299 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
1300 RTAcpiTblStringAppend(m_hAcpiDsdt, pSysTblDev->pszAcpiHid);
1301
1302 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
1303 RTAcpiTblIntegerAppend(m_hAcpiDsdt, uInstance);
1304
1305 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CRS");
1306
1307 int vrc = systemTableAcpiMmioDevResource(m_hAcpiDsdt, m_hAcpiRes, GCPhysMmio, cbMmio, u32Irq + GIC_INTID_RANGE_SPI_START);
1308 AssertRCReturn(vrc, vrc);
1309
1310#if 0 /* Works fine with Linux (also older ones), doesn't with Windows (talk about "standards"). */
1311 /* Construct the _AEI containing the GPIO configuration. */
1312 RTAcpiTblNameAppend(m_hAcpiDsdt, "_AEI");
1313
1314 RTAcpiResourceReset(m_hAcpiRes);
1315 vrc = RTAcpiResourceAddGpioInt(m_hAcpiRes, kAcpiResGpioMod_Level, kAcpiResGpioPol_ActiveHigh, kAcpiResGpioShr_Exclusive,
1316 kAcpiResGpioPpi_PullDown, 0 /*u16DebounceWait*/, "GPI0",
1317 &u16PinShutdown, 1 /* cPins */);
1318 if (RT_SUCCESS(vrc))
1319 vrc = RTAcpiResourceAddGpioInt(m_hAcpiRes, kAcpiResGpioMod_Level, kAcpiResGpioPol_ActiveHigh, kAcpiResGpioShr_Exclusive,
1320 kAcpiResGpioPpi_PullDown, 0 /*u16DebounceWait*/, "GPI0",
1321 &u16PinSuspend, 1 /* cPins */);
1322 if (RT_SUCCESS(vrc))
1323 {
1324 vrc = RTAcpiResourceSeal(m_hAcpiRes);
1325 if (RT_SUCCESS(vrc))
1326 vrc = RTAcpiTblResourceAppend(m_hAcpiDsdt, m_hAcpiRes);
1327 }
1328 AssertRCReturn(vrc, vrc);
1329
1330 /* The interrupt methods for the pins. */
1331 RTAcpiTblMethodStartF(m_hAcpiDsdt, 0 /*cArgs*/, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/,
1332 "_L%02RX16", u16PinShutdown);
1333 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Notify);
1334 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "PBTN");
1335 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x80);
1336 RTAcpiTblMethodFinalize(m_hAcpiDsdt);
1337
1338 RTAcpiTblMethodStartF(m_hAcpiDsdt, 0 /*cArgs*/, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/,
1339 "_L%02RX16", u16PinSuspend);
1340 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Notify);
1341 RTAcpiTblNameStringAppend(m_hAcpiDsdt, "SBTN");
1342 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x80);
1343 RTAcpiTblMethodFinalize(m_hAcpiDsdt);
1344
1345 RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
1346
1347 /* Now create the shutdown and suspend button devices. */
1348 RTAcpiTblDeviceStart(m_hAcpiDsdt, "PBTN");
1349
1350 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
1351 RTAcpiTblEisaIdAppend(m_hAcpiDsdt, "PNP0C0C");
1352
1353 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
1354 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
1355
1356 RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
1357
1358 RTAcpiTblDeviceStart(m_hAcpiDsdt, "SBTN");
1359
1360 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
1361 RTAcpiTblEisaIdAppend(m_hAcpiDsdt, "PNP0C0E");
1362
1363 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
1364 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
1365
1366 return RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
1367#else /* Works on new Linux guests but not Windows so far... */
1368 /* Use the approach from https://learn.microsoft.com/en-us/windows-hardware/drivers/hid/acpi-button-device . */
1369
1370 /* Device specific method. */
1371 RTAcpiTblMethodStart(m_hAcpiDsdt, "_DSM", 4, RTACPI_METHOD_F_SERIALIZED, 0 /*uSyncLvl*/);
1372
1373 RTAcpiTblIfStart(m_hAcpiDsdt);
1374
1375 /* Predicate (LEqual(Arg0, ToUUID("4f248f40-d5e2-499f-834c-27758ea1cd3f")))*/
1376 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1377 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 0);
1378 RTAcpiTblUuidAppendFromStr(m_hAcpiDsdt, "4f248f40-d5e2-499f-834c-27758ea1cd3f");
1379
1380 /* Standard _DSM query function. */
1381 RTAcpiTblIfStart(m_hAcpiDsdt);
1382
1383 /* LEqual(Arg2, Zero). */
1384 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1385 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
1386 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
1387
1388 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1389 uint8_t bBuf = 0x03;
1390 RTAcpiTblBufferAppend(m_hAcpiDsdt, &bBuf, sizeof(bBuf));
1391
1392 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1393
1394 /* Mark the pin for the power button as ActiveHigh. */
1395 RTAcpiTblIfStart(m_hAcpiDsdt);
1396
1397 /* LEqual(Arg2, One). */
1398 RTAcpiTblBinaryOpAppend(m_hAcpiDsdt, kAcpiBinaryOp_LEqual);
1399 RTAcpiTblArgOpAppend(m_hAcpiDsdt, 2);
1400 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1);
1401
1402 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1403 RTAcpiTblPackageStart(m_hAcpiDsdt, 2 /*cElements*/);
1404 RTAcpiTblIntegerAppend(m_hAcpiDsdt, u16PinShutdown);
1405 RTAcpiTblIntegerAppend(m_hAcpiDsdt, u16PinSuspend);
1406 RTAcpiTblPackageFinalize(m_hAcpiDsdt);
1407
1408 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1409
1410 /* Return Unknown function. */
1411 uint8_t bUnkFunc = 0x00;
1412 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1413 RTAcpiTblBufferAppend(m_hAcpiDsdt, &bUnkFunc, sizeof(bUnkFunc));
1414
1415 RTAcpiTblIfFinalize(m_hAcpiDsdt);
1416
1417 /* Return Unknown function. */
1418 bUnkFunc = 0x00;
1419 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1420 RTAcpiTblBufferAppend(m_hAcpiDsdt, &bUnkFunc, sizeof(bUnkFunc));
1421
1422 RTAcpiTblMethodFinalize(m_hAcpiDsdt);
1423
1424 RTAcpiTblDeviceFinalize(m_hAcpiDsdt); /* Finish the GPI0 GPIO device. */
1425
1426 RTAcpiTblDeviceStart(m_hAcpiDsdt, "BTNS");
1427
1428 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
1429 RTAcpiTblStringAppend(m_hAcpiDsdt, "ACPI0011");
1430
1431 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
1432 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
1433
1434 RTAcpiTblMethodStart(m_hAcpiDsdt, "_STA", 0, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
1435 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
1436 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x0f);
1437 RTAcpiTblMethodFinalize(m_hAcpiDsdt);
1438
1439 /* Build the resource template. */
1440 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CRS");
1441 RTAcpiResourceReset(m_hAcpiRes);
1442 vrc = RTAcpiResourceAddGpioInt(m_hAcpiRes, kAcpiResGpioMod_Edge, kAcpiResGpioPol_ActiveBoth, kAcpiResGpioShr_Exclusive,
1443 kAcpiResGpioPpi_PullDown, 0 /*u16DebounceWait*/, "\\_SB.GPI0",
1444 &u16PinShutdown, 1 /* cPins */);
1445 if (RT_SUCCESS(vrc))
1446 vrc = RTAcpiResourceAddGpioInt(m_hAcpiRes, kAcpiResGpioMod_Edge, kAcpiResGpioPol_ActiveBoth, kAcpiResGpioShr_Exclusive,
1447 kAcpiResGpioPpi_PullDown, 0 /*u16DebounceWait*/, "\\_SB.GPI0",
1448 &u16PinSuspend, 1 /* cPins */);
1449 if (RT_SUCCESS(vrc))
1450 {
1451 vrc = RTAcpiResourceSeal(m_hAcpiRes);
1452 if (RT_SUCCESS(vrc))
1453 vrc = RTAcpiTblResourceAppend(m_hAcpiDsdt, m_hAcpiRes);
1454 }
1455 AssertRCReturn(vrc, vrc);
1456
1457 RTAcpiTblNameAppend(m_hAcpiDsdt, "_DSD");
1458 RTAcpiTblPackageStart(m_hAcpiDsdt, 2 /*cElements*/);
1459 RTAcpiTblUuidAppendFromStr(m_hAcpiDsdt, "fa6bd625-9ce8-470d-a2c7-b3ca36c4282e");
1460 RTAcpiTblPackageStart(m_hAcpiDsdt, 3 /*cElements*/);
1461 RTAcpiTblPackageStart(m_hAcpiDsdt, 5 /*cElements*/);
1462 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0); /* Collection */
1463 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1); /* Unique collection ID */
1464 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0); /* Top-Level collection */
1465 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x01); /* Usage Page ("Generic Desktop Page") */
1466 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x0d); /* Usage ("Portable Device Control") */
1467 RTAcpiTblPackageFinalize(m_hAcpiDsdt);
1468
1469 RTAcpiTblPackageStart(m_hAcpiDsdt, 5 /*cElements*/);
1470 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1); /* Control */
1471 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0); /* Interrupt index in _CRS for power button */
1472 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1); /* Unique ID of parent collection */
1473 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x01); /* Usage Page ("Generic Desktop Page") */
1474 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x81); /* Usage ("System Power Down") */
1475 RTAcpiTblPackageFinalize(m_hAcpiDsdt);
1476
1477 RTAcpiTblPackageStart(m_hAcpiDsdt, 5 /*cElements*/);
1478 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1); /* Control */
1479 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1); /* Interrupt index in _CRS for power button */
1480 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1); /* Unique ID of parent collection */
1481 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x01); /* Usage Page ("Generic Desktop Page") */
1482 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x82); /* Usage ("System Sleep") */
1483 RTAcpiTblPackageFinalize(m_hAcpiDsdt);
1484
1485 RTAcpiTblPackageFinalize(m_hAcpiDsdt);
1486 RTAcpiTblPackageFinalize(m_hAcpiDsdt);
1487
1488 return RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
1489#endif
1490}
1491
1492
1493int SystemTableBuilder::initInstance(void)
1494{
1495 return VERR_NOT_IMPLEMENTED;
1496}
1497
1498
1499int SystemTableBuilder::finishTables(RTGCPHYS GCPhysTblsStart, RTVFSIOSTREAM hVfsIos,
1500 PRTGCPHYS pGCPhysTblRoot, size_t *pcbTblRoot, size_t *pcbTbls)
1501{
1502 RT_NOREF(GCPhysTblsStart, hVfsIos, pGCPhysTblRoot, pcbTblRoot, pcbTbls);
1503 return VERR_NOT_IMPLEMENTED;
1504}
1505
1506
1507int SystemTableBuilder::addCpu(uint32_t idCpu)
1508{
1509 RT_NOREF(idCpu);
1510 return VERR_NOT_IMPLEMENTED;
1511}
1512
1513
1514int SystemTableBuilder::addMemory(RTGCPHYS GCPhysStart, RTGCPHYS cbMem)
1515{
1516 RT_NOREF(GCPhysStart, cbMem);
1517 return VERR_NOT_IMPLEMENTED;
1518}
1519
1520
1521int SystemTableBuilder::addMmioDeviceNoIrq(const char *pszVBoxName, uint32_t uInstance, RTGCPHYS GCPhysMmio, RTGCPHYS cbMmio)
1522{
1523 RT_NOREF(pszVBoxName, uInstance, GCPhysMmio, cbMmio);
1524 return VERR_NOT_IMPLEMENTED;
1525}
1526
1527
1528int SystemTableBuilder::addMmioDevice(const char *pszVBoxName, uint32_t uInstance, RTGCPHYS GCPhysMmio, RTGCPHYS cbMmio, uint32_t u32Irq)
1529{
1530 RT_NOREF(pszVBoxName, uInstance, GCPhysMmio, cbMmio, u32Irq);
1531 return VERR_NOT_IMPLEMENTED;
1532}
1533
1534
1535int SystemTableBuilder::configureGic(uint32_t cCpus, RTGCPHYS GCPhysIntcDist, RTGCPHYS cbMmioIntcDist, RTGCPHYS GCPhysIntcReDist,
1536 RTGCPHYS cbMmioIntcReDist, RTGCPHYS GCPhysIntcIts, RTGCPHYS cbMmioIntcIts)
1537{
1538 RT_NOREF(cCpus, GCPhysIntcDist, cbMmioIntcDist, GCPhysIntcReDist, cbMmioIntcReDist, GCPhysIntcIts, cbMmioIntcIts);
1539 return VERR_NOT_IMPLEMENTED;
1540}
1541
1542
1543int SystemTableBuilder::configureClock(void)
1544{
1545 return VERR_NOT_IMPLEMENTED;
1546}
1547
1548
1549int SystemTableBuilder::configurePcieRootBus(const char *pszVBoxName, uint32_t aPinIrqs[4], RTGCPHYS GCPhysMmioPio, RTGCPHYS GCPhysMmioEcam, size_t cbPciMmioEcam,
1550 RTGCPHYS GCPhysPciMmioBase, RTGCPHYS cbPciMmio, RTGCPHYS GCPhysPciMmio32Base, RTGCPHYS cbPciMmio32)
1551{
1552 RT_NOREF(pszVBoxName, aPinIrqs, GCPhysMmioPio, GCPhysMmioEcam, cbPciMmioEcam,
1553 GCPhysPciMmioBase, cbPciMmio, GCPhysPciMmio32Base, cbPciMmio32);
1554 return VERR_NOT_IMPLEMENTED;
1555}
1556
1557
1558int SystemTableBuilder::configureTpm2(bool fCrb, RTGCPHYS GCPhysMmioStart, RTGCPHYS cbMmio, uint32_t u32Irq)
1559{
1560 RT_NOREF(fCrb, GCPhysMmioStart, cbMmio, u32Irq);
1561 return VERR_NOT_IMPLEMENTED;
1562}
1563
1564
1565int SystemTableBuilder::configureGpioDevice(const char *pszVBoxName, uint32_t uInstance, RTGCPHYS GCPhysMmio, RTGCPHYS cbMmio, uint32_t u32Irq,
1566 uint16_t u16PinShutdown, uint16_t u16PinSuspend)
1567{
1568 RT_NOREF(pszVBoxName, uInstance, GCPhysMmio, cbMmio, u32Irq, u16PinShutdown, u16PinSuspend);
1569 return VERR_NOT_IMPLEMENTED;
1570}
1571
1572
1573int SystemTableBuilder::dumpTables(const char *pszFilename)
1574{
1575 RT_NOREF(pszFilename);
1576 return VERR_NOT_IMPLEMENTED;
1577}
1578
1579
1580SystemTableBuilder *SystemTableBuilder::createInstance(SYSTEMTABLETYPE enmTableType)
1581{
1582 AssertReturn(enmTableType == kSystemTableType_Acpi, NULL);
1583
1584 SystemTableBuilder *pInstance = new SystemTableBuilderAcpi();
1585 Assert(pInstance);
1586
1587 int vrc = pInstance->initInstance();
1588 if (RT_FAILURE(vrc))
1589 {
1590 delete pInstance;
1591 pInstance = NULL;
1592 }
1593
1594 return pInstance;
1595}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette