1d2154cff09d431181caed9114304c11bb7374c9vboxsync/* $Id$ */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync/** @file
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsync * VBox NVRAM COM Class implementation.
1d2154cff09d431181caed9114304c11bb7374c9vboxsync */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync/*
f4c45a1ca8a0bbdb88cf32e34c29474850ab0ee8vboxsync * Copyright (C) 2012-2014 Oracle Corporation
1d2154cff09d431181caed9114304c11bb7374c9vboxsync *
1d2154cff09d431181caed9114304c11bb7374c9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1d2154cff09d431181caed9114304c11bb7374c9vboxsync * available from http://www.virtualbox.org. This file is free software;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
1d2154cff09d431181caed9114304c11bb7374c9vboxsync * General Public License (GPL) as published by the Free Software
1d2154cff09d431181caed9114304c11bb7374c9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1d2154cff09d431181caed9114304c11bb7374c9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1d2154cff09d431181caed9114304c11bb7374c9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1d2154cff09d431181caed9114304c11bb7374c9vboxsync */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync/*******************************************************************************
1d2154cff09d431181caed9114304c11bb7374c9vboxsync* Header Files *
1d2154cff09d431181caed9114304c11bb7374c9vboxsync*******************************************************************************/
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include "Nvram.h"
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include "ConsoleImpl.h"
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync#include "Global.h"
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <VBox/vmm/pdm.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <VBox/vmm/pdmdrv.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <VBox/vmm/pdmnvram.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <VBox/vmm/cfgm.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <VBox/log.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <VBox/err.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <iprt/assert.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <iprt/critsect.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <iprt/mem.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <iprt/string.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <iprt/uuid.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <iprt/base64.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <VBox/version.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <iprt/file.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync#include <iprt/semaphore.h>
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync/*******************************************************************************
1d2154cff09d431181caed9114304c11bb7374c9vboxsync* Structures and Typedefs *
1d2154cff09d431181caed9114304c11bb7374c9vboxsync*******************************************************************************/
1d2154cff09d431181caed9114304c11bb7374c9vboxsynctypedef struct NVRAM NVRAM;
1d2154cff09d431181caed9114304c11bb7374c9vboxsynctypedef struct NVRAM *PNVRAM;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync/**
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * Intstance data associated with PDMDRVINS.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync */
1d2154cff09d431181caed9114304c11bb7374c9vboxsyncstruct NVRAM
1d2154cff09d431181caed9114304c11bb7374c9vboxsync{
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /** Pointer to the associated class instance. */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync Nvram *pNvram;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /** The NVRAM connector interface we provide to DevEFI. */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync PDMINVRAMCONNECTOR INvramConnector;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /** The root of the 'Vars' child of the driver config (i.e.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * VBoxInternal/Devices/efi/0/LUN#0/Config/Vars/).
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * This node has one child node per NVRAM variable. */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync PCFGMNODE pCfgVarRoot;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /** The variable node used in the privous drvNvram_VarQueryByIndex call. */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync PCFGMNODE pLastVarNode;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /** The index pLastVarNode corresponds to. */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync uint32_t idxLastVar;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /** Whether to permanently save the variables or not. */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync bool fPermanentSave;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync};
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync/*******************************************************************************
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync* Defined Constants And Macros *
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync*******************************************************************************/
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync/** The default NVRAM attribute value (non-volatile, boot servier access,
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync runtime access). */
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync#define NVRAM_DEFAULT_ATTRIB UINT32_C(0x7)
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync/** The CFGM overlay path of the NVRAM variables. */
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync#define NVRAM_CFGM_OVERLAY_PATH "VBoxInternal/Devices/efi/0/LUN#0/Config/Vars"
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync/**
1d2154cff09d431181caed9114304c11bb7374c9vboxsync * Constructor/destructor
1d2154cff09d431181caed9114304c11bb7374c9vboxsync */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsyncNvram::Nvram(Console *pConsole)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync : mParent(pConsole),
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync mpDrv(NULL)
1d2154cff09d431181caed9114304c11bb7374c9vboxsync{
1d2154cff09d431181caed9114304c11bb7374c9vboxsync}
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsyncNvram::~Nvram()
1d2154cff09d431181caed9114304c11bb7374c9vboxsync{
1d2154cff09d431181caed9114304c11bb7374c9vboxsync if (mpDrv)
1d2154cff09d431181caed9114304c11bb7374c9vboxsync {
1d2154cff09d431181caed9114304c11bb7374c9vboxsync mpDrv->pNvram = NULL;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync mpDrv = NULL;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync }
1d2154cff09d431181caed9114304c11bb7374c9vboxsync}
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync/**
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * @interface_method_impl(PDMINVRAM,pfnVarStoreSeqEnd)
1d2154cff09d431181caed9114304c11bb7374c9vboxsync */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsyncDECLCALLBACK(int) drvNvram_VarStoreSeqEnd(PPDMINVRAMCONNECTOR pInterface, int rc)
1d2154cff09d431181caed9114304c11bb7374c9vboxsync{
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync NOREF(pInterface);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync return rc;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync}
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync/**
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * Converts the binary to a CFGM overlay binary string.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync *
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * @returns Pointer to a heap buffer (hand it to RTMemFree when done).
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * @param pvBuf The binary data to convert.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * @param cbBuf The number of bytes to convert.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsyncstatic char *drvNvram_binaryToCfgmString(void const *pvBuf, size_t cbBuf)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync{
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync static char s_szPrefix[] = "bytes:";
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync size_t cbStr = RTBase64EncodedLength(cbBuf) + sizeof(s_szPrefix);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync char *pszStr = (char *)RTMemAlloc(cbStr);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync if (pszStr)
ddebb26839cf7640db6422d97d78abd4452aeca9vboxsync {
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync memcpy(pszStr, s_szPrefix, sizeof(s_szPrefix) - 1);
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync int rc = RTBase64Encode(pvBuf, cbBuf, &pszStr[sizeof(s_szPrefix) - 1], cbStr - sizeof(s_szPrefix) + 1, NULL);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync if (RT_FAILURE(rc))
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync {
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync RTMemFree(pszStr);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pszStr = NULL;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync }
ddebb26839cf7640db6422d97d78abd4452aeca9vboxsync }
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync return pszStr;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync}
ddebb26839cf7640db6422d97d78abd4452aeca9vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync/**
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * @interface_method_impl(PDMINVRAM,pfnVarStoreSeqPut)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsyncDECLCALLBACK(int) drvNvram_VarStoreSeqPut(PPDMINVRAMCONNECTOR pInterface, int idxVariable,
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync PCRTUUID pVendorUuid, const char *pszName, size_t cchName,
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync uint32_t fAttributes, uint8_t const *pbValue, size_t cbValue)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync{
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvramConnector);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync int rc = VINF_SUCCESS;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync if (pThis->fPermanentSave && pThis->pNvram)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync {
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync char szExtraName[256];
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync size_t offValueNm = RTStrPrintf(szExtraName, sizeof(szExtraName) - 16,
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync NVRAM_CFGM_OVERLAY_PATH "/%04u/", idxVariable);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync char szUuid[RTUUID_STR_LENGTH];
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync int rc2 = RTUuidToStr(pVendorUuid, szUuid, sizeof(szUuid)); AssertRC(rc2);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync char szAttribs[32];
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync if (fAttributes != NVRAM_DEFAULT_ATTRIB)
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync RTStrPrintf(szAttribs, sizeof(szAttribs), "%#x", fAttributes);
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync else
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync szAttribs[0] = '\0';
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync char *pszValue = drvNvram_binaryToCfgmString(pbValue, cbValue);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync if (pszValue)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync {
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync const char *apszTodo[] =
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync {
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync "Name", pszName,
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync "Uuid", szUuid,
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync "Value", pszValue,
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync "Attribs", szAttribs,
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync };
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync for (unsigned i = 0; i < RT_ELEMENTS(apszTodo); i += 2)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync {
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync if (!apszTodo[i + 1][0])
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync continue;
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync Assert(strlen(apszTodo[i]) < 16);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync strcpy(szExtraName + offValueNm, apszTodo[i]);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync try
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync {
f4c45a1ca8a0bbdb88cf32e34c29474850ab0ee8vboxsync HRESULT hrc = pThis->pNvram->getParent()->i_machine()->SetExtraData(Bstr(szExtraName).raw(),
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync Bstr(apszTodo[i + 1]).raw());
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync if (FAILED(hrc))
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync {
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync LogRel(("drvNvram_deleteVar: SetExtraData(%s,%s) returned %Rhrc\n", szExtraName, apszTodo[i + 1], hrc));
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync rc = Global::vboxStatusCodeFromCOM(hrc);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync }
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync }
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync catch (...)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync {
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync LogRel(("drvNvram_deleteVar: SetExtraData(%s,%s) threw exception\n", szExtraName, apszTodo[i + 1]));
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync rc = VERR_UNEXPECTED_EXCEPTION;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync }
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync }
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync }
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync else
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync rc = VERR_NO_MEMORY;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync RTMemFree(pszValue);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync }
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync NOREF(cchName);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync LogFlowFuncLeaveRC(rc);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync return rc;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync}
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync/**
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * Deletes a variable.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync *
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * @param pThis The NVRAM driver instance data.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * @param pszVarNodeNm The variable node name.
1d2154cff09d431181caed9114304c11bb7374c9vboxsync */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsyncstatic void drvNvram_deleteVar(PNVRAM pThis, const char *pszVarNodeNm)
1d2154cff09d431181caed9114304c11bb7374c9vboxsync{
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync char szExtraName[256];
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync size_t offValue = RTStrPrintf(szExtraName, sizeof(szExtraName) - 16, NVRAM_CFGM_OVERLAY_PATH "/%s/", pszVarNodeNm);
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync static const char *s_apszValueNames[] = { "Name", "Uuid", "Value", "Attribs" };
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync for (unsigned i = 0; i < RT_ELEMENTS(s_apszValueNames); i++)
ddebb26839cf7640db6422d97d78abd4452aeca9vboxsync {
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync Assert(strlen(s_apszValueNames[i]) < 16);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync strcpy(szExtraName + offValue, s_apszValueNames[i]);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync try
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync {
f4c45a1ca8a0bbdb88cf32e34c29474850ab0ee8vboxsync HRESULT hrc = pThis->pNvram->getParent()->i_machine()->SetExtraData(Bstr(szExtraName).raw(), Bstr().raw());
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync if (FAILED(hrc))
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync LogRel(("drvNvram_deleteVar: SetExtraData(%s,) returned %Rhrc\n", szExtraName, hrc));
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync }
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync catch (...)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync {
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync LogRel(("drvNvram_deleteVar: SetExtraData(%s,) threw exception\n", szExtraName));
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync }
ddebb26839cf7640db6422d97d78abd4452aeca9vboxsync }
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync}
ddebb26839cf7640db6422d97d78abd4452aeca9vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync/**
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * @interface_method_impl(PDMINVRAM,pfnVarStoreSeqBegin)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsyncDECLCALLBACK(int) drvNvram_VarStoreSeqBegin(PPDMINVRAMCONNECTOR pInterface, uint32_t cVariables)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync{
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvramConnector);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync int rc = VINF_SUCCESS;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync if (pThis->fPermanentSave && pThis->pNvram)
1d2154cff09d431181caed9114304c11bb7374c9vboxsync {
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /*
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * Remove all existing variables.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync for (PCFGMNODE pVarNode = CFGMR3GetFirstChild(pThis->pCfgVarRoot); pVarNode; pVarNode = CFGMR3GetNextChild(pVarNode))
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync {
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync char szName[128];
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync rc = CFGMR3GetName(pVarNode, szName, sizeof(szName));
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync if (RT_SUCCESS(rc))
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync drvNvram_deleteVar(pThis, szName);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync else
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync LogRel(("drvNvram_VarStoreSeqBegin: CFGMR3GetName -> %Rrc\n", rc));
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync }
1d2154cff09d431181caed9114304c11bb7374c9vboxsync }
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync NOREF(cVariables);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync return rc;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync}
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync/**
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * @interface_method_impl(PDMINVRAMCONNECTOR,pfnVarQueryByIndex)
1d2154cff09d431181caed9114304c11bb7374c9vboxsync */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsyncDECLCALLBACK(int) drvNvram_VarQueryByIndex(PPDMINVRAMCONNECTOR pInterface, uint32_t idxVariable,
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync PRTUUID pVendorUuid, char *pszName, uint32_t *pcchName,
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync uint32_t *pfAttributes, uint8_t *pbValue, uint32_t *pcbValue)
1d2154cff09d431181caed9114304c11bb7374c9vboxsync{
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvramConnector);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /*
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * Find the requested variable node.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync PCFGMNODE pVarNode;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync if (pThis->idxLastVar + 1 == idxVariable && pThis->pLastVarNode)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pVarNode = CFGMR3GetNextChild(pThis->pLastVarNode);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync else
ddebb26839cf7640db6422d97d78abd4452aeca9vboxsync {
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync pVarNode = CFGMR3GetFirstChild(pThis->pCfgVarRoot);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync for (uint32_t i = 0; i < idxVariable && pVarNode; i++)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pVarNode = CFGMR3GetNextChild(pVarNode);
ddebb26839cf7640db6422d97d78abd4452aeca9vboxsync }
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync if (!pVarNode)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync return VERR_NOT_FOUND;
ddebb26839cf7640db6422d97d78abd4452aeca9vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /* cache it */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pThis->pLastVarNode = pVarNode;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pThis->idxLastVar = idxVariable;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /*
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * Read the variable node.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync int rc = CFGMR3QueryString(pVarNode, "Name", pszName, *pcchName);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync AssertRCReturn(rc, rc);
acb85e6b36e32c7960c769bde511f0bade006c3dvboxsync *pcchName = (uint32_t)strlen(pszName);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync char szUuid[RTUUID_STR_LENGTH];
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync rc = CFGMR3QueryString(pVarNode, "Uuid", szUuid, sizeof(szUuid));
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync AssertRCReturn(rc, rc);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync rc = RTUuidFromStr(pVendorUuid, szUuid);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync AssertRCReturn(rc, rc);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync
8a4101789e0694e5358bc5392fd741a216e1d598vboxsync rc = CFGMR3QueryU32Def(pVarNode, "Attribs", pfAttributes, NVRAM_DEFAULT_ATTRIB);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync AssertRCReturn(rc, rc);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync size_t cbValue;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync rc = CFGMR3QuerySize(pVarNode, "Value", &cbValue);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync AssertRCReturn(rc, rc);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync AssertReturn(cbValue <= *pcbValue, VERR_BUFFER_OVERFLOW);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync rc = CFGMR3QueryBytes(pVarNode, "Value", pbValue, cbValue);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync AssertRCReturn(rc, rc);
acb85e6b36e32c7960c769bde511f0bade006c3dvboxsync *pcbValue = (uint32_t)cbValue;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync return VINF_SUCCESS;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync}
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync/**
1d2154cff09d431181caed9114304c11bb7374c9vboxsync * @interface_method_impl(PDMIBASE,pfnQueryInterface)
1d2154cff09d431181caed9114304c11bb7374c9vboxsync */
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsyncDECLCALLBACK(void *) Nvram::drvNvram_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
1d2154cff09d431181caed9114304c11bb7374c9vboxsync{
1d2154cff09d431181caed9114304c11bb7374c9vboxsync LogFlow(("%s pInterface:%p, pszIID:%s\n", __FUNCTION__, pInterface, pszIID));
1d2154cff09d431181caed9114304c11bb7374c9vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMINVRAMCONNECTOR, &pThis->INvramConnector);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync return NULL;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync}
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsync
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsync/**
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsync * @interface_method_impl(PDMDRVREG,pfnDestruct)
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsync */
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsyncDECLCALLBACK(void) Nvram::drvNvram_Destruct(PPDMDRVINS pDrvIns)
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsync{
eac18a2a75654a71176720265be9d2e77658481fvboxsync PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsync LogFlow(("%s: iInstance/#d\n", __FUNCTION__, pDrvIns->iInstance));
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsync PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync if (pThis->pNvram != NULL)
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pThis->pNvram->mpDrv = NULL;
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsync}
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsync
c4ee81a185c754f177a871a1ed2e1bc66256858fvboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync/**
1d2154cff09d431181caed9114304c11bb7374c9vboxsync * @interface_method_impl(PDMDRVREG,pfnConstruct)
1d2154cff09d431181caed9114304c11bb7374c9vboxsync */
1d2154cff09d431181caed9114304c11bb7374c9vboxsyncDECLCALLBACK(int) Nvram::drvNvram_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
1d2154cff09d431181caed9114304c11bb7374c9vboxsync{
eac18a2a75654a71176720265be9d2e77658481fvboxsync PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync LogFlowFunc(("iInstance/#d, pCfg:%p, fFlags:%x\n", pDrvIns->iInstance, pCfg, fFlags));
1d2154cff09d431181caed9114304c11bb7374c9vboxsync PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /*
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * Initalize instance data variables first.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync //pThis->pNvram = NULL;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync //pThis->cLoadedVariables = 0;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync //pThis->fPermanentSave = false;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pThis->pCfgVarRoot = CFGMR3GetChild(pCfg, "Vars");
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync //pThis->pLastVarNode = NULL;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pThis->idxLastVar = UINT32_MAX / 2;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pDrvIns->IBase.pfnQueryInterface = Nvram::drvNvram_QueryInterface;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pThis->INvramConnector.pfnVarQueryByIndex = drvNvram_VarQueryByIndex;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pThis->INvramConnector.pfnVarStoreSeqBegin = drvNvram_VarStoreSeqBegin;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pThis->INvramConnector.pfnVarStoreSeqPut = drvNvram_VarStoreSeqPut;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pThis->INvramConnector.pfnVarStoreSeqEnd = drvNvram_VarStoreSeqEnd;
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /*
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * Validate and read configuration.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync */
ddebb26839cf7640db6422d97d78abd4452aeca9vboxsync if (!CFGMR3AreValuesValid(pCfg, "Object\0"
ddebb26839cf7640db6422d97d78abd4452aeca9vboxsync "PermanentSave\0"))
1d2154cff09d431181caed9114304c11bb7374c9vboxsync return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync ("Configuration error: Not possible to attach anything to this driver!\n"),
1d2154cff09d431181caed9114304c11bb7374c9vboxsync VERR_PDM_DRVINS_NO_ATTACH);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync int rc = CFGMR3QueryPtr(pCfg, "Object", (void **)&pThis->pNvram);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync AssertMsgRCReturn(rc, ("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc), rc);
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync rc = CFGMR3QueryBoolDef(pCfg, "PermanentSave", &pThis->fPermanentSave, false);
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync AssertRCReturn(rc, rc);
ddebb26839cf7640db6422d97d78abd4452aeca9vboxsync
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync /*
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync * Let the associated class instance know about us.
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync */
c4ccc0915f8ac8c1d8eb0565a17043dda0a666ddvboxsync pThis->pNvram->mpDrv = pThis;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync return VINF_SUCCESS;
1d2154cff09d431181caed9114304c11bb7374c9vboxsync}
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsync
1d2154cff09d431181caed9114304c11bb7374c9vboxsyncconst PDMDRVREG Nvram::DrvReg =
1d2154cff09d431181caed9114304c11bb7374c9vboxsync{
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* u32Version */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync PDM_DRVREG_VERSION,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* szName[32] */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync "NvramStorage",
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* szRCMod[32] */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync "",
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* szR0Mod[32] */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync "",
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pszDescription */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync "NVRAM Main Driver",
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* fFlags */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* fClass */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync PDM_DRVREG_CLASS_VMMDEV,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* cMaxInstances */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync 1,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* cbInstance */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync sizeof(NVRAM),
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pfnConstruct */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync Nvram::drvNvram_Construct,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pfnDestruct */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync Nvram::drvNvram_Destruct,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pfnRelocate */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync NULL,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pfnIOCtl */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync NULL,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pfnPowerOn */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync NULL,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pfnReset */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync NULL,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pfnSuspend */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync NULL,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pfnResume */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync NULL,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pfnAttach */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync NULL,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pfnDetach */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync NULL,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pfnPowerOff */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync NULL,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* pfnSoftReset */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync NULL,
1d2154cff09d431181caed9114304c11bb7374c9vboxsync /* u32VersionEnd */
1d2154cff09d431181caed9114304c11bb7374c9vboxsync PDM_DRVREG_VERSION
1d2154cff09d431181caed9114304c11bb7374c9vboxsync};
1d2154cff09d431181caed9114304c11bb7374c9vboxsync/* vi: set tabstop=4 shiftwidth=4 expandtab: */