]> git.proxmox.com Git - mirror_edk2.git/blob - QuarkPlatformPkg/Feature/Capsule/Library/PlatformFlashAccessLib/PlatformFlashAccessLibDxe.c
0a6f5405c1dad1319551a015f48ccff0cd5776ab
[mirror_edk2.git] / QuarkPlatformPkg / Feature / Capsule / Library / PlatformFlashAccessLib / PlatformFlashAccessLibDxe.c
1 /** @file
2 Platform Flash Access library.
3
4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <PiDxe.h>
10
11 #include <Library/BaseLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/PcdLib.h>
15 #include <Library/PlatformFlashAccessLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
17 #include <Protocol/Spi.h>
18
19 //
20 // SPI default opcode slots
21 //
22 #define SPI_OPCODE_JEDEC_ID_INDEX 0
23 #define SPI_OPCODE_READ_ID_INDEX 1
24 #define SPI_OPCODE_WRITE_S_INDEX 2
25 #define SPI_OPCODE_WRITE_INDEX 3
26 #define SPI_OPCODE_READ_INDEX 4
27 #define SPI_OPCODE_ERASE_INDEX 5
28 #define SPI_OPCODE_READ_S_INDEX 6
29 #define SPI_OPCODE_CHIP_ERASE_INDEX 7
30
31 #define SPI_ERASE_SECTOR_SIZE SIZE_4KB //This is the chipset requirement
32
33 STATIC EFI_PHYSICAL_ADDRESS mInternalFdAddress;
34 EFI_SPI_PROTOCOL *mSpiProtocol;
35
36 /**
37 Writes specified number of bytes from the input buffer to the address
38
39 @param[in] WriteAddress The flash address to be written.
40 @param[in, out] NumBytes The number of bytes.
41 @param[in] Buffer The data buffer to be written.
42
43 @return The status of flash write.
44 **/
45 EFI_STATUS
46 FlashFdWrite (
47 IN UINTN WriteAddress,
48 IN OUT UINTN *NumBytes,
49 IN UINT8 *Buffer
50 )
51 {
52 EFI_STATUS Status;
53
54 Status = EFI_SUCCESS;
55
56 Status = mSpiProtocol->Execute (
57 mSpiProtocol,
58 SPI_OPCODE_WRITE_INDEX, // OpcodeIndex
59 0, // PrefixOpcodeIndex
60 TRUE, // DataCycle
61 TRUE, // Atomic
62 TRUE, // ShiftOut
63 WriteAddress, // Address
64 (UINT32) (*NumBytes), // Data Number
65 Buffer,
66 EnumSpiRegionBios
67 );
68 DEBUG((DEBUG_INFO, "FlashFdWrite - 0x%x - %r\n", (UINTN)WriteAddress, Status));
69
70 AsmWbinvd ();
71
72 return Status;
73 }
74
75 /**
76 Erase a certain block from address LbaWriteAddress
77
78 @param[in] WriteAddress The flash address to be erased.
79
80 @return The status of flash erase.
81 **/
82 EFI_STATUS
83 FlashFdErase (
84 IN UINTN WriteAddress
85 )
86 {
87 EFI_STATUS Status;
88
89 Status = mSpiProtocol->Execute (
90 mSpiProtocol,
91 SPI_OPCODE_ERASE_INDEX, // OpcodeIndex
92 0, // PrefixOpcodeIndex
93 FALSE, // DataCycle
94 TRUE, // Atomic
95 FALSE, // ShiftOut
96 WriteAddress, // Address
97 0, // Data Number
98 NULL,
99 EnumSpiRegionBios // SPI_REGION_TYPE
100 );
101 DEBUG((DEBUG_INFO, "FlashFdErase - 0x%x - %r\n", (UINTN)WriteAddress, Status));
102
103 AsmWbinvd ();
104
105 return Status;
106 }
107
108 /**
109 Perform flash write operation with progress indicator. The start and end
110 completion percentage values are passed into this function. If the requested
111 flash write operation is broken up, then completion percentage between the
112 start and end values may be passed to the provided Progress function. The
113 caller of this function is required to call the Progress function for the
114 start and end completion percentage values. This allows the Progress,
115 StartPercentage, and EndPercentage parameters to be ignored if the requested
116 flash write operation can not be broken up
117
118 @param[in] FirmwareType The type of firmware.
119 @param[in] FlashAddress The address of flash device to be accessed.
120 @param[in] FlashAddressType The type of flash device address.
121 @param[in] Buffer The pointer to the data buffer.
122 @param[in] Length The length of data buffer in bytes.
123 @param[in] Progress A function used report the progress of the
124 firmware update. This is an optional parameter
125 that may be NULL.
126 @param[in] StartPercentage The start completion percentage value that may
127 be used to report progress during the flash
128 write operation.
129 @param[in] EndPercentage The end completion percentage value that may
130 be used to report progress during the flash
131 write operation.
132
133 @retval EFI_SUCCESS The operation returns successfully.
134 @retval EFI_WRITE_PROTECTED The flash device is read only.
135 @retval EFI_UNSUPPORTED The flash device access is unsupported.
136 @retval EFI_INVALID_PARAMETER The input parameter is not valid.
137 **/
138 EFI_STATUS
139 EFIAPI
140 PerformFlashWriteWithProgress (
141 IN PLATFORM_FIRMWARE_TYPE FirmwareType,
142 IN EFI_PHYSICAL_ADDRESS FlashAddress,
143 IN FLASH_ADDRESS_TYPE FlashAddressType,
144 IN VOID *Buffer,
145 IN UINTN Length,
146 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress, OPTIONAL
147 IN UINTN StartPercentage,
148 IN UINTN EndPercentage
149 )
150 {
151 EFI_STATUS Status;
152 UINTN SectorNum;
153 UINTN Index;
154 UINTN NumBytes;
155
156 DEBUG((DEBUG_INFO, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN)FlashAddress, (UINTN)FlashAddressType, Length));
157 if (FlashAddressType == FlashAddressTypeAbsoluteAddress) {
158 FlashAddress = FlashAddress - mInternalFdAddress;
159 }
160
161 //
162 // Erase & Write
163 //
164 SectorNum = Length / SPI_ERASE_SECTOR_SIZE;
165 for (Index = 0; Index < SectorNum; Index++){
166 if (Progress != NULL) {
167 Progress (StartPercentage + ((Index * (EndPercentage - StartPercentage)) / SectorNum));
168 }
169
170 if (CompareMem(
171 (UINT8 *)(UINTN)(FlashAddress + mInternalFdAddress) + Index * SPI_ERASE_SECTOR_SIZE,
172 (UINT8 *)Buffer + Index * SPI_ERASE_SECTOR_SIZE,
173 SPI_ERASE_SECTOR_SIZE) == 0) {
174 DEBUG((DEBUG_INFO, "Sector - 0x%x - skip\n", Index));
175 continue;
176 }
177 DEBUG((DEBUG_INFO, "Sector - 0x%x - update...\n", Index));
178
179 Status = FlashFdErase (
180 (UINTN)FlashAddress + Index * SPI_ERASE_SECTOR_SIZE
181 );
182 if (Status != EFI_SUCCESS){
183 break;
184 }
185 NumBytes = SPI_ERASE_SECTOR_SIZE;
186 Status = FlashFdWrite (
187 (UINTN)FlashAddress + Index * SPI_ERASE_SECTOR_SIZE,
188 &NumBytes,
189 (UINT8 *)Buffer + Index * SPI_ERASE_SECTOR_SIZE
190 );
191 if (Status != EFI_SUCCESS){
192 break;
193 }
194 }
195 if (Progress != NULL) {
196 Progress (EndPercentage);
197 }
198
199 return EFI_SUCCESS;
200 }
201
202 /**
203 Perform flash write operation.
204
205 @param[in] FirmwareType The type of firmware.
206 @param[in] FlashAddress The address of flash device to be accessed.
207 @param[in] FlashAddressType The type of flash device address.
208 @param[in] Buffer The pointer to the data buffer.
209 @param[in] Length The length of data buffer in bytes.
210
211 @retval EFI_SUCCESS The operation returns successfully.
212 @retval EFI_WRITE_PROTECTED The flash device is read only.
213 @retval EFI_UNSUPPORTED The flash device access is unsupported.
214 @retval EFI_INVALID_PARAMETER The input parameter is not valid.
215 **/
216 EFI_STATUS
217 EFIAPI
218 PerformFlashWrite (
219 IN PLATFORM_FIRMWARE_TYPE FirmwareType,
220 IN EFI_PHYSICAL_ADDRESS FlashAddress,
221 IN FLASH_ADDRESS_TYPE FlashAddressType,
222 IN VOID *Buffer,
223 IN UINTN Length
224 )
225 {
226 return PerformFlashWriteWithProgress (
227 FirmwareType,
228 FlashAddress,
229 FlashAddressType,
230 Buffer,
231 Length,
232 NULL,
233 0,
234 0
235 );
236 }
237
238 /**
239 Platform Flash Access Lib Constructor.
240
241 @param[in] ImageHandle The firmware allocated handle for the EFI image.
242 @param[in] SystemTable A pointer to the EFI System Table.
243
244 @retval EFI_SUCCESS Constructor returns successfully.
245 **/
246 EFI_STATUS
247 EFIAPI
248 PerformFlashAccessLibConstructor (
249 IN EFI_HANDLE ImageHandle,
250 IN EFI_SYSTEM_TABLE *SystemTable
251 )
252 {
253 EFI_STATUS Status;
254
255 mInternalFdAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32(PcdFlashAreaBaseAddress);
256 DEBUG((DEBUG_INFO, "PcdFlashAreaBaseAddress - 0x%x\n", mInternalFdAddress));
257
258 Status = gBS->LocateProtocol(&gEfiSpiProtocolGuid, NULL, (VOID **)&mSpiProtocol);
259 ASSERT_EFI_ERROR(Status);
260
261 return EFI_SUCCESS;
262 }