1 | /** @file
|
---|
2 |
|
---|
3 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
4 |
|
---|
5 | **/
|
---|
6 |
|
---|
7 | #include <Library/BaseLib.h>
|
---|
8 | #include <Library/DebugLib.h>
|
---|
9 |
|
---|
10 | #include "VirtHstiDxe.h"
|
---|
11 |
|
---|
12 | #define WRITE_BYTE_CMD 0x10
|
---|
13 | #define BLOCK_ERASE_CMD 0x20
|
---|
14 | #define CLEAR_STATUS_CMD 0x50
|
---|
15 | #define READ_STATUS_CMD 0x70
|
---|
16 | #define READ_DEVID_CMD 0x90
|
---|
17 | #define BLOCK_ERASE_CONFIRM_CMD 0xd0
|
---|
18 | #define READ_ARRAY_CMD 0xff
|
---|
19 | #define CLEARED_ARRAY_STATUS 0x00
|
---|
20 |
|
---|
21 | /* based on QemuFlashDetected (QemuFlashFvbServicesRuntimeDxe) */
|
---|
22 | UINT32
|
---|
23 | VirtHstiQemuFirmwareFlashCheck (
|
---|
24 | UINT32 Address
|
---|
25 | )
|
---|
26 | {
|
---|
27 | volatile UINT8 *Ptr;
|
---|
28 |
|
---|
29 | UINTN Offset;
|
---|
30 | UINT8 OriginalUint8;
|
---|
31 | UINT8 ProbeUint8;
|
---|
32 |
|
---|
33 | for (Offset = 0; Offset < EFI_PAGE_SIZE; Offset++) {
|
---|
34 | Ptr = (UINT8 *)(UINTN)(Address + Offset);
|
---|
35 | ProbeUint8 = *Ptr;
|
---|
36 | if ((ProbeUint8 != CLEAR_STATUS_CMD) &&
|
---|
37 | (ProbeUint8 != READ_STATUS_CMD) &&
|
---|
38 | (ProbeUint8 != CLEARED_ARRAY_STATUS))
|
---|
39 | {
|
---|
40 | break;
|
---|
41 | }
|
---|
42 | }
|
---|
43 |
|
---|
44 | if (Offset >= EFI_PAGE_SIZE) {
|
---|
45 | DEBUG ((DEBUG_INFO, "%a: check failed\n", __func__));
|
---|
46 | return QEMU_FIRMWARE_FLASH_UNKNOWN;
|
---|
47 | }
|
---|
48 |
|
---|
49 | OriginalUint8 = *Ptr;
|
---|
50 | *Ptr = CLEAR_STATUS_CMD;
|
---|
51 | ProbeUint8 = *Ptr;
|
---|
52 | if ((OriginalUint8 != CLEAR_STATUS_CMD) &&
|
---|
53 | (ProbeUint8 == CLEAR_STATUS_CMD))
|
---|
54 | {
|
---|
55 | *Ptr = OriginalUint8;
|
---|
56 | DEBUG ((DEBUG_INFO, "%a: %p behaves as RAM\n", __func__, Ptr));
|
---|
57 | return QEMU_FIRMWARE_FLASH_IS_RAM;
|
---|
58 | }
|
---|
59 |
|
---|
60 | *Ptr = READ_STATUS_CMD;
|
---|
61 | ProbeUint8 = *Ptr;
|
---|
62 | if (ProbeUint8 == OriginalUint8) {
|
---|
63 | DEBUG ((DEBUG_INFO, "%a: %p behaves as ROM\n", __func__, Ptr));
|
---|
64 | return QEMU_FIRMWARE_FLASH_IS_ROM;
|
---|
65 | }
|
---|
66 |
|
---|
67 | if (ProbeUint8 == READ_STATUS_CMD) {
|
---|
68 | *Ptr = OriginalUint8;
|
---|
69 | DEBUG ((DEBUG_INFO, "%a: %p behaves as RAM\n", __func__, Ptr));
|
---|
70 | return QEMU_FIRMWARE_FLASH_IS_RAM;
|
---|
71 | }
|
---|
72 |
|
---|
73 | if (ProbeUint8 == CLEARED_ARRAY_STATUS) {
|
---|
74 | *Ptr = WRITE_BYTE_CMD;
|
---|
75 | *Ptr = OriginalUint8;
|
---|
76 | *Ptr = READ_STATUS_CMD;
|
---|
77 | ProbeUint8 = *Ptr;
|
---|
78 | *Ptr = READ_ARRAY_CMD;
|
---|
79 | if (ProbeUint8 & 0x10 /* programming error */) {
|
---|
80 | DEBUG ((DEBUG_INFO, "%a: %p behaves as FLASH, write-protected\n", __func__, Ptr));
|
---|
81 | return QEMU_FIRMWARE_FLASH_READ_ONLY;
|
---|
82 | } else {
|
---|
83 | DEBUG ((DEBUG_INFO, "%a: %p behaves as FLASH, writable\n", __func__, Ptr));
|
---|
84 | return QEMU_FIRMWARE_FLASH_WRITABLE;
|
---|
85 | }
|
---|
86 | }
|
---|
87 |
|
---|
88 | DEBUG ((DEBUG_INFO, "%a: check failed\n", __func__));
|
---|
89 | return QEMU_FIRMWARE_FLASH_UNKNOWN;
|
---|
90 | }
|
---|