/** @file Copyright (c) 2017, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include #include #include UINTN mSmmTestPointDatabaseSize; VOID *mSmmTestPointDatabase; VOID PublishPeiTestPoint ( VOID ) { EFI_PEI_HOB_POINTERS Hob; ADAPTER_INFO_PLATFORM_TEST_POINT *TestPoint; UINTN TestPointSize; DEBUG ((DEBUG_INFO, "PublishPeiTestPoint\n")); Hob.Raw = GetHobList (); while (TRUE) { Hob.Raw = GetNextGuidHob (&gAdapterInfoPlatformTestPointGuid, Hob.Raw); if (Hob.Raw == NULL) { return ; } TestPoint = GET_GUID_HOB_DATA (Hob); TestPointSize = GET_GUID_HOB_DATA_SIZE (Hob); TestPointLibSetTable (TestPoint, TestPointSize); Hob.Raw = GET_NEXT_HOB (Hob); if (Hob.Raw == NULL) { return ; } } } VOID TestPointStubForPei ( VOID ) { PublishPeiTestPoint (); } VOID GetTestPointDataSmm ( VOID ) { EFI_STATUS Status; UINTN CommSize; UINT8 *CommBuffer; EFI_SMM_COMMUNICATE_HEADER *CommHeader; SMI_HANDLER_TEST_POINT_PARAMETER_GET_INFO *CommGetInfo; SMI_HANDLER_TEST_POINT_PARAMETER_GET_DATA_BY_OFFSET *CommGetData; EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; UINTN MinimalSizeNeeded; EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable; UINT32 Index; EFI_MEMORY_DESCRIPTOR *Entry; VOID *Buffer; UINTN Size; UINTN Offset; Status = gBS->LocateProtocol(&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **)&SmmCommunication); if (EFI_ERROR(Status)) { DEBUG ((DEBUG_INFO, "SmiHandlerTestPoint: Locate SmmCommunication protocol - %r\n", Status)); return ; } MinimalSizeNeeded = EFI_PAGE_SIZE; Status = EfiGetSystemConfigurationTable( &gEdkiiPiSmmCommunicationRegionTableGuid, (VOID **)&PiSmmCommunicationRegionTable ); if (EFI_ERROR(Status)) { DEBUG ((DEBUG_INFO, "SmiHandlerTestPoint: Get PiSmmCommunicationRegionTable - %r\n", Status)); return ; } ASSERT(PiSmmCommunicationRegionTable != NULL); Entry = (EFI_MEMORY_DESCRIPTOR *)(PiSmmCommunicationRegionTable + 1); Size = 0; for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) { if (Entry->Type == EfiConventionalMemory) { Size = EFI_PAGES_TO_SIZE((UINTN)Entry->NumberOfPages); if (Size >= MinimalSizeNeeded) { break; } } Entry = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)Entry + PiSmmCommunicationRegionTable->DescriptorSize); } ASSERT(Index < PiSmmCommunicationRegionTable->NumberOfEntries); CommBuffer = (UINT8 *)(UINTN)Entry->PhysicalStart; // // Get Size // CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; CopyMem(&CommHeader->HeaderGuid, &gAdapterInfoPlatformTestPointGuid, sizeof(gAdapterInfoPlatformTestPointGuid)); CommHeader->MessageLength = sizeof(SMI_HANDLER_TEST_POINT_PARAMETER_GET_INFO); CommGetInfo = (SMI_HANDLER_TEST_POINT_PARAMETER_GET_INFO *)&CommBuffer[OFFSET_OF(EFI_SMM_COMMUNICATE_HEADER, Data)]; CommGetInfo->Header.Command = SMI_HANDLER_TEST_POINT_COMMAND_GET_INFO; CommGetInfo->Header.DataLength = sizeof(*CommGetInfo); CommGetInfo->Header.ReturnStatus = (UINT64)-1; CommGetInfo->DataSize = 0; CommSize = OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + (UINTN)CommHeader->MessageLength; Status = SmmCommunication->Communicate(SmmCommunication, CommBuffer, &CommSize); if (EFI_ERROR(Status)) { DEBUG ((DEBUG_INFO, "SmiHandlerTestPoint: SmmCommunication - %r\n", Status)); return ; } if (CommGetInfo->Header.ReturnStatus != 0) { DEBUG ((DEBUG_INFO, "SmiHandlerTestPoint: GetInfo - 0x%0x\n", CommGetInfo->Header.ReturnStatus)); return ; } mSmmTestPointDatabaseSize = (UINTN)CommGetInfo->DataSize; // // Get Data // mSmmTestPointDatabase = AllocateZeroPool(mSmmTestPointDatabaseSize); if (mSmmTestPointDatabase == NULL) { Status = EFI_OUT_OF_RESOURCES; DEBUG ((DEBUG_INFO, "SmiHandlerTestPoint: AllocateZeroPool (0x%x) for dump buffer - %r\n", mSmmTestPointDatabaseSize, Status)); return ; } CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; CopyMem(&CommHeader->HeaderGuid, &gAdapterInfoPlatformTestPointGuid, sizeof(gAdapterInfoPlatformTestPointGuid)); CommHeader->MessageLength = sizeof(SMI_HANDLER_TEST_POINT_PARAMETER_GET_DATA_BY_OFFSET); CommGetData = (SMI_HANDLER_TEST_POINT_PARAMETER_GET_DATA_BY_OFFSET *)&CommBuffer[OFFSET_OF(EFI_SMM_COMMUNICATE_HEADER, Data)]; CommGetData->Header.Command = SMI_HANDLER_TEST_POINT_COMMAND_GET_DATA_BY_OFFSET; CommGetData->Header.DataLength = sizeof(*CommGetData); CommGetData->Header.ReturnStatus = (UINT64)-1; CommSize = OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + (UINTN)CommHeader->MessageLength; Buffer = (UINT8 *)CommHeader + CommSize; Size -= CommSize; CommGetData->DataBuffer = (PHYSICAL_ADDRESS)(UINTN)Buffer; CommGetData->DataOffset = 0; while (CommGetData->DataOffset < mSmmTestPointDatabaseSize) { Offset = (UINTN)CommGetData->DataOffset; if (Size <= (mSmmTestPointDatabaseSize - CommGetData->DataOffset)) { CommGetData->DataSize = (UINT64)Size; } else { CommGetData->DataSize = (UINT64)(mSmmTestPointDatabaseSize - CommGetData->DataOffset); } Status = SmmCommunication->Communicate(SmmCommunication, CommBuffer, &CommSize); ASSERT_EFI_ERROR(Status); if (CommGetData->Header.ReturnStatus != 0) { FreePool(mSmmTestPointDatabase); mSmmTestPointDatabase = NULL; DEBUG ((DEBUG_INFO, "SmiHandlerTestPoint: GetData - 0x%x\n", CommGetData->Header.ReturnStatus)); return ; } CopyMem((UINT8 *)mSmmTestPointDatabase + Offset, (VOID *)(UINTN)CommGetData->DataBuffer, (UINTN)CommGetData->DataSize); } DEBUG ((DEBUG_INFO, "SmmTestPointDatabaseSize - 0x%x\n", mSmmTestPointDatabaseSize)); return ; } UINTN GetTestPointInfoSize ( IN ADAPTER_INFO_PLATFORM_TEST_POINT *TestPoint, IN UINTN MaxSize ) { CHAR16 *ErrorString; UINTN ErrorStringLength; UINTN ErrorStringMaxSize; CHAR16 ErrorChar; ErrorString = (CHAR16 *)((UINTN)TestPoint + sizeof(ADAPTER_INFO_PLATFORM_TEST_POINT) + TEST_POINT_FEATURES_ITEM_NUMBER * TestPoint->FeaturesSize); ErrorStringMaxSize = MaxSize - sizeof(ADAPTER_INFO_PLATFORM_TEST_POINT) - TestPoint->FeaturesSize * TEST_POINT_FEATURES_ITEM_NUMBER; // // ErrorString might not be CHAR16 aligned. // CopyMem (&ErrorChar, ErrorString, sizeof(ErrorChar)); for (ErrorStringLength = 0; (ErrorChar != 0) && (ErrorStringLength < (ErrorStringMaxSize/2)); ErrorStringLength++) { ErrorString++; CopyMem (&ErrorChar, ErrorString, sizeof(ErrorChar)); } return sizeof(ADAPTER_INFO_PLATFORM_TEST_POINT) + TEST_POINT_FEATURES_ITEM_NUMBER * TestPoint->FeaturesSize + (ErrorStringLength + 1) * sizeof(CHAR16); } VOID PublishSmmTestPoint ( VOID ) { ADAPTER_INFO_PLATFORM_TEST_POINT *TestPoint; UINTN TestPointSize; DEBUG ((DEBUG_INFO, "PublishSmmTestPoint\n")); GetTestPointDataSmm (); if (mSmmTestPointDatabaseSize == 0) { return ; } if (mSmmTestPointDatabase == NULL) { return ; } TestPoint = mSmmTestPointDatabase; while ((UINTN)TestPoint < (UINTN)mSmmTestPointDatabase + mSmmTestPointDatabaseSize) { TestPointSize = GetTestPointInfoSize (TestPoint, (UINTN)mSmmTestPointDatabase + mSmmTestPointDatabaseSize - (UINTN)TestPoint); TestPointLibSetTable (TestPoint, TestPointSize); TestPoint = (ADAPTER_INFO_PLATFORM_TEST_POINT *)((UINTN)TestPoint + TestPointSize); } } /** Notification function of EVT_GROUP_READY_TO_BOOT event group. It runs after most ReadyToBoot event signaled. This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group. When the Boot Manager is about to load and execute a boot option, it reclaims variable storage if free size is below the threshold. @param[in] Event Event whose notification function is being invoked. @param[in] Context Pointer to the notification function's context. **/ VOID EFIAPI OnReadyToBootLater ( IN EFI_EVENT Event, IN VOID *Context ) { gBS->CloseEvent (Event); PublishSmmTestPoint (); } /** Notification function of EVT_GROUP_READY_TO_BOOT event group. This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group. When the Boot Manager is about to load and execute a boot option, it reclaims variable storage if free size is below the threshold. @param[in] Event Event whose notification function is being invoked. @param[in] Context Pointer to the notification function's context. **/ VOID EFIAPI OnReadyToBoot ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_STATUS Status; EFI_EVENT ReadyToBootLaterEvent; gBS->CloseEvent (Event); Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, OnReadyToBootLater, NULL, &ReadyToBootLaterEvent ); ASSERT_EFI_ERROR (Status); gBS->SignalEvent (ReadyToBootLaterEvent); } VOID TestPointStubForSmm ( VOID ) { EFI_STATUS Status; EFI_EVENT ReadyToBootEvent; Status = EfiCreateEventReadyToBootEx ( TPL_CALLBACK, OnReadyToBoot, NULL, &ReadyToBootEvent ); ASSERT_EFI_ERROR (Status); } /** Initialize TestPointStub. @param[in] ImageHandle Image handle of this driver. @param[in] SystemTable Global system service table. @retval EFI_SUCCESS Initialization complete. @exception EFI_UNSUPPORTED The chipset is unsupported by this driver. @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver. @retval EFI_DEVICE_ERROR Device error, driver exits abnormally. **/ EFI_STATUS EFIAPI TestPointStubDxeEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { TestPointStubForPei (); TestPointStubForSmm (); return EFI_SUCCESS; }