VirtualBox

Changeset 90125 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Jul 9, 2021 2:05:45 PM (4 years ago)
Author:
vboxsync
Message:

Runtime/evivarstorevfs.cpp: Allow overwriting variable data (no variable deletion and creation yet), bugref:9580

File:
1 edited

Legend:

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

    r90116 r90125  
    6666    /** Pointer to the owning variable store. */
    6767    PRTEFIVARSTORE      pVarStore;
    68     /** Offset of the variable header located in the backing image - 0 if not written yet. */
    69     uint64_t            offVarHdr;
    7068    /** Offset of the variable data located in the backing image - 0 if not written yet. */
    7169    uint64_t            offVarData;
     70    /** Pointer to the in memory data, NULL if not yet read. */
     71    void                *pvData;
    7272    /** Monotonic counter value. */
    7373    uint64_t            cMonotonic;
     
    386386    pObjInfo->BirthTime             = *pTime;
    387387    pObjInfo->Attr.fMode            =   fIsDir
    388                                       ? RTFS_TYPE_DIRECTORY | RTFS_UNIX_ALL_PERMS
    389                                       : RTFS_TYPE_FILE | RTFS_UNIX_ALL_PERMS;
     388                                      ? RTFS_TYPE_DIRECTORY | RTFS_UNIX_ALL_ACCESS_PERMS
     389                                      : RTFS_TYPE_FILE | RTFS_UNIX_IWOTH | RTFS_UNIX_IROTH
     390                                                       | RTFS_UNIX_IWGRP | RTFS_UNIX_IRGRP
     391                                                       | RTFS_UNIX_IWUSR | RTFS_UNIX_IRUSR;
    390392    pObjInfo->Attr.enmAdditional    = enmAddAttr;
    391393
     
    532534        if (RT_SUCCESS(rc))
    533535            pThis->offFile = off + cbThisRead;
    534         Log6(("rtFsEfiVarStore_Read: off=%#RX64 cbSeg=%#x -> %Rrc\n", off, pSgBuf->paSegs[0].cbSeg, rc));
     536        Log6(("rtEfiVarStoreFile_ReadMem: off=%#RX64 cbSeg=%#x -> %Rrc\n", off, pSgBuf->paSegs[0].cbSeg, rc));
    535537    }
    536538    else
     
    551553        }
    552554        Log6(("rtEfiVarStoreFile_ReadMem: off=%#RX64 cbSeg=%#x -> %Rrc *pcbRead=%#x\n", off, pSgBuf->paSegs[0].cbSeg, rc, *pcbRead));
     555    }
     556
     557    return rc;
     558}
     559
     560
     561/**
     562 * Writes variable data from the given memory area.
     563 *
     564 * @returns IPRT status code.
     565 * @param   pThis               The EFI variable file instance.
     566 * @param   pvData              Pointer to the start of the data.
     567 * @param   cbData              Size of the variable data in bytes.
     568 * @param   off                 Where to start writing relative from the data start offset.
     569 * @param   pSgBuf              The data to write.
     570 * @param   pcbWritten          Where to return the number of bytes written, optional.
     571 */
     572static int rtEfiVarStoreFile_WriteMem(PRTEFIVARFILE pThis, void *pvData, size_t cbData,
     573                                      RTFOFF off, PCRTSGBUF pSgBuf, size_t *pcbWritten)
     574{
     575    int rc = VINF_SUCCESS;
     576    size_t cbWrite = pSgBuf->paSegs[0].cbSeg;
     577    size_t cbThisWrite = RT_MIN(cbData - off, cbWrite);
     578    uint8_t *pbData = (uint8_t *)pvData;
     579    if (!pcbWritten)
     580    {
     581        if (cbThisWrite == cbWrite)
     582            memcpy(&pbData[off], pSgBuf->paSegs[0].pvSeg, cbThisWrite);
     583        else
     584            rc = VERR_EOF;
     585
     586        if (RT_SUCCESS(rc))
     587            pThis->offFile = off + cbThisWrite;
     588        Log6(("rtEfiVarStoreFile_WriteMem: off=%#RX64 cbSeg=%#x -> %Rrc\n", off, pSgBuf->paSegs[0].cbSeg, rc));
     589    }
     590    else
     591    {
     592        if ((uint64_t)off >= cbData)
     593        {
     594            *pcbWritten = 0;
     595            rc = VINF_EOF;
     596        }
     597        else
     598        {
     599            memcpy(&pbData[off], pSgBuf->paSegs[0].pvSeg, cbThisWrite);
     600            /* Return VINF_EOF if beyond end-of-file. */
     601            if (cbThisWrite < cbWrite)
     602                rc = VINF_EOF;
     603            pThis->offFile = off + cbThisWrite;
     604            *pcbWritten = cbThisWrite;
     605        }
     606        Log6(("rtEfiVarStoreFile_WriteMem: off=%#RX64 cbSeg=%#x -> %Rrc *pcbWritten=%#x\n", off, pSgBuf->paSegs[0].cbSeg, rc, *pcbWritten));
    553607    }
    554608
     
    616670
    617671/**
     672 * Ensures that the variable data is available before any modification.
     673 *
     674 * @returns IPRT status code.
     675 * @param   pVar                The variable instance.
     676 */
     677static int rtEfiVarStore_VarReadData(PRTEFIVAR pVar)
     678{
     679    if (RT_LIKELY(   !pVar->offVarData
     680                  || !pVar->cbData))
     681        return VINF_SUCCESS;
     682
     683    Assert(!pVar->pvData);
     684    pVar->pvData = RTMemAlloc(pVar->cbData);
     685    if (RT_UNLIKELY(!pVar->pvData))
     686        return VERR_NO_MEMORY;
     687
     688    PRTEFIVARSTORE pVarStore = pVar->pVarStore;
     689    int rc = RTVfsFileReadAt(pVarStore->hVfsBacking, pVar->offVarData, pVar->pvData, pVar->cbData, NULL);
     690    if (RT_SUCCESS(rc))
     691        pVar->offVarData = 0; /* Marks the variable data as in memory. */
     692    else
     693    {
     694        RTMemFree(pVar->pvData);
     695        pVar->pvData = NULL;
     696    }
     697
     698    return rc;
     699}
     700
     701
     702/**
     703 * Ensures that the given variable has the given data size.
     704 *
     705 * @returns IPRT status code.
     706 * @retval  VERR_DISK_FULL if the new size would exceed the variable storage size.
     707 * @param   pVar                The variable instance.
     708 * @param   cbData              New number of bytes of data for the variable.
     709 */
     710static int rtEfiVarStore_VarEnsureDataSz(PRTEFIVAR pVar, size_t cbData)
     711{
     712    PRTEFIVARSTORE pVarStore = pVar->pVarStore;
     713
     714    if (pVar->cbData == cbData)
     715        return VINF_SUCCESS;
     716
     717    int rc = VINF_SUCCESS;
     718    if (cbData < pVar->cbData)
     719    {
     720        /* Shrink. */
     721        void *pvNew = RTMemRealloc(pVar->pvData, cbData);
     722        if (pvNew)
     723        {
     724            pVar->pvData = pvNew;
     725            pVarStore->cbVarData -= pVar->cbData - cbData;
     726            pVar->cbData = cbData;
     727        }
     728        else
     729            rc = VERR_NO_MEMORY;
     730    }
     731    else if (cbData > pVar->cbData)
     732    {
     733        /* Grow. */
     734        if (pVarStore->cbVarStore - pVarStore->cbVarData >= cbData - pVar->cbData)
     735        {
     736            void *pvNew = RTMemRealloc(pVar->pvData, cbData);
     737            if (pvNew)
     738            {
     739                pVar->pvData = pvNew;
     740                pVarStore->cbVarData += cbData - pVar->cbData;
     741                pVar->cbData          = cbData;
     742            }
     743            else
     744                rc = VERR_NO_MEMORY;
     745        }
     746        else
     747            rc = VERR_DISK_FULL;
     748    }
     749
     750    return rc;
     751}
     752
     753
     754/**
    618755 * Flush the variable store to the backing storage. This will remove any
    619756 * deleted variables in the backing storage.
     
    626763    int rc = VINF_SUCCESS;
    627764    uint64_t offCur = pThis->offStoreData;
    628     void *pvData = NULL;
    629     size_t cbData = 0;
    630     size_t cbDataMax = 0;
    631765
    632766    for (uint32_t i = 0; i < pThis->cVars && RT_SUCCESS(rc); i++)
     
    642776
    643777            /* Read in the data of the variable if it exists. */
    644             if (pVar->offVarData)
    645             {
    646                 if (cbDataMax < pVar->cbData)
    647                 {
    648                     size_t cbDataMaxNew = pVar->cbData;
    649                     void *pvDataNew = RTMemRealloc(pvData, cbDataMaxNew);
    650                     if (pvDataNew)
    651                     {
    652                         pvData = pvDataNew;
    653                         cbDataMax = cbDataMaxNew;
    654                     }
    655                     else
    656                         rc = VERR_NO_MEMORY;
    657                 }
    658 
    659                 cbData = pVar->cbData;
    660 
    661                 if (RT_SUCCESS(rc))
    662                     rc = RTVfsFileReadAt(pThis->hVfsBacking, pVar->offVarData, pvData, cbData, NULL);
    663             }
    664 
    665             /* Write out the variable. */
     778            rc = rtEfiVarStore_VarReadData(pVar);
    666779            if (RT_SUCCESS(rc))
    667780            {
     781                /* Write out the variable. */
    668782                EFI_AUTH_VAR_HEADER VarHdr;
    669783                size_t cbName = cwcLen * sizeof(RTUTF16);
     
    684798                    rc = RTVfsFileWriteAt(pThis->hVfsBacking, offCur + sizeof(VarHdr), pwszName, cbName, NULL);
    685799                if (RT_SUCCESS(rc))
    686                     rc = RTVfsFileWriteAt(pThis->hVfsBacking, offCur + sizeof(VarHdr) + cbName, pvData, cbData, NULL);
     800                    rc = RTVfsFileWriteAt(pThis->hVfsBacking, offCur + sizeof(VarHdr) + cbName, pVar->pvData, pVar->cbData, NULL);
    687801                if (RT_SUCCESS(rc))
    688802                {
    689                     offCur += sizeof(VarHdr) + cbName + cbData;
     803                    offCur += sizeof(VarHdr) + cbName + pVar->cbData;
    690804                    uint64_t offCurAligned = RT_ALIGN_64(offCur, sizeof(uint16_t));
    691805                    if (offCurAligned > offCur)
     
    722836    }
    723837
    724     if (pvData)
    725         RTMemFree(pvData);
    726 
    727838    return rc;
    728839}
     
    781892        rc = rtEfiVarStoreFile_ReadMem(pThis, (const uint8_t *)pVar + pThis->pEntry->offObject, pThis->pEntry->cbObject, off, pSgBuf, pcbRead);
    782893    else
    783         rc = rtEfiVarStoreFile_ReadFile(pThis, pVar->offVarData, pVar->cbData, off, pSgBuf, pcbRead);
     894    {
     895        /* Data section. */
     896        if (!pVar->offVarData)
     897            rc = rtEfiVarStoreFile_ReadMem(pThis, pVar->pvData, pVar->cbData, off, pSgBuf, pcbRead);
     898        else
     899            rc = rtEfiVarStoreFile_ReadFile(pThis, pVar->offVarData, pVar->cbData, off, pSgBuf, pcbRead);
     900    }
    784901
    785902    return rc;
     
    792909static DECLCALLBACK(int) rtEfiVarStoreFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten)
    793910{
    794     RT_NOREF(pvThis, off, pSgBuf, fBlocking, pcbWritten);
    795     return VERR_WRITE_PROTECT;
     911    PRTEFIVARFILE pThis = (PRTEFIVARFILE)pvThis;
     912    PRTEFIVARSTORE pVarStore = pThis->pVarStore;
     913    PRTEFIVAR pVar = pThis->pVar;
     914    AssertReturn(pSgBuf->cSegs == 1, VERR_INTERNAL_ERROR_3);
     915    RT_NOREF(fBlocking);
     916
     917    if (pVarStore->fMntFlags & RTVFSMNT_F_READ_ONLY)
     918        return VERR_WRITE_PROTECT;
     919
     920    if (off == -1)
     921        off = pThis->offFile;
     922    else
     923        AssertReturn(off >= 0, VERR_INTERNAL_ERROR_3);
     924
     925    int rc;
     926    if (pThis->pEntry->cbObject) /* These can't grow. */
     927        rc = rtEfiVarStoreFile_WriteMem(pThis, (uint8_t *)pVar + pThis->pEntry->offObject, pThis->pEntry->cbObject,
     928                                        off, pSgBuf, pcbWritten);
     929    else
     930    {
     931        /* Writing data section. */
     932        rc = rtEfiVarStore_VarReadData(pVar);
     933        if (RT_SUCCESS(rc))
     934        {
     935            if (off + pSgBuf->paSegs[0].cbSeg > pVar->cbData)
     936                rc = rtEfiVarStore_VarEnsureDataSz(pVar, off + pSgBuf->paSegs[0].cbSeg);
     937            if (RT_SUCCESS(rc))
     938                rc = rtEfiVarStoreFile_WriteMem(pThis, pVar->pvData, pVar->cbData, off, pSgBuf, pcbWritten);
     939        }
     940    }
     941
     942    return rc;
    796943}
    797944
     
    8991046static DECLCALLBACK(int) rtEfiVarStoreFile_SetSize(void *pvThis, uint64_t cbFile, uint32_t fFlags)
    9001047{
    901     RT_NOREF(pvThis, cbFile, fFlags);
    902     return VERR_WRITE_PROTECT;
     1048    PRTEFIVARFILE pThis = (PRTEFIVARFILE)pvThis;
     1049    PRTEFIVAR pVar = pThis->pVar;
     1050    PRTEFIVARSTORE pVarStore = pThis->pVarStore;
     1051
     1052    RT_NOREF(fFlags);
     1053
     1054    if (pVarStore->fMntFlags & RTVFSMNT_F_READ_ONLY)
     1055        return VERR_WRITE_PROTECT;
     1056
     1057    int rc = rtEfiVarStore_VarReadData(pVar);
     1058    if (RT_SUCCESS(rc))
     1059        rc = rtEfiVarStore_VarEnsureDataSz(pVar, cbFile);
     1060
     1061    return rc;
    9031062}
    9041063
     
    9161075
    9171076/**
    918  * EXT file operations.
     1077 * EFI variable store file operations.
    9191078 */
    9201079static const RTVFSFILEOPS g_rtEfiVarStoreFileOps =
     
    9241083            RTVFSOBJOPS_VERSION,
    9251084            RTVFSOBJTYPE_FILE,
    926             "EFiVarStore File",
     1085            "EfiVarStore File",
    9271086            rtEfiVarStoreFile_Close,
    9281087            rtEfiVarStoreFile_QueryInfo,
     
    11121271     */
    11131272    if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN
    1114         || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE)
     1273        || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE
     1274        || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE_REPLACE)
    11151275    { /* likely */ }
    11161276    else
     
    12801440    LogFlowFunc(("\n"));
    12811441
    1282     pThis->idxNext      = 0;
     1442    pThis->idxNext = 0;
    12831443    return VINF_SUCCESS;
    12841444}
     
    17881948    PRTEFIVAR pVar = &pThis->paVars[pThis->cVars++];
    17891949    pVar->pVarStore  = pThis;
    1790     pVar->offVarHdr  = offVar;
    17911950    pVar->offVarData = offVar + sizeof(VarHdr) + RT_LE2H_U32(VarHdr.cbName);
    17921951    pVar->fAttr      = RT_LE2H_U32(VarHdr.fAttr);
     
    17941953    pVar->idPubKey   = RT_LE2H_U32(VarHdr.idPubKey);
    17951954    pVar->cbData     = RT_LE2H_U32(VarHdr.cbData);
     1955    pVar->pvData     = NULL;
    17961956    memcpy(&pVar->EfiTimestamp, &VarHdr.Timestamp, sizeof(VarHdr.Timestamp));
    17971957
Note: See TracChangeset for help on using the changeset viewer.

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