VirtualBox

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

Last change on this file since 77662 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.5 KB
Line 
1/* $Id: DevFlash.cpp 76553 2019-01-01 01:45:53Z 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-2019 Oracle Corporation
14 *
15 * This file is part of VirtualBox Open Source Edition (OSE), as
16 * available from http://www.virtualbox.org. This file is free software;
17 * you can redistribute it and/or modify it under the terms of the GNU
18 * General Public License (GPL) as published by the Free Software
19 * Foundation, in version 2 as it comes in the "COPYING" file of the
20 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
21 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
22 */
23
24
25/*********************************************************************************************************************************
26* Header Files *
27*********************************************************************************************************************************/
28#define LOG_GROUP LOG_GROUP_DEV_FLASH
29#include <VBox/vmm/pdmdev.h>
30#include <VBox/log.h>
31#include <VBox/err.h>
32#include <iprt/assert.h>
33#include <iprt/string.h>
34#include <iprt/file.h>
35
36#include "VBoxDD.h"
37
38
39/*********************************************************************************************************************************
40* Defined Constants And Macros *
41*********************************************************************************************************************************/
42/** The current version of the saved state. */
43#define FLASH_SAVED_STATE_VERSION 1
44
45
46/** @name CUI (Command User Interface) Commands.
47 * @{ */
48#define FLASH_CMD_ALT_WRITE 0x10
49#define FLASH_CMD_ERASE_SETUP 0x20
50#define FLASH_CMD_WRITE 0x40
51#define FLASH_CMD_STS_CLEAR 0x50
52#define FLASH_CMD_STS_READ 0x70
53#define FLASH_CMD_READ_ID 0x90
54#define FLASH_CMD_ERASE_SUS_RES 0xB0
55#define FLASH_CMD_ERASE_CONFIRM 0xD0
56#define FLASH_CMD_ARRAY_READ 0xFF
57/** @} */
58
59/** @name Status register bits.
60 * @{ */
61#define FLASH_STATUS_WSMS 0x80 /* Write State Machine Status, 1=Ready */
62#define FLASH_STATUS_ESS 0x40 /* Erase Suspend Status, 1=Suspended */
63#define FLASH_STATUS_ES 0x20 /* Erase Status, 1=Error */
64#define FLASH_STATUS_BWS 0x10 /* Byte Write Status, 1=Error */
65#define FLASH_STATUS_VPPS 0x08 /* Vpp Status, 1=Low Vpp */
66/* The remaining bits 0-2 are reserved/unused */
67/** @} */
68
69
70/*********************************************************************************************************************************
71* Structures and Typedefs *
72*********************************************************************************************************************************/
73
74
75/**
76 * The flash device
77 */
78typedef struct DEVFLASH
79{
80 /** The current command. */
81 uint8_t bCmd;
82 /** The status register. */
83 uint8_t bStatus;
84 /** Current bus cycle. */
85 uint8_t cBusCycle;
86
87 uint8_t uPadding0;
88
89 /* The following state does not change at runtime.*/
90 /** Manufacturer (high byte) and device (low byte) ID. */
91 uint16_t u16FlashId;
92 /** The configured block size of the device. */
93 uint16_t cbBlockSize;
94 /** The guest physical memory base address. */
95 RTGCPHYS GCPhysFlashBase;
96 /** The flash memory region size. */
97 uint32_t cbFlashSize;
98 /** The actual flash memory data. */
99 uint8_t *pbFlash;
100 /** When set, indicates the state was saved. */
101 bool fStateSaved;
102 /** The backing file. */
103 RTFILE hFlashFile;
104 char *pszFlashFile;
105} DEVFLASH;
106
107/** Pointer to the Flash device state. */
108typedef DEVFLASH *PDEVFLASH;
109
110#ifndef VBOX_DEVICE_STRUCT_TESTCASE
111
112
113/*********************************************************************************************************************************
114* Internal Functions *
115*********************************************************************************************************************************/
116
117
118/*********************************************************************************************************************************
119* Global Variables *
120*********************************************************************************************************************************/
121
122#ifdef IN_RING3 /* for now */
123
124static int flashMemWriteByte(PDEVFLASH pThis, RTGCPHYS GCPhysAddr, uint8_t bCmd)
125{
126 int rc = VINF_SUCCESS;
127 unsigned uOffset;
128
129 /* NB: Older datasheets (e.g. 28F008SA) suggest that for two-cycle commands like byte write or
130 * erase setup, the address is significant in both cycles, but do not explain what happens
131 * should the addresses not match. Newer datasheets (e.g. 28F008B3) clearly say that the address
132 * in the first byte cycle never matters. We prefer the latter interpretation.
133 */
134
135 if (pThis->cBusCycle == 0)
136 {
137 /* First bus write cycle, start processing a new command. Address is ignored. */
138 switch (bCmd)
139 {
140 case FLASH_CMD_ARRAY_READ:
141 case FLASH_CMD_STS_READ:
142 case FLASH_CMD_ERASE_SUS_RES:
143 case FLASH_CMD_READ_ID:
144 /* Single-cycle write commands, only change the current command. */
145 pThis->bCmd = bCmd;
146 break;
147 case FLASH_CMD_STS_CLEAR:
148 /* Status clear continues in read mode. */
149 pThis->bStatus = 0;
150 pThis->bCmd = FLASH_CMD_ARRAY_READ;
151 break;
152 case FLASH_CMD_WRITE:
153 case FLASH_CMD_ALT_WRITE:
154 case FLASH_CMD_ERASE_SETUP:
155 /* Two-cycle commands, advance the bus write cycle. */
156 pThis->bCmd = bCmd;
157 pThis->cBusCycle++;
158 break;
159 default:
160 LogFunc(("1st cycle command %02X, current cmd %02X\n", bCmd, pThis->bCmd));
161 break;
162 }
163 }
164 else
165 {
166 /* Second write of a two-cycle command. */
167 Assert(pThis->cBusCycle == 1);
168 switch (pThis->bCmd)
169 {
170 case FLASH_CMD_WRITE:
171 case FLASH_CMD_ALT_WRITE:
172 uOffset = GCPhysAddr & (pThis->cbFlashSize - 1);
173 if (uOffset < pThis->cbFlashSize)
174 {
175 pThis->pbFlash[uOffset] = bCmd;
176 /* NB: Writes are instant and never fail. */
177 LogFunc(("wrote byte to flash at %08RGp: %02X\n", GCPhysAddr, bCmd));
178 }
179 else
180 LogFunc(("ignoring write at %08RGp: %02X\n", GCPhysAddr, bCmd));
181 break;
182 case FLASH_CMD_ERASE_SETUP:
183 if (bCmd == FLASH_CMD_ERASE_CONFIRM)
184 {
185 /* The current address determines the block to erase. */
186 uOffset = GCPhysAddr & (pThis->cbFlashSize - 1);
187 uOffset = uOffset & ~(pThis->cbBlockSize - 1);
188 memset(pThis->pbFlash + uOffset, 0xff, pThis->cbBlockSize);
189 LogFunc(("Erasing block at offset %u\n", uOffset));
190 }
191 else
192 {
193 /* Anything else is a command erorr. Transition to status read mode. */
194 LogFunc(("2st cycle erase command is %02X, should be confirm (%02X)\n", bCmd, FLASH_CMD_ERASE_CONFIRM));
195 pThis->bCmd = FLASH_CMD_STS_READ;
196 pThis->bStatus |= FLASH_STATUS_BWS | FLASH_STATUS_ES;
197 }
198 break;
199 default:
200 LogFunc(("2st cycle bad command %02X, current cmd %02X\n", bCmd, pThis->bCmd));
201 break;
202 }
203 pThis->cBusCycle = 0;
204 }
205 LogFlow(("flashMemWriteByte: write access at %08RGp: %#x rc=%Rrc\n", GCPhysAddr, bCmd, rc));
206//LogRel(("flashMemWriteByte: write access at %08RGp: %#x (cmd=%02X) rc=%Rrc\n", GCPhysAddr, bCmd, pThis->bCmd, rc));
207 return rc;
208}
209
210
211static int flashMemReadByte(PDEVFLASH pThis, RTGCPHYS GCPhysAddr, uint8_t *pbData)
212{
213 uint8_t bValue;
214 unsigned uOffset;
215 int rc = VINF_SUCCESS;
216
217 /* Reads are only defined in three states: Array read, status register read,
218 * and ID read.
219 */
220 switch (pThis->bCmd)
221 {
222 case FLASH_CMD_ARRAY_READ:
223 uOffset = GCPhysAddr & (pThis->cbFlashSize - 1);
224 bValue = pThis->pbFlash[uOffset];
225 LogFunc(("read byte at %08RGp: %02X\n", GCPhysAddr, bValue));
226 break;
227 case FLASH_CMD_STS_READ:
228 bValue = pThis->bStatus;
229 break;
230 case FLASH_CMD_READ_ID:
231 bValue = GCPhysAddr & 1 ? RT_HI_U8(pThis->u16FlashId) : RT_LO_U8(pThis->u16FlashId);
232 break;
233 default:
234 bValue = 0xff;
235 break;
236 }
237 *pbData = bValue;
238
239 LogFlow(("flashMemReadByte: read access at %08RGp: %02X (cmd=%02X) rc=%Rrc\n", GCPhysAddr, bValue, pThis->bCmd, rc));
240//LogRel(("flashMemReadByte: read access at %08RGp: %02X (cmd=%02X) rc=%Rrc\n", GCPhysAddr, bValue, pThis->bCmd, rc));
241 return rc;
242}
243
244/** @callback_method_impl{FNIOMMIWRITE, Flash memory write} */
245PDMBOTHCBDECL(int) flashMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
246{
247 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH);
248 int rc = VINF_SUCCESS;
249 const uint8_t *pu8Mem = (const uint8_t *)pv;
250 unsigned uOffset;
251 RT_NOREF1(pvUser);
252
253 /* Writes may need to go back to R3. If more than one byte is being written (not likely!),
254 * just suck it up and take the trip to R3 immediately.
255 */
256 /** @todo Idea: We could buffer all writes in R0 and flush them out on a
257 * timer. Probably not worth it.
258 */
259#ifndef IN_RING3
260 if (cb > 1)
261 return VINF_IOM_R3_IOPORT_WRITE;
262#endif
263
264 for (uOffset = 0; uOffset < cb; ++uOffset)
265 {
266 rc = flashMemWriteByte(pThis, GCPhysAddr + uOffset, pu8Mem[uOffset]);
267 if (!RT_SUCCESS(rc))
268 break;
269 }
270
271 LogFlow(("FlashMMIOWrite: completed write at %08RGp (LB %u): rc=%Rrc\n", GCPhysAddr, cb, rc));
272 return rc;
273}
274
275
276/** @callback_method_impl{FNIOMMIOREAD, Flash memory read} */
277PDMBOTHCBDECL(int) flashMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
278{
279 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH);
280 int rc = VINF_SUCCESS;
281 unsigned uOffset;
282 uint8_t *pu8Mem;
283 RT_NOREF1(pvUser);
284
285 /* Reading can always be done witout going back to R3. Reads do not
286 * change the device state and we always have the data.
287 */
288 pu8Mem = (uint8_t *)pv;
289 for (uOffset = 0; uOffset < cb; ++uOffset, ++pu8Mem)
290 {
291 rc = flashMemReadByte(pThis, GCPhysAddr + uOffset, pu8Mem);
292 if (!RT_SUCCESS(rc))
293 break;
294 }
295
296 LogFlow(("flashMMIORead: completed read at %08RGp (LB %u): rc=%Rrc\n", GCPhysAddr, cb, rc));
297 return rc;
298}
299
300#endif /* IN_RING3 for now */
301
302#ifdef IN_RING3
303
304/** @callback_method_impl{FNSSMDEVSAVEEXEC} */
305static DECLCALLBACK(int) flashSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
306{
307 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH);
308
309 /* Save the device state. */
310 SSMR3PutU8(pSSM, pThis->bCmd);
311 SSMR3PutU8(pSSM, pThis->bStatus);
312 SSMR3PutU8(pSSM, pThis->cBusCycle);
313
314 /* Save the current configuration for validation purposes. */
315 SSMR3PutU16(pSSM, pThis->cbBlockSize);
316 SSMR3PutU16(pSSM, pThis->u16FlashId);
317
318 /* Save the current flash contents. */
319 SSMR3PutU32(pSSM, pThis->cbFlashSize);
320 SSMR3PutMem(pSSM, pThis->pbFlash, pThis->cbFlashSize);
321
322 pThis->fStateSaved = true;
323
324 return VINF_SUCCESS;
325}
326
327
328/** @callback_method_impl{FNSSMDEVLOADEXEC} */
329static DECLCALLBACK(int) flashLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
330{
331 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH);
332 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
333
334 /* Fend off unsupported versions. */
335 if (uVersion != FLASH_SAVED_STATE_VERSION)
336 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
337
338 /*
339 * Do the actual restoring.
340 */
341 if (uVersion == FLASH_SAVED_STATE_VERSION)
342 {
343 uint16_t u16Val;
344 uint32_t u32Val;
345
346 SSMR3GetU8(pSSM, &pThis->bCmd);
347 SSMR3GetU8(pSSM, &pThis->bStatus);
348 SSMR3GetU8(pSSM, &pThis->cBusCycle);
349
350 /* Make sure configuration didn't change behind our back. */
351 SSMR3GetU16(pSSM, &u16Val);
352 if (u16Val != pThis->cbBlockSize)
353 return VERR_SSM_LOAD_CONFIG_MISMATCH;
354 SSMR3GetU16(pSSM, &u16Val);
355 if (u16Val != pThis->u16FlashId)
356 return VERR_SSM_LOAD_CONFIG_MISMATCH;
357 SSMR3GetU32(pSSM, &u32Val);
358 if (u16Val != pThis->cbFlashSize)
359 return VERR_SSM_LOAD_CONFIG_MISMATCH;
360
361 /* Suck in the flash contents. */
362 SSMR3GetMem(pSSM, pThis->pbFlash, pThis->cbFlashSize);
363 }
364
365 return VINF_SUCCESS;
366}
367
368/**
369 * @interface_method_impl{PDMDEVREG,pfnReset}
370 */
371static DECLCALLBACK(void) flashReset(PPDMDEVINS pDevIns)
372{
373 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH);
374
375 /*
376 * Initialize the device state.
377 */
378 pThis->bCmd = FLASH_CMD_ARRAY_READ;
379 pThis->bStatus = 0;
380 pThis->cBusCycle = 0;
381}
382
383/**
384 * @interface_method_impl{PDMDEVREG,pfnDestruct}
385 */
386static DECLCALLBACK(int) flashDestruct(PPDMDEVINS pDevIns)
387{
388 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH);
389 int rc;
390
391 if (!pThis->fStateSaved)
392 {
393 rc = RTFileSeek(pThis->hFlashFile, 0, RTFILE_SEEK_BEGIN, NULL);
394 rc = RTFileWrite(pThis->hFlashFile, pThis->pbFlash, pThis->cbFlashSize, NULL);
395 if (RT_FAILURE(rc))
396 LogRel(("flash: Failed to save flash file"));
397 }
398
399 if (pThis->pbFlash)
400 {
401 PDMDevHlpMMHeapFree(pDevIns, pThis->pbFlash);
402 pThis->pbFlash = NULL;
403 }
404
405 if (pThis->pszFlashFile)
406 {
407 PDMDevHlpMMHeapFree(pDevIns, pThis->pszFlashFile);
408 pThis->pszFlashFile = NULL;
409 }
410
411 return VINF_SUCCESS;
412}
413
414/** @todo this does not really belong here; workaround for EFI failing to init empty flash. */
415static const uint8_t aHdrBegin[] = {
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
417 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
418 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x46, 0x56, 0x48, 0xFF, 0xFE, 0x04, 0x00,
419 0x48, 0x00, 0x19, 0xF9, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x36, 0xCF, 0xDD, 0x75, 0x32, 0x64, 0x41,
421 0x98, 0xB6, 0xFE, 0x85, 0x70, 0x7F, 0xFE, 0x7D, 0xB8, 0xDF, 0x00, 0x00, 0x5A, 0xFE, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
423};
424
425/**
426 * @interface_method_impl{PDMDEVREG,pfnConstruct}
427 */
428static DECLCALLBACK(int) flashConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
429{
430 RT_NOREF1(iInstance);
431 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
432 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH);
433 Assert(iInstance == 0);
434
435 /*
436 * Validate configuration.
437 */
438 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "DeviceId|BaseAddress|Size|BlockSize|FlashFile", "");
439
440 /*
441 * Read configuration.
442 */
443
444 /* The default device ID is Intel 28F800SA. */
445 int rc = CFGMR3QueryU16Def(pCfg, "DeviceId", &pThis->u16FlashId, 0xA289);
446 if (RT_FAILURE(rc))
447 return PDMDEV_SET_ERROR(pDevIns, rc,
448 N_("Configuration error: Querying \"DeviceId\" as an integer failed"));
449
450 /* The default base address is 2MB below 4GB. */
451 rc = CFGMR3QueryU64Def(pCfg, "BaseAddress", &pThis->GCPhysFlashBase, 0xFFE00000);
452 if (RT_FAILURE(rc))
453 return PDMDEV_SET_ERROR(pDevIns, rc,
454 N_("Configuration error: Querying \"BaseAddress\" as an integer failed"));
455
456 /* The default flash device size is 128K. */
457 rc = CFGMR3QueryU32Def(pCfg, "Size", &pThis->cbFlashSize, 128 * _1K);
458 if (RT_FAILURE(rc))
459 return PDMDEV_SET_ERROR(pDevIns, rc,
460 N_("Configuration error: Querying \"Size\" as an integer failed"));
461
462 /* The default flash device block size is 4K. */
463 rc = CFGMR3QueryU16Def(pCfg, "BlockSize", &pThis->cbBlockSize, 4 * _1K);
464 if (RT_FAILURE(rc))
465 return PDMDEV_SET_ERROR(pDevIns, rc,
466 N_("Configuration error: Querying \"BlockSize\" as an integer failed"));
467
468 /* The default flash device block size is 4K. */
469 rc = CFGMR3QueryU16Def(pCfg, "BlockSize", &pThis->cbBlockSize, 4 * _1K);
470 if (RT_FAILURE(rc))
471 return PDMDEV_SET_ERROR(pDevIns, rc,
472 N_("Configuration error: Querying \"BlockSize\" as an integer failed"));
473
474 rc = CFGMR3QueryStringAlloc(pCfg, "FlashFile", &pThis->pszFlashFile);
475 if (RT_FAILURE(rc))
476 return PDMDEV_SET_ERROR(pDevIns, rc,
477 N_("Configuration error: Querying \"FlashFile\" as a string failed"));
478
479 /* Try opening the backing file. */
480 rc = RTFileOpen(&pThis->hFlashFile, pThis->pszFlashFile, RTFILE_O_READWRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE);
481 if (RT_FAILURE(rc))
482 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to open flash file"));
483
484 /* Set up the static state, immutable at run-time. */
485 pThis->pbFlash = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, pThis->cbFlashSize);
486 if (!pThis->pbFlash)
487 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to allocate heap memory"));
488
489 size_t cbRead = 0;
490 rc = RTFileRead(pThis->hFlashFile, pThis->pbFlash, pThis->cbFlashSize, &cbRead);
491 if (RT_FAILURE(rc))
492 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to read flash file"));
493 Log(("Read %zu bytes from file (asked for %u)\n.", cbRead, pThis->cbFlashSize));
494
495 /* If the file didn't exist, or someone truncated it, we'll initialize
496 * the storage with default contents.
497 */
498 if (cbRead != pThis->cbFlashSize)
499 {
500 memset(pThis->pbFlash, 0xff, pThis->cbFlashSize);
501 memcpy(pThis->pbFlash, aHdrBegin, sizeof(aHdrBegin));
502 LogRel(("Only read %zu bytes from flash file (asked for %u). Initializing with defaults.\n", cbRead, pThis->cbFlashSize));
503 }
504
505 /* Reset the dynamic state.*/
506 flashReset(pDevIns);
507
508 /*
509 * Register MMIO region.
510 */
511 rc = PDMDevHlpMMIORegister(pDevIns, pThis->GCPhysFlashBase, pThis->cbFlashSize, NULL /*pvUser*/,
512 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
513 flashMMIOWrite, flashMMIORead,
514 "Flash Memory");
515 AssertRCReturn(rc, rc);
516 LogRel(("Registered %uKB flash at %RGp\n", pThis->cbFlashSize / _1K, pThis->GCPhysFlashBase));
517
518 /*
519 * Register saved state.
520 */
521 rc = PDMDevHlpSSMRegister(pDevIns, FLASH_SAVED_STATE_VERSION, sizeof(*pThis), flashSaveExec, flashLoadExec);
522 if (RT_FAILURE(rc))
523 return rc;
524
525 return VINF_SUCCESS;
526}
527
528
529/**
530 * The device registration structure.
531 */
532const PDMDEVREG g_DeviceFlash =
533{
534 /* u32Version */
535 PDM_DEVREG_VERSION,
536 /* szName */
537 "flash",
538 /* szRCMod */
539 "VBoxDDRC.rc",
540 /* szR0Mod */
541 "VBoxDDR0.r0",
542 /* pszDescription */
543 "Flash Memory Device",
544 /* fFlags */
545 PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT | PDM_DEVREG_FLAGS_R0 | PDM_DEVREG_FLAGS_RC,
546 /* fClass */
547 PDM_DEVREG_CLASS_ARCH,
548 /* cMaxInstances */
549 1,
550 /* cbInstance */
551 sizeof(DEVFLASH),
552 /* pfnConstruct */
553 flashConstruct,
554 /* pfnDestruct */
555 flashDestruct,
556 /* pfnRelocate */
557 NULL,
558 /* pfnMemSetup */
559 NULL,
560 /* pfnPowerOn */
561 NULL,
562 /* pfnReset */
563 flashReset,
564 /* pfnSuspend */
565 NULL,
566 /* pfnResume */
567 NULL,
568 /* pfnAttach */
569 NULL,
570 /* pfnDetach */
571 NULL,
572 /* pfnQueryInterface. */
573 NULL,
574 /* pfnInitComplete. */
575 NULL,
576 /* pfnPowerOff */
577 NULL,
578 /* pfnSoftReset */
579 NULL,
580 /* u32VersionEnd */
581 PDM_DEVREG_VERSION
582};
583
584#endif /* IN_RING3 */
585#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