From bc0a1bc83360c8a8a5e17a97167ae740525f1134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20B=C4=83l=C4=83nic=C4=83?= Date: Wed, 10 Jan 2024 02:55:29 +0200 Subject: [PATCH] Silicon/RK3588: Add option to change serial baud rate within UEFI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Firstly, split up the Dw8250 serial lib into "full" and "debug" versions. The full version is only used at SEC phase (PrePi) for setting the specified baud rate, while the debug one is used everywhere else and cannot reinitialize the UART. To read the baud rate NV variable in SEC, introduce BaseVariableLib, which is just a slightly modified FaultTolerantWritePei + VariablePei to not use HOBs and PPIs, since they're not available this early. Previous boot stages (DDR, TF-A, U-Boot SPL) are still hardcoded to output at 1.5 Mbaud. Signed-off-by: Mario Bălănică --- .../Include/Library/BaseVariableLib.h | 90 + .../Library/BaseVariableLib/BaseVariableLib.c | 1460 +++++++++++++++++ .../BaseVariableLib/BaseVariableLib.inf | 51 + .../Library/BaseVariableLib/Variable.h | 45 + .../DebugDw8250SerialPortLib.c | 40 + .../DebugDw8250SerialPortLib.inf | 35 + .../Dw8250SerialPortLib/Dw8250SerialPortLib.c | 246 --- .../Dw8250SerialPortLib.inf | 6 +- .../Dw8250SerialPortLibCommon.c | 260 +++ .../PlatformBootManagerLib/PlatformBm.c | 13 +- .../PlatformBootManagerLib.inf | 8 +- .../Drivers/RK3588Dxe/DebugSerialPort.c | 50 + .../Drivers/RK3588Dxe/DebugSerialPort.h | 33 + .../RK3588/Drivers/RK3588Dxe/RK3588Dxe.c | 3 + .../RK3588/Drivers/RK3588Dxe/RK3588Dxe.inf | 5 +- .../RK3588/Drivers/RK3588Dxe/RK3588DxeHii.uni | 11 +- .../RK3588/Drivers/RK3588Dxe/RK3588DxeHii.vfr | 27 +- .../Rockchip/RK3588/Include/VarStoreData.h | 4 + .../Library/PlatformLib/PlatformLib.inf | 8 + .../RK3588/Library/PlatformLib/Rk3588.c | 23 + .../Rockchip/RK3588/RK3588Base.dsc.inc | 17 +- .../Silicon/Rockchip/Rockchip.dsc.inc | 2 + 22 files changed, 2172 insertions(+), 265 deletions(-) create mode 100644 edk2-rockchip/Silicon/Rockchip/Include/Library/BaseVariableLib.h create mode 100644 edk2-rockchip/Silicon/Rockchip/Library/BaseVariableLib/BaseVariableLib.c create mode 100644 edk2-rockchip/Silicon/Rockchip/Library/BaseVariableLib/BaseVariableLib.inf create mode 100644 edk2-rockchip/Silicon/Rockchip/Library/BaseVariableLib/Variable.h create mode 100644 edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/DebugDw8250SerialPortLib.c create mode 100644 edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/DebugDw8250SerialPortLib.inf create mode 100644 edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLibCommon.c create mode 100644 edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/DebugSerialPort.c create mode 100644 edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/DebugSerialPort.h diff --git a/edk2-rockchip/Silicon/Rockchip/Include/Library/BaseVariableLib.h b/edk2-rockchip/Silicon/Rockchip/Include/Library/BaseVariableLib.h new file mode 100644 index 000000000..7cfdf924c --- /dev/null +++ b/edk2-rockchip/Silicon/Rockchip/Include/Library/BaseVariableLib.h @@ -0,0 +1,90 @@ +/** @file + * + * Read-only non-volatile variable service library for early SEC phase. + * Based on FaultTolerantWritePei and VariablePei, without using any HOBs. + * + * Copyright (c) 2024, Mario Bălănică + * Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) Microsoft Corporation.
+ * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#ifndef __BASE_VARIABLE_LIB_H__ +#define __BASE_VARIABLE_LIB_H__ + +#include + +/** + This service retrieves a variable's value using its name and GUID. + + Read the specified variable from the UEFI variable store. If the Data + buffer is too small to hold the contents of the variable, the error + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer + size to obtain the data. + + @param VariableName A pointer to a null-terminated string that is the variable's name. + @param VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of + VariableGuid and VariableName must be unique. + @param Attributes If non-NULL, on return, points to the variable's attributes. + @param DataSize On entry, points to the size in bytes of the Data buffer. + On return, points to the size of the data returned in Data. + @param Data Points to the buffer which will hold the returned variable value. + May be NULL with a zero DataSize in order to determine the size of the buffer needed. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable was not found. + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data. + DataSize is updated with the size required for + the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. + +**/ +EFI_STATUS +EFIAPI +BaseGetVariable ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ); + +/** + Return the next variable name and GUID. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param VariableNameSize On entry, points to the size of the buffer pointed to by VariableName. + @param VariableName On entry, a pointer to a null-terminated string that is the variable's name. + On return, points to the next variable's null-terminated name string. + + @param VariableGuid On entry, a pointer to an UEFI _GUID that is the variable's GUID. + On return, a pointer to the next variable's GUID. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable could not be found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting + data. VariableNameSize is updated with the size + required for the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or + VariableNameSize is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. + +**/ +EFI_STATUS +EFIAPI +BaseGetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid + ); + +#endif // __BASE_VARIABLE_LIB_H__ diff --git a/edk2-rockchip/Silicon/Rockchip/Library/BaseVariableLib/BaseVariableLib.c b/edk2-rockchip/Silicon/Rockchip/Library/BaseVariableLib/BaseVariableLib.c new file mode 100644 index 000000000..56ab4629e --- /dev/null +++ b/edk2-rockchip/Silicon/Rockchip/Library/BaseVariableLib/BaseVariableLib.c @@ -0,0 +1,1460 @@ +/** @file + * + * Read-only non-volatile variable service library for early SEC phase. + * Based on FaultTolerantWritePei and VariablePei, without using any HOBs. + * + * Copyright (c) 2024, Mario Bălănică + * Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ * Copyright (c) Microsoft Corporation.
+ * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#include "Variable.h" + +STATIC FAULT_TOLERANT_WRITE_LAST_WRITE_DATA mFtwLastWriteData; +STATIC BOOLEAN mFtwLastWriteDataInitialized; + +// Also fits VARIABLE_HEADER +STATIC AUTHENTICATED_VARIABLE_HEADER mVariableHeaderFtw; +STATIC BOOLEAN mVariableHeaderFtwMerged; + +STATIC VARIABLE_INDEX_TABLE mVariableIndexTable; + +/** + Get the last Write Header pointer. + The last write header is the header whose 'complete' state hasn't been set. + After all, this header may be a EMPTY header entry for next Allocate. + + + @param FtwWorkSpaceHeader Pointer of the working block header + @param FtwWorkSpaceSize Size of the work space + @param FtwWriteHeader Pointer to retrieve the last write header + + @retval EFI_SUCCESS Get the last write record successfully + @retval EFI_ABORTED The FTW work space is damaged + +**/ +EFI_STATUS +FtwGetLastWriteHeader ( + IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkSpaceHeader, + IN UINTN FtwWorkSpaceSize, + OUT EFI_FAULT_TOLERANT_WRITE_HEADER **FtwWriteHeader + ) +{ + UINTN Offset; + EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader; + + *FtwWriteHeader = NULL; + FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *)(FtwWorkSpaceHeader + 1); + Offset = sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER); + + while (FtwHeader->Complete == FTW_VALID_STATE) { + Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize); + // + // If Offset exceed the FTW work space boudary, return error. + // + if (Offset >= FtwWorkSpaceSize) { + *FtwWriteHeader = FtwHeader; + return EFI_ABORTED; + } + + FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *)((UINT8 *)FtwWorkSpaceHeader + Offset); + } + + // + // Last write header is found + // + *FtwWriteHeader = FtwHeader; + + return EFI_SUCCESS; +} + +/** + Get the last Write Record pointer. The last write Record is the Record + whose DestinationCompleted state hasn't been set. After all, this Record + may be a EMPTY record entry for next write. + + + @param FtwWriteHeader Pointer to the write record header + @param FtwWriteRecord Pointer to retrieve the last write record + + @retval EFI_SUCCESS Get the last write record successfully + @retval EFI_ABORTED The FTW work space is damaged + +**/ +EFI_STATUS +FtwGetLastWriteRecord ( + IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwWriteHeader, + OUT EFI_FAULT_TOLERANT_WRITE_RECORD **FtwWriteRecord + ) +{ + UINTN Index; + EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord; + + *FtwWriteRecord = NULL; + FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *)(FtwWriteHeader + 1); + + // + // Try to find the last write record "that has not completed" + // + for (Index = 0; Index < FtwWriteHeader->NumberOfWrites; Index += 1) { + if (FtwRecord->DestinationComplete != FTW_VALID_STATE) { + // + // The last write record is found + // + *FtwWriteRecord = FtwRecord; + return EFI_SUCCESS; + } + + FtwRecord++; + + if (FtwWriteHeader->PrivateDataSize != 0) { + FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *)((UINTN)FtwRecord + (UINTN)FtwWriteHeader->PrivateDataSize); + } + } + + // + // if Index == NumberOfWrites, then + // the last record has been written successfully, + // but the Header->Complete Flag has not been set. + // also return the last record. + // + if (Index == FtwWriteHeader->NumberOfWrites) { + *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *)((UINTN)FtwRecord - FTW_RECORD_SIZE (FtwWriteHeader->PrivateDataSize)); + return EFI_SUCCESS; + } + + return EFI_ABORTED; +} + +/** + Check to see if it is a valid work space. + + + @param WorkingHeader Pointer of working block header + @param WorkingLength Working block length + + @retval TRUE The work space is valid. + @retval FALSE The work space is invalid. + +**/ +BOOLEAN +IsValidWorkSpace ( + IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader, + IN UINTN WorkingLength + ) +{ + UINT8 Data; + + if (WorkingHeader == NULL) { + return FALSE; + } + + if ((WorkingHeader->WorkingBlockValid != FTW_VALID_STATE) || (WorkingHeader->WorkingBlockInvalid == FTW_VALID_STATE)) { + DEBUG ((DEBUG_ERROR, "FtwPei: Work block header valid bit check error\n")); + return FALSE; + } + + if (WorkingHeader->WriteQueueSize != (WorkingLength - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER))) { + DEBUG ((DEBUG_ERROR, "FtwPei: Work block header WriteQueueSize check error\n")); + return FALSE; + } + + // + // Check signature with gEdkiiWorkingBlockSignatureGuid + // + if (!CompareGuid (&gEdkiiWorkingBlockSignatureGuid, &WorkingHeader->Signature)) { + DEBUG ((DEBUG_ERROR, "FtwPei: Work block header signature check error, it should be gEdkiiWorkingBlockSignatureGuid\n")); + // + // To be compatible with old signature gEfiSystemNvDataFvGuid. + // + if (!CompareGuid (&gEfiSystemNvDataFvGuid, &WorkingHeader->Signature)) { + return FALSE; + } else { + Data = *(UINT8 *)(WorkingHeader + 1); + if (Data != 0xff) { + DEBUG ((DEBUG_ERROR, "FtwPei: Old format FTW structure can't be handled\n")); + ASSERT (FALSE); + return FALSE; + } + } + } + + return TRUE; +} + +/** + Main entry for Fault Tolerant Write PEIM. + + @param[in] FileHandle Handle of the file being invoked. + @param[in] PeiServices Pointer to PEI Services table. + + @retval EFI_SUCCESS If the interface could be successfully installed + @retval Others Returned from PeiServicesInstallPpi() + +**/ +EFI_STATUS +EFIAPI +FaultTolerantWriteInitialize ( + VOID + ) +{ + EFI_STATUS Status; + EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkingBlockHeader; + EFI_FAULT_TOLERANT_WRITE_HEADER *FtwLastWriteHeader; + EFI_FAULT_TOLERANT_WRITE_RECORD *FtwLastWriteRecord; + EFI_PHYSICAL_ADDRESS WorkSpaceAddress; + UINTN WorkSpaceLength; + EFI_PHYSICAL_ADDRESS SpareAreaAddress; + UINTN SpareAreaLength; + EFI_PHYSICAL_ADDRESS WorkSpaceInSpareArea; + + if (mFtwLastWriteDataInitialized) { + return EFI_SUCCESS; + } + + FtwWorkingBlockHeader = NULL; + FtwLastWriteHeader = NULL; + FtwLastWriteRecord = NULL; + + WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdFlashNvStorageFtwWorkingBase64); + if (WorkSpaceAddress == 0) { + WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdFlashNvStorageFtwWorkingBase); + } + + WorkSpaceLength = (UINTN)PcdGet32 (PcdFlashNvStorageFtwWorkingSize); + + SpareAreaAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdFlashNvStorageFtwSpareBase64); + if (SpareAreaAddress == 0) { + SpareAreaAddress = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdFlashNvStorageFtwSpareBase); + } + + SpareAreaLength = (UINTN)PcdGet32 (PcdFlashNvStorageFtwSpareSize); + + // + // The address of FTW working base and spare base must not be 0. + // + ASSERT ((WorkSpaceAddress != 0) && (SpareAreaAddress != 0)); + + FtwWorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *)(UINTN)WorkSpaceAddress; + if (IsValidWorkSpace (FtwWorkingBlockHeader, WorkSpaceLength)) { + Status = FtwGetLastWriteHeader ( + FtwWorkingBlockHeader, + WorkSpaceLength, + &FtwLastWriteHeader + ); + if (!EFI_ERROR (Status)) { + Status = FtwGetLastWriteRecord ( + FtwLastWriteHeader, + &FtwLastWriteRecord + ); + } + + if (!EFI_ERROR (Status)) { + ASSERT (FtwLastWriteRecord != NULL); + if ((FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE) && (FtwLastWriteRecord->DestinationComplete != FTW_VALID_STATE)) { + // + // If FTW last write was still in progress with SpareComplete set and DestinationComplete not set. + // It means the target buffer has been backed up in spare block, then target block has been erased, + // but the target buffer has not been writen in target block from spare block, we need to build + // FAULT_TOLERANT_WRITE_LAST_WRITE_DATA GUID hob to hold the FTW last write data. + // + mFtwLastWriteData.TargetAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((INT64)SpareAreaAddress + FtwLastWriteRecord->RelativeOffset); + mFtwLastWriteData.SpareAddress = SpareAreaAddress; + mFtwLastWriteData.Length = SpareAreaLength; + DEBUG (( + DEBUG_INFO, + "FtwPei last write data: TargetAddress - 0x%x SpareAddress - 0x%x Length - 0x%x\n", + (UINTN)mFtwLastWriteData.TargetAddress, + (UINTN)mFtwLastWriteData.SpareAddress, + (UINTN)mFtwLastWriteData.Length + )); + } + } + } else { + FtwWorkingBlockHeader = NULL; + // + // If the working block workspace is not valid, try to find workspace in the spare block. + // + WorkSpaceInSpareArea = SpareAreaAddress + SpareAreaLength - WorkSpaceLength; + while (WorkSpaceInSpareArea >= SpareAreaAddress) { + if (CompareGuid (&gEdkiiWorkingBlockSignatureGuid, (EFI_GUID *)(UINTN)WorkSpaceInSpareArea)) { + // + // Found the workspace. + // + DEBUG ((DEBUG_INFO, "FtwPei: workspace in spare block is at 0x%x.\n", (UINTN)WorkSpaceInSpareArea)); + FtwWorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *)(UINTN)WorkSpaceInSpareArea; + break; + } + + WorkSpaceInSpareArea = WorkSpaceInSpareArea - sizeof (EFI_GUID); + } + + if ((FtwWorkingBlockHeader != NULL) && IsValidWorkSpace (FtwWorkingBlockHeader, WorkSpaceLength)) { + // + // It was workspace self reclaim, build FAULT_TOLERANT_WRITE_LAST_WRITE_DATA GUID hob for it. + // + mFtwLastWriteData.TargetAddress = WorkSpaceAddress - (WorkSpaceInSpareArea - SpareAreaAddress); + mFtwLastWriteData.SpareAddress = SpareAreaAddress; + mFtwLastWriteData.Length = SpareAreaLength; + DEBUG (( + DEBUG_INFO, + "FtwPei last write data: TargetAddress - 0x%x SpareAddress - 0x%x Length - 0x%x\n", + (UINTN)mFtwLastWriteData.TargetAddress, + (UINTN)mFtwLastWriteData.SpareAddress, + (UINTN)mFtwLastWriteData.Length + )); + } else { + // + // Both are invalid. + // + DEBUG ((DEBUG_ERROR, "FtwPei: Both working and spare block are invalid.\n")); + } + } + + mFtwLastWriteDataInitialized = TRUE; + + return EFI_SUCCESS; +} + +/** + + Gets the pointer to the first variable header in given variable store area. + + @param VarStoreHeader Pointer to the Variable Store Header. + + @return Pointer to the first variable header. + +**/ +VARIABLE_HEADER * +GetStartPointer ( + IN VARIABLE_STORE_HEADER *VarStoreHeader + ) +{ + // + // The start of variable store + // + return (VARIABLE_HEADER *)HEADER_ALIGN (VarStoreHeader + 1); +} + +/** + + Gets the pointer to the end of the variable storage area. + + This function gets pointer to the end of the variable storage + area, according to the input variable store header. + + @param VarStoreHeader Pointer to the Variable Store Header. + + @return Pointer to the end of the variable storage area. + +**/ +VARIABLE_HEADER * +GetEndPointer ( + IN VARIABLE_STORE_HEADER *VarStoreHeader + ) +{ + // + // The end of variable store + // + return (VARIABLE_HEADER *)HEADER_ALIGN ((UINTN)VarStoreHeader + VarStoreHeader->Size); +} + +/** + This code checks if variable header is valid or not. + + @param Variable Pointer to the Variable Header. + + @retval TRUE Variable header is valid. + @retval FALSE Variable header is not valid. + +**/ +BOOLEAN +IsValidVariableHeader ( + IN VARIABLE_HEADER *Variable + ) +{ + if ((Variable == NULL) || (Variable->StartId != VARIABLE_DATA)) { + return FALSE; + } + + return TRUE; +} + +/** + This code gets the size of variable header. + + @param AuthFlag Authenticated variable flag. + + @return Size of variable header in bytes in type UINTN. + +**/ +UINTN +GetVariableHeaderSize ( + IN BOOLEAN AuthFlag + ) +{ + UINTN Value; + + if (AuthFlag) { + Value = sizeof (AUTHENTICATED_VARIABLE_HEADER); + } else { + Value = sizeof (VARIABLE_HEADER); + } + + return Value; +} + +/** + This code gets the size of name of variable. + + @param Variable Pointer to the Variable Header. + @param AuthFlag Authenticated variable flag. + + @return Size of variable in bytes in type UINTN. + +**/ +UINTN +NameSizeOfVariable ( + IN VARIABLE_HEADER *Variable, + IN BOOLEAN AuthFlag + ) +{ + AUTHENTICATED_VARIABLE_HEADER *AuthVariable; + + AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *)Variable; + if (AuthFlag) { + if ((AuthVariable->State == (UINT8)(-1)) || + (AuthVariable->DataSize == (UINT32)(-1)) || + (AuthVariable->NameSize == (UINT32)(-1)) || + (AuthVariable->Attributes == (UINT32)(-1))) + { + return 0; + } + + return (UINTN)AuthVariable->NameSize; + } else { + if ((Variable->State == (UINT8)(-1)) || + (Variable->DataSize == (UINT32)(-1)) || + (Variable->NameSize == (UINT32)(-1)) || + (Variable->Attributes == (UINT32)(-1))) + { + return 0; + } + + return (UINTN)Variable->NameSize; + } +} + +/** + This code gets the size of data of variable. + + @param Variable Pointer to the Variable Header. + @param AuthFlag Authenticated variable flag. + + @return Size of variable in bytes in type UINTN. + +**/ +UINTN +DataSizeOfVariable ( + IN VARIABLE_HEADER *Variable, + IN BOOLEAN AuthFlag + ) +{ + AUTHENTICATED_VARIABLE_HEADER *AuthVariable; + + AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *)Variable; + if (AuthFlag) { + if ((AuthVariable->State == (UINT8)(-1)) || + (AuthVariable->DataSize == (UINT32)(-1)) || + (AuthVariable->NameSize == (UINT32)(-1)) || + (AuthVariable->Attributes == (UINT32)(-1))) + { + return 0; + } + + return (UINTN)AuthVariable->DataSize; + } else { + if ((Variable->State == (UINT8)(-1)) || + (Variable->DataSize == (UINT32)(-1)) || + (Variable->NameSize == (UINT32)(-1)) || + (Variable->Attributes == (UINT32)(-1))) + { + return 0; + } + + return (UINTN)Variable->DataSize; + } +} + +/** + This code gets the pointer to the variable name. + + @param Variable Pointer to the Variable Header. + @param AuthFlag Authenticated variable flag. + + @return A CHAR16* pointer to Variable Name. + +**/ +CHAR16 * +GetVariableNamePtr ( + IN VARIABLE_HEADER *Variable, + IN BOOLEAN AuthFlag + ) +{ + return (CHAR16 *)((UINTN)Variable + GetVariableHeaderSize (AuthFlag)); +} + +/** + This code gets the pointer to the variable guid. + + @param Variable Pointer to the Variable Header. + @param AuthFlag Authenticated variable flag. + + @return A EFI_GUID* pointer to Vendor Guid. + +**/ +EFI_GUID * +GetVendorGuidPtr ( + IN VARIABLE_HEADER *Variable, + IN BOOLEAN AuthFlag + ) +{ + AUTHENTICATED_VARIABLE_HEADER *AuthVariable; + + AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *)Variable; + if (AuthFlag) { + return &AuthVariable->VendorGuid; + } else { + return &Variable->VendorGuid; + } +} + +/** + This code gets the pointer to the variable data. + + @param Variable Pointer to the Variable Header. + @param VariableHeader Pointer to the Variable Header that has consecutive content. + @param AuthFlag Authenticated variable flag. + + @return A UINT8* pointer to Variable Data. + +**/ +UINT8 * +GetVariableDataPtr ( + IN VARIABLE_HEADER *Variable, + IN VARIABLE_HEADER *VariableHeader, + IN BOOLEAN AuthFlag + ) +{ + UINTN Value; + + // + // Be careful about pad size for alignment + // + Value = (UINTN)GetVariableNamePtr (Variable, AuthFlag); + Value += NameSizeOfVariable (VariableHeader, AuthFlag); + Value += GET_PAD_SIZE (NameSizeOfVariable (VariableHeader, AuthFlag)); + + return (UINT8 *)Value; +} + +/** + This code gets the pointer to the next variable header. + + @param StoreInfo Pointer to variable store info structure. + @param Variable Pointer to the Variable Header. + @param VariableHeader Pointer to the Variable Header that has consecutive content. + + @return A VARIABLE_HEADER* pointer to next variable header. + +**/ +VARIABLE_HEADER * +GetNextVariablePtr ( + IN VARIABLE_STORE_INFO *StoreInfo, + IN VARIABLE_HEADER *Variable, + IN VARIABLE_HEADER *VariableHeader + ) +{ + EFI_PHYSICAL_ADDRESS TargetAddress; + EFI_PHYSICAL_ADDRESS SpareAddress; + UINTN Value; + + Value = (UINTN)GetVariableDataPtr (Variable, VariableHeader, StoreInfo->AuthFlag); + Value += DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag); + Value += GET_PAD_SIZE (DataSizeOfVariable (VariableHeader, StoreInfo->AuthFlag)); + // + // Be careful about pad size for alignment + // + Value = HEADER_ALIGN (Value); + + if (StoreInfo->FtwLastWriteData != NULL) { + TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress; + SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress; + if (((UINTN)Variable < (UINTN)TargetAddress) && (Value >= (UINTN)TargetAddress)) { + // + // Next variable is in spare block. + // + Value = (UINTN)SpareAddress + (Value - (UINTN)TargetAddress); + } + } + + return (VARIABLE_HEADER *)Value; +} + +/** + Get variable store status. + + @param VarStoreHeader Pointer to the Variable Store Header. + + @retval EfiRaw Variable store is raw + @retval EfiValid Variable store is valid + @retval EfiInvalid Variable store is invalid + +**/ +VARIABLE_STORE_STATUS +GetVariableStoreStatus ( + IN VARIABLE_STORE_HEADER *VarStoreHeader + ) +{ + if ((CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid) || + CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid)) && + (VarStoreHeader->Format == VARIABLE_STORE_FORMATTED) && + (VarStoreHeader->State == VARIABLE_STORE_HEALTHY) + ) + { + return EfiValid; + } + + if ((((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff) && + (((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff) && + (((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff) && + (((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff) && + (VarStoreHeader->Size == 0xffffffff) && + (VarStoreHeader->Format == 0xff) && + (VarStoreHeader->State == 0xff) + ) + { + return EfiRaw; + } else { + return EfiInvalid; + } +} + +/** + Compare two variable names, one of them may be inconsecutive. + + @param StoreInfo Pointer to variable store info structure. + @param Name1 Pointer to one variable name. + @param Name2 Pointer to another variable name. + @param NameSize Variable name size. + + @retval TRUE Name1 and Name2 are identical. + @retval FALSE Name1 and Name2 are not identical. + +**/ +BOOLEAN +CompareVariableName ( + IN VARIABLE_STORE_INFO *StoreInfo, + IN CONST CHAR16 *Name1, + IN CONST CHAR16 *Name2, + IN UINTN NameSize + ) +{ + EFI_PHYSICAL_ADDRESS TargetAddress; + EFI_PHYSICAL_ADDRESS SpareAddress; + UINTN PartialNameSize; + + if (StoreInfo->FtwLastWriteData != NULL) { + TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress; + SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress; + if (((UINTN)Name1 < (UINTN)TargetAddress) && (((UINTN)Name1 + NameSize) > (UINTN)TargetAddress)) { + // + // Name1 is inconsecutive. + // + PartialNameSize = (UINTN)TargetAddress - (UINTN)Name1; + // + // Partial content is in NV storage. + // + if (CompareMem ((UINT8 *)Name1, (UINT8 *)Name2, PartialNameSize) == 0) { + // + // Another partial content is in spare block. + // + if (CompareMem ((UINT8 *)(UINTN)SpareAddress, (UINT8 *)Name2 + PartialNameSize, NameSize - PartialNameSize) == 0) { + return TRUE; + } + } + + return FALSE; + } else if (((UINTN)Name2 < (UINTN)TargetAddress) && (((UINTN)Name2 + NameSize) > (UINTN)TargetAddress)) { + // + // Name2 is inconsecutive. + // + PartialNameSize = (UINTN)TargetAddress - (UINTN)Name2; + // + // Partial content is in NV storage. + // + if (CompareMem ((UINT8 *)Name2, (UINT8 *)Name1, PartialNameSize) == 0) { + // + // Another partial content is in spare block. + // + if (CompareMem ((UINT8 *)(UINTN)SpareAddress, (UINT8 *)Name1 + PartialNameSize, NameSize - PartialNameSize) == 0) { + return TRUE; + } + } + + return FALSE; + } + } + + // + // Both Name1 and Name2 are consecutive. + // + if (CompareMem ((UINT8 *)Name1, (UINT8 *)Name2, NameSize) == 0) { + return TRUE; + } + + return FALSE; +} + +/** + This function compares a variable with variable entries in database. + + @param StoreInfo Pointer to variable store info structure. + @param Variable Pointer to the variable in our database + @param VariableHeader Pointer to the Variable Header that has consecutive content. + @param VariableName Name of the variable to compare to 'Variable' + @param VendorGuid GUID of the variable to compare to 'Variable' + @param PtrTrack Variable Track Pointer structure that contains Variable Information. + + @retval EFI_SUCCESS Found match variable + @retval EFI_NOT_FOUND Variable not found + +**/ +EFI_STATUS +CompareWithValidVariable ( + IN VARIABLE_STORE_INFO *StoreInfo, + IN VARIABLE_HEADER *Variable, + IN VARIABLE_HEADER *VariableHeader, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + OUT VARIABLE_POINTER_TRACK *PtrTrack + ) +{ + VOID *Point; + EFI_GUID *TempVendorGuid; + + TempVendorGuid = GetVendorGuidPtr (VariableHeader, StoreInfo->AuthFlag); + + if (VariableName[0] == 0) { + PtrTrack->CurrPtr = Variable; + return EFI_SUCCESS; + } else { + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID a UINT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)VendorGuid)[0] == ((INT32 *)TempVendorGuid)[0]) && + (((INT32 *)VendorGuid)[1] == ((INT32 *)TempVendorGuid)[1]) && + (((INT32 *)VendorGuid)[2] == ((INT32 *)TempVendorGuid)[2]) && + (((INT32 *)VendorGuid)[3] == ((INT32 *)TempVendorGuid)[3]) + ) + { + ASSERT (NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag) != 0); + Point = (VOID *)GetVariableNamePtr (Variable, StoreInfo->AuthFlag); + if (CompareVariableName (StoreInfo, VariableName, Point, NameSizeOfVariable (VariableHeader, StoreInfo->AuthFlag))) { + PtrTrack->CurrPtr = Variable; + return EFI_SUCCESS; + } + } + } + + return EFI_NOT_FOUND; +} + +/** + Return the variable store header and the store info based on the Index. + + @param Type The type of the variable store. + @param StoreInfo Return the store info. + + @return Pointer to the variable store header. +**/ +VARIABLE_STORE_HEADER * +GetVariableStore ( + IN VARIABLE_STORE_TYPE Type, + OUT VARIABLE_STORE_INFO *StoreInfo + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + VARIABLE_STORE_HEADER *VariableStoreHeader; + EFI_PHYSICAL_ADDRESS NvStorageBase; + UINT32 NvStorageSize; + FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData; + UINT32 BackUpOffset; + + StoreInfo->IndexTable = NULL; + StoreInfo->FtwLastWriteData = NULL; + StoreInfo->AuthFlag = FALSE; + VariableStoreHeader = NULL; + switch (Type) { + case VariableStoreTypeHob: + // + // Unsupported + // + break; + + case VariableStoreTypeNv: + if (!PcdGetBool (PcdEmuVariableNvModeEnable)) { + // + // Emulated non-volatile variable mode is not enabled. + // + + NvStorageSize = PcdGet32 (PcdFlashNvStorageVariableSize); + NvStorageBase = (EFI_PHYSICAL_ADDRESS)(PcdGet64 (PcdFlashNvStorageVariableBase64) != 0 ? + PcdGet64 (PcdFlashNvStorageVariableBase64) : + PcdGet32 (PcdFlashNvStorageVariableBase) + ); + ASSERT (NvStorageBase != 0); + + // + // First let FvHeader point to NV storage base. + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)NvStorageBase; + + // + // Check the FTW last write data hob. + // + BackUpOffset = 0; + FaultTolerantWriteInitialize (); + if (mFtwLastWriteDataInitialized) { + FtwLastWriteData = &mFtwLastWriteData; + if (FtwLastWriteData->TargetAddress == NvStorageBase) { + // + // Let FvHeader point to spare block. + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FtwLastWriteData->SpareAddress; + DEBUG ((DEBUG_INFO, "PeiVariable: NV storage is backed up in spare block: 0x%x\n", (UINTN)FtwLastWriteData->SpareAddress)); + } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) && (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) { + StoreInfo->FtwLastWriteData = FtwLastWriteData; + // + // Flash NV storage from the offset is backed up in spare block. + // + BackUpOffset = (UINT32)(FtwLastWriteData->TargetAddress - NvStorageBase); + DEBUG ((DEBUG_INFO, "PeiVariable: High partial NV storage from offset: %x is backed up in spare block: 0x%x\n", BackUpOffset, (UINTN)FtwLastWriteData->SpareAddress)); + // + // At least one block data in flash NV storage is still valid, so still leave FvHeader point to NV storage base. + // + } + } + + // + // Check if the Firmware Volume is not corrupted + // + if ((FvHeader->Signature != EFI_FVH_SIGNATURE) || (!CompareGuid (&gEfiSystemNvDataFvGuid, &FvHeader->FileSystemGuid))) { + DEBUG ((DEBUG_ERROR, "Firmware Volume for Variable Store is corrupted\n")); + break; + } + + VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINT8 *)FvHeader + FvHeader->HeaderLength); + + StoreInfo->AuthFlag = (BOOLEAN)(CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)); + + StoreInfo->IndexTable = &mVariableIndexTable; + if (StoreInfo->IndexTable->StartPtr == NULL) { + // + // If it's the first time to access variable region in flash, create a guid hob to record + // VAR_ADDED type variable info. + // Note that as the resource of PEI phase is limited, only store the limited number of + // VAR_ADDED type variables to reduce access time. + // + StoreInfo->IndexTable->Length = 0; + StoreInfo->IndexTable->StartPtr = GetStartPointer (VariableStoreHeader); + StoreInfo->IndexTable->EndPtr = GetEndPointer (VariableStoreHeader); + StoreInfo->IndexTable->GoneThrough = 0; + } + } + + break; + + default: + ASSERT (FALSE); + break; + } + + StoreInfo->VariableStoreHeader = VariableStoreHeader; + return VariableStoreHeader; +} + +/** + Get variable header that has consecutive content. + + @param StoreInfo Pointer to variable store info structure. + @param Variable Pointer to the Variable Header. + @param VariableHeader Pointer to Pointer to the Variable Header that has consecutive content. + + @retval TRUE Variable header is valid. + @retval FALSE Variable header is not valid. + +**/ +BOOLEAN +GetVariableHeader ( + IN VARIABLE_STORE_INFO *StoreInfo, + IN VARIABLE_HEADER *Variable, + OUT VARIABLE_HEADER **VariableHeader + ) +{ + EFI_PHYSICAL_ADDRESS TargetAddress; + EFI_PHYSICAL_ADDRESS SpareAddress; + UINTN PartialHeaderSize; + + if (Variable == NULL) { + return FALSE; + } + + // + // First assume variable header pointed by Variable is consecutive. + // + *VariableHeader = Variable; + + if (StoreInfo->FtwLastWriteData != NULL) { + TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress; + SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress; + if (((UINTN)Variable > (UINTN)SpareAddress) && + (((UINTN)Variable - (UINTN)SpareAddress + (UINTN)TargetAddress) >= (UINTN)GetEndPointer (StoreInfo->VariableStoreHeader))) + { + // + // Reach the end of variable store. + // + return FALSE; + } + + if (((UINTN)Variable < (UINTN)TargetAddress) && (((UINTN)Variable + GetVariableHeaderSize (StoreInfo->AuthFlag)) > (UINTN)TargetAddress)) { + // + // Variable header pointed by Variable is inconsecutive, + // create a guid hob to combine the two partial variable header content together. + // + *VariableHeader = (VARIABLE_HEADER *)&mVariableHeaderFtw; + if (mVariableHeaderFtwMerged != TRUE) { + PartialHeaderSize = (UINTN)TargetAddress - (UINTN)Variable; + // + // Partial content is in NV storage. + // + CopyMem ((UINT8 *)*VariableHeader, (UINT8 *)Variable, PartialHeaderSize); + // + // Another partial content is in spare block. + // + CopyMem ((UINT8 *)*VariableHeader + PartialHeaderSize, (UINT8 *)(UINTN)SpareAddress, GetVariableHeaderSize (StoreInfo->AuthFlag) - PartialHeaderSize); + + mVariableHeaderFtwMerged = TRUE; + } + } + } else { + if (Variable >= GetEndPointer (StoreInfo->VariableStoreHeader)) { + // + // Reach the end of variable store. + // + return FALSE; + } + } + + return IsValidVariableHeader (*VariableHeader); +} + +/** + Get variable name or data to output buffer. + + @param StoreInfo Pointer to variable store info structure. + @param NameOrData Pointer to the variable name/data that may be inconsecutive. + @param Size Variable name/data size. + @param Buffer Pointer to output buffer to hold the variable name/data. + +**/ +VOID +GetVariableNameOrData ( + IN VARIABLE_STORE_INFO *StoreInfo, + IN UINT8 *NameOrData, + IN UINTN Size, + OUT UINT8 *Buffer + ) +{ + EFI_PHYSICAL_ADDRESS TargetAddress; + EFI_PHYSICAL_ADDRESS SpareAddress; + UINTN PartialSize; + + if (StoreInfo->FtwLastWriteData != NULL) { + TargetAddress = StoreInfo->FtwLastWriteData->TargetAddress; + SpareAddress = StoreInfo->FtwLastWriteData->SpareAddress; + if (((UINTN)NameOrData < (UINTN)TargetAddress) && (((UINTN)NameOrData + Size) > (UINTN)TargetAddress)) { + // + // Variable name/data is inconsecutive. + // + PartialSize = (UINTN)TargetAddress - (UINTN)NameOrData; + // + // Partial content is in NV storage. + // + CopyMem (Buffer, NameOrData, PartialSize); + // + // Another partial content is in spare block. + // + CopyMem (Buffer + PartialSize, (UINT8 *)(UINTN)SpareAddress, Size - PartialSize); + return; + } + } + + // + // Variable name/data is consecutive. + // + CopyMem (Buffer, NameOrData, Size); +} + +/** + Find the variable in the specified variable store. + + @param StoreInfo Pointer to the store info structure. + @param VariableName Name of the variable to be found + @param VendorGuid Vendor GUID to be found. + @param PtrTrack Variable Track Pointer structure that contains Variable Information. + + @retval EFI_SUCCESS Variable found successfully + @retval EFI_NOT_FOUND Variable not found + @retval EFI_INVALID_PARAMETER Invalid variable name + +**/ +EFI_STATUS +FindVariableEx ( + IN VARIABLE_STORE_INFO *StoreInfo, + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + OUT VARIABLE_POINTER_TRACK *PtrTrack + ) +{ + VARIABLE_HEADER *Variable; + VARIABLE_HEADER *LastVariable; + VARIABLE_HEADER *MaxIndex; + UINTN Index; + UINTN Offset; + BOOLEAN StopRecord; + VARIABLE_HEADER *InDeletedVariable; + VARIABLE_STORE_HEADER *VariableStoreHeader; + VARIABLE_INDEX_TABLE *IndexTable; + VARIABLE_HEADER *VariableHeader; + + VariableStoreHeader = StoreInfo->VariableStoreHeader; + + if (VariableStoreHeader == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) { + return EFI_UNSUPPORTED; + } + + if (~VariableStoreHeader->Size == 0) { + return EFI_NOT_FOUND; + } + + IndexTable = StoreInfo->IndexTable; + PtrTrack->StartPtr = GetStartPointer (VariableStoreHeader); + PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader); + + InDeletedVariable = NULL; + + // + // No Variable Address equals zero, so 0 as initial value is safe. + // + MaxIndex = NULL; + VariableHeader = NULL; + + if (IndexTable != NULL) { + // + // traverse the variable index table to look for varible. + // The IndexTable->Index[Index] records the distance of two neighbouring VAR_ADDED type variables. + // + for (Offset = 0, Index = 0; Index < IndexTable->Length; Index++) { + ASSERT (Index < sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0])); + Offset += IndexTable->Index[Index]; + MaxIndex = (VARIABLE_HEADER *)((UINT8 *)IndexTable->StartPtr + Offset); + GetVariableHeader (StoreInfo, MaxIndex, &VariableHeader); + if (CompareWithValidVariable (StoreInfo, MaxIndex, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) { + if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { + InDeletedVariable = PtrTrack->CurrPtr; + } else { + return EFI_SUCCESS; + } + } + } + + if (IndexTable->GoneThrough != 0) { + // + // If the table has all the existing variables indexed, return. + // + PtrTrack->CurrPtr = InDeletedVariable; + return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS; + } + } + + if (MaxIndex != NULL) { + // + // HOB exists but the variable cannot be found in HOB + // If not found in HOB, then let's start from the MaxIndex we've found. + // + Variable = GetNextVariablePtr (StoreInfo, MaxIndex, VariableHeader); + LastVariable = MaxIndex; + } else { + // + // Start Pointers for the variable. + // Actual Data Pointer where data can be written. + // + Variable = PtrTrack->StartPtr; + LastVariable = PtrTrack->StartPtr; + } + + // + // Find the variable by walk through variable store + // + StopRecord = FALSE; + while (GetVariableHeader (StoreInfo, Variable, &VariableHeader)) { + if ((VariableHeader->State == VAR_ADDED) || (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED))) { + // + // Record Variable in VariableIndex HOB + // + if ((IndexTable != NULL) && !StopRecord) { + Offset = (UINTN)Variable - (UINTN)LastVariable; + if ((Offset > 0x0FFFF) || (IndexTable->Length >= sizeof (IndexTable->Index) / sizeof (IndexTable->Index[0]))) { + // + // Stop to record if the distance of two neighbouring VAR_ADDED variable is larger than the allowable scope(UINT16), + // or the record buffer is full. + // + StopRecord = TRUE; + } else { + IndexTable->Index[IndexTable->Length++] = (UINT16)Offset; + LastVariable = Variable; + } + } + + if (CompareWithValidVariable (StoreInfo, Variable, VariableHeader, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) { + if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { + InDeletedVariable = PtrTrack->CurrPtr; + } else { + return EFI_SUCCESS; + } + } + } + + Variable = GetNextVariablePtr (StoreInfo, Variable, VariableHeader); + } + + // + // If gone through the VariableStore, that means we never find in Firmware any more. + // + if ((IndexTable != NULL) && !StopRecord) { + IndexTable->GoneThrough = 1; + } + + PtrTrack->CurrPtr = InDeletedVariable; + + return (PtrTrack->CurrPtr == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS; +} + +/** + Find the variable in HOB and Non-Volatile variable storages. + + @param VariableName Name of the variable to be found + @param VendorGuid Vendor GUID to be found. + @param PtrTrack Variable Track Pointer structure that contains Variable Information. + @param StoreInfo Return the store info. + + @retval EFI_SUCCESS Variable found successfully + @retval EFI_NOT_FOUND Variable not found + @retval EFI_INVALID_PARAMETER Invalid variable name +**/ +EFI_STATUS +FindVariable ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VendorGuid, + OUT VARIABLE_POINTER_TRACK *PtrTrack, + OUT VARIABLE_STORE_INFO *StoreInfo + ) +{ + EFI_STATUS Status; + VARIABLE_STORE_TYPE Type; + + if ((VariableName[0] != 0) && (VendorGuid == NULL)) { + return EFI_INVALID_PARAMETER; + } + + for (Type = (VARIABLE_STORE_TYPE)0; Type < VariableStoreTypeMax; Type++) { + GetVariableStore (Type, StoreInfo); + Status = FindVariableEx ( + StoreInfo, + VariableName, + VendorGuid, + PtrTrack + ); + if (!EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_NOT_FOUND; +} + +/** + This service retrieves a variable's value using its name and GUID. + + Read the specified variable from the UEFI variable store. If the Data + buffer is too small to hold the contents of the variable, the error + EFI_BUFFER_TOO_SMALL is returned and DataSize is set to the required buffer + size to obtain the data. + + @param VariableName A pointer to a null-terminated string that is the variable's name. + @param VariableGuid A pointer to an EFI_GUID that is the variable's GUID. The combination of + VariableGuid and VariableName must be unique. + @param Attributes If non-NULL, on return, points to the variable's attributes. + @param DataSize On entry, points to the size in bytes of the Data buffer. + On return, points to the size of the data returned in Data. + @param Data Points to the buffer which will hold the returned variable value. + May be NULL with a zero DataSize in order to determine the size of the buffer needed. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable was be found. + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the resulting data. + DataSize is updated with the size required for + the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid, DataSize or Data is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. + +**/ +EFI_STATUS +EFIAPI +BaseGetVariable ( + IN CONST CHAR16 *VariableName, + IN CONST EFI_GUID *VariableGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL + ) +{ + VARIABLE_POINTER_TRACK Variable; + UINTN VarDataSize; + EFI_STATUS Status; + VARIABLE_STORE_INFO StoreInfo; + VARIABLE_HEADER *VariableHeader; + + if ((VariableName == NULL) || (VariableGuid == NULL) || (DataSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (VariableName[0] == 0) { + return EFI_NOT_FOUND; + } + + VariableHeader = NULL; + + // + // Find existing variable + // + Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader); + + // + // Get data size + // + VarDataSize = DataSizeOfVariable (VariableHeader, StoreInfo.AuthFlag); + if (*DataSize >= VarDataSize) { + if (Data == NULL) { + return EFI_INVALID_PARAMETER; + } + + GetVariableNameOrData (&StoreInfo, GetVariableDataPtr (Variable.CurrPtr, VariableHeader, StoreInfo.AuthFlag), VarDataSize, Data); + Status = EFI_SUCCESS; + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + + if (Attributes != NULL) { + *Attributes = VariableHeader->Attributes; + } + + *DataSize = VarDataSize; + + return Status; +} + +/** + Return the next variable name and GUID. + + This function is called multiple times to retrieve the VariableName + and VariableGuid of all variables currently available in the system. + On each call, the previous results are passed into the interface, + and, on return, the interface returns the data for the next + interface. When the entire variable list has been returned, + EFI_NOT_FOUND is returned. + + @param VariableNameSize On entry, points to the size of the buffer pointed to by VariableName. + On return, the size of the variable name buffer. + @param VariableName On entry, a pointer to a null-terminated string that is the variable's name. + On return, points to the next variable's null-terminated name string. + @param VariableGuid On entry, a pointer to an EFI_GUID that is the variable's GUID. + On return, a pointer to the next variable's GUID. + + @retval EFI_SUCCESS The variable was read successfully. + @retval EFI_NOT_FOUND The variable could not be found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the resulting + data. VariableNameSize is updated with the size + required for the specified variable. + @retval EFI_INVALID_PARAMETER VariableName, VariableGuid or + VariableNameSize is NULL. + @retval EFI_DEVICE_ERROR The variable could not be retrieved because of a device error. + +**/ +EFI_STATUS +EFIAPI +BaseGetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VariableGuid + ) +{ + VARIABLE_STORE_TYPE Type; + VARIABLE_POINTER_TRACK Variable; + VARIABLE_POINTER_TRACK VariableInHob; + VARIABLE_POINTER_TRACK VariablePtrTrack; + UINTN VarNameSize; + EFI_STATUS Status; + VARIABLE_STORE_HEADER *VariableStoreHeader[VariableStoreTypeMax]; + VARIABLE_HEADER *VariableHeader; + VARIABLE_STORE_INFO StoreInfo; + VARIABLE_STORE_INFO StoreInfoForNv; + VARIABLE_STORE_INFO StoreInfoForHob; + + if ((VariableName == NULL) || (VariableGuid == NULL) || (VariableNameSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + VariableHeader = NULL; + + Status = FindVariable (VariableName, VariableGuid, &Variable, &StoreInfo); + if ((Variable.CurrPtr == NULL) || (Status != EFI_SUCCESS)) { + return Status; + } + + if (VariableName[0] != 0) { + // + // If variable name is not NULL, get next variable + // + GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader); + Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader); + } + + VariableStoreHeader[VariableStoreTypeHob] = GetVariableStore (VariableStoreTypeHob, &StoreInfoForHob); + VariableStoreHeader[VariableStoreTypeNv] = GetVariableStore (VariableStoreTypeNv, &StoreInfoForNv); + + while (TRUE) { + // + // Switch from HOB to Non-Volatile. + // + while (!GetVariableHeader (&StoreInfo, Variable.CurrPtr, &VariableHeader)) { + // + // Find current storage index + // + for (Type = (VARIABLE_STORE_TYPE)0; Type < VariableStoreTypeMax; Type++) { + if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) { + break; + } + } + + ASSERT (Type < VariableStoreTypeMax); + // + // Switch to next storage + // + for (Type++; Type < VariableStoreTypeMax; Type++) { + if (VariableStoreHeader[Type] != NULL) { + break; + } + } + + // + // Capture the case that + // 1. current storage is the last one, or + // 2. no further storage + // + if (Type == VariableStoreTypeMax) { + return EFI_NOT_FOUND; + } + + Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]); + Variable.EndPtr = GetEndPointer (VariableStoreHeader[Type]); + Variable.CurrPtr = Variable.StartPtr; + GetVariableStore (Type, &StoreInfo); + } + + if ((VariableHeader->State == VAR_ADDED) || (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED))) { + if (VariableHeader->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) { + // + // If it is a IN_DELETED_TRANSITION variable, + // and there is also a same ADDED one at the same time, + // don't return it. + // + Status = FindVariableEx ( + &StoreInfo, + GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag), + GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag), + &VariablePtrTrack + ); + if (!EFI_ERROR (Status) && (VariablePtrTrack.CurrPtr != Variable.CurrPtr)) { + Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader); + continue; + } + } + + // + // Don't return NV variable when HOB overrides it + // + if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) && + (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv])) + ) + { + Status = FindVariableEx ( + &StoreInfoForHob, + GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag), + GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag), + &VariableInHob + ); + if (!EFI_ERROR (Status)) { + Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader); + continue; + } + } + + VarNameSize = NameSizeOfVariable (VariableHeader, StoreInfo.AuthFlag); + ASSERT (VarNameSize != 0); + + if (VarNameSize <= *VariableNameSize) { + GetVariableNameOrData (&StoreInfo, (UINT8 *)GetVariableNamePtr (Variable.CurrPtr, StoreInfo.AuthFlag), VarNameSize, (UINT8 *)VariableName); + + CopyMem (VariableGuid, GetVendorGuidPtr (VariableHeader, StoreInfo.AuthFlag), sizeof (EFI_GUID)); + + Status = EFI_SUCCESS; + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + + *VariableNameSize = VarNameSize; + // + // Variable is found + // + return Status; + } else { + Variable.CurrPtr = GetNextVariablePtr (&StoreInfo, Variable.CurrPtr, VariableHeader); + } + } +} diff --git a/edk2-rockchip/Silicon/Rockchip/Library/BaseVariableLib/BaseVariableLib.inf b/edk2-rockchip/Silicon/Rockchip/Library/BaseVariableLib/BaseVariableLib.inf new file mode 100644 index 000000000..f27a0fc6d --- /dev/null +++ b/edk2-rockchip/Silicon/Rockchip/Library/BaseVariableLib/BaseVariableLib.inf @@ -0,0 +1,51 @@ +#/** @file +# +# Read-only non-volatile variable service library for early SEC phase. +# Based on FaultTolerantWritePei and VariablePei, without using any HOBs or PPIs. +# +# Copyright (c) 2024, Mario Bălănică +# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+# Copyright (c) Microsoft Corporation.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +#**/ + +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = BaseVariableLib + FILE_GUID = 0a9a1145-e20f-4d69-be68-eb13b3c3e4a3 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = BaseVariableLib + +[Sources] + BaseVariableLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Silicon/Rockchip/RockchipPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + PcdLib + +[Guids] + gEdkiiWorkingBlockSignatureGuid ## SOMETIMES_CONSUMES ## GUID + gEfiAuthenticatedVariableGuid ## SOMETIMES_CONSUMES ## GUID + gEfiVariableGuid ## SOMETIMES_CONSUMES ## GUID + gEfiSystemNvDataFvGuid ## SOMETIMES_CONSUMES ## GUID + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable ## SOMETIMES_CONSUMES diff --git a/edk2-rockchip/Silicon/Rockchip/Library/BaseVariableLib/Variable.h b/edk2-rockchip/Silicon/Rockchip/Library/BaseVariableLib/Variable.h new file mode 100644 index 000000000..0d725ba4e --- /dev/null +++ b/edk2-rockchip/Silicon/Rockchip/Library/BaseVariableLib/Variable.h @@ -0,0 +1,45 @@ +/** @file + * + * Copyright (c) 2024, Mario Bălănică + * Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#ifndef _BASE_VARIABLE_H_ +#define _BASE_VARIABLE_H_ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +typedef enum { + VariableStoreTypeHob, + VariableStoreTypeNv, + VariableStoreTypeMax +} VARIABLE_STORE_TYPE; + +typedef struct { + VARIABLE_STORE_HEADER *VariableStoreHeader; + VARIABLE_INDEX_TABLE *IndexTable; + // + // If it is not NULL, it means there may be an inconsecutive variable whose + // partial content is still in NV storage, but another partial content is backed up + // in spare block. + // + FAULT_TOLERANT_WRITE_LAST_WRITE_DATA *FtwLastWriteData; + BOOLEAN AuthFlag; +} VARIABLE_STORE_INFO; + +#endif // _BASE_VARIABLE_H_ diff --git a/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/DebugDw8250SerialPortLib.c b/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/DebugDw8250SerialPortLib.c new file mode 100644 index 000000000..f0563327f --- /dev/null +++ b/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/DebugDw8250SerialPortLib.c @@ -0,0 +1,40 @@ +/** @file + UART Serial Port library functions + + Copyright (c) 2006 - 2009, Intel Corporation + Copyright (c) 2015 - 2016, Hisilicon Limited. All rights reserved. + Copyright (c) 2015 - 2016, Linaro Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + + Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/ +**/ +#include +#include +#include +#include +#include + +#include "Dw8250SerialPortLib.h" + +/** + Initialize the serial device hardware. + + If no initialization is required, then return RETURN_SUCCESS. + If the serial device was successfuly initialized, then return RETURN_SUCCESS. + If the serial device could not be initialized, then return RETURN_DEVICE_ERROR. + + @retval RETURN_SUCCESS The serial device was initialized. + @retval RETURN_DEVICE_ERROR The serail device could not be initialized. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + // + // Assume already initialized. + // + return RETURN_SUCCESS; +} diff --git a/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/DebugDw8250SerialPortLib.inf b/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/DebugDw8250SerialPortLib.inf new file mode 100644 index 000000000..a9dc5fe59 --- /dev/null +++ b/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/DebugDw8250SerialPortLib.inf @@ -0,0 +1,35 @@ +#/** @file +# +# Copyright (c) 2011, ARM Ltd. All rights reserved.
+# Copyright (c) 2015-2016, Hisilicon Limited. All rights reserved.
+# Copyright (c) 2015-2016, Linaro Limited. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/ +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = Dw8250SerialPortLib + FILE_GUID = e9b88aa0-16a5-447b-9c05-a77521db1a9e + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib + +[Sources.common] + DebugDw8250SerialPortLib.c + Dw8250SerialPortLibCommon.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + Silicon/Hisilicon/HisiPkg.dec + +[LibraryClasses] + BaseLib + IoLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase + gHisiTokenSpaceGuid.PcdSerialPortSendDelay diff --git a/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.c b/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.c index 4dd44fbe3..ad093b3f8 100644 --- a/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.c +++ b/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.c @@ -16,7 +16,6 @@ #include "Dw8250SerialPortLib.h" - /** Initialize the serial device hardware. @@ -49,248 +48,3 @@ SerialPortInitialize ( return RETURN_SUCCESS; } - - -/** - Write data from buffer to serial device. - - Writes NumberOfBytes data bytes from Buffer to the serial device. - The number of bytes actually written to the serial device is returned. - If the return value is less than NumberOfBytes, then the write operation failed. - - If Buffer is NULL, then ASSERT(). - - If NumberOfBytes is zero, then return 0. - - @param Buffer Pointer to the data buffer to be written. - @param NumberOfBytes Number of bytes to written to the serial device. - - @retval 0 NumberOfBytes is 0. - @retval >0 The number of bytes written to the serial device. - If this value is less than NumberOfBytes, then the read operation failed. - -**/ -UINTN -EFIAPI -SerialPortWrite ( - IN UINT8 *Buffer, - IN UINTN NumberOfBytes -) -{ - UINTN Result; - - if (NULL == Buffer) { - return 0; - } - - Result = NumberOfBytes; - - while (NumberOfBytes--) { - - SerialPortWriteChar(*Buffer); - Buffer++; - } - - return Result; -} - - -/** - Reads data from a serial device into a buffer. - - @param Buffer Pointer to the data buffer to store the data read from the serial device. - @param NumberOfBytes Number of bytes to read from the serial device. - - @retval 0 NumberOfBytes is 0. - @retval >0 The number of bytes read from the serial device. - If this value is less than NumberOfBytes, then the read operation failed. - -**/ -UINTN -EFIAPI -SerialPortRead ( - OUT UINT8 *Buffer, - IN UINTN NumberOfBytes -) -{ - UINTN Result; - - if (NULL == Buffer) { - return 0; - } - - Result = 0; - - while (NumberOfBytes--) { - // - // Wait for the serail port to be ready. - // - *Buffer=SerialPortReadChar(); - Buffer++ ; - Result++; - } - - return Result; -} - -/** - Polls a serial device to see if there is any data waiting to be read. - - Polls aserial device to see if there is any data waiting to be read. - If there is data waiting to be read from the serial device, then TRUE is returned. - If there is no data waiting to be read from the serial device, then FALSE is returned. - - @retval TRUE Data is waiting to be read from the serial device. - @retval FALSE There is no data waiting to be read from the serial device. - -**/ -BOOLEAN -EFIAPI -SerialPortPoll ( - VOID - ) -{ - - return (BOOLEAN) ((MmioRead8 (UART_LSR_REG) & UART_LSR_DR) == UART_LSR_DR); - -} - - -VOID SerialPortWriteChar(UINT8 scShowChar) -{ - UINT32 ulLoop = 0; - - while(ulLoop < (UINT32)UART_SEND_DELAY) - { - - if ((MmioRead8 (UART_USR_REG) & 0x02) == 0x02) - { - break; - } - - ulLoop++; - } - MmioWrite8 (UART_THR_REG, (UINT8)scShowChar); - - ulLoop = 0; - while(ulLoop < (UINT32)UART_SEND_DELAY) - { - if ((MmioRead8 (UART_USR_REG) & 0x04) == 0x04) - { - break; - } - ulLoop++; - } - - return; -} - - -UINT8 SerialPortReadChar(VOID) -{ - UINT8 recvchar = 0; - - while(1) - { - if ((MmioRead8 (UART_LSR_REG) & UART_LSR_DR) == UART_LSR_DR) - { - break; - } - } - - recvchar = MmioRead8 (UART_RBR_REG); - - return recvchar; -} - -/** - Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, - data bits, and stop bits on a serial device. - - @param BaudRate The requested baud rate. A BaudRate value of 0 will use the - device's default interface speed. - On output, the value actually set. - @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the - serial interface. A ReceiveFifoDepth value of 0 will use - the device's default FIFO depth. - On output, the value actually set. - @param Timeout The requested time out for a single character in microseconds. - This timeout applies to both the transmit and receive side of the - interface. A Timeout value of 0 will use the device's default time - out value. - On output, the value actually set. - @param Parity The type of parity to use on this serial device. A Parity value of - DefaultParity will use the device's default parity value. - On output, the value actually set. - @param DataBits The number of data bits to use on the serial device. A DataBits - vaule of 0 will use the device's default data bit setting. - On output, the value actually set. - @param StopBits The number of stop bits to use on this serial device. A StopBits - value of DefaultStopBits will use the device's default number of - stop bits. - On output, the value actually set. - - @retval RETURN_SUCCESS The new attributes were set on the serial device. - @retval RETURN_UNSUPPORTED The serial device does not support this operation. - @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. - @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. - -**/ -RETURN_STATUS -EFIAPI -SerialPortSetAttributes ( - IN OUT UINT64 *BaudRate, - IN OUT UINT32 *ReceiveFifoDepth, - IN OUT UINT32 *Timeout, - IN OUT EFI_PARITY_TYPE *Parity, - IN OUT UINT8 *DataBits, - IN OUT EFI_STOP_BITS_TYPE *StopBits - ) -{ - return RETURN_UNSUPPORTED; -} - -/** - Set the serial device control bits. - - @param Control Control bits which are to be set on the serial device. - - @retval EFI_SUCCESS The new control bits were set on the serial device. - @retval EFI_UNSUPPORTED The serial device does not support this operation. - @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. - -**/ -RETURN_STATUS -EFIAPI -SerialPortSetControl ( - IN UINT32 Control - ) -{ - return EFI_UNSUPPORTED; -} - -/** - Get the serial device control bits. - - @param Control Control signals read from the serial device. - - @retval EFI_SUCCESS The control bits were read from the serial device. - @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. - -**/ -RETURN_STATUS -EFIAPI -SerialPortGetControl ( - OUT UINT32 *Control - ) -{ - - if (SerialPortPoll ()) { - // If a character is pending don't set EFI_SERIAL_INPUT_BUFFER_EMPTY - *Control = EFI_SERIAL_OUTPUT_BUFFER_EMPTY; - } else { - *Control = EFI_SERIAL_INPUT_BUFFER_EMPTY | EFI_SERIAL_OUTPUT_BUFFER_EMPTY; - } - return EFI_SUCCESS; -} - diff --git a/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf b/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf index f9295c88e..752f46896 100644 --- a/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf +++ b/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf @@ -11,21 +11,19 @@ [Defines] INF_VERSION = 0x00010005 BASE_NAME = Dw8250SerialPortLib - FILE_GUID = 78337705-D2A8-4EA7-9C18-27FC4A8A2C6E + FILE_GUID = e7016ad2-40dd-406f-81ef-535da603c8e1 MODULE_TYPE = BASE VERSION_STRING = 1.0 LIBRARY_CLASS = SerialPortLib - [Sources.common] Dw8250SerialPortLib.c - + Dw8250SerialPortLibCommon.c [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec ArmPlatformPkg/ArmPlatformPkg.dec - Silicon/Hisilicon/HisiPkg.dec [LibraryClasses] diff --git a/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLibCommon.c b/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLibCommon.c new file mode 100644 index 000000000..a65497bde --- /dev/null +++ b/edk2-rockchip/Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLibCommon.c @@ -0,0 +1,260 @@ +/** @file + UART Serial Port library functions + + Copyright (c) 2006 - 2009, Intel Corporation + Copyright (c) 2015 - 2016, Hisilicon Limited. All rights reserved. + Copyright (c) 2015 - 2016, Linaro Limited. All rights reserved. + SPDX-License-Identifier: BSD-2-Clause-Patent + + Based on the files under ArmPlatformPkg/Library/PL011SerialPortLib/ +**/ +#include +#include +#include +#include +#include + +#include "Dw8250SerialPortLib.h" + +/** + Write data from buffer to serial device. + + Writes NumberOfBytes data bytes from Buffer to the serial device. + The number of bytes actually written to the serial device is returned. + If the return value is less than NumberOfBytes, then the write operation failed. + + If Buffer is NULL, then ASSERT(). + + If NumberOfBytes is zero, then return 0. + + @param Buffer Pointer to the data buffer to be written. + @param NumberOfBytes Number of bytes to written to the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes written to the serial device. + If this value is less than NumberOfBytes, then the read operation failed. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINTN Result; + + if (NULL == Buffer) { + return 0; + } + + Result = NumberOfBytes; + + while (NumberOfBytes--) { + + SerialPortWriteChar(*Buffer); + Buffer++; + } + + return Result; +} + + +/** + Reads data from a serial device into a buffer. + + @param Buffer Pointer to the data buffer to store the data read from the serial device. + @param NumberOfBytes Number of bytes to read from the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes read from the serial device. + If this value is less than NumberOfBytes, then the read operation failed. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINTN Result; + + if (NULL == Buffer) { + return 0; + } + + Result = 0; + + while (NumberOfBytes--) { + // + // Wait for the serail port to be ready. + // + *Buffer=SerialPortReadChar(); + Buffer++ ; + Result++; + } + + return Result; +} + +/** + Polls a serial device to see if there is any data waiting to be read. + + Polls aserial device to see if there is any data waiting to be read. + If there is data waiting to be read from the serial device, then TRUE is returned. + If there is no data waiting to be read from the serial device, then FALSE is returned. + + @retval TRUE Data is waiting to be read from the serial device. + @retval FALSE There is no data waiting to be read from the serial device. + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + + return (BOOLEAN) ((MmioRead8 (UART_LSR_REG) & UART_LSR_DR) == UART_LSR_DR); + +} + + +VOID SerialPortWriteChar(UINT8 scShowChar) +{ + UINT32 ulLoop = 0; + + while(ulLoop < (UINT32)UART_SEND_DELAY) + { + + if ((MmioRead8 (UART_USR_REG) & 0x02) == 0x02) + { + break; + } + + ulLoop++; + } + MmioWrite8 (UART_THR_REG, (UINT8)scShowChar); + + ulLoop = 0; + while(ulLoop < (UINT32)UART_SEND_DELAY) + { + if ((MmioRead8 (UART_USR_REG) & 0x04) == 0x04) + { + break; + } + ulLoop++; + } + + return; +} + + +UINT8 SerialPortReadChar(VOID) +{ + UINT8 recvchar = 0; + + while(1) + { + if ((MmioRead8 (UART_LSR_REG) & UART_LSR_DR) == UART_LSR_DR) + { + break; + } + } + + recvchar = MmioRead8 (UART_RBR_REG); + + return recvchar; +} + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data bits, and stop bits on a serial device. + + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the + device's default interface speed. + On output, the value actually set. + @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the + serial interface. A ReceiveFifoDepth value of 0 will use + the device's default FIFO depth. + On output, the value actually set. + @param Timeout The requested time out for a single character in microseconds. + This timeout applies to both the transmit and receive side of the + interface. A Timeout value of 0 will use the device's default time + out value. + On output, the value actually set. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + On output, the value actually set. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + On output, the value actually set. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + On output, the value actually set. + + @retval RETURN_SUCCESS The new attributes were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetAttributes ( + IN OUT UINT64 *BaudRate, + IN OUT UINT32 *ReceiveFifoDepth, + IN OUT UINT32 *Timeout, + IN OUT EFI_PARITY_TYPE *Parity, + IN OUT UINT8 *DataBits, + IN OUT EFI_STOP_BITS_TYPE *StopBits + ) +{ + return RETURN_UNSUPPORTED; +} + +/** + Set the serial device control bits. + + @param Control Control bits which are to be set on the serial device. + + @retval EFI_SUCCESS The new control bits were set on the serial device. + @retval EFI_UNSUPPORTED The serial device does not support this operation. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetControl ( + IN UINT32 Control + ) +{ + return EFI_UNSUPPORTED; +} + +/** + Get the serial device control bits. + + @param Control Control signals read from the serial device. + + @retval EFI_SUCCESS The control bits were read from the serial device. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortGetControl ( + OUT UINT32 *Control + ) +{ + + if (SerialPortPoll ()) { + // If a character is pending don't set EFI_SERIAL_INPUT_BUFFER_EMPTY + *Control = EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } else { + *Control = EFI_SERIAL_INPUT_BUFFER_EMPTY | EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } + return EFI_SUCCESS; +} diff --git a/edk2-rockchip/Silicon/Rockchip/Library/PlatformBootManagerLib/PlatformBm.c b/edk2-rockchip/Silicon/Rockchip/Library/PlatformBootManagerLib/PlatformBm.c index 04f4f4605..675ca7f67 100644 --- a/edk2-rockchip/Silicon/Rockchip/Library/PlatformBootManagerLib/PlatformBm.c +++ b/edk2-rockchip/Silicon/Rockchip/Library/PlatformBootManagerLib/PlatformBm.c @@ -65,10 +65,10 @@ STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = { { { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) }, 0, // Reserved - FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate - FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits - FixedPcdGet8 (PcdUartDefaultParity), // Parity - FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits + 0, // BaudRate + 0, // DataBits + 0, // Parity + 0, // StopBits }, // @@ -926,6 +926,11 @@ PlatformBootManagerBeforeConsole ( "PcdUartDefaultStopBits must be set to an actual value, not 'default'" ); + mSerialConsole.Uart.BaudRate = PcdGet64 (PcdUartDefaultBaudRate); + mSerialConsole.Uart.DataBits = PcdGet8 (PcdUartDefaultDataBits); + mSerialConsole.Uart.Parity = PcdGet8 (PcdUartDefaultParity); + mSerialConsole.Uart.StopBits = PcdGet8 (PcdUartDefaultStopBits); + CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid); EfiBootManagerUpdateConsoleVariable ( diff --git a/edk2-rockchip/Silicon/Rockchip/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/edk2-rockchip/Silicon/Rockchip/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf index 3973e3d61..deab399db 100644 --- a/edk2-rockchip/Silicon/Rockchip/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf +++ b/edk2-rockchip/Silicon/Rockchip/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -59,14 +59,14 @@ [FixedPcd] gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType [Pcd] gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits gEfiMdeModulePkgTokenSpaceGuid.PcdBootDiscoveryPolicy gRockchipTokenSpaceGuid.PcdDwcSdhciBaseAddress gRockchipTokenSpaceGuid.PcdRkSdmmcBaseAddress diff --git a/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/DebugSerialPort.c b/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/DebugSerialPort.c new file mode 100644 index 000000000..19855d6e0 --- /dev/null +++ b/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/DebugSerialPort.c @@ -0,0 +1,50 @@ +/** @file + * + * Copyright (c) 2023, Mario Bălănică + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#include +#include +#include + +#include "RK3588DxeFormSetGuid.h" +#include "DebugSerialPort.h" + +VOID +EFIAPI +ApplyDebugSerialPortVariables ( + VOID + ) +{ + /* nothing to do here */ +} + +VOID +EFIAPI +SetupDebugSerialPortVariables ( + VOID + ) +{ + UINTN Size; + UINT64 Var64; + EFI_STATUS Status; + + Size = sizeof (UINT64); + + Status = gRT->GetVariable (L"DebugSerialPortBaudRate", + &gRK3588DxeFormSetGuid, + NULL, &Size, &Var64); + if (EFI_ERROR (Status)) { + Var64 = DEBUG_SERIAL_PORT_BAUD_RATE_DEFAULT; + Status = gRT->SetVariable ( + L"DebugSerialPortBaudRate", + &gRK3588DxeFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + Size, + &Var64); + ASSERT_EFI_ERROR (Status); + } +} diff --git a/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/DebugSerialPort.h b/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/DebugSerialPort.h new file mode 100644 index 000000000..0ffeaeb5b --- /dev/null +++ b/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/DebugSerialPort.h @@ -0,0 +1,33 @@ +/** @file + * + * Copyright (c) 2023, Mario Bălănică + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + * + **/ + +#ifndef __RK3588DXE_DEBUG_SERIAL_PORT_H__ +#define __RK3588DXE_DEBUG_SERIAL_PORT_H__ + +#define DEBUG_SERIAL_PORT_BAUD_RATE_MIN 0 +#define DEBUG_SERIAL_PORT_BAUD_RATE_MAX 1500000 +#define DEBUG_SERIAL_PORT_BAUD_RATE_DEFAULT 1500000 + +// +// Don't declare these in the VFR file. +// +#ifndef VFR_FILE_INCLUDE +VOID +EFIAPI +ApplyDebugSerialPortVariables ( + VOID + ); + +VOID +EFIAPI +SetupDebugSerialPortVariables ( + VOID + ); +#endif // VFR_FILE_INCLUDE + +#endif // __RK3588DXE_DEBUG_SERIAL_PORT_H__ diff --git a/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588Dxe.c b/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588Dxe.c index d795c5954..a99da589d 100644 --- a/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588Dxe.c +++ b/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588Dxe.c @@ -37,6 +37,7 @@ #include "ConfigTable.h" #include "FanControl.h" #include "UsbDpPhy.h" +#include "DebugSerialPort.h" extern UINT8 RK3588DxeHiiBin[]; extern UINT8 RK3588DxeStrings[]; @@ -162,6 +163,7 @@ SetupVariables ( SetupConfigTableVariables (); SetupCoolingFanVariables (); SetupUsbDpPhyVariables (); + SetupDebugSerialPortVariables (); return EFI_SUCCESS; } @@ -207,6 +209,7 @@ ApplyVariables ( ApplyConfigTableVariables (); ApplyCoolingFanVariables (); ApplyUsbDpPhyVariables (); + ApplyDebugSerialPortVariables (); InstallConfigAppliedProtocol (); diff --git a/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588Dxe.inf b/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588Dxe.inf index 16f26c731..46b7a6413 100644 --- a/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588Dxe.inf +++ b/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588Dxe.inf @@ -15,14 +15,15 @@ [Sources.common] RK3588Dxe.c + RK3588DxeHii.uni + RK3588DxeHii.vfr CpuPerformance.c ComboPhy.c PciExpress30.c ConfigTable.c FanControl.c UsbDpPhy.c - RK3588DxeHii.uni - RK3588DxeHii.vfr + DebugSerialPort.c [Packages] ArmPkg/ArmPkg.dec diff --git a/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588DxeHii.uni b/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588DxeHii.uni index 0754c7633..54cb4cc49 100644 --- a/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588DxeHii.uni +++ b/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588DxeHii.uni @@ -154,4 +154,13 @@ #string STR_COOLING_FAN_STATE_HELP #language en-US "Enable or disable the on-board fan output." #string STR_COOLING_FAN_SPEED_PROMPT #language en-US "Fan Speed (%)" -#string STR_COOLING_FAN_SPEED_HELP #language en-US "PWM duty cycle of on-board fan output." \ No newline at end of file +#string STR_COOLING_FAN_SPEED_HELP #language en-US "PWM duty cycle of on-board fan output." + +/* + * Debug Serial Port configuration + */ +#string STR_DEBUG_SERIAL_PORT_FORM_TITLE #language en-US "Debug Serial Port" +#string STR_DEBUG_SERIAL_PORT_FORM_HELP #language en-US "Configure the debug (UART) serial port." +#string STR_DEBUG_SERIAL_PORT_SUBTITLE #language en-US "Note: These settings only take effect in UEFI and might be overridden by the OS. Earlier boot messages will be printed at the default settings." + +#string STR_DEBUG_SERIAL_PORT_BAUD_RATE_PROMPT #language en-US "Baud Rate" diff --git a/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588DxeHii.vfr b/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588DxeHii.vfr index 01eda9c22..848c16722 100644 --- a/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588DxeHii.vfr +++ b/edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588DxeHii.vfr @@ -16,6 +16,7 @@ #define VFR_FILE_INCLUDE #include "CpuPerformance.h" #include "FanControl.h" +#include "DebugSerialPort.h" // // EFI Variable attributes @@ -146,6 +147,11 @@ formset name = CoolingFanSpeed, guid = RK3588DXE_FORMSET_GUID; + efivarstore DEBUG_SERIAL_PORT_BAUD_RATE_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = DebugSerialPortBaudRate, + guid = RK3588DXE_FORMSET_GUID; + form formid = 1, title = STRING_TOKEN(STR_FORM_SET_TITLE); subtitle text = STRING_TOKEN(STR_FORM_SET_TITLE_SUBTITLE); @@ -182,6 +188,9 @@ formset help = STRING_TOKEN(STR_COOLING_FAN_FORM_HELP); #endif + goto 0x1006, + prompt = STRING_TOKEN(STR_DEBUG_SERIAL_PORT_FORM_TITLE), + help = STRING_TOKEN(STR_DEBUG_SERIAL_PORT_FORM_HELP); endform; form formid = 0x1000, @@ -524,7 +533,23 @@ formset endnumeric; endif; endform; - #endif + form formid = 0x1006, + title = STRING_TOKEN(STR_DEBUG_SERIAL_PORT_FORM_TITLE); + + numeric varid = DebugSerialPortBaudRate.Value, + prompt = STRING_TOKEN(STR_DEBUG_SERIAL_PORT_BAUD_RATE_PROMPT), + help = STRING_TOKEN(STR_NULL_STRING), + flags = DISPLAY_UINT_DEC | NUMERIC_SIZE_8 | INTERACTIVE | RESET_REQUIRED, + minimum = DEBUG_SERIAL_PORT_BAUD_RATE_MIN, + maximum = DEBUG_SERIAL_PORT_BAUD_RATE_MAX, + step = 0, + default = DEBUG_SERIAL_PORT_BAUD_RATE_DEFAULT, + endnumeric; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + subtitle text = STRING_TOKEN(STR_DEBUG_SERIAL_PORT_SUBTITLE); + endform; + endformset; diff --git a/edk2-rockchip/Silicon/Rockchip/RK3588/Include/VarStoreData.h b/edk2-rockchip/Silicon/Rockchip/RK3588/Include/VarStoreData.h index b560ba415..3c74b1d16 100644 --- a/edk2-rockchip/Silicon/Rockchip/RK3588/Include/VarStoreData.h +++ b/edk2-rockchip/Silicon/Rockchip/RK3588/Include/VarStoreData.h @@ -78,4 +78,8 @@ typedef struct { UINT32 State; } USBDP_PHY_USB3_STATE_VARSTORE_DATA; +typedef struct { + UINT64 Value; +} DEBUG_SERIAL_PORT_BAUD_RATE_VARSTORE_DATA; + #endif // __VARSTORE_DATA_H__ diff --git a/edk2-rockchip/Silicon/Rockchip/RK3588/Library/PlatformLib/PlatformLib.inf b/edk2-rockchip/Silicon/Rockchip/RK3588/Library/PlatformLib/PlatformLib.inf index 4885b3c9f..1fc2752ea 100644 --- a/edk2-rockchip/Silicon/Rockchip/RK3588/Library/PlatformLib/PlatformLib.inf +++ b/edk2-rockchip/Silicon/Rockchip/RK3588/Library/PlatformLib/PlatformLib.inf @@ -28,12 +28,14 @@ [LibraryClasses] ArmLib + BaseVariableLib FdtLib IoLib MemoryAllocationLib PcdLib PrintLib SdramLib + SerialPortLib [Sources.common] Rk3588.c @@ -62,5 +64,11 @@ gArmTokenSpaceGuid.PcdSystemMemoryBase gArmTokenSpaceGuid.PcdSystemMemorySize +[PatchPcd] + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + [Ppis] gArmMpCoreInfoPpiGuid + +[Guids] + gRK3588DxeFormSetGuid diff --git a/edk2-rockchip/Silicon/Rockchip/RK3588/Library/PlatformLib/Rk3588.c b/edk2-rockchip/Silicon/Rockchip/RK3588/Library/PlatformLib/Rk3588.c index 595c9ec06..d99140986 100644 --- a/edk2-rockchip/Silicon/Rockchip/RK3588/Library/PlatformLib/Rk3588.c +++ b/edk2-rockchip/Silicon/Rockchip/RK3588/Library/PlatformLib/Rk3588.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include @@ -40,6 +42,27 @@ ArmPlatformInitialize ( IN UINTN MpId ) { + EFI_STATUS Status; + UINTN Size; + UINT64 BaudRate; + + Size = sizeof (UINT64); + Status = BaseGetVariable ( + L"DebugSerialPortBaudRate", + &gRK3588DxeFormSetGuid, + NULL, + &Size, + &BaudRate + ); + if (EFI_ERROR (Status) || BaudRate == 0) { + return RETURN_SUCCESS; + } + + DEBUG ((DEBUG_INFO, "%a: Setting baud rate to %lu\n", __func__, BaudRate)); + + PatchPcdSet64 (PcdUartDefaultBaudRate, BaudRate); + SerialPortInitialize (); + return RETURN_SUCCESS; } diff --git a/edk2-rockchip/Silicon/Rockchip/RK3588/RK3588Base.dsc.inc b/edk2-rockchip/Silicon/Rockchip/RK3588/RK3588Base.dsc.inc index 94992be12..167f477fe 100644 --- a/edk2-rockchip/Silicon/Rockchip/RK3588/RK3588Base.dsc.inc +++ b/edk2-rockchip/Silicon/Rockchip/RK3588/RK3588Base.dsc.inc @@ -100,8 +100,8 @@ # ACPI helpers AcpiLib|EmbeddedPkg/Library/AcpiLib/AcpiLib.inf - # UART library - SerialPortLib|Silicon/Hisilicon/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf + # Debug UART library + SerialPortLib|Silicon/Rockchip/Library/Dw8250SerialPortLib/DebugDw8250SerialPortLib.inf # SoC and memory descriptors ArmPlatformLib|Silicon/Rockchip/RK3588/Library/PlatformLib/PlatformLib.inf @@ -166,7 +166,6 @@ # UART2 - Serial Terminal DEFINE SERIAL_BASE = 0xFEB50000 # UART2 gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|$(SERIAL_BASE) - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|1500000 gHisiTokenSpaceGuid.PcdSerialPortSendDelay|500000 gHisiTokenSpaceGuid.PcdUartClkInHz|24000000 @@ -259,6 +258,9 @@ # EHCI disabled by default since it crashes Windows. gRK3588TokenSpaceGuid.PcdAcpiUsb2StateDefault|$(ACPI_USB2_STATE_DISABLED) +[PcdsPatchableInModule] + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|1500000 + [PcdsDynamicDefault.common] # # Display @@ -322,6 +324,15 @@ # ################################################################################ [Components.common] + # + # PEI Phase modules + # + ArmPlatformPkg/PrePi/PeiUniCore.inf { + + # Full UART library + SerialPortLib|Silicon/Rockchip/Library/Dw8250SerialPortLib/Dw8250SerialPortLib.inf + } + # General platform manager Silicon/Rockchip/RK3588/Drivers/RK3588Dxe/RK3588Dxe.inf diff --git a/edk2-rockchip/Silicon/Rockchip/Rockchip.dsc.inc b/edk2-rockchip/Silicon/Rockchip/Rockchip.dsc.inc index e877bf0e6..291449c9a 100644 --- a/edk2-rockchip/Silicon/Rockchip/Rockchip.dsc.inc +++ b/edk2-rockchip/Silicon/Rockchip/Rockchip.dsc.inc @@ -232,6 +232,8 @@ PWMLib|Silicon/Rockchip/Library/PWMLib/PWMLib.inf RockchipDisplayLib|Silicon/Rockchip/Library/DisplayLib/RockchipDisplayLib.inf + BaseVariableLib|Silicon/Rockchip/Library/BaseVariableLib/BaseVariableLib.inf + [LibraryClasses.common.SEC] ArmGicArchLib|ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf