[AMD Official Use Only - General] We had reviewed this patch internally before sending this to community. Reviewed-by: Abner Chang <abner.ch...@amd.com>
> -----Original Message----- > From: Chesley, Brit <brit.ches...@amd.com> > Sent: Thursday, May 2, 2024 3:05 AM > To: devel@edk2.groups.io > Cc: Chang, Abner <abner.ch...@amd.com>; Attar, AbdulLateef (Abdul > Lateef) <abdullateef.at...@amd.com> > Subject: [PATCH v1 2/6] MdeModulePkg/Bus/Spi/SpiBus: Adding SpiBus > Drivers > > From: Brit Chesley <brit.ches...@amd.com> > > Added SpiBus DXE and SMM drivers. This code translates SPI requests from > the application layer into SPI Bus transactions on the SPI host > controller. The code is responsible for checking if the transaction is > valid, then setting up the SPI clock and chip select properly before > passing the bus transaction to the host controller. > > Platform Initialization Spec 1.7 volume 5 section 18.1.6 > > Bugzilla #4753 > > Cc: Abner Chang <abner.ch...@amd.com> > Cc: Abdul Lateef Attar <abdullateef.at...@amd.com> > Signed-off-by: Brit Chesley <brit.ches...@amd.com> > --- > MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf | 41 ++ > MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf | 41 ++ > MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h | 167 +++++++++ > MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c | 433 > ++++++++++++++++++++++ > MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c | 198 ++++++++++ > MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c | 162 ++++++++ > MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni | 10 + > 7 files changed, 1052 insertions(+) > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c > create mode 100644 MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni > > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf > new file mode 100644 > index 000000000000..3e2cc2daba1c > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf > @@ -0,0 +1,41 @@ > +## @file > +# Component description for the SPI BUS DXE module > +# > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > +[Defines] > + INF_VERSION = 1.27 > + BASE_NAME = SpiBusDxe > + FILE_GUID = 25CE038C-5C3A-4A9B-A111-90DF5897E058 > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 0.1 > + PI_SPECIFICATION_VERSION = 0x0001000A > + ENTRY_POINT = SpiBusEntry > + > +[Packages] > + MdePkg/MdePkg.dec > + > +[LibraryClasses] > + DebugLib > + DevicePathLib > + MemoryAllocationLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + > +[Sources] > + SpiBusDxe.c > + SpiBus.c > + SpiBus.h > + > +[Protocols] > + gEfiSpiConfigurationProtocolGuid ## CONSUMES > + gEfiSpiHcProtocolGuid ## CONSUMES > + > +[Depex] > + gEfiSpiConfigurationProtocolGuid AND > + gEfiSpiHcProtocolGuid > + > +[UserExtensions.TianoCore."ExtraFiles"] > + SpiBus.uni > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf > new file mode 100644 > index 000000000000..9e3a5aae7d87 > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf > @@ -0,0 +1,41 @@ > +## @file > +# Component description for the SPI BUS SMM module > +# > +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > +[Defines] > + INF_VERSION = 1.27 > + BASE_NAME = SpiBusSmm > + FILE_GUID = 5DBB52E1-3D78-4C9C-A9D7-A43E79E93AC0 > + MODULE_TYPE = DXE_SMM_DRIVER > + VERSION_STRING = 0.1 > + PI_SPECIFICATION_VERSION = 0x0001000A > + ENTRY_POINT = SpiBusEntry > + > +[Packages] > + MdePkg/MdePkg.dec > + > +[LibraryClasses] > + DebugLib > + DevicePathLib > + MemoryAllocationLib > + MmServicesTableLib > + UefiDriverEntryPoint > + > +[Sources] > + SpiBus.h > + SpiBus.c > + SpiBusSmm.c > + > +[Protocols] > + gEfiSpiSmmConfigurationProtocolGuid ## CONSUMES > + gEfiSpiSmmHcProtocolGuid ## CONSUMES > + > +[Depex] > + gEfiSpiSmmConfigurationProtocolGuid AND > + gEfiSpiSmmHcProtocolGuid > + > +[UserExtensions.TianoCore."ExtraFiles"] > + SpiBus.uni > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h > new file mode 100644 > index 000000000000..7a43f66ac750 > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h > @@ -0,0 +1,167 @@ > +/** @file > + > + SPI bus driver > + > + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef SPI_BUS_H_ > +#define SPI_BUS_H_ > + > +#include <PiDxe.h> > +#include <Library/BaseLib.h> > +#include <Protocol/DevicePath.h> > +#include <Library/DevicePathLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Protocol/SpiIo.h> > +#include <Protocol/SpiHc.h> > +#include <Protocol/SpiConfiguration.h> > + > +#define SPI_IO_SIGNATURE SIGNATURE_32 ('s', 'i', 'o', 'c') > + > +typedef struct { > + UINTN Signature; > + EFI_HANDLE Handle; > + EFI_SPI_IO_PROTOCOL Protocol; > + EFI_SPI_BUS_TRANSACTION BusTransaction; > + EFI_SPI_CONFIGURATION_PROTOCOL *SpiConfig; > + EFI_SPI_HC_PROTOCOL *SpiHc; > + EFI_SPI_BUS *SpiBus; > +} SPI_IO_CHIP; > + > +#define SPI_IO_CHIP_FROM_THIS(a) \ > + CR (a, SPI_IO_CHIP, Protocol, \ > + SPI_IO_SIGNATURE) > + > +/** > + Checks if two device paths are the same > + > + @param[in] DevicePath1 First device path to compare > + @param[in] DevicePath2 Second device path to compare > + > + @retval TRUE The device paths share the same nodes and values > + @retval FALSE The device paths differ > +**/ > +BOOLEAN > +EFIAPI > +DevicePathsAreEqual ( > + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath1, > + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath2 > + ); > + > +/** > + Initiate a SPI transaction between the host and a SPI peripheral. > + > + This routine must be called at or below TPL_NOTIFY. > + This routine works with the SPI bus layer to pass the SPI transaction to > the > + SPI controller for execution on the SPI bus. There are four types of > + supported transactions supported by this routine: > + * Full Duplex: WriteBuffer and ReadBuffer are the same size. > + * Write Only: WriteBuffer contains data for SPI peripheral, ReadBytes = 0 > + * Read Only: ReadBuffer to receive data from SPI peripheral, WriteBytes = 0 > + * Write Then Read: WriteBuffer contains control data to write to SPI > + peripheral before data is placed into the ReadBuffer. > + Both WriteBytes and ReadBytes must be non-zero. > + > + @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure. > + @param[in] TransactionType Type of SPI transaction. > + @param[in] DebugTransaction Set TRUE only when debugging is desired. > + Debugging may be turned on for a single SPI > + transaction. Only this transaction will > display > + debugging messages. All other transactions > with > + this value set to FALSE will not display any > + debugging messages. > + @param[in] ClockHz Specify the ClockHz value as zero (0) to use > + the maximum clock frequency supported by the > + SPI controller and part. Specify a non-zero > + value only when a specific SPI transaction > + requires a reduced clock rate. > + @param[in] BusWidth Width of the SPI bus in bits: 1, 2, 4 > + @param[in] FrameSize Frame size in bits, range: 1 - 32 > + @param[in] WriteBytes The length of the WriteBuffer in bytes. > + Specify zero for read-only operations. > + @param[in] WriteBuffer The buffer containing data to be sent from > the > + host to the SPI chip. Specify NULL for read > + only operations. > + * Frame sizes 1-8 bits: UINT8 (one byte) per > + frame > + * Frame sizes 7-16 bits: UINT16 (two bytes) > per > + frame > + * Frame sizes 17-32 bits: UINT32 (four bytes) > + per frame The transmit frame is in the > least > + significant N bits. > + @param[in] ReadBytes The length of the ReadBuffer in bytes. > + Specify zero for write-only operations. > + @param[out] ReadBuffer The buffer to receeive data from the SPI chip > + during the transaction. Specify NULL for > write > + only operations. > + * Frame sizes 1-8 bits: UINT8 (one byte) per > + frame > + * Frame sizes 7-16 bits: UINT16 (two bytes) > per > + frame > + * Frame sizes 17-32 bits: UINT32 (four bytes) > + per frame The received frame is in the > least > + significant N bits. > + > + @retval EFI_SUCCESS The SPI transaction completed successfully > + @retval EFI_BAD_BUFFER_SIZE The writeBytes value was invalid > + @retval EFI_BAD_BUFFER_SIZE The ReadBytes value was invalid > + @retval EFI_INVALID_PARAMETER TransactionType is not valid, > + or BusWidth not supported by SPI peripheral > or > + SPI host controller, > + or WriteBytes non-zero and WriteBuffer is > + NULL, > + or ReadBytes non-zero and ReadBuffer is > NULL, > + or ReadBuffer != WriteBuffer for full-duplex > + type, > + or WriteBuffer was NULL, > + or TPL is too high > + @retval EFI_OUT_OF_RESOURCES Insufficient memory for SPI transaction > + @retval EFI_UNSUPPORTED The FrameSize is not supported by the SPI > bus > + layer or the SPI host controller > + @retval EFI_UNSUPPORTED The SPI controller was not able to support > + > +**/ > +EFI_STATUS > +EFIAPI > +Transaction ( > + IN CONST EFI_SPI_IO_PROTOCOL *This, > + IN EFI_SPI_TRANSACTION_TYPE TransactionType, > + IN BOOLEAN DebugTransaction, > + IN UINT32 ClockHz OPTIONAL, > + IN UINT32 BusWidth, > + IN UINT32 FrameSize, > + IN UINT32 WriteBytes, > + IN UINT8 *WriteBuffer, > + IN UINT32 ReadBytes, > + OUT UINT8 *ReadBuffer > + ); > + > +/** > + Update the SPI peripheral associated with this SPI 10 instance. > + > + Support socketed SPI parts by allowing the SPI peripheral driver to replace > + the SPI peripheral after the connection is made. An example use is socketed > + SPI NOR flash parts, where the size and parameters change depending upon > + device is in the socket. > + > + @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure. > + @param[in] SpiPeripheral Pointer to an EFI_SPI_PERIPHERAL structure. > + > + @retval EFI_SUCCESS The SPI peripheral was updated successfully > + @retval EFI_INVALID_PARAMETER The SpiPeripheral value is NULL, > + or the SpiPeripheral->SpiBus is NULL, > + or the SpiPeripheral->SpiBus pointing at > + wrong bus, or the SpiPeripheral->SpiPart is > NULL > + > +**/ > +EFI_STATUS > +EFIAPI > +UpdateSpiPeripheral ( > + IN CONST EFI_SPI_IO_PROTOCOL *This, > + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral > + ); > + > +#endif //SPI_BUS_H_ > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c > new file mode 100644 > index 000000000000..b183ca182cab > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c > @@ -0,0 +1,433 @@ > +/** @file > + > + SpiBus driver > + > + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > +#include <Library/BaseLib.h> > +#include <Library/DebugLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Protocol/SpiConfiguration.h> > +#include <Protocol/SpiHc.h> > +#include <Protocol/SpiIo.h> > +#include "SpiBus.h" > + > +/** > + Checks if two device paths are the same. > + > + @param[in] DevicePath1 First device path to compare > + @param[in] DevicePath2 Second device path to compare > + > + @retval TRUE The device paths share the same nodes and values > + @retval FALSE The device paths differ > +**/ > +BOOLEAN > +EFIAPI > +DevicePathsAreEqual ( > + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath1, > + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath2 > + ) > +{ > + UINTN Size1; > + UINTN Size2; > + > + Size1 = GetDevicePathSize (DevicePath1); > + Size2 = GetDevicePathSize (DevicePath2); > + > + if (Size1 != Size2) { > + return FALSE; > + } > + > + if (CompareMem (DevicePath1, DevicePath2, Size1) != 0) { > + return FALSE; > + } > + > + return TRUE; > +} > + > +/** > + Calls the SpiPeripherals ChipSelect if it is not null, otherwise > + calls the Host Controllers ChipSelect function. > + > + @param[in] SpiChip The SpiChip to place on the bus via asserting > its chip > select > + @param[in] PinValue Value to place on the chip select pin > + > + @retval EFI_SUCCESS Chip select pin was placed at > requested level > + @retval EFI_INVALID_PARAMETER Invalid parameters passed into > ChipSelect function > +**/ > +EFI_STATUS > +EFIAPI > +SpiChipSelect ( > + IN CONST SPI_IO_CHIP *SpiChip, > + IN BOOLEAN PinValue > + ) > +{ > + EFI_STATUS Status; > + > + // Check which chip select function to use > + if (SpiChip->Protocol.SpiPeripheral->ChipSelect != NULL) { > + Status = SpiChip->Protocol.SpiPeripheral->ChipSelect ( > + > SpiChip->BusTransaction.SpiPeripheral, > + PinValue > + ); > + } else { > + Status = SpiChip->SpiHc->ChipSelect ( > + SpiChip->SpiHc, > + SpiChip->BusTransaction.SpiPeripheral, > + PinValue > + ); > + } > + > + return Status; > +} > + > +/** > + Checks the SpiChip's BusTransaction attributes to ensure its a valid SPI > transaction. > + > + @param[in] SpiChip The SpiChip where a bus transaction is requested > + > + @retval EFI_SUCCESS This is a valid SPI bus transaction > + @retval EFI_BAD_BUFFER_SIZE The WriteBytes value was invalid > + @retval EFI_BAD_BUFFER_SIZE The ReadBytes value was invalid > + @retval EFI_INVALID_PARAMETER TransactionType is not valid, > + or BusWidth not supported by SPI peripheral > or > + SPI host controller, > + or WriteBytes non-zero and WriteBuffer is > + NULL, > + or ReadBytes non-zero and ReadBuffer is > NULL, > + or ReadBuffer != WriteBuffer for full-duplex > + type, > + or WriteBuffer was NULL, > + or TPL is too high > + @retval EFI_OUT_OF_RESOURCES Insufficient memory for SPI transaction > + @retval EFI_UNSUPPORTED The FrameSize is not supported by the SPI > bus > + layer or the SPI host controller > + @retval EFI_UNSUPPORTED The SPI controller was not able to support > +**/ > +EFI_STATUS > +EFIAPI > +IsValidSpiTransaction ( > + IN SPI_IO_CHIP *SpiChip > + ) > +{ > + // Error checking > + if (SpiChip->BusTransaction.TransactionType > > SPI_TRANSACTION_WRITE_THEN_READ) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (((SpiChip->BusTransaction.BusWidth != 1) && (SpiChip- > >BusTransaction.BusWidth != 2) && (SpiChip->BusTransaction.BusWidth != 4) > && > + (SpiChip->BusTransaction.BusWidth != 8)) || (SpiChip- > >BusTransaction.FrameSize == 0)) > + { > + return EFI_INVALID_PARAMETER; > + } > + > + if ((SpiChip->BusTransaction.BusWidth == 8) && (((SpiChip- > >Protocol.Attributes & SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH) != > SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH) || > + > ((SpiChip->BusTransaction.SpiPeripheral->Attributes > & SPI_PART_SUPPORTS_8_BIT_DATA_BUS_WIDTH) != > SPI_PART_SUPPORTS_8_BIT_DATA_BUS_WIDTH))) > + { > + return EFI_INVALID_PARAMETER; > + } else if ((SpiChip->BusTransaction.BusWidth == 4) && (((SpiChip- > >Protocol.Attributes & SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != > SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) || > + > ((SpiChip->BusTransaction.SpiPeripheral- > >Attributes & SPI_PART_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != > SPI_PART_SUPPORTS_4_BIT_DATA_BUS_WIDTH))) > + { > + return EFI_INVALID_PARAMETER; > + } else if ((SpiChip->BusTransaction.BusWidth == 2) && (((SpiChip- > >Protocol.Attributes & SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != > SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) || > + > ((SpiChip->BusTransaction.SpiPeripheral- > >Attributes & SPI_PART_SUPPORTS_2_BIT_DATA_BUS_WIDTH) != > SPI_PART_SUPPORTS_2_BIT_DATA_BUS_WIDTH))) > + { > + return EFI_INVALID_PARAMETER; > + } > + > + if (((SpiChip->BusTransaction.WriteBytes > 0) && (SpiChip- > >BusTransaction.WriteBuffer == NULL)) || ((SpiChip- > >BusTransaction.ReadBytes > 0) && (SpiChip->BusTransaction.ReadBuffer == > NULL))) { > + return EFI_INVALID_PARAMETER; > + } > + > + if ((SpiChip->BusTransaction.TransactionType == > SPI_TRANSACTION_FULL_DUPLEX) && (SpiChip- > >BusTransaction.ReadBytes != SpiChip->BusTransaction.WriteBytes)) { > + return EFI_INVALID_PARAMETER; > + } > + > + // Check frame size, passed parameter is in bits > + if ((SpiChip->Protocol.FrameSizeSupportMask & (1<<(SpiChip- > >BusTransaction.FrameSize-1))) == 0) { > + return EFI_UNSUPPORTED; > + } > + > + return EFI_SUCCESS; > +} > + > +/** > + Initiate a SPI transaction between the host and a SPI peripheral. > + > + This routine must be called at or below TPL_NOTIFY. > + This routine works with the SPI bus layer to pass the SPI transaction to > the > + SPI controller for execution on the SPI bus. There are four types of > + supported transactions supported by this routine: > + * Full Duplex: WriteBuffer and ReadBuffer are the same size. > + * Write Only: WriteBuffer contains data for SPI peripheral, ReadBytes = 0 > + * Read Only: ReadBuffer to receive data from SPI peripheral, WriteBytes = 0 > + * Write Then Read: WriteBuffer contains control data to write to SPI > + peripheral before data is placed into the ReadBuffer. > + Both WriteBytes and ReadBytes must be non-zero. > + > + @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure. > + @param[in] TransactionType Type of SPI transaction. > + @param[in] DebugTransaction Set TRUE only when debugging is desired. > + Debugging may be turned on for a single SPI > + transaction. Only this transaction will > display > + debugging messages. All other transactions > with > + this value set to FALSE will not display any > + debugging messages. > + @param[in] ClockHz Specify the ClockHz value as zero (0) to use > + the maximum clock frequency supported by the > + SPI controller and part. Specify a non-zero > + value only when a specific SPI transaction > + requires a reduced clock rate. > + @param[in] BusWidth Width of the SPI bus in bits: 1, 2, 4 > + @param[in] FrameSize Frame size in bits, range: 1 - 32 > + @param[in] WriteBytes The length of the WriteBuffer in bytes. > + Specify zero for read-only operations. > + @param[in] WriteBuffer The buffer containing data to be sent from > the > + host to the SPI chip. Specify NULL for read > + only operations. > + * Frame sizes 1-8 bits: UINT8 (one byte) per > + frame > + * Frame sizes 7-16 bits: UINT16 (two bytes) > per > + frame > + * Frame sizes 17-32 bits: UINT32 (four bytes) > + per frame The transmit frame is in the > least > + significant N bits. > + @param[in] ReadBytes The length of the ReadBuffer in bytes. > + Specify zero for write-only operations. > + @param[out] ReadBuffer The buffer to receeive data from the SPI chip > + during the transaction. Specify NULL for > write > + only operations. > + * Frame sizes 1-8 bits: UINT8 (one byte) per > + frame > + * Frame sizes 7-16 bits: UINT16 (two bytes) > per > + frame > + * Frame sizes 17-32 bits: UINT32 (four bytes) > + per frame The received frame is in the > least > + significant N bits. > + > + @retval EFI_SUCCESS The SPI transaction completed successfully > + @retval EFI_BAD_BUFFER_SIZE The WriteBytes value was invalid > + @retval EFI_BAD_BUFFER_SIZE The ReadBytes value was invalid > + @retval EFI_INVALID_PARAMETER TransactionType is not valid, > + or BusWidth not supported by SPI peripheral > or > + SPI host controller, > + or WriteBytes non-zero and WriteBuffer is > + NULL, > + or ReadBytes non-zero and ReadBuffer is > NULL, > + or ReadBuffer != WriteBuffer for full-duplex > + type, > + or WriteBuffer was NULL, > + or TPL is too high > + @retval EFI_OUT_OF_RESOURCES Insufficient memory for SPI transaction > + @retval EFI_UNSUPPORTED The FrameSize is not supported by the SPI > bus > + layer or the SPI host controller > + @retval EFI_UNSUPPORTED The SPI controller was not able to support > + > +**/ > +EFI_STATUS > +EFIAPI > +Transaction ( > + IN CONST EFI_SPI_IO_PROTOCOL *This, > + IN EFI_SPI_TRANSACTION_TYPE TransactionType, > + IN BOOLEAN DebugTransaction, > + IN UINT32 ClockHz OPTIONAL, > + IN UINT32 BusWidth, > + IN UINT32 FrameSize, > + IN UINT32 WriteBytes, > + IN UINT8 *WriteBuffer, > + IN UINT32 ReadBytes, > + OUT UINT8 *ReadBuffer > + ) > +{ > + EFI_STATUS Status; > + SPI_IO_CHIP *SpiChip; > + UINT32 MaxClockHz; > + UINT8 *DummyReadBuffer; > + UINT8 *DummyWriteBuffer; > + > + SpiChip = SPI_IO_CHIP_FROM_THIS (This); > + SpiChip->BusTransaction.SpiPeripheral = > + (EFI_SPI_PERIPHERAL *)SpiChip->Protocol.SpiPeripheral; > + SpiChip->BusTransaction.TransactionType = TransactionType; > + SpiChip->BusTransaction.DebugTransaction = DebugTransaction; > + SpiChip->BusTransaction.BusWidth = BusWidth; > + SpiChip->BusTransaction.FrameSize = FrameSize; > + SpiChip->BusTransaction.WriteBytes = WriteBytes; > + SpiChip->BusTransaction.WriteBuffer = WriteBuffer; > + SpiChip->BusTransaction.ReadBytes = ReadBytes; > + SpiChip->BusTransaction.ReadBuffer = ReadBuffer; > + > + // Ensure valid spi transaction parameters > + Status = IsValidSpiTransaction (SpiChip); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Setup the proper clock frequency > + if (SpiChip->BusTransaction.SpiPeripheral->MaxClockHz != 0) { > + MaxClockHz = SpiChip->BusTransaction.SpiPeripheral->MaxClockHz; > + } else { > + MaxClockHz = SpiChip->BusTransaction.SpiPeripheral->SpiPart- > >MaxClockHz; > + } > + > + // Call proper clock function > + if (SpiChip->Protocol.SpiPeripheral->SpiBus->Clock != NULL) { > + Status = SpiChip->Protocol.SpiPeripheral->SpiBus->Clock ( > + > SpiChip->BusTransaction.SpiPeripheral, > + &MaxClockHz > + ); > + } else { > + Status = SpiChip->SpiHc->Clock ( > + SpiChip->SpiHc, > + SpiChip->BusTransaction.SpiPeripheral, > + &MaxClockHz > + ); > + } > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = SpiChipSelect (SpiChip, SpiChip->BusTransaction.SpiPeripheral- > >SpiPart->ChipSelectPolarity); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Check transaction types and match to HC capabilities > + if ((TransactionType == SPI_TRANSACTION_WRITE_ONLY) && > + ((SpiChip->SpiHc->Attributes & > HC_SUPPORTS_WRITE_ONLY_OPERATIONS) != > HC_SUPPORTS_WRITE_ONLY_OPERATIONS)) > + { > + // Convert to full duplex transaction > + SpiChip->BusTransaction.ReadBytes = SpiChip- > >BusTransaction.WriteBytes; > + SpiChip->BusTransaction.ReadBuffer = AllocateZeroPool (SpiChip- > >BusTransaction.ReadBytes); > + > + Status = SpiChip->SpiHc->Transaction ( > + SpiChip->SpiHc, > + &SpiChip->BusTransaction > + ); > + > + SpiChip->BusTransaction.ReadBytes = ReadBytes; // assign to passed > parameter > + FreePool (SpiChip->BusTransaction.ReadBuffer); // Free temporary buffer > + } else if ((TransactionType == SPI_TRANSACTION_READ_ONLY) && > + ((SpiChip->SpiHc->Attributes & > HC_SUPPORTS_READ_ONLY_OPERATIONS) != > HC_SUPPORTS_READ_ONLY_OPERATIONS)) > + { > + // Convert to full duplex transaction > + SpiChip->BusTransaction.WriteBytes = SpiChip- > >BusTransaction.WriteBytes; > + SpiChip->BusTransaction.WriteBuffer = AllocateZeroPool (SpiChip- > >BusTransaction.WriteBytes); > + > + Status = SpiChip->SpiHc->Transaction ( > + SpiChip->SpiHc, > + &SpiChip->BusTransaction > + ); > + > + SpiChip->BusTransaction.WriteBytes = WriteBytes; > + FreePool (SpiChip->BusTransaction.WriteBuffer); > + } else if ((TransactionType == SPI_TRANSACTION_WRITE_THEN_READ) && > + ((SpiChip->SpiHc->Attributes & > HC_SUPPORTS_WRITE_THEN_READ_OPERATIONS) != > HC_SUPPORTS_WRITE_THEN_READ_OPERATIONS)) > + { > + // Convert to full duplex transaction > + DummyReadBuffer = AllocateZeroPool (WriteBytes); > + DummyWriteBuffer = AllocateZeroPool (ReadBytes); > + SpiChip->BusTransaction.ReadBuffer = DummyReadBuffer; > + SpiChip->BusTransaction.ReadBytes = WriteBytes; > + > + Status = SpiChip->SpiHc->Transaction ( > + SpiChip->SpiHc, > + &SpiChip->BusTransaction > + ); > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + // Write is done, now need to read, restore passed in read buffer info > + SpiChip->BusTransaction.ReadBuffer = ReadBuffer; > + SpiChip->BusTransaction.ReadBytes = ReadBytes; > + > + SpiChip->BusTransaction.WriteBuffer = DummyWriteBuffer; > + SpiChip->BusTransaction.WriteBytes = ReadBytes; > + > + Status = SpiChip->SpiHc->Transaction ( > + SpiChip->SpiHc, > + &SpiChip->BusTransaction > + ); > + // Restore write data > + SpiChip->BusTransaction.WriteBuffer = WriteBuffer; > + SpiChip->BusTransaction.WriteBytes = WriteBytes; > + > + FreePool (DummyReadBuffer); > + FreePool (DummyWriteBuffer); > + } else { > + // Supported transaction type, just pass info the SPI HC Protocol > Transaction > + Status = SpiChip->SpiHc->Transaction ( > + SpiChip->SpiHc, > + &SpiChip->BusTransaction > + ); > + } > + > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + Status = SpiChipSelect (SpiChip, !SpiChip->BusTransaction.SpiPeripheral- > >SpiPart->ChipSelectPolarity); > + > + return Status; > +} > + > +/** > + Update the SPI peripheral associated with this SPI 10 SpiChip. > + > + Support socketed SPI parts by allowing the SPI peripheral driver to replace > + the SPI peripheral after the connection is made. An example use is socketed > + SPI NOR flash parts, where the size and parameters change depending upon > + device is in the socket. > + > + @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure. > + @param[in] SpiPeripheral Pointer to an EFI_SPI_PERIPHERAL structure. > + > + @retval EFI_SUCCESS The SPI peripheral was updated successfully > + @retval EFI_INVALID_PARAMETER The SpiPeripheral value is NULL, > + or the SpiPeripheral->SpiBus is NULL, > + or the SpiPeripheral->SpiBus pointing at > + wrong bus, or the SpiPeripheral->SpiPart is > NULL > +**/ > +EFI_STATUS > +EFIAPI > +UpdateSpiPeripheral ( > + IN CONST EFI_SPI_IO_PROTOCOL *This, > + IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral > + ) > +{ > + EFI_STATUS Status; > + SPI_IO_CHIP *SpiChip; > + > + DEBUG ((DEBUG_VERBOSE, "%a: SPI Bus - Entry\n", __func__)); > + > + SpiChip = SPI_IO_CHIP_FROM_THIS (This); > + > + if ((SpiPeripheral == NULL) || (SpiPeripheral->SpiBus == NULL) || > + (SpiPeripheral->SpiPart == NULL)) > + { > + return EFI_INVALID_PARAMETER; > + } > + > + // EFI_INVALID_PARAMETER if SpiPeripheral->SpiBus is pointing at wrong > bus > + if (!DevicePathsAreEqual (SpiPeripheral->SpiBus->ControllerPath, SpiChip- > >SpiBus->ControllerPath)) { > + return EFI_INVALID_PARAMETER; > + } > + > + SpiChip->Protocol.OriginalSpiPeripheral = SpiChip->Protocol.SpiPeripheral; > + SpiChip->Protocol.SpiPeripheral = SpiPeripheral; > + > + Status = EFI_SUCCESS; > + DEBUG (( > + DEBUG_VERBOSE, > + "%a: SPI Bus - Exit Status=%r\n", > + __func__, > + Status > + )); > + return Status; > +} > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c > new file mode 100644 > index 000000000000..cd0a2c99a27b > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c > @@ -0,0 +1,198 @@ > +/** @file > + > + SPI bus DXE driver > + > + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > +#include <Base.h> > +#include <Library/BaseLib.h> > +#include <Library/DebugLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Protocol/SpiConfiguration.h> > +#include <Protocol/SpiHc.h> > +#include <Protocol/SpiIo.h> > +#include "SpiBus.h" > + > +/** > + Entry point of the Spi Bus layer > + > + @param[in] ImageHandle Image handle of this driver. > + @param[in] SystemTable Pointer to standard EFI system table. > + > + @retval EFI_SUCCESS Succeed. > + @retval EFI_DEVICE_ERROR SpiPeripheral is NULL. > + @retval EFI_NOT_FOUND Fail to locate SpiHcProtocol or > SpiIoConfigurationProtocol > + @retval EFI_OUT_OF_RESOURCES Failed to allocate SpiIoChip > +**/ > +EFI_STATUS > +EFIAPI > +SpiBusEntry ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + SPI_IO_CHIP *SpiChip; > + EFI_SPI_HC_PROTOCOL *SpiHc; > + EFI_SPI_CONFIGURATION_PROTOCOL *SpiConfiguration; > + EFI_SPI_PERIPHERAL *SpiPeripheral; > + EFI_SPI_BUS *Bus; > + UINTN BusIndex; > + UINTN HcIndex; > + EFI_HANDLE *SpiHcHandles; > + UINTN HandleCount; > + EFI_DEVICE_PATH_PROTOCOL *SpiHcDevicePath; > + > + DEBUG ((DEBUG_VERBOSE, "%a - ENTRY\n", __func__)); > + > + // Get all SPI HC protocols, could be multiple SPI HC's on a single > platform > + Status = gBS->LocateHandleBuffer ( > + ByProtocol, > + &gEfiSpiHcProtocolGuid, > + NULL, > + &HandleCount, > + &SpiHcHandles > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "No SpiHcProtocol is found\n")); > + Status = EFI_NOT_FOUND; > + goto Exit; > + } > + > + // Locate the SPI Configuration Protocol > + Status = gBS->LocateProtocol ( > + &gEfiSpiConfigurationProtocolGuid, > + NULL, > + (VOID **)&SpiConfiguration > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "No SpiConfigurationProtocol is found\n")); > + Status = EFI_NOT_FOUND; > + goto Exit; > + } > + > + // Parse through Hc protocols, find correct device path > + for (HcIndex = 0; HcIndex < HandleCount; HcIndex++) { > + Status = gBS->HandleProtocol ( > + SpiHcHandles[HcIndex], > + &gEfiDevicePathProtocolGuid, > + (VOID **)&SpiHcDevicePath > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "Error locating EFI device path for this SPI > controller, status=%r \n", Status)); > + continue; // Continue searching > + } > + > + // Parse through SpiConfiguration's SpiBuses, find matching devicepath > for > SpiHc > + for (BusIndex = 0; BusIndex < SpiConfiguration->BusCount; BusIndex++) { > + Bus = (EFI_SPI_BUS *)SpiConfiguration->Buslist[BusIndex]; > + if (!DevicePathsAreEqual (SpiHcDevicePath, Bus->ControllerPath)) { > + DEBUG ((DEBUG_VERBOSE, "SpiHc and SpiConfig device paths dont > match, continue parsing\n")); > + continue; > + } > + > + DEBUG (( > + DEBUG_VERBOSE, > + "%a: Found matching device paths, Enumerating SPI BUS: %s with > DevicePath: %s\n", > + __func__, > + Bus->FriendlyName, > + ConvertDevicePathToText (SpiHcDevicePath, FALSE, FALSE) > + )); > + > + // Get SpiHc from the SpiHcHandles > + Status = gBS->HandleProtocol ( > + SpiHcHandles[HcIndex], > + &gEfiDevicePathProtocolGuid, > + (VOID **)&SpiHc > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "%a - Error getting SpiHc from Handle\n", > __func__)); > + goto Exit; > + } > + > + SpiPeripheral = (EFI_SPI_PERIPHERAL *)Bus->Peripherallist; > + if (SpiPeripheral != NULL) { > + do { > + DEBUG (( > + DEBUG_VERBOSE, > + "%a: Installing SPI IO protocol for %s, by %s, PN=%s\n", > + __func__, > + SpiPeripheral->FriendlyName, > + SpiPeripheral->SpiPart->Vendor, > + SpiPeripheral->SpiPart->PartNumber > + )); > + // Allocate the SPI IO Device > + SpiChip = AllocateZeroPool (sizeof (SPI_IO_CHIP)); > + ASSERT (SpiChip != NULL); > + if (SpiChip != NULL) { > + // Fill in the SpiChip > + SpiChip->Signature = SPI_IO_SIGNATURE; > + SpiChip->SpiConfig = SpiConfiguration; > + SpiChip->SpiHc = SpiHc; > + SpiChip->SpiBus = Bus; > + SpiChip->Protocol.SpiPeripheral = SpiPeripheral; > + SpiChip->Protocol.OriginalSpiPeripheral = SpiPeripheral; > + SpiChip->Protocol.FrameSizeSupportMask = SpiHc- > >FrameSizeSupportMask; > + SpiChip->Protocol.MaximumTransferBytes = SpiHc- > >MaximumTransferBytes; > + if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_ADDRESS) != > 0) { > + SpiChip->Protocol.Attributes |= > SPI_IO_TRANSFER_SIZE_INCLUDES_ADDRESS; > + } > + > + if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_OPCODE) != 0) > { > + SpiChip->Protocol.Attributes |= > SPI_IO_TRANSFER_SIZE_INCLUDES_OPCODE; > + } > + > + if ((SpiHc->Attributes & HC_SUPPORTS_8_BIT_DATA_BUS_WIDTH) != > 0) { > + SpiChip->Protocol.Attributes |= > SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH; > + } > + > + if ((SpiHc->Attributes & HC_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != > 0) { > + SpiChip->Protocol.Attributes |= > SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH; > + } > + > + if ((SpiHc->Attributes & HC_SUPPORTS_2_BIT_DATA_BUS_WIDTH) != > 0) { > + SpiChip->Protocol.Attributes |= > SPI_IO_SUPPORTS_2_BIT_DATA_BUS_WIDTH; > + } > + > + SpiChip->Protocol.Transaction = Transaction; > + SpiChip->Protocol.UpdateSpiPeripheral = UpdateSpiPeripheral; > + // Install the SPI IO Protocol > + Status = gBS->InstallProtocolInterface ( > + &SpiChip->Handle, > + (GUID *)SpiPeripheral->SpiPeripheralDriverGuid, > + EFI_NATIVE_INTERFACE, > + &SpiChip->Protocol > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "%a - Error installing SpiIoProtocol\n", > __func__)); > + continue; > + } > + } else { > + Status = EFI_OUT_OF_RESOURCES; > + DEBUG (( > + DEBUG_ERROR, > + "%a: Out of Memory resources\n", > + __func__ > + )); > + break; > + } > + > + SpiPeripheral = (EFI_SPI_PERIPHERAL *)SpiPeripheral- > >NextSpiPeripheral; > + } while (SpiPeripheral != NULL); > + } else { > + Status = EFI_DEVICE_ERROR; > + } > + } > + } > + > +Exit: > + DEBUG ((DEBUG_VERBOSE, "%a - EXIT (Status = %r)\n", __func__, Status)); > + return Status; > +} > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c > new file mode 100644 > index 000000000000..d9189b984835 > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c > @@ -0,0 +1,162 @@ > +/** @file > + > + SPI bus SMM driver > + > + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > +#include <Base.h> > +#include <Library/BaseLib.h> > +#include <Library/DebugLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/MmServicesTableLib.h> > +#include <Protocol/SpiSmmConfiguration.h> > +#include <Protocol/SpiSmmHc.h> > +#include <Protocol/SpiIo.h> > +#include "SpiBus.h" > + > +/** > + Entry point of the Spi Bus layer > + > + @param[in] ImageHandle Image handle of this driver. > + @param[in] SystemTable Pointer to standard EFI system table. > + > + @retval EFI_SUCCESS Succeed. > + @retval EFI_DEVICE_ERROR Fail to install EFI_SPI_HC_PROTOCOL protocol. > + @retval EFI_NOT_FOUND fail to locate SpiHcProtocol or > SpiIoConfigurationProtocol > + @retval EFI_OUT_OF_RESOURCES Failed to allocate SpiIoChip > +**/ > +EFI_STATUS > +EFIAPI > +SpiBusEntry ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + SPI_IO_CHIP *SpiChip; > + EFI_SPI_HC_PROTOCOL *SpiHc; > + EFI_SPI_CONFIGURATION_PROTOCOL *SpiConfiguration; > + EFI_SPI_PERIPHERAL *SpiPeripheral; > + EFI_SPI_BUS *Bus; > + > + DEBUG ((DEBUG_VERBOSE, "%a - ENTRY\n", __func__)); > + > + // Only a single Spi HC protocol in SMM > + Status = gMmst->MmLocateProtocol ( > + &gEfiSpiSmmHcProtocolGuid, > + NULL, > + (VOID **)&SpiHc > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "No SpiHcProtocol is found\n")); > + Status = EFI_NOT_FOUND; > + goto Exit; > + } > + > + // Locate the SPI Configuration Protocol > + Status = gMmst->MmLocateProtocol ( > + &gEfiSpiSmmConfigurationProtocolGuid, > + NULL, > + (VOID **)&SpiConfiguration > + ); > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "No SpiConfigurationProtocol is found\n")); > + Status = EFI_NOT_FOUND; > + goto Exit; > + } > + > + // Only one SpiBus supported in SMM > + if (SpiConfiguration->BusCount != 1) { > + DEBUG ((DEBUG_VERBOSE, "Only one SPI Bus supported in SMM\n")); > + Status = EFI_UNSUPPORTED; > + goto Exit; > + } > + > + Bus = (EFI_SPI_BUS *)SpiConfiguration->Buslist[0]; > + > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "%a - Error getting SpiHc from Handle\n", > __func__)); > + goto Exit; > + } > + > + SpiPeripheral = (EFI_SPI_PERIPHERAL *)Bus->Peripherallist; > + if (SpiPeripheral != NULL) { > + do { > + DEBUG (( > + DEBUG_VERBOSE, > + "%a: Installing SPI IO protocol for %s, by %s, PN=%s\n", > + __func__, > + SpiPeripheral->FriendlyName, > + SpiPeripheral->SpiPart->Vendor, > + SpiPeripheral->SpiPart->PartNumber > + )); > + // Allocate the SPI IO Device > + SpiChip = AllocateZeroPool (sizeof (SPI_IO_CHIP)); > + ASSERT (SpiChip != NULL); > + if (SpiChip != NULL) { > + // Fill in the SpiChip > + SpiChip->Signature = SPI_IO_SIGNATURE; > + SpiChip->SpiConfig = SpiConfiguration; > + SpiChip->SpiHc = SpiHc; > + SpiChip->SpiBus = Bus; > + SpiChip->Protocol.SpiPeripheral = SpiPeripheral; > + SpiChip->Protocol.OriginalSpiPeripheral = SpiPeripheral; > + SpiChip->Protocol.FrameSizeSupportMask = SpiHc- > >FrameSizeSupportMask; > + SpiChip->Protocol.MaximumTransferBytes = SpiHc- > >MaximumTransferBytes; > + if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_ADDRESS) != 0) { > + SpiChip->Protocol.Attributes |= > SPI_IO_TRANSFER_SIZE_INCLUDES_ADDRESS; > + } > + > + if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_OPCODE) != 0) { > + SpiChip->Protocol.Attributes |= > SPI_IO_TRANSFER_SIZE_INCLUDES_OPCODE; > + } > + > + if ((SpiHc->Attributes & HC_SUPPORTS_8_BIT_DATA_BUS_WIDTH) != 0) { > + SpiChip->Protocol.Attributes |= > SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH; > + } > + > + if ((SpiHc->Attributes & HC_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != 0) { > + SpiChip->Protocol.Attributes |= > SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH; > + } > + > + if ((SpiHc->Attributes & HC_SUPPORTS_2_BIT_DATA_BUS_WIDTH) != 0) { > + SpiChip->Protocol.Attributes |= > SPI_IO_SUPPORTS_2_BIT_DATA_BUS_WIDTH; > + } > + > + SpiChip->Protocol.Transaction = Transaction; > + SpiChip->Protocol.UpdateSpiPeripheral = UpdateSpiPeripheral; > + // Install the SPI IO Protocol > + Status = gMmst->MmInstallProtocolInterface ( > + &SpiChip->Handle, > + (GUID *)SpiPeripheral->SpiPeripheralDriverGuid, > + EFI_NATIVE_INTERFACE, > + &SpiChip->Protocol > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_VERBOSE, "%a - Error installing SpiIoProtocol\n", > __func__)); > + continue; > + } > + } else { > + Status = EFI_OUT_OF_RESOURCES; > + DEBUG (( > + DEBUG_ERROR, > + "%a: Out of Memory resources\n", > + __func__ > + )); > + break; > + } > + > + SpiPeripheral = (EFI_SPI_PERIPHERAL *)SpiPeripheral->NextSpiPeripheral; > + } while (SpiPeripheral != NULL); > + } else { > + Status = EFI_DEVICE_ERROR; > + } > + > +Exit: > + DEBUG ((DEBUG_VERBOSE, "%a - EXIT (Status = %r)\n", __func__, Status)); > + return Status; > +} > diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni > b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni > new file mode 100644 > index 000000000000..0d913bdbae39 > --- /dev/null > +++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni > @@ -0,0 +1,10 @@ > +// /** @file > +// > +// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR> > +// > +// SPDX-License-Identifier: BSD-2-Clause-Patent > +// > +// **/ > + > +#string STR_PROPERTIES_MODULE_NAME > +#language en-US "SPI Bus driver" > -- > 2.42.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#118493): https://edk2.groups.io/g/devel/message/118493 Mute This Topic: https://groups.io/mt/105849135/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-