MdeModulePkg/SpiNorFlashJedecSfdp: SPI NOR Flash JEDEC SFDP
BZ#: 4471 SPI NOR Flash JEDEC Serial Flash Discoverable Driver implementation. Signed-off-by: Abner Chang <abner.chang@amd.com> Cc: Hao A Wu <hao.a.wu@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Abdul Lateef Attar <abdattar@amd.com> Cc: Brit Chesley <brit.chesley@amd.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
This commit is contained in:
1141
MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlash.c
Normal file
1141
MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlash.c
Normal file
File diff suppressed because it is too large
Load Diff
286
MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlash.h
Normal file
286
MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlash.h
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
/** @file
|
||||||
|
Definitions of SPI NOR flash operation functions.
|
||||||
|
|
||||||
|
Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef SPI_NOR_FLASH_H_
|
||||||
|
#define SPI_NOR_FLASH_H_
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
#include <Protocol/SpiNorFlash.h>
|
||||||
|
#include <Protocol/SpiIo.h>
|
||||||
|
#include "SpiNorFlashJedecSfdpInternal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fill Write Buffer with Opcode, Address, Dummy Bytes, and Data
|
||||||
|
|
||||||
|
@param[in] Opcode - Opcode for transaction
|
||||||
|
@param[in] Address - SPI Offset Start Address
|
||||||
|
@param[in] WriteBytes - Number of bytes to write to SPI device
|
||||||
|
@param[in] WriteBuffer - Buffer containing bytes to write to SPI device
|
||||||
|
|
||||||
|
@retval Size of Data in Buffer
|
||||||
|
**/
|
||||||
|
UINT32
|
||||||
|
FillWriteBuffer (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *SpiNorFlashInstance,
|
||||||
|
IN UINT8 Opcode,
|
||||||
|
IN UINT32 DummyBytes,
|
||||||
|
IN UINT8 AddressBytesSupported,
|
||||||
|
IN BOOLEAN UseAddress,
|
||||||
|
IN UINT32 Address,
|
||||||
|
IN UINT32 WriteBytes,
|
||||||
|
IN UINT8 *WriteBuffer
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set Write Enable Latch
|
||||||
|
|
||||||
|
@param[in] Instance SPI NOR instance with all protocols, etc.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS SPI Write Enable succeeded
|
||||||
|
@retval EFI_DEVICE_ERROR SPI Flash part did not respond properly
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
SetWel (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *SpiNorFlashInstance
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check for not device write in progress
|
||||||
|
|
||||||
|
@param[in] Instance SPI NOR instance with all protocols, etc.
|
||||||
|
@param[in] Timeout Timeout in microsecond
|
||||||
|
@param[in] RetryCount The retry count
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Device does not have a write in progress
|
||||||
|
@retval EFI_DEVICE_ERROR SPI Flash part did not respond properly
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
WaitNotWip (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *SpiNorFlashInstance,
|
||||||
|
IN UINT32 Timeout,
|
||||||
|
IN UINT32 RetryCount
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check for write enable latch set and not device write in progress
|
||||||
|
|
||||||
|
@param[in] Instance SPI NOR instance with all protocols, etc.
|
||||||
|
@param[in] Timeout Timeout in microsecond
|
||||||
|
@param[in] RetryCount The retry count
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Device does not have a write in progress and
|
||||||
|
write enable latch is set
|
||||||
|
@retval EFI_DEVICE_ERROR SPI Flash part did not respond properly
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
WaitWelNotWip (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *SpiNorFlashInstance,
|
||||||
|
IN UINT32 Timeout,
|
||||||
|
IN UINT32 RetryCount
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check for not write enable latch set and not device write in progress
|
||||||
|
|
||||||
|
@param[in] Instance SPI NOR instance with all protocols, etc.
|
||||||
|
@param[in] Timeout Timeout in microsecond
|
||||||
|
@param[in] RetryCount The retry count
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Device does not have a write in progress and
|
||||||
|
write enable latch is not set
|
||||||
|
@retval EFI_DEVICE_ERROR SPI Flash part did not respond properly
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
WaitNotWelNotWip (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *SpiNorFlashInstance,
|
||||||
|
IN UINT32 Timeout,
|
||||||
|
IN UINT32 RetryCount
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read the 3 byte manufacture and device ID from the SPI flash.
|
||||||
|
|
||||||
|
This routine must be called at or below TPL_NOTIFY.
|
||||||
|
This routine reads the 3 byte manufacture and device ID from the flash part
|
||||||
|
filling the buffer provided.
|
||||||
|
|
||||||
|
@param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data structure.
|
||||||
|
@param[out] Buffer Pointer to a 3 byte buffer to receive the manufacture and
|
||||||
|
device ID.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The manufacture and device ID was read
|
||||||
|
successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER Buffer is NULL
|
||||||
|
@retval EFI_DEVICE_ERROR Invalid data received from SPI flash part.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
GetFlashId (
|
||||||
|
IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
|
||||||
|
OUT UINT8 *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read data from the SPI flash.
|
||||||
|
|
||||||
|
This routine must be called at or below TPL_NOTIFY.
|
||||||
|
This routine reads data from the SPI part in the buffer provided.
|
||||||
|
|
||||||
|
@param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data
|
||||||
|
structure.
|
||||||
|
@param[in] FlashAddress Address in the flash to start reading
|
||||||
|
@param[in] LengthInBytes Read length in bytes
|
||||||
|
@param[out] Buffer Address of a buffer to receive the data
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The data was read successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER Buffer is NULL, or
|
||||||
|
FlashAddress >= This->FlashSize, or
|
||||||
|
LengthInBytes > This->FlashSize - FlashAddress
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ReadData (
|
||||||
|
IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
|
||||||
|
IN UINT32 FlashAddress,
|
||||||
|
IN UINT32 LengthInBytes,
|
||||||
|
OUT UINT8 *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read data from the SPI flash at not fast speed
|
||||||
|
|
||||||
|
This routine must be called at or below TPL_NOTIFY.
|
||||||
|
This routine reads data from the SPI part in the buffer provided.
|
||||||
|
|
||||||
|
@param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data
|
||||||
|
structure.
|
||||||
|
@param[in] FlashAddress Address in the flash to start reading
|
||||||
|
@param[in] LengthInBytes Read length in bytes
|
||||||
|
@param[out] Buffer Address of a buffer to receive the data
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The data was read successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER Buffer is NULL, or
|
||||||
|
FlashAddress >= This->FlashSize, or
|
||||||
|
LengthInBytes > This->FlashSize - FlashAddress
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
LfReadData (
|
||||||
|
IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
|
||||||
|
IN UINT32 FlashAddress,
|
||||||
|
IN UINT32 LengthInBytes,
|
||||||
|
OUT UINT8 *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read the flash status register.
|
||||||
|
|
||||||
|
This routine must be called at or below TPL_NOTIFY.
|
||||||
|
This routine reads the flash part status register.
|
||||||
|
|
||||||
|
@param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data
|
||||||
|
structure.
|
||||||
|
@param[in] LengthInBytes Number of status bytes to read.
|
||||||
|
@param[out] FlashStatus Pointer to a buffer to receive the flash status.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The status register was read successfully.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ReadStatus (
|
||||||
|
IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
|
||||||
|
IN UINT32 LengthInBytes,
|
||||||
|
OUT UINT8 *FlashStatus
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write the flash status register.
|
||||||
|
|
||||||
|
This routine must be called at or below TPL_N OTIFY.
|
||||||
|
This routine writes the flash part status register.
|
||||||
|
|
||||||
|
@param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data
|
||||||
|
structure.
|
||||||
|
@param[in] LengthInBytes Number of status bytes to write.
|
||||||
|
@param[in] FlashStatus Pointer to a buffer containing the new status.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The status write was successful.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate the write buffer.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
WriteStatus (
|
||||||
|
IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
|
||||||
|
IN UINT32 LengthInBytes,
|
||||||
|
IN UINT8 *FlashStatus
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write data to the SPI flash.
|
||||||
|
|
||||||
|
This routine must be called at or below TPL_NOTIFY.
|
||||||
|
This routine breaks up the write operation as necessary to write the data to
|
||||||
|
the SPI part.
|
||||||
|
|
||||||
|
@param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data
|
||||||
|
structure.
|
||||||
|
@param[in] FlashAddress Address in the flash to start writing
|
||||||
|
@param[in] LengthInBytes Write length in bytes
|
||||||
|
@param[in] Buffer Address of a buffer containing the data
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The data was written successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER Buffer is NULL, or
|
||||||
|
FlashAddress >= This->FlashSize, or
|
||||||
|
LengthInBytes > This->FlashSize - FlashAddress
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Insufficient memory to copy buffer.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
WriteData (
|
||||||
|
IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
|
||||||
|
IN UINT32 FlashAddress,
|
||||||
|
IN UINT32 LengthInBytes,
|
||||||
|
IN UINT8 *Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Efficiently erases one or more 4KiB regions in the SPI flash.
|
||||||
|
|
||||||
|
This routine must be called at or below TPL_NOTIFY.
|
||||||
|
This routine uses a combination of 4 KiB and larger blocks to erase the
|
||||||
|
specified area.
|
||||||
|
|
||||||
|
@param[in] This Pointer to an EFI_SPI_NOR_FLASH_PROTOCOL data
|
||||||
|
structure.
|
||||||
|
@param[in] FlashAddress Address within a 4 KiB block to start erasing
|
||||||
|
@param[in] BlockCount Number of 4 KiB blocks to erase
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The erase was completed successfully.
|
||||||
|
@retval EFI_INVALID_PARAMETER FlashAddress >= This->FlashSize, or
|
||||||
|
BlockCount * 4 KiB
|
||||||
|
> This->FlashSize - FlashAddress
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
Erase (
|
||||||
|
IN CONST EFI_SPI_NOR_FLASH_PROTOCOL *This,
|
||||||
|
IN UINT32 FlashAddress,
|
||||||
|
IN UINT32 BlockCount
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif // SPI_NOR_FLASH_H_
|
1780
MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlashJedecSfdp.c
Normal file
1780
MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlashJedecSfdp.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,261 @@
|
|||||||
|
/** @file
|
||||||
|
SPI NOR Flash JEDEC Serial Flash Discoverable Parameters (SFDP)
|
||||||
|
DXE driver.
|
||||||
|
|
||||||
|
Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
@par Revision Reference:
|
||||||
|
- JEDEC Standard, JESD216F.02
|
||||||
|
https://www.jedec.org/document_search?search_api_views_fulltext=JESD216
|
||||||
|
|
||||||
|
@par Glossary:
|
||||||
|
- SFDP - Serial Flash Discoverable Parameters
|
||||||
|
- PTP - Parameter Table Pointer
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <Base.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
#include <Protocol/SpiConfiguration.h>
|
||||||
|
#include <Protocol/SpiNorFlash.h>
|
||||||
|
#include <Protocol/SpiIo.h>
|
||||||
|
#include <IndustryStandard/SpiNorFlashJedecSfdp.h>
|
||||||
|
#include "SpiNorFlash.h"
|
||||||
|
#include "SpiNorFlashJedecSfdpInternal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Function to create SPI_NOR_FLASH_INSTANCE for this SPI part.
|
||||||
|
|
||||||
|
@param[in] SpiIoHandle The handle with SPI I/O protocol installed.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Succeed.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Not enough resource to create SPI_NOR_FLASH_INSTANCE.
|
||||||
|
@retval otherwise Fail to create SPI NOR Flash SFDP Instance
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
CreateSpiNorFlashSfdpInstance (
|
||||||
|
IN EFI_HANDLE SpiIoHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
SPI_NOR_FLASH_INSTANCE *Instance;
|
||||||
|
|
||||||
|
// Allocate SPI_NOR_FLASH_INSTANCE Instance.
|
||||||
|
Instance = AllocateZeroPool (sizeof (SPI_NOR_FLASH_INSTANCE));
|
||||||
|
ASSERT (Instance != NULL);
|
||||||
|
if (Instance == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locate the SPI IO Protocol
|
||||||
|
Status = gBS->HandleProtocol (
|
||||||
|
SpiIoHandle,
|
||||||
|
&gEdk2JedecSfdpSpiDxeDriverGuid,
|
||||||
|
(VOID **)&Instance->SpiIo
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "%a: Fail to locate SPI I/O protocol\n", __func__));
|
||||||
|
FreePool (Instance);
|
||||||
|
} else {
|
||||||
|
Status = InitialSpiNorFlashSfdpInstance (Instance);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "%a: Fail to initial SPI_NOR_FLASH_INSTANCE.\n", __func__));
|
||||||
|
FreePool (Instance);
|
||||||
|
} else {
|
||||||
|
// Install SPI NOR Flash Protocol.
|
||||||
|
Status = gBS->InstallProtocolInterface (
|
||||||
|
&Instance->Handle,
|
||||||
|
&gEfiSpiNorFlashProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
&Instance->Protocol
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "%a: Fail to Install gEfiSpiNorFlashProtocolGuid protocol.\n", __func__));
|
||||||
|
FreePool (Instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Callback function executed when the EFI_SPI_IO_PROTOCOL
|
||||||
|
protocol interface is installed.
|
||||||
|
|
||||||
|
@param[in] Event Event whose notification function is being invoked.
|
||||||
|
@param[out] Context Pointer to SPI I/O protocol GUID.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SpiIoProtocolInstalledCallback (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
OUT VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN InstanceBufferSize;
|
||||||
|
EFI_HANDLE InstanceBuffer;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: Entry.\n", __func__));
|
||||||
|
InstanceBufferSize = sizeof (EFI_HANDLE);
|
||||||
|
Status = gBS->LocateHandle (
|
||||||
|
ByRegisterNotify,
|
||||||
|
(EFI_GUID *)Context,
|
||||||
|
NULL,
|
||||||
|
&InstanceBufferSize,
|
||||||
|
&InstanceBuffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Can't locate SPI I/O protocol.\n"));
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: Exit.\n", __func__));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateSpiNorFlashSfdpInstance (InstanceBuffer);
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: Exit.\n", __func__));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Register for the later installed SPI I/O protocol notification.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Succeed.
|
||||||
|
@retval otherwise Fail to register SPI I/O protocol installed
|
||||||
|
notification.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
RegisterSpioProtocolNotification (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_EVENT Event;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
VOID *Registration;
|
||||||
|
|
||||||
|
Status = gBS->CreateEvent (
|
||||||
|
EVT_NOTIFY_SIGNAL,
|
||||||
|
TPL_CALLBACK,
|
||||||
|
SpiIoProtocolInstalledCallback,
|
||||||
|
NULL,
|
||||||
|
&Event
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "%a: Fail to create event for the SPI I/O Protocol installation.", __func__));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gBS->RegisterProtocolNotify (
|
||||||
|
&gEdk2JedecSfdpSpiDxeDriverGuid,
|
||||||
|
Event,
|
||||||
|
&Registration
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "%a: Fail to register event for the SPI I/O Protocol installation.", __func__));
|
||||||
|
} else {
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: Notification for SPI I/O Protocol installation was registered.", __func__));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Entry point of the Macronix SPI NOR Flash driver.
|
||||||
|
|
||||||
|
@param ImageHandle Image handle of this driver.
|
||||||
|
@param SystemTable Pointer to standard EFI system table.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Succeed.
|
||||||
|
@retval EFI_NOT_FOUND No gEdk2JedecSfdpSpiSmmDriverGuid installed on
|
||||||
|
system yet.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Not enough resource for SPI NOR Flash JEDEC SFDP
|
||||||
|
initialization.
|
||||||
|
@retval Otherwise Other errors.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SpiNorFlashJedecSfdpDxeEntry (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_HANDLE *InstanceBuffer;
|
||||||
|
UINTN InstanceIndex;
|
||||||
|
UINTN InstanceBufferSize;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "%a - ENTRY\n", __func__));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register notification for the later SPI I/O protocol installation.
|
||||||
|
//
|
||||||
|
RegisterSpioProtocolNotification ();
|
||||||
|
DEBUG ((DEBUG_INFO, "Check if there were already some gEdk2JedecSfdpSpiDxeDriverGuid handles installed.\n"));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check if there were already some gEdk2JedecSfdpSpiDxeDriverGuid
|
||||||
|
// handles installed.
|
||||||
|
//
|
||||||
|
// Locate the SPI I/O Protocol for the SPI flash part
|
||||||
|
// that supports JEDEC SFDP specification.
|
||||||
|
//
|
||||||
|
InstanceBufferSize = 0;
|
||||||
|
InstanceBuffer = NULL;
|
||||||
|
Status = gBS->LocateHandle (
|
||||||
|
ByProtocol,
|
||||||
|
&gEdk2JedecSfdpSpiDxeDriverGuid,
|
||||||
|
NULL,
|
||||||
|
&InstanceBufferSize,
|
||||||
|
InstanceBuffer
|
||||||
|
);
|
||||||
|
if (Status == EFI_NOT_FOUND) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"No gEdk2JedecSfdpSpiSmmDriverGuid handles found at the moment, wait for the notification of SPI I/O protocol installation.\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: EXIT - Status=%r\n", __func__, Status));
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
} else if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||||
|
InstanceBuffer = (EFI_HANDLE *)AllocateZeroPool (InstanceBufferSize);
|
||||||
|
ASSERT (InstanceBuffer != NULL);
|
||||||
|
if (InstanceBuffer == NULL) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Not enough resource for gEdk2JedecSfdpSpiDxeDriverGuid handles.\n"));
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: EXIT - Status=%r\n", __func__, Status));
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
} else if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Error to locate gEdk2JedecSfdpSpiDxeDriverGuid - Status = %r.\n", Status));
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: EXIT - Status=%r\n", __func__, Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gBS->LocateHandle (
|
||||||
|
ByProtocol,
|
||||||
|
&gEdk2JedecSfdpSpiDxeDriverGuid,
|
||||||
|
NULL,
|
||||||
|
&InstanceBufferSize,
|
||||||
|
InstanceBuffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Fail to locate all gEdk2JedecSfdpSpiDxeDriverGuid handles.\n"));
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: EXIT - Status=%r\n", __func__, Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "%d of gEdk2JedecSfdpSpiDxeDriverGuid are found.\n", InstanceBufferSize / sizeof (EFI_HANDLE)));
|
||||||
|
for (InstanceIndex = 0; InstanceIndex < InstanceBufferSize / sizeof (EFI_HANDLE); InstanceIndex++) {
|
||||||
|
Status = CreateSpiNorFlashSfdpInstance (*(InstanceBuffer + InstanceIndex));
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Fail to create SPI NOR Flash SFDP instance #%d.\n", InstanceIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: EXIT - Status=%r\n", __func__, Status));
|
||||||
|
return Status;
|
||||||
|
}
|
@@ -0,0 +1,64 @@
|
|||||||
|
## @file
|
||||||
|
# The SPI NOR Flash JEDEC Serial Flash Discoverable Parameters (SFDP)
|
||||||
|
# DXE driver INF file.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
#
|
||||||
|
# @par Revision Reference:
|
||||||
|
# - JEDEC Standard, JESD216F.02
|
||||||
|
# https://www.jedec.org/document_search?search_api_views_fulltext=JESD216
|
||||||
|
#
|
||||||
|
# @par Glossary:
|
||||||
|
# - SFDP - Serial Flash Discoverable Parameters
|
||||||
|
# - PTP - Parameter Table Pointer
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 1.25
|
||||||
|
BASE_NAME = SpiNorFlashJedecSfdpDxe
|
||||||
|
FILE_GUID = 0DC9C2C7-D450-41BA-9CF7-D2090C35A797
|
||||||
|
MODULE_TYPE = DXE_DRIVER
|
||||||
|
VERSION_STRING = 0.1
|
||||||
|
PI_SPECIFICATION_VERSION = 1.10
|
||||||
|
ENTRY_POINT = SpiNorFlashJedecSfdpDxeEntry
|
||||||
|
MODULE_UNI_FILE = SpiNorFlashJedecSfdpDxe.uni
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
BaseLib
|
||||||
|
BaseMemoryLib
|
||||||
|
DebugLib
|
||||||
|
DevicePathLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
TimerLib
|
||||||
|
UefiDriverEntryPoint
|
||||||
|
UefiBootServicesTableLib
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
SpiNorFlashJedecSfdpDxe.c
|
||||||
|
SpiNorFlash.c
|
||||||
|
SpiNorFlashJedecSfdp.c
|
||||||
|
SpiNorFlashJedecSfdpInternal.h
|
||||||
|
SpiNorFlash.h
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiSpiNorFlashProtocolGuid ## PROCUDES
|
||||||
|
|
||||||
|
[FixedPcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSpiNorFlashOperationRetryCount
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSpiNorFlashFixedTimeoutRetryCount
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSpiNorFlashOperationDelayMicroseconds
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEdk2JedecSfdpSpiDxeDriverGuid
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
gEdk2JedecSfdpSpiDxeDriverGuid
|
||||||
|
|
||||||
|
[UserExtensions.TianoCore."ExtraFiles"]
|
||||||
|
SpiNorFlashJedecSfdpExtra.uni
|
@@ -0,0 +1,13 @@
|
|||||||
|
// /** @file
|
||||||
|
// SPI NOR Flash SFDP Localized Strings and Content.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
//
|
||||||
|
// **/
|
||||||
|
|
||||||
|
#string STR_MODULE_ABSTRACT #language en-US "EDK2 SPI NOR FLASH SFDP DXE driver"
|
||||||
|
|
||||||
|
#string STR_MODULE_DESCRIPTION #language en-US "This driver provides SPI NOR FLASH Serial Flash Discoverable Parameter (SFDP) compatible flash device capability discovery."
|
||||||
|
|
@@ -0,0 +1,11 @@
|
|||||||
|
// /** @file
|
||||||
|
// SPI NOR Flash SFDP Localized Strings and Content.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
//
|
||||||
|
// **/
|
||||||
|
|
||||||
|
#string STR_PROPERTIES_MODULE_NAME
|
||||||
|
#language en-US "SPI NOR Flash driver for JEDEC Serial Flash Discoverable Parameters (SFDP) compliant SPI Flash Memory"
|
@@ -0,0 +1,299 @@
|
|||||||
|
/** @file
|
||||||
|
SPI NOR flash driver internal definitions.
|
||||||
|
|
||||||
|
Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef SPI_NOR_FLASH_INSTANCE_H_
|
||||||
|
#define SPI_NOR_FLASH_INSTANCE_H_
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
#include <Protocol/SpiNorFlash.h>
|
||||||
|
#include <Protocol/SpiIo.h>
|
||||||
|
#include <IndustryStandard/SpiNorFlashJedecSfdp.h>
|
||||||
|
|
||||||
|
#define SPI_NOR_FLASH_SIGNATURE SIGNATURE_32 ('s', 'n', 'f', 'm')
|
||||||
|
|
||||||
|
#define SPI_NOR_FLASH_FROM_THIS(a) CR (a, SPI_NOR_FLASH_INSTANCE, Protocol, SPI_NOR_FLASH_SIGNATURE)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
LIST_ENTRY NextFastReadCap; ///< Link list to next Fast read capability
|
||||||
|
UINT8 FastReadInstruction; ///< Fast read instruction.
|
||||||
|
UINT8 ModeClocks; ///< Fast read clock.
|
||||||
|
UINT8 WaitStates; ///< Fast read wait dummy clocks
|
||||||
|
} SFPD_FAST_READ_CAPBILITY_RECORD;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
LIST_ENTRY NextEraseType; ///< Link list to next erase type.
|
||||||
|
UINT16 EraseType; ///< Erase type this flash device supports.
|
||||||
|
UINT8 EraseInstruction; ///< Erase instruction
|
||||||
|
UINT32 EraseSizeInByte; ///< The size of byte in 2^EraseSize the erase type command
|
||||||
|
///< can erase.
|
||||||
|
UINT32 EraseTypicalTime; ///< Time the device typically takes to erase this type
|
||||||
|
///< size.
|
||||||
|
UINT64 EraseTimeout; ///< Maximum typical erase timeout.
|
||||||
|
} SFDP_SUPPORTED_ERASE_TYPE_RECORD;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SearchEraseTypeByType = 1,
|
||||||
|
SearchEraseTypeByCommand,
|
||||||
|
SearchEraseTypeBySize,
|
||||||
|
SearchEraseTypeBySmallestSize,
|
||||||
|
SearchEraseTypeByBiggestSize
|
||||||
|
} SFDP_SEARCH_ERASE_TYPE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
LIST_ENTRY NextCommand; ///< Link list to next detection command.
|
||||||
|
UINT32 CommandAddress; ///< Address to issue the command.
|
||||||
|
UINT8 CommandInstruction; ///< Detection command instruction.
|
||||||
|
UINT8 LatencyInClock; ///< Command latency in clocks.
|
||||||
|
SPDF_CONFIGURATION_COMMAND_ADDR_LENGTH CommandAddressLength; ///< Adddress length of detection command.
|
||||||
|
UINT8 ConfigurationBitMask; ///< The interest bit of the byte data retunred
|
||||||
|
///< after sending the detection command.
|
||||||
|
} SFDP_SECTOR_MAP_DETECTION_RECORD;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
LIST_ENTRY NextRegion; ///< Link list to the next region.
|
||||||
|
UINT32 RegionAddress; ///< Region starting address.
|
||||||
|
UINT32 RegionTotalSize; ///< Region total size in bytes.
|
||||||
|
UINT32 RegionSectors; ///< Sectors in this region.
|
||||||
|
UINT32 SectorSize; ///< Sector size in byte (Minimum blcok erase size)
|
||||||
|
UINT8 SupportedEraseTypeNum; ///< Number of erase type supported.
|
||||||
|
UINT8 SupportedEraseType[SFDP_ERASE_TYPES_NUMBER]; ///< Erase types supported.
|
||||||
|
UINT32 EraseTypeBySizeBitmap; ///< The bitmap of supoprted srase block sizes.
|
||||||
|
///< from big to small.
|
||||||
|
} SFDP_SECTOR_REGION_RECORD;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
LIST_ENTRY NextDescriptor; ///< Link list to next flash map descriptor.
|
||||||
|
UINT8 ConfigurationId; ///< The ID of this configuration.
|
||||||
|
UINT8 RegionCount; ///< The regions of this sector map configuration.
|
||||||
|
LIST_ENTRY RegionList; ///< The linked list of the regions.
|
||||||
|
} SFDP_SECTOR_MAP_RECORD;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINTN Signature;
|
||||||
|
EFI_HANDLE Handle;
|
||||||
|
EFI_SPI_NOR_FLASH_PROTOCOL Protocol;
|
||||||
|
EFI_SPI_IO_PROTOCOL *SpiIo;
|
||||||
|
UINT32 SfdpBasicFlashByteCount;
|
||||||
|
UINT32 SfdpSectorMapByteCount;
|
||||||
|
SFDP_BASIC_FLASH_PARAMETER *SfdpBasicFlash;
|
||||||
|
SFDP_SECTOR_MAP_TABLE *SfdpFlashSectorMap;
|
||||||
|
UINT8 *SpiTransactionWriteBuffer;
|
||||||
|
UINT32 SpiTransactionWriteBufferIndex;
|
||||||
|
//
|
||||||
|
// SFDP information.
|
||||||
|
//
|
||||||
|
SFDP_HEADER SfdpHeader; ///< SFDP header.
|
||||||
|
UINT32 FlashDeviceSize; ///< The total size of this flash device.
|
||||||
|
UINT8 CurrentAddressBytes; ///< The current address bytes.
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is a linked list in which the Fast Read capability tables
|
||||||
|
// are linked from the low performance transfer to higher performance
|
||||||
|
// transfer. The SPI read would use the first Fast Read entry for
|
||||||
|
// SPI read operation.
|
||||||
|
//
|
||||||
|
LIST_ENTRY FastReadTableList;
|
||||||
|
|
||||||
|
LIST_ENTRY SupportedEraseTypes; ///< The linked list of supported erase types.
|
||||||
|
BOOLEAN Uniform4KEraseSupported; ///< The flash device supoprts uniform 4K erase.
|
||||||
|
BOOLEAN WriteEnableLatchRequired; ///< Wether Write Enable Latch is supported.
|
||||||
|
UINT8 WriteEnableLatchCommand; ///< Write Enable Latch command.
|
||||||
|
//
|
||||||
|
// Below is the linked list of flash device sector
|
||||||
|
// map configuration detection command and map descriptors.
|
||||||
|
//
|
||||||
|
BOOLEAN ConfigurationCommandsNeeded; ///< Indicates whether sector map
|
||||||
|
///< configuration detection is
|
||||||
|
///< required.
|
||||||
|
LIST_ENTRY ConfigurationCommandList; ///< The linked list of configuration
|
||||||
|
///< detection command sequence.
|
||||||
|
LIST_ENTRY ConfigurationMapList; ///< The linked list of configuration
|
||||||
|
///< map descriptors.
|
||||||
|
SFDP_SECTOR_MAP_RECORD *CurrentSectorMap; ///< The current activated flash device
|
||||||
|
///< sector map.
|
||||||
|
} SPI_NOR_FLASH_INSTANCE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This routine returns the desired Fast Read mode.
|
||||||
|
|
||||||
|
@param[in] Instance Spi Nor Flash Instance data with pointer to
|
||||||
|
EFI_SPI_NOR_FLASH_PROTOCOL and EFI_SPI_IO_PROTOCOL
|
||||||
|
@param[in,out] FastReadInstruction Fast Read instruction, the input is
|
||||||
|
the default value.
|
||||||
|
@param[in,out] FastReadOperationClock Fast Read operation clock, the input is
|
||||||
|
the default value.
|
||||||
|
@param[in,out] FastReadDummyClocks Fast Read wait state (Dummy clocks), the
|
||||||
|
input is the default value.
|
||||||
|
@retval EFI_SUCCESS The parameters are updated.
|
||||||
|
@retval EFI_NOT_FOUND No desired Fas Read mode found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFastReadParameter (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *Instance,
|
||||||
|
IN OUT UINT8 *FastReadInstruction,
|
||||||
|
IN OUT UINT8 *FastReadOperationClock,
|
||||||
|
IN OUT UINT8 *FastReadDummyClocks
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read SFDP parameters into buffer
|
||||||
|
|
||||||
|
This routine reads the JEDEC SPI Flash Discoverable Parameters from the SPI
|
||||||
|
chip.
|
||||||
|
|
||||||
|
@param[in] Instance Spi Nor Flash Instance data with pointer to
|
||||||
|
EFI_SPI_NOR_FLASH_PROTOCOL and EFI_SPI_IO_PROTOCOL
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The SPI part size is filled.
|
||||||
|
@retval EFI_DEVICE_ERROR Invalid data received from SPI flash part.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
ReadSfdpBasicParameterTable (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *Instance
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read SFDP Sector Map Parameter into buffer
|
||||||
|
|
||||||
|
This routine reads the JEDEC SPI Flash Discoverable Parameters from the SPI
|
||||||
|
chip.
|
||||||
|
|
||||||
|
@param[in] Instance Spi Nor Flash Instance data with pointer to
|
||||||
|
EFI_SPI_NOR_FLASH_PROTOCOL and EFI_SPI_IO_PROTOCOL
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The SPI part size is filled.
|
||||||
|
@retval EFI_DEVICE_ERROR Invalid data received from SPI flash part.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
ReadSfdpSectorMapParameterTable (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *Instance
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return flash device size from SFDP Basic Flash Parameter Table DWORD 2
|
||||||
|
|
||||||
|
@param[in] Instance Spi Nor Flash Instance data with pointer to
|
||||||
|
EFI_SPI_NOR_FLASH_PROTOCOL and
|
||||||
|
EFI_SPI_IO_PROTOCOL.
|
||||||
|
|
||||||
|
* @retval UINT32 Flash device size in byte, zero indicates error.
|
||||||
|
|
||||||
|
**/
|
||||||
|
UINT32
|
||||||
|
SfdpGetFlashSize (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *Instance
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read SFDP
|
||||||
|
This routine reads the JEDEC SPI Flash Discoverable Parameters. We just
|
||||||
|
read the necessary tables in this routine.
|
||||||
|
|
||||||
|
@param[in] Instance Spi Nor Flash Instance data with pointer to
|
||||||
|
EFI_SPI_NOR_FLASH_PROTOCOL and EFI_SPI_IO_PROTOCOL
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Header is filled in
|
||||||
|
@retval EFI_DEVICE_ERROR Invalid data received from SPI flash part.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
ReadSfdp (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *Instance
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set EraseBlockBytes in SPI NOR Flash Protocol
|
||||||
|
|
||||||
|
@param[in] Instance Spi Nor Flash Instance data with pointer to
|
||||||
|
EFI_SPI_NOR_FLASH_PROTOCOL and EFI_SPI_IO_PROTOCOL
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The erase block size is returned.
|
||||||
|
@retval Otherwise Failed to get erase block size.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
SetSectorEraseBlockSize (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *Instance
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the erase block attribute for the target address.
|
||||||
|
|
||||||
|
@param[in] Instance Spi Nor Flash Instance data with pointer to
|
||||||
|
EFI_SPI_NOR_FLASH_PROTOCOL and EFI_SPI_IO_PROTOCOL
|
||||||
|
@param[in] FlashRegion The region the flash address belong.
|
||||||
|
@param[in] FlashAddress The target flash address.
|
||||||
|
@param[in] RemainingSize Remaining size to erase.
|
||||||
|
@param[in, out] BlockSizeToErase Input - The block erase size for this continious blocks.
|
||||||
|
Output - The determined block size for erasing.
|
||||||
|
@param[in, out] BlockCountToErase Input - The expected blocks to erase.
|
||||||
|
Output - The determined number of blocks to erase.
|
||||||
|
@param[out] BlockEraseCommand The erase command used for this continious blocks.
|
||||||
|
@param[out] TypicalTime Pointer to receive the typical time in millisecond
|
||||||
|
to erase this erase type size.
|
||||||
|
@param[out] MaximumTimeout Pointer to receive the maximum timeout in millisecond
|
||||||
|
to erase this erase type size.
|
||||||
|
@retval EFI_SUCCESS The erase block attribute is returned.
|
||||||
|
@retval EFI_DEVICE_ERROR No valid SFDP discovered.
|
||||||
|
@retval EFI_NOT_FOUND No valud erase block attribute found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetEraseBlockAttribute (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *Instance,
|
||||||
|
IN SFDP_SECTOR_REGION_RECORD *FlashRegion,
|
||||||
|
IN UINT32 FlashAddress,
|
||||||
|
IN UINT32 RemainingSize,
|
||||||
|
IN OUT UINT32 *BlockSizeToErase,
|
||||||
|
IN OUT UINT32 *BlockCountToErase,
|
||||||
|
OUT UINT8 *BlockEraseCommand,
|
||||||
|
OUT UINT32 *TypicalTime,
|
||||||
|
OUT UINT64 *MaximumTimeout
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the erase block attribute for the target address.
|
||||||
|
|
||||||
|
@param[in] Instance Spi Nor Flash Instance data with pointer to
|
||||||
|
EFI_SPI_NOR_FLASH_PROTOCOL and EFI_SPI_IO_PROTOCOL
|
||||||
|
@param[in] FlashAddress The target flash address.
|
||||||
|
@param[out] FlashRegion The target flash address.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The region is returned.
|
||||||
|
@retval EFI_INVALID_PARAMETER FlashAddress is not belong to any region.
|
||||||
|
@retval EFI_INVALID_PARAMETER Other errors.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetRegionByFlashAddress (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *Instance,
|
||||||
|
IN UINT32 FlashAddress,
|
||||||
|
OUT SFDP_SECTOR_REGION_RECORD **FlashRegion
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initial SPI_NOR_FLASH_INSTANCE structure.
|
||||||
|
|
||||||
|
@param[in] Instance Pointer to SPI_NOR_FLASH_INSTANCE.
|
||||||
|
EFI_SPI_NOR_FLASH_PROTOCOL and EFI_SPI_IO_PROTOCOL
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS SPI_NOR_FLASH_INSTANCE is initialized according to
|
||||||
|
SPI NOR Flash SFDP specification.
|
||||||
|
@retval Otherwisw Failed to initial SPI_NOR_FLASH_INSTANCE structure.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InitialSpiNorFlashSfdpInstance (
|
||||||
|
IN SPI_NOR_FLASH_INSTANCE *Instance
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif // SPI_NOR_FLASH_INSTANCE_H_
|
@@ -0,0 +1,234 @@
|
|||||||
|
/** @file
|
||||||
|
SPI NOR Flash JEDEC Serial Flash Discoverable Parameters (SFDP)
|
||||||
|
SMM driver.
|
||||||
|
|
||||||
|
Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
@par Revision Reference:
|
||||||
|
- JEDEC Standard, JESD216F.02
|
||||||
|
https://www.jedec.org/document_search?search_api_views_fulltext=JESD216
|
||||||
|
|
||||||
|
@par Glossary:
|
||||||
|
- SFDP - Serial Flash Discoverable Parameters
|
||||||
|
- PTP - Parameter Table Pointer
|
||||||
|
**/
|
||||||
|
#include <Base.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/SmmServicesTableLib.h>
|
||||||
|
#include <Protocol/SpiSmmConfiguration.h>
|
||||||
|
#include <Protocol/SpiSmmNorFlash.h>
|
||||||
|
#include <Protocol/SpiIo.h>
|
||||||
|
#include <IndustryStandard/SpiNorFlashJedecSfdp.h>
|
||||||
|
#include "SpiNorFlash.h"
|
||||||
|
#include "SpiNorFlashJedecSfdpInternal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Function to create SPI_NOR_FLASH_INSTANCE for this SPI part.
|
||||||
|
|
||||||
|
@param[in] SpiIoHandle The handle with SPI I/O protocol installed.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Succeed.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Not enough resource to create SPI_NOR_FLASH_INSTANCE.
|
||||||
|
@retval otherwise Fail to create SPI NOR Flash SFDP Instance
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
CreateSpiNorFlashSfdpInstance (
|
||||||
|
IN EFI_HANDLE SpiIoHandle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
SPI_NOR_FLASH_INSTANCE *Instance;
|
||||||
|
|
||||||
|
// Allocate SPI_NOR_FLASH_INSTANCE Instance.
|
||||||
|
Instance = AllocateZeroPool (sizeof (SPI_NOR_FLASH_INSTANCE));
|
||||||
|
ASSERT (Instance != NULL);
|
||||||
|
if (Instance == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locate the SPI IO Protocol.
|
||||||
|
Status = gSmst->SmmHandleProtocol (
|
||||||
|
SpiIoHandle,
|
||||||
|
&gEdk2JedecSfdpSpiSmmDriverGuid,
|
||||||
|
(VOID **)&Instance->SpiIo
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "%a: Fail to locate SPI I/O protocol.\n", __func__));
|
||||||
|
FreePool (Instance);
|
||||||
|
} else {
|
||||||
|
Status = InitialSpiNorFlashSfdpInstance (Instance);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "%a: Fail to initial SPI_NOR_FLASH_INSTANCE.\n", __func__));
|
||||||
|
FreePool (Instance);
|
||||||
|
} else {
|
||||||
|
// Install SPI NOR Flash Protocol.
|
||||||
|
Status = gSmst->SmmInstallProtocolInterface (
|
||||||
|
&Instance->Handle,
|
||||||
|
&gEfiSpiSmmNorFlashProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
&Instance->Protocol
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "%a: Fail to Install gEfiSpiSmmNorFlashProtocolGuid protocol.\n", __func__));
|
||||||
|
FreePool (Instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Callback function executed when the EFI_SPI_IO_PROTOCOL
|
||||||
|
protocol interface is installed.
|
||||||
|
|
||||||
|
@param[in] Protocol Points to the protocol's unique identifier.
|
||||||
|
@param[in] Interface Points to the interface instance.
|
||||||
|
@param[in] Handle The handle on which the interface was installed.
|
||||||
|
|
||||||
|
@return Status Code
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SpiIoProtocolInstalledCallback (
|
||||||
|
IN CONST EFI_GUID *Protocol,
|
||||||
|
IN VOID *Interface,
|
||||||
|
IN EFI_HANDLE Handle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: Entry.\n", __func__));
|
||||||
|
Status = CreateSpiNorFlashSfdpInstance (Handle);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Register notification for the later installed SPI I/O protocol.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Succeed.
|
||||||
|
@retval otherwise Fail to register the notification of
|
||||||
|
SPI I/O protocol installation.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
RegisterSpioProtocolNotification (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
VOID *Registration;
|
||||||
|
|
||||||
|
Status = gSmst->SmmRegisterProtocolNotify (
|
||||||
|
&gEdk2JedecSfdpSpiSmmDriverGuid,
|
||||||
|
SpiIoProtocolInstalledCallback,
|
||||||
|
&Registration
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "%a: Fail to register event for the SPI I/O Protocol installation.", __func__));
|
||||||
|
} else {
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: Notification for SPI I/O Protocol installation was registered.", __func__));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Entry point of the SPI NOR Flash SFDP SMM driver.
|
||||||
|
|
||||||
|
@param ImageHandle Image handle of this driver.
|
||||||
|
@param SystemTable Pointer to standard EFI system table.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Succeed.
|
||||||
|
@retval EFI_NOT_FOUND No gEdk2JedecSfdpSpiSmmDriverGuid installed on
|
||||||
|
system yet.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Not enough resource for SPI NOR Flash JEDEC SFDP
|
||||||
|
initialization.
|
||||||
|
@retval Otherwise Other errors.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SpiNorFlashJedecSfdpSmmEntry (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_HANDLE *InstanceBuffer;
|
||||||
|
UINTN InstanceIndex;
|
||||||
|
UINTN InstanceBufferSize;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "%a - ENTRY.\n", __func__));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register notification for the later SPI I/O protocol installation.
|
||||||
|
//
|
||||||
|
RegisterSpioProtocolNotification ();
|
||||||
|
DEBUG ((DEBUG_INFO, "Check if there were already some gEdk2JedecSfdpSpiSmmDriverGuid handles installed.\n"));
|
||||||
|
//
|
||||||
|
// Check if there were already some gEdk2JedecSfdpSpiSmmDriverGuid
|
||||||
|
// handles installed.
|
||||||
|
//
|
||||||
|
// Locate the SPI I/O Protocol for the SPI flash part
|
||||||
|
// that supports JEDEC SFDP specification.
|
||||||
|
//
|
||||||
|
InstanceBufferSize = 0;
|
||||||
|
InstanceBuffer = NULL;
|
||||||
|
Status = gSmst->SmmLocateHandle (
|
||||||
|
ByProtocol,
|
||||||
|
&gEdk2JedecSfdpSpiSmmDriverGuid,
|
||||||
|
NULL,
|
||||||
|
&InstanceBufferSize,
|
||||||
|
InstanceBuffer
|
||||||
|
);
|
||||||
|
if (Status == EFI_NOT_FOUND) {
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"No gEdk2JedecSfdpSpiSmmDriverGuid handles found at the moment, wait for the notification of SPI I/O protocol installation.\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: EXIT - Status=%r\n", __func__, Status));
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
} else if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||||
|
InstanceBuffer = (EFI_HANDLE *)AllocateZeroPool (InstanceBufferSize);
|
||||||
|
ASSERT (InstanceBuffer != NULL);
|
||||||
|
if (InstanceBuffer == NULL) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Not enough resource for gEdk2JedecSfdpSpiSmmDriverGuid handles.\n"));
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: EXIT - Status=%r\n", __func__, Status));
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
} else if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Error to locate gEdk2JedecSfdpSpiSmmDriverGuid - Status = %r.\n", Status));
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: EXIT - Status=%r\n", __func__, Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gSmst->SmmLocateHandle (
|
||||||
|
ByProtocol,
|
||||||
|
&gEdk2JedecSfdpSpiSmmDriverGuid,
|
||||||
|
NULL,
|
||||||
|
&InstanceBufferSize,
|
||||||
|
InstanceBuffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Fail to locate all gEdk2JedecSfdpSpiSmmDriverGuid handles.\n"));
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: EXIT - Status=%r\n", __func__, Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "%d of gEdk2JedecSfdpSpiSmmDriverGuid handles are found.\n", InstanceBufferSize / sizeof (EFI_HANDLE)));
|
||||||
|
for (InstanceIndex = 0; InstanceIndex < InstanceBufferSize / sizeof (EFI_HANDLE); InstanceIndex++) {
|
||||||
|
Status = CreateSpiNorFlashSfdpInstance (*(InstanceBuffer + InstanceIndex));
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Fail to create SPI NOR Flash SFDP instance #%d.\n", InstanceIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "%a: EXIT - Status=%r\n", __func__, Status));
|
||||||
|
return Status;
|
||||||
|
}
|
@@ -0,0 +1,64 @@
|
|||||||
|
## @file
|
||||||
|
# The SPI NOR Flash JEDEC Serial Flash Discoverable Parameters (SFDP)
|
||||||
|
# SMM driver INF file.
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
#
|
||||||
|
# @par Revision Reference:
|
||||||
|
# - JEDEC Standard, JESD216F.02
|
||||||
|
# https://www.jedec.org/document_search?search_api_views_fulltext=JESD216
|
||||||
|
#
|
||||||
|
# @par Glossary:
|
||||||
|
# - SFDP - Serial Flash Discoverable Parameters
|
||||||
|
# - PTP - Parameter Table Pointer
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 1.25
|
||||||
|
BASE_NAME = SpiNorFlashJedecSfdpSmm
|
||||||
|
FILE_GUID = AC7884C7-35A2-40AC-B9E0-AD67298E3BBA
|
||||||
|
MODULE_TYPE = DXE_SMM_DRIVER
|
||||||
|
VERSION_STRING = 0.1
|
||||||
|
PI_SPECIFICATION_VERSION = 1.10
|
||||||
|
ENTRY_POINT = SpiNorFlashJedecSfdpSmmEntry
|
||||||
|
MODULE_UNI_FILE = SpiNorFlashJedecSfdpSmm.uni
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
BaseLib
|
||||||
|
BaseMemoryLib
|
||||||
|
DebugLib
|
||||||
|
DevicePathLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
SmmServicesTableLib
|
||||||
|
TimerLib
|
||||||
|
UefiDriverEntryPoint
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
SpiNorFlashJedecSfdpSmm.c
|
||||||
|
SpiNorFlash.c
|
||||||
|
SpiNorFlashJedecSfdp.c
|
||||||
|
SpiNorFlashJedecSfdpInternal.h
|
||||||
|
SpiNorFlash.h
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiSpiSmmNorFlashProtocolGuid ## PROCUDES
|
||||||
|
|
||||||
|
[FixedPcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSpiNorFlashOperationRetryCount
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSpiNorFlashFixedTimeoutRetryCount
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSpiNorFlashOperationDelayMicroseconds
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEdk2JedecSfdpSpiSmmDriverGuid
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
gEdk2JedecSfdpSpiSmmDriverGuid
|
||||||
|
|
||||||
|
[UserExtensions.TianoCore."ExtraFiles"]
|
||||||
|
SpiNorFlashJedecSfdpExtra.uni
|
@@ -0,0 +1,13 @@
|
|||||||
|
// /** @file
|
||||||
|
// SPI NOR Flash SFDP Localized Strings and Content.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
//
|
||||||
|
// **/
|
||||||
|
|
||||||
|
#string STR_MODULE_ABSTRACT #language en-US "EDK2 SPI NOR FLASH SFDP SMM driver"
|
||||||
|
|
||||||
|
#string STR_MODULE_DESCRIPTION #language en-US "This driver provides SPI NOR FLASH Serial Flash Discoverable Parameter (SFDP) compatible flash device capability discovery."
|
||||||
|
|
Reference in New Issue
Block a user