Index: trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
===================================================================
--- trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf	(revision 58188)
+++ trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf	(revision 58189)
@@ -38,4 +38,5 @@
   MdePkg/MdePkg.dec
   MdeModulePkg/MdeModulePkg.dec
+  VBoxPkg/VBoxPkg.dec                           # VBox specific so the code can find some necessary headers
 
 
Index: trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/InitVariable.c
===================================================================
--- trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/InitVariable.c	(revision 58188)
+++ trunk/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/InitVariable.c	(revision 58189)
@@ -18,4 +18,70 @@
 
 EFI_EVENT   mVirtualAddressChangeEvent = NULL;
+
+#ifdef VBOX
+# include <Library/PrintLib.h>
+# include <Library/TimerLib.h>
+# include "VBoxPkg.h"
+# include "DevEFI.h"
+# include "iprt/asm.h"
+
+
+static UINT32 VBoxReadNVRAM(UINT8 *pu8Buffer, UINT32 cbBuffer)
+{
+    UINT32 idxBuffer = 0;
+    for (idxBuffer = 0; idxBuffer < cbBuffer; ++idxBuffer)
+        pu8Buffer[idxBuffer] = ASMInU8(EFI_PORT_VARIABLE_OP);
+    return idxBuffer;
+}
+
+DECLINLINE(void) VBoxWriteNVRAMU32Param(UINT32 u32CodeParam, UINT32 u32Param)
+{
+    ASMOutU32(EFI_PORT_VARIABLE_OP, u32CodeParam);
+    ASMOutU32(EFI_PORT_VARIABLE_PARAM, u32Param);
+}
+
+static UINT32 VBoxWriteNVRAMByteArrayParam(const UINT8 *pbParam, UINT32 cbParam)
+{
+    UINT32 idxParam = 0;
+    for (idxParam = 0; idxParam < cbParam; ++idxParam)
+        ASMOutU8(EFI_PORT_VARIABLE_PARAM, pbParam[idxParam]);
+    return idxParam;
+}
+
+static void VBoxWriteNVRAMNameParam(const CHAR16 *pwszName)
+{
+    UINTN i;
+    UINTN cwcName = StrLen(pwszName);
+
+    ASMOutU32(EFI_PORT_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME_UTF16);
+    for (i = 0; i <= cwcName; i++)
+        ASMOutU16(EFI_PORT_VARIABLE_PARAM, pwszName[i]);
+}
+
+DECLINLINE(UINT32) VBoxWriteNVRAMGuidParam(const EFI_GUID *pGuid)
+{
+    ASMOutU32(EFI_PORT_VARIABLE_OP, EFI_VM_VARIABLE_OP_GUID);
+    return VBoxWriteNVRAMByteArrayParam((UINT8 *)pGuid, sizeof(EFI_GUID));
+}
+
+static UINT32 VBoxWriteNVRAMDoOp(UINT32 u32Operation)
+{
+    UINT32 u32Rc;
+    VBoxLogFlowFuncEnter();
+    VBoxLogFlowFuncMarkVar(u32Operation, "%x");
+    VBoxWriteNVRAMU32Param(EFI_VM_VARIABLE_OP_START, u32Operation);
+
+    while ((u32Rc = ASMInU32(EFI_PORT_VARIABLE_OP)) == EFI_VARIABLE_OP_STATUS_BSY)
+    {
+#if 0
+        MicroSecondDelay (400);
+#endif
+        /* @todo: sleep here. bird: won't ever happen, so don't bother. */
+    }
+    VBoxLogFlowFuncMarkVar(u32Rc, "%x");
+    VBoxLogFlowFuncLeave();
+    return u32Rc;
+}
+#endif
 
 /**
@@ -46,4 +112,5 @@
   )
 {
+#ifndef VBOX
   return EmuGetVariable (
           VariableName,
@@ -54,4 +121,59 @@
           &mVariableModuleGlobal->VariableGlobal[Physical]
           );
+#else
+    EFI_STATUS rc;
+    UINT32 u32Rc;
+
+    VBoxLogFlowFuncEnter();
+
+    /*
+     * Tell DevEFI to look for the specified variable.
+     */
+    VBoxWriteNVRAMGuidParam(VendorGuid);
+    VBoxWriteNVRAMNameParam(VariableName);
+    u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY);
+    if (u32Rc == EFI_VARIABLE_OP_STATUS_OK)
+    {
+        /*
+         * Check if we got enought space for the value.
+         */
+        UINT32 VarLen;
+        ASMOutU32(EFI_PORT_VARIABLE_OP, EFI_VM_VARIABLE_OP_VALUE_LENGTH);
+        VarLen = ASMInU32(EFI_PORT_VARIABLE_OP);
+        VBoxLogFlowFuncMarkVar(*DataSize, "%d");
+        VBoxLogFlowFuncMarkVar(VarLen, "%d");
+        if (   VarLen <= *DataSize
+            && Data)
+        {
+            /*
+             * We do, then read it and, if requrest, the attribute.
+             */
+            *DataSize = VarLen;
+            ASMOutU32(EFI_PORT_VARIABLE_OP, EFI_VM_VARIABLE_OP_VALUE);
+            VBoxReadNVRAM((UINT8 *)Data, VarLen);
+
+            if (Attributes)
+            {
+                ASMOutU32(EFI_PORT_VARIABLE_OP, EFI_VM_VARIABLE_OP_ATTRIBUTE);
+                *Attributes = ASMInU32(EFI_PORT_VARIABLE_OP);
+                VBoxLogFlowFuncMarkVar(Attributes, "%x");
+            }
+
+            rc = EFI_SUCCESS;
+        }
+        else
+        {
+            *DataSize = VarLen;
+            rc = EFI_BUFFER_TOO_SMALL;
+        }
+    }
+    else
+    {
+        rc = EFI_NOT_FOUND;
+    }
+
+    VBoxLogFlowFuncLeaveRC(rc);
+    return rc;
+#endif
 }
 
@@ -78,4 +200,5 @@
   )
 {
+#ifndef VBOX
   return EmuGetNextVariableName (
           VariableNameSize,
@@ -84,4 +207,70 @@
           &mVariableModuleGlobal->VariableGlobal[Physical]
           );
+#else
+    uint32_t    u32Rc;
+    EFI_STATUS  rc;
+    VBoxLogFlowFuncEnter();
+
+    /*
+     * Validate inputs.
+     */
+    if (!VariableNameSize || !VariableName || !VendorGuid)
+    {
+        VBoxLogFlowFuncLeaveRC(EFI_INVALID_PARAMETER);
+        return EFI_INVALID_PARAMETER;
+    }
+
+    /*
+     * Tell DevEFI which the current variable is, then ask for the next one.
+     */
+    if (!VariableName[0])
+        u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY_REWIND);
+    else
+    {
+        VBoxWriteNVRAMGuidParam(VendorGuid);
+        VBoxWriteNVRAMNameParam(VariableName);
+        u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY);
+    }
+    if (u32Rc == EFI_VARIABLE_OP_STATUS_OK)
+        u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY_NEXT);
+    /** @todo We're supposed to skip stuff depending on attributes and
+     *        runtime/boottime, at least if EmuGetNextVariableName is something
+     *        to go by... */
+
+    if (u32Rc == EFI_VARIABLE_OP_STATUS_OK)
+    {
+        /*
+         * Output buffer check.
+         */
+        UINT32      cwcName;
+        ASMOutU32(EFI_PORT_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME_LENGTH_UTF16);
+        cwcName = ASMInU32(EFI_PORT_VARIABLE_OP);
+        if ((cwcName + 1) * 2 <= *VariableNameSize) /* ASSUMES byte size is specified */
+        {
+            UINT32 i;
+
+            /*
+             * Read back the result.
+             */
+            ASMOutU32(EFI_PORT_VARIABLE_OP, EFI_VM_VARIABLE_OP_GUID);
+            VBoxReadNVRAM((UINT8 *)VendorGuid, sizeof(EFI_GUID));
+
+            ASMOutU32(EFI_PORT_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME_UTF16);
+            for (i = 0; i < cwcName; i++)
+                VariableName[i] = ASMInU16(EFI_PORT_VARIABLE_OP);
+            VariableName[i] = '\0';
+
+            rc = EFI_SUCCESS;
+        }
+        else
+            rc = EFI_BUFFER_TOO_SMALL;
+        *VariableNameSize = (cwcName + 1) * 2;
+    }
+    else
+        rc = EFI_NOT_FOUND; /* whatever */
+
+    VBoxLogFlowFuncLeaveRC(rc);
+    return rc;
+#endif
 }
 
@@ -114,4 +303,5 @@
   )
 {
+#ifndef VBOX
   return EmuSetVariable (
           VariableName,
@@ -124,4 +314,34 @@
           &mVariableModuleGlobal->NonVolatileLastVariableOffset
           );
+#else
+    UINT32 u32Rc;
+    VBoxLogFlowFuncEnter();
+    VBoxLogFlowFuncMarkVar(VendorGuid, "%g");
+    VBoxLogFlowFuncMarkVar(VariableName, "%s");
+    VBoxLogFlowFuncMarkVar(DataSize, "%d");
+    /* set guid */
+    VBoxWriteNVRAMGuidParam(VendorGuid);
+    /* set name */
+    VBoxWriteNVRAMNameParam(VariableName);
+    /* set attribute */
+    VBoxWriteNVRAMU32Param(EFI_VM_VARIABLE_OP_ATTRIBUTE, Attributes);
+    /* set value length */
+    VBoxWriteNVRAMU32Param(EFI_VM_VARIABLE_OP_VALUE_LENGTH, (UINT32)DataSize);
+    /* fill value bytes */
+    ASMOutU32(EFI_PORT_VARIABLE_OP, EFI_VM_VARIABLE_OP_VALUE);
+    VBoxWriteNVRAMByteArrayParam(Data, (UINT32)DataSize);
+    /* start fetch operation */
+    u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_ADD);
+    /* process errors */
+    VBoxLogFlowFuncLeave();
+    switch (u32Rc)
+    {
+        case EFI_VARIABLE_OP_STATUS_OK:
+            return EFI_SUCCESS;
+        case EFI_VARIABLE_OP_STATUS_NOT_WP:
+        default:
+            return EFI_WRITE_PROTECTED;
+    }
+#endif
 }
 
@@ -153,4 +373,5 @@
   )
 {
+#ifndef VBOX
   return EmuQueryVariableInfo (
           Attributes,
@@ -160,4 +381,10 @@
           &mVariableModuleGlobal->VariableGlobal[Physical]
           );
+#else
+    *MaximumVariableStorageSize = 64 * 1024 * 1024;
+    *MaximumVariableSize = 1024;
+    *RemainingVariableStorageSize = 32 * 1024 * 1024;
+    return EFI_SUCCESS;
+#endif
 }
 
@@ -179,4 +406,5 @@
   )
 {
+#ifndef VBOX
   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);
   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);
@@ -191,4 +419,5 @@
     );
   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
+#endif
 }
 
@@ -247,4 +476,58 @@
   ASSERT_EFI_ERROR (Status);
 
+#ifdef VBOX
+  /* Self Test */
+    {
+        EFI_GUID TestUUID = {0xe660597e, 0xb94d, 0x4209, {0x9c, 0x80, 0x18, 0x05, 0xb5, 0xd1, 0x9b, 0x69}};
+        const char *pszVariable0 = "This is test!!!";
+        const CHAR16 *pszVariable1 = L"This is test!!!";
+        char szTestVariable[512];
+#if 0
+        rc = runtime->SetVariable(&TestUUID,
+            NULL ,
+            (EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS| EFI_VARIABLE_RUNTIME_ACCESS),
+            0,
+            NULL );
+        ASSERT(rc == EFI_INVALID_PARAMETER);
+#endif
+        UINTN size = sizeof(szTestVariable),
+        rc = RuntimeServiceSetVariable(
+            L"Test0" ,
+            &TestUUID,
+            (EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS| EFI_VARIABLE_RUNTIME_ACCESS),
+            AsciiStrSize(pszVariable0),
+            (void *)pszVariable0);
+        ASSERT_EFI_ERROR(rc);
+        SetMem(szTestVariable, 512, 0);
+        rc = RuntimeServiceGetVariable(
+            L"Test0" ,
+            &TestUUID,
+            NULL,
+            &size,
+            (void *)szTestVariable);
+        VBoxLogFlowFuncMarkVar(szTestVariable, "%a");
+
+        ASSERT(CompareMem(szTestVariable, pszVariable0, size) == 0);
+
+        rc = RuntimeServiceSetVariable(
+            L"Test1" ,
+            &TestUUID,
+            (EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS| EFI_VARIABLE_RUNTIME_ACCESS),
+            StrSize(pszVariable1),
+            (void *)pszVariable1);
+        ASSERT_EFI_ERROR(rc);
+        SetMem(szTestVariable, 512, 0);
+        size = StrSize(pszVariable1);
+        rc = RuntimeServiceGetVariable(
+            L"Test1" ,
+            &TestUUID,
+            NULL,
+            &size,
+            (void *)szTestVariable);
+        VBoxLogFlowFuncMarkVar((CHAR16 *)szTestVariable, "%s");
+        ASSERT(CompareMem(szTestVariable, pszVariable1, size) == 0);
+    }
+#endif
+
   return EFI_SUCCESS;
 }
Index: trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.dsc
===================================================================
--- trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.dsc	(revision 58188)
+++ trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.dsc	(revision 58189)
@@ -403,5 +403,5 @@
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
 !else
-  VBoxPkg/VBoxVariable/VBoxVariableRuntimeDxe.inf
+  MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
 !endif
   MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
Index: trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.fdf
===================================================================
--- trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.fdf	(revision 58188)
+++ trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.fdf	(revision 58189)
@@ -173,5 +173,5 @@
 INF  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
 !else
-INF VBoxPkg/VBoxVariable/VBoxVariableRuntimeDxe.inf
+INF  MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
 !endif
 INF  MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
Index: trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.dsc
===================================================================
--- trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.dsc	(revision 58188)
+++ trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.dsc	(revision 58189)
@@ -403,5 +403,5 @@
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
 !else
-  VBoxPkg/VBoxVariable/VBoxVariableRuntimeDxe.inf
+  MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
 !endif
   MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
Index: trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.fdf
===================================================================
--- trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.fdf	(revision 58188)
+++ trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.fdf	(revision 58189)
@@ -171,5 +171,5 @@
 INF  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
 !else
-INF VBoxPkg/VBoxVariable/VBoxVariableRuntimeDxe.inf
+INF  MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf
 !endif
 INF  MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
