VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/ACPI/VBoxAcpi.cpp@ 108143

Last change on this file since 108143 was 108143, checked in by vboxsync, 11 days ago

Devices/PC/DevACPI: Create the CPU hotplug variant SSDT on the fly and remove the static variant which got patched accordingly, bugref:10733

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.1 KB
Line 
1/* $Id: VBoxAcpi.cpp 108143 2025-02-10 14:44:27Z vboxsync $ */
2/** @file
3 * VBoxAcpi - VirtualBox ACPI manipulation functionality.
4 */
5
6/*
7 * Copyright (C) 2009-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#include <iprt/cdefs.h>
33#if !defined(IN_RING3)
34# error Pure R3 code
35#endif
36
37#define LOG_GROUP LOG_GROUP_DEV_ACPI
38#include <VBox/vmm/pdmdev.h>
39#include <VBox/vmm/pgm.h>
40#include <VBox/log.h>
41#include <VBox/param.h>
42#include <VBox/vmm/cfgm.h>
43#include <VBox/vmm/mm.h>
44#include <iprt/acpi.h>
45#include <iprt/assert.h>
46#include <iprt/alloc.h>
47#include <iprt/buildconfig.h>
48#include <iprt/string.h>
49#include <iprt/file.h>
50
51/* Statically compiled AML */
52#include <vboxaml.hex>
53#ifdef VBOX_WITH_TPM
54# include <vboxssdt_tpm.hex>
55#endif
56
57#include "VBoxDD.h"
58
59/** The CPU suffixes being used for processor object names. */
60static const char g_achCpuSuff[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
61
62/**
63 * Creates the SSDT exposing configured CPUs as processor objects.
64 *
65 * @returns VBox status code.
66 * @param pDevIns The PDM device instance data.
67 * @param ppabAml Where to store the pointer to the buffer containing the ACPI table on success.
68 * @param pcbAml Where to store the size of the ACPI table in bytes on success.
69 *
70 * @note This replaces the old vbox-standard.dsl which was patched accordingly.
71 */
72static int acpiCreateCpuSsdt(PPDMDEVINS pDevIns, uint8_t **ppabAml, size_t *pcbAml)
73{
74 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
75
76 uint16_t cCpus;
77 int rc = pHlp->pfnCFGMQueryU16Def(pDevIns->pCfg, "NumCPUs", &cCpus, 1);
78 if (RT_FAILURE(rc))
79 return rc;
80
81 bool fShowCpu;
82 rc = pHlp->pfnCFGMQueryBoolDef(pDevIns->pCfg, "ShowCpu", &fShowCpu, false);
83 if (RT_FAILURE(rc))
84 return rc;
85
86 /* Don't expose any CPU object if we are not required to. */
87 if (!fShowCpu)
88 cCpus = 0;
89
90 RTACPITBL hAcpiTbl;
91 rc = RTAcpiTblCreate(&hAcpiTbl, ACPI_TABLE_HDR_SIGNATURE_SSDT, 1, "VBOX ", "VBOXCPUT", 2, "VBOX", RTBldCfgRevision());
92 if (RT_SUCCESS(rc))
93 {
94 RTAcpiTblScopeStart(hAcpiTbl, "\\_PR");
95 for (uint16_t i = 0; i < cCpus; i++)
96 {
97 uint8_t const cCpuSuff = RT_ELEMENTS(g_achCpuSuff);
98 RTAcpiTblProcessorStartF(hAcpiTbl, i /*bProcId*/, 0 /*u32PBlkAddr*/, 0 /*cbPBlk*/, "CP%c%c",
99 i < cCpuSuff ? 'U' : 'V',
100 g_achCpuSuff[i % cCpuSuff]);
101 rc = RTAcpiTblProcessorFinalize(hAcpiTbl);
102 if (RT_FAILURE(rc))
103 break;
104 }
105 RTAcpiTblScopeFinalize(hAcpiTbl);
106
107 rc = RTAcpiTblFinalize(hAcpiTbl);
108 if (RT_SUCCESS(rc))
109 {
110 rc = RTAcpiTblDumpToBufferA(hAcpiTbl, RTACPITBLTYPE_AML, ppabAml, pcbAml);
111 if (RT_FAILURE(rc))
112 rc = PDMDEV_SET_ERROR(pDevIns, rc, N_("ACPI error: Failed to dump CPU SSDT"));
113 }
114 else
115 rc = PDMDEV_SET_ERROR(pDevIns, rc, N_("ACPI error: Failed to finalize CPU SSDT"));
116
117 RTAcpiTblDestroy(hAcpiTbl);
118 }
119 else
120 rc = PDMDEV_SET_ERROR(pDevIns, rc, N_("ACPI error: Failed to create CPU SSDT"));
121
122 return rc;
123}
124
125
126/**
127 * Creates the SSDT exposing configured CPUs as processor objects - hotplug variant.
128 *
129 * @returns VBox status code.
130 * @param pDevIns The PDM device instance data.
131 * @param ppabAml Where to store the pointer to the buffer containing the ACPI table on success.
132 * @param pcbAml Where to store the size of the ACPI table in bytes on success.
133 *
134 * @note This replaces the old vbox-cpuhotplug.dsl which was patched accordingly.
135 */
136static int acpiCreateCpuHotplugSsdt(PPDMDEVINS pDevIns, uint8_t **ppabAml, size_t *pcbAml)
137{
138 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
139
140 uint16_t cCpus;
141 int rc = pHlp->pfnCFGMQueryU16Def(pDevIns->pCfg, "NumCPUs", &cCpus, 1);
142 if (RT_FAILURE(rc))
143 return rc;
144
145 RTACPITBL hAcpiTbl;
146 rc = RTAcpiTblCreate(&hAcpiTbl, ACPI_TABLE_HDR_SIGNATURE_SSDT, 1, "VBOX ", "VBOXCPUT", 2, "VBOX", RTBldCfgRevision());
147 if (RT_SUCCESS(rc))
148 {
149 uint8_t const cCpuSuff = RT_ELEMENTS(g_achCpuSuff);
150
151 /* Declare externals */
152 RTAcpiTblIfStart(hAcpiTbl);
153 RTAcpiTblIntegerAppend(hAcpiTbl, 0);
154
155 RTAcpiTblExternalAppend(hAcpiTbl, "CPUC", kAcpiObjType_Unknown, 0 /*cArgs*/);
156 RTAcpiTblExternalAppend(hAcpiTbl, "CPUL", kAcpiObjType_Unknown, 0 /*cArgs*/);
157 RTAcpiTblExternalAppend(hAcpiTbl, "CPEV", kAcpiObjType_Unknown, 0 /*cArgs*/);
158 RTAcpiTblExternalAppend(hAcpiTbl, "CPET", kAcpiObjType_Unknown, 0 /*cArgs*/);
159
160 RTAcpiTblIfFinalize(hAcpiTbl);
161
162 /* Define two helper methods. */
163
164 /* CPCK(Arg0) -> Boolean - Checks whether the CPU identified by the given indes is locked. */
165 RTAcpiTblMethodStart(hAcpiTbl, "CPCK", 1 /*cArgs*/, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
166 RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Store);
167 RTAcpiTblArgOpAppend(hAcpiTbl, 0);
168 RTAcpiTblNameStringAppend(hAcpiTbl, "CPUC");
169
170 RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Return);
171 RTAcpiTblBinaryOpAppend(hAcpiTbl, kAcpiBinaryOp_LEqual);
172 RTAcpiTblNameStringAppend(hAcpiTbl, "CPUL");
173 RTAcpiTblIntegerAppend(hAcpiTbl, 1);
174 RTAcpiTblMethodFinalize(hAcpiTbl);
175
176 /* CPLO(Arg0) -> Nothing - Unlocks the CPU identified by the given index. */
177 RTAcpiTblMethodStart(hAcpiTbl, "CPLO", 1 /*cArgs*/, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
178 RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Store);
179 RTAcpiTblArgOpAppend(hAcpiTbl, 0);
180 RTAcpiTblNameStringAppend(hAcpiTbl, "CPUL");
181 RTAcpiTblMethodFinalize(hAcpiTbl);
182
183 /* Define all configured CPUs. */
184 RTAcpiTblScopeStart(hAcpiTbl, "\\_SB");
185 for (uint16_t i = 0; i < cCpus; i++)
186 {
187 RTAcpiTblDeviceStartF(hAcpiTbl, "SC%c%c", i < cCpuSuff ? 'K' : 'L', g_achCpuSuff[i % cCpuSuff]);
188
189 RTAcpiTblNameAppend(hAcpiTbl, "_HID");
190 RTAcpiTblStringAppend(hAcpiTbl, "ACPI0004");
191 RTAcpiTblNameAppend(hAcpiTbl, "_UID");
192 RTAcpiTblStringAppendF(hAcpiTbl, "SCKCP%c%c", i < cCpuSuff ? 'U' : 'V', g_achCpuSuff[i % cCpuSuff]);
193
194 RTAcpiTblProcessorStartF(hAcpiTbl, i /*bProcId*/, 0 /*u32PBlkAddr*/, 0 /*cbPBlk*/, "CP%c%c",
195 i < cCpuSuff ? 'U' : 'V',
196 g_achCpuSuff[i % cCpuSuff]);
197
198 RTAcpiTblNameAppend(hAcpiTbl, "_HID");
199 RTAcpiTblStringAppend(hAcpiTbl, "ACPI0007");
200 RTAcpiTblNameAppend(hAcpiTbl, "_UID");
201 RTAcpiTblIntegerAppend(hAcpiTbl, i);
202 RTAcpiTblNameAppend(hAcpiTbl, "_PXM");
203 RTAcpiTblIntegerAppend(hAcpiTbl, 0);
204
205 uint8_t abBufApic[8] = { 0x00, 0x08, (uint8_t)i, (uint8_t)i, 0, 0, 0, 0};
206 RTAcpiTblNameAppend(hAcpiTbl, "APIC");
207 RTAcpiTblBufferAppend(hAcpiTbl, &abBufApic[0], sizeof(abBufApic));
208
209 /* _MAT Method. */
210 RTAcpiTblMethodStart(hAcpiTbl, "_MAT", 0 /*cArgs*/, RTACPI_METHOD_F_SERIALIZED, 0 /*uSyncLvl*/);
211 RTAcpiTblIfStart(hAcpiTbl);
212 RTAcpiTblNameStringAppend(hAcpiTbl, "CPCK");
213 RTAcpiTblIntegerAppend(hAcpiTbl, i);
214
215 RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Store);
216 RTAcpiTblIntegerAppend(hAcpiTbl, 1);
217 RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Index);
218 RTAcpiTblNameStringAppend(hAcpiTbl, "APIC");
219 RTAcpiTblIntegerAppend(hAcpiTbl, 4);
220 RTAcpiTblNullNameAppend(hAcpiTbl);
221
222 RTAcpiTblIfFinalize(hAcpiTbl);
223 RTAcpiTblElseStart(hAcpiTbl);
224 RTAcpiTblElseFinalize(hAcpiTbl);
225
226 RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Return);
227 RTAcpiTblNameStringAppend(hAcpiTbl, "APIC");
228 RTAcpiTblMethodFinalize(hAcpiTbl);
229
230 /* _STA Method. */
231 RTAcpiTblMethodStart(hAcpiTbl, "_STA", 0 /*cArgs*/, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
232 RTAcpiTblIfStart(hAcpiTbl);
233 RTAcpiTblNameStringAppend(hAcpiTbl, "CPCK");
234 RTAcpiTblIntegerAppend(hAcpiTbl, i);
235
236 RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Return);
237 RTAcpiTblIntegerAppend(hAcpiTbl, 0xf);
238 RTAcpiTblIfFinalize(hAcpiTbl);
239 RTAcpiTblElseStart(hAcpiTbl);
240 RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Return);
241 RTAcpiTblIntegerAppend(hAcpiTbl, 0x0);
242 RTAcpiTblElseFinalize(hAcpiTbl);
243 RTAcpiTblMethodFinalize(hAcpiTbl);
244
245 /* _EJ0 Method. */
246 RTAcpiTblMethodStart(hAcpiTbl, "_EJ0", 1 /*cArgs*/, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
247 RTAcpiTblNameStringAppend(hAcpiTbl, "CPLO");
248 RTAcpiTblIntegerAppend(hAcpiTbl, i);
249 RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Return);
250 RTAcpiTblMethodFinalize(hAcpiTbl);
251
252 RTAcpiTblProcessorFinalize(hAcpiTbl);
253
254 rc = RTAcpiTblDeviceFinalize(hAcpiTbl);
255 if (RT_FAILURE(rc))
256 break;
257 }
258
259 if (RT_SUCCESS(rc))
260 {
261 RTAcpiTblScopeFinalize(hAcpiTbl);
262
263 /* Now the _GPE scope where event processing takes place. */
264 RTAcpiTblScopeStart(hAcpiTbl, "\\_GPE");
265 RTAcpiTblMethodStart(hAcpiTbl, "_L01", 0 /*cArgs*/, RTACPI_METHOD_F_NOT_SERIALIZED, 0 /*uSyncLvl*/);
266
267 RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Store);
268 RTAcpiTblNameStringAppend(hAcpiTbl, "CPEV");
269 RTAcpiTblLocalOpAppend(hAcpiTbl, 0);
270
271 RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Store);
272 RTAcpiTblNameStringAppend(hAcpiTbl, "CPET");
273 RTAcpiTblLocalOpAppend(hAcpiTbl, 1);
274
275 for (uint16_t i = 0; i < cCpus; i++)
276 {
277 RTAcpiTblIfStart(hAcpiTbl);
278 RTAcpiTblBinaryOpAppend(hAcpiTbl, kAcpiBinaryOp_LEqual);
279 RTAcpiTblLocalOpAppend(hAcpiTbl, 0);
280 RTAcpiTblIntegerAppend(hAcpiTbl, i);
281
282 RTAcpiTblStmtSimpleAppend(hAcpiTbl, kAcpiStmt_Notify);
283 RTAcpiTblNameStringAppendF(hAcpiTbl, "\\_SB.SC%c%c.CP%c%c",
284 i < cCpuSuff ? 'K' : 'L',
285 g_achCpuSuff[i % cCpuSuff],
286 i < cCpuSuff ? 'U' : 'V',
287 g_achCpuSuff[i % cCpuSuff]);
288 RTAcpiTblLocalOpAppend(hAcpiTbl, 1);
289 rc = RTAcpiTblIfFinalize(hAcpiTbl);
290 if (RT_FAILURE(rc))
291 break;
292 }
293
294 RTAcpiTblMethodFinalize(hAcpiTbl);
295 RTAcpiTblScopeFinalize(hAcpiTbl);
296 }
297
298 rc = RTAcpiTblFinalize(hAcpiTbl);
299 if (RT_SUCCESS(rc))
300 {
301 rc = RTAcpiTblDumpToBufferA(hAcpiTbl, RTACPITBLTYPE_AML, ppabAml, pcbAml);
302 if (RT_FAILURE(rc))
303 rc = PDMDEV_SET_ERROR(pDevIns, rc, N_("ACPI error: Failed to dump CPU SSDT"));
304 }
305 else
306 rc = PDMDEV_SET_ERROR(pDevIns, rc, N_("ACPI error: Failed to finalize CPU SSDT"));
307
308 RTAcpiTblDestroy(hAcpiTbl);
309 }
310 else
311 rc = PDMDEV_SET_ERROR(pDevIns, rc, N_("ACPI error: Failed to create CPU SSDT"));
312
313 return rc;
314}
315
316
317/**
318 * Loads an AML file if present in CFGM
319 *
320 * @returns VBox status code
321 * @param pDevIns The device instance
322 * @param pcszCfgName The configuration key holding the file path
323 * @param pcszSignature The signature to check for
324 * @param ppabAmlCode Where to store the pointer to the AML code on success.
325 * @param pcbAmlCode Where to store the number of bytes of the AML code on success.
326 */
327static int acpiAmlLoadExternal(PPDMDEVINS pDevIns, const char *pcszCfgName, const char *pcszSignature,
328 uint8_t **ppabAmlCode, size_t *pcbAmlCode)
329{
330 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
331
332 char *pszAmlFilePath = NULL;
333 int rc = pHlp->pfnCFGMQueryStringAlloc(pDevIns->pCfg, pcszCfgName, &pszAmlFilePath);
334 if (RT_SUCCESS(rc))
335 {
336 /* Load from file. */
337 RTFILE hFileAml = NIL_RTFILE;
338 rc = RTFileOpen(&hFileAml, pszAmlFilePath, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
339 if (RT_SUCCESS(rc))
340 {
341 /*
342 * An AML file contains the raw DSDT or SSDT thus the size of the file
343 * is equal to the size of the DSDT or SSDT.
344 */
345 uint64_t cbAmlFile = 0;
346 rc = RTFileQuerySize(hFileAml, &cbAmlFile);
347
348 /* Don't use AML files over 32MiB. */
349 if ( RT_SUCCESS(rc)
350 && cbAmlFile <= _32M)
351 {
352 size_t const cbAmlCode = (size_t)cbAmlFile;
353 uint8_t *pabAmlCode = (uint8_t *)RTMemAllocZ(cbAmlCode);
354 if (pabAmlCode)
355 {
356 rc = RTFileReadAt(hFileAml, 0, pabAmlCode, cbAmlCode, NULL);
357
358 /*
359 * We fail if reading failed or the identifier at the
360 * beginning is wrong.
361 */
362 if ( RT_FAILURE(rc)
363 || strncmp((const char *)pabAmlCode, pcszSignature, 4))
364 {
365 RTMemFree(pabAmlCode);
366 pabAmlCode = NULL;
367
368 /* Return error if file header check failed */
369 if (RT_SUCCESS(rc))
370 rc = VERR_PARSE_ERROR;
371 }
372 else
373 {
374 *ppabAmlCode = pabAmlCode;
375 *pcbAmlCode = cbAmlCode;
376 rc = VINF_SUCCESS;
377 }
378 }
379 else
380 rc = VERR_NO_MEMORY;
381 }
382 else if (RT_SUCCESS(rc))
383 rc = VERR_OUT_OF_RANGE;
384
385 RTFileClose(hFileAml);
386 }
387 PDMDevHlpMMHeapFree(pDevIns, pszAmlFilePath);
388 }
389
390 return rc;
391}
392
393
394/** No docs, lazy coder. */
395int acpiPrepareDsdt(PPDMDEVINS pDevIns, void **ppvPtr, size_t *pcbDsdt)
396{
397 uint8_t *pabAmlCodeDsdt = NULL;
398 size_t cbAmlCodeDsdt = 0;
399 int rc = acpiAmlLoadExternal(pDevIns, "DsdtFilePath", "DSDT", &pabAmlCodeDsdt, &cbAmlCodeDsdt);
400 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
401 {
402 /* Use the compiled in AML code */
403 cbAmlCodeDsdt = sizeof(AmlCode);
404 pabAmlCodeDsdt = (uint8_t *)RTMemDup(AmlCode, cbAmlCodeDsdt);
405 if (pabAmlCodeDsdt)
406 rc = VINF_SUCCESS;
407 else
408 rc = VERR_NO_MEMORY;
409 }
410 else if (RT_FAILURE(rc))
411 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"DsdtFilePath\""));
412
413 if (RT_SUCCESS(rc))
414 {
415 *ppvPtr = pabAmlCodeDsdt;
416 *pcbDsdt = cbAmlCodeDsdt;
417 }
418 return rc;
419}
420
421/** No docs, lazy coder. */
422int acpiCleanupDsdt(PPDMDEVINS pDevIns, void *pvPtr)
423{
424 RT_NOREF1(pDevIns);
425 if (pvPtr)
426 RTMemFree(pvPtr);
427 return VINF_SUCCESS;
428}
429
430/** No docs, lazy coder. */
431int acpiPrepareSsdt(PPDMDEVINS pDevIns, void **ppvPtr, size_t *pcbSsdt)
432{
433 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
434
435 uint8_t *pabAmlCodeSsdt = NULL;
436 size_t cbAmlCodeSsdt = 0;
437 int rc = acpiAmlLoadExternal(pDevIns, "SsdtFilePath", "SSDT", &pabAmlCodeSsdt, &cbAmlCodeSsdt);
438 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
439 {
440 bool fCpuHotPlug = false;
441 rc = pHlp->pfnCFGMQueryBoolDef(pDevIns->pCfg, "CpuHotPlug", &fCpuHotPlug, false);
442 if (RT_SUCCESS(rc))
443 {
444 if (fCpuHotPlug)
445 rc = acpiCreateCpuHotplugSsdt(pDevIns, &pabAmlCodeSsdt, &cbAmlCodeSsdt);
446 else
447 rc = acpiCreateCpuSsdt(pDevIns, &pabAmlCodeSsdt, &cbAmlCodeSsdt);
448 }
449 }
450 else if (RT_FAILURE(rc))
451 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"SsdtFilePath\""));
452
453 if (RT_SUCCESS(rc))
454 {
455 *ppvPtr = pabAmlCodeSsdt;
456 *pcbSsdt = cbAmlCodeSsdt;
457 }
458 return rc;
459}
460
461/** No docs, lazy coder. */
462int acpiCleanupSsdt(PPDMDEVINS pDevIns, void *pvPtr)
463{
464 RT_NOREF1(pDevIns);
465 if (pvPtr)
466 RTMemFree(pvPtr);
467 return VINF_SUCCESS;
468}
469
470#ifdef VBOX_WITH_TPM
471/** No docs, lazy coder. */
472int acpiPrepareTpmSsdt(PPDMDEVINS pDevIns, void **ppvPtr, size_t *pcbSsdt)
473{
474 uint8_t *pabAmlCodeSsdt = NULL;
475 size_t cbAmlCodeSsdt = 0;
476 int rc = acpiAmlLoadExternal(pDevIns, "SsdtTpmFilePath", "SSDT", &pabAmlCodeSsdt, &cbAmlCodeSsdt);
477 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
478 {
479 rc = VINF_SUCCESS;
480 cbAmlCodeSsdt = sizeof(AmlCodeSsdtTpm);
481 pabAmlCodeSsdt = (uint8_t *)RTMemDup(AmlCodeSsdtTpm, sizeof(AmlCodeSsdtTpm));
482 if (!pabAmlCodeSsdt)
483 rc = VERR_NO_MEMORY;
484 }
485 else if (RT_FAILURE(rc))
486 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"SsdtFilePath\""));
487
488 if (RT_SUCCESS(rc))
489 {
490 *ppvPtr = pabAmlCodeSsdt;
491 *pcbSsdt = cbAmlCodeSsdt;
492 }
493 return rc;
494}
495
496/** No docs, lazy coder. */
497int acpiCleanupTpmSsdt(PPDMDEVINS pDevIns, void *pvPtr)
498{
499 RT_NOREF1(pDevIns);
500 if (pvPtr)
501 RTMemFree(pvPtr);
502 return VINF_SUCCESS;
503}
504#endif
505
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