VirtualBox

source: vbox/trunk/src/VBox/Devices/Misc/DevPlatform.cpp@ 107882

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

Devices,Main,Installer,/Makefile.kmk: Take ARM EFI firmwares from the same build box as the x86 & amd64 ones (efi2). Renamed the firmware images and internal variables to include full arch (kbuild style) for x86 & amd64 as well. jiraref:VBP-1458

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.1 KB
Line 
1/* $Id: DevPlatform.cpp 107139 2024-11-26 10:19:37Z vboxsync $ */
2/** @file
3 * DevPlatform - Guest platform <-> VirtualBox Integration Framework.
4 */
5
6/*
7 * Copyright (C) 2023-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_DEV_PLATFORM
33
34#include <VBox/vmm/pdmdev.h>
35#include <VBox/vmm/pgm.h>
36#include <VBox/vmm/cpum.h>
37#include <VBox/vmm/mm.h>
38#include <VBox/log.h>
39#include <VBox/err.h>
40#include <VBox/param.h>
41#include <VBox/vmm/dbgf.h>
42
43#include <iprt/asm.h>
44#include <iprt/assert.h>
45#include <iprt/ctype.h>
46#include <iprt/file.h>
47#include <iprt/list.h>
48#include <iprt/mem.h>
49#include <iprt/string.h>
50#include <iprt/uuid.h>
51#include <iprt/path.h>
52#include <iprt/string.h>
53
54#include "VBoxDD.h"
55#include "VBoxDD2.h"
56
57
58/*********************************************************************************************************************************
59* Structures and Typedefs *
60*********************************************************************************************************************************/
61/**
62 * Platform resource entry.
63 */
64typedef struct DEVPLATFORMRESOURCE
65{
66 /** Node in the list of resources added to the VM. */
67 RTLISTNODE NdLst;
68 /** The ID in the resource store or filename to load. */
69 const char *pszResourceIdOrFilename;
70 /** The physical load address of the resource. */
71 RTGCPHYS GCPhysResource;
72 /** The resource data. */
73 uint8_t const *pu8Resource;
74 /** The resource data pointer to be passed to RTFileReadAllFree (only valid when DEVPLATFORMRESOURCE::fResourceId is false). */
75 uint8_t *pu8ResourceFree;
76 /** The size of the resource. */
77 size_t cbResource;
78 /** Flag whether the resource is loaded from the resource store of from a file. */
79 bool fResourceId;
80 /** Name of the resource. */
81 char szName[32];
82} DEVPLATFORMRESOURCE;
83/** Pointer to a platform resource entry. */
84typedef DEVPLATFORMRESOURCE *PDEVPLATFORMRESOURCE;
85/** Pointer to a constant platform resource entry. */
86typedef const DEVPLATFORMRESOURCE *PCDEVPLATFORMRESOURCE;
87
88
89/**
90 * The plaatform device state structure, shared state.
91 */
92typedef struct DEVPLATFORM
93{
94 /** Pointer back to the device instance. */
95 PPDMDEVINS pDevIns;
96
97 /** The resource namespace. */
98 char *pszResourceNamespace;
99
100 /** List head for resources added in the memory setup phase
101 * (written to guest memory). */
102 RTLISTANCHOR LstResourcesMem;
103 /** List head for resources added as a ROM file. */
104 RTLISTANCHOR LstResourcesRom;
105
106 /**
107 * Resource port - LUN\#0.
108 */
109 struct
110 {
111 /** The base interface we provide the resource driver. */
112 PDMIBASE IBase;
113 /** The resource driver base interface. */
114 PPDMIBASE pDrvBase;
115 /** The VFS interface of the driver below for resource state loading and storing. */
116 PPDMIVFSCONNECTOR pDrvVfs;
117 } Lun0;
118} DEVPLATFORM;
119/** Pointer to the platform device state. */
120typedef DEVPLATFORM *PDEVPLATFORM;
121
122
123/*********************************************************************************************************************************
124* Defined Constants And Macros *
125*********************************************************************************************************************************/
126
127
128/*********************************************************************************************************************************
129* Global Variables *
130*********************************************************************************************************************************/
131# ifdef VBOX_WITH_EFI_IN_DD2
132/** Special file name value for indicating the 32-bit built-in EFI firmware. */
133static const char g_szEfiBuiltinArm32[] = "VBoxEFI-arm32.fd";
134/** Special file name value for indicating the 64-bit built-in EFI firmware. */
135static const char g_szEfiBuiltinArm64[] = "VBoxEFI-arm64.fd";
136# endif
137
138
139/**
140 * Resolves the given resource content.
141 *
142 * @returns VBox status code.
143 * @param pDevIns The device instance data.
144 * @param pThis The device state for the current context.
145 * @param pRes The resource to resolve.
146 * @param ppvFree Where to store pointer to the function freeing the resource data
147 * (RTFileReadAllFree() or PDMDevHlpMMHeapFree()).
148 * @param ppv Where to store the pointer to the reoucer data content.
149 * @param pcb Where to store the size of the content in bytes.
150 */
151static int platformR3ResourceResolveContent(PPDMDEVINS pDevIns, PDEVPLATFORM pThis,
152 PCDEVPLATFORMRESOURCE pRes,
153 void **ppvFree, void const **ppv, size_t *pcb)
154{
155 if (pRes->fResourceId)
156 {
157#ifdef VBOX_WITH_EFI_IN_DD2
158 if ( RTStrCmp(pRes->pszResourceIdOrFilename, g_szEfiBuiltinArm32) == 0
159 || RTStrCmp(pRes->pszResourceIdOrFilename, "VBoxEFIAArch32.fd") == 0 /* legacy */)
160 {
161 *ppvFree = NULL;
162 *ppv = g_abEfiFirmwareArm32;
163 *pcb = g_cbEfiFirmwareArm32;
164 }
165 else if ( RTStrCmp(pRes->pszResourceIdOrFilename, g_szEfiBuiltinArm64) == 0
166 || RTStrCmp(pRes->pszResourceIdOrFilename, "VBoxEFIAArch64.fd") == 0 /* legacy */)
167 {
168 *ppvFree = NULL;
169 *ppv = g_abEfiFirmwareArm64;
170 *pcb = g_cbEfiFirmwareArm64;
171 }
172 else
173#endif
174 {
175 AssertPtrReturn(pThis->Lun0.pDrvVfs, VERR_INVALID_STATE);
176
177 uint64_t cbResource = 0;
178 int rc = pThis->Lun0.pDrvVfs->pfnQuerySize(pThis->Lun0.pDrvVfs, pThis->pszResourceNamespace,
179 pRes->pszResourceIdOrFilename, &cbResource);
180 if (RT_SUCCESS(rc))
181 {
182 void *pv = PDMDevHlpMMHeapAlloc(pDevIns, cbResource);
183 if (pv)
184 {
185 rc = pThis->Lun0.pDrvVfs->pfnReadAll(pThis->Lun0.pDrvVfs, pThis->pszResourceNamespace,
186 pRes->pszResourceIdOrFilename, pv, cbResource);
187 if (RT_FAILURE(rc))
188 {
189 PDMDevHlpMMHeapFree(pDevIns, pv);
190 return rc;
191 }
192
193 *ppvFree = pv;
194 *ppv = pv;
195 *pcb = cbResource;
196 }
197 else
198 rc = VERR_NO_MEMORY;
199 }
200 AssertLogRelRCReturn(rc, rc);
201 }
202 }
203 else
204 {
205 void *pvFile;
206 size_t cbFile;
207 int rc = RTFileReadAllEx(pRes->pszResourceIdOrFilename,
208 0 /*off*/,
209 RTFOFF_MAX /*cbMax*/,
210 RTFILE_RDALL_O_DENY_WRITE,
211 &pvFile,
212 &cbFile);
213 if (RT_FAILURE(rc))
214 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
215 N_("Loading the resource '%s' failed with rc=%Rrc"),
216 pRes->pszResourceIdOrFilename, rc);
217 *ppvFree = (uint8_t *)pvFile;
218 *ppv = (uint8_t *)pvFile;
219 *pcb = cbFile;
220 }
221
222 return VINF_SUCCESS;
223}
224
225
226/**
227 * Returns the load address of the given resource.
228 *
229 * @returns Guest physical load address of the resource.
230 * @param pDevIns The device instance data.
231 * @param pRes The resource to get the load address from.
232 */
233DECLINLINE(RTGCPHYS) platformR3ResourceGetLoadAddress(PPDMDEVINS pDevIns, PCDEVPLATFORMRESOURCE pRes)
234{
235 /*
236 * Maximum means determine the guest physical address width and place at the end
237 * (which requires the size of the resource to be known (assuming we won't ever have
238 * one byte large contents to be placed at the end).
239 */
240 if (pRes->GCPhysResource == RTGCPHYS_MAX)
241 {
242 uint8_t cPhysAddrBits, cLinearAddrBits;
243 PDMDevHlpCpuGetGuestAddrWidths(pDevIns, &cPhysAddrBits, &cLinearAddrBits);
244
245 return RT_BIT_64(cPhysAddrBits) - pRes->cbResource;
246 }
247
248 return pRes->GCPhysResource;
249}
250
251
252/**
253 * Destroys the given resource list.
254 *
255 * @param pDevIns The device instance data.
256 * @param pLst The resource list to destroy.
257 */
258static void platformR3DestructResourceList(PPDMDEVINS pDevIns, PRTLISTANCHOR pLst)
259{
260 PDEVPLATFORMRESOURCE pIt, pItNext;
261
262 RTListForEachSafe(pLst, pIt, pItNext, DEVPLATFORMRESOURCE, NdLst)
263 {
264 RTListNodeRemove(&pIt->NdLst);
265
266 if (pIt->pu8ResourceFree)
267 {
268 if (!pIt->fResourceId)
269 RTFileReadAllFree(pIt->pu8ResourceFree, pIt->cbResource);
270 else
271 PDMDevHlpMMHeapFree(pDevIns, pIt->pu8ResourceFree);
272 }
273
274 PDMDevHlpMMHeapFree(pDevIns, (void *)pIt->pszResourceIdOrFilename);
275
276 pIt->pszResourceIdOrFilename = NULL;
277 pIt->pu8ResourceFree = NULL;
278 pIt->pu8Resource = NULL;
279 pIt->cbResource = 0;
280
281 PDMDevHlpMMHeapFree(pDevIns, pIt);
282 }
283}
284
285
286/**
287 * @copydoc(PDMIBASE::pfnQueryInterface)
288 */
289static DECLCALLBACK(void *) platformR3QueryInterface(PPDMIBASE pInterface, const char *pszIID)
290{
291 LogFlowFunc(("ENTER: pIBase=%p pszIID=%p\n", pInterface, pszIID));
292 PDEVPLATFORM pThis = RT_FROM_MEMBER(pInterface, DEVPLATFORM, Lun0.IBase);
293
294 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);
295 return NULL;
296}
297
298
299/**
300 * @interface_method_impl{PDMDEVREG,pfnMemSetup}
301 */
302static DECLCALLBACK(void) platformR3MemSetup(PPDMDEVINS pDevIns, PDMDEVMEMSETUPCTX enmCtx)
303{
304 PDEVPLATFORM pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPLATFORM);
305 LogFlow(("platformR3MemSetup\n"));
306
307 RT_NOREF(enmCtx);
308
309 /* Iterate over the memory resource list and write everything there. */
310 PDEVPLATFORMRESOURCE pIt;
311 RTListForEach(&pThis->LstResourcesMem, pIt, DEVPLATFORMRESOURCE, NdLst)
312 {
313 int rc = platformR3ResourceResolveContent(pDevIns, pThis, pIt, (void **)&pIt->pu8ResourceFree,
314 (const void **)&pIt->pu8Resource, &pIt->cbResource);
315 if (RT_SUCCESS(rc))
316 {
317 rc = PDMDevHlpPhysWrite(pDevIns, platformR3ResourceGetLoadAddress(pDevIns, pIt), pIt->pu8Resource, pIt->cbResource);
318
319 /* Don't need to keep it around, will be queried the next time the VM is reset. */
320 if (pIt->pu8ResourceFree)
321 {
322 if (!pIt->fResourceId)
323 RTFileReadAllFree(pIt->pu8ResourceFree, pIt->cbResource);
324 else
325 PDMDevHlpMMHeapFree(pDevIns, pIt->pu8ResourceFree);
326 }
327
328 pIt->pu8ResourceFree = NULL;
329 pIt->pu8Resource = NULL;
330 pIt->cbResource = 0;
331 }
332 AssertLogRelRCReturnVoid(rc);
333 }
334}
335
336
337/**
338 * Destruct a device instance.
339 *
340 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
341 * resources can be freed correctly.
342 *
343 * @param pDevIns The device instance data.
344 */
345static DECLCALLBACK(int) platformR3Destruct(PPDMDEVINS pDevIns)
346{
347 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
348 PDEVPLATFORM pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPLATFORM);
349
350 /*
351 * Walk the resource lists and free everything.
352 */
353 platformR3DestructResourceList(pDevIns, &pThis->LstResourcesMem);
354 platformR3DestructResourceList(pDevIns, &pThis->LstResourcesRom);
355
356 RTListInit(&pThis->LstResourcesMem);
357 RTListInit(&pThis->LstResourcesRom);
358
359 /*
360 * Free MM heap pointers (waste of time, but whatever).
361 */
362 if (pThis->pszResourceNamespace)
363 {
364 PDMDevHlpMMHeapFree(pDevIns, pThis->pszResourceNamespace);
365 pThis->pszResourceNamespace = NULL;
366 }
367
368 return VINF_SUCCESS;
369}
370
371
372/**
373 * Load the ROM resources into the guest physical address space.
374 *
375 * @returns VBox status code.
376 * @param pDevIns The device instance.
377 * @param pThis The device state for the current context.
378 */
379static int platformR3LoadRoms(PPDMDEVINS pDevIns, PDEVPLATFORM pThis)
380{
381 int rc = VINF_SUCCESS;
382
383 PDEVPLATFORMRESOURCE pIt;
384 RTListForEach(&pThis->LstResourcesRom, pIt, DEVPLATFORMRESOURCE, NdLst)
385 {
386 rc = platformR3ResourceResolveContent(pDevIns, pThis, pIt, (void **)&pIt->pu8ResourceFree,
387 (void const **)&pIt->pu8Resource, &pIt->cbResource);
388 if (RT_SUCCESS(rc))
389 {
390 AssertLogRel((uint32_t)pIt->cbResource == pIt->cbResource);
391 rc = PDMDevHlpROMRegister(pDevIns, platformR3ResourceGetLoadAddress(pDevIns, pIt),
392 (uint32_t)pIt->cbResource, pIt->pu8Resource, (uint32_t)pIt->cbResource,
393 PGMPHYS_ROM_FLAGS_SHADOWED | PGMPHYS_ROM_FLAGS_PERMANENT_BINARY, pIt->szName);
394 }
395 AssertRCReturn(rc, rc);
396 }
397
398 return rc;
399}
400
401
402/**
403 * @interface_method_impl{PDMDEVREG,pfnConstruct}
404 */
405static DECLCALLBACK(int) platformR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
406{
407 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
408 PDEVPLATFORM pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPLATFORM);
409 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
410 int rc;
411
412 RT_NOREF(iInstance);
413 Assert(iInstance == 0);
414
415 /*
416 * Initalize the basic variables so that the destructor always works.
417 */
418 pThis->pDevIns = pDevIns;
419 pThis->pszResourceNamespace = NULL;
420 pThis->Lun0.IBase.pfnQueryInterface = platformR3QueryInterface;
421 RTListInit(&pThis->LstResourcesMem);
422 RTListInit(&pThis->LstResourcesRom);
423
424 /*
425 * Validate and read the configuration.
426 */
427 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "ResourceNamespace", "Resources");
428
429 rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "ResourceNamespace", &pThis->pszResourceNamespace);
430 if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND)
431 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
432 N_("Configuration error: Querying \"ResourceNamespace\" as a string failed"));
433
434 /*
435 * Resource storage.
436 */
437 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->Lun0.IBase, &pThis->Lun0.pDrvBase, "ResourceStorage");
438 if (RT_SUCCESS(rc))
439 {
440 pThis->Lun0.pDrvVfs = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pDrvBase, PDMIVFSCONNECTOR);
441 if (!pThis->Lun0.pDrvVfs)
442 return PDMDevHlpVMSetError(pDevIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS, N_("Resource storage driver is missing VFS interface below"));
443 }
444 else
445 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("Can't attach resource Storage driver"));
446
447 /*
448 * Load the resources.
449 */
450 PCFGMNODE pCfgRes = pHlp->pfnCFGMGetChild(pCfg, "Resources");
451 if (pCfgRes)
452 {
453 pCfgRes = pHlp->pfnCFGMGetFirstChild(pCfgRes);
454 while (pCfgRes)
455 {
456 rc = pHlp->pfnCFGMValidateConfig(pCfgRes, "/",
457 "RegisterAsRom"
458 "|Filename"
459 "|ResourceId"
460 "|GCPhysLoadAddress",
461 "",
462 pDevIns->pReg->szName, pDevIns->iInstance);
463 if (RT_FAILURE(rc))
464 return rc;
465
466 bool fRegisterAsRom;
467 rc = pHlp->pfnCFGMQueryBool(pCfgRes, "RegisterAsRom", &fRegisterAsRom);
468 if (RT_FAILURE(rc))
469 return PDMDEV_SET_ERROR(pDevIns, rc,
470 N_("Configuration error: Querying \"RegisterAsRom\" as boolean failed"));
471
472 PDEVPLATFORMRESOURCE pRes = (PDEVPLATFORMRESOURCE)PDMDevHlpMMHeapAlloc(pDevIns, sizeof(*pRes));
473 if (!pRes)
474 return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY,
475 N_("Configuration error: Failed to allocate resource node"));
476
477 rc = pHlp->pfnCFGMGetName(pCfgRes, &pRes->szName[0], sizeof(pRes->szName));
478 if (RT_FAILURE(rc))
479 return PDMDEV_SET_ERROR(pDevIns, rc,
480 N_("Configuration error: Querying resource name as a string failed"));
481
482 rc = pHlp->pfnCFGMQueryU64Def(pCfgRes, "GCPhysLoadAddress", &pRes->GCPhysResource, RTGCPHYS_MAX);
483 if (RT_FAILURE(rc))
484 return PDMDEV_SET_ERROR(pDevIns, rc,
485 N_("Configuration error: Querying \"GCPhysLoadAddress\" as integer failed"));
486
487 /* Setting a filename overrides the resource store (think of CFGM extradata from the user). */
488 pRes->fResourceId = false;
489 rc = pHlp->pfnCFGMQueryStringAlloc(pCfgRes, "Filename", (char **)&pRes->pszResourceIdOrFilename);
490 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
491 {
492 /* There must be an existing resource ID. */
493 rc = pHlp->pfnCFGMQueryStringAlloc(pCfgRes, "ResourceId", (char **)&pRes->pszResourceIdOrFilename);
494 if (RT_SUCCESS(rc))
495 pRes->fResourceId = true;
496 }
497 if (RT_FAILURE(rc))
498 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
499 N_("Configuration error: Querying \"Filename\" or \"ResourceId\" as a string failed"));
500
501 /* Add it to the appropriate list. */
502 RTListAppend(fRegisterAsRom ? &pThis->LstResourcesRom : &pThis->LstResourcesMem, &pRes->NdLst);
503
504 /* Next one please. */
505 pCfgRes = pHlp->pfnCFGMGetNextChild(pCfgRes);
506 }
507 }
508
509 /* Load and register the ROM resources. */
510 rc = platformR3LoadRoms(pDevIns, pThis);
511 if (RT_FAILURE(rc))
512 return rc;
513
514 return VINF_SUCCESS;
515}
516
517
518/**
519 * The device registration structure.
520 */
521const PDMDEVREG g_DevicePlatform =
522{
523 /* .u32Version = */ PDM_DEVREG_VERSION,
524 /* .uReserved0 = */ 0,
525 /* .szName = */ "platform",
526 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_NEW_STYLE,
527 /* .fClass = */ PDM_DEVREG_CLASS_ARCH_BIOS,
528 /* .cMaxInstances = */ 1,
529 /* .uSharedVersion = */ 42,
530 /* .cbInstanceShared = */ sizeof(DEVPLATFORM),
531 /* .cbInstanceCC = */ 0,
532 /* .cbInstanceRC = */ 0,
533 /* .cMaxPciDevices = */ 0,
534 /* .cMaxMsixVectors = */ 0,
535 /* .pszDescription = */ "Generic platform device for registering ROMs and loading resources into guest RAM.\n",
536#if defined(IN_RING3)
537 /* .pszRCMod = */ "",
538 /* .pszR0Mod = */ "",
539 /* .pfnConstruct = */ platformR3Construct,
540 /* .pfnDestruct = */ platformR3Destruct,
541 /* .pfnRelocate = */ NULL,
542 /* .pfnMemSetup = */ platformR3MemSetup,
543 /* .pfnPowerOn = */ NULL,
544 /* .pfnReset = */ NULL,
545 /* .pfnSuspend = */ NULL,
546 /* .pfnResume = */ NULL,
547 /* .pfnAttach = */ NULL,
548 /* .pfnDetach = */ NULL,
549 /* .pfnQueryInterface = */ NULL,
550 /* .pfnInitComplete = */ NULL,
551 /* .pfnPowerOff = */ NULL,
552 /* .pfnSoftReset = */ NULL,
553 /* .pfnReserved0 = */ NULL,
554 /* .pfnReserved1 = */ NULL,
555 /* .pfnReserved2 = */ NULL,
556 /* .pfnReserved3 = */ NULL,
557 /* .pfnReserved4 = */ NULL,
558 /* .pfnReserved5 = */ NULL,
559 /* .pfnReserved6 = */ NULL,
560 /* .pfnReserved7 = */ NULL,
561#elif defined(IN_RING0)
562 /* .pfnEarlyConstruct = */ NULL,
563 /* .pfnConstruct = */ NULL,
564 /* .pfnDestruct = */ NULL,
565 /* .pfnFinalDestruct = */ NULL,
566 /* .pfnRequest = */ NULL,
567 /* .pfnReserved0 = */ NULL,
568 /* .pfnReserved1 = */ NULL,
569 /* .pfnReserved2 = */ NULL,
570 /* .pfnReserved3 = */ NULL,
571 /* .pfnReserved4 = */ NULL,
572 /* .pfnReserved5 = */ NULL,
573 /* .pfnReserved6 = */ NULL,
574 /* .pfnReserved7 = */ NULL,
575#elif defined(IN_RC)
576 /* .pfnConstruct = */ NULL,
577 /* .pfnReserved0 = */ NULL,
578 /* .pfnReserved1 = */ NULL,
579 /* .pfnReserved2 = */ NULL,
580 /* .pfnReserved3 = */ NULL,
581 /* .pfnReserved4 = */ NULL,
582 /* .pfnReserved5 = */ NULL,
583 /* .pfnReserved6 = */ NULL,
584 /* .pfnReserved7 = */ NULL,
585#else
586# error "Not in IN_RING3, IN_RING0 or IN_RC!"
587#endif
588 /* .u32VersionEnd = */ PDM_DEVREG_VERSION
589};
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