VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/DevFlash.cpp@ 106061

Last change on this file since 106061 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.3 KB
Line 
1/* $Id: DevFlash.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * DevFlash - A simple Flash device
4 *
5 * A simple non-volatile byte-wide (x8) memory device modeled after Intel 28F008
6 * FlashFile. See 28F008SA datasheet, Intel order number 290429-007.
7 *
8 * Implemented as an MMIO device attached directly to the CPU, not behind any
9 * bus. Typically mapped as part of the firmware image.
10 */
11
12/*
13 * Copyright (C) 2018-2024 Oracle and/or its affiliates.
14 *
15 * This file is part of VirtualBox base platform packages, as
16 * available from https://www.virtualbox.org.
17 *
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation, in version 3 of the
21 * License.
22 *
23 * This program is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, see <https://www.gnu.org/licenses>.
30 *
31 * SPDX-License-Identifier: GPL-3.0-only
32 */
33
34
35/*********************************************************************************************************************************
36* Header Files *
37*********************************************************************************************************************************/
38#define LOG_GROUP LOG_GROUP_DEV_FLASH
39#include <VBox/vmm/pdmdev.h>
40#include <VBox/log.h>
41#include <VBox/err.h>
42#include <iprt/assert.h>
43#include <iprt/string.h>
44#include <iprt/file.h>
45
46#include "VBoxDD.h"
47#include "FlashCore.h"
48
49
50
51/*********************************************************************************************************************************
52* Structures and Typedefs *
53*********************************************************************************************************************************/
54/**
55 * The flash device, shared state.
56 */
57typedef struct DEVFLASH
58{
59 /** The flash core device instance.*/
60 FLASHCORE Core;
61 /** The guest physical memory base address. */
62 RTGCPHYS GCPhysFlashBase;
63 /** The handle to the MMIO region. */
64 IOMMMIOHANDLE hMmio;
65} DEVFLASH;
66/** Pointer to the Flash device state. */
67typedef DEVFLASH *PDEVFLASH;
68
69/**
70 * The flash device, ring-3 state.
71 */
72typedef struct DEVFLASHR3
73{
74 /** The file conaining the flash content. */
75 char *pszFlashFile;
76} DEVFLASHR3;
77/** Pointer to the ring-3 Flash device state. */
78typedef DEVFLASHR3 *PDEVFLASHR3;
79
80/**
81 * The flash device, ring-0 state.
82 */
83typedef struct DEVFLASHR0
84{
85 /** Dummy, no R0 only component so far. */
86 uint8_t bDummy;
87} DEVFLASHR0;
88/** Pointer to the ring-3 Flash device state. */
89typedef DEVFLASHR0 *PDEVFLASHR0;
90
91/** The serial device state for the current context. */
92typedef CTX_SUFF(DEVFLASH) DEVFLASHCC;
93/** Pointer to the serial device state for the current context. */
94typedef CTX_SUFF(PDEVFLASH) PDEVFLASHCC;
95
96
97#ifndef VBOX_DEVICE_STRUCT_TESTCASE
98
99
100/**
101 * @callback_method_impl{FNIOMMMIONEWWRITE, Flash memory write}
102 */
103static DECLCALLBACK(VBOXSTRICTRC) flashMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
104{
105 PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH);
106 RT_NOREF1(pvUser);
107 return flashWrite(&pThis->Core, off, pv, cb);
108}
109
110
111/**
112 * @callback_method_impl{FNIOMMMIONEWREAD, Flash memory read}
113 */
114static DECLCALLBACK(VBOXSTRICTRC) flashMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb)
115{
116 PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH);
117 RT_NOREF1(pvUser);
118 return flashRead(&pThis->Core, off, pv, cb);
119}
120
121#ifdef IN_RING3
122
123/**
124 * @callback_method_impl{FNSSMDEVSAVEEXEC}
125 */
126static DECLCALLBACK(int) flashSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
127{
128 PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH);
129 return flashR3SaveExec(&pThis->Core, pDevIns, pSSM);
130}
131
132
133/**
134 * @callback_method_impl{FNSSMDEVLOADEXEC}
135 */
136static DECLCALLBACK(int) flashLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
137{
138 PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH);
139 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
140
141 /* Fend off unsupported versions. */
142 if (uVersion != FLASH_SAVED_STATE_VERSION)
143 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
144
145 return flashR3LoadExec(&pThis->Core, pDevIns, pSSM);
146}
147
148
149/**
150 * @interface_method_impl{PDMDEVREG,pfnReset}
151 */
152static DECLCALLBACK(void) flashReset(PPDMDEVINS pDevIns)
153{
154 PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH);
155 flashR3Reset(&pThis->Core);
156}
157
158
159/**
160 * @interface_method_impl{PDMDEVREG,pfnDestruct}
161 */
162static DECLCALLBACK(int) flashDestruct(PPDMDEVINS pDevIns)
163{
164 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
165 PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH);
166 PDEVFLASHR3 pThisR3 = PDMDEVINS_2_DATA_CC(pDevIns, PDEVFLASHR3);
167
168 if (pThisR3->pszFlashFile)
169 {
170 int rc = flashR3SaveToFile(&pThis->Core, pDevIns, pThisR3->pszFlashFile);
171 if (RT_FAILURE(rc))
172 LogRel(("Flash: Failed to save flash file: %Rrc\n", rc));
173
174 PDMDevHlpMMHeapFree(pDevIns, pThisR3->pszFlashFile);
175 pThisR3->pszFlashFile = NULL;
176 }
177
178 flashR3Destruct(&pThis->Core, pDevIns);
179 return VINF_SUCCESS;
180}
181
182
183/**
184 * @interface_method_impl{PDMDEVREG,pfnConstruct}
185 */
186static DECLCALLBACK(int) flashConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
187{
188 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
189 PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH);
190 PDEVFLASHR3 pThisR3 = PDMDEVINS_2_DATA_CC(pDevIns, PDEVFLASHR3);
191 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
192
193 Assert(iInstance == 0); RT_NOREF1(iInstance);
194
195 /*
196 * Validate configuration.
197 */
198 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "DeviceId|BaseAddress|Size|BlockSize|FlashFile", "");
199
200 /*
201 * Read configuration.
202 */
203
204 /* The default device ID is Intel 28F800SA. */
205 uint16_t u16FlashId = 0;
206 int rc = pHlp->pfnCFGMQueryU16Def(pCfg, "DeviceId", &u16FlashId, 0xA289);
207 if (RT_FAILURE(rc))
208 return PDMDEV_SET_ERROR(pDevIns, rc,
209 N_("Configuration error: Querying \"DeviceId\" as an integer failed"));
210
211 /* The default base address is 2MB below 4GB. */
212 rc = pHlp->pfnCFGMQueryU64Def(pCfg, "BaseAddress", &pThis->GCPhysFlashBase, 0xFFE00000);
213 if (RT_FAILURE(rc))
214 return PDMDEV_SET_ERROR(pDevIns, rc,
215 N_("Configuration error: Querying \"BaseAddress\" as an integer failed"));
216
217 /* The default flash device size is 128K. */
218 uint32_t cbFlash = 0;
219 rc = pHlp->pfnCFGMQueryU32Def(pCfg, "Size", &cbFlash, 128 * _1K);
220 if (RT_FAILURE(rc))
221 return PDMDEV_SET_ERROR(pDevIns, rc,
222 N_("Configuration error: Querying \"Size\" as an integer failed"));
223
224 /* The default flash device block size is 4K. */
225 uint16_t cbBlock = 0;
226 rc = pHlp->pfnCFGMQueryU16Def(pCfg, "BlockSize", &cbBlock, _4K);
227 if (RT_FAILURE(rc))
228 return PDMDEV_SET_ERROR(pDevIns, rc,
229 N_("Configuration error: Querying \"BlockSize\" as an integer failed"));
230
231 rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "FlashFile", &pThisR3->pszFlashFile);
232 if (RT_FAILURE(rc))
233 return PDMDEV_SET_ERROR(pDevIns, rc,
234 N_("Configuration error: Querying \"FlashFile\" as a string failed"));
235
236 /*
237 * Initialize the flash core.
238 */
239 rc = flashR3Init(&pThis->Core, pDevIns, u16FlashId, cbFlash, cbBlock);
240 if (RT_FAILURE(rc))
241 return PDMDEV_SET_ERROR(pDevIns, rc,
242 N_("Flash: Failed to initialize core flash device"));
243
244 /* Try to load the flash content from file. */
245 rc = flashR3LoadFromFile(&pThis->Core, pDevIns, pThisR3->pszFlashFile);
246 if (RT_FAILURE(rc))
247 return PDMDEV_SET_ERROR(pDevIns, rc,
248 N_("Flash: Failed to load flash content from given file"));
249
250 /*
251 * Register MMIO region.
252 */
253 rc = PDMDevHlpMmioCreateExAndMap(pDevIns, pThis->GCPhysFlashBase, cbFlash,
254 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, NULL, UINT32_MAX,
255 flashMMIOWrite, flashMMIORead, NULL, NULL, "Flash Memory", &pThis->hMmio);
256 AssertRCReturn(rc, rc);
257 LogRel(("Registered %uKB flash at %RGp\n", pThis->Core.cbFlashSize / _1K, pThis->GCPhysFlashBase));
258
259 /*
260 * Register saved state.
261 */
262 rc = PDMDevHlpSSMRegister(pDevIns, FLASH_SAVED_STATE_VERSION, sizeof(*pThis), flashSaveExec, flashLoadExec);
263 AssertRCReturn(rc, rc);
264
265 return VINF_SUCCESS;
266}
267
268#else /* !IN_RING3 */
269
270/**
271 * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
272 */
273static DECLCALLBACK(int) flashRZConstruct(PPDMDEVINS pDevIns)
274{
275 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
276 PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH);
277
278# if 1
279 int rc = PDMDevHlpMmioSetUpContext(pDevIns, pThis->hMmio, flashMMIOWrite, flashMMIORead, NULL /*pvUser*/);
280 AssertRCReturn(rc, rc);
281# else
282 RT_NOREF(pDevIns, pThis); (void)&flashMMIOWrite; (void)&flashMMIORead;
283# endif
284
285 return VINF_SUCCESS;
286}
287
288#endif /* !IN_RING3 */
289
290/**
291 * The device registration structure.
292 */
293const PDMDEVREG g_DeviceFlash =
294{
295 /* .u32Version = */ PDM_DEVREG_VERSION,
296 /* .uReserved0 = */ 0,
297 /* .szName = */ "flash",
298 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE,
299 /* .fClass = */ PDM_DEVREG_CLASS_ARCH,
300 /* .cMaxInstances = */ 1,
301 /* .uSharedVersion = */ 42,
302 /* .cbInstanceShared = */ sizeof(DEVFLASH),
303 /* .cbInstanceCC = */ sizeof(DEVFLASHCC),
304 /* .cbInstanceRC = */ 0,
305 /* .cMaxPciDevices = */ 0,
306 /* .cMaxMsixVectors = */ 0,
307 /* .pszDescription = */ "Flash Memory Device",
308#if defined(IN_RING3)
309 /* .pszRCMod = */ "VBoxDDRC.rc",
310 /* .pszR0Mod = */ "VBoxDDR0.r0",
311 /* .pfnConstruct = */ flashConstruct,
312 /* .pfnDestruct = */ flashDestruct,
313 /* .pfnRelocate = */ NULL,
314 /* .pfnMemSetup = */ NULL,
315 /* .pfnPowerOn = */ NULL,
316 /* .pfnReset = */ flashReset,
317 /* .pfnSuspend = */ NULL,
318 /* .pfnResume = */ NULL,
319 /* .pfnAttach = */ NULL,
320 /* .pfnDetach = */ NULL,
321 /* .pfnQueryInterface = */ NULL,
322 /* .pfnInitComplete = */ NULL,
323 /* .pfnPowerOff = */ NULL,
324 /* .pfnSoftReset = */ NULL,
325 /* .pfnReserved0 = */ NULL,
326 /* .pfnReserved1 = */ NULL,
327 /* .pfnReserved2 = */ NULL,
328 /* .pfnReserved3 = */ NULL,
329 /* .pfnReserved4 = */ NULL,
330 /* .pfnReserved5 = */ NULL,
331 /* .pfnReserved6 = */ NULL,
332 /* .pfnReserved7 = */ NULL,
333#elif defined(IN_RING0)
334 /* .pfnEarlyConstruct = */ NULL,
335 /* .pfnConstruct = */ flashRZConstruct,
336 /* .pfnDestruct = */ NULL,
337 /* .pfnFinalDestruct = */ NULL,
338 /* .pfnRequest = */ NULL,
339 /* .pfnReserved0 = */ NULL,
340 /* .pfnReserved1 = */ NULL,
341 /* .pfnReserved2 = */ NULL,
342 /* .pfnReserved3 = */ NULL,
343 /* .pfnReserved4 = */ NULL,
344 /* .pfnReserved5 = */ NULL,
345 /* .pfnReserved6 = */ NULL,
346 /* .pfnReserved7 = */ NULL,
347#elif defined(IN_RC)
348 /* .pfnConstruct = */ NULL,
349 /* .pfnReserved0 = */ flashRZConstruct,
350 /* .pfnReserved1 = */ NULL,
351 /* .pfnReserved2 = */ NULL,
352 /* .pfnReserved3 = */ NULL,
353 /* .pfnReserved4 = */ NULL,
354 /* .pfnReserved5 = */ NULL,
355 /* .pfnReserved6 = */ NULL,
356 /* .pfnReserved7 = */ NULL,
357#else
358# error "Not in IN_RING3, IN_RING0 or IN_RC!"
359#endif
360 /* .u32VersionEnd = */ PDM_DEVREG_VERSION
361};
362
363#endif /* VBOX_DEVICE_STRUCT_TESTCASE */
Note: See TracBrowser for help on using the repository browser.

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