blob: 8d8dacd3e028351c5f2f1eeeecfc4127a00e125d [file] [log] [blame]
/** @file
*
* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
* Copyright (c) 2015, Linaro Limited. All rights reserved.
*
* This program and the accompanying materials
* are licensed and made available under the terms and conditions of the BSD License
* which accompanies this distribution. The full text of the license may be found at
* http://opensource.org/licenses/bsd-license.php
*
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
*
**/
#include "AddSmbiosType9.h"
extern SMBIOS_TABLE_TYPE9 gPcieSlotInfo[];
extern UINT8 OemGetPcieSlotNumber ();
REPORT_PCIEDIDVID2BMC PcieDeviceToReport_2P[PCIEDEVICE_REPORT_MAX] = {
{67,0,0,0},
{225,0,0,3},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF}
};
VOID
EFIAPI
UpdateSmbiosType9Info(
IN OUT SMBIOS_TABLE_TYPE9 *Type9Record
)
{
EFI_STATUS Status;
UINTN HandleIndex;
EFI_HANDLE *HandleBuffer;
UINTN HandleCount;
EFI_PCI_IO_PROTOCOL *PciIo;
UINTN SegmentNumber;
UINTN BusNumber;
UINTN DeviceNumber;
UINTN FunctionNumber;
UINTN Index;
REPORT_PCIEDIDVID2BMC ReportPcieDidVid[PCIEDEVICE_REPORT_MAX];
if(OemIsMpBoot()){
(VOID)CopyMem((VOID *)ReportPcieDidVid,(VOID *)PcieDeviceToReport_2P,sizeof(PcieDeviceToReport_2P));
} else {
(VOID)CopyMem((VOID *)ReportPcieDidVid,(VOID *)PcieDeviceToReport,sizeof(PcieDeviceToReport));
}
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiPciIoProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
if(EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, " Locate gEfiPciIoProtocol Failed.\n"));
gBS->FreePool ((VOID *)HandleBuffer);
return;
}
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
Status = gBS->HandleProtocol (
HandleBuffer[HandleIndex],
&gEfiPciIoProtocolGuid,
(VOID **)&PciIo
);
if (EFI_ERROR (Status)) {
DEBUG((EFI_D_ERROR, "[%a]:[%dL] Status : %r\n", __FUNCTION__, __LINE__, Status));
continue;
}
(VOID)PciIo->GetLocation(PciIo, &SegmentNumber, &BusNumber, &DeviceNumber, &FunctionNumber);
for(Index = 0; Index < sizeof(ReportPcieDidVid) / sizeof(REPORT_PCIEDIDVID2BMC); Index++){
if (Type9Record->SlotID == ReportPcieDidVid[Index].Slot + 1) {
if((BusNumber == ReportPcieDidVid[Index].Bus) && (DeviceNumber == ReportPcieDidVid[Index].Device)) {
DEBUG((EFI_D_ERROR,"PCIe device plot in slot Seg %d bdf %d %d %d\r\n",SegmentNumber,BusNumber,DeviceNumber,FunctionNumber));
Type9Record->SegmentGroupNum = SegmentNumber;
Type9Record->BusNum = BusNumber;
Type9Record->DevFuncNum = (DeviceNumber << 3) | FunctionNumber;
Type9Record->CurrentUsage = SlotUsageInUse;
break;
}
}
}
}
gBS->FreePool ((VOID *)HandleBuffer);
return;
}
EFI_STATUS
EFIAPI
AddSmbiosType9Entry (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_SMBIOS_TYPE SmbiosType;
EFI_SMBIOS_HANDLE SmbiosHandle;
EFI_SMBIOS_PROTOCOL *Smbios;
EFI_SMBIOS_TABLE_HEADER *Record;
SMBIOS_TABLE_TYPE9 *Type9Record;
SMBIOS_TABLE_TYPE9 *SmbiosRecord = NULL;
CHAR8 *OptionalStrStart;
UINT8 SmbiosAddType9Number;
UINT8 Index;
CHAR16 *SlotDesignation = NULL;
UINTN SlotDesignationStrLen;
Status = gBS->LocateProtocol (
&gEfiSmbiosProtocolGuid,
NULL,
(VOID **) &Smbios
);
if (EFI_ERROR (Status)) {
DEBUG((EFI_D_ERROR, "[%a]:[%dL] LocateProtocol Failed. Status : %r\n", __FUNCTION__, __LINE__, Status));
return Status;
}
do {
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
SmbiosType = EFI_SMBIOS_TYPE_SYSTEM_SLOTS;
Status = Smbios->GetNext (Smbios, &SmbiosHandle, &SmbiosType, &Record, NULL);
if (!EFI_ERROR(Status)) {
Status = Smbios->Remove (Smbios, SmbiosHandle);
if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "[%a]:[%dL] Remove System Slot Failed. Status : %r\n", __FUNCTION__, __LINE__, Status));
break;
}
}
} while (SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED);
SmbiosAddType9Number = OemGetPcieSlotNumber();
for (Index = 0; Index < SmbiosAddType9Number; Index++)
{
if (gPcieSlotInfo[Index].Hdr.Type != EFI_SMBIOS_TYPE_SYSTEM_SLOTS)
{
continue;
}
Type9Record = &gPcieSlotInfo[Index];
UpdateSmbiosType9Info (Type9Record);
SlotDesignation = AllocateZeroPool ((sizeof (CHAR16)) * SMBIOS_STRING_MAX_LENGTH);
if (NULL == SlotDesignation)
{
Status = EFI_OUT_OF_RESOURCES;
DEBUG((EFI_D_ERROR, "[%a]:[%dL] AllocateZeroPool Failed. Status : %r\n", __FUNCTION__, __LINE__, Status));
goto Exit;
}
SlotDesignationStrLen = UnicodeSPrint (SlotDesignation, SMBIOS_STRING_MAX_LENGTH - 1, L"PCIE Slot%d", Type9Record->SlotID);
//
// Two zeros following the last string.
//
SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE9) + SlotDesignationStrLen + 1 + 1);
if(NULL == SmbiosRecord)
{
Status = EFI_OUT_OF_RESOURCES;
DEBUG((EFI_D_ERROR, "[%a]:[%dL] AllocateZeroPool Failed. Status : %r\n", __FUNCTION__, __LINE__, Status));
goto Exit;
}
(VOID)CopyMem(SmbiosRecord, Type9Record, sizeof (SMBIOS_TABLE_TYPE9));
SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE9);
OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
UnicodeStrToAsciiStr(SlotDesignation, OptionalStrStart);
//
// Now we have got the full smbios record, call smbios protocol to add this record.
//
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
Status = Smbios->Add (Smbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *)SmbiosRecord);
if(EFI_ERROR(Status))
{
DEBUG((EFI_D_ERROR, "[%a]:[%dL] Smbios Type09 Table Log Failed! %r \n", __FUNCTION__, __LINE__, Status));
goto Exit;
}
FreePool(SmbiosRecord);
FreePool(SlotDesignation);
}
return EFI_SUCCESS;
Exit:
if(SmbiosRecord != NULL)
{
FreePool(SmbiosRecord);
}
if(SlotDesignation != NULL)
{
FreePool(SlotDesignation);
}
return Status;
}