From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- src/VBox/Devices/EFI/DevFlash.cpp | 347 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100644 src/VBox/Devices/EFI/DevFlash.cpp (limited to 'src/VBox/Devices/EFI/DevFlash.cpp') diff --git a/src/VBox/Devices/EFI/DevFlash.cpp b/src/VBox/Devices/EFI/DevFlash.cpp new file mode 100644 index 00000000..13bfb382 --- /dev/null +++ b/src/VBox/Devices/EFI/DevFlash.cpp @@ -0,0 +1,347 @@ +/* $Id: DevFlash.cpp $ */ +/** @file + * DevFlash - A simple Flash device + * + * A simple non-volatile byte-wide (x8) memory device modeled after Intel 28F008 + * FlashFile. See 28F008SA datasheet, Intel order number 290429-007. + * + * Implemented as an MMIO device attached directly to the CPU, not behind any + * bus. Typically mapped as part of the firmware image. + */ + +/* + * Copyright (C) 2018-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#define LOG_GROUP LOG_GROUP_DEV_FLASH +#include +#include +#include +#include +#include +#include + +#include "VBoxDD.h" +#include "FlashCore.h" + + + +/********************************************************************************************************************************* +* Structures and Typedefs * +*********************************************************************************************************************************/ +/** + * The flash device, shared state. + */ +typedef struct DEVFLASH +{ + /** The flash core device instance.*/ + FLASHCORE Core; + /** The guest physical memory base address. */ + RTGCPHYS GCPhysFlashBase; + /** The handle to the MMIO region. */ + IOMMMIOHANDLE hMmio; +} DEVFLASH; +/** Pointer to the Flash device state. */ +typedef DEVFLASH *PDEVFLASH; + +/** + * The flash device, ring-3 state. + */ +typedef struct DEVFLASHR3 +{ + /** The file conaining the flash content. */ + char *pszFlashFile; +} DEVFLASHR3; +/** Pointer to the ring-3 Flash device state. */ +typedef DEVFLASHR3 *PDEVFLASHR3; + + +#ifndef VBOX_DEVICE_STRUCT_TESTCASE + + +/** + * @callback_method_impl{FNIOMMMIONEWWRITE, Flash memory write} + */ +static DECLCALLBACK(VBOXSTRICTRC) flashMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb) +{ + PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH); + RT_NOREF1(pvUser); + return flashWrite(&pThis->Core, off, pv, cb); +} + + +/** + * @callback_method_impl{FNIOMMMIONEWREAD, Flash memory read} + */ +static DECLCALLBACK(VBOXSTRICTRC) flashMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb) +{ + PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH); + RT_NOREF1(pvUser); + return flashRead(&pThis->Core, off, pv, cb); +} + +#ifdef IN_RING3 + +/** + * @callback_method_impl{FNSSMDEVSAVEEXEC} + */ +static DECLCALLBACK(int) flashSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) +{ + PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH); + return flashR3SaveExec(&pThis->Core, pDevIns, pSSM); +} + + +/** + * @callback_method_impl{FNSSMDEVLOADEXEC} + */ +static DECLCALLBACK(int) flashLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) +{ + PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH); + Assert(uPass == SSM_PASS_FINAL); NOREF(uPass); + + /* Fend off unsupported versions. */ + if (uVersion != FLASH_SAVED_STATE_VERSION) + return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; + + return flashR3LoadExec(&pThis->Core, pDevIns, pSSM); +} + + +/** + * @interface_method_impl{PDMDEVREG,pfnReset} + */ +static DECLCALLBACK(void) flashReset(PPDMDEVINS pDevIns) +{ + PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH); + flashR3Reset(&pThis->Core); +} + + +/** + * @interface_method_impl{PDMDEVREG,pfnDestruct} + */ +static DECLCALLBACK(int) flashDestruct(PPDMDEVINS pDevIns) +{ + PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns); + PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH); + PDEVFLASHR3 pThisR3 = PDMDEVINS_2_DATA_CC(pDevIns, PDEVFLASHR3); + + if (pThisR3->pszFlashFile) + { + int rc = flashR3SaveToFile(&pThis->Core, pDevIns, pThisR3->pszFlashFile); + if (RT_FAILURE(rc)) + LogRel(("Flash: Failed to save flash file: %Rrc\n", rc)); + + PDMDevHlpMMHeapFree(pDevIns, pThisR3->pszFlashFile); + pThisR3->pszFlashFile = NULL; + } + + flashR3Destruct(&pThis->Core, pDevIns); + return VINF_SUCCESS; +} + + +/** + * @interface_method_impl{PDMDEVREG,pfnConstruct} + */ +static DECLCALLBACK(int) flashConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) +{ + PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); + PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH); + PDEVFLASHR3 pThisR3 = PDMDEVINS_2_DATA_CC(pDevIns, PDEVFLASHR3); + PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; + + Assert(iInstance == 0); RT_NOREF1(iInstance); + + /* + * Validate configuration. + */ + PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "DeviceId|BaseAddress|Size|BlockSize|FlashFile", ""); + + /* + * Read configuration. + */ + + /* The default device ID is Intel 28F800SA. */ + uint16_t u16FlashId = 0; + int rc = pHlp->pfnCFGMQueryU16Def(pCfg, "DeviceId", &u16FlashId, 0xA289); + if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, + N_("Configuration error: Querying \"DeviceId\" as an integer failed")); + + /* The default base address is 2MB below 4GB. */ + rc = pHlp->pfnCFGMQueryU64Def(pCfg, "BaseAddress", &pThis->GCPhysFlashBase, 0xFFE00000); + if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, + N_("Configuration error: Querying \"BaseAddress\" as an integer failed")); + + /* The default flash device size is 128K. */ + uint32_t cbFlash = 0; + rc = pHlp->pfnCFGMQueryU32Def(pCfg, "Size", &cbFlash, 128 * _1K); + if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, + N_("Configuration error: Querying \"Size\" as an integer failed")); + + /* The default flash device block size is 4K. */ + uint16_t cbBlock = 0; + rc = pHlp->pfnCFGMQueryU16Def(pCfg, "BlockSize", &cbBlock, _4K); + if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, + N_("Configuration error: Querying \"BlockSize\" as an integer failed")); + + rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "FlashFile", &pThisR3->pszFlashFile); + if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, + N_("Configuration error: Querying \"FlashFile\" as a string failed")); + + /* + * Initialize the flash core. + */ + rc = flashR3Init(&pThis->Core, pDevIns, u16FlashId, cbFlash, cbBlock); + if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, + N_("Flash: Failed to initialize core flash device")); + + /* Try to load the flash content from file. */ + rc = flashR3LoadFromFile(&pThis->Core, pDevIns, pThisR3->pszFlashFile); + if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, + N_("Flash: Failed to load flash content from given file")); + + /* + * Register MMIO region. + */ + rc = PDMDevHlpMmioCreateExAndMap(pDevIns, pThis->GCPhysFlashBase, cbFlash, + IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, NULL, UINT32_MAX, + flashMMIOWrite, flashMMIORead, NULL, NULL, "Flash Memory", &pThis->hMmio); + AssertRCReturn(rc, rc); + LogRel(("Registered %uKB flash at %RGp\n", pThis->Core.cbFlashSize / _1K, pThis->GCPhysFlashBase)); + + /* + * Register saved state. + */ + rc = PDMDevHlpSSMRegister(pDevIns, FLASH_SAVED_STATE_VERSION, sizeof(*pThis), flashSaveExec, flashLoadExec); + AssertRCReturn(rc, rc); + + return VINF_SUCCESS; +} + +#else /* !IN_RING3 */ + +/** + * @callback_method_impl{PDMDEVREGR0,pfnConstruct} + */ +static DECLCALLBACK(int) flashRZConstruct(PPDMDEVINS pDevIns) +{ + PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); + PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH); + +# if 1 + int rc = PDMDevHlpMmioSetUpContext(pDevIns, pThis->hMmio, flashMMIOWrite, flashMMIORead, NULL /*pvUser*/); + AssertRCReturn(rc, rc); +# else + RT_NOREF(pDevIns, pThis); (void)&flashMMIOWrite; (void)&flashMMIORead; +# endif + + return VINF_SUCCESS; +} + +#endif /* !IN_RING3 */ + +/** + * The device registration structure. + */ +const PDMDEVREG g_DeviceFlash = +{ + /* .u32Version = */ PDM_DEVREG_VERSION, + /* .uReserved0 = */ 0, + /* .szName = */ "flash", + /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE, + /* .fClass = */ PDM_DEVREG_CLASS_ARCH, + /* .cMaxInstances = */ 1, + /* .uSharedVersion = */ 42, + /* .cbInstanceShared = */ sizeof(DEVFLASH), + /* .cbInstanceCC = */ 0, + /* .cbInstanceRC = */ 0, + /* .cMaxPciDevices = */ 0, + /* .cMaxMsixVectors = */ 0, + /* .pszDescription = */ "Flash Memory Device", +#if defined(IN_RING3) + /* .pszRCMod = */ "VBoxDDRC.rc", + /* .pszR0Mod = */ "VBoxDDR0.r0", + /* .pfnConstruct = */ flashConstruct, + /* .pfnDestruct = */ flashDestruct, + /* .pfnRelocate = */ NULL, + /* .pfnMemSetup = */ NULL, + /* .pfnPowerOn = */ NULL, + /* .pfnReset = */ flashReset, + /* .pfnSuspend = */ NULL, + /* .pfnResume = */ NULL, + /* .pfnAttach = */ NULL, + /* .pfnDetach = */ NULL, + /* .pfnQueryInterface = */ NULL, + /* .pfnInitComplete = */ NULL, + /* .pfnPowerOff = */ NULL, + /* .pfnSoftReset = */ NULL, + /* .pfnReserved0 = */ NULL, + /* .pfnReserved1 = */ NULL, + /* .pfnReserved2 = */ NULL, + /* .pfnReserved3 = */ NULL, + /* .pfnReserved4 = */ NULL, + /* .pfnReserved5 = */ NULL, + /* .pfnReserved6 = */ NULL, + /* .pfnReserved7 = */ NULL, +#elif defined(IN_RING0) + /* .pfnEarlyConstruct = */ NULL, + /* .pfnConstruct = */ flashRZConstruct, + /* .pfnDestruct = */ NULL, + /* .pfnFinalDestruct = */ NULL, + /* .pfnRequest = */ NULL, + /* .pfnReserved0 = */ NULL, + /* .pfnReserved1 = */ NULL, + /* .pfnReserved2 = */ NULL, + /* .pfnReserved3 = */ NULL, + /* .pfnReserved4 = */ NULL, + /* .pfnReserved5 = */ NULL, + /* .pfnReserved6 = */ NULL, + /* .pfnReserved7 = */ NULL, +#elif defined(IN_RC) + /* .pfnConstruct = */ NULL, + /* .pfnReserved0 = */ flashRZConstruct, + /* .pfnReserved1 = */ NULL, + /* .pfnReserved2 = */ NULL, + /* .pfnReserved3 = */ NULL, + /* .pfnReserved4 = */ NULL, + /* .pfnReserved5 = */ NULL, + /* .pfnReserved6 = */ NULL, + /* .pfnReserved7 = */ NULL, +#else +# error "Not in IN_RING3, IN_RING0 or IN_RC!" +#endif + /* .u32VersionEnd = */ PDM_DEVREG_VERSION +}; + +#endif /* VBOX_DEVICE_STRUCT_TESTCASE */ -- cgit v1.2.3