Introduce gEdkIIRedfishHostInterfaceReadyProtocolGuid and produce it when Redfish Host Interface is installed on system. Signed-off-by: Abner Chang <abner.chang@amd.com> Cc: Nickle Wang <nicklew@nvidia.com> Cc: Igor Kulchytskyy <igork@ami.com> Cc: Mike Maslenkin <mike.maslenkin@gmail.com> Reviewed-by: Nickle Wang <nicklew@nvidia.com> Acked-by: Mike Maslenkin <mike.maslenkin@gmail.com>
		
			
				
	
	
		
			358 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			358 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @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>
 | 
						|
  Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.<BR>
 | 
						|
  Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 | 
						|
  Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<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>
 | 
						|
 | 
						|
static EFI_EVENT  mPlatformHostInterfaceReadylEvent        = NULL;
 | 
						|
static VOID       *mPlatformHostInterfaceReadyRegistration = NULL;
 | 
						|
 | 
						|
/**
 | 
						|
  Create SMBIOS type 42 record for Redfish host interface.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS    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;
 | 
						|
  EFI_HANDLE                         Handle;
 | 
						|
 | 
						|
  Handle = NULL;
 | 
						|
  //
 | 
						|
  // 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.\n", __func__));
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
 | 
						|
    DEBUG ((DEBUG_ERROR, "%a: Fail to get device descriptor, %r.", __func__, 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.", __func__));
 | 
						|
    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.", __func__));
 | 
						|
      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.", __func__));
 | 
						|
        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_MANAGEABILITY, "RedfishPlatformDxe: Smbios->Add() - %r\n", Status));
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_EXIT;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Install Redfish Host Interface ready protocol.
 | 
						|
  //
 | 
						|
  Status = gBS->InstallProtocolInterface (
 | 
						|
                  &Handle,
 | 
						|
                  &gEdkIIRedfishHostInterfaceReadyProtocolGuid,
 | 
						|
                  EFI_NATIVE_INTERFACE,
 | 
						|
                  (VOID *)NULL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "Failed to install gEdkIIRedfishHostInterfaceReadyProtocolGuid.\n"));
 | 
						|
    DEBUG ((DEBUG_ERROR, "PlatformConfigHandler driver may not be triggered to acquire Redfish service.\n"));
 | 
						|
  }
 | 
						|
 | 
						|
  // Set Status to EFI_SUCCESS that indicates SMBIOS 42 record was installed
 | 
						|
  // on the platform sucessfully.
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
 | 
						|
ON_EXIT:
 | 
						|
  if (DeviceDescriptor != NULL) {
 | 
						|
    FreePool (DeviceDescriptor);
 | 
						|
  }
 | 
						|
 | 
						|
  if (NewProtocolRecords != NULL) {
 | 
						|
    FreePool (NewProtocolRecords);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Type42Record != NULL) {
 | 
						|
    FreePool (Type42Record);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Notification event of platform Redfish Host Interface readiness.
 | 
						|
 | 
						|
  @param[in]  Event     Event whose notification function is being invoked.
 | 
						|
  @param[in]  Context   The pointer to the notification function's context,
 | 
						|
                        which is implementation-dependent.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
PlatformHostInterfaceInformationReady (
 | 
						|
  IN  EFI_EVENT  Event,
 | 
						|
  IN  VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  DEBUG ((DEBUG_MANAGEABILITY, "%a: Platform Redfish Host Interface informtion is ready\n", __func__));
 | 
						|
 | 
						|
  RedfishCreateSmbiosTable42 ();
 | 
						|
 | 
						|
  //
 | 
						|
  // Close event so we don't create multiple type 42 records
 | 
						|
  //
 | 
						|
  gBS->CloseEvent (Event);
 | 
						|
  mPlatformHostInterfaceReadylEvent = NULL;
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Main entry for this driver.
 | 
						|
 | 
						|
  @param ImageHandle     Image handle this driver.
 | 
						|
  @param SystemTable     Pointer to SystemTable.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS    This function always complete successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
RedfishHostInterfaceDxeEntryPoint (
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE  *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  EFI_GUID    *ReadyGuid;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_MANAGEABILITY, "%a: Entry\n.", __func__));
 | 
						|
 | 
						|
  //
 | 
						|
  // Check if the Redfish Host Interface depends on
 | 
						|
  // the specific protocol installation.
 | 
						|
  //
 | 
						|
  Status = RedfishPlatformHostInterfaceNotification (&ReadyGuid);
 | 
						|
  if (Status == EFI_SUCCESS) {
 | 
						|
    DEBUG ((DEBUG_MANAGEABILITY, "    Create protocol install notification to know the installation of platform Redfish host interface readiness\n"));
 | 
						|
    DEBUG ((DEBUG_MANAGEABILITY, "    Protocol GUID: %g\n", ReadyGuid));
 | 
						|
    //
 | 
						|
    // Register event for ReadyGuid protocol installed by
 | 
						|
    // platform Redfish host interface library.
 | 
						|
    //
 | 
						|
    Status = gBS->CreateEvent (
 | 
						|
                    EVT_NOTIFY_SIGNAL,
 | 
						|
                    TPL_CALLBACK,
 | 
						|
                    PlatformHostInterfaceInformationReady,
 | 
						|
                    NULL,
 | 
						|
                    &mPlatformHostInterfaceReadylEvent
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "    Fail to create event for the installation of platform Redfish host interface readiness.\n"));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = gBS->RegisterProtocolNotify (
 | 
						|
                    ReadyGuid,
 | 
						|
                    mPlatformHostInterfaceReadylEvent,
 | 
						|
                    &mPlatformHostInterfaceReadyRegistration
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "    Fail to register event for the installation of platform Redfish host interface readiness.\n"));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Status == EFI_UNSUPPORTED) || (Status == EFI_ALREADY_STARTED)) {
 | 
						|
    Status = RedfishCreateSmbiosTable42 ();
 | 
						|
  }
 | 
						|
 | 
						|
  // Return other erros.
 | 
						|
  return Status;
 | 
						|
}
 |