VirtualBox

Changeset 91324 in vbox


Ignore:
Timestamp:
Sep 22, 2021 10:38:20 AM (3 years ago)
Author:
vboxsync
Message:

Devices/DevEFI: Kick out the unused NVRAM handling code in preparation for bugref:10098

Location:
trunk
Files:
1 deleted
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/EFI/DevEFI.cpp

    r90447 r91324  
    3030#include <VBox/param.h>
    3131#include <VBox/vmm/dbgf.h>
    32 #include <VBox/vmm/pdmnvram.h>
    3332
    3433#include <iprt/asm.h>
     
    7473*   Structures and Typedefs                                                                                                      *
    7574*********************************************************************************************************************************/
    76 /**
    77  * EFI NVRAM variable.
    78  */
    79 typedef struct EFIVAR
    80 {
    81     /** The list node for the variable. */
    82     RTLISTNODE      ListNode;
    83     /** The unique sequence number of the variable.
    84      * This is used to find pCurVar when restoring saved state and therefore only
    85      * set when saving. */
    86     uint32_t        idUniqueSavedState;
    87     /** The value attributess. */
    88     uint32_t        fAttributes;
    89     /** The variable name length (not counting the terminator char). */
    90     uint32_t        cchName;
    91     /** The size of the value. This cannot be zero. */
    92     uint32_t        cbValue;
    93     /** The vendor UUID scoping the variable name. */
    94     RTUUID          uuid;
    95     /** The variable name. */
    96     char            szName[EFI_VARIABLE_NAME_MAX];
    97     /** The variable value bytes.  */
    98     uint8_t         abValue[EFI_VARIABLE_VALUE_MAX];
    99 } EFIVAR;
    100 /** Pointer to an EFI NVRAM variable. */
    101 typedef EFIVAR *PEFIVAR;
    102 /** Pointer to a const EFI NVRAM variable. */
    103 typedef EFIVAR const *PCEFIVAR;
    104 /** Pointer to an EFI NVRAM variable pointer. */
    105 typedef PEFIVAR *PPEFIVAR;
    106 
    107 /**
    108  * NVRAM state.
    109  */
    110 typedef struct NVRAMDESC
    111 {
    112     /** The current operation. */
    113     EFIVAROP        enmOp;
    114     /** The current status. */
    115     uint32_t        u32Status;
    116     /** The current  */
    117     uint32_t        offOpBuffer;
    118     /** The current number of variables. */
    119     uint32_t        cVariables;
    120     /** The list of variables. */
    121     RTLISTANCHOR    VarList;
    122 
    123     /** The unique variable sequence ID, for the saved state only.
    124      * @todo It's part of this structure for hysterical raisins, consider remove it
    125      *       when changing the saved state format the next time. */
    126     uint32_t        idUniqueCurVar;
    127     /** Variable buffered used both when adding and querying NVRAM variables.
    128      * When querying a variable, a copy of it is stored in this buffer and read
    129      * from it.  When adding, updating or deleting a variable, this buffer is used
    130      * to set up the parameters before taking action. */
    131     EFIVAR          VarOpBuf;
    132     /** The current variable. This is only used by EFI_VARIABLE_OP_QUERY_NEXT,
    133      * the attribute readers work against the copy in VarOpBuf. */
    134     PEFIVAR         pCurVar;
    135 } NVRAMDESC;
    136 
    137 
    13875/**
    13976 * The EFI device shared state structure.
     
    260197    RTGCPHYS                GCPhysNvram;
    261198
    262     /** NVRAM state variables. */
    263     NVRAMDESC               NVRAM;
    264199    /** Filename of the file containing the NVRAM store. */
    265200    char                    *pszNvramFile;
     
    274209        /** The NVRAM driver base interface. */
    275210        PPDMIBASE           pDrvBase;
    276         /** The NVRAM interface provided by the driver. */
    277         PPDMINVRAMCONNECTOR pNvramDrv;
    278211    } Lun0;
    279212} DEVEFIR3;
     
    342275*********************************************************************************************************************************/
    343276#ifdef IN_RING3
    344 /** Saved state NVRAMDESC field descriptors. */
    345 static SSMFIELD const g_aEfiNvramDescField[] =
    346 {
    347         SSMFIELD_ENTRY(       NVRAMDESC, enmOp),
    348         SSMFIELD_ENTRY(       NVRAMDESC, u32Status),
    349         SSMFIELD_ENTRY(       NVRAMDESC, offOpBuffer),
    350         SSMFIELD_ENTRY_IGNORE(NVRAMDESC, VarOpBuf),
    351         SSMFIELD_ENTRY(       NVRAMDESC, cVariables),
    352         SSMFIELD_ENTRY_OLD(   idUnquireLast, 4),
    353         SSMFIELD_ENTRY_IGNORE(NVRAMDESC, VarList),
    354         SSMFIELD_ENTRY(       NVRAMDESC, idUniqueCurVar),
    355         SSMFIELD_ENTRY_IGNORE(NVRAMDESC, pCurVar),
    356         SSMFIELD_ENTRY_TERM()
    357 };
    358 
    359 /** Saved state EFIVAR field descriptors. */
    360 static SSMFIELD const g_aEfiVariableDescFields[] =
    361 {
    362         SSMFIELD_ENTRY_IGNORE(EFIVAR, ListNode),
    363         SSMFIELD_ENTRY(       EFIVAR, idUniqueSavedState),
    364         SSMFIELD_ENTRY(       EFIVAR, uuid),
    365         SSMFIELD_ENTRY(       EFIVAR, szName),
    366         SSMFIELD_ENTRY_OLD(   cchName, 4),
    367         SSMFIELD_ENTRY(       EFIVAR, abValue),
    368         SSMFIELD_ENTRY(       EFIVAR, cbValue),
    369         SSMFIELD_ENTRY(       EFIVAR, fAttributes),
    370         SSMFIELD_ENTRY_TERM()
    371 };
    372 
    373277/** The EfiSystemNvDataFv GUID for NVRAM storage. */
    374278static const RTUUID g_UuidNvDataFv = { { 0x8d, 0x2b, 0xf1, 0xff, 0x96, 0x76, 0x8b, 0x4c, 0xa9, 0x85, 0x27, 0x47, 0x07, 0x5b, 0x4f, 0x50} };
     
    384288
    385289#ifdef IN_RING3
    386 
    387 /**
    388  * Flushes the variable list.
    389  *
    390  * @param   pThisCC             The EFI state for the current context.
    391  */
    392 static void nvramFlushDeviceVariableList(PDEVEFIR3 pThisCC)
    393 {
    394     while (!RTListIsEmpty(&pThisCC->NVRAM.VarList))
    395     {
    396         PEFIVAR pEfiVar = RTListNodeGetNext(&pThisCC->NVRAM.VarList, EFIVAR, ListNode);
    397         RTListNodeRemove(&pEfiVar->ListNode);
    398         RTMemFree(pEfiVar);
    399     }
    400 
    401     pThisCC->NVRAM.pCurVar = NULL;
    402 }
    403 
    404 /**
    405  * This function looks up variable in NVRAM list.
    406  */
    407 static int nvramLookupVariableByUuidAndName(PDEVEFIR3 pThisCC, char *pszVariableName, PCRTUUID pUuid, PPEFIVAR ppEfiVar)
    408 {
    409     LogFlowFunc(("%RTuuid::'%s'\n", pUuid, pszVariableName));
    410     size_t const    cchVariableName = strlen(pszVariableName);
    411     int             rc              = VERR_NOT_FOUND;
    412 
    413     /*
    414      * Start by checking the last variable queried.
    415      */
    416     if (   pThisCC->NVRAM.pCurVar
    417         && pThisCC->NVRAM.pCurVar->cchName == cchVariableName
    418         && memcmp(pThisCC->NVRAM.pCurVar->szName, pszVariableName, cchVariableName + 1) == 0
    419         && RTUuidCompare(&pThisCC->NVRAM.pCurVar->uuid, pUuid) == 0
    420         )
    421     {
    422         *ppEfiVar = pThisCC->NVRAM.pCurVar;
    423         rc = VINF_SUCCESS;
    424     }
    425     else
    426     {
    427         /*
    428          * Linear list search.
    429          */
    430         PEFIVAR pEfiVar;
    431         RTListForEach(&pThisCC->NVRAM.VarList, pEfiVar, EFIVAR, ListNode)
    432         {
    433             Assert(strlen(pEfiVar->szName) == pEfiVar->cchName);
    434             if (   pEfiVar->cchName == cchVariableName
    435                 && memcmp(pEfiVar->szName, pszVariableName, cchVariableName + 1) == 0
    436                 && RTUuidCompare(&pEfiVar->uuid, pUuid) == 0)
    437             {
    438                 *ppEfiVar = pEfiVar;
    439                 rc = VINF_SUCCESS;
    440                 break;
    441             }
    442         }
    443     }
    444 
    445     LogFlowFunc(("rc=%Rrc pEfiVar=%p\n", rc, *ppEfiVar));
    446     return rc;
    447 }
    448 
    449 
    450 /**
    451  * Inserts the EFI variable into the list.
    452  *
    453  * This enforces the desired list ordering and/or insertion policy.
    454  *
    455  * @param   pThisCC         The EFI state for the current context.
    456  * @param   pEfiVar         The variable to insert.
    457  */
    458 static void nvramInsertVariable(PDEVEFIR3 pThisCC, PEFIVAR pEfiVar)
    459 {
    460 #if 1
    461     /*
    462      * Sorted by UUID and name.
    463      */
    464     PEFIVAR pCurVar;
    465     RTListForEach(&pThisCC->NVRAM.VarList, pCurVar, EFIVAR, ListNode)
    466     {
    467         int iDiff = RTUuidCompare(&pEfiVar->uuid, &pCurVar->uuid);
    468         if (!iDiff)
    469             iDiff = strcmp(pEfiVar->szName, pCurVar->szName);
    470         if (iDiff < 0)
    471         {
    472             RTListNodeInsertBefore(&pCurVar->ListNode, &pEfiVar->ListNode);
    473             return;
    474         }
    475     }
    476 #endif
    477 
    478     /*
    479      * Add it at the end.
    480      */
    481     RTListAppend(&pThisCC->NVRAM.VarList, &pEfiVar->ListNode);
    482 }
    483 
    484 
    485 /**
    486  * Creates an device internal list of variables.
    487  *
    488  * @returns VBox status code.
    489  * @param   pThisCC         The EFI state for the current context.
    490  */
    491 static int nvramLoad(PDEVEFIR3 pThisCC)
    492 {
    493     int rc;
    494     for (uint32_t iVar = 0; iVar < EFI_VARIABLE_MAX; iVar++)
    495     {
    496         PEFIVAR pEfiVar = (PEFIVAR)RTMemAllocZ(sizeof(EFIVAR));
    497         AssertReturn(pEfiVar, VERR_NO_MEMORY);
    498 
    499         pEfiVar->cchName = sizeof(pEfiVar->szName);
    500         pEfiVar->cbValue = sizeof(pEfiVar->abValue);
    501         rc = pThisCC->Lun0.pNvramDrv->pfnVarQueryByIndex(pThisCC->Lun0.pNvramDrv, iVar,
    502                                                        &pEfiVar->uuid, &pEfiVar->szName[0], &pEfiVar->cchName,
    503                                                        &pEfiVar->fAttributes, &pEfiVar->abValue[0], &pEfiVar->cbValue);
    504         if (RT_SUCCESS(rc))
    505         {
    506             /* Some validations. */
    507             rc = RTStrValidateEncoding(pEfiVar->szName);
    508             size_t cchName = RTStrNLen(pEfiVar->szName, sizeof(pEfiVar->szName));
    509             if (cchName != pEfiVar->cchName)
    510                 rc = VERR_INVALID_PARAMETER;
    511             if (pEfiVar->cbValue == 0)
    512                 rc = VERR_NO_DATA;
    513             if (RT_FAILURE(rc))
    514                 LogRel(("EFI/nvramLoad: Bad variable #%u: cbValue=%#x cchName=%#x (strlen=%#x) szName=%.*Rhxs\n",
    515                         iVar, pEfiVar->cbValue, pEfiVar->cchName, cchName, pEfiVar->cchName + 1, pEfiVar->szName));
    516         }
    517         if (RT_FAILURE(rc))
    518         {
    519             RTMemFree(pEfiVar);
    520             if (rc == VERR_NOT_FOUND)
    521                 rc = VINF_SUCCESS;
    522             AssertRC(rc);
    523             return rc;
    524         }
    525 
    526         /* Append it. */
    527         nvramInsertVariable(pThisCC, pEfiVar);
    528         pThisCC->NVRAM.cVariables++;
    529     }
    530 
    531     AssertLogRelMsgFailed(("EFI: Too many variables.\n"));
    532     return VERR_TOO_MUCH_DATA;
    533 }
    534 
    535 
    536 /**
    537  * Let the NVRAM driver store the internal NVRAM variable list.
    538  *
    539  * @returns VBox status code.
    540  * @param   pThisCC             The EFI state for the current context.
    541  */
    542 static int nvramStore(PDEVEFIR3 pThisCC)
    543 {
    544     /*
    545      * Count the non-volatile variables and issue the begin call.
    546      */
    547     PEFIVAR  pEfiVar;
    548     uint32_t cNonVolatile = 0;
    549     RTListForEach(&pThisCC->NVRAM.VarList, pEfiVar, EFIVAR, ListNode)
    550         if (pEfiVar->fAttributes & VBOX_EFI_VARIABLE_NON_VOLATILE)
    551             cNonVolatile++;
    552     int rc = pThisCC->Lun0.pNvramDrv->pfnVarStoreSeqBegin(pThisCC->Lun0.pNvramDrv, cNonVolatile);
    553     if (RT_SUCCESS(rc))
    554     {
    555         /*
    556          * Store each non-volatile variable.
    557          */
    558         uint32_t    idxVar  = 0;
    559         RTListForEach(&pThisCC->NVRAM.VarList, pEfiVar, EFIVAR, ListNode)
    560         {
    561             /* Skip volatile variables. */
    562             if (!(pEfiVar->fAttributes & VBOX_EFI_VARIABLE_NON_VOLATILE))
    563                 continue;
    564 
    565             int rc2 = pThisCC->Lun0.pNvramDrv->pfnVarStoreSeqPut(pThisCC->Lun0.pNvramDrv, idxVar,
    566                                                                &pEfiVar->uuid, pEfiVar->szName,  pEfiVar->cchName,
    567                                                                pEfiVar->fAttributes, pEfiVar->abValue, pEfiVar->cbValue);
    568             if (RT_FAILURE(rc2) && RT_SUCCESS_NP(rc))
    569             {
    570                 LogRel(("EFI: pfnVarStoreVarByIndex failed: %Rrc\n", rc));
    571                 rc = rc2;
    572             }
    573             idxVar++;
    574         }
    575         Assert(idxVar == cNonVolatile);
    576 
    577         /*
    578          * Done.
    579          */
    580         rc = pThisCC->Lun0.pNvramDrv->pfnVarStoreSeqEnd(pThisCC->Lun0.pNvramDrv, rc);
    581     }
    582     else
    583         LogRel(("EFI: pfnVarStoreBegin failed: %Rrc\n", rc));
    584     return rc;
    585 }
    586 
    587 /**
    588  * EFI_VARIABLE_OP_QUERY and EFI_VARIABLE_OP_QUERY_NEXT worker that copies the
    589  * variable into the VarOpBuf, set pCurVar and u32Status.
    590  *
    591  * @param   pThisCC             The EFI state for the current context.
    592  * @param   pEfiVar             The resulting variable. NULL if not found / end.
    593  * @param   fEnumQuery          Set if enumeration query, clear if specific.
    594  */
    595 static void nvramWriteVariableOpQueryCopyResult(PDEVEFIR3 pThisCC, PEFIVAR pEfiVar, bool fEnumQuery)
    596 {
    597     RT_ZERO(pThisCC->NVRAM.VarOpBuf.abValue);
    598     if (pEfiVar)
    599     {
    600         RT_ZERO(pThisCC->NVRAM.VarOpBuf.szName);
    601         pThisCC->NVRAM.VarOpBuf.uuid        = pEfiVar->uuid;
    602         pThisCC->NVRAM.VarOpBuf.cchName     = pEfiVar->cchName;
    603         memcpy(pThisCC->NVRAM.VarOpBuf.szName, pEfiVar->szName, pEfiVar->cchName); /* no need for + 1. */
    604         pThisCC->NVRAM.VarOpBuf.fAttributes = pEfiVar->fAttributes;
    605         pThisCC->NVRAM.VarOpBuf.cbValue     = pEfiVar->cbValue;
    606         memcpy(pThisCC->NVRAM.VarOpBuf.abValue, pEfiVar->abValue, pEfiVar->cbValue);
    607         pThisCC->NVRAM.pCurVar              = pEfiVar;
    608         pThisCC->NVRAM.u32Status            = EFI_VARIABLE_OP_STATUS_OK;
    609         LogFlow(("EFI: Variable query -> %RTuuid::'%s' (%d) abValue=%.*Rhxs\n", &pThisCC->NVRAM.VarOpBuf.uuid,
    610                  pThisCC->NVRAM.VarOpBuf.szName, pThisCC->NVRAM.VarOpBuf.cchName,
    611                  pThisCC->NVRAM.VarOpBuf.cbValue, pThisCC->NVRAM.VarOpBuf.abValue));
    612     }
    613     else
    614     {
    615         if (fEnumQuery)
    616             LogFlow(("EFI: Variable query -> NOT_FOUND \n"));
    617         else
    618             LogFlow(("EFI: Variable query %RTuuid::'%s' -> NOT_FOUND \n",
    619                      &pThisCC->NVRAM.VarOpBuf.uuid, pThisCC->NVRAM.VarOpBuf.szName));
    620         RT_ZERO(pThisCC->NVRAM.VarOpBuf.szName);
    621         pThisCC->NVRAM.VarOpBuf.fAttributes = 0;
    622         pThisCC->NVRAM.VarOpBuf.cbValue     = 0;
    623         pThisCC->NVRAM.VarOpBuf.cchName     = 0;
    624         pThisCC->NVRAM.pCurVar              = NULL;
    625         pThisCC->NVRAM.u32Status            = EFI_VARIABLE_OP_STATUS_NOT_FOUND;
    626     }
    627 }
    628 
    629 /**
    630  * Implements EFI_VARIABLE_PARAM + EFI_VARIABLE_OP_QUERY.
    631  *
    632  * @returns IOM strict status code.
    633  * @param   pThisCC             The EFI state for the current context.
    634  */
    635 static int nvramWriteVariableOpQuery(PDEVEFIR3 pThisCC)
    636 {
    637     Log(("EFI_VARIABLE_OP_QUERY: %RTuuid::'%s'\n", &pThisCC->NVRAM.VarOpBuf.uuid, pThisCC->NVRAM.VarOpBuf.szName));
    638 
    639     PEFIVAR pEfiVar;
    640     int rc = nvramLookupVariableByUuidAndName(pThisCC,
    641                                               pThisCC->NVRAM.VarOpBuf.szName,
    642                                               &pThisCC->NVRAM.VarOpBuf.uuid,
    643                                               &pEfiVar);
    644     nvramWriteVariableOpQueryCopyResult(pThisCC, RT_SUCCESS(rc) ? pEfiVar : NULL, false /*fEnumQuery*/);
    645     return VINF_SUCCESS;
    646 }
    647 
    648 /**
    649  * Implements EFI_VARIABLE_PARAM + EFI_VARIABLE_OP_QUERY_NEXT.
    650  *
    651  * This simply walks the list.
    652  *
    653  * @returns IOM strict status code.
    654  * @param   pThisCC             The EFI state for the current context.
    655  */
    656 static int nvramWriteVariableOpQueryNext(PDEVEFIR3 pThisCC)
    657 {
    658     Log(("EFI_VARIABLE_OP_QUERY_NEXT: pCurVar=%p\n", pThisCC->NVRAM.pCurVar));
    659     PEFIVAR pEfiVar = pThisCC->NVRAM.pCurVar;
    660     if (pEfiVar)
    661         pEfiVar = RTListGetNext(&pThisCC->NVRAM.VarList, pEfiVar, EFIVAR, ListNode);
    662     else
    663         pEfiVar = RTListGetFirst(&pThisCC->NVRAM.VarList, EFIVAR, ListNode);
    664     nvramWriteVariableOpQueryCopyResult(pThisCC, pEfiVar, true /* fEnumQuery */);
    665     return VINF_SUCCESS;
    666 }
    667 
    668 /**
    669  * Implements EFI_VARIABLE_PARAM + EFI_VARIABLE_OP_ADD.
    670  *
    671  * @returns IOM strict status code.
    672  * @param   pThisCC             The EFI state for the current context.
    673  */
    674 static int nvramWriteVariableOpAdd(PDEVEFIR3 pThisCC)
    675 {
    676     Log(("EFI_VARIABLE_OP_ADD: %RTuuid::'%s' fAttributes=%#x abValue=%.*Rhxs\n",
    677          &pThisCC->NVRAM.VarOpBuf.uuid, pThisCC->NVRAM.VarOpBuf.szName, pThisCC->NVRAM.VarOpBuf.fAttributes,
    678          pThisCC->NVRAM.VarOpBuf.cbValue, pThisCC->NVRAM.VarOpBuf.abValue));
    679 
    680     /*
    681      * Validate and adjust the input a little before we start.
    682      */
    683     int rc = RTStrValidateEncoding(pThisCC->NVRAM.VarOpBuf.szName);
    684     if (RT_FAILURE(rc))
    685         LogRel(("EFI: Badly encoded variable name: %.*Rhxs\n", pThisCC->NVRAM.VarOpBuf.cchName + 1, pThisCC->NVRAM.VarOpBuf.szName));
    686     if (RT_FAILURE(rc))
    687     {
    688         pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR;
    689         return VINF_SUCCESS;
    690     }
    691     pThisCC->NVRAM.VarOpBuf.cchName = (uint32_t)RTStrNLen(pThisCC->NVRAM.VarOpBuf.szName, sizeof(pThisCC->NVRAM.VarOpBuf.szName));
    692 
    693     /*
    694      * Look it up and see what to do.
    695      */
    696     PEFIVAR pEfiVar;
    697     rc = nvramLookupVariableByUuidAndName(pThisCC,
    698                                           pThisCC->NVRAM.VarOpBuf.szName,
    699                                           &pThisCC->NVRAM.VarOpBuf.uuid,
    700                                           &pEfiVar);
    701     if (RT_SUCCESS(rc))
    702     {
    703         LogFlowFunc(("Old abValue=%.*Rhxs\n", pEfiVar->cbValue, pEfiVar->abValue));
    704 #if 0 /** @todo Implement read-only EFI variables. */
    705         if (pEfiVar->fAttributes & EFI_VARIABLE_XXXXXXX)
    706         {
    707             pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_RO;
    708             break;
    709         }
    710 #endif
    711 
    712         if (pThisCC->NVRAM.VarOpBuf.cbValue == 0)
    713         {
    714             /*
    715              * Delete it.
    716              */
    717             LogRel(("EFI: Deleting variable %RTuuid::'%s'\n", &pThisCC->NVRAM.VarOpBuf.uuid, pThisCC->NVRAM.VarOpBuf.szName));
    718             RTListNodeRemove(&pEfiVar->ListNode);
    719             pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK;
    720             pThisCC->NVRAM.cVariables--;
    721 
    722             if (pThisCC->NVRAM.pCurVar == pEfiVar)
    723                 pThisCC->NVRAM.pCurVar = NULL;
    724             RTMemFree(pEfiVar);
    725             pEfiVar = NULL;
    726         }
    727         else
    728         {
    729             /*
    730              * Update/replace it. (The name and UUID are unchanged, of course.)
    731              */
    732             LogRel(("EFI: Replacing variable %RTuuid::'%s' fAttrib=%#x cbValue=%#x\n", &pThisCC->NVRAM.VarOpBuf.uuid,
    733                     pThisCC->NVRAM.VarOpBuf.szName, pThisCC->NVRAM.VarOpBuf.fAttributes, pThisCC->NVRAM.VarOpBuf.cbValue));
    734             pEfiVar->fAttributes   = pThisCC->NVRAM.VarOpBuf.fAttributes;
    735             pEfiVar->cbValue       = pThisCC->NVRAM.VarOpBuf.cbValue;
    736             memcpy(pEfiVar->abValue, pThisCC->NVRAM.VarOpBuf.abValue, pEfiVar->cbValue);
    737             pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK;
    738         }
    739     }
    740     else if (pThisCC->NVRAM.VarOpBuf.cbValue == 0)
    741     {
    742         /* delete operation, but nothing to delete. */
    743         LogFlow(("nvramWriteVariableOpAdd: Delete (not found)\n"));
    744         pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK;
    745     }
    746     else if (pThisCC->NVRAM.cVariables < EFI_VARIABLE_MAX)
    747     {
    748         /*
    749          * Add a new variable.
    750          */
    751         LogRel(("EFI: Adding variable %RTuuid::'%s' fAttrib=%#x cbValue=%#x\n", &pThisCC->NVRAM.VarOpBuf.uuid,
    752                 pThisCC->NVRAM.VarOpBuf.szName, pThisCC->NVRAM.VarOpBuf.fAttributes, pThisCC->NVRAM.VarOpBuf.cbValue));
    753         pEfiVar = (PEFIVAR)RTMemAllocZ(sizeof(EFIVAR));
    754         if (pEfiVar)
    755         {
    756             pEfiVar->uuid          = pThisCC->NVRAM.VarOpBuf.uuid;
    757             pEfiVar->cchName       = pThisCC->NVRAM.VarOpBuf.cchName;
    758             memcpy(pEfiVar->szName, pThisCC->NVRAM.VarOpBuf.szName, pEfiVar->cchName); /* The buffer is zeroed, so skip '\0'. */
    759             pEfiVar->fAttributes   = pThisCC->NVRAM.VarOpBuf.fAttributes;
    760             pEfiVar->cbValue       = pThisCC->NVRAM.VarOpBuf.cbValue;
    761             memcpy(pEfiVar->abValue, pThisCC->NVRAM.VarOpBuf.abValue, pEfiVar->cbValue);
    762 
    763             nvramInsertVariable(pThisCC, pEfiVar);
    764             pThisCC->NVRAM.cVariables++;
    765             pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK;
    766         }
    767         else
    768             pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR;
    769     }
    770     else
    771     {
    772         /*
    773          * Too many variables.
    774          */
    775         LogRelMax(5, ("EFI: Too many variables (%RTuuid::'%s' fAttrib=%#x cbValue=%#x)\n", &pThisCC->NVRAM.VarOpBuf.uuid,
    776                   pThisCC->NVRAM.VarOpBuf.szName, pThisCC->NVRAM.VarOpBuf.fAttributes, pThisCC->NVRAM.VarOpBuf.cbValue));
    777         pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR;
    778         Log(("nvramWriteVariableOpAdd: Too many variabled.\n"));
    779     }
    780 
    781     /*
    782      * Log the value of bugcheck variables.
    783      */
    784     if (   (   pThisCC->NVRAM.VarOpBuf.cbValue == 4
    785             || pThisCC->NVRAM.VarOpBuf.cbValue == 8)
    786         && (   strcmp(pThisCC->NVRAM.VarOpBuf.szName, "BugCheckCode") == 0
    787             || strcmp(pThisCC->NVRAM.VarOpBuf.szName, "BugCheckParameter0") == 0
    788             || strcmp(pThisCC->NVRAM.VarOpBuf.szName, "BugCheckParameter1") == 0
    789             || strcmp(pThisCC->NVRAM.VarOpBuf.szName, "BugCheckParameter2") == 0
    790             || strcmp(pThisCC->NVRAM.VarOpBuf.szName, "BugCheckParameter3") == 0
    791             || strcmp(pThisCC->NVRAM.VarOpBuf.szName, "BugCheckProgress")   == 0 ) )
    792     {
    793         if (pThisCC->NVRAM.VarOpBuf.cbValue == 4)
    794             LogRel(("EFI: %RTuuid::'%s' = %#010RX32\n", &pThisCC->NVRAM.VarOpBuf.uuid, pThisCC->NVRAM.VarOpBuf.szName,
    795                     RT_MAKE_U32_FROM_U8(pThisCC->NVRAM.VarOpBuf.abValue[0], pThisCC->NVRAM.VarOpBuf.abValue[1],
    796                                         pThisCC->NVRAM.VarOpBuf.abValue[2], pThisCC->NVRAM.VarOpBuf.abValue[3])));
    797         else
    798             LogRel(("EFI: %RTuuid::'%s' = %#018RX64\n", &pThisCC->NVRAM.VarOpBuf.uuid, pThisCC->NVRAM.VarOpBuf.szName,
    799                     RT_MAKE_U64_FROM_U8(pThisCC->NVRAM.VarOpBuf.abValue[0], pThisCC->NVRAM.VarOpBuf.abValue[1],
    800                                         pThisCC->NVRAM.VarOpBuf.abValue[2], pThisCC->NVRAM.VarOpBuf.abValue[3],
    801                                         pThisCC->NVRAM.VarOpBuf.abValue[4], pThisCC->NVRAM.VarOpBuf.abValue[5],
    802                                         pThisCC->NVRAM.VarOpBuf.abValue[6], pThisCC->NVRAM.VarOpBuf.abValue[7])));
    803     }
    804 
    805 
    806     LogFunc(("cVariables=%u u32Status=%#x\n", pThisCC->NVRAM.cVariables, pThisCC->NVRAM.u32Status));
    807     return VINF_SUCCESS;
    808 }
    809 
    810 /**
    811  * Implements EFI_VARIABLE_PARAM writes.
    812  *
    813  * @returns IOM strict status code.
    814  * @param   pThisCC             The EFI state for the current context.
    815  * @param   u32Value            The value being written.
    816  */
    817 static int nvramWriteVariableParam(PDEVEFIR3 pThisCC, uint32_t u32Value)
    818 {
    819     int rc = VINF_SUCCESS;
    820     switch (pThisCC->NVRAM.enmOp)
    821     {
    822         case EFI_VM_VARIABLE_OP_START:
    823             switch (u32Value)
    824             {
    825                 case EFI_VARIABLE_OP_QUERY:
    826                     rc = nvramWriteVariableOpQuery(pThisCC);
    827                     break;
    828 
    829                 case EFI_VARIABLE_OP_QUERY_NEXT:
    830                     rc = nvramWriteVariableOpQueryNext(pThisCC);
    831                     break;
    832 
    833                 case EFI_VARIABLE_OP_QUERY_REWIND:
    834                     Log2(("EFI_VARIABLE_OP_QUERY_REWIND\n"));
    835                     pThisCC->NVRAM.pCurVar   = NULL;
    836                     pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK;
    837                     break;
    838 
    839                 case EFI_VARIABLE_OP_ADD:
    840                     rc = nvramWriteVariableOpAdd(pThisCC);
    841                     break;
    842 
    843                 default:
    844                     pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR;
    845                     LogRel(("EFI: Unknown  EFI_VM_VARIABLE_OP_START value %#x\n", u32Value));
    846                     break;
    847             }
    848             break;
    849 
    850         case EFI_VM_VARIABLE_OP_GUID:
    851             Log2(("EFI_VM_VARIABLE_OP_GUID[%#x]=%#x\n", pThisCC->NVRAM.offOpBuffer, u32Value));
    852             if (pThisCC->NVRAM.offOpBuffer < sizeof(pThisCC->NVRAM.VarOpBuf.uuid))
    853                 pThisCC->NVRAM.VarOpBuf.uuid.au8[pThisCC->NVRAM.offOpBuffer++] = (uint8_t)u32Value;
    854             else
    855             {
    856                 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_GUID write (%#x).\n", u32Value));
    857                 pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR;
    858             }
    859             break;
    860 
    861         case EFI_VM_VARIABLE_OP_ATTRIBUTE:
    862             Log2(("EFI_VM_VARIABLE_OP_ATTRIBUTE=%#x\n", u32Value));
    863             pThisCC->NVRAM.VarOpBuf.fAttributes = u32Value;
    864             break;
    865 
    866         case EFI_VM_VARIABLE_OP_NAME:
    867             Log2(("EFI_VM_VARIABLE_OP_NAME[%#x]=%#x\n", pThisCC->NVRAM.offOpBuffer, u32Value));
    868             if (pThisCC->NVRAM.offOpBuffer < pThisCC->NVRAM.VarOpBuf.cchName)
    869                 pThisCC->NVRAM.VarOpBuf.szName[pThisCC->NVRAM.offOpBuffer++] = (uint8_t)u32Value;
    870             else if (u32Value == 0)
    871                 Assert(pThisCC->NVRAM.VarOpBuf.szName[sizeof(pThisCC->NVRAM.VarOpBuf.szName) - 1] == 0);
    872             else
    873             {
    874                 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_NAME write (%#x).\n", u32Value));
    875                 pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR;
    876             }
    877             break;
    878 
    879         case EFI_VM_VARIABLE_OP_NAME_LENGTH:
    880             Log2(("EFI_VM_VARIABLE_OP_NAME_LENGTH=%#x\n", u32Value));
    881             RT_ZERO(pThisCC->NVRAM.VarOpBuf.szName);
    882             if (u32Value < sizeof(pThisCC->NVRAM.VarOpBuf.szName))
    883                 pThisCC->NVRAM.VarOpBuf.cchName = u32Value;
    884             else
    885             {
    886                 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_NAME_LENGTH write (%#x, max %#x).\n",
    887                         u32Value, sizeof(pThisCC->NVRAM.VarOpBuf.szName) - 1));
    888                 pThisCC->NVRAM.VarOpBuf.cchName = sizeof(pThisCC->NVRAM.VarOpBuf.szName) - 1;
    889                 pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR;
    890             }
    891             Assert(pThisCC->NVRAM.offOpBuffer == 0);
    892             break;
    893 
    894         case EFI_VM_VARIABLE_OP_NAME_UTF16:
    895         {
    896             Log2(("EFI_VM_VARIABLE_OP_NAME_UTF16[%#x]=%#x\n", pThisCC->NVRAM.offOpBuffer, u32Value));
    897             /* Currently simplifying this to UCS2, i.e. no surrogates. */
    898             if (pThisCC->NVRAM.offOpBuffer == 0)
    899                 RT_ZERO(pThisCC->NVRAM.VarOpBuf.szName);
    900             uint32_t cbUtf8 = (uint32_t)RTStrCpSize(u32Value);
    901             if (pThisCC->NVRAM.offOpBuffer + cbUtf8 < sizeof(pThisCC->NVRAM.VarOpBuf.szName))
    902             {
    903                 RTStrPutCp(&pThisCC->NVRAM.VarOpBuf.szName[pThisCC->NVRAM.offOpBuffer], u32Value);
    904                 pThisCC->NVRAM.offOpBuffer += cbUtf8;
    905             }
    906             else if (u32Value == 0)
    907                 Assert(pThisCC->NVRAM.VarOpBuf.szName[sizeof(pThisCC->NVRAM.VarOpBuf.szName) - 1] == 0);
    908             else
    909             {
    910                 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_NAME_UTF16 write (%#x).\n", u32Value));
    911                 pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR;
    912             }
    913             break;
    914         }
    915 
    916         case EFI_VM_VARIABLE_OP_VALUE:
    917             Log2(("EFI_VM_VARIABLE_OP_VALUE[%#x]=%#x\n", pThisCC->NVRAM.offOpBuffer, u32Value));
    918             if (pThisCC->NVRAM.offOpBuffer < pThisCC->NVRAM.VarOpBuf.cbValue)
    919                 pThisCC->NVRAM.VarOpBuf.abValue[pThisCC->NVRAM.offOpBuffer++] = (uint8_t)u32Value;
    920             else
    921             {
    922                 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_VALUE write (%#x).\n", u32Value));
    923                 pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR;
    924             }
    925             break;
    926 
    927         case EFI_VM_VARIABLE_OP_VALUE_LENGTH:
    928             Log2(("EFI_VM_VARIABLE_OP_VALUE_LENGTH=%#x\n", u32Value));
    929             RT_ZERO(pThisCC->NVRAM.VarOpBuf.abValue);
    930             if (u32Value <= sizeof(pThisCC->NVRAM.VarOpBuf.abValue))
    931                 pThisCC->NVRAM.VarOpBuf.cbValue = u32Value;
    932             else
    933             {
    934                 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_VALUE_LENGTH write (%#x, max %#x).\n",
    935                         u32Value, sizeof(pThisCC->NVRAM.VarOpBuf.abValue)));
    936                 pThisCC->NVRAM.VarOpBuf.cbValue = sizeof(pThisCC->NVRAM.VarOpBuf.abValue);
    937                 pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR;
    938             }
    939             Assert(pThisCC->NVRAM.offOpBuffer == 0);
    940             break;
    941 
    942         default:
    943             pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR;
    944             LogRel(("EFI: Unexpected variable operation %#x\n", pThisCC->NVRAM.enmOp));
    945             break;
    946     }
    947     return VINF_SUCCESS;
    948 }
    949 
    950 /**
    951  * Implements EFI_VARIABLE_OP reads.
    952  *
    953  * @returns IOM strict status code.
    954  * @param   pThisCC             The EFI state for the current context.
    955  * @param   u32Value            The value being written.
    956  */
    957 static int nvramReadVariableOp(PDEVEFIR3 pThisCC,  uint32_t *pu32, unsigned cb)
    958 {
    959     switch (pThisCC->NVRAM.enmOp)
    960     {
    961         case EFI_VM_VARIABLE_OP_START:
    962             *pu32 = pThisCC->NVRAM.u32Status;
    963             break;
    964 
    965         case EFI_VM_VARIABLE_OP_GUID:
    966             if (pThisCC->NVRAM.offOpBuffer < sizeof(pThisCC->NVRAM.VarOpBuf.uuid) && cb == 1)
    967                 *pu32 = pThisCC->NVRAM.VarOpBuf.uuid.au8[pThisCC->NVRAM.offOpBuffer++];
    968             else
    969             {
    970                 if (cb == 1)
    971                     LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_GUID read.\n"));
    972                 else
    973                     LogRel(("EFI: Invalid EFI_VM_VARIABLE_OP_GUID read size (%d).\n", cb));
    974                 *pu32 = UINT32_MAX;
    975             }
    976             break;
    977 
    978         case EFI_VM_VARIABLE_OP_ATTRIBUTE:
    979             *pu32 = pThisCC->NVRAM.VarOpBuf.fAttributes;
    980             break;
    981 
    982         case EFI_VM_VARIABLE_OP_NAME:
    983             /* allow reading terminator char */
    984             if (pThisCC->NVRAM.offOpBuffer <= pThisCC->NVRAM.VarOpBuf.cchName && cb == 1)
    985                 *pu32 = pThisCC->NVRAM.VarOpBuf.szName[pThisCC->NVRAM.offOpBuffer++];
    986             else
    987             {
    988                 if (cb == 1)
    989                     LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_NAME read.\n"));
    990                 else
    991                     LogRel(("EFI: Invalid EFI_VM_VARIABLE_OP_NAME read size (%d).\n", cb));
    992                 *pu32 = UINT32_MAX;
    993             }
    994             break;
    995 
    996         case EFI_VM_VARIABLE_OP_NAME_LENGTH:
    997             *pu32 = pThisCC->NVRAM.VarOpBuf.cchName;
    998             break;
    999 
    1000         case EFI_VM_VARIABLE_OP_NAME_UTF16:
    1001             /* Lazy bird: ASSUME no surrogate pairs. */
    1002             if (pThisCC->NVRAM.offOpBuffer <= pThisCC->NVRAM.VarOpBuf.cchName && cb == 2)
    1003             {
    1004                 char const *psz1 = &pThisCC->NVRAM.VarOpBuf.szName[pThisCC->NVRAM.offOpBuffer];
    1005                 char const *psz2 = psz1;
    1006                 RTUNICP Cp;
    1007                 RTStrGetCpEx(&psz2, &Cp);
    1008                 *pu32 = Cp;
    1009                 Log2(("EFI_VM_VARIABLE_OP_NAME_UTF16[%u] => %#x (+%d)\n", pThisCC->NVRAM.offOpBuffer, *pu32, psz2 - psz1));
    1010                 pThisCC->NVRAM.offOpBuffer += psz2 - psz1;
    1011             }
    1012             else
    1013             {
    1014                 if (cb == 2)
    1015                     LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_NAME_UTF16 read.\n"));
    1016                 else
    1017                     LogRel(("EFI: Invalid EFI_VM_VARIABLE_OP_NAME_UTF16 read size (%d).\n", cb));
    1018                 *pu32 = UINT32_MAX;
    1019             }
    1020             break;
    1021 
    1022         case EFI_VM_VARIABLE_OP_NAME_LENGTH_UTF16:
    1023             /* Lazy bird: ASSUME no surrogate pairs. */
    1024             *pu32 = (uint32_t)RTStrUniLen(pThisCC->NVRAM.VarOpBuf.szName);
    1025             break;
    1026 
    1027         case EFI_VM_VARIABLE_OP_VALUE:
    1028             if (pThisCC->NVRAM.offOpBuffer < pThisCC->NVRAM.VarOpBuf.cbValue && cb == 1)
    1029                 *pu32 = pThisCC->NVRAM.VarOpBuf.abValue[pThisCC->NVRAM.offOpBuffer++];
    1030             else
    1031             {
    1032                 if (cb == 1)
    1033                     LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_VALUE read.\n"));
    1034                 else
    1035                     LogRel(("EFI: Invalid EFI_VM_VARIABLE_OP_VALUE read size (%d).\n", cb));
    1036                 *pu32 = UINT32_MAX;
    1037             }
    1038             break;
    1039 
    1040         case EFI_VM_VARIABLE_OP_VALUE_LENGTH:
    1041             *pu32 = pThisCC->NVRAM.VarOpBuf.cbValue;
    1042             break;
    1043 
    1044         default:
    1045             *pu32 = UINT32_MAX;
    1046             break;
    1047     }
    1048     return VINF_SUCCESS;
    1049 }
    1050 
    1051 
    1052 /**
    1053  * Checks if the EFI variable value looks like a printable UTF-8 string.
    1054  *
    1055  * @returns true if it is, false if not.
    1056  * @param   pEfiVar             The variable.
    1057  * @param   pfZeroTerm          Where to return whether the string is zero
    1058  *                              terminated.
    1059  */
    1060 static bool efiInfoNvramIsUtf8(PCEFIVAR pEfiVar, bool *pfZeroTerm)
    1061 {
    1062     if (pEfiVar->cbValue < 2)
    1063         return false;
    1064     const char *pachValue = (const char *)&pEfiVar->abValue[0];
    1065     *pfZeroTerm = pachValue[pEfiVar->cbValue - 1] == 0;
    1066 
    1067     /* Check the length. */
    1068     size_t cchValue = RTStrNLen((const char *)pEfiVar->abValue, pEfiVar->cbValue);
    1069     if (cchValue != pEfiVar->cbValue - *pfZeroTerm)
    1070         return false; /* stray zeros in the value, forget it. */
    1071 
    1072     /* Check that the string is valid UTF-8 and printable. */
    1073     const char *pchCur = pachValue;
    1074     while ((uintptr_t)(pchCur - pachValue) < cchValue)
    1075     {
    1076         RTUNICP uc;
    1077         int rc = RTStrGetCpEx(&pachValue, &uc);
    1078         if (RT_FAILURE(rc))
    1079             return false;
    1080         /** @todo Missing RTUniCpIsPrintable. */
    1081         if (uc < 128 && !RT_C_IS_PRINT(uc))
    1082             return false;
    1083     }
    1084 
    1085     return true;
    1086 }
    1087 
    1088 
    1089 /**
    1090  * Checks if the EFI variable value looks like a printable UTF-16 string.
    1091  *
    1092  * @returns true if it is, false if not.
    1093  * @param   pEfiVar             The variable.
    1094  * @param   pfZeroTerm          Where to return whether the string is zero
    1095  *                              terminated.
    1096  */
    1097 static bool efiInfoNvramIsUtf16(PCEFIVAR pEfiVar, bool *pfZeroTerm)
    1098 {
    1099     if (pEfiVar->cbValue < 4 || (pEfiVar->cbValue & 1))
    1100         return false;
    1101 
    1102     PCRTUTF16 pwcValue = (PCRTUTF16)&pEfiVar->abValue[0];
    1103     size_t    cwcValue = pEfiVar->cbValue /  sizeof(RTUTF16);
    1104     *pfZeroTerm = pwcValue[cwcValue - 1] == 0;
    1105     if (!*pfZeroTerm && RTUtf16IsHighSurrogate(pwcValue[cwcValue - 1]))
    1106         return false; /* Catch bad string early, before reading a char too many. */
    1107     cwcValue -= *pfZeroTerm;
    1108     if (cwcValue < 2)
    1109         return false;
    1110 
    1111     /* Check that the string is valid UTF-16, printable and spans the whole
    1112        value length. */
    1113     size_t    cAscii = 0;
    1114     PCRTUTF16 pwcCur = pwcValue;
    1115     while ((uintptr_t)(pwcCur - pwcValue) < cwcValue)
    1116     {
    1117         RTUNICP uc;
    1118         int rc = RTUtf16GetCpEx(&pwcCur, &uc);
    1119         if (RT_FAILURE(rc))
    1120             return false;
    1121         /** @todo Missing RTUniCpIsPrintable. */
    1122         if (uc < 128 && !RT_C_IS_PRINT(uc))
    1123             return false;
    1124         cAscii += uc < 128;
    1125     }
    1126     if (cAscii < 2)
    1127         return false;
    1128 
    1129     return true;
    1130 }
    1131 
    1132 
    1133 /**
    1134  * @implement_callback_method{FNDBGFHANDLERDEV}
    1135  */
    1136 static DECLCALLBACK(void) efiInfoNvram(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    1137 {
    1138     RT_NOREF(pszArgs);
    1139     PDEVEFIR3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PDEVEFIR3);
    1140     int const rcLock = PDMDevHlpCritSectEnter(pDevIns, pDevIns->pCritSectRoR3, VERR_IGNORED);
    1141     PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, pDevIns->pCritSectRoR3, rcLock); \
    1142 
    1143     pHlp->pfnPrintf(pHlp, "NVRAM variables: %u\n", pThisCC->NVRAM.cVariables);
    1144     PCEFIVAR pEfiVar;
    1145     RTListForEach(&pThisCC->NVRAM.VarList, pEfiVar, EFIVAR, ListNode)
    1146     {
    1147         /* Detect UTF-8 and UTF-16 strings. */
    1148         bool fZeroTerm = false;
    1149         if (efiInfoNvramIsUtf8(pEfiVar, &fZeroTerm))
    1150             pHlp->pfnPrintf(pHlp,
    1151                             "Variable - fAttr=%#04x - '%RTuuid:%s' - cb=%#04x\n"
    1152                             "String value (UTF-8%s): \"%.*s\"\n",
    1153                             pEfiVar->fAttributes, &pEfiVar->uuid, pEfiVar->szName, pEfiVar->cbValue,
    1154                             fZeroTerm ? "" : ",nz", pEfiVar->cbValue, pEfiVar->abValue);
    1155         else if (efiInfoNvramIsUtf16(pEfiVar, &fZeroTerm))
    1156             pHlp->pfnPrintf(pHlp,
    1157                             "Variable - fAttr=%#04x - '%RTuuid:%s' - cb=%#04x\n"
    1158                             "String value (UTF-16%s): \"%.*ls\"\n",
    1159                             pEfiVar->fAttributes, &pEfiVar->uuid, pEfiVar->szName, pEfiVar->cbValue,
    1160                             fZeroTerm ? "" : ",nz", pEfiVar->cbValue, pEfiVar->abValue);
    1161         else
    1162             pHlp->pfnPrintf(pHlp,
    1163                             "Variable - fAttr=%#04x - '%RTuuid:%s' - cb=%#04x\n"
    1164                             "%.*Rhxd\n",
    1165                             pEfiVar->fAttributes, &pEfiVar->uuid, pEfiVar->szName, pEfiVar->cbValue,
    1166                             pEfiVar->cbValue, pEfiVar->abValue);
    1167 
    1168     }
    1169 
    1170     PDMDevHlpCritSectLeave(pDevIns, pDevIns->pCritSectRoR3);
    1171 }
    1172 
    1173 
    1174290
    1175291/**
     
    1493609# endif
    1494610
    1495         case EFI_PORT_VARIABLE_OP:
    1496             return nvramReadVariableOp(pThisCC, pu32, cb);
    1497 
     611        case EFI_PORT_VARIABLE_OP: /* Obsolete */
    1498612        case EFI_PORT_VARIABLE_PARAM:
    1499613        case EFI_PORT_DEBUG_POINT:
     
    1648762
    1649763        case EFI_PORT_VARIABLE_OP:
     764        case EFI_PORT_VARIABLE_PARAM:
    1650765        {
    1651             /* clear buffer index */
    1652             if (u32 >= (uint32_t)EFI_VM_VARIABLE_OP_MAX)
    1653             {
    1654                 Log(("EFI: Invalid variable op %#x\n", u32));
    1655                 u32 = EFI_VM_VARIABLE_OP_ERROR;
    1656             }
    1657             pThisCC->NVRAM.offOpBuffer = 0;
    1658             pThisCC->NVRAM.enmOp = (EFIVAROP)u32;
    1659             Log2(("EFI_VARIABLE_OP: enmOp=%#x (%d)\n", u32, u32));
     766            /* Ignore access to the obsolete variable handling port. */
     767            Log(("EFI: Write to obsolete variable handling port %RTiop: %#x (cb=%d)\n", offPort, u32, cb));
    1660768            break;
    1661769        }
    1662 
    1663         case EFI_PORT_VARIABLE_PARAM:
    1664             rc = nvramWriteVariableParam(pThisCC, u32);
    1665             break;
    1666770
    1667771        case EFI_PORT_DEBUG_POINT:
     
    1729833{
    1730834    PDEVEFI         pThis   = PDMDEVINS_2_DATA(pDevIns, PDEVEFI);
    1731     PDEVEFIR3       pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PDEVEFIR3);
    1732835    PCPDMDEVHLPR3   pHlp    = pDevIns->pHlpR3;
    1733836    LogFlow(("efiLoadExec: uVersion=%d uPass=%d\n", uVersion, uPass));
     
    1750853    {
    1751854        /*
    1752          * Kill the current variables before loading anything.
     855         * Ignore the old NVRAM state.
    1753856         */
    1754         nvramFlushDeviceVariableList(pThisCC);
    1755 
    1756         /*
    1757          * Load the NVRAM state.
    1758          */
    1759         rc = pHlp->pfnSSMGetStructEx(pSSM, &pThisCC->NVRAM, sizeof(NVRAMDESC), 0, g_aEfiNvramDescField, NULL);
    1760         AssertRCReturn(rc, rc);
    1761         pThisCC->NVRAM.pCurVar = NULL;
    1762 
    1763         rc = pHlp->pfnSSMGetStructEx(pSSM, &pThisCC->NVRAM.VarOpBuf, sizeof(EFIVAR), 0, g_aEfiVariableDescFields, NULL);
    1764         AssertRCReturn(rc, rc);
    1765 
    1766         /*
    1767          * Load variables.
    1768          */
    1769         pThisCC->NVRAM.pCurVar = NULL;
    1770         Assert(RTListIsEmpty(&pThisCC->NVRAM.VarList));
    1771         RTListInit(&pThisCC->NVRAM.VarList);
    1772         for (uint32_t i = 0; i < pThisCC->NVRAM.cVariables; i++)
    1773         {
    1774             PEFIVAR pEfiVar = (PEFIVAR)RTMemAllocZ(sizeof(EFIVAR));
    1775             AssertReturn(pEfiVar, VERR_NO_MEMORY);
    1776 
    1777             rc = pHlp->pfnSSMGetStructEx(pSSM, pEfiVar, sizeof(EFIVAR), 0, g_aEfiVariableDescFields, NULL);
    1778             if (RT_SUCCESS(rc))
    1779             {
    1780                 if (   pEfiVar->cbValue > sizeof(pEfiVar->abValue)
    1781                     || pEfiVar->cbValue == 0)
    1782                 {
    1783                     rc = VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
    1784                     LogRel(("EFI: Loaded invalid variable value length %#x\n", pEfiVar->cbValue));
    1785                 }
    1786                 uint32_t cchVarName = (uint32_t)RTStrNLen(pEfiVar->szName, sizeof(pEfiVar->szName));
    1787                 if (cchVarName >= sizeof(pEfiVar->szName))
    1788                 {
    1789                     rc = VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
    1790                     LogRel(("EFI: Loaded variable name is unterminated.\n"));
    1791                 }
    1792                 if (pEfiVar->cchName > cchVarName) /* No check for 0 here, busted load code in 4.2, so now storing 0 here. */
    1793                 {
    1794                     rc = VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
    1795                     LogRel(("EFI: Loaded invalid variable name length %#x (cchVarName=%#x)\n", pEfiVar->cchName, cchVarName));
    1796                 }
    1797                 if (RT_SUCCESS(rc))
    1798                     pEfiVar->cchName = cchVarName;
    1799             }
    1800             AssertRCReturnStmt(rc, RTMemFree(pEfiVar), rc);
    1801 
    1802             /* Add it (not using nvramInsertVariable to preserve saved order),
    1803                updating the current variable pointer while we're here. */
    1804 #if 1
    1805             RTListAppend(&pThisCC->NVRAM.VarList, &pEfiVar->ListNode);
    1806 #else
    1807             nvramInsertVariable(pThisCC, pEfiVar);
    1808 #endif
    1809             if (pThisCC->NVRAM.idUniqueCurVar == pEfiVar->idUniqueSavedState)
    1810                 pThisCC->NVRAM.pCurVar = pEfiVar;
    1811         }
     857        rc = pHlp->pfnSSMSkipToEndOfUnit(pSSM);
    1812858    }
    1813859
     
    19641010{
    19651011    PDEVEFIR3  pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PDEVEFIR3);
    1966 
    1967     if (pThisCC->Lun0.pNvramDrv)
    1968         nvramStore(pThisCC);
     1012    RT_NOREF(pThisCC);
    19691013}
    19701014
     
    19841028    PDEVEFI   pThis   = PDMDEVINS_2_DATA(pDevIns, PDEVEFI);
    19851029    PDEVEFIR3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PDEVEFIR3);
    1986 
    1987     nvramFlushDeviceVariableList(pThisCC);
    19881030
    19891031    if (pThisCC->pszNvramFile)
     
    23841426     */
    23851427    pThisCC->pDevIns = pDevIns;
    2386     RTListInit(&pThisCC->NVRAM.VarList);
    23871428    pThisCC->Lun0.IBase.pfnQueryInterface = devEfiQueryInterface;
    23881429
     
    25191560
    25201561    /*
    2521      * NVRAM processing.
     1562     * Saved State handling.
    25221563     */
    25231564    rc = PDMDevHlpSSMRegister(pDevIns, EFI_SSM_VERSION, sizeof(*pThisCC), efiSaveExec, efiLoadExec);
    25241565    AssertRCReturn(rc, rc);
    25251566
     1567    /*
     1568     * NVRAM storage.
     1569     */
    25261570    rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThisCC->Lun0.IBase, &pThisCC->Lun0.pDrvBase, "NvramStorage");
    25271571    if (RT_SUCCESS(rc))
    25281572    {
    2529         pThisCC->Lun0.pNvramDrv = PDMIBASE_QUERY_INTERFACE(pThisCC->Lun0.pDrvBase, PDMINVRAMCONNECTOR);
    2530         AssertPtrReturn(pThisCC->Lun0.pNvramDrv, VERR_PDM_MISSING_INTERFACE_BELOW);
    2531 
    2532         rc = nvramLoad(pThisCC);
    2533         AssertRCReturn(rc, rc);
     1573        /** @todo */
    25341574    }
    25351575    else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    2536     {
    2537         pThisCC->Lun0.pNvramDrv = NULL;
    25381576        rc = VINF_SUCCESS; /* Missing driver is no error condition. */
    2539     }
    25401577    else
    25411578        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("Can't attach Nvram Storage driver"));
     
    26811718                              PGMPHYS_ROM_FLAGS_PERMANENT_BINARY, "DMI tables");
    26821719
    2683     AssertRCReturn(rc, rc);
    2684 
    2685     /*
    2686      * Register info handlers.
    2687      */
    2688     rc = PDMDevHlpDBGFInfoRegister(pDevIns, "nvram", "Dumps the NVRAM variables.\n", efiInfoNvram);
    26891720    AssertRCReturn(rc, rc);
    26901721
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette