/** @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; | |
} | |