Changeset 91324 in vbox
- Timestamp:
- Sep 22, 2021 10:38:20 AM (3 years ago)
- Location:
- trunk
- Files:
-
- 1 deleted
- 1 edited
-
include/VBox/vmm/pdmnvram.h (deleted)
-
src/VBox/Devices/EFI/DevEFI.cpp (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/EFI/DevEFI.cpp
r90447 r91324 30 30 #include <VBox/param.h> 31 31 #include <VBox/vmm/dbgf.h> 32 #include <VBox/vmm/pdmnvram.h>33 32 34 33 #include <iprt/asm.h> … … 74 73 * Structures and Typedefs * 75 74 *********************************************************************************************************************************/ 76 /**77 * EFI NVRAM variable.78 */79 typedef struct EFIVAR80 {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 only85 * 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 NVRAMDESC111 {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 it125 * 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 read129 * from it. When adding, updating or deleting a variable, this buffer is used130 * 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 138 75 /** 139 76 * The EFI device shared state structure. … … 260 197 RTGCPHYS GCPhysNvram; 261 198 262 /** NVRAM state variables. */263 NVRAMDESC NVRAM;264 199 /** Filename of the file containing the NVRAM store. */ 265 200 char *pszNvramFile; … … 274 209 /** The NVRAM driver base interface. */ 275 210 PPDMIBASE pDrvBase; 276 /** The NVRAM interface provided by the driver. */277 PPDMINVRAMCONNECTOR pNvramDrv;278 211 } Lun0; 279 212 } DEVEFIR3; … … 342 275 *********************************************************************************************************************************/ 343 276 #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 373 277 /** The EfiSystemNvDataFv GUID for NVRAM storage. */ 374 278 static const RTUUID g_UuidNvDataFv = { { 0x8d, 0x2b, 0xf1, 0xff, 0x96, 0x76, 0x8b, 0x4c, 0xa9, 0x85, 0x27, 0x47, 0x07, 0x5b, 0x4f, 0x50} }; … … 384 288 385 289 #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.pCurVar417 && pThisCC->NVRAM.pCurVar->cchName == cchVariableName418 && memcmp(pThisCC->NVRAM.pCurVar->szName, pszVariableName, cchVariableName + 1) == 0419 && RTUuidCompare(&pThisCC->NVRAM.pCurVar->uuid, pUuid) == 0420 )421 {422 *ppEfiVar = pThisCC->NVRAM.pCurVar;423 rc = VINF_SUCCESS;424 }425 else426 {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 == cchVariableName435 && memcmp(pEfiVar->szName, pszVariableName, cchVariableName + 1) == 0436 && 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 1461 /*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 #endif477 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 else583 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 the589 * 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 else614 {615 if (fEnumQuery)616 LogFlow(("EFI: Variable query -> NOT_FOUND \n"));617 else618 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 else663 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 #endif711 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 else728 {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 else768 pThisCC->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR;769 }770 else771 {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 == 4785 || pThisCC->NVRAM.VarOpBuf.cbValue == 8)786 && ( strcmp(pThisCC->NVRAM.VarOpBuf.szName, "BugCheckCode") == 0787 || strcmp(pThisCC->NVRAM.VarOpBuf.szName, "BugCheckParameter0") == 0788 || strcmp(pThisCC->NVRAM.VarOpBuf.szName, "BugCheckParameter1") == 0789 || strcmp(pThisCC->NVRAM.VarOpBuf.szName, "BugCheckParameter2") == 0790 || strcmp(pThisCC->NVRAM.VarOpBuf.szName, "BugCheckParameter3") == 0791 || 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 else798 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 else855 {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 else873 {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 else885 {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 else909 {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 else921 {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 else933 {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 else969 {970 if (cb == 1)971 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_GUID read.\n"));972 else973 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 else987 {988 if (cb == 1)989 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_NAME read.\n"));990 else991 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 else1013 {1014 if (cb == 2)1015 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_NAME_UTF16 read.\n"));1016 else1017 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 else1031 {1032 if (cb == 1)1033 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_VALUE read.\n"));1034 else1035 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 zero1058 * 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 zero1095 * 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 whole1112 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 else1162 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 1174 290 1175 291 /** … … 1493 609 # endif 1494 610 1495 case EFI_PORT_VARIABLE_OP: 1496 return nvramReadVariableOp(pThisCC, pu32, cb); 1497 611 case EFI_PORT_VARIABLE_OP: /* Obsolete */ 1498 612 case EFI_PORT_VARIABLE_PARAM: 1499 613 case EFI_PORT_DEBUG_POINT: … … 1648 762 1649 763 case EFI_PORT_VARIABLE_OP: 764 case EFI_PORT_VARIABLE_PARAM: 1650 765 { 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)); 1660 768 break; 1661 769 } 1662 1663 case EFI_PORT_VARIABLE_PARAM:1664 rc = nvramWriteVariableParam(pThisCC, u32);1665 break;1666 770 1667 771 case EFI_PORT_DEBUG_POINT: … … 1729 833 { 1730 834 PDEVEFI pThis = PDMDEVINS_2_DATA(pDevIns, PDEVEFI); 1731 PDEVEFIR3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PDEVEFIR3);1732 835 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 1733 836 LogFlow(("efiLoadExec: uVersion=%d uPass=%d\n", uVersion, uPass)); … … 1750 853 { 1751 854 /* 1752 * Kill the current variables before loading anything.855 * Ignore the old NVRAM state. 1753 856 */ 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); 1812 858 } 1813 859 … … 1964 1010 { 1965 1011 PDEVEFIR3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PDEVEFIR3); 1966 1967 if (pThisCC->Lun0.pNvramDrv) 1968 nvramStore(pThisCC); 1012 RT_NOREF(pThisCC); 1969 1013 } 1970 1014 … … 1984 1028 PDEVEFI pThis = PDMDEVINS_2_DATA(pDevIns, PDEVEFI); 1985 1029 PDEVEFIR3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PDEVEFIR3); 1986 1987 nvramFlushDeviceVariableList(pThisCC);1988 1030 1989 1031 if (pThisCC->pszNvramFile) … … 2384 1426 */ 2385 1427 pThisCC->pDevIns = pDevIns; 2386 RTListInit(&pThisCC->NVRAM.VarList);2387 1428 pThisCC->Lun0.IBase.pfnQueryInterface = devEfiQueryInterface; 2388 1429 … … 2519 1560 2520 1561 /* 2521 * NVRAM processing.1562 * Saved State handling. 2522 1563 */ 2523 1564 rc = PDMDevHlpSSMRegister(pDevIns, EFI_SSM_VERSION, sizeof(*pThisCC), efiSaveExec, efiLoadExec); 2524 1565 AssertRCReturn(rc, rc); 2525 1566 1567 /* 1568 * NVRAM storage. 1569 */ 2526 1570 rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThisCC->Lun0.IBase, &pThisCC->Lun0.pDrvBase, "NvramStorage"); 2527 1571 if (RT_SUCCESS(rc)) 2528 1572 { 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 */ 2534 1574 } 2535 1575 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER) 2536 {2537 pThisCC->Lun0.pNvramDrv = NULL;2538 1576 rc = VINF_SUCCESS; /* Missing driver is no error condition. */ 2539 }2540 1577 else 2541 1578 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("Can't attach Nvram Storage driver")); … … 2681 1718 PGMPHYS_ROM_FLAGS_PERMANENT_BINARY, "DMI tables"); 2682 1719 2683 AssertRCReturn(rc, rc);2684 2685 /*2686 * Register info handlers.2687 */2688 rc = PDMDevHlpDBGFInfoRegister(pDevIns, "nvram", "Dumps the NVRAM variables.\n", efiInfoNvram);2689 1720 AssertRCReturn(rc, rc); 2690 1721
Note:
See TracChangeset
for help on using the changeset viewer.

