/** @file | |
RedfishHostInterfaceDxe builds up SMBIOS Type 42h host interface | |
record for Redfish service host interface using EFI MBIOS Protocol. | |
RedfishHostInterfacePlatformLib is the platform-level library which | |
provides the content of Redfish host interface type 42h record. | |
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> | |
(C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <Uefi.h> | |
#include <Library/BaseLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/MemoryAllocationLib.h> | |
#include <Library/PrintLib.h> | |
#include <Library/RedfishHostInterfaceLib.h> | |
#include <Library/UefiLib.h> | |
#include <Library/UefiBootServicesTableLib.h> | |
#include <Library/UefiRuntimeServicesTableLib.h> | |
/** | |
Create SMBIOS type 42 record for Redfish host interface. | |
@retval EFI_SUCESS SMBIOS type 42 record is created. | |
@retval Others Fail to create SMBIOS 42 record. | |
**/ | |
EFI_STATUS | |
RedfishCreateSmbiosTable42 ( | |
VOID | |
) | |
{ | |
REDFISH_INTERFACE_DATA *DeviceDescriptor; | |
UINT8 DeviceDataLength; | |
UINT8 DeviceType; | |
EFI_STATUS Status; | |
MC_HOST_INTERFACE_PROTOCOL_RECORD *ProtocolRecord; | |
VOID *ProtocolRecords; | |
VOID *NewProtocolRecords; | |
UINT8 ProtocolCount; | |
UINT8 CurrentProtocolsDataLength; | |
UINT8 NewProtocolsDataLength; | |
UINT8 ProtocolDataSize; | |
SMBIOS_TABLE_TYPE42 *Type42Record; | |
EFI_SMBIOS_PROTOCOL *Smbios; | |
EFI_SMBIOS_HANDLE MemArrayMappedAddrSmbiosHandle; | |
// | |
// Get platform Redfish host interface device type descriptor data. | |
// | |
Status = RedfishPlatformHostInterfaceDeviceDescriptor (&DeviceType, &DeviceDescriptor); | |
if (EFI_ERROR (Status)) { | |
if (Status == EFI_NOT_FOUND) { | |
DEBUG ((DEBUG_ERROR, "%a: No Redfish host interface descriptor is provided on this platform.", __FUNCTION__)); | |
return EFI_NOT_FOUND; | |
} | |
DEBUG((DEBUG_ERROR, "%a: Fail to get device descriptor, %r.", __FUNCTION__, Status)); | |
return Status; | |
} | |
if (DeviceType != REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2 && | |
DeviceType != REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2 | |
) { | |
DEBUG ((DEBUG_ERROR, "%a: Only support either protocol type 04h or 05h as Redfish host interface.", __FUNCTION__)); | |
return EFI_UNSUPPORTED; | |
} | |
if (DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) { | |
DeviceDataLength = DeviceDescriptor->DeviceDescriptor.PciPcieDeviceV2.Length; | |
} else { | |
DeviceDataLength = DeviceDescriptor->DeviceDescriptor.UsbDeviceV2.Length; | |
} | |
// | |
// Loop to get platform Redfish host interface protocol type data. | |
// | |
ProtocolRecord = NULL; | |
ProtocolRecords = NULL; | |
NewProtocolRecords = NULL; | |
Type42Record = NULL; | |
ProtocolCount = 0; | |
CurrentProtocolsDataLength = 0; | |
NewProtocolsDataLength = 0; | |
while (TRUE) { | |
Status = RedfishPlatformHostInterfaceProtocolData (&ProtocolRecord, ProtocolCount); | |
if (Status == EFI_NOT_FOUND) { | |
break; | |
} | |
if (EFI_ERROR(Status)) { | |
DEBUG ((DEBUG_ERROR, "%a: Fail to get Redfish host interafce protocol type data.", __FUNCTION__)); | |
if (ProtocolRecords != NULL) { | |
FreePool (ProtocolRecords); | |
} | |
if (ProtocolRecord != NULL) { | |
FreePool (ProtocolRecord); | |
} | |
return Status; | |
} | |
ProtocolDataSize = sizeof (MC_HOST_INTERFACE_PROTOCOL_RECORD) - sizeof(ProtocolRecord->ProtocolTypeData) + ProtocolRecord->ProtocolTypeDataLen; | |
NewProtocolsDataLength += ProtocolDataSize; | |
if (ProtocolRecords == NULL) { | |
ProtocolRecords = AllocateZeroPool (NewProtocolsDataLength); | |
if (ProtocolRecords == NULL) { | |
FreePool (ProtocolRecord); | |
return EFI_OUT_OF_RESOURCES; | |
} | |
CopyMem ((VOID *)ProtocolRecords, (VOID *)ProtocolRecord, ProtocolDataSize); | |
NewProtocolRecords = ProtocolRecords; | |
} else { | |
NewProtocolRecords = ReallocatePool(CurrentProtocolsDataLength, NewProtocolsDataLength, (VOID *)ProtocolRecords); | |
if (NewProtocolRecords == NULL) { | |
DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for Redfish host interface protocol data.")); | |
FreePool (ProtocolRecords); | |
FreePool (ProtocolRecord); | |
return EFI_OUT_OF_RESOURCES; | |
} | |
CopyMem ( | |
(VOID *)((UINT8 *)NewProtocolRecords + CurrentProtocolsDataLength), | |
(VOID *)ProtocolRecord, | |
ProtocolDataSize | |
); | |
} | |
FreePool (ProtocolRecord); | |
CurrentProtocolsDataLength = NewProtocolsDataLength; | |
ProtocolCount ++; | |
}; | |
if (ProtocolCount == 0) { | |
goto ON_EXIT; | |
} | |
// | |
// Construct SMBIOS Type 42h for Redfish host inteface. | |
// | |
// SMBIOS type 42 Record for Redfish Interface | |
// 00h Type BYTE 42 Management Controller Host Interface structure indicator | |
// 01h Length BYTE Varies Length of the structure, a minimum of 09h | |
// 02h Handle WORD Varies | |
// 04h Interface Type BYTE Varies Management Controller Interface Type. | |
// 05h Interface Specific Data Length (n) | |
// 06h Interface Specific data | |
// 06h+n number of protocols defined for the host interface (typically 1) | |
// 07h+n Include a Protocol Record for each protocol supported. | |
// | |
Type42Record = (SMBIOS_TABLE_TYPE42 *) AllocateZeroPool ( | |
sizeof (SMBIOS_TABLE_TYPE42) - 4 | |
+ DeviceDataLength | |
+ 1 /// For Protocol Record Count | |
+ CurrentProtocolsDataLength | |
+ 2 /// Double NULL terminator/ | |
); | |
if (Type42Record == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ON_EXIT; | |
} | |
Type42Record->Hdr.Type = EFI_SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE; | |
Type42Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE42) - 4 | |
+ DeviceDataLength | |
+ 1 | |
+ CurrentProtocolsDataLength; | |
Type42Record->Hdr.Handle = 0; | |
Type42Record->InterfaceType = MCHostInterfaceTypeNetworkHostInterface; // Network Host Interface | |
// | |
// Fill in InterfaceTypeSpecificDataLength field | |
// | |
Type42Record->InterfaceTypeSpecificDataLength = DeviceDataLength; | |
// | |
// Fill in InterfaceTypeSpecificData field | |
// | |
CopyMem (Type42Record->InterfaceTypeSpecificData, DeviceDescriptor, DeviceDataLength); | |
FreePool (DeviceDescriptor); | |
DeviceDescriptor = NULL; | |
// | |
// Fill in InterfaceTypeSpecificData Protocol Count field | |
// | |
*(Type42Record->InterfaceTypeSpecificData + DeviceDataLength) = ProtocolCount; | |
// | |
// Fill in Redfish Protocol Data | |
// | |
CopyMem ( | |
Type42Record->InterfaceTypeSpecificData + DeviceDataLength + 1, | |
NewProtocolRecords, | |
CurrentProtocolsDataLength | |
); | |
// | |
// 5. Add Redfish interface data record to SMBIOS table 42 | |
// | |
Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; | |
Status = Smbios->Add ( | |
Smbios, | |
NULL, | |
&MemArrayMappedAddrSmbiosHandle, | |
(EFI_SMBIOS_TABLE_HEADER*) Type42Record | |
); | |
DEBUG ((DEBUG_INFO, "RedfishPlatformDxe: Smbios->Add() - %r\n", Status)); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
Status = EFI_SUCCESS; | |
ON_EXIT: | |
if (DeviceDescriptor != NULL) { | |
FreePool (DeviceDescriptor); | |
} | |
if (NewProtocolRecords != NULL) { | |
FreePool (NewProtocolRecords); | |
} | |
if (Type42Record != NULL) { | |
FreePool (Type42Record); | |
} | |
return Status; | |
} | |
/** | |
Main entry for this driver. | |
@param ImageHandle Image handle this driver. | |
@param SystemTable Pointer to SystemTable. | |
@retval EFI_SUCESS This function always complete successfully. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
RedfishHostInterfaceDxeEntryPoint ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
{ | |
// | |
// Create SMBIOS type 42 record. | |
// | |
return RedfishCreateSmbiosTable42 (); | |
} |