VirtualBox

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

Last change on this file since 106358 was 106358, checked in by vboxsync, 3 months ago

Main: Some early system table builder code to generate ACPI tables for a VM, bugref:10733 [scm]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.9 KB
Line 
1/* $Id: SystemTableBuilder.cpp 106358 2024-10-16 12:20:58Z 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* Structures and Typedefs *
45*********************************************************************************************************************************/
46/**
47 * A system table device.
48 */
49typedef struct SYSTEMTABLEDEVICE
50{
51 const char *pszVBoxName;
52 const char *pszFdtName;
53 const char *pszFdtCompatible;
54 const char *pszAcpiName;
55 const char *pszAcpiHid;
56} SYSTEMTABLEDEVICE;
57typedef SYSTEMTABLEDEVICE *PSYSTEMTABLEDEVICE;
58typedef const SYSTEMTABLEDEVICE *PCSYSTEMTABLEDEVICE;
59
60
61/*********************************************************************************************************************************
62* Global Variables *
63*********************************************************************************************************************************/
64static const SYSTEMTABLEDEVICE g_aSysTblDevices[] =
65{
66 { "qemu-fw-cfg", "fw-cfg", "qemu,fw-cfg-mmio", "FWC", "QEMU0002" },
67 { "arm-pl011", "pl011", "arm,pl011", "SRL", "ARMH0011" },
68 { "arm-pl061-gpio", "pl061", "arm,pl061", "GPI", "ARMH0061" },
69 { "pci-generic-ecam", "pcie", "pci-host-ecam-generic", "PCI", "PNP0A08" },
70};
71
72
73static PCSYSTEMTABLEDEVICE systemTableVBoxDevName2SysTblDevice(const char *pszVBoxName)
74{
75 for (uint32_t i = 0; i < RT_ELEMENTS(g_aSysTblDevices); i++)
76 if (!strcmp(pszVBoxName, g_aSysTblDevices[i].pszVBoxName))
77 return &g_aSysTblDevices[i];
78
79 return NULL;
80}
81
82
83static int systemTableAcpiMmioDevResource(RTACPITBL hDsdt, RTACPIRES hAcpiRes, uint64_t u64AddrBase,
84 uint64_t cbMmio, uint32_t uIrq)
85{
86 uint32_t const fAddrSpace = RTACPI_RESOURCE_ADDR_RANGE_F_DECODE_TYPE_POS
87 | RTACPI_RESOURCE_ADDR_RANGE_F_MIN_ADDR_FIXED
88 | RTACPI_RESOURCE_ADDR_RANGE_F_MAX_ADDR_FIXED;
89
90 RTAcpiResourceReset(hAcpiRes);
91 int vrc = RTAcpiResourceAddQWordMemoryRange(hAcpiRes, kAcpiResMemRangeCacheability_NonCacheable, kAcpiResMemType_Memory, true /*fRw*/,
92 fAddrSpace, u64AddrBase, u64AddrBase + cbMmio - 1, 0 /*u64OffTrans*/, 0 /*u64Granularity*/,
93 cbMmio);
94 if (RT_SUCCESS(vrc))
95 vrc = RTAcpiResourceAddExtendedInterrupt(hAcpiRes, true /*fConsumer*/, false /*fEdgeTriggered*/, false /*fActiveLow*/,
96 false /*fShared*/, false /*fWakeCapable*/, 1, &uIrq);
97 if (RT_SUCCESS(vrc))
98 {
99 vrc = RTAcpiResourceSeal(hAcpiRes);
100 if (RT_SUCCESS(vrc))
101 vrc = RTAcpiTblResourceAppend(hDsdt, hAcpiRes);
102 }
103
104 return vrc;
105}
106
107
108static int systemTableAcpiMmioDevResourceNoIrq(RTACPITBL hDsdt, RTACPIRES hAcpiRes, uint64_t u64AddrBase,
109 uint64_t cbMmio)
110{
111 uint32_t const fAddrSpace = RTACPI_RESOURCE_ADDR_RANGE_F_DECODE_TYPE_POS
112 | RTACPI_RESOURCE_ADDR_RANGE_F_MIN_ADDR_FIXED
113 | RTACPI_RESOURCE_ADDR_RANGE_F_MAX_ADDR_FIXED;
114
115 RTAcpiResourceReset(hAcpiRes);
116 int vrc = RTAcpiResourceAddQWordMemoryRange(hAcpiRes, kAcpiResMemRangeCacheability_NonCacheable, kAcpiResMemType_Memory, true /*fRw*/,
117 fAddrSpace, u64AddrBase, u64AddrBase + cbMmio - 1, 0 /*u64OffTrans*/, 0 /*u64Granularity*/,
118 cbMmio);
119 if (RT_SUCCESS(vrc))
120 {
121 vrc = RTAcpiResourceSeal(hAcpiRes);
122 if (RT_SUCCESS(vrc))
123 vrc = RTAcpiTblResourceAppend(hDsdt, hAcpiRes);
124 }
125
126 return vrc;
127}
128
129
130int SystemTableBuilderAcpi::initInstance(void)
131{
132 m_fTpm20 = false;
133
134 int vrc = RTAcpiTblCreate(&m_hAcpiDsdt, ACPI_TABLE_HDR_SIGNATURE_DSDT, 6, "ORCL ", "VBOXDSDT", 1, "VBOX", 1);
135 AssertRCReturn(vrc, vrc);
136
137 vrc = RTAcpiResourceCreate(&m_hAcpiRes);
138 AssertRCReturn(vrc, vrc);
139
140 /* Append _SB Scope. */
141 return RTAcpiTblScopeStart(m_hAcpiDsdt, "\\_SB");
142}
143
144
145int SystemTableBuilderAcpi::finishTables(RTGCPHYS GCPhysTblsStart, RTVFSIOSTREAM hVfsIos,
146 PRTGCPHYS pGCPhysTblRoot, size_t *pcbTblRoot, size_t *pcbTbls)
147{
148 int vrc = RTAcpiTblScopeFinalize(m_hAcpiDsdt); /* End \_SB scope */
149 AssertRCReturn(vrc, vrc);
150
151 vrc = RTAcpiTblFinalize(m_hAcpiDsdt);
152 AssertRCReturn(vrc, vrc);
153
154 RTGCPHYS GCPhysDsdt = GCPhysTblsStart;
155
156 size_t cbAcpiTbls = RTAcpiTblGetSize(m_hAcpiDsdt);
157 Assert(cbAcpiTbls);
158
159 /* Write the DSDT. */
160 vrc = RTAcpiTblDumpToVfsIoStrm(m_hAcpiDsdt, hVfsIos);
161 AssertRCReturn(vrc, vrc);
162
163 GCPhysTblsStart += cbAcpiTbls;
164
165 uint32_t cTbls = 0;
166 uint8_t abXsdt[36 + 32 * sizeof(uint64_t)]; RT_ZERO(abXsdt);
167 PACPIXSDT pXsdt = (PACPIXSDT)&abXsdt[0];
168
169 /* Build the FADT. */
170 size_t cbTbl = 0;
171 vrc = buildFadt(hVfsIos, GCPhysDsdt, &cbTbl);
172 AssertRCReturn(vrc, vrc);
173
174 pXsdt->au64AddrTbl[cTbls++] = GCPhysTblsStart;
175 cbAcpiTbls += cbTbl;
176 GCPhysTblsStart += cbTbl;
177
178 /* Build the GTDT. */
179 vrc = buildGtdt(hVfsIos, &cbTbl);
180 AssertRCReturn(vrc, vrc);
181
182 pXsdt->au64AddrTbl[cTbls++] = GCPhysTblsStart;
183 cbAcpiTbls += cbTbl;
184 GCPhysTblsStart += cbTbl;
185
186 /* Build the MADT. */
187 vrc = buildMadt(hVfsIos, &cbTbl);
188 AssertRCReturn(vrc, vrc);
189
190 pXsdt->au64AddrTbl[cTbls++] = GCPhysTblsStart;
191 cbAcpiTbls += cbTbl;
192 GCPhysTblsStart += cbTbl;
193
194 /* Build the MCFG. */
195 vrc = buildMcfg(hVfsIos, &cbTbl);
196 AssertRCReturn(vrc, vrc);
197
198 pXsdt->au64AddrTbl[cTbls++] = GCPhysTblsStart;
199 cbAcpiTbls += cbTbl;
200 GCPhysTblsStart += cbTbl;
201
202 /* Build TPM2 table if configured. */
203 if (m_fTpm20)
204 {
205 vrc = buildTpm20(hVfsIos, &cbTbl);
206 AssertRCReturn(vrc, vrc);
207
208 pXsdt->au64AddrTbl[cTbls++] = GCPhysTblsStart;
209 cbAcpiTbls += cbTbl;
210 GCPhysTblsStart += cbTbl;
211 }
212
213 /* Build XSDT. */
214 RTGCPHYS GCPhysXsdt = GCPhysTblsStart;
215 size_t const cbXsdt = RT_UOFFSETOF_DYN(ACPIXSDT, au64AddrTbl[cTbls]);
216 pXsdt->Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_XSDT;
217 pXsdt->Hdr.cbTbl = RT_UOFFSETOF_DYN(ACPIXSDT, au64AddrTbl[cTbls]);
218 pXsdt->Hdr.bRevision = 6;
219 pXsdt->Hdr.bChkSum = 0;
220 pXsdt->Hdr.u32OemRevision = 1;
221 pXsdt->Hdr.u32CreatorRevision = 1;
222
223 memcpy(&pXsdt->Hdr.abOemId[0], "ORCLVB", 6);
224 memcpy(&pXsdt->Hdr.abOemTblId[0], "ORCL", 4);
225 memcpy(&pXsdt->Hdr.abOemTblId[4], &pXsdt->Hdr.u32Signature, 4);
226 memcpy(&pXsdt->Hdr.abCreatorId[0], "ORCL", 4);
227 RTAcpiTblHdrChecksumGenerate(&pXsdt->Hdr, cbXsdt);
228 vrc = RTVfsIoStrmWrite(hVfsIos, &abXsdt[0], cbXsdt, true /*fBlocking*/, NULL /*pcbWritten*/);
229 AssertRCReturn(vrc, vrc);
230
231 GCPhysTblsStart += cbXsdt;
232 cbAcpiTbls += cbXsdt;
233
234 /* Build XSDP */
235 ACPIRSDP Xsdp; RT_ZERO(Xsdp);
236
237 /* ACPI 1.0 part (RSDT) */
238 memcpy(Xsdp.abSignature, "RSD PTR ", 8);
239 memcpy(Xsdp.abOemId, "ORCLVB", 6);
240 Xsdp.bRevision = 3;
241 Xsdp.u32AddrRsdt = 0;
242 Xsdp.bChkSum = RTAcpiChecksumGenerate(&Xsdp, RT_OFFSETOF(ACPIRSDP, cbRsdp));
243
244 /* ACPI 2.0 part (XSDT) */
245 Xsdp.cbRsdp = RT_H2LE_U32(sizeof(ACPIRSDP));
246 Xsdp.u64AddrXsdt = RT_H2LE_U64(GCPhysXsdt);
247 Xsdp.bExtChkSum = RTAcpiChecksumGenerate(&Xsdp, sizeof(ACPIRSDP));
248
249 vrc = RTVfsIoStrmWrite(hVfsIos, &Xsdp, sizeof(Xsdp), true /*fBlocking*/, NULL /*pcbWritten*/);
250 AssertRCReturn(vrc, vrc);
251 cbAcpiTbls += sizeof(Xsdp);
252
253 *pGCPhysTblRoot = GCPhysTblsStart;
254 *pcbTblRoot = sizeof(Xsdp);
255 *pcbTbls = cbAcpiTbls;
256
257 return VINF_SUCCESS;
258}
259
260
261int SystemTableBuilderAcpi::addCpu(uint32_t idCpu)
262{
263 RTAcpiTblDeviceStartF(m_hAcpiDsdt, "CP%02RX32", idCpu);
264
265 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
266 RTAcpiTblStringAppend(m_hAcpiDsdt, "ACPI0007");
267
268 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
269 RTAcpiTblIntegerAppend(m_hAcpiDsdt, idCpu);
270
271 return RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
272}
273
274
275int SystemTableBuilderAcpi::addMemory(RTGCPHYS GCPhysStart, RTGCPHYS cbMem)
276{
277 RT_NOREF(GCPhysStart, cbMem);
278 return VINF_SUCCESS;
279}
280
281
282int SystemTableBuilderAcpi::addMmioDeviceNoIrq(const char *pszVBoxName, uint32_t uInstance, RTGCPHYS GCPhysMmio, RTGCPHYS cbMmio)
283{
284 PCSYSTEMTABLEDEVICE pSysTblDev = systemTableVBoxDevName2SysTblDevice(pszVBoxName);
285 AssertPtrReturn(pSysTblDev, VERR_NOT_FOUND);
286
287 RTAcpiTblDeviceStartF(m_hAcpiDsdt, "%s%RX32", pSysTblDev->pszAcpiName, uInstance);
288
289 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
290 RTAcpiTblStringAppend(m_hAcpiDsdt, pSysTblDev->pszAcpiHid);
291
292 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
293 RTAcpiTblIntegerAppend(m_hAcpiDsdt, uInstance);
294
295 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CRS");
296 int vrc = systemTableAcpiMmioDevResourceNoIrq(m_hAcpiDsdt, m_hAcpiRes, GCPhysMmio, cbMmio);
297 AssertRCReturn(vrc, vrc);
298
299 return RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
300}
301
302
303int SystemTableBuilderAcpi::addMmioDevice(const char *pszVBoxName, uint32_t uInstance, RTGCPHYS GCPhysMmio, RTGCPHYS cbMmio,
304 uint32_t u32Irq)
305{
306 PCSYSTEMTABLEDEVICE pSysTblDev = systemTableVBoxDevName2SysTblDevice(pszVBoxName);
307 AssertPtrReturn(pSysTblDev, VERR_NOT_FOUND);
308
309 RTAcpiTblDeviceStartF(m_hAcpiDsdt, "%s%RX32", pSysTblDev->pszAcpiName, uInstance);
310
311 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
312 RTAcpiTblStringAppend(m_hAcpiDsdt, pSysTblDev->pszAcpiHid);
313
314 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
315 RTAcpiTblIntegerAppend(m_hAcpiDsdt, uInstance);
316
317 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CRS");
318 int vrc = systemTableAcpiMmioDevResource(m_hAcpiDsdt, m_hAcpiRes, GCPhysMmio, cbMmio, u32Irq + GIC_INTID_RANGE_SPI_START);
319 AssertRCReturn(vrc, vrc);
320
321 return RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
322}
323
324
325int SystemTableBuilderAcpi::configureGic(uint32_t cCpus, RTGCPHYS GCPhysIntcDist, RTGCPHYS cbMmioIntcDist, RTGCPHYS GCPhysIntcReDist,
326 RTGCPHYS cbMmioIntcReDist)
327{
328 m_cCpus = cCpus;
329 m_GCPhysIntcDist = GCPhysIntcDist;
330 m_cbMmioIntcDist = cbMmioIntcDist;
331 m_GCPhysIntcReDist = GCPhysIntcReDist;
332 m_cbMmioIntcReDist = cbMmioIntcReDist;
333 return VINF_SUCCESS;
334}
335
336
337int SystemTableBuilderAcpi::configureClock(void)
338{
339 return VINF_SUCCESS;
340}
341
342
343int SystemTableBuilderAcpi::configurePcieRootBus(const char *pszVBoxName, uint32_t aPinIrqs[4], RTGCPHYS GCPhysMmioPio, RTGCPHYS GCPhysMmioEcam, size_t cbPciMmioEcam,
344 RTGCPHYS GCPhysPciMmioBase, RTGCPHYS cbPciMmio, RTGCPHYS GCPhysPciMmio32Base, RTGCPHYS cbPciMmio32)
345{
346 PCSYSTEMTABLEDEVICE pSysTblDev = systemTableVBoxDevName2SysTblDevice(pszVBoxName);
347 AssertPtrReturn(pSysTblDev, VERR_NOT_FOUND);
348
349 m_GCPhysPciMmioEcam = GCPhysMmioEcam; /* Need that for MCFG later. */
350
351 RTAcpiTblDeviceStartF(m_hAcpiDsdt, "%s%RX32", pSysTblDev->pszAcpiName, 0);
352
353 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
354 RTAcpiTblStringAppend(m_hAcpiDsdt, pSysTblDev->pszAcpiHid);
355
356 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CID");
357 RTAcpiTblStringAppend(m_hAcpiDsdt, "PNP0A03"); /** @todo */
358
359 RTAcpiTblNameAppend(m_hAcpiDsdt, "_UID");
360 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0);
361
362 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CCA"); /* Cache coherency attribute. */
363 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 1);
364
365 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CRS");
366
367 uint32_t const fAddrSpace = RTACPI_RESOURCE_ADDR_RANGE_F_DECODE_TYPE_POS
368 | RTACPI_RESOURCE_ADDR_RANGE_F_MIN_ADDR_FIXED
369 | RTACPI_RESOURCE_ADDR_RANGE_F_MAX_ADDR_FIXED;
370
371 RTAcpiResourceReset(m_hAcpiRes);
372 int vrc = RTAcpiResourceAddWordBusNumber(m_hAcpiRes, fAddrSpace, 0 /*u16BusMin*/, 0xff /*u16BusMax*/,
373 0 /*u16OffTrans*/, 0 /*u16Granularity*/, 256 /*u16Length*/);
374 AssertRCReturn(vrc, vrc);
375
376 vrc = RTAcpiResourceAddQWordIoRange(m_hAcpiRes, kAcpiResIoRangeType_Translation_Dense, kAcpiResIoRange_Whole,
377 fAddrSpace, 0 /*u64AddrMin*/, UINT16_MAX /*u64AddrMax*/, GCPhysMmioPio,
378 0 /*u64Granularity*/, _64K);
379 AssertRCReturn(vrc, vrc);
380
381 vrc = RTAcpiResourceAddDWordMemoryRange(m_hAcpiRes, kAcpiResMemRangeCacheability_NonCacheable, kAcpiResMemType_Memory, true /*fRw*/,
382 fAddrSpace, (uint32_t)GCPhysPciMmio32Base, (uint32_t)(GCPhysPciMmio32Base + cbPciMmio32 - 1),
383 0 /*u32OffTrans*/, 0 /*u32Granularity*/, (uint32_t)cbPciMmio32);
384 AssertRCReturn(vrc, vrc);
385
386 vrc = RTAcpiResourceAddQWordMemoryRange(m_hAcpiRes, kAcpiResMemRangeCacheability_NonCacheable, kAcpiResMemType_Memory, true /*fRw*/,
387 fAddrSpace, GCPhysPciMmioBase, GCPhysPciMmioBase + cbPciMmio - 1,
388 0 /*u64OffTrans*/, 0 /*u64Granularity*/, cbPciMmio);
389 if (RT_SUCCESS(vrc))
390 {
391 vrc = RTAcpiResourceSeal(m_hAcpiRes);
392 if (RT_SUCCESS(vrc))
393 vrc = RTAcpiTblResourceAppend(m_hAcpiDsdt, m_hAcpiRes);
394 }
395
396 /* For the ECAM base we need to define a new device with a new resource template inside the PCI device. */
397 RTAcpiTblDeviceStart(m_hAcpiDsdt, "RES0");
398
399 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
400 RTAcpiTblStringAppend(m_hAcpiDsdt, "PNP0C02");
401
402 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CRS");
403 RTAcpiResourceReset(m_hAcpiRes);
404 vrc = RTAcpiResourceAddQWordMemoryRange(m_hAcpiRes, kAcpiResMemRangeCacheability_NonCacheable, kAcpiResMemType_Memory, true /*fRw*/,
405 fAddrSpace, GCPhysMmioEcam, GCPhysMmioEcam + cbPciMmioEcam - 1,
406 0 /*u64OffTrans*/, 0 /*u64Granularity*/, cbPciMmioEcam);
407 if (RT_SUCCESS(vrc))
408 {
409 vrc = RTAcpiResourceSeal(m_hAcpiRes);
410 if (RT_SUCCESS(vrc))
411 vrc = RTAcpiTblResourceAppend(m_hAcpiDsdt, m_hAcpiRes);
412 }
413
414 /* Finish RES0 device. */
415 vrc = RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
416 AssertRCReturn(vrc, vrc);
417
418 /* Build the PCI interrupt routing table (_PRT). */
419 RTAcpiTblNameAppend(m_hAcpiDsdt, "_PRT");
420 RTAcpiTblPackageStart(m_hAcpiDsdt, 32 * 4);
421
422 uint32_t iIrqPinSwizzle = 0;
423
424 for (uint32_t i = 0; i < 32; i++)
425 {
426 for (uint32_t iIrqPin = 0; iIrqPin < 4; iIrqPin++)
427 {
428 RTAcpiTblPackageStart(m_hAcpiDsdt, 4);
429 RTAcpiTblIntegerAppend(m_hAcpiDsdt, (i << 16) | 0xffff); /* ACPI PCI address. */
430 RTAcpiTblIntegerAppend(m_hAcpiDsdt, iIrqPin); /* Interrupt pin (INTA, INTB, ...). */
431 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0); /* Interrupt destination, unused. */
432 RTAcpiTblIntegerAppend(m_hAcpiDsdt, GIC_INTID_RANGE_SPI_START
433 + aPinIrqs[(iIrqPinSwizzle + iIrqPin) % 4]); /* GSI of the interrupt. */
434 RTAcpiTblPackageFinalize(m_hAcpiDsdt);
435 }
436
437 iIrqPinSwizzle++;
438 }
439
440 RTAcpiTblPackageFinalize(m_hAcpiDsdt);
441
442 /* Create _CBA for the ECAM base. */
443 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CBA");
444 RTAcpiTblIntegerAppend(m_hAcpiDsdt, GCPhysMmioEcam);
445
446 return RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
447}
448
449
450int SystemTableBuilderAcpi::dumpTables(const char *pszFilename)
451{
452 return RTAcpiTblDumpToFile(m_hAcpiDsdt, pszFilename);
453}
454
455
456int SystemTableBuilderAcpi::buildMadt(RTVFSIOSTREAM hVfsIos, size_t *pcbMadt)
457{
458 uint8_t abMadt[_4K];
459 size_t cbMadt = 0;
460
461 RT_ZERO(abMadt);
462
463 PACPIMADT pMadt = (PACPIMADT)&abMadt[0];
464 PACPIMADTGICC pGicc = (PACPIMADTGICC)(pMadt + 1);
465
466 cbMadt += sizeof(*pMadt);
467
468 /* Include a GIC CPU interface for each CPU. */
469 for (uint32_t i = 0; i < m_cCpus; i++)
470 {
471 pGicc->bType = ACPI_MADT_INTR_CTRL_TYPE_GICC;
472 pGicc->cbThis = sizeof(*pGicc);
473 pGicc->u32CpuId = i;
474 pGicc->u32AcpiCpuUid = i;
475 pGicc->fGicc = ACPI_MADT_GICC_F_ENABLED;
476 pGicc->u64Mpidr = i;
477
478 cbMadt += sizeof(*pGicc);
479 pGicc++;
480 }
481
482 /* Build the GICD. */
483 PACPIMADTGICD pGicd = (PACPIMADTGICD)pGicc;
484 pGicd->bType = ACPI_MADT_INTR_CTRL_TYPE_GICD;
485 pGicd->cbThis = sizeof(*pGicd);
486 pGicd->u64PhysAddrBase = m_GCPhysIntcDist;
487 pGicd->bGicVersion = ACPI_MADT_GICD_VERSION_GICv3;
488
489 cbMadt += sizeof(*pGicd);
490
491 /* Build the GICR. */
492 PACPIMADTGICR pGicr = (PACPIMADTGICR)(pGicd + 1);
493 pGicr->bType = ACPI_MADT_INTR_CTRL_TYPE_GICR;
494 pGicr->cbThis = sizeof(*pGicr);
495 pGicr->u64PhysAddrGicrRangeBase = m_GCPhysIntcReDist;
496 pGicr->cbGicrRange = m_cbMmioIntcReDist;
497
498 cbMadt += sizeof(*pGicr);
499
500 /* Finalize the MADT. */
501 pMadt->Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_APIC;
502 pMadt->Hdr.cbTbl = cbMadt;
503 pMadt->Hdr.bRevision = 6;
504 pMadt->Hdr.bChkSum = 0;
505 pMadt->Hdr.u32OemRevision = 1;
506 pMadt->Hdr.u32CreatorRevision = 1;
507
508 memcpy(&pMadt->Hdr.abOemId[0], "ORCLVB", 6);
509 memcpy(&pMadt->Hdr.abOemTblId[0], "ORCL", 4);
510 memcpy(&pMadt->Hdr.abOemTblId[4], &pMadt->Hdr.u32Signature, 4);
511 memcpy(&pMadt->Hdr.abCreatorId[0], "ORCL", 4);
512 RTAcpiTblHdrChecksumGenerate(&pMadt->Hdr, cbMadt);
513 *pcbMadt = cbMadt;
514 return RTVfsIoStrmWrite(hVfsIos, pMadt, cbMadt, true /*fBlocking*/, NULL /*pcbWritten*/);
515}
516
517
518int SystemTableBuilderAcpi::buildMcfg(RTVFSIOSTREAM hVfsIos, size_t *pcbMcfg)
519{
520 uint8_t abMcfg[_1K];
521 size_t cbMcfg = 0;
522
523 RT_ZERO(abMcfg);
524
525 PACPIMCFG pMcfg = (PACPIMCFG)&abMcfg[0];
526 PACPIMCFGALLOC pAlloc = (PACPIMCFGALLOC)(pMcfg + 1);
527
528 cbMcfg += sizeof(*pMcfg) + sizeof(*pAlloc);
529
530 pAlloc->u64PhysAddrBase = m_GCPhysPciMmioEcam;
531 pAlloc->u16PciSegGrpNr = 0;
532 pAlloc->bPciBusFirst = 0;
533 pAlloc->bPciBusLast = 0xff;
534
535 /* Finalize the MADT. */
536 pMcfg->Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_RSVD_MCFG;
537 pMcfg->Hdr.cbTbl = cbMcfg;
538 pMcfg->Hdr.bRevision = 6;
539 pMcfg->Hdr.bChkSum = 0;
540 pMcfg->Hdr.u32OemRevision = 1;
541 pMcfg->Hdr.u32CreatorRevision = 1;
542
543 memcpy(&pMcfg->Hdr.abOemId[0], "ORCLVB", 6);
544 memcpy(&pMcfg->Hdr.abOemTblId[0], "ORCL", 4);
545 memcpy(&pMcfg->Hdr.abOemTblId[4], &pMcfg->Hdr.u32Signature, 4);
546 memcpy(&pMcfg->Hdr.abCreatorId[0], "ORCL", 4);
547 RTAcpiTblHdrChecksumGenerate(&pMcfg->Hdr, cbMcfg);
548 *pcbMcfg = cbMcfg;
549 return RTVfsIoStrmWrite(hVfsIos, pMcfg, cbMcfg, true /*fBlocking*/, NULL /*pcbWritten*/);
550}
551
552
553int SystemTableBuilderAcpi::buildGtdt(RTVFSIOSTREAM hVfsIos, size_t *pcbGtdt)
554{
555 ACPIGTDT Gtdt; RT_ZERO(Gtdt);
556
557#if 1
558 Gtdt.u64PhysAddrCntControlBase = UINT64_MAX;
559 Gtdt.u32Rsvd = 0;
560 Gtdt.u32El1SecTimerGsiv = 0;
561 Gtdt.fEl1SecTimer = 0;
562 Gtdt.u32El1NonSecTimerGsiv = 0x1a; /** @todo */
563 Gtdt.fEl1NonSecTimer = ACPI_GTDT_TIMER_F_INTR_MODE_LEVEL | ACPI_GTDT_TIMER_F_INTR_POLARITY_ACTIVE_HIGH | ACPI_GTDT_TIMER_F_ALWAYS_ON_CAP;
564 Gtdt.u32El1VirtTimerGsiv = 0x1b; /** @todo */
565 Gtdt.fEl1VirtTimer = ACPI_GTDT_TIMER_F_INTR_MODE_LEVEL | ACPI_GTDT_TIMER_F_INTR_POLARITY_ACTIVE_HIGH;
566 Gtdt.u32El2TimerGsiv = 0x1e;
567 Gtdt.fEl2Timer = ACPI_GTDT_TIMER_F_INTR_MODE_LEVEL | ACPI_GTDT_TIMER_F_INTR_POLARITY_ACTIVE_HIGH;
568 Gtdt.u64PhysAddrCndReadBase = UINT64_MAX;
569 Gtdt.cPlatformTimers = 0;
570 Gtdt.offPlatformTimers = 0;
571 Gtdt.u32El2VirtTimerGsiv = 0;
572 Gtdt.fEl2VirtTimer = 0;
573#else /* Nested virt config on AppleSilicon. */
574 Gtdt.u64PhysAddrCntControlBase = UINT64_MAX;
575 Gtdt.u32Rsvd = 0;
576 Gtdt.u32El1SecTimerGsiv = 0;
577 Gtdt.fEl1SecTimer = 0;
578 Gtdt.u32El1NonSecTimerGsiv = 0x1e; /** @todo */
579 Gtdt.fEl1NonSecTimer = ACPI_GTDT_TIMER_F_INTR_MODE_LEVEL | ACPI_GTDT_TIMER_F_INTR_POLARITY_ACTIVE_HIGH | ACPI_GTDT_TIMER_F_ALWAYS_ON_CAP;
580 Gtdt.u32El1VirtTimerGsiv = 0x1b; /** @todo */
581 Gtdt.fEl1VirtTimer = ACPI_GTDT_TIMER_F_INTR_MODE_LEVEL | ACPI_GTDT_TIMER_F_INTR_POLARITY_ACTIVE_HIGH;
582 Gtdt.u32El2TimerGsiv = 0x1a;
583 Gtdt.fEl2Timer = ACPI_GTDT_TIMER_F_INTR_MODE_LEVEL | ACPI_GTDT_TIMER_F_INTR_POLARITY_ACTIVE_HIGH;
584 Gtdt.u64PhysAddrCndReadBase = UINT64_MAX;
585 Gtdt.cPlatformTimers = 0;
586 Gtdt.offPlatformTimers = 0;
587 Gtdt.u32El2VirtTimerGsiv = 0;
588 Gtdt.fEl2VirtTimer = 0;
589#endif
590
591 Gtdt.Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_GTDT;
592 Gtdt.Hdr.cbTbl = sizeof(Gtdt);
593 Gtdt.Hdr.bRevision = 6;
594 Gtdt.Hdr.bChkSum = 0;
595 Gtdt.Hdr.u32OemRevision = 1;
596 Gtdt.Hdr.u32CreatorRevision = 1;
597
598 memcpy(&Gtdt.Hdr.abOemId[0], "ORCLVB", 6);
599 memcpy(&Gtdt.Hdr.abOemTblId[0], "ORCL", 4);
600 memcpy(&Gtdt.Hdr.abOemTblId[4], &Gtdt.Hdr.u32Signature, 4);
601 memcpy(&Gtdt.Hdr.abCreatorId[0], "ORCL", 4);
602 RTAcpiTblHdrChecksumGenerate(&Gtdt.Hdr, sizeof(Gtdt));
603 *pcbGtdt = sizeof(Gtdt);
604 return RTVfsIoStrmWrite(hVfsIos, &Gtdt, sizeof(Gtdt), true /*fBlocking*/, NULL /*pcbWritten*/);
605}
606
607
608int SystemTableBuilderAcpi::buildFadt(RTVFSIOSTREAM hVfsIos, RTGCPHYS GCPhysXDsdt, size_t *pcbFadt)
609{
610 /* Build FADT. */
611 ACPIFADT Fadt; RT_ZERO(Fadt);
612
613 Fadt.fFeatures = ACPI_FADT_F_HW_REDUCED_ACPI;
614 Fadt.fArmBootArch = ACPI_FADT_ARM_BOOT_ARCH_F_PSCI_COMP
615 | ACPI_FADT_ARM_BOOT_ARCH_F_PSCI_USE_HVC;
616 Fadt.bFadtVersionMinor = 3;
617 Fadt.u64AddrXDsdt = GCPhysXDsdt;
618
619 Fadt.Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_FACP;
620 Fadt.Hdr.cbTbl = sizeof(Fadt);
621 Fadt.Hdr.bRevision = 6;
622 Fadt.Hdr.bChkSum = 0;
623 Fadt.Hdr.u32OemRevision = 1;
624 Fadt.Hdr.u32CreatorRevision = 1;
625
626 memcpy(&Fadt.Hdr.abOemId[0], "ORCLVB", 6);
627 memcpy(&Fadt.Hdr.abOemTblId[0], "ORCL", 4);
628 memcpy(&Fadt.Hdr.abOemTblId[4], &Fadt.Hdr.u32Signature, 4);
629 memcpy(&Fadt.Hdr.abCreatorId[0], "ORCL", 4);
630 RTAcpiTblHdrChecksumGenerate(&Fadt.Hdr, sizeof(Fadt));
631 *pcbFadt = sizeof(Fadt);
632 return RTVfsIoStrmWrite(hVfsIos, &Fadt, sizeof(Fadt), true /*fBlocking*/, NULL /*pcbWritten*/);
633}
634
635
636int SystemTableBuilderAcpi::buildTpm20(RTVFSIOSTREAM hVfsIos, size_t *pcbTpm20)
637{
638 Assert(m_fTpm20);
639
640 ACPITPM20 Tpm2;
641 RT_ZERO(Tpm2);
642
643 Tpm2.u32StartMethod = m_fCrb ? ACPITBL_TPM20_START_METHOD_CRB : ACPITBL_TPM20_START_METHOD_TIS12;
644 Tpm2.u64BaseAddrCrbOrFifo = m_GCPhysTpm20Mmio;
645 Tpm2.u16PlatCls = ACPITBL_TPM20_PLAT_CLS_CLIENT;
646
647 Tpm2.Hdr.u32Signature = ACPI_TABLE_HDR_SIGNATURE_RSVD_TPM2;
648 Tpm2.Hdr.cbTbl = sizeof(Tpm2);
649 Tpm2.Hdr.bRevision = ACPI_TPM20_REVISION;
650 Tpm2.Hdr.bChkSum = 0;
651 Tpm2.Hdr.u32OemRevision = 1;
652 Tpm2.Hdr.u32CreatorRevision = 1;
653
654 memcpy(&Tpm2.Hdr.abOemId[0], "ORCLVB", 6);
655 memcpy(&Tpm2.Hdr.abOemTblId[0], "ORCL", 4);
656 memcpy(&Tpm2.Hdr.abOemTblId[4], &Tpm2.Hdr.u32Signature, 4);
657 memcpy(&Tpm2.Hdr.abCreatorId[0], "ORCL", 4);
658 RTAcpiTblHdrChecksumGenerate(&Tpm2.Hdr, sizeof(Tpm2));
659 *pcbTpm20 = sizeof(Tpm2);
660 return RTVfsIoStrmWrite(hVfsIos, &Tpm2, sizeof(Tpm2), true /*fBlocking*/, NULL /*pcbWritten*/);
661}
662
663
664int SystemTableBuilderAcpi::configureTpm2(bool fCrb, RTGCPHYS GCPhysMmioStart, RTGCPHYS cbMmio, uint32_t u32Irq)
665{
666 m_fTpm20 = true;
667 m_fCrb = fCrb;
668 m_GCPhysTpm20Mmio = GCPhysMmioStart;
669
670 RTAcpiTblDeviceStartF(m_hAcpiDsdt, "TPM0");
671
672 RTAcpiTblNameAppend(m_hAcpiDsdt, "_HID");
673 RTAcpiTblStringAppend(m_hAcpiDsdt, "MSFT0101");
674
675 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CID");
676 RTAcpiTblStringAppend(m_hAcpiDsdt, "MSFT0101");
677
678 RTAcpiTblNameAppend(m_hAcpiDsdt, "_STR");
679 RTAcpiTblStringAppend(m_hAcpiDsdt, "TPM 2.0 Device");
680
681 RTAcpiTblNameAppend(m_hAcpiDsdt, "_CRS");
682 int vrc = systemTableAcpiMmioDevResource(m_hAcpiDsdt, m_hAcpiRes, GCPhysMmioStart, cbMmio, u32Irq + GIC_INTID_RANGE_SPI_START);
683 AssertRCReturn(vrc, vrc);
684
685 RTAcpiTblMethodStart(m_hAcpiDsdt, "_STA", 0, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
686 RTAcpiTblStmtSimpleAppend(m_hAcpiDsdt, kAcpiStmt_Return);
687 RTAcpiTblIntegerAppend(m_hAcpiDsdt, 0x0f);
688 RTAcpiTblMethodFinalize(m_hAcpiDsdt);
689
690 return RTAcpiTblDeviceFinalize(m_hAcpiDsdt);
691}
692
693
694int SystemTableBuilder::initInstance(void)
695{
696 return VERR_NOT_IMPLEMENTED;
697}
698
699
700int SystemTableBuilder::finishTables(RTGCPHYS GCPhysTblsStart, RTVFSIOSTREAM hVfsIos,
701 PRTGCPHYS pGCPhysTblRoot, size_t *pcbTblRoot, size_t *pcbTbls)
702{
703 RT_NOREF(GCPhysTblsStart, hVfsIos, pGCPhysTblRoot, pcbTblRoot, pcbTbls);
704 return VERR_NOT_IMPLEMENTED;
705}
706
707
708int SystemTableBuilder::addCpu(uint32_t idCpu)
709{
710 RT_NOREF(idCpu);
711 return VERR_NOT_IMPLEMENTED;
712}
713
714
715int SystemTableBuilder::addMemory(RTGCPHYS GCPhysStart, RTGCPHYS cbMem)
716{
717 RT_NOREF(GCPhysStart, cbMem);
718 return VERR_NOT_IMPLEMENTED;
719}
720
721
722int SystemTableBuilder::addMmioDeviceNoIrq(const char *pszVBoxName, uint32_t uInstance, RTGCPHYS GCPhysMmio, RTGCPHYS cbMmio)
723{
724 RT_NOREF(pszVBoxName, uInstance, GCPhysMmio, cbMmio);
725 return VERR_NOT_IMPLEMENTED;
726}
727
728
729int SystemTableBuilder::addMmioDevice(const char *pszVBoxName, uint32_t uInstance, RTGCPHYS GCPhysMmio, RTGCPHYS cbMmio, uint32_t u32Irq)
730{
731 RT_NOREF(pszVBoxName, uInstance, GCPhysMmio, cbMmio, u32Irq);
732 return VERR_NOT_IMPLEMENTED;
733}
734
735
736int SystemTableBuilder::configureGic(uint32_t cCpus, RTGCPHYS GCPhysIntcDist, RTGCPHYS cbMmioIntcDist, RTGCPHYS GCPhysIntcReDist,
737 RTGCPHYS cbMmioIntcReDist)
738{
739 RT_NOREF(cCpus, GCPhysIntcDist, cbMmioIntcDist, GCPhysIntcReDist, cbMmioIntcReDist);
740 return VERR_NOT_IMPLEMENTED;
741}
742
743
744int SystemTableBuilder::configureClock(void)
745{
746 return VERR_NOT_IMPLEMENTED;
747}
748
749
750int SystemTableBuilder::configurePcieRootBus(const char *pszVBoxName, uint32_t aPinIrqs[4], RTGCPHYS GCPhysMmioPio, RTGCPHYS GCPhysMmioEcam, size_t cbPciMmioEcam,
751 RTGCPHYS GCPhysPciMmioBase, RTGCPHYS cbPciMmio, RTGCPHYS GCPhysPciMmio32Base, RTGCPHYS cbPciMmio32)
752{
753 RT_NOREF(pszVBoxName, aPinIrqs, GCPhysMmioPio, GCPhysMmioEcam, cbPciMmioEcam,
754 GCPhysPciMmioBase, cbPciMmio, GCPhysPciMmio32Base, cbPciMmio32);
755 return VERR_NOT_IMPLEMENTED;
756}
757
758
759int SystemTableBuilder::configureTpm2(bool fCrb, RTGCPHYS GCPhysMmioStart, RTGCPHYS cbMmio, uint32_t u32Irq)
760{
761 RT_NOREF(fCrb, GCPhysMmioStart, cbMmio, u32Irq);
762 return VERR_NOT_IMPLEMENTED;
763}
764
765
766int SystemTableBuilder::dumpTables(const char *pszFilename)
767{
768 RT_NOREF(pszFilename);
769 return VERR_NOT_IMPLEMENTED;
770}
771
772
773SystemTableBuilder *SystemTableBuilder::createInstance(SYSTEMTABLETYPE enmTableType)
774{
775 AssertReturn(enmTableType == kSystemTableType_Acpi, NULL);
776
777 SystemTableBuilder *pInstance = new SystemTableBuilderAcpi();
778 Assert(pInstance);
779
780 int vrc = pInstance->initInstance();
781 if (RT_FAILURE(vrc))
782 {
783 delete pInstance;
784 pInstance = NULL;
785 }
786
787 return pInstance;
788}
Note: See TracBrowser for help on using the repository browser.

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