/** @file UbaConfigDatabaseDxe Driver. @copyright Copyright 2013 - 2021 Intel Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "CfgDbDxe.h" #include // For Hob #include #include #include #include #include #include #include /** Internal function for getting the platform record node in the database. @param This uba Protocol instance. @param SkuNode The pointer to pointer of Platform record node. @retval EFI_NOT_FOUND Platform record not found. @retval EFI_SUCCESS Platform found. **/ EFI_STATUS InternalGetSkuNode ( IN UBA_CONFIG_DATABASE_PROTOCOL *This, OUT UBA_BOARD_NODE **SkuNode ) { UBA_DXE_PRIVATE_DATA *UbaDxePrivate; UbaDxePrivate = NULL; UbaDxePrivate = PRIVATE_DATA_FROM_PROTOCOL (This); *SkuNode = UbaDxePrivate->CurrentSku; return EFI_SUCCESS; } /** Internal function for init the platform record to database. Create the connections between UBA_BOARD_NODE and UBA_DXE_PRIVATE_DATA @param This UBA Protocol instance. @param BoardId The platform type. @param BoardGuid The platform GUID. @param BoardName The platform user friendly name. @param SkuNode The pointer to pointer of Platform record node. @retval EFI_ALREADY_STARTED Platform record already exist. @retval EFI_OUT_OF_RESOURCES No enough resource. @retval EFI_SUCCESS Operation success. **/ EFI_STATUS InternalInitSkuDxe ( IN UBA_CONFIG_DATABASE_PROTOCOL *This, IN UINT32 BoardId, IN EFI_GUID *BoardGuid, OPTIONAL IN CHAR8 *BoardName, OPTIONAL OUT UBA_BOARD_NODE **SkuNode OPTIONAL ) { UBA_DXE_PRIVATE_DATA *UbaDxePrivate; UBA_BOARD_NODE *NewSkuNode; UbaDxePrivate = NULL; NewSkuNode = NULL; UbaDxePrivate = PRIVATE_DATA_FROM_PROTOCOL (This); NewSkuNode = AllocateZeroPool (sizeof (UBA_BOARD_NODE)); if (NewSkuNode == NULL) { return EFI_OUT_OF_RESOURCES; } NewSkuNode->Signature = UBA_BOARD_SIGNATURE; NewSkuNode->Version = UBA_BOARD_VERSION; NewSkuNode->BoardId = BoardId; if (BoardName != NULL) { AsciiStrnCpyS (NewSkuNode->BoardName, AsciiStrSize (BoardName) / sizeof (CHAR8), BoardName, sizeof (NewSkuNode->BoardName) - 1); } if (BoardGuid != NULL) { CopyMem (&NewSkuNode->BoardGuid, BoardGuid, sizeof (EFI_GUID)); } // Initialize the list head for Datalink. InitializeListHead (&NewSkuNode->DataLinkHead); if (SkuNode != NULL) { // Output the point of sku node. *SkuNode = NewSkuNode; // Pass the point to CurrentSku in UbaDxePrivate. UbaDxePrivate->CurrentSku = NewSkuNode; } return EFI_SUCCESS; } /** Internal function for adding new configuration data record to database. @param This uba Protocol instance. @param ResId The resource ID. @param Data Data pointer. @param DataSize Data size. @retval EFI_INVALID_PARAMETER Parameter invalid. @retval EFI_OUT_OF_RESOURCES No enough resource. @retval EFI_SUCCESS Operation success. **/ EFI_STATUS InternalAddNewConfigData ( IN UBA_CONFIG_DATABASE_PROTOCOL *This, IN EFI_GUID *ResId, IN VOID *Data, IN UINTN DataSize ) { EFI_STATUS Status; EFI_HANDLE Handle; UBA_DXE_PRIVATE_DATA *UbaDxePrivate; UBA_CONFIG_NODE *NewDataNode; UBA_BOARD_NODE *SkuNode; UbaDxePrivate = NULL; NewDataNode = NULL; SkuNode = NULL; if ((ResId == NULL) || (Data == NULL) || (DataSize <= 0)) { return EFI_INVALID_PARAMETER; } UbaDxePrivate = PRIVATE_DATA_FROM_PROTOCOL (This); Status = InternalGetSkuNode (This, &SkuNode); if (EFI_ERROR (Status)) { return Status; } NewDataNode = AllocateZeroPool (sizeof (UBA_CONFIG_NODE)); if (NewDataNode == NULL) { return EFI_OUT_OF_RESOURCES; } NewDataNode->Signature = UBA_BOARD_SIGNATURE; NewDataNode->Version = UBA_BOARD_VERSION; NewDataNode->Handle = (EFI_HANDLE) (UINTN) UbaDxePrivate->HandleCount; NewDataNode->Data = AllocateCopyPool (DataSize, Data); NewDataNode->Size = (UINT32) DataSize; CopyMem (&NewDataNode->ResId, ResId, sizeof (EFI_GUID)); InsertTailList (&SkuNode->DataLinkHead, &NewDataNode->DataLink); SkuNode->DataCount ++; UbaDxePrivate->ConfigDataCount ++; UbaDxePrivate->HandleCount ++; // // This Protocol just install for Protocol notify // The Protocol instance UbaCfgDbProtocol should not used // Handle = NULL; Status = gBS->InstallProtocolInterface ( &Handle, &NewDataNode->ResId, EFI_NATIVE_INTERFACE, &UbaDxePrivate->UbaCfgDbProtocol ); ASSERT_EFI_ERROR (Status); if (Status != EFI_SUCCESS) { return Status; } return EFI_SUCCESS; } /** Internal function for Getting configuration data from database. @param This uba Protocol instance. @param SkuNode The platform node record. @param ResId The resource ID. @param Data Data pointer. @param DataSize Data size pointer. @retval EFI_INVALID_PARAMETER Parameter invalid. @retval EFI_NOT_FOUND Resource not found. @retval EFI_BUFFER_TOO_SMALL The buffer is too small to copy the data. @retval EFI_SUCCESS Operation success. **/ EFI_STATUS InternalGetConfigData ( IN UBA_CONFIG_DATABASE_PROTOCOL *This, IN UBA_BOARD_NODE *SkuNode, IN EFI_GUID *ResId, OUT VOID *Data, OPTIONAL OUT UINTN *DataSize OPTIONAL ) { LIST_ENTRY *ListHead; LIST_ENTRY *Link; UBA_CONFIG_NODE *DataNode; ListHead = NULL; Link = NULL; DataNode = NULL; if ((SkuNode == NULL) || (ResId == NULL)) { return EFI_INVALID_PARAMETER; } ListHead = &SkuNode->DataLinkHead; if (IsListEmpty (ListHead)) { return EFI_NOT_FOUND; } for (Link = GetFirstNode (ListHead); !IsNull (ListHead, Link); Link = GetNextNode (ListHead, Link)) { DataNode = CONFIG_NODE_INSTANCE_FROM_THIS (Link); ASSERT (DataNode != NULL); if (DataNode == NULL) { return EFI_UNSUPPORTED; } if (CompareGuid (ResId, &DataNode->ResId)) { if (DataSize != NULL) { if (*DataSize < DataNode->Size) { *DataSize = DataNode->Size; return EFI_BUFFER_TOO_SMALL; } *DataSize = DataNode->Size; if (Data != NULL) { CopyMem (Data, DataNode->Data, DataNode->Size); } } return EFI_SUCCESS; } } return EFI_NOT_FOUND; } /** Get platform's GUID and user friendly name by BoardId. This is used when you need a BoardGuid to Add/Get platform data Core will create a new platform for you if the BoardId is not recorded in database, and assgin a unique GUID for this platform. @param This uba Protocol instance. @param BoardId The platform type, same define as Platform.h. @param BoardGuid The GUID for this platform. @param BoardName The user friendly name for this platform. @retval EFI_ALREADY_STARTED Create new for an exist platform. @retval EFI_OUT_OF_RESOURCES Resource not enough. @retval EFI_NOT_FOUND Platform not found. @retval EFI_SUCCESS Operation success. **/ EFI_STATUS EFIAPI DxeUbaGetPlatformSku ( IN UBA_CONFIG_DATABASE_PROTOCOL *This, OUT UINT32 *BoardId, OUT EFI_GUID *BoardGuid, OPTIONAL OUT CHAR8 *BoardName OPTIONAL ) { EFI_STATUS Status; UBA_BOARD_NODE *SkuNode; SkuNode = NULL; Status = InternalGetSkuNode (This, &SkuNode); if (!EFI_ERROR (Status)) { if (BoardId != NULL) { *BoardId = SkuNode->BoardId; } if (BoardName != NULL) { AsciiStrCpyS (BoardName, AsciiStrSize (SkuNode->BoardName) / sizeof (CHAR8) , SkuNode->BoardName); } if (BoardGuid != NULL) { CopyMem (BoardGuid, &SkuNode->BoardGuid, sizeof (EFI_GUID)); } return EFI_SUCCESS; } return Status; } /** Add configuration data to uba configuration database. @param This uba Protocol instance. @param ResId The configuration data resource id. @param Data The data buffer pointer. @param DataSize Size of data want to add into database. @retval EFI_INVALID_PARAMETER Required parameters not correct. @retval EFI_OUT_OF_RESOURCES Resource not enough. @retval EFI_NOT_FOUND Platform not found. @retval EFI_SUCCESS Operation success. **/ EFI_STATUS EFIAPI DxeUbaAddData ( IN UBA_CONFIG_DATABASE_PROTOCOL *This, IN EFI_GUID *ResId, IN VOID *Data, IN UINTN DataSize ) { EFI_STATUS Status; UBA_BOARD_NODE *SkuNode; SkuNode = NULL; Status = InternalGetSkuNode (This, &SkuNode); if (EFI_ERROR (Status)) { return Status; } Status = InternalAddNewConfigData (This, ResId, Data, DataSize); return Status; } /** Get configuration data from uba configuration database. @param This uba Protocol instance. @param ResId The configuration data resource id. @param Data The data buffer pointer. @param DataSize IN:Size of data want to get, OUT: Size of data in database. @retval EFI_INVALID_PARAMETER Required parameters not correct. @retval EFI_BUFFER_TOO_SMALL The DataSize of Data buffer is too small to get this configuration data @retval EFI_OUT_OF_RESOURCES Resource not enough. @retval EFI_NOT_FOUND Platform or data not found. @retval EFI_SUCCESS Operation success. **/ EFI_STATUS EFIAPI DxeUbaGetData ( IN UBA_CONFIG_DATABASE_PROTOCOL *This, IN EFI_GUID *ResId, OUT VOID *Data, OUT UINTN *DataSize ) { EFI_STATUS Status; UBA_DXE_PRIVATE_DATA *UbaDxePrivate; UBA_BOARD_NODE *SkuNode; UbaDxePrivate = NULL; SkuNode = NULL; if ((ResId == NULL) || (Data == NULL) || (DataSize == NULL)) { return EFI_INVALID_PARAMETER; } UbaDxePrivate = PRIVATE_DATA_FROM_PROTOCOL (This); Status = InternalGetSkuNode (This, &SkuNode); if (EFI_ERROR (Status)) { return Status; } Status = InternalGetConfigData (This, SkuNode, ResId, Data, DataSize); if (!EFI_ERROR (Status)) { return EFI_SUCCESS; } return EFI_NOT_FOUND; } /** Internal function for getting current platform's configuration data from HOB, which passed by PEIM. @param This uba Protocol instance. @retval EFI_INVALID_PARAMETER Required parameters not correct. @retval EFI_OUT_OF_RESOURCES Resource not enough. @retval EFI_NOT_FOUND Platform or data not found. @retval EFI_SUCCESS Operation success. **/ EFI_STATUS InternalGetConfigDataFromHob ( IN UBA_CONFIG_DATABASE_PROTOCOL *This ) { EFI_STATUS Status; EFI_PEI_HOB_POINTERS Hob; UINT8 *HobDataStart; UBA_CONFIG_HOB_HEADER *HobHeader; UBA_CONFIG_HOB_FIELD *HobDataFieldStart; UINTN Index; UBA_DXE_PRIVATE_DATA *UbaDxePrivate; UBA_BOARD_NODE *SkuNode; HobHeader = NULL; HobDataFieldStart = NULL; UbaDxePrivate = NULL; SkuNode = NULL; UbaDxePrivate = PRIVATE_DATA_FROM_PROTOCOL (This); Hob.Raw = GetFirstGuidHob (&gUbaCurrentConfigHobGuid); ASSERT (Hob.Raw != NULL); if (Hob.Raw == NULL) { return EFI_UNSUPPORTED; } DEBUG ((DEBUG_INFO, "UbaConfigDatabasedxeEntry: get first hob!\n")); HobDataStart = GET_GUID_HOB_DATA (Hob); HobHeader = (UBA_CONFIG_HOB_HEADER *) HobDataStart; HobDataFieldStart = HobHeader->HobField; //Call internal function for SKU init, accroding to hob data. Status = InternalInitSkuDxe (This, HobHeader->BoardId, &HobHeader->BoardGuid, HobHeader->BoardName, &SkuNode); if (EFI_ERROR (Status)) { return Status; } // Obtain all data stored in the hob from PEI phase. for (Index = 0; Index < HobHeader->DataCount; Index ++) { Status = This->AddData ( This, &HobDataFieldStart[Index].ResId, (VOID *) ((UINTN) HobDataFieldStart[Index].DataOffset + (UINTN) HobHeader), HobDataFieldStart[Index].Size ); ASSERT_EFI_ERROR (Status); if (Status != EFI_SUCCESS) { return Status; } } return EFI_SUCCESS; } /** The Driver Entry Point. The function is the driver Entry point. @param ImageHandle A handle for the image that is initializing this driver @param SystemTable A pointer to the EFI system table @retval EFI_SUCCESS: Driver initialized successfully @retval EFI_LOAD_ERROR: Failed to Initialize or has been loaded @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources **/ EFI_STATUS EFIAPI UbaConfigDatabaseEntry ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; UBA_DXE_PRIVATE_DATA *UbaDxePrivate; EFI_HANDLE Handle; UbaDxePrivate = NULL; UbaDxePrivate = AllocateZeroPool (sizeof (UBA_DXE_PRIVATE_DATA)); ASSERT (UbaDxePrivate != NULL); if (UbaDxePrivate == NULL) { return EFI_OUT_OF_RESOURCES; } DEBUG ((DEBUG_INFO, "UbaConfigDatabasedxeEntry: after allocate Memory!\n")); UbaDxePrivate->Signature = UBA_BOARD_SIGNATURE; UbaDxePrivate->Version = UBA_BOARD_VERSION; UbaDxePrivate->ConfigDataCount = 0; UbaDxePrivate->HandleCount = 0; UbaDxePrivate->UbaCfgDbProtocol.Signature = UBA_CONFIG_PROTOCOL_SIGNATURE; UbaDxePrivate->UbaCfgDbProtocol.Version = UBA_CONFIG_PROTOCOL_VERSION; UbaDxePrivate->UbaCfgDbProtocol.GetSku = DxeUbaGetPlatformSku; UbaDxePrivate->UbaCfgDbProtocol.AddData = DxeUbaAddData; UbaDxePrivate->UbaCfgDbProtocol.GetData = DxeUbaGetData; // // Just produce our Protocol // Handle = NULL; Status = gBS->InstallProtocolInterface ( &Handle, &gUbaConfigDatabaseProtocolGuid, EFI_NATIVE_INTERFACE, &UbaDxePrivate->UbaCfgDbProtocol ); if (EFI_ERROR (Status)) { return Status; } DEBUG ((DEBUG_INFO, "UbaConfigDatabasedxeEntry: before get data from hob!\n")); // Init sku dxe and get configuration data from hob passed by PEIM. Status = InternalGetConfigDataFromHob (&UbaDxePrivate->UbaCfgDbProtocol); ASSERT_EFI_ERROR (Status); return Status; }