- Timestamp:
- Oct 14, 2019 11:41:24 AM (5 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/EFI/DevFlash.cpp
r80704 r81250 35 35 36 36 #include "VBoxDD.h" 37 #include "FlashCore.h" 37 38 38 39 … … 40 41 * Defined Constants And Macros * 41 42 *********************************************************************************************************************************/ 42 /** The current version of the saved state. */43 #define FLASH_SAVED_STATE_VERSION 144 45 46 /** @name CUI (Command User Interface) Commands.47 * @{ */48 #define FLASH_CMD_ALT_WRITE 0x1049 #define FLASH_CMD_ERASE_SETUP 0x2050 #define FLASH_CMD_WRITE 0x4051 #define FLASH_CMD_STS_CLEAR 0x5052 #define FLASH_CMD_STS_READ 0x7053 #define FLASH_CMD_READ_ID 0x9054 #define FLASH_CMD_ERASE_SUS_RES 0xB055 #define FLASH_CMD_ERASE_CONFIRM 0xD056 #define FLASH_CMD_ARRAY_READ 0xFF57 /** @} */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 43 69 44 … … 76 51 typedef struct DEVFLASH 77 52 { 78 /** The current command. */ 79 uint8_t bCmd; 80 /** The status register. */ 81 uint8_t bStatus; 82 /** Current bus cycle. */ 83 uint8_t cBusCycle; 84 85 uint8_t uPadding0; 86 87 /* The following state does not change at runtime.*/ 88 /** Manufacturer (high byte) and device (low byte) ID. */ 89 uint16_t u16FlashId; 90 /** The configured block size of the device. */ 91 uint16_t cbBlockSize; 53 /** The flash core device instance.*/ 54 FLASHCORE Core; 92 55 /** The guest physical memory base address. */ 93 56 RTGCPHYS GCPhysFlashBase; 94 /** The flash memory region size. */95 uint32_t cbFlashSize;96 /** The actual flash memory data. */97 uint8_t *pbFlash;98 57 /** When set, indicates the state was saved. */ 99 58 bool fStateSaved; 100 /** The backing file. */ 101 RTFILE hFlashFile; 59 /** The file conaining the flash content. */ 102 60 char *pszFlashFile; 103 61 } DEVFLASH; … … 111 69 #ifdef IN_RING3 /* for now */ 112 70 113 static int flashMemWriteByte(PDEVFLASH pThis, RTGCPHYS GCPhysAddr, uint8_t bCmd)114 {115 int rc = VINF_SUCCESS;116 unsigned uOffset;117 118 /* NB: Older datasheets (e.g. 28F008SA) suggest that for two-cycle commands like byte write or119 * erase setup, the address is significant in both cycles, but do not explain what happens120 * should the addresses not match. Newer datasheets (e.g. 28F008B3) clearly say that the address121 * in the first byte cycle never matters. We prefer the latter interpretation.122 */123 124 if (pThis->cBusCycle == 0)125 {126 /* First bus write cycle, start processing a new command. Address is ignored. */127 switch (bCmd)128 {129 case FLASH_CMD_ARRAY_READ:130 case FLASH_CMD_STS_READ:131 case FLASH_CMD_ERASE_SUS_RES:132 case FLASH_CMD_READ_ID:133 /* Single-cycle write commands, only change the current command. */134 pThis->bCmd = bCmd;135 break;136 case FLASH_CMD_STS_CLEAR:137 /* Status clear continues in read mode. */138 pThis->bStatus = 0;139 pThis->bCmd = FLASH_CMD_ARRAY_READ;140 break;141 case FLASH_CMD_WRITE:142 case FLASH_CMD_ALT_WRITE:143 case FLASH_CMD_ERASE_SETUP:144 /* Two-cycle commands, advance the bus write cycle. */145 pThis->bCmd = bCmd;146 pThis->cBusCycle++;147 break;148 default:149 LogFunc(("1st cycle command %02X, current cmd %02X\n", bCmd, pThis->bCmd));150 break;151 }152 }153 else154 {155 /* Second write of a two-cycle command. */156 Assert(pThis->cBusCycle == 1);157 switch (pThis->bCmd)158 {159 case FLASH_CMD_WRITE:160 case FLASH_CMD_ALT_WRITE:161 uOffset = GCPhysAddr & (pThis->cbFlashSize - 1);162 if (uOffset < pThis->cbFlashSize)163 {164 pThis->pbFlash[uOffset] = bCmd;165 /* NB: Writes are instant and never fail. */166 LogFunc(("wrote byte to flash at %08RGp: %02X\n", GCPhysAddr, bCmd));167 }168 else169 LogFunc(("ignoring write at %08RGp: %02X\n", GCPhysAddr, bCmd));170 break;171 case FLASH_CMD_ERASE_SETUP:172 if (bCmd == FLASH_CMD_ERASE_CONFIRM)173 {174 /* The current address determines the block to erase. */175 uOffset = GCPhysAddr & (pThis->cbFlashSize - 1);176 uOffset = uOffset & ~(pThis->cbBlockSize - 1);177 memset(pThis->pbFlash + uOffset, 0xff, pThis->cbBlockSize);178 LogFunc(("Erasing block at offset %u\n", uOffset));179 }180 else181 {182 /* Anything else is a command erorr. Transition to status read mode. */183 LogFunc(("2st cycle erase command is %02X, should be confirm (%02X)\n", bCmd, FLASH_CMD_ERASE_CONFIRM));184 pThis->bCmd = FLASH_CMD_STS_READ;185 pThis->bStatus |= FLASH_STATUS_BWS | FLASH_STATUS_ES;186 }187 break;188 default:189 LogFunc(("2st cycle bad command %02X, current cmd %02X\n", bCmd, pThis->bCmd));190 break;191 }192 pThis->cBusCycle = 0;193 }194 LogFlow(("flashMemWriteByte: write access at %08RGp: %#x rc=%Rrc\n", GCPhysAddr, bCmd, rc));195 //LogRel(("flashMemWriteByte: write access at %08RGp: %#x (cmd=%02X) rc=%Rrc\n", GCPhysAddr, bCmd, pThis->bCmd, rc));196 return rc;197 }198 199 200 static int flashMemReadByte(PDEVFLASH pThis, RTGCPHYS GCPhysAddr, uint8_t *pbData)201 {202 uint8_t bValue;203 unsigned uOffset;204 int rc = VINF_SUCCESS;205 206 /* Reads are only defined in three states: Array read, status register read,207 * and ID read.208 */209 switch (pThis->bCmd)210 {211 case FLASH_CMD_ARRAY_READ:212 uOffset = GCPhysAddr & (pThis->cbFlashSize - 1);213 bValue = pThis->pbFlash[uOffset];214 LogFunc(("read byte at %08RGp: %02X\n", GCPhysAddr, bValue));215 break;216 case FLASH_CMD_STS_READ:217 bValue = pThis->bStatus;218 break;219 case FLASH_CMD_READ_ID:220 bValue = GCPhysAddr & 1 ? RT_HI_U8(pThis->u16FlashId) : RT_LO_U8(pThis->u16FlashId);221 break;222 default:223 bValue = 0xff;224 break;225 }226 *pbData = bValue;227 228 LogFlow(("flashMemReadByte: read access at %08RGp: %02X (cmd=%02X) rc=%Rrc\n", GCPhysAddr, bValue, pThis->bCmd, rc));229 //LogRel(("flashMemReadByte: read access at %08RGp: %02X (cmd=%02X) rc=%Rrc\n", GCPhysAddr, bValue, pThis->bCmd, rc));230 return rc;231 }232 233 71 /** @callback_method_impl{FNIOMMIWRITE, Flash memory write} */ 234 72 PDMBOTHCBDECL(int) flashMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb) 235 73 { 236 74 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 237 int rc = VINF_SUCCESS;238 const uint8_t *pu8Mem = (const uint8_t *)pv;239 unsigned uOffset;240 75 RT_NOREF1(pvUser); 241 76 242 /* Writes may need to go back to R3. If more than one byte is being written (not likely!), 243 * just suck it up and take the trip to R3 immediately. 244 */ 245 /** @todo Idea: We could buffer all writes in R0 and flush them out on a 246 * timer. Probably not worth it. 247 */ 248 #ifndef IN_RING3 249 if (cb > 1) 250 return VINF_IOM_R3_IOPORT_WRITE; 251 #endif 252 253 for (uOffset = 0; uOffset < cb; ++uOffset) 254 { 255 rc = flashMemWriteByte(pThis, GCPhysAddr + uOffset, pu8Mem[uOffset]); 256 if (!RT_SUCCESS(rc)) 257 break; 258 } 259 260 LogFlow(("FlashMMIOWrite: completed write at %08RGp (LB %u): rc=%Rrc\n", GCPhysAddr, cb, rc)); 261 return rc; 77 return flashWrite(&pThis->Core, GCPhysAddr - pThis->GCPhysFlashBase, pv, cb); 262 78 } 263 79 … … 267 83 { 268 84 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 269 int rc = VINF_SUCCESS;270 unsigned uOffset;271 uint8_t *pu8Mem;272 85 RT_NOREF1(pvUser); 273 86 274 /* Reading can always be done witout going back to R3. Reads do not 275 * change the device state and we always have the data. 276 */ 277 pu8Mem = (uint8_t *)pv; 278 for (uOffset = 0; uOffset < cb; ++uOffset, ++pu8Mem) 279 { 280 rc = flashMemReadByte(pThis, GCPhysAddr + uOffset, pu8Mem); 281 if (!RT_SUCCESS(rc)) 282 break; 283 } 284 285 LogFlow(("flashMMIORead: completed read at %08RGp (LB %u): rc=%Rrc\n", GCPhysAddr, cb, rc)); 286 return rc; 87 return flashRead(&pThis->Core, GCPhysAddr - pThis->GCPhysFlashBase, pv, cb); 287 88 } 288 89 … … 296 97 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 297 98 298 /* Save the device state. */ 299 SSMR3PutU8(pSSM, pThis->bCmd); 300 SSMR3PutU8(pSSM, pThis->bStatus); 301 SSMR3PutU8(pSSM, pThis->cBusCycle); 302 303 /* Save the current configuration for validation purposes. */ 304 SSMR3PutU16(pSSM, pThis->cbBlockSize); 305 SSMR3PutU16(pSSM, pThis->u16FlashId); 306 307 /* Save the current flash contents. */ 308 SSMR3PutU32(pSSM, pThis->cbFlashSize); 309 SSMR3PutMem(pSSM, pThis->pbFlash, pThis->cbFlashSize); 310 311 pThis->fStateSaved = true; 312 313 return VINF_SUCCESS; 99 int rc = flashR3SsmSaveExec(&pThis->Core, pSSM); 100 if (RT_SUCCESS(rc)) 101 pThis->fStateSaved = true; 102 103 return rc; 314 104 } 315 105 … … 325 115 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 326 116 327 /* 328 * Do the actual restoring. 329 */ 330 if (uVersion == FLASH_SAVED_STATE_VERSION) 331 { 332 uint16_t u16Val; 333 uint32_t u32Val; 334 335 SSMR3GetU8(pSSM, &pThis->bCmd); 336 SSMR3GetU8(pSSM, &pThis->bStatus); 337 SSMR3GetU8(pSSM, &pThis->cBusCycle); 338 339 /* Make sure configuration didn't change behind our back. */ 340 SSMR3GetU16(pSSM, &u16Val); 341 if (u16Val != pThis->cbBlockSize) 342 return VERR_SSM_LOAD_CONFIG_MISMATCH; 343 SSMR3GetU16(pSSM, &u16Val); 344 if (u16Val != pThis->u16FlashId) 345 return VERR_SSM_LOAD_CONFIG_MISMATCH; 346 SSMR3GetU32(pSSM, &u32Val); 347 if (u16Val != pThis->cbFlashSize) 348 return VERR_SSM_LOAD_CONFIG_MISMATCH; 349 350 /* Suck in the flash contents. */ 351 SSMR3GetMem(pSSM, pThis->pbFlash, pThis->cbFlashSize); 352 } 353 354 return VINF_SUCCESS; 117 return flashR3SsmLoadExec(&pThis->Core, pSSM); 355 118 } 356 119 … … 362 125 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 363 126 364 /* 365 * Initialize the device state. 366 */ 367 pThis->bCmd = FLASH_CMD_ARRAY_READ; 368 pThis->bStatus = 0; 369 pThis->cBusCycle = 0; 127 flashR3Reset(&pThis->Core); 370 128 } 371 129 … … 380 138 if (!pThis->fStateSaved) 381 139 { 382 rc = RTFileSeek(pThis->hFlashFile, 0, RTFILE_SEEK_BEGIN, NULL); 383 rc = RTFileWrite(pThis->hFlashFile, pThis->pbFlash, pThis->cbFlashSize, NULL); 140 rc = flashR3SaveToFile(&pThis->Core, pThis->pszFlashFile); 384 141 if (RT_FAILURE(rc)) 385 LogRel(("flash: Failed to save flash file")); 386 } 387 388 if (pThis->pbFlash) 389 { 390 PDMDevHlpMMHeapFree(pDevIns, pThis->pbFlash); 391 pThis->pbFlash = NULL; 142 LogRel(("Flash: Failed to save flash file")); 392 143 } 393 144 … … 398 149 } 399 150 151 flashR3Destruct(&pThis->Core); 400 152 return VINF_SUCCESS; 401 153 } 402 403 /** @todo this does not really belong here; workaround for EFI failing to init empty flash. */404 static const uint8_t aHdrBegin[] = {405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,406 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,407 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x46, 0x56, 0x48, 0xFF, 0xFE, 0x04, 0x00,408 0x48, 0x00, 0x19, 0xF9, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x36, 0xCF, 0xDD, 0x75, 0x32, 0x64, 0x41,410 0x98, 0xB6, 0xFE, 0x85, 0x70, 0x7F, 0xFE, 0x7D, 0xB8, 0xDF, 0x00, 0x00, 0x5A, 0xFE, 0x00, 0x00,411 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF412 };413 154 414 155 /** … … 432 173 433 174 /* The default device ID is Intel 28F800SA. */ 434 int rc = CFGMR3QueryU16Def(pCfg, "DeviceId", &pThis->u16FlashId, 0xA289); 175 uint16_t u16FlashId = 0; 176 int rc = CFGMR3QueryU16Def(pCfg, "DeviceId", &u16FlashId, 0xA289); 435 177 if (RT_FAILURE(rc)) 436 178 return PDMDEV_SET_ERROR(pDevIns, rc, … … 444 186 445 187 /* The default flash device size is 128K. */ 446 rc = CFGMR3QueryU32Def(pCfg, "Size", &pThis->cbFlashSize, 128 * _1K); 188 uint32_t cbFlash = 0; 189 rc = CFGMR3QueryU32Def(pCfg, "Size", &cbFlash, 128 * _1K); 447 190 if (RT_FAILURE(rc)) 448 191 return PDMDEV_SET_ERROR(pDevIns, rc, … … 450 193 451 194 /* The default flash device block size is 4K. */ 452 rc = CFGMR3QueryU16Def(pCfg, "BlockSize", &pThis->cbBlockSize, 4 * _1K); 195 uint16_t cbBlock = 0; 196 rc = CFGMR3QueryU16Def(pCfg, "BlockSize", &cbBlock, _4K); 453 197 if (RT_FAILURE(rc)) 454 198 return PDMDEV_SET_ERROR(pDevIns, rc, 455 199 N_("Configuration error: Querying \"BlockSize\" as an integer failed")); 456 200 457 /* The default flash device block size is 4K. */458 rc = CFGMR3QueryU16Def(pCfg, "BlockSize", &pThis->cbBlockSize, 4 * _1K);459 if (RT_FAILURE(rc))460 return PDMDEV_SET_ERROR(pDevIns, rc,461 N_("Configuration error: Querying \"BlockSize\" as an integer failed"));462 463 201 rc = CFGMR3QueryStringAlloc(pCfg, "FlashFile", &pThis->pszFlashFile); 464 202 if (RT_FAILURE(rc)) … … 466 204 N_("Configuration error: Querying \"FlashFile\" as a string failed")); 467 205 468 /* Try opening the backing file. */ 469 rc = RTFileOpen(&pThis->hFlashFile, pThis->pszFlashFile, RTFILE_O_READWRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); 470 if (RT_FAILURE(rc)) 471 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to open flash file")); 472 473 /* Set up the static state, immutable at run-time. */ 474 pThis->pbFlash = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, pThis->cbFlashSize); 475 if (!pThis->pbFlash) 476 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to allocate heap memory")); 477 478 size_t cbRead = 0; 479 rc = RTFileRead(pThis->hFlashFile, pThis->pbFlash, pThis->cbFlashSize, &cbRead); 480 if (RT_FAILURE(rc)) 481 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to read flash file")); 482 Log(("Read %zu bytes from file (asked for %u)\n.", cbRead, pThis->cbFlashSize)); 483 484 /* If the file didn't exist, or someone truncated it, we'll initialize 485 * the storage with default contents. 486 */ 487 if (cbRead != pThis->cbFlashSize) 488 { 489 memset(pThis->pbFlash, 0xff, pThis->cbFlashSize); 490 memcpy(pThis->pbFlash, aHdrBegin, sizeof(aHdrBegin)); 491 LogRel(("Only read %zu bytes from flash file (asked for %u). Initializing with defaults.\n", cbRead, pThis->cbFlashSize)); 492 } 493 494 /* Reset the dynamic state.*/ 495 flashReset(pDevIns); 206 rc = flashR3Init(&pThis->Core, pDevIns, u16FlashId, cbFlash, cbBlock); 207 if (RT_FAILURE(rc)) 208 return PDMDEV_SET_ERROR(pDevIns, rc, 209 N_("Flash: Failed to initialize core flash device")); 210 211 /* Try to load the flash content from file. */ 212 rc = flashR3LoadFromFile(&pThis->Core, pThis->pszFlashFile); 213 if (RT_FAILURE(rc)) 214 return PDMDEV_SET_ERROR(pDevIns, rc, 215 N_("Flash: Failed to load flash content from given file")); 496 216 497 217 /* 498 218 * Register MMIO region. 499 219 */ 500 rc = PDMDevHlpMMIORegister(pDevIns, pThis->GCPhysFlashBase, pThis->cbFlashSize, NULL /*pvUser*/,220 rc = PDMDevHlpMMIORegister(pDevIns, pThis->GCPhysFlashBase, cbFlash, NULL /*pvUser*/, 501 221 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, 502 222 flashMMIOWrite, flashMMIORead, 503 223 "Flash Memory"); 504 224 AssertRCReturn(rc, rc); 505 LogRel(("Registered %uKB flash at %RGp\n", pThis-> cbFlashSize / _1K, pThis->GCPhysFlashBase));225 LogRel(("Registered %uKB flash at %RGp\n", pThis->Core.cbFlashSize / _1K, pThis->GCPhysFlashBase)); 506 226 507 227 /* -
trunk/src/VBox/Devices/EFI/FlashCore.cpp
r81236 r81250 35 35 36 36 #include "VBoxDD.h" 37 #include "FlashCore.h" 37 38 38 39 … … 40 41 * Defined Constants And Macros * 41 42 *********************************************************************************************************************************/ 42 /** The current version of the saved state. */43 #define FLASH_SAVED_STATE_VERSION 144 45 46 43 /** @name CUI (Command User Interface) Commands. 47 44 * @{ */ … … 71 68 * Structures and Typedefs * 72 69 *********************************************************************************************************************************/ 73 /**74 * The flash device75 */76 typedef struct DEVFLASH77 {78 /** The current command. */79 uint8_t bCmd;80 /** The status register. */81 uint8_t bStatus;82 /** Current bus cycle. */83 uint8_t cBusCycle;84 85 uint8_t uPadding0;86 87 /* The following state does not change at runtime.*/88 /** Manufacturer (high byte) and device (low byte) ID. */89 uint16_t u16FlashId;90 /** The configured block size of the device. */91 uint16_t cbBlockSize;92 /** The guest physical memory base address. */93 RTGCPHYS GCPhysFlashBase;94 /** The flash memory region size. */95 uint32_t cbFlashSize;96 /** The actual flash memory data. */97 uint8_t *pbFlash;98 /** When set, indicates the state was saved. */99 bool fStateSaved;100 /** The backing file. */101 RTFILE hFlashFile;102 char *pszFlashFile;103 } DEVFLASH;104 105 /** Pointer to the Flash device state. */106 typedef DEVFLASH *PDEVFLASH;107 108 70 #ifndef VBOX_DEVICE_STRUCT_TESTCASE 109 71 … … 111 73 #ifdef IN_RING3 /* for now */ 112 74 113 static int flashMemWriteByte(P DEVFLASH pThis, RTGCPHYS GCPhysAddr, uint8_t bCmd)75 static int flashMemWriteByte(PFLASHCORE pThis, uint32_t off, uint8_t bCmd) 114 76 { 115 77 int rc = VINF_SUCCESS; … … 127 89 switch (bCmd) 128 90 { 129 case FLASH_CMD_ARRAY_READ:130 case FLASH_CMD_STS_READ:131 case FLASH_CMD_ERASE_SUS_RES:132 case FLASH_CMD_READ_ID:133 /* Single-cycle write commands, only change the current command. */134 pThis->bCmd = bCmd;135 break;136 case FLASH_CMD_STS_CLEAR:137 /* Status clear continues in read mode. */138 pThis->bStatus = 0;139 pThis->bCmd = FLASH_CMD_ARRAY_READ;140 break;141 case FLASH_CMD_WRITE:142 case FLASH_CMD_ALT_WRITE:143 case FLASH_CMD_ERASE_SETUP:144 /* Two-cycle commands, advance the bus write cycle. */145 pThis->bCmd = bCmd;146 pThis->cBusCycle++;147 break;148 default:149 LogFunc(("1st cycle command %02X, current cmd %02X\n", bCmd, pThis->bCmd));150 break;91 case FLASH_CMD_ARRAY_READ: 92 case FLASH_CMD_STS_READ: 93 case FLASH_CMD_ERASE_SUS_RES: 94 case FLASH_CMD_READ_ID: 95 /* Single-cycle write commands, only change the current command. */ 96 pThis->bCmd = bCmd; 97 break; 98 case FLASH_CMD_STS_CLEAR: 99 /* Status clear continues in read mode. */ 100 pThis->bStatus = 0; 101 pThis->bCmd = FLASH_CMD_ARRAY_READ; 102 break; 103 case FLASH_CMD_WRITE: 104 case FLASH_CMD_ALT_WRITE: 105 case FLASH_CMD_ERASE_SETUP: 106 /* Two-cycle commands, advance the bus write cycle. */ 107 pThis->bCmd = bCmd; 108 pThis->cBusCycle++; 109 break; 110 default: 111 LogFunc(("1st cycle command %02X, current cmd %02X\n", bCmd, pThis->bCmd)); 112 break; 151 113 } 152 114 } … … 157 119 switch (pThis->bCmd) 158 120 { 159 case FLASH_CMD_WRITE:160 case FLASH_CMD_ALT_WRITE:161 uOffset = GCPhysAddr& (pThis->cbFlashSize - 1);162 if (uOffset < pThis->cbFlashSize)163 {164 pThis->pbFlash[uOffset] = bCmd;165 /* NB: Writes are instant and never fail. */166 LogFunc(("wrote byte to flash at %08RGp: %02X\n", GCPhysAddr, bCmd));167 }168 else169 LogFunc(("ignoring write at %08RGp: %02X\n", GCPhysAddr, bCmd));170 break;171 case FLASH_CMD_ERASE_SETUP:172 if (bCmd == FLASH_CMD_ERASE_CONFIRM)173 {174 /* The current address determines the block to erase. */175 uOffset = GCPhysAddr& (pThis->cbFlashSize - 1);176 uOffset = uOffset & ~(pThis->cbBlockSize - 1);177 memset(pThis->pbFlash + uOffset, 0xff, pThis->cbBlockSize);178 LogFunc(("Erasing block at offset %u\n", uOffset));179 }180 else181 {182 /* Anything else is a command erorr. Transition to status read mode. */183 LogFunc(("2st cycle erase command is %02X, should be confirm (%02X)\n", bCmd, FLASH_CMD_ERASE_CONFIRM));184 pThis->bCmd = FLASH_CMD_STS_READ;185 pThis->bStatus |= FLASH_STATUS_BWS | FLASH_STATUS_ES;186 }187 break;188 default:189 LogFunc(("2st cycle bad command %02X, current cmd %02X\n", bCmd, pThis->bCmd));190 break;121 case FLASH_CMD_WRITE: 122 case FLASH_CMD_ALT_WRITE: 123 uOffset = off & (pThis->cbFlashSize - 1); 124 if (uOffset < pThis->cbFlashSize) 125 { 126 pThis->pbFlash[uOffset] = bCmd; 127 /* NB: Writes are instant and never fail. */ 128 LogFunc(("wrote byte to flash at %08RX32: %02X\n", off, bCmd)); 129 } 130 else 131 LogFunc(("ignoring write at %08RX32: %02X\n", off, bCmd)); 132 break; 133 case FLASH_CMD_ERASE_SETUP: 134 if (bCmd == FLASH_CMD_ERASE_CONFIRM) 135 { 136 /* The current address determines the block to erase. */ 137 uOffset = off & (pThis->cbFlashSize - 1); 138 uOffset = uOffset & ~(pThis->cbBlockSize - 1); 139 memset(pThis->pbFlash + uOffset, 0xff, pThis->cbBlockSize); 140 LogFunc(("Erasing block at offset %u\n", uOffset)); 141 } 142 else 143 { 144 /* Anything else is a command erorr. Transition to status read mode. */ 145 LogFunc(("2st cycle erase command is %02X, should be confirm (%02X)\n", bCmd, FLASH_CMD_ERASE_CONFIRM)); 146 pThis->bCmd = FLASH_CMD_STS_READ; 147 pThis->bStatus |= FLASH_STATUS_BWS | FLASH_STATUS_ES; 148 } 149 break; 150 default: 151 LogFunc(("2st cycle bad command %02X, current cmd %02X\n", bCmd, pThis->bCmd)); 152 break; 191 153 } 192 154 pThis->cBusCycle = 0; 193 155 } 194 LogFlow(("flashMemWriteByte: write access at %08RGp: %#x rc=%Rrc\n", GCPhysAddr, bCmd, rc)); 195 //LogRel(("flashMemWriteByte: write access at %08RGp: %#x (cmd=%02X) rc=%Rrc\n", GCPhysAddr, bCmd, pThis->bCmd, rc)); 196 return rc; 197 } 198 199 200 static int flashMemReadByte(PDEVFLASH pThis, RTGCPHYS GCPhysAddr, uint8_t *pbData) 156 LogFlow(("flashMemWriteByte: write access at %08RX32: %#x rc=%Rrc\n", off, bCmd, rc)); 157 return rc; 158 } 159 160 161 static int flashMemReadByte(PFLASHCORE pThis, uint32_t off, uint8_t *pbData) 201 162 { 202 163 uint8_t bValue; … … 204 165 int rc = VINF_SUCCESS; 205 166 206 /* Reads are only defined in three states: Array read, status register read, 167 /* 168 * Reads are only defined in three states: Array read, status register read, 207 169 * and ID read. 208 170 */ 209 171 switch (pThis->bCmd) 210 172 { 211 case FLASH_CMD_ARRAY_READ:212 uOffset = GCPhysAddr& (pThis->cbFlashSize - 1);213 bValue = pThis->pbFlash[uOffset];214 LogFunc(("read byte at %08RGp: %02X\n", GCPhysAddr, bValue));215 break;216 case FLASH_CMD_STS_READ:217 bValue = pThis->bStatus;218 break;219 case FLASH_CMD_READ_ID:220 bValue = GCPhysAddr& 1 ? RT_HI_U8(pThis->u16FlashId) : RT_LO_U8(pThis->u16FlashId);221 break;222 default:223 bValue = 0xff;224 break;173 case FLASH_CMD_ARRAY_READ: 174 uOffset = off & (pThis->cbFlashSize - 1); 175 bValue = pThis->pbFlash[uOffset]; 176 LogFunc(("read byte at %08RX32: %02X\n", off, bValue)); 177 break; 178 case FLASH_CMD_STS_READ: 179 bValue = pThis->bStatus; 180 break; 181 case FLASH_CMD_READ_ID: 182 bValue = off & 1 ? RT_HI_U8(pThis->u16FlashId) : RT_LO_U8(pThis->u16FlashId); 183 break; 184 default: 185 bValue = 0xff; 186 break; 225 187 } 226 188 *pbData = bValue; 227 189 228 LogFlow(("flashMemReadByte: read access at %08RGp: %02X (cmd=%02X) rc=%Rrc\n", GCPhysAddr, bValue, pThis->bCmd, rc)); 229 //LogRel(("flashMemReadByte: read access at %08RGp: %02X (cmd=%02X) rc=%Rrc\n", GCPhysAddr, bValue, pThis->bCmd, rc)); 230 return rc; 231 } 232 233 /** @callback_method_impl{FNIOMMIWRITE, Flash memory write} */ 234 PDMBOTHCBDECL(int) flashMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb) 235 { 236 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 190 LogFlow(("flashMemReadByte: read access at %08RX: %02X (cmd=%02X) rc=%Rrc\n", bValue, pThis->bCmd, rc)); 191 return rc; 192 } 193 194 DECLHIDDEN(int) flashWrite(PFLASHCORE pThis, uint32_t off, const void *pv, size_t cb) 195 { 237 196 int rc = VINF_SUCCESS; 238 197 const uint8_t *pu8Mem = (const uint8_t *)pv; 239 unsigned uOffset; 240 RT_NOREF1(pvUser); 241 242 /* Writes may need to go back to R3. If more than one byte is being written (not likely!), 243 * just suck it up and take the trip to R3 immediately. 244 */ 245 /** @todo Idea: We could buffer all writes in R0 and flush them out on a 246 * timer. Probably not worth it. 247 */ 198 248 199 #ifndef IN_RING3 249 200 if (cb > 1) … … 251 202 #endif 252 203 253 for (u Offset = 0; uOffset < cb; ++uOffset)254 { 255 rc = flashMemWriteByte(pThis, GCPhysAddr+ uOffset, pu8Mem[uOffset]);204 for (uint32_t uOffset = 0; uOffset < cb; ++uOffset) 205 { 206 rc = flashMemWriteByte(pThis, off + uOffset, pu8Mem[uOffset]); 256 207 if (!RT_SUCCESS(rc)) 257 208 break; 258 209 } 259 210 260 LogFlow(("FlashMMIOWrite: completed write at %08RGp (LB %u): rc=%Rrc\n", GCPhysAddr, cb, rc)); 261 return rc; 262 } 263 264 265 /** @callback_method_impl{FNIOMMIOREAD, Flash memory read} */ 266 PDMBOTHCBDECL(int) flashMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb) 267 { 268 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 211 LogFlow(("flashWrite: completed write at %08RX32 (LB %u): rc=%Rrc\n", off, cb, rc)); 212 return rc; 213 } 214 215 DECLHIDDEN(int) flashRead(PFLASHCORE pThis, uint32_t off, void *pv, size_t cb) 216 { 269 217 int rc = VINF_SUCCESS; 270 unsigned uOffset; 271 uint8_t *pu8Mem; 272 RT_NOREF1(pvUser); 273 274 /* Reading can always be done witout going back to R3. Reads do not 218 uint8_t *pu8Mem = (uint8_t *)pv; 219 220 /* 221 * Reading can always be done witout going back to R3. Reads do not 275 222 * change the device state and we always have the data. 276 223 */ 277 pu8Mem = (uint8_t *)pv; 278 for (uOffset = 0; uOffset < cb; ++uOffset, ++pu8Mem) 279 { 280 rc = flashMemReadByte(pThis, GCPhysAddr + uOffset, pu8Mem); 224 for (uint32_t uOffset = 0; uOffset < cb; ++uOffset, ++pu8Mem) 225 { 226 rc = flashMemReadByte(pThis, off + uOffset, pu8Mem); 281 227 if (!RT_SUCCESS(rc)) 282 228 break; 283 229 } 284 230 285 LogFlow(("flash MMIORead: completed read at %08RGp (LB %u): rc=%Rrc\n", GCPhysAddr, cb, rc));231 LogFlow(("flashRead: completed read at %08RX32 (LB %u): rc=%Rrc\n", off, cb, rc)); 286 232 return rc; 287 233 } … … 291 237 #ifdef IN_RING3 292 238 293 /** @callback_method_impl{FNSSMDEVSAVEEXEC} */ 294 static DECLCALLBACK(int) flashSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 295 { 296 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 239 DECLHIDDEN(int) flashR3Init(PFLASHCORE pThis, PPDMDEVINS pDevIns, uint16_t idFlashDev, uint32_t cbFlash, uint16_t cbBlock) 240 { 241 pThis->pDevIns = pDevIns; 242 pThis->u16FlashId = idFlashDev; 243 pThis->cbBlockSize = cbBlock; 244 pThis->cbFlashSize = cbFlash; 245 246 /* Set up the flash data. */ 247 pThis->pbFlash = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, pThis->cbFlashSize); 248 if (!pThis->pbFlash) 249 return PDMDEV_SET_ERROR(pDevIns, VERR_NO_MEMORY, N_("Failed to allocate heap memory")); 250 251 /* Default value for empty flash. */ 252 memset(pThis->pbFlash, 0xff, pThis->cbFlashSize); 253 254 /* Reset the dynamic state.*/ 255 flashR3Reset(pThis); 256 return VINF_SUCCESS; 257 } 258 259 DECLHIDDEN(void) flashR3Destruct(PFLASHCORE pThis) 260 { 261 if (pThis->pbFlash) 262 { 263 PDMDevHlpMMHeapFree(pThis->pDevIns, pThis->pbFlash); 264 pThis->pbFlash = NULL; 265 } 266 } 267 268 DECLHIDDEN(int) flashR3LoadFromFile(PFLASHCORE pThis, const char *pszFilename) 269 { 270 RTFILE hFlashFile = NIL_RTFILE; 271 272 int rc = RTFileOpen(&hFlashFile, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); 273 if (RT_FAILURE(rc)) 274 return PDMDEV_SET_ERROR(pThis->pDevIns, rc, N_("Failed to open flash file")); 275 276 size_t cbRead = 0; 277 rc = RTFileRead(hFlashFile, pThis->pbFlash, pThis->cbFlashSize, &cbRead); 278 if (RT_FAILURE(rc)) 279 return PDMDEV_SET_ERROR(pThis->pDevIns, rc, N_("Failed to read flash file")); 280 Log(("Read %zu bytes from file (asked for %u)\n.", cbRead, pThis->cbFlashSize)); 281 282 RTFileClose(hFlashFile); 283 return VINF_SUCCESS; 284 } 285 286 DECLHIDDEN(int) flashR3LoadFromBuf(PFLASHCORE pThis, void *pvBuf, size_t cbBuf) 287 { 288 AssertReturn(pThis->cbFlashSize >= cbBuf, VERR_BUFFER_OVERFLOW); 289 290 memcpy(pThis->pbFlash, pvBuf, RT_MIN(cbBuf, pThis->cbFlashSize)); 291 return VINF_SUCCESS; 292 } 293 294 DECLHIDDEN(int) flashR3SaveToFile(PFLASHCORE pThis, const char *pszFilename) 295 { 296 RTFILE hFlashFile = NIL_RTFILE; 297 298 int rc = RTFileOpen(&hFlashFile, pszFilename, RTFILE_O_READWRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); 299 if (RT_FAILURE(rc)) 300 return PDMDEV_SET_ERROR(pThis->pDevIns, rc, N_("Failed to open flash file")); 301 302 rc = RTFileWrite(hFlashFile, pThis->pbFlash, pThis->cbFlashSize, NULL); 303 if (RT_FAILURE(rc)) 304 return PDMDEV_SET_ERROR(pThis->pDevIns, rc, N_("Failed to write flash file")); 305 306 RTFileClose(hFlashFile); 307 return VINF_SUCCESS; 308 } 309 310 DECLHIDDEN(int) flashR3SaveToBuf(PFLASHCORE pThis, void *pvBuf, size_t cbBuf) 311 { 312 AssertReturn(pThis->cbFlashSize <= cbBuf, VERR_BUFFER_OVERFLOW); 313 314 memcpy(pvBuf, pThis->pbFlash, RT_MIN(cbBuf, pThis->cbFlashSize)); 315 return VINF_SUCCESS; 316 } 317 318 DECLHIDDEN(void) flashR3Reset(PFLASHCORE pThis) 319 { 320 /* 321 * Initialize the device state. 322 */ 323 pThis->bCmd = FLASH_CMD_ARRAY_READ; 324 pThis->bStatus = 0; 325 pThis->cBusCycle = 0; 326 } 327 328 DECLHIDDEN(int) flashR3SsmSaveExec(PFLASHCORE pThis, PSSMHANDLE pSSM) 329 { 330 SSMR3PutU32(pSSM, FLASH_SAVED_STATE_VERSION); 297 331 298 332 /* Save the device state. */ … … 309 343 SSMR3PutMem(pSSM, pThis->pbFlash, pThis->cbFlashSize); 310 344 311 pThis->fStateSaved = true; 312 313 return VINF_SUCCESS; 314 } 315 316 317 /** @callback_method_impl{FNSSMDEVLOADEXEC} */ 318 static DECLCALLBACK(int) flashLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 319 { 320 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 321 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass); 322 323 /* Fend off unsupported versions. */ 324 if (uVersion != FLASH_SAVED_STATE_VERSION) 325 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 345 return VINF_SUCCESS; 346 } 347 348 DECLHIDDEN(int) flashR3SsmLoadExec(PFLASHCORE pThis, PSSMHANDLE pSSM) 349 { 350 uint32_t uVersion = FLASH_SAVED_STATE_VERSION; 351 int rc = SSMR3GetU32(pSSM, &uVersion); 352 AssertRCReturn(rc, rc); 326 353 327 354 /* … … 351 378 SSMR3GetMem(pSSM, pThis->pbFlash, pThis->cbFlashSize); 352 379 } 353 354 return VINF_SUCCESS; 355 } 356 357 /** 358 * @interface_method_impl{PDMDEVREG,pfnReset} 359 */ 360 static DECLCALLBACK(void) flashReset(PPDMDEVINS pDevIns) 361 { 362 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 363 364 /* 365 * Initialize the device state. 366 */ 367 pThis->bCmd = FLASH_CMD_ARRAY_READ; 368 pThis->bStatus = 0; 369 pThis->cBusCycle = 0; 370 } 371 372 /** 373 * @interface_method_impl{PDMDEVREG,pfnDestruct} 374 */ 375 static DECLCALLBACK(int) flashDestruct(PPDMDEVINS pDevIns) 376 { 377 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 378 int rc; 379 380 if (!pThis->fStateSaved) 381 { 382 rc = RTFileSeek(pThis->hFlashFile, 0, RTFILE_SEEK_BEGIN, NULL); 383 rc = RTFileWrite(pThis->hFlashFile, pThis->pbFlash, pThis->cbFlashSize, NULL); 384 if (RT_FAILURE(rc)) 385 LogRel(("flash: Failed to save flash file")); 386 } 387 388 if (pThis->pbFlash) 389 { 390 PDMDevHlpMMHeapFree(pDevIns, pThis->pbFlash); 391 pThis->pbFlash = NULL; 392 } 393 394 if (pThis->pszFlashFile) 395 { 396 PDMDevHlpMMHeapFree(pDevIns, pThis->pszFlashFile); 397 pThis->pszFlashFile = NULL; 398 } 399 400 return VINF_SUCCESS; 401 } 402 403 /** @todo this does not really belong here; workaround for EFI failing to init empty flash. */ 404 static const uint8_t aHdrBegin[] = { 405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 406 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50, 407 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x46, 0x56, 0x48, 0xFF, 0xFE, 0x04, 0x00, 408 0x48, 0x00, 0x19, 0xF9, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x36, 0xCF, 0xDD, 0x75, 0x32, 0x64, 0x41, 410 0x98, 0xB6, 0xFE, 0x85, 0x70, 0x7F, 0xFE, 0x7D, 0xB8, 0xDF, 0x00, 0x00, 0x5A, 0xFE, 0x00, 0x00, 411 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 412 }; 413 414 /** 415 * @interface_method_impl{PDMDEVREG,pfnConstruct} 416 */ 417 static DECLCALLBACK(int) flashConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) 418 { 419 RT_NOREF1(iInstance); 420 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 421 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 422 Assert(iInstance == 0); 423 424 /* 425 * Validate configuration. 426 */ 427 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "DeviceId|BaseAddress|Size|BlockSize|FlashFile", ""); 428 429 /* 430 * Read configuration. 431 */ 432 433 /* The default device ID is Intel 28F800SA. */ 434 int rc = CFGMR3QueryU16Def(pCfg, "DeviceId", &pThis->u16FlashId, 0xA289); 435 if (RT_FAILURE(rc)) 436 return PDMDEV_SET_ERROR(pDevIns, rc, 437 N_("Configuration error: Querying \"DeviceId\" as an integer failed")); 438 439 /* The default base address is 2MB below 4GB. */ 440 rc = CFGMR3QueryU64Def(pCfg, "BaseAddress", &pThis->GCPhysFlashBase, 0xFFE00000); 441 if (RT_FAILURE(rc)) 442 return PDMDEV_SET_ERROR(pDevIns, rc, 443 N_("Configuration error: Querying \"BaseAddress\" as an integer failed")); 444 445 /* The default flash device size is 128K. */ 446 rc = CFGMR3QueryU32Def(pCfg, "Size", &pThis->cbFlashSize, 128 * _1K); 447 if (RT_FAILURE(rc)) 448 return PDMDEV_SET_ERROR(pDevIns, rc, 449 N_("Configuration error: Querying \"Size\" as an integer failed")); 450 451 /* The default flash device block size is 4K. */ 452 rc = CFGMR3QueryU16Def(pCfg, "BlockSize", &pThis->cbBlockSize, 4 * _1K); 453 if (RT_FAILURE(rc)) 454 return PDMDEV_SET_ERROR(pDevIns, rc, 455 N_("Configuration error: Querying \"BlockSize\" as an integer failed")); 456 457 /* The default flash device block size is 4K. */ 458 rc = CFGMR3QueryU16Def(pCfg, "BlockSize", &pThis->cbBlockSize, 4 * _1K); 459 if (RT_FAILURE(rc)) 460 return PDMDEV_SET_ERROR(pDevIns, rc, 461 N_("Configuration error: Querying \"BlockSize\" as an integer failed")); 462 463 rc = CFGMR3QueryStringAlloc(pCfg, "FlashFile", &pThis->pszFlashFile); 464 if (RT_FAILURE(rc)) 465 return PDMDEV_SET_ERROR(pDevIns, rc, 466 N_("Configuration error: Querying \"FlashFile\" as a string failed")); 467 468 /* Try opening the backing file. */ 469 rc = RTFileOpen(&pThis->hFlashFile, pThis->pszFlashFile, RTFILE_O_READWRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); 470 if (RT_FAILURE(rc)) 471 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to open flash file")); 472 473 /* Set up the static state, immutable at run-time. */ 474 pThis->pbFlash = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, pThis->cbFlashSize); 475 if (!pThis->pbFlash) 476 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to allocate heap memory")); 477 478 size_t cbRead = 0; 479 rc = RTFileRead(pThis->hFlashFile, pThis->pbFlash, pThis->cbFlashSize, &cbRead); 480 if (RT_FAILURE(rc)) 481 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to read flash file")); 482 Log(("Read %zu bytes from file (asked for %u)\n.", cbRead, pThis->cbFlashSize)); 483 484 /* If the file didn't exist, or someone truncated it, we'll initialize 485 * the storage with default contents. 486 */ 487 if (cbRead != pThis->cbFlashSize) 488 { 489 memset(pThis->pbFlash, 0xff, pThis->cbFlashSize); 490 memcpy(pThis->pbFlash, aHdrBegin, sizeof(aHdrBegin)); 491 LogRel(("Only read %zu bytes from flash file (asked for %u). Initializing with defaults.\n", cbRead, pThis->cbFlashSize)); 492 } 493 494 /* Reset the dynamic state.*/ 495 flashReset(pDevIns); 496 497 /* 498 * Register MMIO region. 499 */ 500 rc = PDMDevHlpMMIORegister(pDevIns, pThis->GCPhysFlashBase, pThis->cbFlashSize, NULL /*pvUser*/, 501 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, 502 flashMMIOWrite, flashMMIORead, 503 "Flash Memory"); 504 AssertRCReturn(rc, rc); 505 LogRel(("Registered %uKB flash at %RGp\n", pThis->cbFlashSize / _1K, pThis->GCPhysFlashBase)); 506 507 /* 508 * Register saved state. 509 */ 510 rc = PDMDevHlpSSMRegister(pDevIns, FLASH_SAVED_STATE_VERSION, sizeof(*pThis), flashSaveExec, flashLoadExec); 511 if (RT_FAILURE(rc)) 512 return rc; 513 514 return VINF_SUCCESS; 380 else 381 rc = VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 382 383 return rc; 515 384 } 516 385 517 386 #endif /* IN_RING3 */ 518 387 519 /**520 * The device registration structure.521 */522 const PDMDEVREG g_DeviceFlash =523 {524 /* .u32Version = */ PDM_DEVREG_VERSION,525 /* .uReserved0 = */ 0,526 /* .szName = */ "flash",527 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS,528 /* .fClass = */ PDM_DEVREG_CLASS_ARCH,529 /* .cMaxInstances = */ 1,530 /* .uSharedVersion = */ 42,531 /* .cbInstanceShared = */ sizeof(DEVFLASH),532 /* .cbInstanceCC = */ 0,533 /* .cbInstanceRC = */ 0,534 /* .cMaxPciDevices = */ 0,535 /* .cMaxMsixVectors = */ 0,536 /* .pszDescription = */ "Flash Memory Device",537 #if defined(IN_RING3)538 /* .pszRCMod = */ "",539 /* .pszR0Mod = */ "",540 /* .pfnConstruct = */ flashConstruct,541 /* .pfnDestruct = */ flashDestruct,542 /* .pfnRelocate = */ NULL,543 /* .pfnMemSetup = */ NULL,544 /* .pfnPowerOn = */ NULL,545 /* .pfnReset = */ flashReset,546 /* .pfnSuspend = */ NULL,547 /* .pfnResume = */ NULL,548 /* .pfnAttach = */ NULL,549 /* .pfnDetach = */ NULL,550 /* .pfnQueryInterface = */ NULL,551 /* .pfnInitComplete = */ NULL,552 /* .pfnPowerOff = */ NULL,553 /* .pfnSoftReset = */ NULL,554 /* .pfnReserved0 = */ NULL,555 /* .pfnReserved1 = */ NULL,556 /* .pfnReserved2 = */ NULL,557 /* .pfnReserved3 = */ NULL,558 /* .pfnReserved4 = */ NULL,559 /* .pfnReserved5 = */ NULL,560 /* .pfnReserved6 = */ NULL,561 /* .pfnReserved7 = */ NULL,562 #elif defined(IN_RING0)563 /* .pfnEarlyConstruct = */ NULL,564 /* .pfnConstruct = */ NULL,565 /* .pfnDestruct = */ NULL,566 /* .pfnFinalDestruct = */ NULL,567 /* .pfnRequest = */ NULL,568 /* .pfnReserved0 = */ NULL,569 /* .pfnReserved1 = */ NULL,570 /* .pfnReserved2 = */ NULL,571 /* .pfnReserved3 = */ NULL,572 /* .pfnReserved4 = */ NULL,573 /* .pfnReserved5 = */ NULL,574 /* .pfnReserved6 = */ NULL,575 /* .pfnReserved7 = */ NULL,576 #elif defined(IN_RC)577 /* .pfnConstruct = */ NULL,578 /* .pfnReserved0 = */ NULL,579 /* .pfnReserved1 = */ NULL,580 /* .pfnReserved2 = */ NULL,581 /* .pfnReserved3 = */ NULL,582 /* .pfnReserved4 = */ NULL,583 /* .pfnReserved5 = */ NULL,584 /* .pfnReserved6 = */ NULL,585 /* .pfnReserved7 = */ NULL,586 #else587 # error "Not in IN_RING3, IN_RING0 or IN_RC!"588 #endif589 /* .u32VersionEnd = */ PDM_DEVREG_VERSION590 };591 592 388 #endif /* VBOX_DEVICE_STRUCT_TESTCASE */ -
trunk/src/VBox/Devices/EFI/FlashCore.h
r81236 r81250 1 1 /* $Id$ */ 2 2 /** @file 3 * DevFlash -A simple Flash device3 * A simple Flash device 4 4 * 5 5 * A simple non-volatile byte-wide (x8) memory device modeled after Intel 28F008 … … 22 22 */ 23 23 24 #ifndef VBOX_INCLUDED_SRC_EFI_FlashCore_h 25 #define VBOX_INCLUDED_SRC_EFI_FlashCore_h 26 #ifndef RT_WITHOUT_PRAGMA_ONCE 27 # pragma once 28 #endif 24 29 25 30 /********************************************************************************************************************************* 26 31 * Header Files * 27 32 *********************************************************************************************************************************/ 28 #define LOG_GROUP LOG_GROUP_DEV_FLASH29 33 #include <VBox/vmm/pdmdev.h> 30 34 #include <VBox/log.h> … … 36 40 #include "VBoxDD.h" 37 41 42 RT_C_DECLS_BEGIN 38 43 39 44 /********************************************************************************************************************************* … … 44 49 45 50 46 /** @name CUI (Command User Interface) Commands.47 * @{ */48 #define FLASH_CMD_ALT_WRITE 0x1049 #define FLASH_CMD_ERASE_SETUP 0x2050 #define FLASH_CMD_WRITE 0x4051 #define FLASH_CMD_STS_CLEAR 0x5052 #define FLASH_CMD_STS_READ 0x7053 #define FLASH_CMD_READ_ID 0x9054 #define FLASH_CMD_ERASE_SUS_RES 0xB055 #define FLASH_CMD_ERASE_CONFIRM 0xD056 #define FLASH_CMD_ARRAY_READ 0xFF57 /** @} */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 51 /********************************************************************************************************************************* 71 52 * Structures and Typedefs * 72 53 *********************************************************************************************************************************/ 73 54 /** 74 * The flash device 75 */ 76 typedef struct DEVFLASH55 * The flash device core structure. 56 */ 57 typedef struct FLASHCORE 77 58 { 59 /** Owning device instance. */ 60 PPDMDEVINS pDevIns; 78 61 /** The current command. */ 79 62 uint8_t bCmd; … … 90 73 /** The configured block size of the device. */ 91 74 uint16_t cbBlockSize; 92 /** The guest physical memory base address. */93 RTGCPHYS GCPhysFlashBase;94 75 /** The flash memory region size. */ 95 76 uint32_t cbFlashSize; … … 98 79 /** When set, indicates the state was saved. */ 99 80 bool fStateSaved; 100 /** The backing file. */ 101 RTFILE hFlashFile; 102 char *pszFlashFile; 103 } DEVFLASH; 81 } FLASHCORE; 104 82 105 83 /** Pointer to the Flash device state. */ 106 typedef DEVFLASH *PDEVFLASH;84 typedef FLASHCORE *PFLASHCORE; 107 85 108 86 #ifndef VBOX_DEVICE_STRUCT_TESTCASE 109 87 110 111 #ifdef IN_RING3 /* for now */ 112 113 static int flashMemWriteByte(PDEVFLASH pThis, RTGCPHYS GCPhysAddr, uint8_t bCmd) 114 { 115 int rc = VINF_SUCCESS; 116 unsigned uOffset; 117 118 /* NB: Older datasheets (e.g. 28F008SA) suggest that for two-cycle commands like byte write or 119 * erase setup, the address is significant in both cycles, but do not explain what happens 120 * should the addresses not match. Newer datasheets (e.g. 28F008B3) clearly say that the address 121 * in the first byte cycle never matters. We prefer the latter interpretation. 122 */ 123 124 if (pThis->cBusCycle == 0) 125 { 126 /* First bus write cycle, start processing a new command. Address is ignored. */ 127 switch (bCmd) 128 { 129 case FLASH_CMD_ARRAY_READ: 130 case FLASH_CMD_STS_READ: 131 case FLASH_CMD_ERASE_SUS_RES: 132 case FLASH_CMD_READ_ID: 133 /* Single-cycle write commands, only change the current command. */ 134 pThis->bCmd = bCmd; 135 break; 136 case FLASH_CMD_STS_CLEAR: 137 /* Status clear continues in read mode. */ 138 pThis->bStatus = 0; 139 pThis->bCmd = FLASH_CMD_ARRAY_READ; 140 break; 141 case FLASH_CMD_WRITE: 142 case FLASH_CMD_ALT_WRITE: 143 case FLASH_CMD_ERASE_SETUP: 144 /* Two-cycle commands, advance the bus write cycle. */ 145 pThis->bCmd = bCmd; 146 pThis->cBusCycle++; 147 break; 148 default: 149 LogFunc(("1st cycle command %02X, current cmd %02X\n", bCmd, pThis->bCmd)); 150 break; 151 } 152 } 153 else 154 { 155 /* Second write of a two-cycle command. */ 156 Assert(pThis->cBusCycle == 1); 157 switch (pThis->bCmd) 158 { 159 case FLASH_CMD_WRITE: 160 case FLASH_CMD_ALT_WRITE: 161 uOffset = GCPhysAddr & (pThis->cbFlashSize - 1); 162 if (uOffset < pThis->cbFlashSize) 163 { 164 pThis->pbFlash[uOffset] = bCmd; 165 /* NB: Writes are instant and never fail. */ 166 LogFunc(("wrote byte to flash at %08RGp: %02X\n", GCPhysAddr, bCmd)); 167 } 168 else 169 LogFunc(("ignoring write at %08RGp: %02X\n", GCPhysAddr, bCmd)); 170 break; 171 case FLASH_CMD_ERASE_SETUP: 172 if (bCmd == FLASH_CMD_ERASE_CONFIRM) 173 { 174 /* The current address determines the block to erase. */ 175 uOffset = GCPhysAddr & (pThis->cbFlashSize - 1); 176 uOffset = uOffset & ~(pThis->cbBlockSize - 1); 177 memset(pThis->pbFlash + uOffset, 0xff, pThis->cbBlockSize); 178 LogFunc(("Erasing block at offset %u\n", uOffset)); 179 } 180 else 181 { 182 /* Anything else is a command erorr. Transition to status read mode. */ 183 LogFunc(("2st cycle erase command is %02X, should be confirm (%02X)\n", bCmd, FLASH_CMD_ERASE_CONFIRM)); 184 pThis->bCmd = FLASH_CMD_STS_READ; 185 pThis->bStatus |= FLASH_STATUS_BWS | FLASH_STATUS_ES; 186 } 187 break; 188 default: 189 LogFunc(("2st cycle bad command %02X, current cmd %02X\n", bCmd, pThis->bCmd)); 190 break; 191 } 192 pThis->cBusCycle = 0; 193 } 194 LogFlow(("flashMemWriteByte: write access at %08RGp: %#x rc=%Rrc\n", GCPhysAddr, bCmd, rc)); 195 //LogRel(("flashMemWriteByte: write access at %08RGp: %#x (cmd=%02X) rc=%Rrc\n", GCPhysAddr, bCmd, pThis->bCmd, rc)); 196 return rc; 197 } 198 199 200 static int flashMemReadByte(PDEVFLASH pThis, RTGCPHYS GCPhysAddr, uint8_t *pbData) 201 { 202 uint8_t bValue; 203 unsigned uOffset; 204 int rc = VINF_SUCCESS; 205 206 /* Reads are only defined in three states: Array read, status register read, 207 * and ID read. 208 */ 209 switch (pThis->bCmd) 210 { 211 case FLASH_CMD_ARRAY_READ: 212 uOffset = GCPhysAddr & (pThis->cbFlashSize - 1); 213 bValue = pThis->pbFlash[uOffset]; 214 LogFunc(("read byte at %08RGp: %02X\n", GCPhysAddr, bValue)); 215 break; 216 case FLASH_CMD_STS_READ: 217 bValue = pThis->bStatus; 218 break; 219 case FLASH_CMD_READ_ID: 220 bValue = GCPhysAddr & 1 ? RT_HI_U8(pThis->u16FlashId) : RT_LO_U8(pThis->u16FlashId); 221 break; 222 default: 223 bValue = 0xff; 224 break; 225 } 226 *pbData = bValue; 227 228 LogFlow(("flashMemReadByte: read access at %08RGp: %02X (cmd=%02X) rc=%Rrc\n", GCPhysAddr, bValue, pThis->bCmd, rc)); 229 //LogRel(("flashMemReadByte: read access at %08RGp: %02X (cmd=%02X) rc=%Rrc\n", GCPhysAddr, bValue, pThis->bCmd, rc)); 230 return rc; 231 } 232 233 /** @callback_method_impl{FNIOMMIWRITE, Flash memory write} */ 234 PDMBOTHCBDECL(int) flashMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb) 235 { 236 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 237 int rc = VINF_SUCCESS; 238 const uint8_t *pu8Mem = (const uint8_t *)pv; 239 unsigned uOffset; 240 RT_NOREF1(pvUser); 241 242 /* Writes may need to go back to R3. If more than one byte is being written (not likely!), 243 * just suck it up and take the trip to R3 immediately. 244 */ 245 /** @todo Idea: We could buffer all writes in R0 and flush them out on a 246 * timer. Probably not worth it. 247 */ 248 #ifndef IN_RING3 249 if (cb > 1) 250 return VINF_IOM_R3_IOPORT_WRITE; 251 #endif 252 253 for (uOffset = 0; uOffset < cb; ++uOffset) 254 { 255 rc = flashMemWriteByte(pThis, GCPhysAddr + uOffset, pu8Mem[uOffset]); 256 if (!RT_SUCCESS(rc)) 257 break; 258 } 259 260 LogFlow(("FlashMMIOWrite: completed write at %08RGp (LB %u): rc=%Rrc\n", GCPhysAddr, cb, rc)); 261 return rc; 262 } 263 264 265 /** @callback_method_impl{FNIOMMIOREAD, Flash memory read} */ 266 PDMBOTHCBDECL(int) flashMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb) 267 { 268 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 269 int rc = VINF_SUCCESS; 270 unsigned uOffset; 271 uint8_t *pu8Mem; 272 RT_NOREF1(pvUser); 273 274 /* Reading can always be done witout going back to R3. Reads do not 275 * change the device state and we always have the data. 276 */ 277 pu8Mem = (uint8_t *)pv; 278 for (uOffset = 0; uOffset < cb; ++uOffset, ++pu8Mem) 279 { 280 rc = flashMemReadByte(pThis, GCPhysAddr + uOffset, pu8Mem); 281 if (!RT_SUCCESS(rc)) 282 break; 283 } 284 285 LogFlow(("flashMMIORead: completed read at %08RGp (LB %u): rc=%Rrc\n", GCPhysAddr, cb, rc)); 286 return rc; 287 } 288 289 #endif /* IN_RING3 for now */ 290 291 #ifdef IN_RING3 292 293 /** @callback_method_impl{FNSSMDEVSAVEEXEC} */ 294 static DECLCALLBACK(int) flashSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 295 { 296 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 297 298 /* Save the device state. */ 299 SSMR3PutU8(pSSM, pThis->bCmd); 300 SSMR3PutU8(pSSM, pThis->bStatus); 301 SSMR3PutU8(pSSM, pThis->cBusCycle); 302 303 /* Save the current configuration for validation purposes. */ 304 SSMR3PutU16(pSSM, pThis->cbBlockSize); 305 SSMR3PutU16(pSSM, pThis->u16FlashId); 306 307 /* Save the current flash contents. */ 308 SSMR3PutU32(pSSM, pThis->cbFlashSize); 309 SSMR3PutMem(pSSM, pThis->pbFlash, pThis->cbFlashSize); 310 311 pThis->fStateSaved = true; 312 313 return VINF_SUCCESS; 314 } 315 316 317 /** @callback_method_impl{FNSSMDEVLOADEXEC} */ 318 static DECLCALLBACK(int) flashLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 319 { 320 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 321 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass); 322 323 /* Fend off unsupported versions. */ 324 if (uVersion != FLASH_SAVED_STATE_VERSION) 325 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 326 327 /* 328 * Do the actual restoring. 329 */ 330 if (uVersion == FLASH_SAVED_STATE_VERSION) 331 { 332 uint16_t u16Val; 333 uint32_t u32Val; 334 335 SSMR3GetU8(pSSM, &pThis->bCmd); 336 SSMR3GetU8(pSSM, &pThis->bStatus); 337 SSMR3GetU8(pSSM, &pThis->cBusCycle); 338 339 /* Make sure configuration didn't change behind our back. */ 340 SSMR3GetU16(pSSM, &u16Val); 341 if (u16Val != pThis->cbBlockSize) 342 return VERR_SSM_LOAD_CONFIG_MISMATCH; 343 SSMR3GetU16(pSSM, &u16Val); 344 if (u16Val != pThis->u16FlashId) 345 return VERR_SSM_LOAD_CONFIG_MISMATCH; 346 SSMR3GetU32(pSSM, &u32Val); 347 if (u16Val != pThis->cbFlashSize) 348 return VERR_SSM_LOAD_CONFIG_MISMATCH; 349 350 /* Suck in the flash contents. */ 351 SSMR3GetMem(pSSM, pThis->pbFlash, pThis->cbFlashSize); 352 } 353 354 return VINF_SUCCESS; 355 } 356 357 /** 358 * @interface_method_impl{PDMDEVREG,pfnReset} 359 */ 360 static DECLCALLBACK(void) flashReset(PPDMDEVINS pDevIns) 361 { 362 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 363 364 /* 365 * Initialize the device state. 366 */ 367 pThis->bCmd = FLASH_CMD_ARRAY_READ; 368 pThis->bStatus = 0; 369 pThis->cBusCycle = 0; 370 } 371 372 /** 373 * @interface_method_impl{PDMDEVREG,pfnDestruct} 374 */ 375 static DECLCALLBACK(int) flashDestruct(PPDMDEVINS pDevIns) 376 { 377 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 378 int rc; 379 380 if (!pThis->fStateSaved) 381 { 382 rc = RTFileSeek(pThis->hFlashFile, 0, RTFILE_SEEK_BEGIN, NULL); 383 rc = RTFileWrite(pThis->hFlashFile, pThis->pbFlash, pThis->cbFlashSize, NULL); 384 if (RT_FAILURE(rc)) 385 LogRel(("flash: Failed to save flash file")); 386 } 387 388 if (pThis->pbFlash) 389 { 390 PDMDevHlpMMHeapFree(pDevIns, pThis->pbFlash); 391 pThis->pbFlash = NULL; 392 } 393 394 if (pThis->pszFlashFile) 395 { 396 PDMDevHlpMMHeapFree(pDevIns, pThis->pszFlashFile); 397 pThis->pszFlashFile = NULL; 398 } 399 400 return VINF_SUCCESS; 401 } 402 403 /** @todo this does not really belong here; workaround for EFI failing to init empty flash. */ 404 static const uint8_t aHdrBegin[] = { 405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 406 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50, 407 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x46, 0x56, 0x48, 0xFF, 0xFE, 0x04, 0x00, 408 0x48, 0x00, 0x19, 0xF9, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x36, 0xCF, 0xDD, 0x75, 0x32, 0x64, 0x41, 410 0x98, 0xB6, 0xFE, 0x85, 0x70, 0x7F, 0xFE, 0x7D, 0xB8, 0xDF, 0x00, 0x00, 0x5A, 0xFE, 0x00, 0x00, 411 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 412 }; 413 414 /** 415 * @interface_method_impl{PDMDEVREG,pfnConstruct} 416 */ 417 static DECLCALLBACK(int) flashConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) 418 { 419 RT_NOREF1(iInstance); 420 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 421 PDEVFLASH pThis = PDMINS_2_DATA(pDevIns, PDEVFLASH); 422 Assert(iInstance == 0); 423 424 /* 425 * Validate configuration. 426 */ 427 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "DeviceId|BaseAddress|Size|BlockSize|FlashFile", ""); 428 429 /* 430 * Read configuration. 431 */ 432 433 /* The default device ID is Intel 28F800SA. */ 434 int rc = CFGMR3QueryU16Def(pCfg, "DeviceId", &pThis->u16FlashId, 0xA289); 435 if (RT_FAILURE(rc)) 436 return PDMDEV_SET_ERROR(pDevIns, rc, 437 N_("Configuration error: Querying \"DeviceId\" as an integer failed")); 438 439 /* The default base address is 2MB below 4GB. */ 440 rc = CFGMR3QueryU64Def(pCfg, "BaseAddress", &pThis->GCPhysFlashBase, 0xFFE00000); 441 if (RT_FAILURE(rc)) 442 return PDMDEV_SET_ERROR(pDevIns, rc, 443 N_("Configuration error: Querying \"BaseAddress\" as an integer failed")); 444 445 /* The default flash device size is 128K. */ 446 rc = CFGMR3QueryU32Def(pCfg, "Size", &pThis->cbFlashSize, 128 * _1K); 447 if (RT_FAILURE(rc)) 448 return PDMDEV_SET_ERROR(pDevIns, rc, 449 N_("Configuration error: Querying \"Size\" as an integer failed")); 450 451 /* The default flash device block size is 4K. */ 452 rc = CFGMR3QueryU16Def(pCfg, "BlockSize", &pThis->cbBlockSize, 4 * _1K); 453 if (RT_FAILURE(rc)) 454 return PDMDEV_SET_ERROR(pDevIns, rc, 455 N_("Configuration error: Querying \"BlockSize\" as an integer failed")); 456 457 /* The default flash device block size is 4K. */ 458 rc = CFGMR3QueryU16Def(pCfg, "BlockSize", &pThis->cbBlockSize, 4 * _1K); 459 if (RT_FAILURE(rc)) 460 return PDMDEV_SET_ERROR(pDevIns, rc, 461 N_("Configuration error: Querying \"BlockSize\" as an integer failed")); 462 463 rc = CFGMR3QueryStringAlloc(pCfg, "FlashFile", &pThis->pszFlashFile); 464 if (RT_FAILURE(rc)) 465 return PDMDEV_SET_ERROR(pDevIns, rc, 466 N_("Configuration error: Querying \"FlashFile\" as a string failed")); 467 468 /* Try opening the backing file. */ 469 rc = RTFileOpen(&pThis->hFlashFile, pThis->pszFlashFile, RTFILE_O_READWRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); 470 if (RT_FAILURE(rc)) 471 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to open flash file")); 472 473 /* Set up the static state, immutable at run-time. */ 474 pThis->pbFlash = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, pThis->cbFlashSize); 475 if (!pThis->pbFlash) 476 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to allocate heap memory")); 477 478 size_t cbRead = 0; 479 rc = RTFileRead(pThis->hFlashFile, pThis->pbFlash, pThis->cbFlashSize, &cbRead); 480 if (RT_FAILURE(rc)) 481 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to read flash file")); 482 Log(("Read %zu bytes from file (asked for %u)\n.", cbRead, pThis->cbFlashSize)); 483 484 /* If the file didn't exist, or someone truncated it, we'll initialize 485 * the storage with default contents. 486 */ 487 if (cbRead != pThis->cbFlashSize) 488 { 489 memset(pThis->pbFlash, 0xff, pThis->cbFlashSize); 490 memcpy(pThis->pbFlash, aHdrBegin, sizeof(aHdrBegin)); 491 LogRel(("Only read %zu bytes from flash file (asked for %u). Initializing with defaults.\n", cbRead, pThis->cbFlashSize)); 492 } 493 494 /* Reset the dynamic state.*/ 495 flashReset(pDevIns); 496 497 /* 498 * Register MMIO region. 499 */ 500 rc = PDMDevHlpMMIORegister(pDevIns, pThis->GCPhysFlashBase, pThis->cbFlashSize, NULL /*pvUser*/, 501 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, 502 flashMMIOWrite, flashMMIORead, 503 "Flash Memory"); 504 AssertRCReturn(rc, rc); 505 LogRel(("Registered %uKB flash at %RGp\n", pThis->cbFlashSize / _1K, pThis->GCPhysFlashBase)); 506 507 /* 508 * Register saved state. 509 */ 510 rc = PDMDevHlpSSMRegister(pDevIns, FLASH_SAVED_STATE_VERSION, sizeof(*pThis), flashSaveExec, flashLoadExec); 511 if (RT_FAILURE(rc)) 512 return rc; 513 514 return VINF_SUCCESS; 515 } 516 517 #endif /* IN_RING3 */ 518 519 /** 520 * The device registration structure. 521 */ 522 const PDMDEVREG g_DeviceFlash = 523 { 524 /* .u32Version = */ PDM_DEVREG_VERSION, 525 /* .uReserved0 = */ 0, 526 /* .szName = */ "flash", 527 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS, 528 /* .fClass = */ PDM_DEVREG_CLASS_ARCH, 529 /* .cMaxInstances = */ 1, 530 /* .uSharedVersion = */ 42, 531 /* .cbInstanceShared = */ sizeof(DEVFLASH), 532 /* .cbInstanceCC = */ 0, 533 /* .cbInstanceRC = */ 0, 534 /* .cMaxPciDevices = */ 0, 535 /* .cMaxMsixVectors = */ 0, 536 /* .pszDescription = */ "Flash Memory Device", 537 #if defined(IN_RING3) 538 /* .pszRCMod = */ "", 539 /* .pszR0Mod = */ "", 540 /* .pfnConstruct = */ flashConstruct, 541 /* .pfnDestruct = */ flashDestruct, 542 /* .pfnRelocate = */ NULL, 543 /* .pfnMemSetup = */ NULL, 544 /* .pfnPowerOn = */ NULL, 545 /* .pfnReset = */ flashReset, 546 /* .pfnSuspend = */ NULL, 547 /* .pfnResume = */ NULL, 548 /* .pfnAttach = */ NULL, 549 /* .pfnDetach = */ NULL, 550 /* .pfnQueryInterface = */ NULL, 551 /* .pfnInitComplete = */ NULL, 552 /* .pfnPowerOff = */ NULL, 553 /* .pfnSoftReset = */ NULL, 554 /* .pfnReserved0 = */ NULL, 555 /* .pfnReserved1 = */ NULL, 556 /* .pfnReserved2 = */ NULL, 557 /* .pfnReserved3 = */ NULL, 558 /* .pfnReserved4 = */ NULL, 559 /* .pfnReserved5 = */ NULL, 560 /* .pfnReserved6 = */ NULL, 561 /* .pfnReserved7 = */ NULL, 562 #elif defined(IN_RING0) 563 /* .pfnEarlyConstruct = */ NULL, 564 /* .pfnConstruct = */ NULL, 565 /* .pfnDestruct = */ NULL, 566 /* .pfnFinalDestruct = */ NULL, 567 /* .pfnRequest = */ NULL, 568 /* .pfnReserved0 = */ NULL, 569 /* .pfnReserved1 = */ NULL, 570 /* .pfnReserved2 = */ NULL, 571 /* .pfnReserved3 = */ NULL, 572 /* .pfnReserved4 = */ NULL, 573 /* .pfnReserved5 = */ NULL, 574 /* .pfnReserved6 = */ NULL, 575 /* .pfnReserved7 = */ NULL, 576 #elif defined(IN_RC) 577 /* .pfnConstruct = */ NULL, 578 /* .pfnReserved0 = */ NULL, 579 /* .pfnReserved1 = */ NULL, 580 /* .pfnReserved2 = */ NULL, 581 /* .pfnReserved3 = */ NULL, 582 /* .pfnReserved4 = */ NULL, 583 /* .pfnReserved5 = */ NULL, 584 /* .pfnReserved6 = */ NULL, 585 /* .pfnReserved7 = */ NULL, 586 #else 587 # error "Not in IN_RING3, IN_RING0 or IN_RC!" 588 #endif 589 /* .u32VersionEnd = */ PDM_DEVREG_VERSION 590 }; 88 /** 89 * Performs a write to the given flash offset. 90 * 91 * @returns VBox status code. 92 * @param pThis The UART core instance. 93 * @param off Offset to start writing to. 94 * @param pv The value to write. 95 * @param cb Number of bytes to write. 96 */ 97 DECLHIDDEN(int) flashWrite(PFLASHCORE pThis, uint32_t off, const void *pv, size_t cb); 98 99 /** 100 * Performs a read from the given flash offset. 101 * 102 * @returns VBox status code. 103 * @param pThis The UART core instance. 104 * @param off Offset to start reading from. 105 * @param pv Where to store the read data. 106 * @param cb Number of bytes to read. 107 */ 108 DECLHIDDEN(int) flashRead(PFLASHCORE pThis, uint32_t off, void *pv, size_t cb); 109 110 # ifdef IN_RING3 111 112 /** 113 * Initialiizes the given flash device instance. 114 * 115 * @returns VBox status code. 116 * @param pThis The flash device core instance. 117 * @param pDevIns Pointer to the owning device instance. 118 * @param idFlashDev The flash device ID. 119 * @param GCPhysFlashBase Base MMIO address where the flash is located. 120 * @param cbFlash Size of the flash device in bytes. 121 * @param cbBlock Size of a flash block. 122 */ 123 DECLHIDDEN(int) flashR3Init(PFLASHCORE pThis, PPDMDEVINS pDevIns, uint16_t idFlashDev, uint32_t cbFlash, uint16_t cbBlock); 124 125 /** 126 * Destroys the given flash device instance. 127 * 128 * @returns nothing. 129 * @param pThis The flash device core instance. 130 */ 131 DECLHIDDEN(void) flashR3Destruct(PFLASHCORE pThis); 132 133 /** 134 * Loads the flash content from the given file. 135 * 136 * @returns VBox status code. 137 * @param pThis The flash device core instance. 138 * @param pszFilename The file to load the flash content from. 139 */ 140 DECLHIDDEN(int) flashR3LoadFromFile(PFLASHCORE pThis, const char *pszFilename); 141 142 /** 143 * Loads the flash content from the given buffer. 144 * 145 * @returns VBox status code. 146 * @param pThis The flash device core instance. 147 * @param pvBuf The buffer to load the content from. 148 * @param cbBuf Size of the buffer in bytes. 149 */ 150 DECLHIDDEN(int) flashR3LoadFromBuf(PFLASHCORE pThis, void *pvBuf, size_t cbBuf); 151 152 /** 153 * Saves the flash content to the given file. 154 * 155 * @returns VBox status code. 156 * @param pThis The flash device core instance. 157 * @param pszFilename The file to save the flash content to. 158 */ 159 DECLHIDDEN(int) flashR3SaveToFile(PFLASHCORE pThis, const char *pszFilename); 160 161 /** 162 * Saves the flash content to the given buffer. 163 * 164 * @returns VBox status code. 165 * @param pThis The flash device core instance. 166 * @param pvBuf The buffer to save the content to. 167 * @param cbBuf Size of the buffer in bytes. 168 */ 169 DECLHIDDEN(int) flashR3SaveToBuf(PFLASHCORE pThis, void *pvBuf, size_t cbBuf); 170 171 /** 172 * Resets the dynamic part of the flash device state. 173 * 174 * @returns nothing. 175 * @param pThis The flash device core instance. 176 */ 177 DECLHIDDEN(void) flashR3Reset(PFLASHCORE pThis); 178 179 /** 180 * Saves the flash device state to the given SSM handle. 181 * 182 * @returns VBox status code. 183 * @param pThis The flash device core instance. 184 * @param pSSM The SSM handle to save to. 185 */ 186 DECLHIDDEN(int) flashR3SsmSaveExec(PFLASHCORE pThis, PSSMHANDLE pSSM); 187 188 /** 189 * Loads the flash device state from the given SSM handle. 190 * 191 * @returns VBox status code. 192 * @param pThis The flash device core instance. 193 * @param pSSM The SSM handle to load from. 194 */ 195 DECLHIDDEN(int) flashR3SsmLoadExec(PFLASHCORE pThis, PSSMHANDLE pSSM); 196 197 # endif /* IN_RING3 */ 591 198 592 199 #endif /* VBOX_DEVICE_STRUCT_TESTCASE */ 200 201 RT_C_DECLS_END 202 203 #endif /* !VBOX_INCLUDED_SRC_EFI_FlashCore_h */ 204 -
trunk/src/VBox/Devices/Makefile.kmk
r81016 r81250 156 156 EFI/DevSmc.cpp \ 157 157 EFI/DevFlash.cpp \ 158 EFI/FlashCore.cpp \ 158 159 Graphics/DevVGA.cpp \ 159 160 Storage/DevATA.cpp \
Note:
See TracChangeset
for help on using the changeset viewer.