VirtualBox

source: vbox/trunk/src/VBox/Devices/Misc/DevFlashCFI.cpp@ 100658

Last change on this file since 100658 was 99943, checked in by vboxsync, 18 months ago

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

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.4 KB
Line 
1/* $Id: DevFlashCFI.cpp 99943 2023-05-23 20:34:46Z vboxsync $ */
2/** @file
3 * DevFlashCFI - A simple Flash device implementing the Common Flash Interface
4 * using the sepc from https://ia803103.us.archive.org/30/items/m30l0r7000t0/m30l0r7000t0.pdf
5 *
6 * Implemented as an MMIO device attached directly to the CPU, not behind any
7 * bus. Typically mapped as part of the firmware image.
8 */
9
10/*
11 * Copyright (C) 2023 Oracle and/or its affiliates.
12 *
13 * This file is part of VirtualBox base platform packages, as
14 * available from https://www.virtualbox.org.
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation, in version 3 of the
19 * License.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, see <https://www.gnu.org/licenses>.
28 *
29 * SPDX-License-Identifier: GPL-3.0-only
30 */
31
32
33/*********************************************************************************************************************************
34* Header Files *
35*********************************************************************************************************************************/
36#define LOG_GROUP LOG_GROUP_DEV_FLASH
37#include <VBox/vmm/pdmdev.h>
38#include <VBox/log.h>
39#include <VBox/err.h>
40#include <iprt/assert.h>
41#include <iprt/string.h>
42#include <iprt/file.h>
43#include <iprt/uuid.h>
44
45#include "VBoxDD.h"
46
47
48/*********************************************************************************************************************************
49* Defined Constants And Macros *
50*********************************************************************************************************************************/
51/** @name CFI (Command User Interface) Commands.
52 * @{ */
53/** Block erase setup */
54#define FLASH_CFI_CMD_BLOCK_ERASE_SETUP 0x20
55/** Clear status register. */
56#define FLASH_CFI_CMD_CLEAR_STATUS_REG 0x50
57/** Read status register. */
58#define FLASH_CFI_CMD_READ_STATUS_REG 0x70
59/** Read status register. */
60#define FLASH_CFI_CMD_READ_DEVICE_ID 0x90
61/** Buffered program setup. */
62#define FLASH_CFI_CMD_BUFFERED_PROGRAM_SETUP 0xe8
63/** Buffered program setup. */
64#define FLASH_CFI_CMD_BUFFERED_PROGRAM_CONFIRM 0xd0
65/** Read from the flash array. */
66#define FLASH_CFI_CMD_ARRAY_READ 0xff
67/** @} */
68
69/** @name Status register bits.
70 * @{ */
71/** Bank Write/Multiple Word Program Status Bit. */
72#define FLASH_CFI_SR_BWS RT_BIT(0)
73/** Block Protection Status Bit. */
74#define FLASH_CFI_SR_BLOCK_PROTETION RT_BIT(1)
75#define FLASH_CFI_SR_PROGRAM_SUSPEND RT_BIT(2)
76#define FLASH_CFI_SR_VPP RT_BIT(3)
77#define FLASH_CFI_SR_PROGRAM RT_BIT(4)
78#define FLASH_CFI_SR_ERASE RT_BIT(5)
79#define FLASH_CFI_SR_ERASE_SUSPEND RT_BIT(6)
80#define FLASH_CFI_SR_PROGRAM_ERASE RT_BIT(7)
81/** @} */
82
83/** The namespace the NVRAM content is stored under (historical reasons). */
84#define FLASH_CFI_VFS_NAMESPACE "efi"
85
86
87/*********************************************************************************************************************************
88* Structures and Typedefs *
89*********************************************************************************************************************************/
90/**
91 * The flash device, shared state.
92 */
93typedef struct DEVFLASHCFI
94{
95 /** The current command. */
96 uint16_t u16Cmd;
97 /** The status register. */
98 uint8_t bStatus;
99 /** Current bus cycle. */
100 uint8_t cBusCycle;
101
102 uint8_t cWordsTransfered;
103
104 /** @name The following state does not change at runtime
105 * @{ */
106 /** When set, indicates the state was saved. */
107 bool fStateSaved;
108 /** Manufacturer (high byte) and device (low byte) ID. */
109 uint16_t u16FlashId;
110 /** The configured block size of the device. */
111 uint16_t cbBlockSize;
112 /** The actual flash memory data. */
113 R3PTRTYPE(uint8_t *) pbFlash;
114 /** The flash memory region size. */
115 uint32_t cbFlashSize;
116 /** @} */
117
118 /** The file conaining the flash content. */
119 char *pszFlashFile;
120 /** The guest physical memory base address. */
121 RTGCPHYS GCPhysFlashBase;
122 /** The handle to the MMIO region. */
123 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;
144} DEVFLASHCFI;
145/** Pointer to the Flash device state. */
146typedef DEVFLASHCFI *PDEVFLASHCFI;
147
148
149#ifndef VBOX_DEVICE_STRUCT_TESTCASE
150
151
152/**
153 * @callback_method_impl{FNIOMMMIONEWWRITE, Flash memory write}
154 */
155static DECLCALLBACK(VBOXSTRICTRC) flashMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
156{
157 PDEVFLASHCFI pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASHCFI);
158 RT_NOREF1(pvUser);
159
160 /** @todo For now we only emulate a x32 device using two x16 chips so the command must be send to both chips at the same time
161 * (and we don't support sending different commands to both devices). */
162 Assert(cb == sizeof(uint32_t));
163 uint32_t u32Val = *(const uint32_t *)pv;
164
165 LogFlowFunc(("off=%RGp u32Val=%#x cb=%u\n", off, u32Val, cb));
166
167 if (pThis->cBusCycle == 0)
168 {
169 /* Writes new command, the comand must be sent to both chips at the same time. */
170 Assert((u32Val >> 16) == (u32Val & 0xffff));
171 switch (u32Val & 0xffff)
172 {
173 case FLASH_CFI_CMD_READ_STATUS_REG:
174 case FLASH_CFI_CMD_ARRAY_READ:
175 case FLASH_CFI_CMD_READ_DEVICE_ID:
176 pThis->u16Cmd = u32Val;
177 break;
178 case FLASH_CFI_CMD_BLOCK_ERASE_SETUP:
179 pThis->u16Cmd = u32Val;
180 pThis->cBusCycle++;
181 break;
182 case FLASH_CFI_CMD_BUFFERED_PROGRAM_SETUP:
183 Assert(pThis->bStatus & FLASH_CFI_SR_PROGRAM_ERASE);
184 pThis->u16Cmd = u32Val;
185 pThis->offBlock = (uint32_t)off;
186 pThis->cBusCycle++;
187 break;
188 case FLASH_CFI_CMD_CLEAR_STATUS_REG:
189 pThis->bStatus &= ~(FLASH_CFI_SR_BLOCK_PROTETION | FLASH_CFI_SR_VPP | FLASH_CFI_SR_PROGRAM | FLASH_CFI_SR_ERASE);
190 pThis->u16Cmd = FLASH_CFI_CMD_ARRAY_READ;
191 break;
192 default:
193 AssertReleaseFailed();
194 }
195 }
196 else if (pThis->cBusCycle == 1)
197 {
198 switch (pThis->u16Cmd)
199 {
200 case FLASH_CFI_CMD_BLOCK_ERASE_SETUP:
201 {
202 /* This contains the address. */
203 pThis->u16Cmd = FLASH_CFI_CMD_READ_STATUS_REG;
204 pThis->cBusCycle = 0;
205 memset(pThis->pbFlash + off, 0xff, RT_MIN(pThis->cbFlashSize - off, pThis->cbBlockSize));
206 break;
207 }
208 case FLASH_CFI_CMD_BUFFERED_PROGRAM_SETUP:
209 {
210 /* Receives the number of words to be transfered. */
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();
217 break;
218 }
219 }
220 }
221 else if (pThis->cBusCycle == 2)
222 {
223 switch (pThis->u16Cmd)
224 {
225 case FLASH_CFI_CMD_BUFFERED_PROGRAM_SETUP:
226 {
227 /* Receives the address and data. */
228 if (!pThis->cWordsTransfered)
229 {
230 /* Should be the confirm now. */
231 if ((u32Val & 0xffff) == FLASH_CFI_CMD_BUFFERED_PROGRAM_CONFIRM)
232 {
233 if (pThis->offBlock + pThis->cbWrite <= pThis->cbFlashSize)
234 memcpy(pThis->pbFlash + pThis->offBlock, &pThis->abProgramBuf[0], pThis->cbWrite);
235 /* Reset to read array. */
236 pThis->cBusCycle = 0;
237 pThis->u16Cmd = FLASH_CFI_CMD_ARRAY_READ;
238 }
239 else
240 AssertReleaseFailed();
241 }
242 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();
250 pThis->cWordsTransfered--;
251 }
252 break;
253 }
254 }
255 }
256 else
257 AssertReleaseFailed();
258
259 LogFlow(("flashWrite: completed write at %08RX32 (LB %u)\n", off, cb));
260 return VINF_SUCCESS;
261}
262
263
264/**
265 * @callback_method_impl{FNIOMMMIONEWREAD, Flash memory read}
266 */
267static DECLCALLBACK(VBOXSTRICTRC) flashMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb)
268{
269 PDEVFLASHCFI pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASHCFI);
270 RT_NOREF1(pvUser);
271
272 LogFlowFunc(("off=%RGp cb=%u\n", off, cb));
273
274 if (pThis->u16Cmd == FLASH_CFI_CMD_ARRAY_READ)
275 {
276 size_t cbThisRead = RT_MIN(cb, pThis->cbFlashSize - off);
277 size_t cbSetFf = cb - cbThisRead;
278 if (cbThisRead)
279 memcpy(pv, &pThis->pbFlash[off], cbThisRead);
280 if (cbSetFf)
281 memset((uint8_t *)pv + cbThisRead, 0xff, cbSetFf);
282 }
283 else
284 {
285 /** @todo For now we only emulate a x32 device using two x16 chips so the command must be send to both chips at the same time. */
286 Assert(cb == sizeof(uint32_t));
287
288 uint32_t *pu32 = (uint32_t *)pv;
289 switch (pThis->u16Cmd)
290 {
291 case FLASH_CFI_CMD_READ_DEVICE_ID:
292 *pu32 = 0; /** @todo */
293 break;
294 case FLASH_CFI_CMD_READ_STATUS_REG:
295 case FLASH_CFI_CMD_BUFFERED_PROGRAM_SETUP:
296 *pu32 = ((uint32_t)pThis->bStatus << 16) | pThis->bStatus;
297 break;
298 default:
299 AssertReleaseFailed();
300 }
301 }
302
303 LogFlow(("flashRead: completed read at %08RX32 (LB %u)\n", off, cb));
304 return VINF_SUCCESS;
305}
306
307
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
321#if 0 /** @todo Later */
322/**
323 * @callback_method_impl{FNSSMDEVSAVEEXEC}
324 */
325static DECLCALLBACK(int) flashSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
326{
327 PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH);
328 return flashR3SaveExec(&pThis->Core, pDevIns, pSSM);
329}
330
331
332/**
333 * @callback_method_impl{FNSSMDEVLOADEXEC}
334 */
335static DECLCALLBACK(int) flashLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
336{
337 PDEVFLASH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASH);
338 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
339
340 /* Fend off unsupported versions. */
341 if (uVersion != FLASH_SAVED_STATE_VERSION)
342 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
343
344 return flashR3LoadExec(&pThis->Core, pDevIns, pSSM);
345}
346#endif
347
348/**
349 * @interface_method_impl{PDMDEVREG,pfnReset}
350 */
351static DECLCALLBACK(void) flashR3Reset(PPDMDEVINS pDevIns)
352{
353 PDEVFLASHCFI pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASHCFI);
354
355 /*
356 * Initialize the device state.
357 */
358 pThis->u16Cmd = FLASH_CFI_CMD_ARRAY_READ;
359 pThis->bStatus = FLASH_CFI_SR_PROGRAM_ERASE; /* Prgram/Erase controller is inactive. */
360 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 }
394}
395
396
397/**
398 * @interface_method_impl{PDMDEVREG,pfnDestruct}
399 */
400static DECLCALLBACK(int) flashR3Destruct(PPDMDEVINS pDevIns)
401{
402 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
403 PDEVFLASHCFI pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASHCFI);
404
405 if (pThis->pszFlashFile)
406 {
407 RTFILE hFlashFile = NIL_RTFILE;
408
409 int rc = RTFileOpen(&hFlashFile, pThis->pszFlashFile, RTFILE_O_READWRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE);
410 if (RT_FAILURE(rc))
411 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to open flash file"));
412
413 rc = RTFileWrite(hFlashFile, pThis->pbFlash, pThis->cbFlashSize, NULL);
414 RTFileClose(hFlashFile);
415 if (RT_FAILURE(rc))
416 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to write flash file"));
417
418 PDMDevHlpMMHeapFree(pDevIns, pThis->pszFlashFile);
419 pThis->pszFlashFile = NULL;
420 }
421
422 if (pThis->pbFlash)
423 {
424 PDMDevHlpMMHeapFree(pDevIns, pThis->pbFlash);
425 pThis->pbFlash = NULL;
426 }
427
428 return VINF_SUCCESS;
429}
430
431
432/**
433 * @interface_method_impl{PDMDEVREG,pfnConstruct}
434 */
435static DECLCALLBACK(int) flashR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
436{
437 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
438 PDEVFLASHCFI pThis = PDMDEVINS_2_DATA(pDevIns, PDEVFLASHCFI);
439 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
440
441 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
448
449 /*
450 * Validate configuration.
451 */
452 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "DeviceId|BaseAddress|Size|BlockSize|FlashFile", "");
453
454 /*
455 * Read configuration.
456 */
457
458 uint16_t u16FlashId = 0;
459 int rc = pHlp->pfnCFGMQueryU16Def(pCfg, "DeviceId", &u16FlashId, 0xA289);
460 if (RT_FAILURE(rc))
461 return PDMDEV_SET_ERROR(pDevIns, rc,
462 N_("Configuration error: Querying \"DeviceId\" as an integer failed"));
463
464 /* The default base address is 2MB below 4GB. */
465 rc = pHlp->pfnCFGMQueryU64Def(pCfg, "BaseAddress", &pThis->GCPhysFlashBase, 0xFFE00000);
466 if (RT_FAILURE(rc))
467 return PDMDEV_SET_ERROR(pDevIns, rc,
468 N_("Configuration error: Querying \"BaseAddress\" as an integer failed"));
469
470 /* The default flash device size is 128K. */
471 uint64_t cbFlash = 0;
472 rc = pHlp->pfnCFGMQueryU64Def(pCfg, "Size", &cbFlash, 128 * _1K);
473 if (RT_FAILURE(rc))
474 return PDMDEV_SET_ERROR(pDevIns, rc,
475 N_("Configuration error: Querying \"Size\" as an integer failed"));
476
477 /* The default flash device block size is 4K. */
478 uint16_t cbBlock = 0;
479 rc = pHlp->pfnCFGMQueryU16Def(pCfg, "BlockSize", &cbBlock, _4K);
480 if (RT_FAILURE(rc))
481 return PDMDEV_SET_ERROR(pDevIns, rc,
482 N_("Configuration error: Querying \"BlockSize\" as an integer failed"));
483
484 rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "FlashFile", &pThis->pszFlashFile);
485 if (RT_FAILURE(rc))
486 return PDMDEV_SET_ERROR(pDevIns, rc,
487 N_("Configuration error: Querying \"FlashFile\" as a string failed"));
488
489 /*
490 * Initialize the flash core.
491 */
492 pThis->u16FlashId = u16FlashId;
493 pThis->cbBlockSize = cbBlock;
494 pThis->cbFlashSize = cbFlash;
495
496 /* Set up the flash data. */
497 pThis->pbFlash = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, pThis->cbFlashSize);
498 if (!pThis->pbFlash)
499 return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY, N_("Failed to allocate heap memory"));
500
501 /* Default value for empty flash. */
502 memset(pThis->pbFlash, 0xff, pThis->cbFlashSize);
503
504 /* Reset the dynamic state.*/
505 flashR3Reset(pDevIns);
506
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 }
550
551 /*
552 * Register MMIO region.
553 */
554 rc = PDMDevHlpMmioCreateExAndMap(pDevIns, pThis->GCPhysFlashBase, cbFlash,
555 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, NULL, UINT32_MAX,
556 flashMMIOWrite, flashMMIORead, NULL, NULL, "Flash Memory", &pThis->hMmio);
557 AssertRCReturn(rc, rc);
558 LogRel(("Registered %uKB flash at %RGp\n", pThis->cbFlashSize / _1K, pThis->GCPhysFlashBase));
559
560#if 0 /** @todo Later */
561 /*
562 * Register saved state.
563 */
564 rc = PDMDevHlpSSMRegister(pDevIns, FLASH_SAVED_STATE_VERSION, sizeof(*pThis), flashSaveExec, flashLoadExec);
565 AssertRCReturn(rc, rc);
566#endif
567
568 return VINF_SUCCESS;
569}
570
571
572/**
573 * The device registration structure.
574 */
575const PDMDEVREG g_DeviceFlashCFI =
576{
577 /* .u32Version = */ PDM_DEVREG_VERSION,
578 /* .uReserved0 = */ 0,
579 /* .szName = */ "flash-cfi",
580 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_NEW_STYLE,
581 /* .fClass = */ PDM_DEVREG_CLASS_ARCH,
582 /* .cMaxInstances = */ 1,
583 /* .uSharedVersion = */ 42,
584 /* .cbInstanceShared = */ sizeof(DEVFLASHCFI),
585 /* .cbInstanceCC = */ 0,
586 /* .cbInstanceRC = */ 0,
587 /* .cMaxPciDevices = */ 0,
588 /* .cMaxMsixVectors = */ 0,
589 /* .pszDescription = */ "Flash Memory Device",
590#if defined(IN_RING3)
591 /* .pszRCMod = */ "",
592 /* .pszR0Mod = */ "",
593 /* .pfnConstruct = */ flashR3Construct,
594 /* .pfnDestruct = */ flashR3Destruct,
595 /* .pfnRelocate = */ NULL,
596 /* .pfnMemSetup = */ NULL,
597 /* .pfnPowerOn = */ NULL,
598 /* .pfnReset = */ flashR3Reset,
599 /* .pfnSuspend = */ NULL,
600 /* .pfnResume = */ NULL,
601 /* .pfnAttach = */ NULL,
602 /* .pfnDetach = */ NULL,
603 /* .pfnQueryInterface = */ NULL,
604 /* .pfnInitComplete = */ NULL,
605 /* .pfnPowerOff = */ flashR3PowerOff,
606 /* .pfnSoftReset = */ NULL,
607 /* .pfnReserved0 = */ NULL,
608 /* .pfnReserved1 = */ NULL,
609 /* .pfnReserved2 = */ NULL,
610 /* .pfnReserved3 = */ NULL,
611 /* .pfnReserved4 = */ NULL,
612 /* .pfnReserved5 = */ NULL,
613 /* .pfnReserved6 = */ NULL,
614 /* .pfnReserved7 = */ NULL,
615#elif defined(IN_RING0)
616 /* .pfnEarlyConstruct = */ NULL,
617 /* .pfnConstruct = */ NULL,
618 /* .pfnDestruct = */ NULL,
619 /* .pfnFinalDestruct = */ NULL,
620 /* .pfnRequest = */ NULL,
621 /* .pfnReserved0 = */ NULL,
622 /* .pfnReserved1 = */ NULL,
623 /* .pfnReserved2 = */ NULL,
624 /* .pfnReserved3 = */ NULL,
625 /* .pfnReserved4 = */ NULL,
626 /* .pfnReserved5 = */ NULL,
627 /* .pfnReserved6 = */ NULL,
628 /* .pfnReserved7 = */ NULL,
629#elif defined(IN_RC)
630 /* .pfnConstruct = */ NULL,
631 /* .pfnReserved0 = */ NULL,
632 /* .pfnReserved1 = */ NULL,
633 /* .pfnReserved2 = */ NULL,
634 /* .pfnReserved3 = */ NULL,
635 /* .pfnReserved4 = */ NULL,
636 /* .pfnReserved5 = */ NULL,
637 /* .pfnReserved6 = */ NULL,
638 /* .pfnReserved7 = */ NULL,
639#else
640# error "Not in IN_RING3, IN_RING0 or IN_RC!"
641#endif
642 /* .u32VersionEnd = */ PDM_DEVREG_VERSION
643};
644
645#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