3 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Library/FlashDeviceLib.h>
14 #include <Library/DebugLib.h>
15 #include <Library/BaseLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
17 #include <Library/UefiRuntimeServicesTableLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/UefiRuntimeLib.h>
20 #include <Protocol/SmmBase2.h>
21 #include <Guid/EventGroup.h>
22 #include "SpiChipDefinitions.h"
24 UINTN FlashDeviceBase
= FLASH_DEVICE_BASE_ADDRESS
;
26 EFI_SPI_PROTOCOL
*mSpiProtocol
= NULL
;
34 EFI_STATUS Status
= EFI_SUCCESS
;
38 SpiAddress
= (UINT32
)(UINTN
)(BaseAddress
) - (UINT32
)FlashDeviceBase
;
39 SectorSize
= SECTOR_SIZE_4KB
;
40 while ( (NumBytes
> 0) && (NumBytes
<= MAX_FWH_SIZE
) ) {
41 Status
= mSpiProtocol
->Execute (
53 if (EFI_ERROR (Status
)) {
56 SpiAddress
+= SectorSize
;
57 NumBytes
-= SectorSize
;
70 EFI_STATUS Status
= EFI_SUCCESS
;
74 SpiAddress
= (UINT32
)(UINTN
)(BaseAddress
) - (UINT32
)FlashDeviceBase
;
75 SectorSize
= SECTOR_SIZE_4KB
;
76 while ( (NumBytes
> 0) && (NumBytes
<= MAX_FWH_SIZE
) ) {
77 Status
= mSpiProtocol
->Execute (
89 if (EFI_ERROR (Status
)) {
92 SpiAddress
+= SectorSize
;
93 NumBytes
-= SectorSize
;
109 UINT32 NumBytes
= (UINT32
)Length
;
113 SpiAddress
= (UINT32
)(UINTN
)(DstBufferPtr
) - (UINT32
)FlashDeviceBase
;
114 Status
= mSpiProtocol
->Execute (
130 Read the Serial Flash Status Registers.
132 @param SpiStatus Pointer to a caller-allocated UINT8. On successful return, it contains the
133 status data read from the Serial Flash Status Register.
136 @retval EFI_SUCCESS Operation success, status is returned in SpiStatus.
137 @retval EFI_DEVICE_ERROR The block device is not functioning correctly and the operation failed.
147 Status
= mSpiProtocol
->Execute (
164 IN UINT8
*BaseAddress
,
180 // Always disable block protection to workaround tool issue.
181 // Feature may be re-enabled in a future bios.
184 Status
= mSpiProtocol
->Execute (
196 if (EFI_ERROR (Status
)) {
200 Status
= ReadStatusRegister (&SpiStatus
);
201 if (EFI_ERROR (Status
)) {
205 if ((SpiStatus
& SpiData
) != SpiData
) {
206 Status
= EFI_DEVICE_ERROR
;
214 Read NumBytes bytes of data from the address specified by
215 PAddress into Buffer.
217 @param[in] PAddress The starting physical address of the read.
218 @param[in,out] NumBytes On input, the number of bytes to read. On output, the number
219 of bytes actually read.
220 @param[out] Buffer The destination data buffer for the read.
222 @retval EFI_SUCCESS. Opertion is successful.
223 @retval EFI_DEVICE_ERROR If there is any device errors.
228 LibFvbFlashDeviceRead (
230 IN OUT UINTN
*NumBytes
,
234 CopyMem(Buffer
, (VOID
*)PAddress
, *NumBytes
);
240 Write NumBytes bytes of data from Buffer to the address specified by
243 @param[in] PAddress The starting physical address of the write.
244 @param[in,out] NumBytes On input, the number of bytes to write. On output,
245 the actual number of bytes written.
246 @param[in] Buffer The source data buffer for the write.
248 @retval EFI_SUCCESS. Opertion is successful.
249 @retval EFI_DEVICE_ERROR If there is any device errors.
254 LibFvbFlashDeviceWrite (
256 IN OUT UINTN
*NumBytes
,
261 Status
= SpiFlashWrite((UINT8
*)PAddress
, Buffer
, *NumBytes
);
267 Erase the block staring at PAddress.
269 @param[in] PAddress The starting physical address of the block to be erased.
270 This library assume that caller garantee that the PAddress
271 is at the starting address of this block.
272 @param[in] LbaLength The length of the logical block to be erased.
274 @retval EFI_SUCCESS. Opertion is successful.
275 @retval EFI_DEVICE_ERROR If there is any device errors.
280 LibFvbFlashDeviceBlockErase (
286 Status
= SpiFlashBlockErase((UINT8
*)PAddress
, LbaLength
);
293 Lock or unlock the block staring at PAddress.
295 @param[in] PAddress The starting physical address of region to be (un)locked.
296 @param[in] LbaLength The length of the logical block to be erased.
297 @param[in] Lock TRUE to lock. FALSE to unlock.
299 @retval EFI_SUCCESS. Opertion is successful.
300 @retval EFI_DEVICE_ERROR If there is any device errors.
305 LibFvbFlashDeviceBlockLock (
313 Status
= SpiFlashLock((UINT8
*)PAddress
, LbaLength
, Lock
);
319 LibFvbFlashDeviceVirtualAddressChangeNotifyEvent (
324 gRT
->ConvertPointer (0, (VOID
**) &mSpiProtocol
);
325 gRT
->ConvertPointer (0, (VOID
**) &FlashDeviceBase
);
330 The library constructuor.
332 The function does the necessary initialization work for this library
333 instance. Please put all initialization works in it.
335 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
336 @param[in] SystemTable A pointer to the EFI system table.
338 @retval EFI_SUCCESS The function always return EFI_SUCCESS for now.
339 It will ASSERT on error for debug version.
340 @retval EFI_ERROR Please reference LocateProtocol for error code details.
345 LibFvbFlashDeviceSupportInit (
346 IN EFI_HANDLE ImageHandle
,
347 IN EFI_SYSTEM_TABLE
*SystemTable
355 UINT8 SpiNotMatchError
;
356 EFI_SMM_BASE2_PROTOCOL
*SmmBase
;
360 SpiNotMatchError
= 0x00;
363 Status
= gBS
->LocateProtocol (
364 &gEfiSmmBase2ProtocolGuid
,
368 if (!EFI_ERROR(Status
)) {
369 Status
= SmmBase
->InSmm(SmmBase
, &InSmm
);
370 if (EFI_ERROR(Status
)) {
376 Status
= gBS
->LocateProtocol (
377 &gEfiSpiProtocolGuid
,
379 (VOID
**)&mSpiProtocol
381 ASSERT_EFI_ERROR (Status
);
383 Status
= gBS
->CreateEventEx (
386 LibFvbFlashDeviceVirtualAddressChangeNotifyEvent
,
388 &gEfiEventVirtualAddressChangeGuid
,
391 ASSERT_EFI_ERROR (Status
);
393 Status
= gBS
->LocateProtocol (
394 &gEfiSmmSpiProtocolGuid
,
396 (VOID
**)&mSpiProtocol
398 ASSERT_EFI_ERROR (Status
);
402 for (FlashIndex
= EnumSpiFlashW25Q64
; FlashIndex
< EnumSpiFlashMax
; FlashIndex
++) {
403 Status
= mSpiProtocol
->Init (mSpiProtocol
, &(mInitTable
[FlashIndex
]));
404 if (!EFI_ERROR (Status
)) {
406 // Read Vendor/Device IDs to check if the driver supports the Serial Flash device.
408 Status
= mSpiProtocol
->Execute (
420 if (!EFI_ERROR (Status
)) {
421 if ((SfId
[0] == mInitTable
[FlashIndex
].VendorId
) &&
422 (SfId
[1] == mInitTable
[FlashIndex
].DeviceId0
) &&
423 (SfId
[2] == mInitTable
[FlashIndex
].DeviceId1
)) {
425 // Found a matching SPI device, FlashIndex now contains flash device.
427 DEBUG ((DEBUG_ERROR
, "OK - Found SPI Flash Type in SPI Flash Driver, Device Type ID 0 = 0x%02x!\n", mInitTable
[FlashIndex
].DeviceId0
));
428 DEBUG ((DEBUG_ERROR
, "Device Type ID 1 = 0x%02x!\n", mInitTable
[FlashIndex
].DeviceId1
));
430 if (mInitTable
[FlashIndex
].BiosStartOffset
== (UINTN
) (-1)) {
431 DEBUG ((DEBUG_ERROR
, "ERROR - The size of BIOS image is bigger than SPI Flash device!\n"));
444 DEBUG ((DEBUG_ERROR
, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId
[0], SfId
[1], SfId
[2]));
446 if (FlashIndex
< EnumSpiFlashMax
) {
449 if (SpiReadError
!= 0) {
450 DEBUG ((DEBUG_ERROR
, "ERROR - SPI Read ID execution failed! Error Count = %d\n", SpiReadError
));
453 if (SpiNotMatchError
!= 0) {
454 DEBUG ((DEBUG_ERROR
, "ERROR - No supported SPI flash chip found! Error Count = %d\n", SpiNotMatchError
));
455 DEBUG ((DEBUG_ERROR
, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId
[0], SfId
[1], SfId
[2]));
458 return EFI_UNSUPPORTED
;