2 Platform Flash Access library.
4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
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>
20 // SPI default opcode slots
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
31 #define SPI_ERASE_SECTOR_SIZE SIZE_4KB //This is the chipset requirement
33 STATIC EFI_PHYSICAL_ADDRESS mInternalFdAddress
;
34 EFI_SPI_PROTOCOL
*mSpiProtocol
;
37 Writes specified number of bytes from the input buffer to the address
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.
43 @return The status of flash write.
47 IN UINTN WriteAddress
,
48 IN OUT UINTN
*NumBytes
,
56 Status
= mSpiProtocol
->Execute (
58 SPI_OPCODE_WRITE_INDEX
, // OpcodeIndex
59 0, // PrefixOpcodeIndex
63 WriteAddress
, // Address
64 (UINT32
) (*NumBytes
), // Data Number
68 DEBUG((DEBUG_INFO
, "FlashFdWrite - 0x%x - %r\n", (UINTN
)WriteAddress
, Status
));
76 Erase a certain block from address LbaWriteAddress
78 @param[in] WriteAddress The flash address to be erased.
80 @return The status of flash erase.
89 Status
= mSpiProtocol
->Execute (
91 SPI_OPCODE_ERASE_INDEX
, // OpcodeIndex
92 0, // PrefixOpcodeIndex
96 WriteAddress
, // Address
99 EnumSpiRegionBios
// SPI_REGION_TYPE
101 DEBUG((DEBUG_INFO
, "FlashFdErase - 0x%x - %r\n", (UINTN
)WriteAddress
, Status
));
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
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
126 @param[in] StartPercentage The start completion percentage value that may
127 be used to report progress during the flash
129 @param[in] EndPercentage The end completion percentage value that may
130 be used to report progress during the flash
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.
140 PerformFlashWriteWithProgress (
141 IN PLATFORM_FIRMWARE_TYPE FirmwareType
,
142 IN EFI_PHYSICAL_ADDRESS FlashAddress
,
143 IN FLASH_ADDRESS_TYPE FlashAddressType
,
146 IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress
, OPTIONAL
147 IN UINTN StartPercentage
,
148 IN UINTN EndPercentage
156 DEBUG((DEBUG_INFO
, "PerformFlashWrite - 0x%x(%x) - 0x%x\n", (UINTN
)FlashAddress
, (UINTN
)FlashAddressType
, Length
));
157 if (FlashAddressType
== FlashAddressTypeAbsoluteAddress
) {
158 FlashAddress
= FlashAddress
- mInternalFdAddress
;
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
));
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
));
177 DEBUG((DEBUG_INFO
, "Sector - 0x%x - update...\n", Index
));
179 Status
= FlashFdErase (
180 (UINTN
)FlashAddress
+ Index
* SPI_ERASE_SECTOR_SIZE
182 if (Status
!= EFI_SUCCESS
){
185 NumBytes
= SPI_ERASE_SECTOR_SIZE
;
186 Status
= FlashFdWrite (
187 (UINTN
)FlashAddress
+ Index
* SPI_ERASE_SECTOR_SIZE
,
189 (UINT8
*)Buffer
+ Index
* SPI_ERASE_SECTOR_SIZE
191 if (Status
!= EFI_SUCCESS
){
195 if (Progress
!= NULL
) {
196 Progress (EndPercentage
);
203 Perform flash write operation.
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.
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.
219 IN PLATFORM_FIRMWARE_TYPE FirmwareType
,
220 IN EFI_PHYSICAL_ADDRESS FlashAddress
,
221 IN FLASH_ADDRESS_TYPE FlashAddressType
,
226 return PerformFlashWriteWithProgress (
239 Platform Flash Access Lib Constructor.
241 @param[in] ImageHandle The firmware allocated handle for the EFI image.
242 @param[in] SystemTable A pointer to the EFI System Table.
244 @retval EFI_SUCCESS Constructor returns successfully.
248 PerformFlashAccessLibConstructor (
249 IN EFI_HANDLE ImageHandle
,
250 IN EFI_SYSTEM_TABLE
*SystemTable
255 mInternalFdAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)PcdGet32(PcdFlashAreaBaseAddress
);
256 DEBUG((DEBUG_INFO
, "PcdFlashAreaBaseAddress - 0x%x\n", mInternalFdAddress
));
258 Status
= gBS
->LocateProtocol(&gEfiSpiProtocolGuid
, NULL
, (VOID
**)&mSpiProtocol
);
259 ASSERT_EFI_ERROR(Status
);