VirtualBox

Ignore:
Timestamp:
Mar 13, 2025 5:47:45 PM (5 weeks ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
167951
Message:

Runtime/common/efi,Main: Fix creating NVRAM files for ARM VMs, the previous ones where incompatible to what the UEFI firmware expected causing a hang during boot under certain circumstances, bugref:10872

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/efi/efivarstorevfs.cpp

    r107450 r108554  
    24362436
    24372437
    2438 RTDECL(int) RTEfiVarStoreCreate(RTVFSFILE hVfsFile, uint64_t offStore, uint64_t cbStore, uint32_t fFlags, uint32_t cbBlock,
    2439                                 PRTERRINFO pErrInfo)
     2438RTDECL(int) RTEfiVarStoreCreate(RTVFSFILE hVfsFile, uint64_t offStore, PCRTEFIVARSTORECFG pCfg, PRTERRINFO pErrInfo)
    24402439{
    24412440    RT_NOREF(pErrInfo);
     
    24442443     * Validate input.
    24452444     */
    2446     if (!cbBlock)
    2447         cbBlock = 4096;
    2448     else
    2449         AssertMsgReturn(cbBlock <= 8192 && RT_IS_POWER_OF_TWO(cbBlock),
    2450                         ("cbBlock=%#x\n", cbBlock), VERR_INVALID_PARAMETER);
    2451     AssertReturn(!(fFlags & ~RTEFIVARSTORE_CREATE_F_VALID_MASK), VERR_INVALID_FLAGS);
    2452 
    2453     if (!cbStore)
    2454     {
    2455         uint64_t cbFile;
    2456         int rc = RTVfsFileQuerySize(hVfsFile, &cbFile);
    2457         AssertRCReturn(rc, rc);
    2458         AssertMsgReturn(cbFile > offStore, ("cbFile=%#RX64 offStore=%#RX64\n", cbFile, offStore), VERR_INVALID_PARAMETER);
    2459         cbStore = cbFile - offStore;
    2460     }
    2461 
    2462     uint32_t cbFtw = 0;
    2463     uint32_t offFtw = 0;
    2464     uint32_t cbVarStore = cbStore;
    2465     uint32_t cbNvEventLog = 0;
    2466     uint32_t offNvEventLog = 0;
    2467     if (!(fFlags & RTEFIVARSTORE_CREATE_F_NO_FTW_WORKING_SPACE))
    2468     {
    2469         /* Split the available space in half for the fault tolerant working area. */
    2470         /** @todo Don't fully understand how these values come together right now but
    2471          * we want to create NVRAM files matching the default OVMF_VARS.fd for now, see
    2472          * https://github.com/tianocore/edk2/commit/b24fca05751f8222acf264853709012e0ab7bf49
    2473          * for the layout.
    2474          * Probably have toadd more arguments to control the different parameters.
    2475          */
    2476         cbNvEventLog  = _4K;
    2477         cbVarStore    = cbStore / 2 - cbNvEventLog - _4K;
    2478         cbFtw         = cbVarStore + _4K;
    2479         offNvEventLog = cbVarStore;
    2480         offFtw        = offNvEventLog + cbNvEventLog;
    2481     }
    2482 
    2483     uint32_t const cBlocks = (uint32_t)(cbStore / cbBlock);
     2445    AssertPtrReturn(pCfg, VERR_INVALID_PARAMETER);
     2446
     2447    uint32_t const cBlocks = (uint32_t)(pCfg->cbFv / pCfg->cbBlock);
    24842448
    24852449    EFI_GUID                   GuidVarStore = EFI_VARSTORE_FILESYSTEM_GUID;
     
    24912455    /* Firmware volume header. */
    24922456    memcpy(&FvHdr.GuidFilesystem, &GuidVarStore, sizeof(GuidVarStore));
    2493     FvHdr.cbFv           = RT_H2LE_U64(cbStore);
     2457    FvHdr.cbFv           = RT_H2LE_U64(pCfg->cbFv);
    24942458    FvHdr.u32Signature   = RT_H2LE_U32(EFI_FIRMWARE_VOLUME_HEADER_SIGNATURE);
    24952459    FvHdr.fAttr          = RT_H2LE_U32(0x4feff); /** @todo */
     
    25032467        u16Chksum += RT_LE2H_U16(*pu16++);
    25042468
    2505     /* Block map, the second entry remains 0 as it serves the delimiter. */
    2506     aBlockMap[0].cbBlock     = RT_H2LE_U32(cbBlock);
     2469    /* Block map, the second entry remains 0 as it serves as the delimiter. */
     2470    aBlockMap[0].cbBlock     = RT_H2LE_U32(pCfg->cbBlock);
    25072471    aBlockMap[0].cBlocks     = RT_H2LE_U32(cBlocks);
    25082472
     
    25152479    /* Variable store header. */
    25162480    memcpy(&VarStoreHdr.GuidVarStore, &GuidVarAuth, sizeof(GuidVarAuth));
    2517     VarStoreHdr.cbVarStore   = RT_H2LE_U32(cbVarStore - sizeof(FvHdr) - sizeof(aBlockMap));
     2481    VarStoreHdr.cbVarStore   = RT_H2LE_U32(pCfg->cbVarStore - (sizeof(FvHdr) + sizeof(aBlockMap)));
    25182482    VarStoreHdr.bFmt         = EFI_VARSTORE_HEADER_FMT_FORMATTED;
    25192483    VarStoreHdr.bState       = EFI_VARSTORE_HEADER_STATE_HEALTHY;
     2484
     2485    /* Fill the remainder with 0xff as it would be the case for a real NAND flash device. */
     2486    uint64_t const offVarStoreStart = offStore + sizeof(FvHdr) + sizeof(aBlockMap) + sizeof(VarStoreHdr);
     2487    uint64_t const offVarStoreEnd   = offVarStoreStart + (pCfg->cbVarStore - offVarStoreStart);
    25202488
    25212489    /* Write everything. */
     
    25262494        rc = RTVfsFileWriteAt(hVfsFile, offStore + sizeof(FvHdr) + sizeof(aBlockMap), &VarStoreHdr, sizeof(VarStoreHdr), NULL);
    25272495    if (RT_SUCCESS(rc))
    2528     {
    2529         /* Fill the remainder with 0xff as it would be the case for a real NAND flash device. */
    2530         uint64_t offStart = offStore + sizeof(FvHdr) + sizeof(aBlockMap) + sizeof(VarStoreHdr);
    2531         uint64_t offEnd   = offStore + cbVarStore;
    2532 
    2533         rc = rtEfiVarStoreFillWithFF(hVfsFile, offStart, offEnd);
    2534     }
    2535 
     2496        rc = rtEfiVarStoreFillWithFF(hVfsFile, offVarStoreStart, offVarStoreEnd);
     2497
     2498    /* The area starts with the event log which defaults to 0xff. */
    25362499    if (   RT_SUCCESS(rc)
    2537         && !(fFlags & RTEFIVARSTORE_CREATE_F_NO_FTW_WORKING_SPACE))
     2500        && pCfg->cbNvEventLog)
     2501        rc = rtEfiVarStoreFillWithFF(hVfsFile, offVarStoreEnd, offVarStoreEnd + pCfg->cbNvEventLog);
     2502
     2503    if (   RT_SUCCESS(rc)
     2504        && pCfg->cbFtw)
    25382505    {
    25392506        EFI_GUID             GuidFtwArea = EFI_WORKING_BLOCK_SIGNATURE_GUID;
     
    25422509        memcpy(&FtwHdr.GuidSignature, &GuidFtwArea, sizeof(GuidFtwArea));
    25432510        FtwHdr.fWorkingBlockValid = RT_H2LE_U32(0xfffffffe); /** @todo */
    2544         FtwHdr.cbWriteQueue       = RT_H2LE_U64(0xfe0ULL); /* This comes from the default OVMF variable volume. */
     2511        FtwHdr.cbWriteQueue       = RT_H2LE_U64(pCfg->cbWriteQueue);
    25452512        FtwHdr.u32Chksum          = RTCrc32(&FtwHdr, sizeof(FtwHdr));
    25462513
    2547         /* The area starts with the event log which defaults to 0xff. */
    2548         rc = rtEfiVarStoreFillWithFF(hVfsFile, offNvEventLog, offNvEventLog + cbNvEventLog);
     2514        uint32_t const offFtwStart = offVarStoreEnd + pCfg->cbNvEventLog;
     2515
     2516        /* Write the FTW header. */
     2517        rc = RTVfsFileWriteAt(hVfsFile, offFtwStart, &FtwHdr, sizeof(FtwHdr), NULL);
    25492518        if (RT_SUCCESS(rc))
    2550         {
    2551             /* Write the FTW header. */
    2552             rc = RTVfsFileWriteAt(hVfsFile, offFtw, &FtwHdr, sizeof(FtwHdr), NULL);
    2553             if (RT_SUCCESS(rc))
    2554                 rc = rtEfiVarStoreFillWithFF(hVfsFile, offFtw + sizeof(FtwHdr), offFtw + cbFtw);
    2555         }
     2519            rc = rtEfiVarStoreFillWithFF(hVfsFile, offFtwStart + sizeof(FtwHdr), offFtwStart + pCfg->cbFtw);
    25562520    }
    25572521
Note: See TracChangeset for help on using the changeset viewer.

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