VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/Nvram.cpp@ 43157

Last change on this file since 43157 was 43157, checked in by vboxsync, 12 years ago

EFI: save'n'restore support.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.0 KB
Line 
1/* $Id: Nvram.cpp 43157 2012-09-04 09:00:28Z vboxsync $ */
2
3/** @file
4 * VBox NVRAM COM Class implementation
5 */
6
7/*
8 * Copyright (C) 2012 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include "Nvram.h"
23#include "ConsoleImpl.h"
24
25#include <VBox/vmm/pdm.h>
26#include <VBox/vmm/pdmdrv.h>
27#include <VBox/vmm/pdmnvram.h>
28#include <VBox/vmm/cfgm.h>
29#include <VBox/log.h>
30#include <VBox/err.h>
31#include <iprt/assert.h>
32#include <iprt/critsect.h>
33#include <iprt/mem.h>
34#include <iprt/string.h>
35#include <iprt/uuid.h>
36#include <iprt/base64.h>
37#include <VBox/version.h>
38#include <iprt/file.h>
39#include <iprt/semaphore.h>
40
41
42/*******************************************************************************
43* Structures and Typedefs *
44*******************************************************************************/
45typedef struct NVRAM NVRAM;
46typedef struct NVRAM *PNVRAM;
47
48struct NVRAM
49{
50 Nvram *pNvram;
51 PDMINVRAM INvram;
52 int cLoadedVariables;
53};
54
55
56/**
57 * Constructor/destructor
58 */
59Nvram::Nvram(Console *console)
60 : mpDrv(NULL),
61 mParent(console)
62{
63}
64
65Nvram::~Nvram()
66{
67 if (mpDrv)
68 {
69 mpDrv->pNvram = NULL;
70 mpDrv = NULL;
71 }
72}
73
74
75/**
76 * @interface_method_impl(PDMINVRAM,pfnStoreNvramValue)
77 */
78DECLCALLBACK(int) drvNvram_pfnStoreNvramValue(PPDMINVRAM pInterface,
79 int idxVariable,
80 RTUUID *pVendorUuid,
81 const char *pcszVariableName,
82 size_t cbVariableName,
83 uint8_t *pu8Value,
84 size_t cbValue)
85{
86 int rc = VINF_SUCCESS;
87 char szExtraDataKey[256];
88 char szExtraDataValue[1024];
89 LogFlowFunc(("ENTER: pVendorUuid:%RTuuid, pcszVariableName:%s, cbVariableName:%d, pu8Value:%.*Rhxs, cbValue:%d\n",
90 pVendorUuid,
91 pcszVariableName,
92 cbVariableName,
93 cbValue,
94 pu8Value,
95 cbValue));
96 PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvram);
97
98 RT_ZERO(szExtraDataKey);
99 RT_ZERO(szExtraDataValue);
100 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableName", idxVariable);
101 RTStrPrintf(szExtraDataValue, 1024, "%s", pcszVariableName? pcszVariableName: "");
102 pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraDataKey).raw(), Bstr(szExtraDataValue).raw());
103
104 RT_ZERO(szExtraDataKey);
105 RT_ZERO(szExtraDataValue);
106 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VendorGuid", idxVariable);
107 if (pVendorUuid)
108 RTUuidToStr(pVendorUuid, szExtraDataValue, 1024);
109 pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraDataKey).raw(), Bstr(szExtraDataValue).raw());
110
111 RT_ZERO(szExtraDataKey);
112 RT_ZERO(szExtraDataValue);
113 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableValueLength", idxVariable);
114 if (!cbValue)
115 RTStrPrintf(szExtraDataValue, 1024, "%d", cbValue);
116 pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraDataKey).raw(), Bstr(szExtraDataValue).raw());
117
118 RT_ZERO(szExtraDataKey);
119 RT_ZERO(szExtraDataValue);
120 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableValue", idxVariable);
121 size_t cbActualSize;
122 if (pu8Value)
123 rc = RTBase64Encode(pu8Value, cbValue, szExtraDataValue, 1024, &cbActualSize);
124 AssertRCReturn(rc, rc);
125 pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraDataKey).raw(), Bstr(szExtraDataValue).raw());
126
127 LogFlowFuncLeaveRC(rc);
128 return rc;
129}
130
131/**
132 * @interface_method_impl(PDMINVRAM,pfnFlushNvramStorage)
133 */
134DECLCALLBACK(int) drvNvram_pfnFlushNvramStorage(PPDMINVRAM pInterface)
135{
136 int rc = VINF_SUCCESS;
137 LogFlowFuncEnter();
138 PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvram);
139 int idxVariable = 0;
140 for (idxVariable = 0; idxVariable < pThis->cLoadedVariables; ++idxVariable)
141 {
142 drvNvram_pfnStoreNvramValue(pInterface, idxVariable, NULL, NULL, 0, NULL, 0);
143 }
144 LogFlowFuncLeaveRC(rc);
145 return rc;
146}
147
148/**
149 * @interface_method_impl(PDMINVRAM,pfnStoreNvramValue)
150 */
151DECLCALLBACK(int) drvNvram_pfnLoadNvramValue(PPDMINVRAM pInterface,
152 int idxVariable,
153 RTUUID *pVendorUuid,
154 char *pcszVariableName,
155 size_t *pcbVariableName,
156 uint8_t *pu8Value,
157 size_t *pcbValue)
158{
159 int rc = VINF_SUCCESS;
160 char szExtraDataKey[256];
161 Bstr bstrValue;
162 HRESULT hrc;
163 LogFlowFunc(("ENTER: idxVariable:%d, *pcbVariableName:%d, *pcbValue:%d\n",
164 idxVariable,
165 *pcbVariableName,
166 *pcbValue));
167 PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvram);
168
169 RT_ZERO(szExtraDataKey);
170 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableName", idxVariable);
171 hrc = pThis->pNvram->getParent()->machine()->GetExtraData(Bstr(szExtraDataKey).raw(), bstrValue.asOutParam());
172 if (!SUCCEEDED(hrc))
173 return VERR_NOT_FOUND;
174 *pcbVariableName = RTStrCopy(pcszVariableName, 1024, Utf8Str(bstrValue).c_str());
175
176 RT_ZERO(szExtraDataKey);
177 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VendorGuid", idxVariable);
178 hrc = pThis->pNvram->getParent()->machine()->GetExtraData(Bstr(szExtraDataKey).raw(), bstrValue.asOutParam());
179 RTUuidFromStr(pVendorUuid, Utf8Str(bstrValue).c_str());
180
181#if 0
182 RT_ZERO(szExtraDataKey);
183 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableValueLength", idxVariable);
184 hrc = pThis->pNvram->getParent()->machine()->GetExtraData(Bstr(szExtraDataKey).raw(), bstrValue.asOutParam());
185 *pcbValue = Utf8Str(bstrValue).toUInt32();
186#endif
187
188 RT_ZERO(szExtraDataKey);
189 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableValue", idxVariable);
190 hrc = pThis->pNvram->getParent()->machine()->GetExtraData(Bstr(szExtraDataKey).raw(), bstrValue.asOutParam());
191 rc = RTBase64Decode(Utf8Str(bstrValue).c_str(), pu8Value, 1024, pcbValue, NULL);
192 AssertRCReturn(rc, rc);
193
194 pThis->cLoadedVariables++;
195 LogFlowFuncLeaveRC(rc);
196 return rc;
197}
198
199
200/**
201 * @interface_method_impl(PDMIBASE,pfnQueryInterface)
202 */
203DECLCALLBACK(void *)Nvram::drvNvram_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
204{
205 LogFlow(("%s pInterface:%p, pszIID:%s\n", __FUNCTION__, pInterface, pszIID));
206 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
207 PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);
208
209 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
210 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINVRAM, &pThis->INvram);
211 return NULL;
212}
213
214/**
215 * @interface_method_impl(PDMDRVREG,pfnConstruct)
216 */
217DECLCALLBACK(int) Nvram::drvNvram_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
218{
219 LogFlowFunc(("iInstance/#d, pCfg:%p, fFlags:%x\n", pDrvIns->iInstance, pCfg, fFlags));
220 PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);
221
222 if (!CFGMR3AreValuesValid(pCfg, "Object\0"))
223 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
224 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
225 ("Configuration error: Not possible to attach anything to this driver!\n"),
226 VERR_PDM_DRVINS_NO_ATTACH);
227
228 void *pv;
229 int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
230 AssertMsgRCReturn(rc, ("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc), rc);
231 pThis->pNvram = (Nvram *)pv;
232
233 pDrvIns->IBase.pfnQueryInterface = Nvram::drvNvram_QueryInterface;
234 pThis->INvram.pfnFlushNvramStorage = drvNvram_pfnFlushNvramStorage;
235 pThis->INvram.pfnStoreNvramValue = drvNvram_pfnStoreNvramValue;
236 pThis->INvram.pfnLoadNvramValue = drvNvram_pfnLoadNvramValue;
237
238 return VINF_SUCCESS;
239}
240
241/**
242 * @interface_method_impl(PDMDRVREG,pfnDestruct)
243 */
244DECLCALLBACK(void) Nvram::drvNvram_Destruct(PPDMDRVINS pDrvIns)
245{
246 LogFlow(("%s: iInstance/#d\n", __FUNCTION__, pDrvIns->iInstance));
247 PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);
248}
249
250const PDMDRVREG Nvram::DrvReg =
251{
252 /* u32Version */
253 PDM_DRVREG_VERSION,
254 /* szName[32] */
255 "NvramStorage",
256 /* szRCMod[32] */
257 "",
258 /* szR0Mod[32] */
259 "",
260 /* pszDescription */
261 "NVRAM Main Driver",
262 /* fFlags */
263 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
264 /* fClass */
265 PDM_DRVREG_CLASS_VMMDEV,
266 /* cMaxInstances */
267 1,
268 /* cbInstance */
269 sizeof(NVRAM),
270 /* pfnConstruct */
271 Nvram::drvNvram_Construct,
272 /* pfnDestruct */
273 Nvram::drvNvram_Destruct,
274 /* pfnRelocate */
275 NULL,
276 /* pfnIOCtl */
277 NULL,
278 /* pfnPowerOn */
279 NULL,
280 /* pfnReset */
281 NULL,
282 /* pfnSuspend */
283 NULL,
284 /* pfnResume */
285 NULL,
286 /* pfnAttach */
287 NULL,
288 /* pfnDetach */
289 NULL,
290 /* pfnPowerOff */
291 NULL,
292 /* pfnSoftReset */
293 NULL,
294 /* u32VersionEnd */
295 PDM_DRVREG_VERSION
296};
297/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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