/** @file * * Copyright (c) 2015 - 2020, Hisilicon Limited. All rights reserved. * Copyright (c) 2015, Linaro Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent * **/ #include "AddSmbiosType9.h" extern SMBIOS_TABLE_TYPE9 gPcieSlotInfo[]; extern UINT8 OemGetPcieSlotNumber (); 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]; GetPciDidVid ((VOID *)ReportPcieDidVid); Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_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 ((DEBUG_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 ((DEBUG_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; } STATIC VOID EmptySmbiosType9 ( EFI_SMBIOS_PROTOCOL *Smbios ) { EFI_STATUS Status; EFI_SMBIOS_TYPE SmbiosType; EFI_SMBIOS_HANDLE SmbiosHandle; EFI_SMBIOS_TABLE_HEADER *Record; 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 ((DEBUG_ERROR, "[%a]:[%dL] Remove System Slot Failed. Status : %r\n", __FUNCTION__, __LINE__, Status)); break; } } } while (SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED); return; } STATIC EFI_STATUS AddSmbiosType9Record ( EFI_SMBIOS_PROTOCOL *Smbios, SMBIOS_TABLE_TYPE9 *Type9Record ) { EFI_STATUS Status; EFI_SMBIOS_HANDLE SmbiosHandle; SMBIOS_TABLE_TYPE9 *SmbiosRecord; CHAR8 *OptionalStrStart; CHAR16 SlotDesignation[SMBIOS_STRING_MAX_LENGTH]; UINTN SlotStrLen; SlotStrLen = UnicodeSPrint ( SlotDesignation, SMBIOS_STRING_MAX_LENGTH * 2, L"PCIE Slot%d", Type9Record->SlotID); // // Two zeros following the last string. // SmbiosRecord = AllocateZeroPool (sizeof (SMBIOS_TABLE_TYPE9) + SlotStrLen + 1 + 1); if (SmbiosRecord == NULL) { DEBUG ((DEBUG_ERROR, "AllocateZeroPool Failed for SmbiosRecord.\n")); return EFI_OUT_OF_RESOURCES; } (VOID)CopyMem (SmbiosRecord, Type9Record, sizeof (SMBIOS_TABLE_TYPE9)); SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE9); OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1); Status = UnicodeStrToAsciiStrS (SlotDesignation, OptionalStrStart, SlotStrLen + 1); ASSERT_EFI_ERROR (Status); // // 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 ((DEBUG_ERROR, "Add Smbios Type09 Failed! %r\n", Status)); } FreePool (SmbiosRecord); return Status; } STATIC VOID HandleSmbiosType9 ( EFI_SMBIOS_PROTOCOL *Smbios ) { EFI_STATUS Status; SMBIOS_TABLE_TYPE9 *Type9Record; UINT8 RecordCount; UINT8 Index; RecordCount = OemGetPcieSlotNumber (); if (RecordCount == 0) { return; } EmptySmbiosType9 (Smbios); Status = EFI_SUCCESS; for (Index = 0; Index < RecordCount; Index++) { if (gPcieSlotInfo[Index].Hdr.Type != EFI_SMBIOS_TYPE_SYSTEM_SLOTS) { continue; } Type9Record = &gPcieSlotInfo[Index]; UpdateSmbiosType9Info (Type9Record); Status = AddSmbiosType9Record (Smbios, Type9Record); if (EFI_ERROR (Status)) { break; } } return; } EFI_STATUS EFIAPI AddSmbiosType9Entry ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_SMBIOS_PROTOCOL *Smbios; Status = gBS->LocateProtocol ( &gEfiSmbiosProtocolGuid, NULL, (VOID **) &Smbios ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "[%a]:[%dL] LocateProtocol Failed. Status : %r\n", __FUNCTION__, __LINE__, Status)); return Status; } HandleSmbiosType9 (Smbios); return Status; }