VirtualBox

Changeset 90114 in vbox


Ignore:
Timestamp:
Jul 9, 2021 11:12:53 AM (4 years ago)
Author:
vboxsync
Message:

Runtime/RTEfi*: Updates to the EFI variable storage access module, bugref:9580

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/formats/efi-varstore.h

    r90061 r90114  
    115115
    116116/** Value in EFI_AUTH_VAR_HEADER::u16StartId for a valid variable header. */
    117 #define EFI_AUTH_VAR_HEADER_START                       0x55aa
     117#define EFI_AUTH_VAR_HEADER_START                               0x55aa
    118118/** @name Possible variable states.
    119119 * @{ */
    120120/** Variable is in the process of being deleted. */
    121 #define EFI_AUTH_VAR_HEADER_STATE_IN_DELETED_TRANSITION 0xfe
     121#define EFI_AUTH_VAR_HEADER_STATE_IN_DELETED_TRANSITION         0xfe
    122122/** Variable was deleted. */
    123 #define EFI_AUTH_VAR_HEADER_STATE_DELETED               0xfd
     123#define EFI_AUTH_VAR_HEADER_STATE_DELETED                       0xfd
    124124/** Variable has only a valid header right now. */
    125 #define EFI_AUTH_VAR_HEADER_STATE_HDR_VALID_ONLY        0x7f
     125#define EFI_AUTH_VAR_HEADER_STATE_HDR_VALID_ONLY                0x7f
    126126/** Variable header, name and data are all valid. */
    127 #define EFI_AUTH_VAR_HEADER_STATE_ADDED                 0x3f
     127#define EFI_AUTH_VAR_HEADER_STATE_ADDED                         0x3f
    128128/** @} */
    129129
    130130
     131/** @name Possible variable attributes.
     132 * @{ */
     133/** The variable is stored in non volatile memory. */
     134#define EFI_VAR_HEADER_ATTR_NON_VOLATILE                        RT_BIT_32(0)
     135/** The variable is accessible by the EFI bootservice stage. */
     136#define EFI_VAR_HEADER_ATTR_BOOTSERVICE_ACCESS                  RT_BIT_32(1)
     137/** The variable is accessible during runtime. */
     138#define EFI_VAR_HEADER_ATTR_RUNTIME_ACCESS                      RT_BIT_32(2)
     139/** The variable contains an hardware error record. */
     140#define EFI_VAR_HEADER_ATTR_HW_ERROR_RECORD                     RT_BIT_32(3)
     141/** The variable can be modified only by an authenticated source. */
     142#define EFI_AUTH_VAR_HEADER_ATTR_AUTH_WRITE_ACCESS              RT_BIT_32(4)
     143/** The variable was written with a time based authentication. */
     144#define EFI_AUTH_VAR_HEADER_ATTR_TIME_BASED_AUTH_WRITE_ACCESS   RT_BIT_32(5)
     145/** The variable can be appended. */
     146#define EFI_AUTH_VAR_HEADER_ATTR_APPEND_WRITE                   RT_BIT_32(6)
     147/** @} */
     148
    131149#endif /* !IPRT_INCLUDED_formats_efi_varstore_h */
    132150
  • trunk/src/VBox/Runtime/common/efi/efitime.cpp

    r90065 r90114  
    5454    RTTIME Time; RT_ZERO(Time);
    5555
    56     Time.i32Year       = pEfiTime->u16Year + 1900;
     56    Time.i32Year       = pEfiTime->u16Year;
    5757    Time.u8Month       = pEfiTime->u8Month;
    5858    Time.u8MonthDay    = pEfiTime->u8Day;
     
    9090
    9191    RT_ZERO(*pEfiTime);
    92     pEfiTime->u16Year       =   Time.i32Year < 1900
     92    pEfiTime->u16Year       =   Time.i32Year < 0
    9393                              ? 0
    94                               : Time.i32Year - 1900;
     94                              : (uint16_t)Time.i32Year;
    9595    pEfiTime->u8Month       = Time.u8Month;
    9696    pEfiTime->u8Day         = Time.u8MonthDay;
  • trunk/src/VBox/Runtime/common/efi/efivarstorevfs.cpp

    r90068 r90114  
    6666    /** Pointer to the owning variable store. */
    6767    PRTEFIVARSTORE      pVarStore;
    68     /** Offset of the variable header located in the backing image. */
     68    /** Offset of the variable header located in the backing image - 0 if not written yet. */
    6969    uint64_t            offVarHdr;
    70     /** Offset of the variable data located in the backing image. */
     70    /** Offset of the variable data located in the backing image - 0 if not written yet. */
    7171    uint64_t            offVarData;
    72     /** The validated variable header. */
    73     EFI_AUTH_VAR_HEADER VarHdr;
     72    /** Monotonic counter value. */
     73    uint64_t            cMonotonic;
     74    /** Size of the variable data in bytes. */
     75    uint32_t            cbData;
     76    /** Index of the assoicated public key. */
     77    uint32_t            idPubKey;
     78    /** Attributes for the variable. */
     79    uint32_t            fAttr;
    7480    /** Name of the variable. */
    7581    char                *pszName;
    76     /** The time creation/update time. */
     82    /** The raw EFI timestamp as read from the header. */
     83    EFI_TIME            EfiTimestamp;
     84    /** The creation/update time. */
    7785    RTTIMESPEC          Time;
    7886    /** The vendor UUID of the variable. */
     
    8896typedef struct RTEFIGUID
    8997{
    90     /** The UUID rpresentation of the GUID. */
     98    /** The UUID representation of the GUID. */
    9199    RTUUID              Uuid;
    92100    /** Pointer to the array of indices into RTEFIVARSTORE::paVars. */
     
    119127
    120128    /** Size of the variable store (minus the header). */
    121     size_t              cbVarStore;
     129    uint64_t            cbVarStore;
    122130    /** Start offset into the backing image where the variable data starts. */
    123131    uint64_t            offStoreData;
     
    155163    /** 'by-name' directory. */
    156164    RTEFIVARSTOREDIRTYPE_BY_NAME,
    157     /** 'by-guid' directory. */
     165    /** 'by-uuid' directory. */
    158166    RTEFIVARSTOREDIRTYPE_BY_GUID,
     167    /** 'raw' directory. */
     168    RTEFIVARSTOREDIRTYPE_RAW,
    159169    /** Specific 'by-uuid/{...}' directory. */
    160170    RTEFIVARSTOREDIRTYPE_GUID,
     171    /** Specific 'raw/{...}' directory. */
     172    RTEFIVARSTOREDIRTYPE_RAW_ENTRY,
    161173    /** 32bit blowup hack. */
    162174    RTEFIVARSTOREDIRTYPE_32BIT_HACK = 0x7fffffff
     
    177189    /** The variable store associated with this directory. */
    178190    PRTEFIVARSTORE          pVarStore;
     191    /** Time when the directory was created. */
     192    RTTIMESPEC              Time;
    179193    /** Pointer to the GUID entry, only valid for RTEFIVARSTOREDIRTYPE_GUID. */
    180194    PRTEFIGUID              pGuid;
    181     /** Time when the directory was created. */
    182     RTTIMESPEC              Time;
     195    /** The variable ID, only valid for RTEFIVARSTOREDIRTYPE_RAW_ENTRY. */
     196    uint32_t                idVar;
    183197} RTEFIVARSTOREDIR;
    184198/** Pointer to an Variable store directory. */
     
    187201
    188202/**
     203 * File type.
     204 */
     205typedef enum RTEFIVARSTOREFILETYPE
     206{
     207    /** Invalid type, do not use. */
     208    RTEFIVARSTOREFILETYPE_INVALID = 0,
     209    /** File accesses the data portion of the variable. */
     210    RTEFIVARSTOREFILETYPE_DATA,
     211    /** File accesses the attributes of the variable. */
     212    RTEFIVARSTOREFILETYPE_ATTR,
     213    /** File accesses the UUID of the variable. */
     214    RTEFIVARSTOREFILETYPE_UUID,
     215    /** File accesses the public key index of the variable. */
     216    RTEFIVARSTOREFILETYPE_PUBKEY,
     217    /** File accesses the raw EFI Time of the variable. */
     218    RTEFIVARSTOREFILETYPE_TIME,
     219    /** The monotonic counter (deprecated). */
     220    RTEFIVARSTOREFILETYPE_MONOTONIC,
     221    /** 32bit hack. */
     222    RTEFIVARSTOREFILETYPE_32BIT_HACK = 0x7fffffff,
     223} RTEFIVARSTOREFILETYPE;
     224
     225
     226/**
     227 * Raw file type entry.
     228 */
     229typedef struct RTEFIVARSTOREFILERAWENTRY
     230{
     231    /** Name of the entry. */
     232    const char              *pszName;
     233    /** The associated file type. */
     234    RTEFIVARSTOREFILETYPE   enmType;
     235    /** File size of the object, 0 if dynamic. */
     236    size_t                  cbObject;
     237    /** Offset of the item in the variable header. */
     238    uint32_t                offObject;
     239} RTEFIVARSTOREFILERAWENTRY;
     240/** Pointer to a raw file type entry. */
     241typedef RTEFIVARSTOREFILERAWENTRY *PRTEFIVARSTOREFILERAWENTRY;
     242/** Pointer to a const file type entry. */
     243typedef const RTEFIVARSTOREFILERAWENTRY *PCRTEFIVARSTOREFILERAWENTRY;
     244
     245
     246/**
    189247 * Open file instance.
    190248 */
    191249typedef struct RTEFIVARFILE
    192250{
     251    /** The file type. */
     252    PCRTEFIVARSTOREFILERAWENTRY pEntry;
    193253    /** Variable store this file belongs to. */
    194     PRTEFIVARSTORE      pVarStore;
     254    PRTEFIVARSTORE              pVarStore;
    195255    /** The underlying variable structure. */
    196     PRTEFIVAR           pVar;
     256    PRTEFIVAR                   pVar;
    197257    /** Current offset into the file for I/O. */
    198     RTFOFF              offFile;
     258    RTFOFF                      offFile;
    199259} RTEFIVARFILE;
    200260/** Pointer to an open file instance. */
     
    202262
    203263
     264/**
     265 * Raw files for accessing specific items in the variable header.
     266 */
     267static const RTEFIVARSTOREFILERAWENTRY g_aRawFiles[] =
     268{
     269    { "attr",      RTEFIVARSTOREFILETYPE_ATTR,      sizeof(uint32_t), RT_UOFFSETOF(RTEFIVAR, fAttr)        },
     270    { "data",      RTEFIVARSTOREFILETYPE_DATA,                     0,                                    0 },
     271    { "uuid",      RTEFIVARSTOREFILETYPE_UUID,      sizeof(RTUUID),   RT_UOFFSETOF(RTEFIVAR, Uuid)         },
     272    { "pubkey",    RTEFIVARSTOREFILETYPE_PUBKEY,    sizeof(uint32_t), RT_UOFFSETOF(RTEFIVAR, idPubKey)     },
     273    { "time",      RTEFIVARSTOREFILETYPE_TIME,      sizeof(EFI_TIME), RT_UOFFSETOF(RTEFIVAR, EfiTimestamp) },
     274    { "monotonic", RTEFIVARSTOREFILETYPE_MONOTONIC, sizeof(uint64_t), RT_UOFFSETOF(RTEFIVAR, cMonotonic)   }
     275};
     276
     277#define RTEFIVARSTORE_FILE_ENTRY_DATA 1
     278
     279
    204280/*********************************************************************************************************************************
    205281*   Internal Functions                                                                                                           *
    206282*********************************************************************************************************************************/
    207 static int rtEfiVarStore_NewDirByType(PRTEFIVARSTORE pThis, RTEFIVARSTOREDIRTYPE enmDirType, PRTEFIGUID pGuid, PRTVFSOBJ phVfsObj);
     283static int rtEfiVarStore_NewDirByType(PRTEFIVARSTORE pThis, RTEFIVARSTOREDIRTYPE enmDirType,
     284                                      PRTEFIGUID pGuid, uint32_t idVar, PRTVFSOBJ phVfsObj);
    208285
    209286
     
    428505
    429506
    430 /*
    431  *
    432  * File operations.
    433  * File operations.
    434  * File operations.
    435  *
    436  */
    437 
    438 /**
    439  * @interface_method_impl{RTVFSOBJOPS,pfnClose}
    440  */
    441 static DECLCALLBACK(int) rtEfiVarStoreFile_Close(void *pvThis)
    442 {
    443     PRTEFIVARFILE pThis = (PRTEFIVARFILE)pvThis;
    444     LogFlow(("rtEfiVarStoreFile_Close(%p/%p)\n", pThis, pThis->pVar));
    445     RT_NOREF(pThis);
    446     return VINF_SUCCESS;
    447 }
    448 
    449 
    450 /**
    451  * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
    452  */
    453 static DECLCALLBACK(int) rtEfiVarStoreFile_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
    454 {
    455     PRTEFIVARFILE pThis = (PRTEFIVARFILE)pvThis;
    456     return rtEfiVarStore_QueryInfo(RT_LE2H_U32(pThis->pVar->VarHdr.cbData), false /*fIsDir*/,
    457                                    &pThis->pVar->Time, pObjInfo, enmAddAttr);
    458 }
    459 
    460 
    461 /**
    462  * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
    463  */
    464 static DECLCALLBACK(int) rtEfiVarStoreFile_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
    465 {
    466     PRTEFIVARFILE pThis = (PRTEFIVARFILE)pvThis;
     507/**
     508 * Reads variable data from the given memory area.
     509 *
     510 * @returns IPRT status code.
     511 * @param   pThis               The EFI variable file instance.
     512 * @param   pvData              Pointer to the start of the data.
     513 * @param   cbData              Size of the variable data in bytes.
     514 * @param   off                 Where to start reading relative from the data start offset.
     515 * @param   pSgBuf              Where to store the read data.
     516 * @param   pcbRead             Where to return the number of bytes read, optional.
     517 */
     518static int rtEfiVarStoreFile_ReadMem(PRTEFIVARFILE pThis, const void *pvData, size_t cbData,
     519                                     RTFOFF off, PCRTSGBUF pSgBuf, size_t *pcbRead)
     520{
     521    int rc = VINF_SUCCESS;
     522    size_t cbRead = pSgBuf->paSegs[0].cbSeg;
     523    size_t cbThisRead = RT_MIN(cbData - off, cbRead);
     524    const uint8_t *pbData = (const uint8_t *)pvData;
     525    if (!pcbRead)
     526    {
     527        if (cbThisRead == cbRead)
     528            memcpy(pSgBuf->paSegs[0].pvSeg, &pbData[off], cbThisRead);
     529        else
     530            rc = VERR_EOF;
     531
     532        if (RT_SUCCESS(rc))
     533            pThis->offFile = off + cbThisRead;
     534        Log6(("rtFsEfiVarStore_Read: off=%#RX64 cbSeg=%#x -> %Rrc\n", off, pSgBuf->paSegs[0].cbSeg, rc));
     535    }
     536    else
     537    {
     538        if ((uint64_t)off >= cbData)
     539        {
     540            *pcbRead = 0;
     541            rc = VINF_EOF;
     542        }
     543        else
     544        {
     545            memcpy(pSgBuf->paSegs[0].pvSeg, &pbData[off], cbThisRead);
     546            /* Return VINF_EOF if beyond end-of-file. */
     547            if (cbThisRead < cbRead)
     548                rc = VINF_EOF;
     549            pThis->offFile = off + cbThisRead;
     550            *pcbRead = cbThisRead;
     551        }
     552        Log6(("rtEfiVarStoreFile_ReadMem: off=%#RX64 cbSeg=%#x -> %Rrc *pcbRead=%#x\n", off, pSgBuf->paSegs[0].cbSeg, rc, *pcbRead));
     553    }
     554
     555    return rc;
     556}
     557
     558
     559/**
     560 * Reads variable data from the given range.
     561 *
     562 * @returns IPRT status code.
     563 * @param   pThis               The EFI variable file instance.
     564 * @param   offData             Where the data starts in the backing storage.
     565 * @param   cbData              Size of the variable data in bytes.
     566 * @param   off                 Where to start reading relative from the data start offset.
     567 * @param   pSgBuf              Where to store the read data.
     568 * @param   pcbRead             Where to return the number of bytes read, optional.
     569 */
     570static int rtEfiVarStoreFile_ReadFile(PRTEFIVARFILE pThis, uint64_t offData, size_t cbData,
     571                                      RTFOFF off, PCRTSGBUF pSgBuf, size_t *pcbRead)
     572{
     573    int rc;
    467574    PRTEFIVARSTORE pVarStore = pThis->pVarStore;
    468     AssertReturn(pSgBuf->cSegs == 1, VERR_INTERNAL_ERROR_3);
    469     RT_NOREF(fBlocking);
    470 
    471     if (off == -1)
    472         off = pThis->offFile;
    473     else
    474         AssertReturn(off >= 0, VERR_INTERNAL_ERROR_3);
    475 
    476     int rc;
    477575    size_t cbRead = pSgBuf->paSegs[0].cbSeg;
    478     size_t cbData = RT_LE2H_U32(pThis->pVar->VarHdr.cbData);
    479576    size_t cbThisRead = RT_MIN(cbData - off, cbRead);
    480     uint64_t offStart = pThis->pVar->offVarData + off;
     577    uint64_t offStart = offData + off;
    481578    if (!pcbRead)
    482579    {
     
    519616
    520617/**
     618 * Flush the variable store to the backing storage. This will remove any
     619 * deleted variables in the backing storage.
     620 *
     621 * @returns IPRT status code.
     622 * @param   pThis               The EFI variable store instance.
     623 */
     624static int rtEfiVarStore_Flush(PRTEFIVARSTORE pThis)
     625{
     626    int rc = VINF_SUCCESS;
     627    uint64_t offCur = pThis->offStoreData;
     628    void *pvData = NULL;
     629    size_t cbData = 0;
     630    size_t cbDataMax = 0;
     631
     632    for (uint32_t i = 0; i < pThis->cVars && RT_SUCCESS(rc); i++)
     633    {
     634        PRTUTF16 pwszName = NULL;
     635        size_t cwcLen = 0;
     636        PRTEFIVAR pVar = &pThis->paVars[i];
     637
     638        rc = RTStrToUtf16Ex(pVar->pszName, RTSTR_MAX, &pwszName, 0, &cwcLen);
     639        if (RT_SUCCESS(rc))
     640        {
     641            cwcLen++; /* Include the terminator. */
     642
     643            /* 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. */
     666            if (RT_SUCCESS(rc))
     667            {
     668                EFI_AUTH_VAR_HEADER VarHdr;
     669                size_t cbName = cwcLen * sizeof(RTUTF16);
     670
     671                VarHdr.u16StartId = RT_H2LE_U16(EFI_AUTH_VAR_HEADER_START);
     672                VarHdr.bState     = EFI_AUTH_VAR_HEADER_STATE_ADDED;
     673                VarHdr.bRsvd      = 0;
     674                VarHdr.fAttr      = RT_H2LE_U32(pVar->fAttr);
     675                VarHdr.cMonotonic = RT_H2LE_U64(pVar->cMonotonic);
     676                VarHdr.idPubKey   = RT_H2LE_U32(pVar->idPubKey);
     677                VarHdr.cbName     = RT_H2LE_U32(cbName);
     678                VarHdr.cbData     = RT_H2LE_U32(pVar->cbData);
     679                RTEfiGuidFromUuid(&VarHdr.GuidVendor, &pVar->Uuid);
     680                memcpy(&VarHdr.Timestamp, &pVar->EfiTimestamp, sizeof(pVar->EfiTimestamp));
     681
     682                rc = RTVfsFileWriteAt(pThis->hVfsBacking, offCur, &VarHdr, sizeof(VarHdr), NULL);
     683                if (RT_SUCCESS(rc))
     684                    rc = RTVfsFileWriteAt(pThis->hVfsBacking, offCur + sizeof(VarHdr), pwszName, cbName, NULL);
     685                if (RT_SUCCESS(rc))
     686                    rc = RTVfsFileWriteAt(pThis->hVfsBacking, offCur + sizeof(VarHdr) + cbName, pvData, cbData, NULL);
     687                if (RT_SUCCESS(rc))
     688                {
     689                    offCur += sizeof(VarHdr) + cbName + cbData;
     690                    uint64_t offCurAligned = RT_ALIGN_64(offCur, sizeof(uint16_t));
     691                    if (offCurAligned > offCur)
     692                    {
     693                        /* Should be at most 1 byte to align the next variable to a 16bit boundary. */
     694                        Assert(offCurAligned - offCur == 1);
     695                        uint8_t bFill = 0xff;
     696                        rc = RTVfsFileWriteAt(pThis->hVfsBacking, offCur, &bFill, sizeof(bFill), NULL);
     697                    }
     698
     699                    offCur = offCurAligned;
     700                }
     701            }
     702
     703            RTUtf16Free(pwszName);
     704        }
     705    }
     706
     707    if (RT_SUCCESS(rc))
     708    {
     709        /* Fill the remainder with 0xff as it would be the case for a real NAND flash device. */
     710        uint8_t abFF[512];
     711        memset(&abFF[0], 0xff, sizeof(abFF));
     712
     713        uint64_t offStart = offCur;
     714        uint64_t offEnd   = pThis->offStoreData + pThis->cbVarStore;
     715        while (   offStart < offEnd
     716               && RT_SUCCESS(rc))
     717        {
     718            size_t cbThisWrite = RT_MIN(sizeof(abFF), offEnd - offStart);
     719            rc = RTVfsFileWriteAt(pThis->hVfsBacking, offStart, &abFF[0], cbThisWrite, NULL);
     720            offStart += cbThisWrite;
     721        }
     722    }
     723
     724    if (pvData)
     725        RTMemFree(pvData);
     726
     727    return rc;
     728}
     729
     730
     731/*
     732 *
     733 * File operations.
     734 * File operations.
     735 * File operations.
     736 *
     737 */
     738
     739/**
     740 * @interface_method_impl{RTVFSOBJOPS,pfnClose}
     741 */
     742static DECLCALLBACK(int) rtEfiVarStoreFile_Close(void *pvThis)
     743{
     744    PRTEFIVARFILE pThis = (PRTEFIVARFILE)pvThis;
     745    LogFlow(("rtEfiVarStoreFile_Close(%p/%p)\n", pThis, pThis->pVar));
     746    RT_NOREF(pThis);
     747    return VINF_SUCCESS;
     748}
     749
     750
     751/**
     752 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo}
     753 */
     754static DECLCALLBACK(int) rtEfiVarStoreFile_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr)
     755{
     756    PRTEFIVARFILE pThis = (PRTEFIVARFILE)pvThis;
     757    uint64_t cbObject =   pThis->pEntry->cbObject > 0
     758                        ? pThis->pEntry->cbObject
     759                        : pThis->pVar->cbData;
     760    return rtEfiVarStore_QueryInfo(cbObject, false /*fIsDir*/, &pThis->pVar->Time, pObjInfo, enmAddAttr);
     761}
     762
     763
     764/**
     765 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead}
     766 */
     767static DECLCALLBACK(int) rtEfiVarStoreFile_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead)
     768{
     769    PRTEFIVARFILE pThis = (PRTEFIVARFILE)pvThis;
     770    PRTEFIVAR pVar = pThis->pVar;
     771    AssertReturn(pSgBuf->cSegs == 1, VERR_INTERNAL_ERROR_3);
     772    RT_NOREF(fBlocking);
     773
     774    if (off == -1)
     775        off = pThis->offFile;
     776    else
     777        AssertReturn(off >= 0, VERR_INTERNAL_ERROR_3);
     778
     779    int rc;
     780    if (pThis->pEntry->cbObject)
     781        rc = rtEfiVarStoreFile_ReadMem(pThis, (const uint8_t *)pVar + pThis->pEntry->offObject, pThis->pEntry->cbObject, off, pSgBuf, pcbRead);
     782    else
     783        rc = rtEfiVarStoreFile_ReadFile(pThis, pVar->offVarData, pVar->cbData, off, pSgBuf, pcbRead);
     784
     785    return rc;
     786}
     787
     788
     789/**
    521790 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite}
    522791 */
     
    593862            break;
    594863        case RTFILE_SEEK_END:
    595             offNew = RT_LE2H_U32(pThis->pVar->VarHdr.cbData) + offSeek;
     864            offNew = pThis->pVar->cbData + offSeek;
    596865            break;
    597866        case RTFILE_SEEK_CURRENT:
     
    617886{
    618887    PRTEFIVARFILE pThis = (PRTEFIVARFILE)pvThis;
    619     *pcbFile = (uint64_t)RT_LE2H_U32(pThis->pVar->VarHdr.cbData);
     888    if (pThis->pEntry->cbObject)
     889        *pcbFile = pThis->pEntry->cbObject;
     890    else
     891        *pcbFile = (uint64_t)pThis->pVar->cbData;
    620892    return VINF_SUCCESS;
    621893}
     
    692964 * @param   pThis               The ext volume instance.
    693965 * @param   fOpen               Open flags passed.
    694  * @param   iInode              The inode for the file.
     966 * @param   pVar                The variable this file accesses.
     967 * @param   pEntry              File type entry.
    695968 * @param   phVfsFile           Where to store the VFS file handle on success.
    696969 * @param   pErrInfo            Where to record additional error information on error, optional.
    697970 */
    698971static int rtEfiVarStore_NewFile(PRTEFIVARSTORE pThis, uint64_t fOpen, PRTEFIVAR pVar,
    699                                  PRTVFSOBJ phVfsObj)
     972                                 PCRTEFIVARSTOREFILERAWENTRY pEntry, PRTVFSOBJ phVfsObj)
    700973{
    701974    RTVFSFILE hVfsFile;
     
    705978    if (RT_SUCCESS(rc))
    706979    {
     980        pNewFile->pEntry    = pEntry;
    707981        pNewFile->pVarStore = pThis;
    708982        pNewFile->pVar      = pVar;
     
    8071081            if (   pThis->enmType == RTEFIVARSTOREDIRTYPE_BY_NAME
    8081082                || pThis->enmType == RTEFIVARSTOREDIRTYPE_BY_GUID
     1083                || pThis->enmType == RTEFIVARSTOREDIRTYPE_RAW
    8091084                || pThis->enmType == RTEFIVARSTOREDIRTYPE_ROOT)
    8101085                enmDirTypeNew = RTEFIVARSTOREDIRTYPE_ROOT;
    8111086            else if (pThis->enmType == RTEFIVARSTOREDIRTYPE_GUID)
    8121087                enmDirTypeNew = RTEFIVARSTOREDIRTYPE_BY_GUID;
     1088            else if (pThis->enmType == RTEFIVARSTOREDIRTYPE_RAW_ENTRY)
     1089                enmDirTypeNew = RTEFIVARSTOREDIRTYPE_RAW;
    8131090            else
    8141091                AssertMsgFailedReturn(("Invalid directory type %d\n", pThis->enmType), VERR_ACCESS_DENIED);
     
    8211098                if (   (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN
    8221099                    || (fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE)
    823                     rc = rtEfiVarStore_NewDirByType(pVarStore, enmDirTypeNew, NULL /*pGuid*/, phVfsObj);
     1100                    rc = rtEfiVarStore_NewDirByType(pVarStore, enmDirTypeNew, NULL /*pGuid*/, 0 /*idVar*/, phVfsObj);
    8241101                else
    8251102                    rc = VERR_ACCESS_DENIED;
     
    8451122        {
    8461123            if (!strcmp(pszEntry, "by-name"))
    847                 return rtEfiVarStore_NewDirByType(pVarStore, RTEFIVARSTOREDIRTYPE_BY_NAME, NULL /*pGuid*/, phVfsObj);
     1124                return rtEfiVarStore_NewDirByType(pVarStore, RTEFIVARSTOREDIRTYPE_BY_NAME,
     1125                                                  NULL /*pGuid*/, 0 /*idVar*/, phVfsObj);
    8481126            else if (!strcmp(pszEntry, "by-uuid"))
    849                 return rtEfiVarStore_NewDirByType(pVarStore, RTEFIVARSTOREDIRTYPE_BY_GUID, NULL /*pGuid*/, phVfsObj);
     1127                return rtEfiVarStore_NewDirByType(pVarStore, RTEFIVARSTOREDIRTYPE_BY_GUID,
     1128                                                  NULL /*pGuid*/, 0 /*idVar*/, phVfsObj);
     1129            else if (!strcmp(pszEntry, "raw"))
     1130                return rtEfiVarStore_NewDirByType(pVarStore, RTEFIVARSTOREDIRTYPE_RAW,
     1131                                                  NULL /*pGuid*/, 0 /*idVar*/, phVfsObj);
    8501132            else
    8511133                rc = VERR_FILE_NOT_FOUND;
     
    8541136        case RTEFIVARSTOREDIRTYPE_GUID: /** @todo This looks through all variables, not only the ones with the GUID. */
    8551137        case RTEFIVARSTOREDIRTYPE_BY_NAME:
     1138        case RTEFIVARSTOREDIRTYPE_RAW:
    8561139        {
    8571140            /* Look for the name. */
    8581141            for (uint32_t i = 0; i < pVarStore->cVars; i++)
    8591142                if (!strcmp(pszEntry, pVarStore->paVars[i].pszName))
    860                     return rtEfiVarStore_NewFile(pVarStore, fOpen, &pVarStore->paVars[i], phVfsObj);
     1143                {
     1144                    if (pThis->enmType == RTEFIVARSTOREDIRTYPE_RAW)
     1145                        return rtEfiVarStore_NewDirByType(pVarStore, RTEFIVARSTOREDIRTYPE_RAW_ENTRY,
     1146                                                          NULL /*pGuid*/, i /*idVar*/, phVfsObj);
     1147                    else
     1148                        return rtEfiVarStore_NewFile(pVarStore, fOpen, &pVarStore->paVars[i],
     1149                                                     &g_aRawFiles[RTEFIVARSTORE_FILE_ENTRY_DATA], phVfsObj);
     1150                }
    8611151
    8621152            rc = VERR_FILE_NOT_FOUND;
     
    8741164
    8751165                if (!strcmp(pszEntry, szUuid))
    876                     return rtEfiVarStore_NewDirByType(pVarStore, RTEFIVARSTOREDIRTYPE_GUID, pGuid, phVfsObj);
     1166                    return rtEfiVarStore_NewDirByType(pVarStore, RTEFIVARSTOREDIRTYPE_GUID,
     1167                                                      pGuid, 0 /*idVar*/, phVfsObj);
    8771168            }
     1169
     1170            rc = VERR_FILE_NOT_FOUND;
     1171            break;
     1172        }
     1173        case RTEFIVARSTOREDIRTYPE_RAW_ENTRY:
     1174        {
     1175            /* Look for the name. */
     1176            for (uint32_t i = 0; i < RT_ELEMENTS(g_aRawFiles); i++)
     1177                if (!strcmp(pszEntry, g_aRawFiles[i].pszName))
     1178                    return rtEfiVarStore_NewFile(pVarStore, fOpen, &pVarStore->paVars[pThis->idVar],
     1179                                                 &g_aRawFiles[i], phVfsObj);
    8781180
    8791181            rc = VERR_FILE_NOT_FOUND;
     
    8951197static DECLCALLBACK(int) rtEfiVarStoreDir_CreateDir(void *pvThis, const char *pszSubDir, RTFMODE fMode, PRTVFSDIR phVfsDir)
    8961198{
    897     RT_NOREF(pvThis, pszSubDir, fMode, phVfsDir);
     1199    PRTEFIVARSTOREDIR pThis     = (PRTEFIVARSTOREDIR)pvThis;
     1200    PRTEFIVARSTORE    pVarStore = pThis->pVarStore;
    8981201    LogFlowFunc(("\n"));
    899     return VERR_WRITE_PROTECT;
     1202
     1203    RT_NOREF(pszSubDir, fMode, phVfsDir);
     1204
     1205    if (pVarStore->fMntFlags & RTVFSMNT_F_READ_ONLY)
     1206        return VERR_WRITE_PROTECT;
     1207
     1208    /* We support creating directories only for GUIDs. */
     1209    if (pThis->enmType != RTEFIVARSTOREDIRTYPE_BY_GUID)
     1210        return VERR_NOT_SUPPORTED;
     1211
     1212    RTUUID Uuid;
     1213    int rc = RTUuidFromStr(&Uuid, pszSubDir);
     1214    if (RT_FAILURE(rc))
     1215        return VERR_NOT_SUPPORTED;
     1216
     1217    PRTEFIGUID pGuid = rtEfiVarStore_GetGuid(pVarStore, &Uuid);
     1218    if (pGuid)
     1219        return VERR_ALREADY_EXISTS;
     1220
     1221    pGuid = rtEfiVarStore_AddGuid(pVarStore, &Uuid);
     1222    if (!pGuid)
     1223        return VERR_NO_MEMORY;
     1224
     1225    return VINF_SUCCESS;
    9001226}
    9011227
     
    10001326                cbObject = 1;
    10011327                fIsDir   = true;
     1328            }
     1329            else if (pThis->idxNext == 2)
     1330            {
     1331                pszName  = "raw";
     1332                cbName   = sizeof("raw");
     1333                cbObject = 1;
     1334                fIsDir   = true;
    10021335                fNoMoreFiles = true;
    10031336            }
     
    10051338        }
    10061339        case RTEFIVARSTOREDIRTYPE_BY_NAME:
     1340        case RTEFIVARSTOREDIRTYPE_RAW:
    10071341        {
    10081342            PRTEFIVAR pVar = &pVarStore->paVars[pThis->idxNext];
     
    10111345            pszName  = pVar->pszName;
    10121346            cbName   = strlen(pszName) + 1;
    1013             cbObject = RT_LE2H_U32(pVar->VarHdr.cbData);
     1347            cbObject = pVar->cbData;
    10141348            pTimeSpec = &pVar->Time;
     1349            if (pThis->enmType == RTEFIVARSTOREDIRTYPE_RAW)
     1350                fIsDir = true;
    10151351            break;
    10161352        }
     
    10361372            pszName  = pVar->pszName;
    10371373            cbName   = strlen(pszName) + 1;
    1038             cbObject = RT_LE2H_U32(pVar->VarHdr.cbData);
     1374            cbObject = pVar->cbData;
     1375            pTimeSpec = &pVar->Time;
     1376            break;
     1377        }
     1378        case RTEFIVARSTOREDIRTYPE_RAW_ENTRY:
     1379        {
     1380            PCRTEFIVARSTOREFILERAWENTRY pEntry = &g_aRawFiles[pThis->idxNext];
     1381            PRTEFIVAR                   pVar   = &pVarStore->paVars[pThis->idVar];
     1382
     1383            if (pThis->idxNext + 1 == RT_ELEMENTS(g_aRawFiles))
     1384                fNoMoreFiles = true;
     1385            pszName  = pEntry->pszName;
     1386            cbName   = strlen(pszName) + 1;
     1387            cbObject = pEntry->cbObject;
     1388            if (!cbObject)
     1389                cbObject = pVar->cbData;
    10391390            pTimeSpec = &pVar->Time;
    10401391            break;
     
    11111462
    11121463
    1113 static int rtEfiVarStore_NewDirByType(PRTEFIVARSTORE pThis, RTEFIVARSTOREDIRTYPE enmDirType, PRTEFIGUID pGuid, PRTVFSOBJ phVfsObj)
     1464static int rtEfiVarStore_NewDirByType(PRTEFIVARSTORE pThis, RTEFIVARSTOREDIRTYPE enmDirType,
     1465                                      PRTEFIGUID pGuid, uint32_t idVar, PRTVFSOBJ phVfsObj)
    11141466{
    11151467    RTVFSDIR hVfsDir;
     
    11231475        pDir->pVarStore = pThis;
    11241476        pDir->pGuid     = pGuid;
     1477        pDir->idVar     = idVar;
    11251478        RTTimeNow(&pDir->Time);
    11261479
     
    11481501{
    11491502    PRTEFIVARSTORE pThis = (PRTEFIVARSTORE)pvThis;
     1503
     1504    /* Write the variable store if in read/write mode. */
     1505    if (!(pThis->fMntFlags & RTVFSMNT_F_READ_ONLY))
     1506    {
     1507        int rc = rtEfiVarStore_Flush(pThis);
     1508        if (RT_FAILURE(rc))
     1509            return rc;
     1510    }
    11501511
    11511512    /*
     
    14291790    pVar->offVarHdr  = offVar;
    14301791    pVar->offVarData = offVar + sizeof(VarHdr) + RT_LE2H_U32(VarHdr.cbName);
    1431     memcpy(&pVar->VarHdr, &VarHdr, sizeof(VarHdr));
     1792    pVar->fAttr      = RT_LE2H_U32(VarHdr.fAttr);
     1793    pVar->cMonotonic = RT_LE2H_U64(VarHdr.cMonotonic);
     1794    pVar->idPubKey   = RT_LE2H_U32(VarHdr.idPubKey);
     1795    pVar->cbData     = RT_LE2H_U32(VarHdr.cbData);
     1796    memcpy(&pVar->EfiTimestamp, &VarHdr.Timestamp, sizeof(VarHdr.Timestamp));
     1797
    14321798    if (VarHdr.Timestamp.u8Month)
    14331799        RTEfiTimeToTimeSpec(&pVar->Time, &VarHdr.Timestamp);
     
    16662032            size_t cbThisWrite = RT_MIN(sizeof(abFF), offEnd - offStart);
    16672033            rc = RTVfsFileWriteAt(hVfsFile, offStart, &abFF[0], cbThisWrite, NULL);
     2034            offStart += cbThisWrite;
    16682035        }
    16692036    }
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