mirror of
https://github.com/acidanthera/audk.git
synced 2025-04-07 19:45:07 +02:00
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:
parent
6dc09fda04
commit
8b02ecc5f0
MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp
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."
|
||||
|
Loading…
x
Reference in New Issue
Block a user