| /** @file | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include <Library/BaseLib.h> | |
| #include <Library/DebugLib.h> | |
| #include "VirtHstiDxe.h" | |
| #define WRITE_BYTE_CMD 0x10 | |
| #define BLOCK_ERASE_CMD 0x20 | |
| #define CLEAR_STATUS_CMD 0x50 | |
| #define READ_STATUS_CMD 0x70 | |
| #define READ_DEVID_CMD 0x90 | |
| #define BLOCK_ERASE_CONFIRM_CMD 0xd0 | |
| #define READ_ARRAY_CMD 0xff | |
| #define CLEARED_ARRAY_STATUS 0x00 | |
| /* based on QemuFlashDetected (QemuFlashFvbServicesRuntimeDxe) */ | |
| UINT32 | |
| VirtHstiQemuFirmwareFlashCheck ( | |
| UINT32 Address | |
| ) | |
| { | |
| volatile UINT8 *Ptr; | |
| UINTN Offset; | |
| UINT8 OriginalUint8; | |
| UINT8 ProbeUint8; | |
| for (Offset = 0; Offset < EFI_PAGE_SIZE; Offset++) { | |
| Ptr = (UINT8 *)(UINTN)(Address + Offset); | |
| ProbeUint8 = *Ptr; | |
| if ((ProbeUint8 != CLEAR_STATUS_CMD) && | |
| (ProbeUint8 != READ_STATUS_CMD) && | |
| (ProbeUint8 != CLEARED_ARRAY_STATUS)) | |
| { | |
| break; | |
| } | |
| } | |
| if (Offset >= EFI_PAGE_SIZE) { | |
| DEBUG ((DEBUG_INFO, "%a: check failed\n", __func__)); | |
| return QEMU_FIRMWARE_FLASH_UNKNOWN; | |
| } | |
| OriginalUint8 = *Ptr; | |
| *Ptr = CLEAR_STATUS_CMD; | |
| ProbeUint8 = *Ptr; | |
| if ((OriginalUint8 != CLEAR_STATUS_CMD) && | |
| (ProbeUint8 == CLEAR_STATUS_CMD)) | |
| { | |
| *Ptr = OriginalUint8; | |
| DEBUG ((DEBUG_INFO, "%a: %p behaves as RAM\n", __func__, Ptr)); | |
| return QEMU_FIRMWARE_FLASH_IS_RAM; | |
| } | |
| *Ptr = READ_STATUS_CMD; | |
| ProbeUint8 = *Ptr; | |
| if (ProbeUint8 == OriginalUint8) { | |
| DEBUG ((DEBUG_INFO, "%a: %p behaves as ROM\n", __func__, Ptr)); | |
| return QEMU_FIRMWARE_FLASH_IS_ROM; | |
| } | |
| if (ProbeUint8 == READ_STATUS_CMD) { | |
| *Ptr = OriginalUint8; | |
| DEBUG ((DEBUG_INFO, "%a: %p behaves as RAM\n", __func__, Ptr)); | |
| return QEMU_FIRMWARE_FLASH_IS_RAM; | |
| } | |
| if (ProbeUint8 == CLEARED_ARRAY_STATUS) { | |
| *Ptr = WRITE_BYTE_CMD; | |
| *Ptr = OriginalUint8; | |
| *Ptr = READ_STATUS_CMD; | |
| ProbeUint8 = *Ptr; | |
| *Ptr = READ_ARRAY_CMD; | |
| if (ProbeUint8 & 0x10 /* programming error */) { | |
| DEBUG ((DEBUG_INFO, "%a: %p behaves as FLASH, write-protected\n", __func__, Ptr)); | |
| return QEMU_FIRMWARE_FLASH_READ_ONLY; | |
| } else { | |
| DEBUG ((DEBUG_INFO, "%a: %p behaves as FLASH, writable\n", __func__, Ptr)); | |
| return QEMU_FIRMWARE_FLASH_WRITABLE; | |
| } | |
| } | |
| DEBUG ((DEBUG_INFO, "%a: check failed\n", __func__)); | |
| return QEMU_FIRMWARE_FLASH_UNKNOWN; | |
| } |