diff options
Diffstat (limited to '')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeHstiLib/HstiDxe.c | 606 |
1 files changed, 606 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeHstiLib/HstiDxe.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeHstiLib/HstiDxe.c new file mode 100644 index 00000000..be132e9d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeHstiLib/HstiDxe.c @@ -0,0 +1,606 @@ +/** @file + + Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "HstiDxe.h" + +/** + Find HSTI table in AIP protocol, and return the data. + This API will return the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param HstiData HSTI data. This buffer is allocated by callee, and it + is the responsibility of the caller to free it after + using it. + @param HstiSize HSTI size + + @return Aip The AIP protocol having this HSTI. + @return NULL There is not HSTI table with the Role and ImplementationID published in system. +**/ +VOID * +InternalHstiFindAip ( + IN UINT32 Role, + IN CHAR16 *ImplementationID OPTIONAL, + OUT VOID **HstiData OPTIONAL, + OUT UINTN *HstiSize OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; + UINTN NoHandles; + EFI_HANDLE *Handles; + UINTN Index; + EFI_GUID *InfoTypesBuffer; + UINTN InfoTypesBufferCount; + UINTN InfoTypesIndex; + EFI_ADAPTER_INFORMATION_PROTOCOL *AipCandidate; + VOID *InformationBlock; + UINTN InformationBlockSize; + ADAPTER_INFO_PLATFORM_SECURITY *Hsti; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiAdapterInformationProtocolGuid, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + Hsti = NULL; + Aip = NULL; + InformationBlock = NULL; + InformationBlockSize = 0; + for (Index = 0; Index < NoHandles; Index++) { + Status = gBS->HandleProtocol ( + Handles[Index], + &gEfiAdapterInformationProtocolGuid, + (VOID **)&Aip + ); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Check AIP + // + Status = Aip->GetSupportedTypes ( + Aip, + &InfoTypesBuffer, + &InfoTypesBufferCount + ); + if (EFI_ERROR (Status) || (InfoTypesBuffer == NULL) || (InfoTypesBufferCount == 0)) { + continue; + } + + AipCandidate = NULL; + for (InfoTypesIndex = 0; InfoTypesIndex < InfoTypesBufferCount; InfoTypesIndex++) { + if (CompareGuid (&InfoTypesBuffer[InfoTypesIndex], &gAdapterInfoPlatformSecurityGuid)) { + AipCandidate = Aip; + break; + } + } + FreePool (InfoTypesBuffer); + + if (AipCandidate == NULL) { + continue; + } + + // + // Check HSTI Role + // + Aip = AipCandidate; + Status = Aip->GetInformation ( + Aip, + &gAdapterInfoPlatformSecurityGuid, + &InformationBlock, + &InformationBlockSize + ); + if (EFI_ERROR (Status)) { + continue; + } + + Hsti = InformationBlock; + if ((Hsti->Role == Role) && + ((ImplementationID == NULL) || (StrCmp (ImplementationID, Hsti->ImplementationID) == 0))) { + break; + } else { + Hsti = NULL; + FreePool (InformationBlock); + continue; + } + } + FreePool (Handles); + + if (Hsti == NULL) { + return NULL; + } + + if (HstiData != NULL) { + *HstiData = InformationBlock; + } + if (HstiSize != NULL) { + *HstiSize = InformationBlockSize; + } + return Aip; +} + +/** + Return if input HSTI data follows HSTI specification. + + @param HstiData HSTI data + @param HstiSize HSTI size + + @retval TRUE HSTI data follows HSTI specification. + @retval FALSE HSTI data does not follow HSTI specification. +**/ +BOOLEAN +InternalHstiIsValidTable ( + IN VOID *HstiData, + IN UINTN HstiSize + ) +{ + ADAPTER_INFO_PLATFORM_SECURITY *Hsti; + UINTN Index; + CHAR16 *ErrorString; + CHAR16 ErrorChar; + UINTN ErrorStringSize; + UINTN ErrorStringLength; + + Hsti = HstiData; + + // + // basic check for header + // + if (HstiData == NULL) { + DEBUG ((EFI_D_ERROR, "HstiData == NULL\n")); + return FALSE; + } + if (HstiSize < sizeof(ADAPTER_INFO_PLATFORM_SECURITY)) { + DEBUG ((EFI_D_ERROR, "HstiSize < sizeof(ADAPTER_INFO_PLATFORM_SECURITY)\n")); + return FALSE; + } + if (((HstiSize - sizeof(ADAPTER_INFO_PLATFORM_SECURITY)) / 3) < Hsti->SecurityFeaturesSize) { + DEBUG ((EFI_D_ERROR, "((HstiSize - sizeof(ADAPTER_INFO_PLATFORM_SECURITY)) / 3) < SecurityFeaturesSize\n")); + return FALSE; + } + + // + // Check Version + // + if (Hsti->Version != PLATFORM_SECURITY_VERSION_VNEXTCS) { + DEBUG ((EFI_D_ERROR, "Version != PLATFORM_SECURITY_VERSION_VNEXTCS\n")); + return FALSE; + } + + // + // Check Role + // + if ((Hsti->Role < PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE) || + (Hsti->Role > PLATFORM_SECURITY_ROLE_IMPLEMENTOR_ODM)) { + DEBUG ((EFI_D_ERROR, "Role < PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE ||\n")); + DEBUG ((EFI_D_ERROR, "Role > PLATFORM_SECURITY_ROLE_IMPLEMENTOR_ODM\n")); + return FALSE; + } + + // + // Check ImplementationID + // + for (Index = 0; Index < sizeof(Hsti->ImplementationID)/sizeof(Hsti->ImplementationID[0]); Index++) { + if (Hsti->ImplementationID[Index] == 0) { + break; + } + } + if (Index == sizeof(Hsti->ImplementationID)/sizeof(Hsti->ImplementationID[0])) { + DEBUG ((EFI_D_ERROR, "ImplementationID has no NUL CHAR\n")); + return FALSE; + } + + ErrorStringSize = HstiSize - sizeof(ADAPTER_INFO_PLATFORM_SECURITY) - Hsti->SecurityFeaturesSize * 3; + ErrorString = (CHAR16 *)((UINTN)Hsti + sizeof(ADAPTER_INFO_PLATFORM_SECURITY) + Hsti->SecurityFeaturesSize * 3); + + // + // basic check for ErrorString + // + if (ErrorStringSize == 0) { + DEBUG ((EFI_D_ERROR, "ErrorStringSize == 0\n")); + return FALSE; + } + if ((ErrorStringSize & BIT0) != 0) { + DEBUG ((EFI_D_ERROR, "(ErrorStringSize & BIT0) != 0\n")); + return FALSE; + } + + // + // ErrorString might not be CHAR16 aligned. + // + CopyMem (&ErrorChar, ErrorString, sizeof(ErrorChar)); + for (ErrorStringLength = 0; (ErrorChar != 0) && (ErrorStringLength < (ErrorStringSize/2)); ErrorStringLength++) { + ErrorString++; + CopyMem (&ErrorChar, ErrorString, sizeof(ErrorChar)); + } + + // + // check the length of ErrorString + // + if (ErrorChar != 0) { + DEBUG ((EFI_D_ERROR, "ErrorString has no NUL CHAR\n")); + return FALSE; + } + if (ErrorStringLength == (ErrorStringSize/2)) { + DEBUG ((EFI_D_ERROR, "ErrorString Length incorrect\n")); + return FALSE; + } + + return TRUE; +} + +/** + Publish HSTI table in AIP protocol. + + One system should have only one PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE. + + If the Role is NOT PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE, + SecurityFeaturesRequired field will be ignored. + + @param Hsti HSTI data + @param HstiSize HSTI size + + @retval EFI_SUCCESS The HSTI data is published in AIP protocol. + @retval EFI_ALREADY_STARTED There is already HSTI table with Role and ImplementationID published in system. + @retval EFI_VOLUME_CORRUPTED The input HSTI data does not follow HSTI specification. + @retval EFI_OUT_OF_RESOURCES There is not enough system resource to publish HSTI data in AIP protocol. +**/ +EFI_STATUS +EFIAPI +HstiLibSetTable ( + IN VOID *Hsti, + IN UINTN HstiSize + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + HSTI_AIP_PRIVATE_DATA *HstiAip; + EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; + UINT32 Role; + CHAR16 *ImplementationID; + UINT32 SecurityFeaturesSize; + UINT8 *SecurityFeaturesRequired; + + if (!InternalHstiIsValidTable (Hsti, HstiSize)) { + return EFI_VOLUME_CORRUPTED; + } + + Role = ((ADAPTER_INFO_PLATFORM_SECURITY *)Hsti)->Role; + ImplementationID = ((ADAPTER_INFO_PLATFORM_SECURITY *)Hsti)->ImplementationID; + Aip = InternalHstiFindAip (Role, ImplementationID, NULL, NULL); + if (Aip != NULL) { + return EFI_ALREADY_STARTED; + } + + HstiAip = AllocateZeroPool (sizeof(HSTI_AIP_PRIVATE_DATA)); + if (HstiAip == NULL) { + return EFI_OUT_OF_RESOURCES; + } + HstiAip->Hsti = AllocateCopyPool (HstiSize, Hsti); + if (HstiAip->Hsti == NULL) { + FreePool (HstiAip); + return EFI_OUT_OF_RESOURCES; + } + if (Role != PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE) { + SecurityFeaturesRequired = (UINT8 *)HstiAip->Hsti + sizeof(ADAPTER_INFO_PLATFORM_SECURITY); + SecurityFeaturesSize = ((ADAPTER_INFO_PLATFORM_SECURITY *)Hsti)->SecurityFeaturesSize; + ZeroMem (SecurityFeaturesRequired, SecurityFeaturesSize); + } + + HstiAip->Signature = HSTI_AIP_PRIVATE_SIGNATURE; + CopyMem (&HstiAip->Aip, &mAdapterInformationProtocol, sizeof(EFI_ADAPTER_INFORMATION_PROTOCOL)); + HstiAip->HstiSize = HstiSize; + HstiAip->HstiMaxSize = HstiSize; + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiAdapterInformationProtocolGuid, + &HstiAip->Aip, + NULL + ); + if (EFI_ERROR (Status)) { + FreePool (HstiAip->Hsti); + FreePool (HstiAip); + } + + return Status; +} + +/** + Search HSTI table in AIP protocol, and return the data. + This API will return the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param Hsti HSTI data. This buffer is allocated by callee, and it + is the responsibility of the caller to free it after + using it. + @param HstiSize HSTI size + + @retval EFI_SUCCESS The HSTI data in AIP protocol is returned. + @retval EFI_NOT_FOUND There is not HSTI table with the Role and ImplementationID published in system. +**/ +EFI_STATUS +EFIAPI +HstiLibGetTable ( + IN UINT32 Role, + IN CHAR16 *ImplementationID OPTIONAL, + OUT VOID **Hsti, + OUT UINTN *HstiSize + ) +{ + EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; + + Aip = InternalHstiFindAip (Role, ImplementationID, Hsti, HstiSize); + if (Aip == NULL) { + return EFI_NOT_FOUND; + } + return EFI_SUCCESS; +} + +/** + Record FeaturesVerified in published HSTI table. + This API will update the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param ByteIndex Byte index of FeaturesVerified of HSTI data. + @param BitMask Bit mask of FeaturesVerified of HSTI data. + @param Set TRUE means to set the FeaturesVerified bit. + FALSE means to clear the FeaturesVerified bit. + + @retval EFI_SUCCESS The FeaturesVerified of HSTI data updated in AIP protocol. + @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system. + @retval EFI_UNSUPPORTED The ByteIndex is invalid. +**/ +EFI_STATUS +InternalHstiRecordFeaturesVerified ( + IN UINT32 Role, + IN CHAR16 *ImplementationID, OPTIONAL + IN UINT32 ByteIndex, + IN UINT8 Bit, + IN BOOLEAN Set + ) +{ + EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; + ADAPTER_INFO_PLATFORM_SECURITY *Hsti; + UINTN HstiSize; + UINT8 *SecurityFeaturesVerified; + EFI_STATUS Status; + + Aip = InternalHstiFindAip (Role, ImplementationID, (VOID **)&Hsti, &HstiSize); + if (Aip == NULL) { + return EFI_NOT_STARTED; + } + + if (ByteIndex >= Hsti->SecurityFeaturesSize) { + return EFI_UNSUPPORTED; + } + + SecurityFeaturesVerified = (UINT8 *)((UINTN)Hsti + sizeof(ADAPTER_INFO_PLATFORM_SECURITY) + Hsti->SecurityFeaturesSize * 2); + + if (Set) { + SecurityFeaturesVerified[ByteIndex] = (UINT8)(SecurityFeaturesVerified[ByteIndex] | (Bit)); + } else { + SecurityFeaturesVerified[ByteIndex] = (UINT8)(SecurityFeaturesVerified[ByteIndex] & (~Bit)); + } + + Status = Aip->SetInformation ( + Aip, + &gAdapterInfoPlatformSecurityGuid, + Hsti, + HstiSize + ); + FreePool (Hsti); + return Status; +} + +/** + Set FeaturesVerified in published HSTI table. + This API will update the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param ByteIndex Byte index of FeaturesVerified of HSTI data. + @param BitMask Bit mask of FeaturesVerified of HSTI data. + + @retval EFI_SUCCESS The FeaturesVerified of HSTI data updated in AIP protocol. + @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system. + @retval EFI_UNSUPPORTED The ByteIndex is invalid. +**/ +EFI_STATUS +EFIAPI +HstiLibSetFeaturesVerified ( + IN UINT32 Role, + IN CHAR16 *ImplementationID, OPTIONAL + IN UINT32 ByteIndex, + IN UINT8 BitMask + ) +{ + return InternalHstiRecordFeaturesVerified ( + Role, + ImplementationID, + ByteIndex, + BitMask, + TRUE + ); +} + +/** + Clear FeaturesVerified in published HSTI table. + This API will update the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param ByteIndex Byte index of FeaturesVerified of HSTI data. + @param BitMask Bit mask of FeaturesVerified of HSTI data. + + @retval EFI_SUCCESS The FeaturesVerified of HSTI data updated in AIP protocol. + @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system. + @retval EFI_UNSUPPORTED The ByteIndex is invalid. +**/ +EFI_STATUS +EFIAPI +HstiLibClearFeaturesVerified ( + IN UINT32 Role, + IN CHAR16 *ImplementationID, OPTIONAL + IN UINT32 ByteIndex, + IN UINT8 BitMask + ) +{ + return InternalHstiRecordFeaturesVerified ( + Role, + ImplementationID, + ByteIndex, + BitMask, + FALSE + ); +} + +/** + Record ErrorString in published HSTI table. + This API will update the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param ErrorString ErrorString of HSTI data. + @param Append TRUE means to append the ErrorString to HSTI table. + FALSE means to set the ErrorString in HSTI table. + + @retval EFI_SUCCESS The ErrorString of HSTI data is published in AIP protocol. + @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system. + @retval EFI_OUT_OF_RESOURCES There is not enough system resource to update ErrorString. +**/ +EFI_STATUS +InternalHstiRecordErrorString ( + IN UINT32 Role, + IN CHAR16 *ImplementationID, OPTIONAL + IN CHAR16 *ErrorString, + IN BOOLEAN Append + ) +{ + EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; + ADAPTER_INFO_PLATFORM_SECURITY *Hsti; + UINTN HstiSize; + UINTN StringSize; + VOID *NewHsti; + UINTN NewHstiSize; + UINTN Offset; + EFI_STATUS Status; + + Aip = InternalHstiFindAip (Role, ImplementationID, (VOID **)&Hsti, &HstiSize); + if (Aip == NULL) { + return EFI_NOT_STARTED; + } + + if (Append) { + Offset = HstiSize - sizeof(CHAR16); + } else { + Offset = sizeof(ADAPTER_INFO_PLATFORM_SECURITY) + Hsti->SecurityFeaturesSize * 3; + } + StringSize = StrSize (ErrorString); + + NewHstiSize = Offset + StringSize; + NewHsti = AllocatePool (NewHstiSize); + if (NewHsti == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (NewHsti, Hsti, Offset); + CopyMem ((UINT8 *)NewHsti + Offset, ErrorString, StringSize); + + Status = Aip->SetInformation ( + Aip, + &gAdapterInfoPlatformSecurityGuid, + NewHsti, + NewHstiSize + ); + FreePool (Hsti); + FreePool (NewHsti); + return Status; +} + +/** + Append ErrorString in published HSTI table. + This API will update the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param ErrorString ErrorString of HSTI data. + + @retval EFI_SUCCESS The ErrorString of HSTI data is updated in AIP protocol. + @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system. + @retval EFI_OUT_OF_RESOURCES There is not enough system resource to update ErrorString. +**/ +EFI_STATUS +EFIAPI +HstiLibAppendErrorString ( + IN UINT32 Role, + IN CHAR16 *ImplementationID, OPTIONAL + IN CHAR16 *ErrorString + ) +{ + return InternalHstiRecordErrorString ( + Role, + ImplementationID, + ErrorString, + TRUE + ); +} + +/** + Set a new ErrorString in published HSTI table. + This API will update the HSTI table with indicated Role and ImplementationID, + NULL ImplementationID means to find the first HSTI table with indicated Role. + + @param Role Role of HSTI data. + @param ImplementationID ImplementationID of HSTI data. + NULL means find the first one match Role. + @param ErrorString ErrorString of HSTI data. + + @retval EFI_SUCCESS The ErrorString of HSTI data is updated in AIP protocol. + @retval EFI_NOT_STARTED There is not HSTI table with the Role and ImplementationID published in system. + @retval EFI_OUT_OF_RESOURCES There is not enough system resource to update ErrorString. +**/ +EFI_STATUS +EFIAPI +HstiLibSetErrorString ( + IN UINT32 Role, + IN CHAR16 *ImplementationID, OPTIONAL + IN CHAR16 *ErrorString + ) +{ + return InternalHstiRecordErrorString ( + Role, + ImplementationID, + ErrorString, + FALSE + ); +} |