| /** @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 ((DEBUG_ERROR, "HstiData == NULL\n")); | |
| return FALSE; | |
| } | |
| if (HstiSize < sizeof (ADAPTER_INFO_PLATFORM_SECURITY)) { | |
| DEBUG ((DEBUG_ERROR, "HstiSize < sizeof(ADAPTER_INFO_PLATFORM_SECURITY)\n")); | |
| return FALSE; | |
| } | |
| if (((HstiSize - sizeof (ADAPTER_INFO_PLATFORM_SECURITY)) / 3) < Hsti->SecurityFeaturesSize) { | |
| DEBUG ((DEBUG_ERROR, "((HstiSize - sizeof(ADAPTER_INFO_PLATFORM_SECURITY)) / 3) < SecurityFeaturesSize\n")); | |
| return FALSE; | |
| } | |
| // | |
| // Check Version | |
| // | |
| if (Hsti->Version != PLATFORM_SECURITY_VERSION_VNEXTCS) { | |
| DEBUG ((DEBUG_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 ((DEBUG_ERROR, "Role < PLATFORM_SECURITY_ROLE_PLATFORM_REFERENCE ||\n")); | |
| DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_ERROR, "ErrorStringSize == 0\n")); | |
| return FALSE; | |
| } | |
| if ((ErrorStringSize & BIT0) != 0) { | |
| DEBUG ((DEBUG_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 ((DEBUG_ERROR, "ErrorString has no NUL CHAR\n")); | |
| return FALSE; | |
| } | |
| if (ErrorStringLength == (ErrorStringSize/2)) { | |
| DEBUG ((DEBUG_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 | |
| ); | |
| } |