Changeset 44591 in vbox for trunk/src/VBox
- Timestamp:
- Feb 8, 2013 4:48:00 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 83669
- Location:
- trunk/src/VBox
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/EFI/DevEFI.cpp
r44582 r44591 60 60 * Structures and Typedefs * 61 61 *******************************************************************************/ 62 typedef struct { 63 RTLISTNODE List; 64 int idxVariable; 65 RTUUID uuid; 66 char szVariableName[EFI_VARIABLE_NAME_MAX]; 67 uint32_t cbVariableName; 68 uint8_t au8Value[EFI_VARIABLE_VALUE_MAX]; 69 uint32_t cbValue; 70 uint32_t u32Attribute; 71 } EFIVAR, *PEFIVAR; 72 62 /** 63 * EFI NVRAM variable. 64 */ 65 typedef struct EFIVAR 66 { 67 /** The list node for the variable. */ 68 RTLISTNODE ListNode; 69 /** The unique sequence number of the variable. 70 * This is used to find pCurVar when restoring saved state and therefore only 71 * set when saving. */ 72 uint32_t idUniqueSavedState; 73 /** The value attributess. */ 74 uint32_t fAttributes; 75 /** The variable name length (not counting the terminator char). */ 76 uint32_t cchName; 77 /** The size of the value. This cannot be zero. */ 78 uint32_t cbValue; 79 /** The vendor UUID scoping the variable name. */ 80 RTUUID uuid; 81 /** The variable name. */ 82 char szName[EFI_VARIABLE_NAME_MAX]; 83 /** The variable value bytes. */ 84 uint8_t abValue[EFI_VARIABLE_VALUE_MAX]; 85 } EFIVAR; 86 /** Pointer to an EFI NVRAM variable. */ 87 typedef EFIVAR *PEFIVAR; 88 /** Pointer to an EFI NVRAM variable pointer. */ 73 89 typedef PEFIVAR *PPEFIVAR; 74 90 75 typedef struct { 91 /** 92 * NVRAM state. 93 */ 94 typedef struct NVRAMDESC 95 { 96 /** The current operation. */ 76 97 EFIVAROP enmOp; 98 /** The current status. */ 77 99 uint32_t u32Status; 78 uint32_t idxOpBuffer; 79 EFIVAR OperationVarOp; 80 int cNvramVariables; 81 int iNvramLastIndex; 82 EFIVAR NvramVariableList; 83 int idxCurrentVar; 84 PEFIVAR pCurrentVarOp; 100 /** The current */ 101 uint32_t offOpBuffer; 102 /** The current number of variables. */ 103 uint32_t cVariables; 104 /** The list of variables. */ 105 RTLISTANCHOR VarList; 106 107 /** The unique variable sequence ID, for the saved state only. 108 * @todo It's part of this structure for hysterical raisins, consider remove it 109 * when changing the saved state format the next time. */ 110 uint32_t idUniqueCurVar; 111 /** Variable buffered used both when adding and querying NVRAM variables. 112 * When querying a variable, a copy of it is stored in this buffer and read 113 * from it. When adding, updating or deleting a variable, this buffer is used 114 * to set up the parameters before taking action. */ 115 EFIVAR VarOpBuf; 116 /** The current variable. This is only used by EFI_VARIABLE_OP_QUERY_NEXT, 117 * the attribute readers work against the copy in VarOpBuf. */ 118 PEFIVAR pCurVar; 85 119 } NVRAMDESC; 86 120 121 122 /** 123 * The EFI device state structure. 124 */ 87 125 typedef struct DEVEFI 88 126 { 89 127 /** Pointer back to the device instance. */ 90 PPDMDEVINS pDevIns;128 PPDMDEVINS pDevIns; 91 129 /** EFI message buffer. */ 92 char szMsg[VBOX_EFI_DEBUG_BUFFER];130 char szMsg[VBOX_EFI_DEBUG_BUFFER]; 93 131 /** EFI message buffer index. */ 94 uint32_t iMsg;132 uint32_t iMsg; 95 133 /** EFI panic message buffer. */ 96 char szPanicMsg[2048];134 char szPanicMsg[2048]; 97 135 /** EFI panic message buffer index. */ 98 uint32_t iPanicMsg;136 uint32_t iPanicMsg; 99 137 /** The system EFI ROM data. */ 100 uint8_t *pu8EfiRom;138 uint8_t *pu8EfiRom; 101 139 /** The size of the system EFI ROM. */ 102 uint64_t cbEfiRom;140 uint64_t cbEfiRom; 103 141 /** The name of the EFI ROM file. */ 104 char *pszEfiRomFile;142 char *pszEfiRomFile; 105 143 /** Thunk page pointer. */ 106 uint8_t *pu8EfiThunk;144 uint8_t *pu8EfiThunk; 107 145 /** First entry point of the EFI firmware. */ 108 RTGCPHYS GCEntryPoint0;146 RTGCPHYS GCEntryPoint0; 109 147 /** Second Entry Point (PeiCore)*/ 110 RTGCPHYS GCEntryPoint1;148 RTGCPHYS GCEntryPoint1; 111 149 /** EFI firmware physical load address. */ 112 RTGCPHYS GCLoadAddress;150 RTGCPHYS GCLoadAddress; 113 151 /** Current info selector. */ 114 uint32_t iInfoSelector;152 uint32_t iInfoSelector; 115 153 /** Current info position. */ 116 int32_t offInfo;154 int32_t offInfo; 117 155 118 156 /** Number of virtual CPUs. (Config) */ 119 uint32_t cCpus;157 uint32_t cCpus; 120 158 /** RAM below 4GB (in bytes). (Config) */ 121 uint32_t cbBelow4GB;159 uint32_t cbBelow4GB; 122 160 /** RAM above 4GB (in bytes). (Config) */ 123 uint64_t cbAbove4GB;161 uint64_t cbAbove4GB; 124 162 /** The total amount of memory. */ 125 uint64_t cbRam;163 uint64_t cbRam; 126 164 /** The size of the RAM hole below 4GB. */ 127 uint64_t cbRamHole;165 uint64_t cbRamHole; 128 166 129 167 /** The size of the DMI tables. */ 130 uint16_t cbDmiTables;168 uint16_t cbDmiTables; 131 169 /** The DMI tables. */ 132 uint8_t au8DMIPage[0x1000];170 uint8_t au8DMIPage[0x1000]; 133 171 134 172 /** I/O-APIC enabled? */ 135 uint8_t u8IOAPIC;173 uint8_t u8IOAPIC; 136 174 137 175 /** Boot parameters passed to the firmware. */ 138 char szBootArgs[256];176 char szBootArgs[256]; 139 177 140 178 /** Host UUID (for DMI). */ 141 RTUUID aUuid;179 RTUUID aUuid; 142 180 143 181 /** Device properties buffer. */ … … 155 193 uint32_t u32GopMode; 156 194 /** Uga mode horisontal resolution. */ 157 uint32_t cxUgaResolution;195 uint32_t cxUgaResolution; 158 196 /** Uga mode vertical resolution. */ 159 uint32_t cyUgaResolution; 160 161 NVRAMDESC NVRAM; 197 uint32_t cyUgaResolution; 198 199 200 /** NVRAM state variables. */ 201 NVRAMDESC NVRAM; 202 203 /** 204 * NVRAM port - LUN\#0. 205 */ 162 206 struct 163 207 { 164 PPDMIBASE pDrvBase; 165 PDMIBASE IBase; 166 PPDMINVRAM pNvramDown; 208 /** The base interface we provide the NVRAM driver. */ 209 PDMIBASE IBase; 210 /** The NVRAM driver base interface. */ 211 PPDMIBASE pDrvBase; 212 /** The NVRAM interface provided by the driver. */ 213 PPDMINVRAMCONNECTOR pNvramDrv; 167 214 } Lun0; 168 215 } DEVEFI; … … 174 221 *******************************************************************************/ 175 222 /** The saved state version. */ 176 #define EFI_SSM_VERSION 1 223 #define EFI_SSM_VERSION 2 224 /** The saved state version from VBox 4.2. */ 225 #define EFI_SSM_VERSION_4_2 1 177 226 178 227 … … 183 232 static SSMFIELD const g_aEfiNvramDescField[] = 184 233 { 185 SSMFIELD_ENTRY (NVRAMDESC, enmOp),186 SSMFIELD_ENTRY (NVRAMDESC, u32Status),187 SSMFIELD_ENTRY (NVRAMDESC, idxOpBuffer),188 SSMFIELD_ENTRY_IGNORE (NVRAMDESC, OperationVarOp),189 SSMFIELD_ENTRY (NVRAMDESC, cNvramVariables),190 SSMFIELD_ENTRY (NVRAMDESC, iNvramLastIndex),191 SSMFIELD_ENTRY_IGNORE (NVRAMDESC, NvramVariableList),192 SSMFIELD_ENTRY (NVRAMDESC, idxCurrentVar),193 SSMFIELD_ENTRY_IGNORE (NVRAMDESC, pCurrentVarOp),234 SSMFIELD_ENTRY( NVRAMDESC, enmOp), 235 SSMFIELD_ENTRY( NVRAMDESC, u32Status), 236 SSMFIELD_ENTRY( NVRAMDESC, offOpBuffer), 237 SSMFIELD_ENTRY_IGNORE(NVRAMDESC, VarOpBuf), 238 SSMFIELD_ENTRY( NVRAMDESC, cVariables), 239 SSMFIELD_ENTRY_OLD( idUnquireLast, 4), 240 SSMFIELD_ENTRY_IGNORE(NVRAMDESC, VarList), 241 SSMFIELD_ENTRY( NVRAMDESC, idUniqueCurVar), 242 SSMFIELD_ENTRY_IGNORE(NVRAMDESC, pCurVar), 194 243 SSMFIELD_ENTRY_TERM() 195 244 }; … … 198 247 static SSMFIELD const g_aEfiVariableDescFields[] = 199 248 { 200 SSMFIELD_ENTRY_IGNORE (EFIVAR, List),201 SSMFIELD_ENTRY (EFIVAR, idxVariable),202 SSMFIELD_ENTRY (EFIVAR, uuid),203 SSMFIELD_ENTRY (EFIVAR, szVariableName),204 SSMFIELD_ENTRY (EFIVAR, cbVariableName),205 SSMFIELD_ENTRY (EFIVAR, au8Value),206 SSMFIELD_ENTRY (EFIVAR, cbValue),207 SSMFIELD_ENTRY (EFIVAR, u32Attribute),249 SSMFIELD_ENTRY_IGNORE(EFIVAR, ListNode), 250 SSMFIELD_ENTRY( EFIVAR, idUniqueSavedState), 251 SSMFIELD_ENTRY( EFIVAR, uuid), 252 SSMFIELD_ENTRY( EFIVAR, szName), 253 SSMFIELD_ENTRY_OLD( cchName, 4), 254 SSMFIELD_ENTRY( EFIVAR, abValue), 255 SSMFIELD_ENTRY( EFIVAR, cbValue), 256 SSMFIELD_ENTRY( EFIVAR, fAttributes), 208 257 SSMFIELD_ENTRY_TERM() 209 258 }; … … 211 260 212 261 213 /** 214 * Write to CMOS memory. 215 * This is used by the init complete code. 216 */ 217 static void cmosWrite(PPDMDEVINS pDevIns, int off, uint32_t u32Val) 218 { 219 Assert(off < 128); 220 Assert(u32Val < 256); 221 222 int rc = PDMDevHlpCMOSWrite(pDevIns, off, u32Val); 223 AssertRC(rc); 224 } 225 226 DECLINLINE(void) nvramFlushDeviceVariableList(PDEVEFI pThis) 227 { 228 PEFIVAR pEfiVar = NULL; 229 while (!RTListIsEmpty(&pThis->NVRAM.NvramVariableList.List)) 230 { 231 pEfiVar = RTListNodeGetNext(&pThis->NVRAM.NvramVariableList.List, EFIVAR, List); 232 RTListNodeRemove(&pEfiVar->List); 262 263 /** 264 * Flushes the variable list. 265 * 266 * @param pThis The EFI state. 267 */ 268 static void nvramFlushDeviceVariableList(PDEVEFI pThis) 269 { 270 while (!RTListIsEmpty(&pThis->NVRAM.VarList)) 271 { 272 PEFIVAR pEfiVar = RTListNodeGetNext(&pThis->NVRAM.VarList, EFIVAR, ListNode); 273 RTListNodeRemove(&pEfiVar->ListNode); 233 274 RTMemFree(pEfiVar); 234 275 } 235 } 236 237 /** 238 * This function looks up variable in NVRAM list 276 277 pThis->NVRAM.pCurVar = NULL; 278 } 279 280 /** 281 * This function looks up variable in NVRAM list. 239 282 */ 240 283 static int nvramLookupVariableByUuidAndName(PDEVEFI pThis, char *pszVariableName, PCRTUUID pUuid, PPEFIVAR ppEfiVar) 241 284 { 242 int rc = VERR_NOT_FOUND; 243 PEFIVAR pEfiVar = NULL; 244 LogFlowFunc(("pszVariableName:%s, pUuid:%RTuuid\n", pszVariableName, pUuid)); 245 int idxVar = 0; 246 RTListForEach((PRTLISTNODE)&pThis->NVRAM.NvramVariableList.List, pEfiVar, EFIVAR, List) 285 LogFlowFunc(("%RTuuid::'%s'\n", pUuid, pszVariableName)); 286 287 int rc = VERR_NOT_FOUND; 288 uint32_t cVariables = 0; 289 PEFIVAR pEfiVar; 290 RTListForEach(&pThis->NVRAM.VarList, pEfiVar, EFIVAR, ListNode) 247 291 { 248 292 LogFlowFunc(("pEfiVar:%p\n", pEfiVar)); 249 idxVar++;293 cVariables++; 250 294 if ( pEfiVar 251 295 && RTUuidCompare(pUuid, &pEfiVar->uuid) == 0 252 && RTStrCmp(pszVariableName, pEfiVar->sz VariableName) == 0)296 && RTStrCmp(pszVariableName, pEfiVar->szName) == 0) /** @todo case sensitive or insensitive? */ 253 297 { 254 298 *ppEfiVar = pEfiVar; … … 257 301 } 258 302 } 259 Assert(pThis->NVRAM.cNvramVariables >= idxVar); 260 LogFlowFuncLeaveRC(rc); 303 Assert(pThis->NVRAM.cVariables >= cVariables); 304 305 LogFlowFunc(("rc=%Rrc pEfiVar=%p\n", rc, *ppEfiVar)); 261 306 return rc; 262 307 } 263 308 309 /** 310 * Creates an device internal list of variables. 311 * 312 * @returns VBox status code. 313 * @param pThis The EFI state. 314 */ 264 315 static int nvramLoad(PDEVEFI pThis) 265 316 { 266 int rc = VINF_SUCCESS; 267 PEFIVAR pEfiVar = NULL; 268 int idxValue = 0; 269 while(idxValue < 100) 270 { 271 pEfiVar = (PEFIVAR)RTMemAllocZ(sizeof(EFIVAR)); 272 if (!pEfiVar) 317 int rc; 318 for (uint32_t iVar = 0; iVar < EFI_VARIABLE_MAX; iVar++) 319 { 320 PEFIVAR pEfiVar = (PEFIVAR)RTMemAllocZ(sizeof(EFIVAR)); 321 AssertReturn(pEfiVar, VERR_NO_MEMORY); 322 323 pEfiVar->cchName = sizeof(pEfiVar->szName); 324 pEfiVar->cbValue = sizeof(pEfiVar->abValue); 325 rc = pThis->Lun0.pNvramDrv->pfnVarQueryByIndex(pThis->Lun0.pNvramDrv, iVar, 326 &pEfiVar->uuid, &pEfiVar->szName[0], &pEfiVar->cchName, 327 &pEfiVar->fAttributes, &pEfiVar->abValue[0], &pEfiVar->cbValue); 328 if (RT_SUCCESS(rc)) 273 329 { 274 LogRel(("EFI: Can't allocate space for stored EFI variable\n")); 275 return VERR_NO_MEMORY; 330 /* Some validations. */ 331 rc = RTStrValidateEncoding(pEfiVar->szName); 332 size_t cchName = RTStrNLen(pEfiVar->szName, sizeof(pEfiVar->szName)); 333 if (cchName != pEfiVar->cchName) 334 rc = VERR_INVALID_PARAMETER; 335 if (pEfiVar->cbValue == 0) 336 rc = VERR_NO_DATA; 337 if (RT_FAILURE(rc)) 338 LogRel(("EFI/nvramLoad: Bad variable #%u: cbValue=%#x cchName=%#x (strlen=%#x) szName=%.*Rhxs\n", 339 pEfiVar->cbValue, pEfiVar->cchName, cchName, pEfiVar->cchName + 1, pEfiVar->szName)); 276 340 } 277 pEfiVar->cbVariableName = EFI_VARIABLE_NAME_MAX;278 pEfiVar->cbValue = EFI_VARIABLE_VALUE_MAX;279 rc = pThis->Lun0.pNvramDown->pfnLoadNvramValue(pThis->Lun0.pNvramDown,280 idxValue,281 &pEfiVar->uuid,282 pEfiVar->szVariableName,283 (size_t *)&pEfiVar->cbVariableName,284 pEfiVar->au8Value,285 (size_t *)&pEfiVar->cbValue);286 idxValue++;287 341 if (RT_FAILURE(rc)) 288 342 { 289 343 RTMemFree(pEfiVar); 290 break; 344 if (rc == VERR_NOT_FOUND) 345 rc = VINF_SUCCESS; 346 AssertRC(rc); 347 return rc; 291 348 } 292 pThis->NVRAM.cNvramVariables++; 293 RTListAppend((PRTLISTNODE)&pThis->NVRAM.NvramVariableList.List, &pEfiVar->List); 294 } 295 if ( RT_FAILURE(rc) 296 && rc == VERR_NOT_FOUND) 297 rc = VINF_SUCCESS; 298 AssertRCReturn(rc, rc); 349 350 /* Append it. */ 351 RTListAppend((PRTLISTNODE)&pThis->NVRAM.VarList, &pEfiVar->ListNode); 352 pThis->NVRAM.cVariables++; 353 } 354 355 AssertLogRelMsgFailed(("EFI: Too many variables.\n")); 356 return VERR_TOO_MUCH_DATA; 357 } 358 359 360 /** 361 * Let the NVRAM driver store the internal NVRAM variable list. 362 * 363 * @returns VBox status code. 364 * @param pThis The EFI state. 365 */ 366 static int nvramStore(PDEVEFI pThis) 367 { 368 int rc = pThis->Lun0.pNvramDrv->pfnVarStoreSeqBegin(pThis->Lun0.pNvramDrv, pThis->NVRAM.cVariables); 369 if (RT_SUCCESS(rc)) 370 { 371 uint32_t idxVar = 0; 372 PEFIVAR pEfiVar; 373 RTListForEach(&pThis->NVRAM.VarList, pEfiVar, EFIVAR, ListNode) 374 { 375 int rc2 = pThis->Lun0.pNvramDrv->pfnVarStoreSeqPut(pThis->Lun0.pNvramDrv, idxVar, 376 &pEfiVar->uuid, pEfiVar->szName, pEfiVar->cchName, 377 pEfiVar->fAttributes, pEfiVar->abValue, pEfiVar->cbValue); 378 if (RT_FAILURE(rc2) && RT_SUCCESS_NP(rc)) 379 { 380 LogRel(("EFI: pfnVarStoreVarByIndex failed: %Rrc\n", rc)); 381 rc = rc2; 382 } 383 idxVar++; 384 } 385 Assert((pThis->NVRAM.cVariables == idxVar)); 386 rc = pThis->Lun0.pNvramDrv->pfnVarStoreSeqEnd(pThis->Lun0.pNvramDrv, rc); 387 } 388 else 389 LogRel(("EFI: pfnVarStoreBegin failed: %Rrc\n", rc)); 299 390 return rc; 300 391 } 301 392 302 static int nvramStore(PDEVEFI pThis) 393 /** 394 * EFI_VARIABLE_OP_QUERY and EFI_VARIABLE_OP_QUERY_NEXT worker that copies the 395 * variable into the VarOpBuf, set pCurVar and u32Status. 396 * 397 * @param pThis The EFI state. 398 * @param pEfiVar The resulting variable. NULL if not found / end. 399 */ 400 static void nvramWriteVariableOpQueryCopyResult(PDEVEFI pThis, PEFIVAR pEfiVar) 401 { 402 RT_ZERO(pThis->NVRAM.VarOpBuf.szName); 403 RT_ZERO(pThis->NVRAM.VarOpBuf.abValue); 404 if (pEfiVar) 405 { 406 pThis->NVRAM.VarOpBuf.uuid = pEfiVar->uuid; 407 pThis->NVRAM.VarOpBuf.cchName = pEfiVar->cchName; 408 memcpy(pThis->NVRAM.VarOpBuf.szName, pEfiVar->szName, pEfiVar->cchName); /* no need for + 1. */ 409 pThis->NVRAM.VarOpBuf.fAttributes = pEfiVar->fAttributes; 410 pThis->NVRAM.VarOpBuf.cbValue = pEfiVar->cbValue; 411 memcpy(pThis->NVRAM.VarOpBuf.abValue, pEfiVar->abValue, pEfiVar->cbValue); 412 pThis->NVRAM.pCurVar = pEfiVar; 413 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK; 414 LogFlow(("EFI: Variable query -> %RTuuid::'%s' abValue=%.*Rhxs\n", &pThis->NVRAM.VarOpBuf.uuid, 415 pThis->NVRAM.VarOpBuf.szName, pThis->NVRAM.VarOpBuf.cbValue, pThis->NVRAM.VarOpBuf.abValue)); 416 } 417 else 418 { 419 pThis->NVRAM.VarOpBuf.fAttributes = 0; 420 pThis->NVRAM.VarOpBuf.cbValue = 0; 421 pThis->NVRAM.VarOpBuf.cchName = 0; 422 pThis->NVRAM.pCurVar = NULL; 423 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_NOT_FOUND; 424 LogFlow(("EFI: Variable query -> NOT_FOUND\n")); 425 } 426 } 427 428 /** 429 * Implements EFI_VARIABLE_PARAM + EFI_VARIABLE_OP_QUERY. 430 * 431 * @returns IOM strict status code. 432 * @param pThis The EFI state. 433 */ 434 static int nvramWriteVariableOpQuery(PDEVEFI pThis) 435 { 436 LogRel(("EFI: Querying Variable %RTuuid::'%s'\n", 437 &pThis->NVRAM.VarOpBuf.uuid, pThis->NVRAM.VarOpBuf.szName)); 438 439 PEFIVAR pEfiVar; 440 int rc = nvramLookupVariableByUuidAndName(pThis, 441 pThis->NVRAM.VarOpBuf.szName, 442 &pThis->NVRAM.VarOpBuf.uuid, 443 &pEfiVar); 444 nvramWriteVariableOpQueryCopyResult(pThis, RT_SUCCESS(rc) ? pEfiVar : NULL); 445 return VINF_SUCCESS; 446 } 447 448 /** 449 * Implements EFI_VARIABLE_PARAM + EFI_VARIABLE_OP_QUERY_NEXT. 450 * 451 * This simply walks the list. 452 * 453 * @returns IOM strict status code. 454 * @param pThis The EFI state. 455 */ 456 static int nvramWriteVariableOpQueryNext(PDEVEFI pThis) 457 { 458 Log(("EFI: Querying next variable...\n")); 459 PEFIVAR pEfiVar = pThis->NVRAM.pCurVar; 460 if (pEfiVar) 461 pEfiVar = RTListGetNext(&pThis->NVRAM.VarList, pEfiVar, EFIVAR, ListNode); 462 nvramWriteVariableOpQueryCopyResult(pThis, pEfiVar); 463 return VINF_SUCCESS; 464 } 465 466 /** 467 * Implements EFI_VARIABLE_PARAM + EFI_VARIABLE_OP_ADD. 468 * 469 * @returns IOM strict status code. 470 * @param pThis The EFI state. 471 */ 472 static int nvramWriteVariableOpAdd(PDEVEFI pThis) 473 { 474 LogRel(("EFI: Adding variable %RTuuid::'%s'\n", &pThis->NVRAM.VarOpBuf.uuid, pThis->NVRAM.VarOpBuf.szName)); 475 LogFlowFunc(("fAttributes=%#x abValue=%.*Rhxs\n", pThis->NVRAM.VarOpBuf.fAttributes, 476 pThis->NVRAM.VarOpBuf.cbValue, pThis->NVRAM.VarOpBuf.abValue)); 477 478 /* 479 * Validate the input a little. 480 */ 481 int rc = RTStrValidateEncoding(pThis->NVRAM.VarOpBuf.szName); 482 if (RT_FAILURE(rc)) 483 LogRel(("EFI: Badly encoded variable name: %.*Rhxs\n", pThis->NVRAM.VarOpBuf.cchName + 1, pThis->NVRAM.VarOpBuf.szName)); 484 size_t cchName = RTStrNLen(pThis->NVRAM.VarOpBuf.szName, sizeof(pThis->NVRAM.VarOpBuf.szName)); 485 if (cchName != pThis->NVRAM.VarOpBuf.cchName) 486 { 487 LogRel(("EFI: Bad name length %#x, expected %#x: %.*Rhxs\n", 488 cchName, pThis->NVRAM.VarOpBuf.cchName, pThis->NVRAM.VarOpBuf.cchName + 1, pThis->NVRAM.VarOpBuf.szName)); 489 rc = VERR_INVALID_PARAMETER; 490 } 491 if (RT_FAILURE(rc)) 492 { 493 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR; 494 return VINF_SUCCESS; 495 } 496 497 /* 498 * Look it up and see what to do. 499 */ 500 PEFIVAR pEfiVar; 501 rc = nvramLookupVariableByUuidAndName(pThis, 502 pThis->NVRAM.VarOpBuf.szName, 503 &pThis->NVRAM.VarOpBuf.uuid, 504 &pEfiVar); 505 if (RT_SUCCESS(rc)) 506 { 507 LogFlowFunc(("Old abValue=%.*Rhxs\n", pEfiVar->cbValue, pEfiVar->abValue)); 508 #if 0 /** @todo Implement read-only EFI variables. */ 509 if (pEfiVar->fAttributes & EFI_VARIABLE_XXXXXXX) 510 { 511 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_RO; 512 break; 513 } 514 #endif 515 516 if (pThis->NVRAM.VarOpBuf.cbValue == 0) 517 { 518 /* 519 * Delete it. 520 */ 521 LogFlow(("nvramWriteVariableOpAdd: Delete\n")); 522 RTListNodeRemove(&pEfiVar->ListNode); 523 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK; 524 pThis->NVRAM.cVariables--; 525 526 if (pThis->NVRAM.pCurVar == pEfiVar) 527 pThis->NVRAM.pCurVar = NULL; 528 RTMemFree(pEfiVar); 529 pEfiVar = NULL; 530 } 531 else 532 { 533 /* 534 * Update/replace it. (The name and UUID are unchanged, of course.) 535 */ 536 LogFlow(("nvramWriteVariableOpAdd: Replace\n")); 537 pEfiVar->fAttributes = pThis->NVRAM.VarOpBuf.fAttributes; 538 pEfiVar->cbValue = pThis->NVRAM.VarOpBuf.cbValue; 539 memcpy(pEfiVar->abValue, pThis->NVRAM.VarOpBuf.abValue, pEfiVar->cbValue); 540 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK; 541 } 542 } 543 else if (pThis->NVRAM.VarOpBuf.cbValue == 0) 544 { 545 /* delete operation, but nothing to delete. */ 546 LogFlow(("nvramWriteVariableOpAdd: Delete (not found)\n")); 547 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK; 548 } 549 else if (pThis->NVRAM.cVariables < EFI_VARIABLE_MAX) 550 { 551 /* 552 * Add a new variable. 553 */ 554 LogFlow(("nvramWriteVariableOpAdd: New\n")); 555 pEfiVar = (PEFIVAR)RTMemAllocZ(sizeof(EFIVAR)); 556 if (pEfiVar) 557 { 558 pEfiVar->uuid = pThis->NVRAM.VarOpBuf.uuid; 559 pEfiVar->cchName = pThis->NVRAM.VarOpBuf.cchName; 560 memcpy(pEfiVar->szName, pThis->NVRAM.VarOpBuf.szName, pEfiVar->cchName); /* The buffer is zeroed, so skip '\0'. */ 561 pEfiVar->fAttributes = pThis->NVRAM.VarOpBuf.fAttributes; 562 pEfiVar->cbValue = pThis->NVRAM.VarOpBuf.cbValue; 563 memcpy(pEfiVar->abValue, pThis->NVRAM.VarOpBuf.abValue, pEfiVar->cbValue); 564 565 RTListAppend(&pThis->NVRAM.VarList, &pEfiVar->ListNode); 566 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK; 567 pThis->NVRAM.cVariables++; 568 } 569 else 570 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR; 571 } 572 else 573 { 574 /* 575 * Too many variables. 576 */ 577 static unsigned s_cWarnings = 0; 578 if (s_cWarnings++ < 5) 579 LogRel(("EFI: Too many variables.\n")); 580 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR; 581 Log(("nvramWriteVariableOpAdd: Too many variabled.\n")); 582 } 583 584 LogFunc(("cVariables=%u u32Status=%#x\n", pThis->NVRAM.cVariables, pThis->NVRAM.u32Status)); 585 return VINF_SUCCESS; 586 } 587 588 /** 589 * Implements EFI_VARIABLE_PARAM writes. 590 * 591 * @returns IOM strict status code. 592 * @param pThis The EFI state. 593 * @param u32Value The value being written. 594 */ 595 static int nvramWriteVariableParam(PDEVEFI pThis, uint32_t u32Value) 303 596 { 304 597 int rc = VINF_SUCCESS; 305 PEFIVAR pEfiVar = NULL; 306 int idxVar = 0; 307 pThis->Lun0.pNvramDown->pfnFlushNvramStorage(pThis->Lun0.pNvramDown); 308 309 RTListForEach((PRTLISTNODE)&pThis->NVRAM.NvramVariableList.List, pEfiVar, EFIVAR, List) 310 { 311 pThis->Lun0.pNvramDown->pfnStoreNvramValue(pThis->Lun0.pNvramDown, 312 idxVar, 313 &pEfiVar->uuid, 314 pEfiVar->szVariableName, 315 pEfiVar->cbVariableName, 316 pEfiVar->au8Value, 317 pEfiVar->cbValue); 318 idxVar++; 319 } 320 Assert((pThis->NVRAM.cNvramVariables == idxVar)); 598 switch (pThis->NVRAM.enmOp) 599 { 600 case EFI_VM_VARIABLE_OP_START: 601 switch (u32Value) 602 { 603 case EFI_VARIABLE_OP_QUERY: 604 rc = nvramWriteVariableOpQuery(pThis); 605 break; 606 607 case EFI_VARIABLE_OP_QUERY_NEXT: 608 rc = nvramWriteVariableOpQueryNext(pThis); 609 break; 610 611 case EFI_VARIABLE_OP_ADD: 612 rc = nvramWriteVariableOpAdd(pThis); 613 break; 614 615 default: 616 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR; 617 LogRel(("EFI: Unknown EFI_VM_VARIABLE_OP_START value %#x\n", u32Value)); 618 break; 619 } 620 break; 621 622 case EFI_VM_VARIABLE_OP_GUID: 623 Log2(("EFI_VM_VARIABLE_OP_GUID[%#x]=%#x\n", pThis->NVRAM.offOpBuffer, u32Value)); 624 if (pThis->NVRAM.offOpBuffer < sizeof(pThis->NVRAM.VarOpBuf.uuid)) 625 pThis->NVRAM.VarOpBuf.uuid.au8[pThis->NVRAM.offOpBuffer++] = (uint8_t)u32Value; 626 else 627 { 628 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_GUID write (%#x).\n", u32Value)); 629 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR; 630 } 631 break; 632 633 case EFI_VM_VARIABLE_OP_ATTRIBUTE: 634 Log2(("EFI_VM_VARIABLE_OP_ATTRIBUTE=%#x\n", u32Value)); 635 pThis->NVRAM.VarOpBuf.fAttributes = u32Value; 636 break; 637 638 case EFI_VM_VARIABLE_OP_NAME: 639 Log2(("EFI_VM_VARIABLE_OP_NAME[%#x]=%#x\n", pThis->NVRAM.offOpBuffer, u32Value)); 640 if (pThis->NVRAM.offOpBuffer < pThis->NVRAM.VarOpBuf.cchName) 641 pThis->NVRAM.VarOpBuf.szName[pThis->NVRAM.offOpBuffer++] = (uint8_t)u32Value; 642 else if (u32Value == 0) 643 Assert(pThis->NVRAM.VarOpBuf.szName[sizeof(pThis->NVRAM.VarOpBuf.szName) - 1] == 0); 644 else 645 { 646 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_NAME write (%#x).\n", u32Value)); 647 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR; 648 } 649 break; 650 651 case EFI_VM_VARIABLE_OP_NAME_LENGTH: 652 Log2(("EFI_VM_VARIABLE_OP_NAME_LENGTH=%#x\n", u32Value)); 653 RT_ZERO(pThis->NVRAM.VarOpBuf.szName); 654 if (u32Value < sizeof(pThis->NVRAM.VarOpBuf.szName)) 655 pThis->NVRAM.VarOpBuf.cchName = u32Value; 656 else 657 { 658 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_NAME_LENGTH write (%#x, max %#x).\n", 659 u32Value, sizeof(pThis->NVRAM.VarOpBuf.szName) - 1)); 660 pThis->NVRAM.VarOpBuf.cchName = sizeof(pThis->NVRAM.VarOpBuf.szName) - 1; 661 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR; 662 } 663 Assert(pThis->NVRAM.offOpBuffer == 0); 664 break; 665 666 case EFI_VM_VARIABLE_OP_NAME_UTF16: 667 { 668 Log2(("EFI_VM_VARIABLE_OP_NAME_UTF16[%#x]=%#x\n", pThis->NVRAM.offOpBuffer, u32Value)); 669 /* Currently simplifying this to UCS2, i.e. no surrogates. */ 670 if (pThis->NVRAM.offOpBuffer == 0) 671 RT_ZERO(pThis->NVRAM.VarOpBuf.szName); 672 size_t cbUtf8 = RTStrCpSize(u32Value); 673 if (pThis->NVRAM.offOpBuffer + cbUtf8 < sizeof(pThis->NVRAM.VarOpBuf.szName)) 674 { 675 RTStrPutCp(&pThis->NVRAM.VarOpBuf.szName[pThis->NVRAM.offOpBuffer], u32Value); 676 pThis->NVRAM.offOpBuffer += cbUtf8; 677 } 678 else if (u32Value == 0) 679 Assert(pThis->NVRAM.VarOpBuf.szName[sizeof(pThis->NVRAM.VarOpBuf.szName) - 1] == 0); 680 else 681 { 682 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_NAME_UTF16 write (%#x).\n", u32Value)); 683 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR; 684 } 685 break; 686 } 687 688 case EFI_VM_VARIABLE_OP_VALUE: 689 Log2(("EFI_VM_VARIABLE_OP_VALUE[%#x]=%#x\n", pThis->NVRAM.offOpBuffer, u32Value)); 690 if (pThis->NVRAM.offOpBuffer < pThis->NVRAM.VarOpBuf.cbValue) 691 pThis->NVRAM.VarOpBuf.abValue[pThis->NVRAM.offOpBuffer++] = (uint8_t)u32Value; 692 else 693 { 694 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_VALUE write (%#x).\n", u32Value)); 695 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR; 696 } 697 break; 698 699 case EFI_VM_VARIABLE_OP_VALUE_LENGTH: 700 Log2(("EFI_VM_VARIABLE_OP_VALUE_LENGTH=%#x\n", u32Value)); 701 RT_ZERO(pThis->NVRAM.VarOpBuf.abValue); 702 if (u32Value <= sizeof(pThis->NVRAM.VarOpBuf.abValue)) 703 pThis->NVRAM.VarOpBuf.cbValue = u32Value; 704 else 705 { 706 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_VALUE_LENGTH write (%#x, max %#x).\n", 707 u32Value, sizeof(pThis->NVRAM.VarOpBuf.abValue))); 708 pThis->NVRAM.VarOpBuf.cbValue = sizeof(pThis->NVRAM.VarOpBuf.abValue); 709 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR; 710 } 711 Assert(pThis->NVRAM.offOpBuffer == 0); 712 break; 713 714 default: 715 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR; 716 LogRel(("EFI: Unexpected variable operation %#x\n", pThis->NVRAM.enmOp)); 717 break; 718 } 321 719 return VINF_SUCCESS; 322 720 } 721 722 /** 723 * Implements EFI_VARIABLE_OP reads. 724 * 725 * @returns IOM strict status code. 726 * @param pThis The EFI state. 727 * @param u32Value The value being written. 728 */ 729 static int nvramReadVariableOp(PDEVEFI pThis, uint32_t *pu32, unsigned cb) 730 { 731 switch (pThis->NVRAM.enmOp) 732 { 733 case EFI_VM_VARIABLE_OP_START: 734 *pu32 = pThis->NVRAM.u32Status; 735 break; 736 737 case EFI_VM_VARIABLE_OP_GUID: 738 if (pThis->NVRAM.offOpBuffer < sizeof(pThis->NVRAM.VarOpBuf.uuid) && cb == 1) 739 *pu32 = pThis->NVRAM.VarOpBuf.uuid.au8[pThis->NVRAM.offOpBuffer++]; 740 else 741 { 742 if (cb == 1) 743 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_GUID read.\n")); 744 else 745 LogRel(("EFI: Invalid EFI_VM_VARIABLE_OP_GUID read size (%d).\n", cb)); 746 *pu32 = UINT32_MAX; 747 } 748 break; 749 750 case EFI_VM_VARIABLE_OP_ATTRIBUTE: 751 *pu32 = pThis->NVRAM.VarOpBuf.fAttributes; 752 break; 753 754 case EFI_VM_VARIABLE_OP_NAME: 755 /* allow reading terminator char */ 756 if (pThis->NVRAM.offOpBuffer <= pThis->NVRAM.VarOpBuf.cchName && cb == 1) 757 *pu32 = pThis->NVRAM.VarOpBuf.szName[pThis->NVRAM.offOpBuffer++]; 758 else 759 { 760 if (cb == 1) 761 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_NAME read.\n")); 762 else 763 LogRel(("EFI: Invalid EFI_VM_VARIABLE_OP_NAME read size (%d).\n", cb)); 764 *pu32 = UINT32_MAX; 765 } 766 break; 767 768 case EFI_VM_VARIABLE_OP_NAME_LENGTH: 769 *pu32 = pThis->NVRAM.VarOpBuf.cchName; 770 break; 771 772 case EFI_VM_VARIABLE_OP_NAME_UTF16: 773 /* Lazy bird: ASSUME no surrogate pairs. */ 774 if (pThis->NVRAM.offOpBuffer < pThis->NVRAM.VarOpBuf.cchName) 775 { 776 char const *psz1 = &pThis->NVRAM.VarOpBuf.szName[pThis->NVRAM.offOpBuffer]; 777 char const *psz2 = psz2; 778 RTUNICP Cp; 779 RTStrGetCpEx(&psz2, &Cp); 780 *pu32 = Cp; 781 pThis->NVRAM.offOpBuffer += psz2 - psz1; 782 } 783 else if (pThis->NVRAM.offOpBuffer == pThis->NVRAM.VarOpBuf.cchName) 784 { 785 *pu32 = 0; 786 pThis->NVRAM.offOpBuffer++; 787 } 788 else 789 { 790 if (cb == 1) 791 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_NAME_UTF16 read.\n")); 792 else 793 LogRel(("EFI: Invalid EFI_VM_VARIABLE_OP_NAME_UTF16 read size (%d).\n", cb)); 794 *pu32 = UINT32_MAX; 795 } 796 break; 797 798 case EFI_VM_VARIABLE_OP_NAME_LENGTH_UTF16: 799 /* Lazy bird: ASSUME no surrogate pairs. */ 800 *pu32 = RTStrUniLen(pThis->NVRAM.VarOpBuf.szName); 801 break; 802 803 case EFI_VM_VARIABLE_OP_VALUE: 804 if (pThis->NVRAM.offOpBuffer < pThis->NVRAM.VarOpBuf.cbValue && cb == 1) 805 *pu32 = pThis->NVRAM.VarOpBuf.abValue[pThis->NVRAM.offOpBuffer++]; 806 else 807 { 808 if (cb == 1) 809 LogRel(("EFI: Out of bounds EFI_VM_VARIABLE_OP_VALUE read.\n")); 810 else 811 LogRel(("EFI: Invalid EFI_VM_VARIABLE_OP_VALUE read size (%d).\n", cb)); 812 *pu32 = UINT32_MAX; 813 } 814 break; 815 816 case EFI_VM_VARIABLE_OP_VALUE_LENGTH: 817 *pu32 = pThis->NVRAM.VarOpBuf.cbValue; 818 break; 819 820 default: 821 *pu32 = UINT32_MAX; 822 break; 823 } 824 return VINF_SUCCESS; 825 } 826 827 /** 828 * @implement_callback_method{FNDBGFHANDLERDEV} 829 */ 830 static DECLCALLBACK(void) efiInfoNvram(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) 831 { 832 PDEVEFI pThis = PDMINS_2_DATA(pDevIns, PDEVEFI); 833 PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED); 834 835 pHlp->pfnPrintf(pHlp, "NVRAM variables: %u\n", pThis->NVRAM.cVariables); 836 PEFIVAR pEfiVar; 837 RTListForEach(&pThis->NVRAM.VarList, pEfiVar, EFIVAR, ListNode) 838 { 839 pHlp->pfnPrintf(pHlp, "%RTuuid::'%s' = %.*Rhxs (attr=%#x)\n", 840 &pEfiVar->uuid, pEfiVar->szName, pEfiVar->cbValue, pEfiVar->abValue, pEfiVar->fAttributes); 841 } 842 843 PDMCritSectLeave(pDevIns->pCritSectRoR3); 844 } 845 323 846 324 847 … … 436 959 } 437 960 438 static DECLCALLBACK(int) efiSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)439 {440 int rc = VINF_SUCCESS;441 PEFIVAR pEfiVar = NULL;442 LogFlowFuncEnter();443 PDEVEFI pThis = PDMINS_2_DATA(pDevIns, PDEVEFI);444 rc = SSMR3PutStructEx(pSSM, &pThis->NVRAM, sizeof(NVRAMDESC), 0, g_aEfiNvramDescField, NULL);445 AssertRCReturn(rc, rc);446 rc = SSMR3PutStructEx(pSSM, &pThis->NVRAM.OperationVarOp, sizeof(EFIVAR), 0, g_aEfiVariableDescFields, NULL);447 AssertRCReturn(rc, rc);448 int idxV = 0;449 RTListForEach(&pThis->NVRAM.NvramVariableList.List, pEfiVar, EFIVAR, List)450 {451 rc = SSMR3PutStructEx(pSSM, pEfiVar, sizeof(EFIVAR), 0, g_aEfiVariableDescFields, NULL);452 AssertRCReturn(rc, rc);453 idxV++;454 }455 Assert((pThis->NVRAM.cNvramVariables == idxV));456 Log2(("idxV: %d\n", idxV));457 LogFlowFuncLeaveRC(rc);458 return rc;459 }460 461 static DECLCALLBACK(int) efiLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)462 {463 int rc = VINF_SUCCESS;464 NOREF(uPass);465 LogFlowFunc(("ENTER: uVersion:%d, uPass:%d\n", uVersion, uPass));466 PDEVEFI pThis = PDMINS_2_DATA(pDevIns, PDEVEFI);467 if (uPass != SSM_PASS_FINAL)468 return rc;469 /* we should clean up the loaded values */470 nvramFlushDeviceVariableList(pThis);471 if (uVersion == 1)472 {473 rc = SSMR3GetStructEx(pSSM, &pThis->NVRAM, sizeof(NVRAMDESC), 0, g_aEfiNvramDescField, NULL);474 AssertRCReturn(rc, rc);475 rc = SSMR3GetStructEx(pSSM, &pThis->NVRAM.OperationVarOp, sizeof(EFIVAR), 0, g_aEfiVariableDescFields, NULL);476 AssertRCReturn(rc, rc);477 int idxVariable = 0;478 Assert(RTListIsEmpty(&pThis->NVRAM.NvramVariableList.List));479 RTListInit(&pThis->NVRAM.NvramVariableList.List);480 for (idxVariable = 0; idxVariable < pThis->NVRAM.cNvramVariables; ++idxVariable)481 {482 PEFIVAR pEfiVar = (PEFIVAR)RTMemAllocZ(sizeof(EFIVAR));483 AssertPtrReturn(pEfiVar, VERR_NO_MEMORY);484 485 rc = SSMR3GetStructEx(pSSM, pEfiVar, sizeof(EFIVAR), 0, g_aEfiVariableDescFields, NULL);486 AssertRCReturn(rc, rc);487 488 RTListInit(&pEfiVar->List);489 RTListAppend(&pThis->NVRAM.NvramVariableList.List, &pEfiVar->List);490 491 if (pThis->NVRAM.idxCurrentVar == pEfiVar->idxVariable)492 pThis->NVRAM.pCurrentVarOp = pEfiVar;493 }494 }495 LogFlowFuncLeaveRC(rc);496 return rc;497 }498 499 #if 0500 static DECLCALLBACK(int) efiLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)501 {502 int rc = VINF_SUCCESS;503 PDEVEFI pThis = PDMINS_2_DATA(pDevIns, PDEVEFI);504 LogFlowFuncEnter();505 if (RTListIsEmpty(&pThis->NVRAM.NvramVariableList.List))506 nvramLoad(pThis);507 LogFlowFuncLeaveRC(rc);508 return rc;509 }510 #endif511 512 961 /** 513 962 * Port I/O Handler for IN operations. … … 555 1004 return VINF_IOM_R3_IOPORT_READ; 556 1005 #endif 1006 557 1007 case EFI_VARIABLE_OP: 558 switch (pThis->NVRAM.enmOp) 559 { 560 case EFI_VM_VARIABLE_OP_START: 561 /* @todo: nop ? */ 562 *pu32 = pThis->NVRAM.u32Status; 563 break; 564 case EFI_VM_VARIABLE_OP_END: 565 break; 566 case EFI_VM_VARIABLE_OP_INDEX: 567 break; 568 case EFI_VM_VARIABLE_OP_GUID: 569 *pu32 = pThis->NVRAM.OperationVarOp.uuid.au8[pThis->NVRAM.idxOpBuffer]; 570 pThis->NVRAM.idxOpBuffer++; 571 break; 572 case EFI_VM_VARIABLE_OP_ATTRIBUTE: 573 *pu32 = pThis->NVRAM.OperationVarOp.u32Attribute; 574 break; 575 case EFI_VM_VARIABLE_OP_NAME: 576 *pu32 = pThis->NVRAM.OperationVarOp.szVariableName[pThis->NVRAM.idxOpBuffer]; 577 pThis->NVRAM.idxOpBuffer++; 578 break; 579 case EFI_VM_VARIABLE_OP_NAME_LENGTH: 580 *pu32 = pThis->NVRAM.OperationVarOp.cbVariableName; 581 break; 582 case EFI_VM_VARIABLE_OP_VALUE: 583 *pu32 = pThis->NVRAM.OperationVarOp.au8Value[pThis->NVRAM.idxOpBuffer]; 584 pThis->NVRAM.idxOpBuffer++; 585 break; 586 case EFI_VM_VARIABLE_OP_VALUE_LENGTH: 587 *pu32 = pThis->NVRAM.OperationVarOp.cbValue; 588 break; 589 default: 590 break; 591 } 1008 return nvramReadVariableOp(pThis, pu32, cb); 1009 1010 case EFI_VARIABLE_PARAM: 1011 *pu32 = UINT32_MAX; 592 1012 return VINF_SUCCESS; 593 case EFI_VARIABLE_PARAM:594 {595 break;596 }597 return VINF_SUCCESS;598 1013 } 599 1014 … … 616 1031 { 617 1032 PDEVEFI pThis = PDMINS_2_DATA(pDevIns, PDEVEFI); 1033 int rc = VINF_SUCCESS; 618 1034 Log4(("efi: out %x %x %d\n", Port, u32, cb)); 619 1035 … … 621 1037 { 622 1038 case EFI_INFO_PORT: 1039 Log2(("EFI_INFO_PORT: iInfoSelector=%#x\n", u32)); 623 1040 pThis->iInfoSelector = u32; 624 1041 pThis->offInfo = -1; 625 1042 break; 1043 626 1044 case EFI_DEBUG_PORT: 627 1045 { … … 648 1066 649 1067 PRTSTREAM pStrm; 650 int rc = RTStrmOpen("./DevEFI.VBoxDbg", "a", &pStrm);651 if (RT_SUCCESS(rc ))1068 int rc2 = RTStrmOpen("./DevEFI.VBoxDbg", "a", &pStrm); 1069 if (RT_SUCCESS(rc2)) 652 1070 { 653 1071 RTStrmPutStr(pStrm, pszVBoxDbg); … … 725 1143 break; 726 1144 } 1145 727 1146 case EFI_VARIABLE_OP: 728 1147 { 729 1148 /* clear buffer index */ 730 Assert(u32 < EFI_VM_VARIABLE_OP_MAX); 731 if (u32 >= EFI_VM_VARIABLE_OP_MAX) 732 { 733 u32 = EFI_VARIABLE_OP_STATUS_ERROR; 734 break; 735 } 736 pThis->NVRAM.idxOpBuffer = 0; 1149 if (u32 >= (uint32_t)EFI_VM_VARIABLE_OP_MAX) 1150 { 1151 Log(("EFI: Invalid variable op %#x\n", u32)); 1152 u32 = EFI_VM_VARIABLE_OP_ERROR; 1153 } 1154 pThis->NVRAM.offOpBuffer = 0; 737 1155 pThis->NVRAM.enmOp = (EFIVAROP)u32; 1156 Log2(("EFI_VARIABLE_OP: enmOp=%#x (%d)\n", u32)); 1157 break; 738 1158 } 739 break; 1159 740 1160 case EFI_VARIABLE_PARAM: 741 { 742 switch (pThis->NVRAM.enmOp) 743 { 744 case EFI_VM_VARIABLE_OP_START: 745 { 746 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_BSY; 747 switch (u32) 748 { 749 case EFI_VARIABLE_OP_QUERY: 750 { 751 LogRel(("EFI: variable lookup %RTuuid, %s\n", 752 &pThis->NVRAM.OperationVarOp.uuid, 753 pThis->NVRAM.OperationVarOp.szVariableName)); 754 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_BSY; 755 PEFIVAR pEfiVar = NULL; 756 memset(pThis->NVRAM.OperationVarOp.au8Value, 0, EFI_VARIABLE_NAME_MAX); 757 int nvramRc = nvramLookupVariableByUuidAndName( 758 pThis, 759 pThis->NVRAM.OperationVarOp.szVariableName, 760 &pThis->NVRAM.OperationVarOp.uuid, 761 &pEfiVar); 762 if (RT_SUCCESS(nvramRc)) 763 { 764 pThis->NVRAM.OperationVarOp.u32Attribute = pEfiVar->u32Attribute; 765 pThis->NVRAM.OperationVarOp.cbVariableName = pEfiVar->cbVariableName; 766 pThis->NVRAM.OperationVarOp.cbValue = pEfiVar->cbValue; 767 memcpy(pThis->NVRAM.OperationVarOp.au8Value, 768 pEfiVar->au8Value, pEfiVar->cbValue); 769 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK; 770 pThis->NVRAM.pCurrentVarOp = pEfiVar; 771 pThis->NVRAM.idxCurrentVar = pEfiVar->idxVariable; 772 LogFlowFunc(("OperationVar: au8Value:%.*Rhxs\n", 773 pThis->NVRAM.OperationVarOp.cbValue, 774 pThis->NVRAM.OperationVarOp.au8Value)); 775 } 776 else 777 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_NOT_FOUND; 778 } 779 break; 780 case EFI_VARIABLE_OP_ADD: 781 { 782 LogRel(("EFI: variable add %RTuuid, %s\n", &pThis->NVRAM.OperationVarOp.uuid, pThis->NVRAM.OperationVarOp.szVariableName)); 783 PEFIVAR pEfiVar = NULL; 784 LogFlowFunc(("OperationVar: au8Value:%.*Rhxs\n", 785 pThis->NVRAM.OperationVarOp.cbValue, 786 pThis->NVRAM.OperationVarOp.au8Value)); 787 int nvramRc = nvramLookupVariableByUuidAndName( 788 pThis, 789 pThis->NVRAM.OperationVarOp.szVariableName, 790 &pThis->NVRAM.OperationVarOp.uuid, 791 &pEfiVar); 792 if (RT_SUCCESS(nvramRc)) 793 { 794 /* delete or update ? */ 795 /* @todo: check whether pEfiVar is WP */ 796 LogFlowFunc(("pEfiVar: au8Value:%.*Rhxs\n", 797 pEfiVar->cbValue, 798 pEfiVar->au8Value)); 799 if (pThis->NVRAM.OperationVarOp.cbValue == 0) 800 { 801 /* delete */ 802 RTListNodeRemove(&pEfiVar->List); 803 RTMemFree(pEfiVar); 804 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK; 805 pThis->NVRAM.cNvramVariables--; 806 } 807 else 808 { 809 /* update */ 810 pEfiVar->cbValue = pThis->NVRAM.OperationVarOp.cbValue; 811 memcpy(pEfiVar->au8Value, pThis->NVRAM.OperationVarOp.au8Value, pEfiVar->cbValue); 812 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK; 813 } 814 } 815 else 816 { 817 if (pThis->NVRAM.OperationVarOp.cbValue != 0) 818 { 819 pEfiVar = (PEFIVAR)RTMemAllocZ(sizeof(EFIVAR)); 820 if (!pEfiVar) 821 { 822 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_ERROR; 823 break; 824 } 825 } 826 else 827 { 828 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK; 829 break; 830 } 831 832 memcpy(pEfiVar, &pThis->NVRAM.OperationVarOp, sizeof(EFIVAR)); 833 RTListInit(&pEfiVar->List); 834 RTListAppend(&pThis->NVRAM.NvramVariableList.List, &pEfiVar->List); 835 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK; 836 pThis->NVRAM.cNvramVariables++; 837 pEfiVar->idxVariable = pThis->NVRAM.iNvramLastIndex; 838 pThis->NVRAM.iNvramLastIndex++; 839 } 840 } 841 LogFunc(("cNvramVariables:%d, iNvramLastIndex:%d\n", pThis->NVRAM.cNvramVariables, pThis->NVRAM.iNvramLastIndex)); 842 break; 843 case EFI_VARIABLE_OP_QUERY_NEXT: 844 { 845 PEFIVAR pEfiVar = RTListNodeGetNext(&pThis->NVRAM.pCurrentVarOp->List, EFIVAR, List); 846 if (pEfiVar) 847 { 848 memcpy(&pThis->NVRAM.OperationVarOp, pEfiVar, sizeof(EFIVAR)); 849 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_OK; 850 } 851 else 852 pThis->NVRAM.u32Status = EFI_VARIABLE_OP_STATUS_NOT_FOUND; 853 } 854 break; 855 default: 856 /* @todo: return error */ 857 break; 858 } 859 } 860 case EFI_VM_VARIABLE_OP_END: 861 break; 862 case EFI_VM_VARIABLE_OP_INDEX: 863 break; 864 case EFI_VM_VARIABLE_OP_GUID: 865 pThis->NVRAM.OperationVarOp.uuid.au8[pThis->NVRAM.idxOpBuffer] = (uint8_t)u32; 866 pThis->NVRAM.idxOpBuffer++; 867 break; 868 case EFI_VM_VARIABLE_OP_ATTRIBUTE: 869 pThis->NVRAM.OperationVarOp.u32Attribute = u32; 870 break; 871 case EFI_VM_VARIABLE_OP_NAME: 872 pThis->NVRAM.OperationVarOp.szVariableName[pThis->NVRAM.idxOpBuffer] = (uint8_t)u32; 873 pThis->NVRAM.idxOpBuffer++; 874 break; 875 case EFI_VM_VARIABLE_OP_NAME_LENGTH: 876 pThis->NVRAM.OperationVarOp.cbVariableName = u32; 877 memset(pThis->NVRAM.OperationVarOp.szVariableName, 0, EFI_VARIABLE_NAME_MAX); 878 break; 879 case EFI_VM_VARIABLE_OP_VALUE: 880 pThis->NVRAM.OperationVarOp.au8Value[pThis->NVRAM.idxOpBuffer] = (uint8_t)u32; 881 pThis->NVRAM.idxOpBuffer++; 882 break; 883 case EFI_VM_VARIABLE_OP_VALUE_LENGTH: 884 pThis->NVRAM.OperationVarOp.cbValue = u32; 885 memset(pThis->NVRAM.OperationVarOp.au8Value, 0, EFI_VARIABLE_VALUE_MAX); 886 break; 887 default: 888 break; 889 } 890 } 891 break; 1161 rc = nvramWriteVariableParam(pThis, u32); 1162 break; 892 1163 893 1164 default: … … 895 1166 break; 896 1167 } 1168 return rc; 1169 } 1170 1171 static DECLCALLBACK(int) efiSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 1172 { 1173 PDEVEFI pThis = PDMINS_2_DATA(pDevIns, PDEVEFI); 1174 LogFlow(("efiSaveExec:\n")); 1175 1176 /* 1177 * Set variables only used when saving state. 1178 */ 1179 uint32_t idUniqueSavedState = 0; 1180 PEFIVAR pEfiVar; 1181 RTListForEach(&pThis->NVRAM.VarList, pEfiVar, EFIVAR, ListNode) 1182 { 1183 pEfiVar->idUniqueSavedState = idUniqueSavedState++; 1184 } 1185 Assert(idUniqueSavedState == pThis->NVRAM.cVariables); 1186 1187 pThis->NVRAM.idUniqueCurVar = pThis->NVRAM.pCurVar 1188 ? pThis->NVRAM.pCurVar->idUniqueSavedState 1189 : UINT32_MAX; 1190 1191 /* 1192 * Save the NVRAM state. 1193 */ 1194 SSMR3PutStructEx(pSSM, &pThis->NVRAM, sizeof(NVRAMDESC), 0, g_aEfiNvramDescField, NULL); 1195 SSMR3PutStructEx(pSSM, &pThis->NVRAM.VarOpBuf, sizeof(EFIVAR), 0, g_aEfiVariableDescFields, NULL); 1196 1197 /* 1198 * Save the list variables (we saved the length above). 1199 */ 1200 RTListForEach(&pThis->NVRAM.VarList, pEfiVar, EFIVAR, ListNode) 1201 { 1202 SSMR3PutStructEx(pSSM, pEfiVar, sizeof(EFIVAR), 0, g_aEfiVariableDescFields, NULL); 1203 } 1204 1205 return VINF_SUCCESS; /* SSM knows */ 1206 } 1207 1208 static DECLCALLBACK(int) efiLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 1209 { 1210 PDEVEFI pThis = PDMINS_2_DATA(pDevIns, PDEVEFI); 1211 LogFlow(("efiLoadExec: uVersion=%d uPass=%d\n", uVersion, uPass)); 1212 1213 /* 1214 * Validate input. 1215 */ 1216 if (uPass != SSM_PASS_FINAL) 1217 return VERR_SSM_UNEXPECTED_PASS; 1218 if ( uVersion != EFI_SSM_VERSION 1219 && uVersion != EFI_SSM_VERSION_4_2 1220 ) 1221 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 1222 1223 /* 1224 * Kill the current variables before loading anything. 1225 */ 1226 nvramFlushDeviceVariableList(pThis); 1227 1228 /* 1229 * Load the NVRAM state. 1230 */ 1231 int rc = SSMR3GetStructEx(pSSM, &pThis->NVRAM, sizeof(NVRAMDESC), 0, g_aEfiNvramDescField, NULL); 1232 AssertRCReturn(rc, rc); 1233 pThis->NVRAM.pCurVar = NULL; 1234 1235 rc = SSMR3GetStructEx(pSSM, &pThis->NVRAM.VarOpBuf, sizeof(EFIVAR), 0, g_aEfiVariableDescFields, NULL); 1236 AssertRCReturn(rc, rc); 1237 1238 /* 1239 * Load variables. 1240 */ 1241 pThis->NVRAM.pCurVar = NULL; 1242 Assert(RTListIsEmpty(&pThis->NVRAM.VarList)); 1243 RTListInit(&pThis->NVRAM.VarList); 1244 for (uint32_t i = 0; i < pThis->NVRAM.cVariables; i++) 1245 { 1246 PEFIVAR pEfiVar = (PEFIVAR)RTMemAllocZ(sizeof(EFIVAR)); 1247 AssertPtrReturn(pEfiVar, VERR_NO_MEMORY); 1248 1249 rc = SSMR3GetStructEx(pSSM, pEfiVar, sizeof(EFIVAR), 0, g_aEfiVariableDescFields, NULL); 1250 if (RT_SUCCESS(rc)) 1251 { 1252 if ( pEfiVar->cbValue > sizeof(pEfiVar->abValue) 1253 || pEfiVar->cbValue == 0) 1254 { 1255 rc = VERR_SSM_DATA_UNIT_FORMAT_CHANGED; 1256 LogRel(("EFI: Loaded invalid variable value length %#x\n", pEfiVar->cbValue)); 1257 } 1258 size_t cchVarName = RTStrNLen(pEfiVar->szName, sizeof(pEfiVar->szName)); 1259 if (cchVarName >= sizeof(pEfiVar->szName)) 1260 { 1261 rc = VERR_SSM_DATA_UNIT_FORMAT_CHANGED; 1262 LogRel(("EFI: Loaded variable name is unterminated.\n")); 1263 } 1264 if (pEfiVar->cchName > cchVarName) /* No check for 0 here, busted load code in 4.2, so now storing 0 here. */ 1265 { 1266 rc = VERR_SSM_DATA_UNIT_FORMAT_CHANGED; 1267 LogRel(("EFI: Loaded invalid variable name length %#x (cchVarName=%#x)\n", pEfiVar->cchName, cchVarName)); 1268 } 1269 if (RT_SUCCESS(rc)) 1270 pEfiVar->cchName = cchVarName; 1271 } 1272 AssertRCReturnStmt(rc, RTMemFree(pEfiVar), rc); 1273 1274 /* Add it, updating the current variable pointer while we're here. */ 1275 RTListAppend(&pThis->NVRAM.VarList, &pEfiVar->ListNode); 1276 if (pThis->NVRAM.idUniqueCurVar == pEfiVar->idUniqueSavedState) 1277 pThis->NVRAM.pCurVar = pEfiVar; 1278 } 1279 897 1280 return VINF_SUCCESS; 1281 } 1282 1283 1284 /** 1285 * @copydoc(PDMIBASE::pfnQueryInterface) 1286 */ 1287 static DECLCALLBACK(void *) devEfiQueryInterface(PPDMIBASE pInterface, const char *pszIID) 1288 { 1289 LogFlowFunc(("ENTER: pIBase: %p, pszIID:%p\n", __FUNCTION__, pInterface, pszIID)); 1290 PDEVEFI pThis = RT_FROM_MEMBER(pInterface, DEVEFI, Lun0.IBase); 1291 1292 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase); 1293 return NULL; 1294 } 1295 1296 1297 /** 1298 * Write to CMOS memory. 1299 * This is used by the init complete code. 1300 */ 1301 static void cmosWrite(PPDMDEVINS pDevIns, unsigned off, uint32_t u32Val) 1302 { 1303 Assert(off < 128); 1304 Assert(u32Val < 256); 1305 1306 int rc = PDMDevHlpCMOSWrite(pDevIns, off, u32Val); 1307 AssertRC(rc); 898 1308 } 899 1309 … … 999 1409 { 1000 1410 PDEVEFI pThis = PDMINS_2_DATA(pDevIns, PDEVEFI); 1411 1001 1412 nvramStore(pThis); 1002 1413 nvramFlushDeviceVariableList(pThis); 1003 1414 1004 /*1005 * Free MM heap pointers.1006 */1007 1415 if (pThis->pu8EfiRom) 1008 1416 { … … 1011 1419 } 1012 1420 1421 /* 1422 * Free MM heap pointers (waste of time, but whatever). 1423 */ 1013 1424 if (pThis->pszEfiRomFile) 1014 1425 { … … 1232 1643 1233 1644 /** 1234 * @copydoc(PDMIBASE::pfnQueryInterface)1235 */1236 static DECLCALLBACK(void *) devEfiQueryInterface(PPDMIBASE pInterface, const char *pszIID)1237 {1238 LogFlowFunc(("ENTER: pIBase: %p, pszIID:%p\n", __FUNCTION__, pInterface, pszIID));1239 PDEVEFI pThis = RT_FROM_MEMBER(pInterface, DEVEFI, Lun0.IBase);1240 1241 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);1242 return NULL;1243 }1244 1245 /**1246 1645 * @interface_method_impl{PDMDEVREG,pfnConstruct} 1247 1646 */ … … 1253 1652 Assert(iInstance == 0); 1254 1653 1654 /* 1655 * Initalize the basic variables so that the destructor always works. 1656 */ 1255 1657 pThis->pDevIns = pDevIns; 1658 RTListInit(&pThis->NVRAM.VarList); 1659 pThis->Lun0.IBase.pfnQueryInterface = devEfiQueryInterface; 1660 1256 1661 1257 1662 /* … … 1332 1737 uuid.Gen.u16TimeHiAndVersion = RT_H2BE_U16(uuid.Gen.u16TimeHiAndVersion); 1333 1738 memcpy(&pThis->aUuid, &uuid, sizeof pThis->aUuid); 1334 RTListInit((PRTLISTNODE)&pThis->NVRAM.NvramVariableList.List);1335 1336 1739 1337 1740 /* … … 1372 1775 * NVRAM processing. 1373 1776 */ 1374 pThis->Lun0.IBase.pfnQueryInterface = devEfiQueryInterface;1375 1376 #if 01377 rc = PDMDevHlpSSMRegisterEx(pDevIns, EFI_SSM_VERSION, sizeof(*pThis), NULL /*pszBefore*/,1378 NULL /*pfnLivePrep*/, NULL /*pfnLiveExec*/, NULL /*pfnLiveDone*/,1379 NULL /*pfnSavePrep*/, efiSaveExec, NULL /*pfnSaveDone*/,1380 NULL /*pfnLoadPrep*/, efiLoadExec, efiLoadDone);1381 #else1382 1777 rc = PDMDevHlpSSMRegister(pDevIns, EFI_SSM_VERSION, sizeof(*pThis), efiSaveExec, efiLoadExec); 1383 #endif1384 1778 AssertRCReturn(rc, rc); 1385 1779 … … 1388 1782 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("Can't attach Nvram Storage driver")); 1389 1783 1390 pThis->Lun0.pNvramDown = (PPDMINVRAM)pThis->Lun0.pDrvBase->pfnQueryInterface(pThis->Lun0.pDrvBase, PDMINVRAM_IID); 1391 AssertPtrReturn(pThis->Lun0.pNvramDown, VERR_PDM_MISSING_INTERFACE_BELOW); 1392 1393 nvramLoad(pThis); 1784 pThis->Lun0.pNvramDrv = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pDrvBase, PDMINVRAMCONNECTOR); 1785 AssertPtrReturn(pThis->Lun0.pNvramDrv, VERR_PDM_MISSING_INTERFACE_BELOW); 1786 1787 rc = nvramLoad(pThis); 1788 AssertRCReturn(rc, rc); 1394 1789 1395 1790 /* 1396 1791 * Get boot args. 1397 1792 */ 1398 rc = CFGMR3QueryString(pCfg, "BootArgs", 1399 pThis->szBootArgs, sizeof pThis->szBootArgs); 1400 if (rc == VERR_CFGM_VALUE_NOT_FOUND) 1401 { 1402 strcpy(pThis->szBootArgs, ""); 1403 rc = VINF_SUCCESS; 1404 } 1793 rc = CFGMR3QueryStringDef(pCfg, "BootArgs", pThis->szBootArgs, sizeof(pThis->szBootArgs), ""); 1405 1794 if (RT_FAILURE(rc)) 1406 1795 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, … … 1412 1801 * Get device props. 1413 1802 */ 1414 char* pszDeviceProps; 1415 rc = CFGMR3QueryStringAlloc(pCfg, "DeviceProps", &pszDeviceProps); 1416 if (rc == VERR_CFGM_VALUE_NOT_FOUND) 1417 { 1418 pszDeviceProps = NULL; 1419 rc = VINF_SUCCESS; 1420 } 1803 char *pszDeviceProps; 1804 rc = CFGMR3QueryStringAllocDef(pCfg, "DeviceProps", &pszDeviceProps, NULL); 1421 1805 if (RT_FAILURE(rc)) 1422 1806 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, … … 1440 1824 * CPU frequencies 1441 1825 */ 1442 /// @todo :we need to have VMM API to access TSC increase speed, for now provide reasonable default1826 /// @todo we need to have VMM API to access TSC increase speed, for now provide reasonable default 1443 1827 pThis->u64TscFrequency = RTMpGetMaxFrequency(0) * 1000 * 1000;// TMCpuTicksPerSecond(PDMDevHlpGetVM(pDevIns)); 1444 1828 if (pThis->u64TscFrequency == 0) … … 1451 1835 * GOP graphics 1452 1836 */ 1453 rc = CFGMR3QueryU32(pCfg, "GopMode", &pThis->u32GopMode); 1454 AssertRC(rc); 1837 rc = CFGMR3QueryU32Def(pCfg, "GopMode", &pThis->u32GopMode, 2 /* 1024x768 */); 1838 if (RT_FAILURE(rc)) 1839 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 1840 N_("Configuration error: Querying \"GopMode\" as a 32-bit int failed")); 1455 1841 if (pThis->u32GopMode == UINT32_MAX) 1456 {1457 1842 pThis->u32GopMode = 2; /* 1024x768 */ 1458 } 1459 1460 /* 1461 * Uga graphics 1843 1844 /* 1845 * Uga graphics. 1462 1846 */ 1463 1847 rc = CFGMR3QueryU32Def(pCfg, "UgaHorizontalResolution", &pThis->cxUgaResolution, 0); AssertRC(rc); … … 1483 1867 1484 1868 /* 1485 * Register our communicationports.1869 * Register our I/O ports. 1486 1870 */ 1487 1871 rc = PDMDevHlpIOPortRegister(pDevIns, EFI_PORT_BASE, EFI_PORT_COUNT, NULL, … … 1492 1876 1493 1877 /* 1494 * Plant DMI and MPS tables 1878 * Plant DMI and MPS tables. 1495 1879 */ 1496 1880 /** @todo XXX I wonder if we really need these tables as there is no SMBIOS header... */ … … 1508 1892 1509 1893 /* 1894 * Register info handlers. 1895 */ 1896 rc = PDMDevHlpDBGFInfoRegister(pDevIns, "nvram", "Dumps the NVRAM variables.\n", efiInfoNvram); 1897 AssertRCReturn(rc, rc); 1898 1899 /* 1510 1900 * Call reset to set things up. 1511 1901 */ … … 1529 1919 "", 1530 1920 /* pszDescription */ 1531 "Extensible Firmware Interface Device", 1921 "Extensible Firmware Interface Device. " 1922 "LUN#0 - NVRAM port", 1532 1923 /* fFlags */ 1533 1924 PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64, -
trunk/src/VBox/Devices/EFI/Firmware2/VBoxPkg/Include/DevEFI.h
r44575 r44591 120 120 #define EFI_VARIABLE_OP_STATUS_BSY 0xcafe0010 121 121 122 #define EFI_VARIABLE_NAME_MAX 1024 123 #define EFI_VARIABLE_VALUE_MAX 1024 122 /** The max number of variables allowed. */ 123 #define EFI_VARIABLE_MAX 128 124 /** The max variable name length (in bytes, including the zero terminator). */ 125 #define EFI_VARIABLE_NAME_MAX 1024 126 /** The max value length (in bytes). */ 127 #define EFI_VARIABLE_VALUE_MAX 1024 124 128 125 typedef enum { 129 typedef enum 130 { 126 131 EFI_VM_VARIABLE_OP_START = 0, 127 EFI_VM_VARIABLE_OP_END, 128 EFI_VM_VARIABLE_OP_ INDEX,132 EFI_VM_VARIABLE_OP_END, /**< @todo r=bird: What's the point of this one? */ 133 EFI_VM_VARIABLE_OP_RESERVED_USED_TO_BE_INDEX, 129 134 EFI_VM_VARIABLE_OP_GUID, 130 135 EFI_VM_VARIABLE_OP_ATTRIBUTE, … … 133 138 EFI_VM_VARIABLE_OP_VALUE, 134 139 EFI_VM_VARIABLE_OP_VALUE_LENGTH, 135 EFI_VM_VARIABLE_OP_MAX 140 EFI_VM_VARIABLE_OP_ERROR, 141 EFI_VM_VARIABLE_OP_NAME_UTF16, 142 EFI_VM_VARIABLE_OP_NAME_LENGTH_UTF16, 143 EFI_VM_VARIABLE_OP_MAX, 144 EFI_VM_VARIABLE_OP_32BIT_HACK = 0x7fffffff 136 145 } EFIVAROP; 137 146 -
trunk/src/VBox/Devices/EFI/Firmware2/VBoxPkg/VBoxVariable/InitVariable.c
r43212 r44591 45 45 46 46 47 static inlineUINT32 VBoxReadNVRAM(UINT8 *pu8Buffer, UINT32 cbBuffer)47 static UINT32 VBoxReadNVRAM(UINT8 *pu8Buffer, UINT32 cbBuffer) 48 48 { 49 49 UINT32 idxBuffer = 0; … … 59 59 } 60 60 61 static inline UINT32 VBoxWriteNVRAMByteArrayParam(const UINT8 *pu8Param, UINT32 cbParam)61 static UINT32 VBoxWriteNVRAMByteArrayParam(const UINT8 *pbParam, UINT32 cbParam) 62 62 { 63 63 UINT32 idxParam = 0; 64 64 for (idxParam = 0; idxParam < cbParam; ++idxParam) 65 ASMOutU8(EFI_VARIABLE_PARAM, p u8Param[idxParam]);65 ASMOutU8(EFI_VARIABLE_PARAM, pbParam[idxParam]); 66 66 return idxParam; 67 67 } 68 68 69 static inline UINT32 VBoxWriteNVRAMStringParam(const CHAR16 *ps16VariableName) 70 { 71 CHAR8 szVarName[512]; 72 UINT32 cbVarName = StrLen(ps16VariableName); 73 LogFlowFuncEnter(); 74 ASSERT (cbVarName < 512); 75 if (cbVarName > 512) 76 { 77 LogFlowFuncMarkVar(cbVarName, "%d"); 78 LogFlowFuncLeave(); 79 return 0; 80 } 81 UnicodeStrToAsciiStr(ps16VariableName, szVarName); 82 83 VBoxWriteNVRAMU32Param(EFI_VM_VARIABLE_OP_NAME_LENGTH, cbVarName); 84 85 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME); 86 cbVarName = VBoxWriteNVRAMByteArrayParam((UINT8 *)szVarName, cbVarName); 87 88 LogFlowFuncMarkVar(cbVarName, "%d"); 89 LogFlowFuncLeave(); 90 return cbVarName; 69 static void VBoxWriteNVRAMNameParam(const CHAR16 *pwszName) 70 { 71 UINT32 i; 72 UINT32 cwcName = StrLen(pwszName); 73 74 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME_UTF16); 75 for (i = 0; i <= cwcName; i++) 76 ASMOutU16(EFI_VARIABLE_PARAM, pwszName[i]); 91 77 } 92 78 … … 97 83 } 98 84 99 static inlineUINT32 VBoxWriteNVRAMDoOp(UINT32 u32Operation)85 static UINT32 VBoxWriteNVRAMDoOp(UINT32 u32Operation) 100 86 { 101 87 UINT32 u32Rc; … … 104 90 VBoxWriteNVRAMU32Param(EFI_VM_VARIABLE_OP_START, u32Operation); 105 91 106 while ((u32Rc = ASMInU32(EFI_VARIABLE_OP)) == EFI_VARIABLE_OP_STATUS_BSY)92 while ((u32Rc = ASMInU32(EFI_VARIABLE_OP)) == EFI_VARIABLE_OP_STATUS_BSY) 107 93 { 108 94 #if 0 109 95 MicroSecondDelay (400); 110 96 #endif 111 /* @todo: sleep here */97 /* @todo: sleep here. bird: won't ever happen, so don't bother. */ 112 98 } 113 99 LogFlowFuncMarkVar(u32Rc, "%x"); … … 154 140 ); 155 141 #else 156 UINT32 VarLen;157 UINT32 u32Rc = 0;142 EFI_STATUS rc; 143 UINT32 u32Rc; 158 144 159 145 LogFlowFuncEnter(); 160 /* set uuid */ 146 147 /* 148 * Tell DevEFI to look for the specified variable. 149 */ 161 150 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_GUID); 162 151 VBoxWriteNVRAMGuidParam(VendorGuid); 163 164 /* set name */ 165 VBoxWriteNVRAMStringParam(VariableName); 166 167 /* start operation */ 152 VBoxWriteNVRAMNameParam(VariableName); 153 168 154 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY); 169 170 ASSERT (u32Rc != EFI_VARIABLE_OP_STATUS_ERROR); 171 switch(u32Rc) 155 if (u32Rc == EFI_VARIABLE_OP_STATUS_OK) 172 156 { 173 case EFI_VARIABLE_OP_STATUS_ERROR: /* for release build */ 174 case EFI_VARIABLE_OP_STATUS_NOT_FOUND: 175 LogFlowFuncLeaveRC(EFI_NOT_FOUND); 176 return EFI_NOT_FOUND; 177 case EFI_VARIABLE_OP_STATUS_OK: 157 /* 158 * Check if we got enought space for the value. 159 */ 160 UINT32 VarLen; 161 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_VALUE_LENGTH); 162 VarLen = ASMInU32(EFI_VARIABLE_OP); 163 LogFlowFuncMarkVar(*DataSize, "%d"); 164 LogFlowFuncMarkVar(VarLen, "%d"); 165 if ( VarLen <= *DataSize 166 && Data) 178 167 { 179 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_VALUE_LENGTH); 180 VarLen = ASMInU32(EFI_VARIABLE_OP); 181 LogFlowFuncMarkVar(*DataSize, "%d"); 182 LogFlowFuncMarkVar(VarLen, "%d"); 183 if ( VarLen > *DataSize 184 || !Data) 185 { 186 *DataSize = VarLen; 187 /* @todo: should we end op ? */ 188 LogFlowFuncLeave(); 189 return EFI_BUFFER_TOO_SMALL; 190 } 168 /* 169 * We do, then read it and, if requrest, the attribute. 170 */ 171 *DataSize = VarLen; 191 172 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_VALUE); 192 *DataSize = VBoxReadNVRAM((UINT8 *)Data, VarLen); 173 VBoxReadNVRAM((UINT8 *)Data, VarLen); 174 193 175 if (Attributes) 194 176 { … … 197 179 LogFlowFuncMarkVar(Attributes, "%x"); 198 180 } 199 LogFlowFuncLeaveRC((EFI_SUCCESS)); 200 return EFI_SUCCESS; 181 182 rc = EFI_SUCCESS; 183 } 184 else 185 { 186 *DataSize = VarLen; 187 rc = EFI_BUFFER_TOO_SMALL; 201 188 } 202 189 } 203 #endif 204 return EFI_SUCCESS; 190 else 191 { 192 rc = EFI_NOT_FOUND; 193 } 194 195 LogFlowFuncLeaveRC(rc); 196 return rc; 197 #endif 205 198 } 206 199 … … 235 228 ); 236 229 #else 237 uint32_t u32Rc = 0; 238 EFI_STATUS rc = EFI_NOT_FOUND; 239 CHAR8 szVariableName[512]; 240 int cbVarName = 0; 241 230 uint32_t u32Rc; 231 EFI_STATUS rc; 242 232 LogFlowFuncEnter(); 243 233 244 SetMem(szVariableName, 512, 0); 245 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY_NEXT); 246 switch (u32Rc) 234 /* 235 * Tell DevEFI which the current variable is, then ask for the next one. 236 */ 237 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_GUID); 238 VBoxWriteNVRAMGuidParam(VendorGuid); 239 VBoxWriteNVRAMNameParam(VariableName); 240 241 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY); 242 if (u32Rc == EFI_VARIABLE_OP_STATUS_OK) 243 u32Rc = VBoxWriteNVRAMDoOp(EFI_VARIABLE_OP_QUERY_NEXT); 244 245 if (u32Rc == EFI_VARIABLE_OP_STATUS_OK) 247 246 { 248 case EFI_VARIABLE_OP_STATUS_OK: 247 /* 248 * Output buffer check. 249 */ 250 UINT32 cwcName; 251 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME_LENGTH_UTF16); 252 cwcName = ASMInU32(EFI_VARIABLE_OP); 253 if (cwcName * 2 < *VariableNameSize) /* ASSUMES byte size is specified */ 249 254 { 250 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME_LENGTH); 251 cbVarName = ASMInU32(EFI_VARIABLE_OP); 252 255 UINT32 i; 256 257 /* 258 * Read back the result. 259 */ 253 260 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_GUID); 254 261 VBoxReadNVRAM((UINT8 *)VendorGuid, sizeof(EFI_GUID)); 255 262 256 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME); 257 VBoxReadNVRAM((UINT8 *)szVariableName, cbVarName); 258 259 if (cbVarName < *VariableNameSize) 260 { 261 UnicodeSPrintAsciiFormat(VariableName, cbVarName, "%a", szVariableName); 262 LogFlowFuncMarkVar(*VariableNameSize, "%d"); 263 LogFlowFuncMarkVar(VariableName, "%s"); 264 LogFlowFuncMarkVar(VendorGuid, "%g"); 265 *VariableNameSize = cbVarName; 266 LogFlowFuncMarkVar(*VariableNameSize, "%d"); 267 rc = EFI_SUCCESS; 268 } 269 else 270 rc = EFI_BUFFER_TOO_SMALL; 263 ASMOutU32(EFI_VARIABLE_OP, EFI_VM_VARIABLE_OP_NAME_UTF16); 264 for (i = 0; i < cwcName; i++) 265 VariableName[i] = ASMInU16(EFI_VARIABLE_OP); 266 VariableName[i] = '\0'; 267 268 *VariableNameSize = cwcName * 2; 269 rc = EFI_SUCCESS; 271 270 } 272 case EFI_VARIABLE_OP_STATUS_ERROR: 273 case EFI_VARIABLE_OP_STATUS_NOT_FOUND: 274 case EFI_VARIABLE_OP_STATUS_NOT_WP: 275 rc = EFI_NOT_FOUND; 271 else 272 { 273 rc = EFI_BUFFER_TOO_SMALL; 274 *VariableNameSize = (cwcName + 1) * 2; 275 } 276 276 } 277 else 278 rc = EFI_NOT_FOUND; /* whatever */ 279 277 280 LogFlowFuncLeaveRC(rc); 278 281 return rc; … … 328 331 VBoxWriteNVRAMGuidParam(VendorGuid); 329 332 /* set name */ 330 VBoxWriteNVRAM StringParam(VariableName);333 VBoxWriteNVRAMNameParam(VariableName); 331 334 /* set attribute */ 332 335 VBoxWriteNVRAMU32Param(EFI_VM_VARIABLE_OP_ATTRIBUTE, Attributes); … … 340 343 /* process errors */ 341 344 LogFlowFuncLeave(); 342 switch (u32Rc)345 switch (u32Rc) 343 346 { 344 347 case EFI_VARIABLE_OP_STATUS_OK: -
trunk/src/VBox/Main/include/Nvram.h
r43133 r44591 31 31 Nvram(Console *console); 32 32 virtual ~Nvram(); 33 34 Console *getParent(void) { return mParent; } 35 33 36 static const PDMDRVREG DrvReg; 34 Console *getParent(void) { return mParent; }35 struct NVRAM *mpDrv;36 37 37 38 private: … … 40 41 static DECLCALLBACK(void) drvNvram_Destruct(PPDMDRVINS pDrvIns); 41 42 43 /** Pointer to the parent object. */ 42 44 Console * const mParent; 45 /** Pointer to the driver instance data. 46 * Can be NULL during init and termination. */ 47 struct NVRAM *mpDrv; 43 48 }; 44 49 -
trunk/src/VBox/Main/src-client/Nvram.cpp
r43256 r44591 5 5 6 6 /* 7 * Copyright (C) 2012 Oracle Corporation7 * Copyright (C) 2012-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 #include "Nvram.h" 22 22 #include "ConsoleImpl.h" 23 #include "Global.h" 23 24 24 25 #include <VBox/vmm/pdm.h> … … 45 46 typedef struct NVRAM *PNVRAM; 46 47 48 /** 49 * Intstance data associated with PDMDRVINS. 50 */ 47 51 struct NVRAM 48 52 { 49 Nvram *pNvram; 50 PDMINVRAM INvram; 51 int cLoadedVariables; 52 bool fPermanentSave; 53 /** Pointer to the associated class instance. */ 54 Nvram *pNvram; 55 /** The NVRAM connector interface we provide to DevEFI. */ 56 PDMINVRAMCONNECTOR INvramConnector; 57 /** The root of the 'Vars' child of the driver config (i.e. 58 * VBoxInternal/Devices/efi/0/LUN#0/Config/Vars/). 59 * This node has one child node per NVRAM variable. */ 60 PCFGMNODE pCfgVarRoot; 61 /** The variable node used in the privous drvNvram_VarQueryByIndex call. */ 62 PCFGMNODE pLastVarNode; 63 /** The index pLastVarNode corresponds to. */ 64 uint32_t idxLastVar; 65 /** Whether to permanently save the variables or not. */ 66 bool fPermanentSave; 53 67 }; 54 68 … … 57 71 * Constructor/destructor 58 72 */ 59 Nvram::Nvram(Console * console)60 : m pDrv(NULL),61 m Parent(console)73 Nvram::Nvram(Console *pConsole) 74 : mParent(pConsole), 75 mpDrv(NULL) 62 76 { 63 77 } … … 74 88 75 89 /** 76 * @interface_method_impl(PDMINVRAM,pfnStoreNvramValue) 77 */ 78 DECLCALLBACK(int) drvNvram_pfnStoreNvramValue(PPDMINVRAM pInterface, 79 int idxVariable, 80 RTUUID *pVendorUuid, 81 const char *pcszVariableName, 82 size_t cbVariableName, 83 uint8_t *pu8Value, 84 size_t cbValue) 85 { 86 int rc = VINF_SUCCESS; 87 char szExtraDataKey[256]; 88 char szExtraDataValue[1024]; 89 LogFlowFunc(("ENTER: pVendorUuid:%RTuuid, pcszVariableName:%s, cbVariableName:%d, pu8Value:%.*Rhxs, cbValue:%d\n", 90 pVendorUuid, 91 pcszVariableName, 92 cbVariableName, 93 cbValue, 94 pu8Value, 95 cbValue)); 96 PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvram); 97 if (!pThis->fPermanentSave) 98 { 99 LogFlowFuncLeaveRC(rc); 100 return rc; 101 } 102 103 bool fFlushVariable = (!pu8Value); 104 105 RT_ZERO(szExtraDataKey); 106 RT_ZERO(szExtraDataValue); 107 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableName", idxVariable); 108 if (!fFlushVariable) 109 RTStrPrintf(szExtraDataValue, 1024, "%s", pcszVariableName); 110 pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraDataKey).raw(), Bstr(szExtraDataValue).raw()); 111 112 RT_ZERO(szExtraDataKey); 113 RT_ZERO(szExtraDataValue); 114 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VendorGuid", idxVariable); 115 if (!fFlushVariable) 116 RTUuidToStr(pVendorUuid, szExtraDataValue, 1024); 117 pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraDataKey).raw(), Bstr(szExtraDataValue).raw()); 118 119 RT_ZERO(szExtraDataKey); 120 RT_ZERO(szExtraDataValue); 121 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableValueLength", idxVariable); 122 if (!fFlushVariable) 123 RTStrPrintf(szExtraDataValue, 1024, "%d", cbValue); 124 pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraDataKey).raw(), Bstr(szExtraDataValue).raw()); 125 126 RT_ZERO(szExtraDataKey); 127 RT_ZERO(szExtraDataValue); 128 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableValue", idxVariable); 129 size_t cbActualSize; 130 if (pu8Value) 131 rc = RTBase64Encode(pu8Value, cbValue, szExtraDataValue, 1024, &cbActualSize); 132 AssertRCReturn(rc, rc); 133 pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraDataKey).raw(), Bstr(szExtraDataValue).raw()); 134 90 * @interface_method_impl(PDMINVRAM,pfnVarStoreSeqEnd) 91 */ 92 DECLCALLBACK(int) drvNvram_VarStoreSeqEnd(PPDMINVRAMCONNECTOR pInterface, int rc) 93 { 94 NOREF(pInterface); 95 return rc; 96 } 97 98 /** 99 * Converts the binary to a CFGM overlay binary string. 100 * 101 * @returns Pointer to a heap buffer (hand it to RTMemFree when done). 102 * @param pvBuf The binary data to convert. 103 * @param cbBuf The number of bytes to convert. 104 */ 105 static char *drvNvram_binaryToCfgmString(void const *pvBuf, size_t cbBuf) 106 { 107 static char s_szPrefix[] = "bytes:"; 108 size_t cbStr = RTBase64EncodedLength(cbBuf) + sizeof(s_szPrefix); 109 char *pszStr = (char *)RTMemAlloc(cbStr); 110 if (pszStr) 111 { 112 memcpy(pszStr, s_szPrefix, sizeof(s_szPrefix) - 1); 113 int rc = RTBase64Encode(pvBuf, cbBuf, &pszStr[sizeof(s_szPrefix) - 1], cbBuf - sizeof(s_szPrefix) + 1, NULL); 114 if (RT_FAILURE(rc)) 115 { 116 RTMemFree(pszStr); 117 pszStr = NULL; 118 } 119 } 120 return pszStr; 121 } 122 123 /** 124 * @interface_method_impl(PDMINVRAM,pfnVarStoreSeqPut) 125 */ 126 DECLCALLBACK(int) drvNvram_VarStoreSeqPut(PPDMINVRAMCONNECTOR pInterface, int idxVariable, 127 PCRTUUID pVendorUuid, const char *pszName, size_t cchName, 128 uint32_t fAttributes, uint8_t const *pbValue, size_t cbValue) 129 { 130 PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvramConnector); 131 int rc = VINF_SUCCESS; 132 133 if (pThis->fPermanentSave && pThis->pNvram) 134 { 135 char szExtraName[256]; 136 size_t offValueNm = RTStrPrintf(szExtraName, sizeof(szExtraName) - 16, 137 "VBoxInternal/Devices/efi/0/LUN#0/Config/Vars/%4u/", idxVariable); 138 139 char szAttribs[32]; 140 RTStrPrintf(szAttribs, sizeof(szAttribs), "%#x", fAttributes); 141 142 char szUuid[RTUUID_STR_LENGTH]; 143 int rc2 = RTUuidToStr(pVendorUuid, szUuid, sizeof(szUuid)); AssertRC(rc2); 144 145 char *pszValue = drvNvram_binaryToCfgmString(pbValue, cbValue); 146 if (pszValue) 147 { 148 const char *apszTodo[] = 149 { 150 "Name", pszName, 151 "Uuid", szUuid, 152 "Attribs", szAttribs, 153 "Value", pszValue, 154 }; 155 for (unsigned i = 0; i < RT_ELEMENTS(apszTodo); i += 2) 156 { 157 Assert(strlen(apszTodo[i]) < 16); 158 strcpy(szExtraName + offValueNm, apszTodo[i]); 159 try 160 { 161 HRESULT hrc = pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraName).raw(), 162 Bstr(apszTodo[i + 1]).raw()); 163 if (FAILED(hrc)) 164 { 165 LogRel(("drvNvram_deleteVar: SetExtraData(%s,%s) returned %Rhrc\n", szExtraName, apszTodo[i + 1], hrc)); 166 rc = Global::vboxStatusCodeFromCOM(hrc); 167 } 168 } 169 catch (...) 170 { 171 LogRel(("drvNvram_deleteVar: SetExtraData(%s,%s) threw exception\n", szExtraName, apszTodo[i + 1])); 172 rc = VERR_UNEXPECTED_EXCEPTION; 173 } 174 } 175 } 176 else 177 rc = VERR_NO_MEMORY; 178 RTMemFree(pszValue); 179 } 180 181 NOREF(cchName); 135 182 LogFlowFuncLeaveRC(rc); 136 183 return rc; 137 184 } 138 185 139 140 /** 141 * @interface_method_impl(PDMINVRAM,pfnFlushNvramStorage) 142 */ 143 DECLCALLBACK(int) drvNvram_pfnFlushNvramStorage(PPDMINVRAM pInterface) 144 { 145 int rc = VINF_SUCCESS; 146 LogFlowFuncEnter(); 147 PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvram); 148 if (!pThis->fPermanentSave) 149 { 150 LogFlowFuncLeaveRC(rc); 151 return rc; 152 } 153 154 for (int idxVariable = 0; idxVariable < pThis->cLoadedVariables; ++idxVariable) 155 { 156 drvNvram_pfnStoreNvramValue(pInterface, idxVariable, NULL, NULL, 0, NULL, 0); 157 } 158 LogFlowFuncLeaveRC(rc); 186 /** 187 * Deletes a variable. 188 * 189 * @param pThis The NVRAM driver instance data. 190 * @param pszVarNodeNm The variable node name. 191 */ 192 static void drvNvram_deleteVar(PNVRAM pThis, const char *pszVarNodeNm) 193 { 194 char szExtraName[256]; 195 size_t offValue = RTStrPrintf(szExtraName, sizeof(szExtraName) - 16, 196 "VBoxInternal/Devices/efi/0/LUN#0/Config/Vars/%s/", pszVarNodeNm); 197 static const char *s_apszValueNames[] = { "Name", "Attribs", "Value" }; 198 for (unsigned i = 0; i < RT_ELEMENTS(s_apszValueNames); i++) 199 { 200 Assert(strlen(s_apszValueNames[i]) < 16); 201 strcpy(szExtraName + offValue, s_apszValueNames[i]); 202 try 203 { 204 HRESULT hrc = pThis->pNvram->getParent()->machine()->SetExtraData(Bstr(szExtraName).raw(), Bstr().raw()); 205 if (FAILED(hrc)) 206 LogRel(("drvNvram_deleteVar: SetExtraData(%s,) returned %Rhrc\n", szExtraName, hrc)); 207 } 208 catch (...) 209 { 210 LogRel(("drvNvram_deleteVar: SetExtraData(%s,) threw exception\n", szExtraName)); 211 } 212 } 213 } 214 215 /** 216 * @interface_method_impl(PDMINVRAM,pfnVarStoreSeqBegin) 217 */ 218 DECLCALLBACK(int) drvNvram_VarStoreSeqBegin(PPDMINVRAMCONNECTOR pInterface, uint32_t cVariables) 219 { 220 PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvramConnector); 221 int rc = VINF_SUCCESS; 222 if (pThis->fPermanentSave && pThis->pNvram) 223 { 224 /* 225 * Remove all existing variables. 226 */ 227 for (PCFGMNODE pVarNode = CFGMR3GetFirstChild(pThis->pCfgVarRoot); pVarNode; pVarNode = CFGMR3GetNextChild(pVarNode)) 228 { 229 char szName[128]; 230 rc = CFGMR3GetName(pVarNode, szName, sizeof(szName)); 231 if (RT_SUCCESS(rc)) 232 drvNvram_deleteVar(pThis, szName); 233 else 234 LogRel(("drvNvram_VarStoreSeqBegin: CFGMR3GetName -> %Rrc\n", rc)); 235 } 236 } 237 238 NOREF(cVariables); 159 239 return rc; 160 240 } 161 241 162 163 /** 164 * @interface_method_impl(PDMINVRAM,pfnStoreNvramValue) 165 */ 166 DECLCALLBACK(int) drvNvram_pfnLoadNvramValue(PPDMINVRAM pInterface, 167 int idxVariable, 168 RTUUID *pVendorUuid, 169 char *pcszVariableName, 170 size_t *pcbVariableName, 171 uint8_t *pu8Value, 172 size_t *pcbValue) 173 { 174 int rc = VINF_SUCCESS; 175 char szExtraDataKey[256]; 176 Bstr bstrValue; 177 HRESULT hrc; 178 LogFlowFunc(("ENTER: idxVariable:%d, *pcbVariableName:%d, *pcbValue:%d\n", 179 idxVariable, 180 *pcbVariableName, 181 *pcbValue)); 182 PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvram); 183 if (!pThis->fPermanentSave) 184 { 185 rc = VERR_NOT_FOUND; 186 LogFlowFuncLeaveRC(rc); 187 return rc; 188 } 189 190 191 RT_ZERO(szExtraDataKey); 192 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableName", idxVariable); 193 hrc = pThis->pNvram->getParent()->machine()->GetExtraData(Bstr(szExtraDataKey).raw(), bstrValue.asOutParam()); 194 if (!SUCCEEDED(hrc)) 242 /** 243 * @interface_method_impl(PDMINVRAMCONNECTOR,pfnVarQueryByIndex) 244 */ 245 DECLCALLBACK(int) drvNvram_VarQueryByIndex(PPDMINVRAMCONNECTOR pInterface, uint32_t idxVariable, 246 PRTUUID pVendorUuid, char *pszName, uint32_t *pcchName, 247 uint32_t *pfAttributes, uint8_t *pbValue, uint32_t *pcbValue) 248 { 249 PNVRAM pThis = RT_FROM_MEMBER(pInterface, NVRAM, INvramConnector); 250 251 /* 252 * Find the requested variable node. 253 */ 254 PCFGMNODE pVarNode; 255 if (pThis->idxLastVar + 1 == idxVariable && pThis->pLastVarNode) 256 pVarNode = CFGMR3GetNextChild(pThis->pLastVarNode); 257 else 258 { 259 pVarNode = CFGMR3GetFirstChild(pThis->pLastVarNode); 260 for (uint32_t i = 0; i < idxVariable && pVarNode; i++) 261 pVarNode = CFGMR3GetNextChild(pVarNode); 262 } 263 if (!pVarNode) 195 264 return VERR_NOT_FOUND; 196 *pcbVariableName = RTStrCopy(pcszVariableName, 1024, Utf8Str(bstrValue).c_str()); 197 198 RT_ZERO(szExtraDataKey); 199 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VendorGuid", idxVariable); 200 hrc = pThis->pNvram->getParent()->machine()->GetExtraData(Bstr(szExtraDataKey).raw(), bstrValue.asOutParam()); 201 RTUuidFromStr(pVendorUuid, Utf8Str(bstrValue).c_str()); 202 203 #if 0 204 RT_ZERO(szExtraDataKey); 205 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableValueLength", idxVariable); 206 hrc = pThis->pNvram->getParent()->machine()->GetExtraData(Bstr(szExtraDataKey).raw(), bstrValue.asOutParam()); 207 *pcbValue = Utf8Str(bstrValue).toUInt32(); 208 #endif 209 210 RT_ZERO(szExtraDataKey); 211 RTStrPrintf(szExtraDataKey, 256, "VBoxInternal/Devices/efi/0/LUN#0/Config/NVRAM/%d/VariableValue", idxVariable); 212 hrc = pThis->pNvram->getParent()->machine()->GetExtraData(Bstr(szExtraDataKey).raw(), bstrValue.asOutParam()); 213 rc = RTBase64Decode(Utf8Str(bstrValue).c_str(), pu8Value, 1024, pcbValue, NULL); 214 AssertRCReturn(rc, rc); 215 216 pThis->cLoadedVariables++; 217 LogFlowFuncLeaveRC(rc); 218 return rc; 265 266 /* cache it */ 267 pThis->pLastVarNode = pVarNode; 268 pThis->idxLastVar = idxVariable; 269 270 /* 271 * Read the variable node. 272 */ 273 int rc = CFGMR3QueryString(pVarNode, "Name", pszName, *pcchName); 274 AssertRCReturn(rc, rc); 275 *pcchName = strlen(pszName); 276 277 char szUuid[RTUUID_STR_LENGTH]; 278 rc = CFGMR3QueryString(pVarNode, "Uuid", szUuid, sizeof(szUuid)); 279 AssertRCReturn(rc, rc); 280 rc = RTUuidFromStr(pVendorUuid, szUuid); 281 AssertRCReturn(rc, rc); 282 283 rc = CFGMR3QueryU32(pVarNode, "Attribs", pfAttributes); 284 AssertRCReturn(rc, rc); 285 286 size_t cbValue; 287 rc = CFGMR3QuerySize(pVarNode, "Value", &cbValue); 288 AssertRCReturn(rc, rc); 289 AssertReturn(cbValue <= *pcbValue, VERR_BUFFER_OVERFLOW); 290 rc = CFGMR3QueryBytes(pVarNode, "Value", pbValue, cbValue); 291 AssertRCReturn(rc, rc); 292 293 return VINF_SUCCESS; 219 294 } 220 295 … … 230 305 231 306 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase); 232 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINVRAM , &pThis->INvram);307 PDMIBASE_RETURN_INTERFACE(pszIID, PDMINVRAMCONNECTOR, &pThis->INvramConnector); 233 308 return NULL; 234 309 } … … 242 317 LogFlow(("%s: iInstance/#d\n", __FUNCTION__, pDrvIns->iInstance)); 243 318 PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM); 319 if (pThis->pNvram != NULL) 320 pThis->pNvram->mpDrv = NULL; 244 321 } 245 322 … … 253 330 PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM); 254 331 332 /* 333 * Initalize instance data variables first. 334 */ 335 //pThis->pNvram = NULL; 336 //pThis->cLoadedVariables = 0; 337 //pThis->fPermanentSave = false; 338 pThis->pCfgVarRoot = CFGMR3GetChild(pCfg, "Vars"); 339 //pThis->pLastVarNode = NULL; 340 pThis->idxLastVar = UINT32_MAX / 2; 341 342 pDrvIns->IBase.pfnQueryInterface = Nvram::drvNvram_QueryInterface; 343 pThis->INvramConnector.pfnVarQueryByIndex = drvNvram_VarQueryByIndex; 344 pThis->INvramConnector.pfnVarStoreSeqBegin = drvNvram_VarStoreSeqBegin; 345 pThis->INvramConnector.pfnVarStoreSeqPut = drvNvram_VarStoreSeqPut; 346 pThis->INvramConnector.pfnVarStoreSeqEnd = drvNvram_VarStoreSeqEnd; 347 348 /* 349 * Validate and read configuration. 350 */ 255 351 if (!CFGMR3AreValuesValid(pCfg, "Object\0" 256 352 "PermanentSave\0")) … … 260 356 VERR_PDM_DRVINS_NO_ATTACH); 261 357 262 void *pv; 263 int rc = CFGMR3QueryPtr(pCfg, "Object", &pv); 358 int rc = CFGMR3QueryPtr(pCfg, "Object", (void **)&pThis->pNvram); 264 359 AssertMsgRCReturn(rc, ("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc), rc); 265 pThis->pNvram = (Nvram *)pv; 266 267 bool fPermanentSave = false; 268 rc = CFGMR3QueryBool(pCfg, "PermanentSave", &fPermanentSave); 269 if ( RT_SUCCESS(rc) 270 || rc == VERR_CFGM_VALUE_NOT_FOUND) 271 pThis->fPermanentSave = fPermanentSave; 272 else 273 AssertRCReturn(rc, rc); 274 275 pDrvIns->IBase.pfnQueryInterface = Nvram::drvNvram_QueryInterface; 276 pThis->INvram.pfnFlushNvramStorage = drvNvram_pfnFlushNvramStorage; 277 pThis->INvram.pfnStoreNvramValue = drvNvram_pfnStoreNvramValue; 278 pThis->INvram.pfnLoadNvramValue = drvNvram_pfnLoadNvramValue; 360 361 rc = CFGMR3QueryBoolDef(pCfg, "PermanentSave", &pThis->fPermanentSave, false); 362 AssertRCReturn(rc, rc); 363 364 /* 365 * Let the associated class instance know about us. 366 */ 367 pThis->pNvram->mpDrv = pThis; 279 368 280 369 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.