VirtualBox

Changeset 99943 in vbox


Ignore:
Timestamp:
May 23, 2023 8:34:46 PM (20 months ago)
Author:
vboxsync
Message:

Devices/Misc/DevFlashCFI: Add support for the NVRAM VFS interface, bugref:10434

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Misc/DevFlashCFI.cpp

    r99542 r99943  
    4141#include <iprt/string.h>
    4242#include <iprt/file.h>
     43#include <iprt/uuid.h>
    4344
    4445#include "VBoxDD.h"
     
    8081/** @} */
    8182
     83/** The namespace the NVRAM content is stored under (historical reasons). */
     84#define FLASH_CFI_VFS_NAMESPACE                 "efi"
     85
    8286
    8387/*********************************************************************************************************************************
     
    118122    /** The handle to the MMIO region. */
    119123    IOMMMIOHANDLE           hMmio;
     124
     125    /** The offset of the block to write. */
     126    uint32_t                offBlock;
     127    /** Number of bytes to write. */
     128    uint32_t                cbWrite;
     129    /** The word buffer for the buffered program command (32 16-bit words for each emulated chip). */
     130    uint8_t                 abProgramBuf[2 * 32 * sizeof(uint16_t)];
     131
     132    /**
     133     * NVRAM port - LUN\#0.
     134     */
     135    struct
     136    {
     137        /** The base interface we provide the NVRAM driver. */
     138        PDMIBASE            IBase;
     139        /** The NVRAM driver base interface. */
     140        PPDMIBASE           pDrvBase;
     141        /** The VFS interface of the driver below for NVRAM state loading and storing. */
     142        PPDMIVFSCONNECTOR   pDrvVfs;
     143    } Lun0;
    120144} DEVFLASHCFI;
    121145/** Pointer to the Flash device state. */
     
    158182            case FLASH_CFI_CMD_BUFFERED_PROGRAM_SETUP:
    159183                Assert(pThis->bStatus & FLASH_CFI_SR_PROGRAM_ERASE);
    160                 pThis->u16Cmd = u32Val;
     184                pThis->u16Cmd   = u32Val;
     185                pThis->offBlock = (uint32_t)off;
    161186                pThis->cBusCycle++;
    162187                break;
     
    178203                pThis->u16Cmd = FLASH_CFI_CMD_READ_STATUS_REG;
    179204                pThis->cBusCycle = 0;
     205                memset(pThis->pbFlash + off, 0xff, RT_MIN(pThis->cbFlashSize - off, pThis->cbBlockSize));
    180206                break;
    181207            }
     
    183209            {
    184210                /* Receives the number of words to be transfered. */
    185                 pThis->cWordsTransfered = u32Val & 0xffff;
    186                 pThis->cBusCycle++;
     211                pThis->cWordsTransfered = (u32Val & 0xffff) + 1;
     212                pThis->cbWrite = pThis->cWordsTransfered * 2 * sizeof(uint16_t);
     213                if (pThis->cbWrite <= sizeof(pThis->abProgramBuf))
     214                    pThis->cBusCycle++;
     215                else
     216                    AssertReleaseFailed();
    187217                break;
    188218            }
     
    201231                    if ((u32Val & 0xffff) == FLASH_CFI_CMD_BUFFERED_PROGRAM_CONFIRM)
    202232                    {
    203                         /** @todo Write out data to flash. */
     233                        if (pThis->offBlock + pThis->cbWrite <= pThis->cbFlashSize)
     234                            memcpy(pThis->pbFlash + pThis->offBlock, &pThis->abProgramBuf[0], pThis->cbWrite);
    204235                        /* Reset to read array. */
    205236                        pThis->cBusCycle = 0;
    206237                        pThis->u16Cmd    = FLASH_CFI_CMD_ARRAY_READ;
    207238                    }
     239                    else
     240                        AssertReleaseFailed();
    208241                }
    209242                else
     243                {
     244                    if (   off >= pThis->offBlock
     245                        && (off + cb >= pThis->offBlock)
     246                        && ((off + cb) - pThis->offBlock) <= sizeof(pThis->abProgramBuf))
     247                        memcpy(&pThis->abProgramBuf[off - pThis->offBlock], pv, cb);
     248                    else
     249                        AssertReleaseFailed();
    210250                    pThis->cWordsTransfered--;
     251                }
    211252                break;
    212253            }
     
    265306
    266307
     308/**
     309 * @copydoc(PDMIBASE::pfnQueryInterface)
     310 */
     311static DECLCALLBACK(void *) flashR3QueryInterface(PPDMIBASE pInterface, const char *pszIID)
     312{
     313    LogFlowFunc(("ENTER: pIBase=%p pszIID=%p\n", pInterface, pszIID));
     314    PDEVFLASHCFI pThis = RT_FROM_MEMBER(pInterface, DEVFLASHCFI, Lun0.IBase);
     315
     316    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->Lun0.IBase);
     317    return NULL;
     318}
     319
     320
    267321#if 0 /** @todo Later */
    268322/**
     
    305359    pThis->bStatus   = FLASH_CFI_SR_PROGRAM_ERASE; /* Prgram/Erase controller is inactive. */
    306360    pThis->cBusCycle = 0;
     361}
     362
     363
     364/**
     365 * @interface_method_impl{PDMDEVREG,pfnPowerOff}
     366 */
     367static DECLCALLBACK(void) flashR3PowerOff(PPDMDEVINS pDevIns)
     368{
     369    PDEVFLASHCFI pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASHCFI);
     370
     371    if (pThis->Lun0.pDrvVfs)
     372    {
     373        AssertPtr(pThis->pszFlashFile);
     374        int rc = pThis->Lun0.pDrvVfs->pfnWriteAll(pThis->Lun0.pDrvVfs, FLASH_CFI_VFS_NAMESPACE, pThis->pszFlashFile,
     375                                                  pThis->pbFlash, pThis->cbFlashSize);
     376        if (RT_FAILURE(rc))
     377            LogRel(("EFI: Failed to save flash file to NVRAM store: %Rrc\n", rc));
     378    }
     379    else if (pThis->pszFlashFile)
     380    {
     381        RTFILE hFlashFile = NIL_RTFILE;
     382
     383        int rc = RTFileOpen(&hFlashFile, pThis->pszFlashFile, RTFILE_O_READWRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE);
     384        if (RT_SUCCESS(rc))
     385        {
     386            rc = RTFileWrite(hFlashFile, pThis->pbFlash, pThis->cbFlashSize, NULL);
     387            RTFileClose(hFlashFile);
     388            if (RT_FAILURE(rc))
     389                PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to write flash file"));
     390        }
     391        else
     392            PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to open flash file"));
     393    }
    307394}
    308395
     
    353440
    354441    Assert(iInstance == 0); RT_NOREF1(iInstance);
     442
     443    /*
     444     * Initalize the basic variables so that the destructor always works.
     445     */
     446    pThis->Lun0.IBase.pfnQueryInterface = flashR3QueryInterface;
     447
    355448
    356449    /*
     
    376469
    377470    /* The default flash device size is 128K. */
    378     uint32_t cbFlash = 0;
    379     rc = pHlp->pfnCFGMQueryU32Def(pCfg, "Size", &cbFlash, 128 * _1K);
     471    uint64_t cbFlash = 0;
     472    rc = pHlp->pfnCFGMQueryU64Def(pCfg, "Size", &cbFlash, 128 * _1K);
    380473    if (RT_FAILURE(rc))
    381474        return PDMDEV_SET_ERROR(pDevIns, rc,
     
    412505    flashR3Reset(pDevIns);
    413506
    414     RTFILE hFlashFile = NIL_RTFILE;
    415     rc = RTFileOpen(&hFlashFile, pThis->pszFlashFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
    416     if (RT_FAILURE(rc))
    417         return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to open flash file"));
    418 
    419     size_t cbRead = 0;
    420     rc = RTFileRead(hFlashFile, pThis->pbFlash, pThis->cbFlashSize, &cbRead);
    421     RTFileClose(hFlashFile);
    422     if (RT_FAILURE(rc))
    423         return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to read flash file"));
    424     LogRel(("flash-cfi#%u: Read %zu bytes from file (asked for %u)\n.", cbRead, pThis->cbFlashSize, iInstance));
    425 
     507    /*
     508     * NVRAM storage.
     509     */
     510    rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->Lun0.IBase, &pThis->Lun0.pDrvBase, "NvramStorage");
     511    if (RT_SUCCESS(rc))
     512    {
     513        pThis->Lun0.pDrvVfs = PDMIBASE_QUERY_INTERFACE(pThis->Lun0.pDrvBase, PDMIVFSCONNECTOR);
     514        if (!pThis->Lun0.pDrvVfs)
     515            return PDMDevHlpVMSetError(pDevIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS, N_("NVRAM storage driver is missing VFS interface below"));
     516    }
     517    else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
     518        rc = VINF_SUCCESS; /* Missing driver is no error condition. */
     519    else
     520        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("Can't attach Nvram Storage driver"));
     521
     522    if (pThis->Lun0.pDrvVfs)
     523    {
     524        AssertPtr(pThis->pszFlashFile);
     525        rc = pThis->Lun0.pDrvVfs->pfnQuerySize(pThis->Lun0.pDrvVfs, FLASH_CFI_VFS_NAMESPACE, pThis->pszFlashFile, &cbFlash);
     526        if (RT_SUCCESS(rc))
     527        {
     528            if (cbFlash <= pThis->cbFlashSize)
     529                rc = pThis->Lun0.pDrvVfs->pfnReadAll(pThis->Lun0.pDrvVfs, FLASH_CFI_VFS_NAMESPACE, pThis->pszFlashFile,
     530                                                     pThis->pbFlash, pThis->cbFlashSize);
     531            else
     532                return PDMDEV_SET_ERROR(pDevIns, VERR_BUFFER_OVERFLOW, N_("Configured flash size is too small to fit the saved NVRAM content"));
     533        }
     534    }
     535    else if (pThis->pszFlashFile)
     536    {
     537        RTFILE hFlashFile = NIL_RTFILE;
     538        rc = RTFileOpen(&hFlashFile, pThis->pszFlashFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     539        if (RT_FAILURE(rc))
     540            return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to open flash file"));
     541
     542        size_t cbRead = 0;
     543        rc = RTFileRead(hFlashFile, pThis->pbFlash, pThis->cbFlashSize, &cbRead);
     544        RTFileClose(hFlashFile);
     545        if (RT_FAILURE(rc))
     546            return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to read flash file"));
     547
     548        LogRel(("flash-cfi#%u: Read %zu bytes from file (asked for %u)\n.", cbRead, pThis->cbFlashSize, iInstance));
     549    }
    426550
    427551    /*
     
    479603    /* .pfnQueryInterface = */      NULL,
    480604    /* .pfnInitComplete = */        NULL,
    481     /* .pfnPowerOff = */            NULL,
     605    /* .pfnPowerOff = */            flashR3PowerOff,
    482606    /* .pfnSoftReset = */           NULL,
    483607    /* .pfnReserved0 = */           NULL,
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