1625 lines
58 KiB
C
Executable File

/** @file
Copyright (C) 2016 - 2018, The HermitCrabs Lab. All rights reserved.
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 <Uefi.h>
#include <Protocol/PciRootBridgeIo.h>
#include <Guid/SmBios.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/OcCpuLib.h>
#include <Library/OcSmbiosLib.h>
#include <Library/OcMiscLib.h>
#include <Library/OcGuardLib.h>
#include <Library/OcStringLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <IndustryStandard/AppleSmBios.h>
#include <IndustryStandard/Pci.h>
#include "DebugSmbios.h"
#include "SmbiosInternal.h"
#include <ProcessorInfo.h>
STATIC SMBIOS_TABLE_ENTRY_POINT *mOriginalSmbios;
STATIC SMBIOS_TABLE_3_0_ENTRY_POINT *mOriginalSmbios3;
STATIC APPLE_SMBIOS_STRUCTURE_POINTER mOriginalTable;
STATIC UINT32 mOriginalTableSize;
#define SMBIOS_OVERRIDE_S(Table, Field, Original, Value, Index, Fallback) \
do { \
CONST CHAR8 *RealValue__ = (Value); \
if (RealValue__ == NULL && ((Original).Raw) != NULL && (Original).Raw + (Original).Standard.Hdr->Length \
>= ((UINT8 *)&((Original).Field) + sizeof (SMBIOS_TABLE_STRING))) { \
RealValue__ = SmbiosGetString ((Original), ((Original).Field)); \
} \
(((Table)->CurrentPtr).Field) = SmbiosOverrideString ( \
(Table), \
RealValue__ != NULL ? RealValue__ : (Fallback), \
(Index) \
); \
} while (0)
#define SMBIOS_OVERRIDE_V(Table, Field, Original, Value, Fallback) \
do { \
if ((Value) != NULL) { \
CopyMem (&(((Table)->CurrentPtr).Field), (Value), sizeof ((((Table)->CurrentPtr).Field))); \
} else if ((Original).Raw != NULL && (Original).Raw + (Original).Standard.Hdr->Length \
>= ((UINT8 *)&((Original).Field) + sizeof ((((Table)->CurrentPtr).Field)))) { \
CopyMem (&(((Table)->CurrentPtr).Field), &((Original).Field), sizeof ((((Table)->CurrentPtr).Field))); \
} else if ((Fallback) != NULL) { \
CopyMem (&(((Table)->CurrentPtr).Field), (Fallback), sizeof ((((Table)->CurrentPtr).Field))); \
} else { \
/* No ZeroMem call as written area is guaranteed to be 0 */ \
} \
} while (0)
#define SMBIOS_ACCESSIBLE(Table, Field) \
(((UINT8 *) &(Table).Field - (Table).Raw + sizeof ((Table).Field)) <= (Table).Standard.Hdr->Length)
STATIC
APPLE_SMBIOS_STRUCTURE_POINTER
SmbiosGetOriginalStructure (
IN SMBIOS_TYPE Type,
IN UINT16 Index
)
{
if (mOriginalTable.Raw == NULL) {
return mOriginalTable;
}
return SmbiosGetStructureOfType (mOriginalTable, mOriginalTableSize, Type, Index);
}
STATIC
UINT16
SmbiosGetOriginalStructureCount (
IN SMBIOS_TYPE Type
)
{
if (mOriginalTable.Raw == NULL) {
return 0;
}
return SmbiosGetStructureCount (mOriginalTable, mOriginalTableSize, Type);
}
/** Type 0
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchBiosInformation (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT8 MinLength;
UINT8 StringIndex;
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_BIOS_INFORMATION, 1);
MinLength = sizeof (*Original.Standard.Type0);
StringIndex = 0;
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_BIOS_INFORMATION, MinLength, 1))) {
return;
}
SMBIOS_OVERRIDE_S (Table, Standard.Type0->Vendor, Original, Data->BIOSVendor, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type0->BiosVersion, Original, Data->BIOSVersion, &StringIndex, NULL);
//
// Leave BiosSegment as 0 to ensure checks for IODeviceTree:/rom@0 or IODeviceTree:/rom@e0000 are met.
//
SMBIOS_OVERRIDE_S (Table, Standard.Type0->BiosReleaseDate, Original, Data->BIOSReleaseDate, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type0->BiosSize, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type0->BiosCharacteristics, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type0->BIOSCharacteristicsExtensionBytes, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type0->SystemBiosMajorRelease, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type0->SystemBiosMinorRelease, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type0->EmbeddedControllerFirmwareMajorRelease, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type0->EmbeddedControllerFirmwareMinorRelease, Original, NULL, NULL);
SmbiosFinaliseStruct (Table);
}
/** Type 1
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchSystemInformation (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT8 MinLength;
UINT8 StringIndex;
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_SYSTEM_INFORMATION, 1);
MinLength = sizeof (*Original.Standard.Type1);
StringIndex = 0;
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_SYSTEM_INFORMATION, MinLength, 1))) {
return;
}
SMBIOS_OVERRIDE_S (Table, Standard.Type1->Manufacturer, Original, Data->SystemManufacturer, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type1->ProductName, Original, Data->SystemProductName, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type1->Version, Original, Data->SystemVersion, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type1->SerialNumber, Original, Data->SystemSerialNumber, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type1->Uuid, Original, Data->SystemUUID, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type1->WakeUpType, Original, NULL, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type1->SKUNumber, Original, Data->SystemSKUNumber, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type1->Family, Original, Data->SystemFamily, &StringIndex, NULL);
SmbiosFinaliseStruct (Table);
}
/** Type 2
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchBaseboardInformation (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT8 MinLength;
UINT8 StringIndex;
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_BASEBOARD_INFORMATION, 1);
MinLength = sizeof (*Original.Standard.Type2);
StringIndex = 0;
//
// Hack for EDK 2 not using flexible array members adding extra data at struct end.
//
MinLength -= sizeof (Original.Standard.Type2->ContainedObjectHandles[0]);
OC_INLINE_STATIC_ASSERT (
sizeof (Original.Standard.Type2->ContainedObjectHandles) == sizeof (UINT16),
"Please remove this hack, the structure should have been fixed by now."
);
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_BASEBOARD_INFORMATION, MinLength, 1))) {
return;
}
SMBIOS_OVERRIDE_S (Table, Standard.Type2->Manufacturer, Original, Data->BoardManufacturer, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type2->ProductName, Original, Data->BoardProduct, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type2->Version, Original, Data->BoardVersion, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type2->SerialNumber, Original, Data->BoardSerialNumber, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type2->AssetTag, Original, Data->BoardAssetTag, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type2->FeatureFlag, Original, NULL, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type2->LocationInChassis, Original, Data->BoardLocationInChassis, &StringIndex, NULL);
Table->CurrentPtr.Standard.Type2->ChassisHandle = OcSmbiosSystemEnclosureHandle;
SMBIOS_OVERRIDE_V (Table, Standard.Type2->BoardType, Original, Data->BoardType, NULL);
//
// Leave NumberOfContainedObjectHandles as 0, just like Apple does.
//
SmbiosFinaliseStruct (Table);
}
/** Type 3
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchSystemEnclosure (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT8 MinLength;
UINT8 StringIndex;
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_SYSTEM_ENCLOSURE, 1);
MinLength = sizeof (*Original.Standard.Type3);
StringIndex = 0;
//
// Hack for EDK 2 not using flexible array members adding extra data at struct end.
//
MinLength -= sizeof (Original.Standard.Type3->ContainedElements[0]);
OC_INLINE_STATIC_ASSERT (
sizeof (Original.Standard.Type3->ContainedElements) == sizeof (UINT8)*3,
"Please remove this hack, the structure should have been fixed by now."
);
//
// Another hack for omitted SKUNumber after flexible array.
// Note, Apple just ignores this field and just writes Type3 as is.
//
MinLength += sizeof (SMBIOS_TABLE_STRING);
OC_INLINE_STATIC_ASSERT (
sizeof (*Original.Standard.Type3) == sizeof (UINT8) * 0x18,
"The structure has changed, please fix this up."
);
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_SYSTEM_ENCLOSURE, MinLength, 1))) {
return;
}
SMBIOS_OVERRIDE_S (Table, Standard.Type3->Manufacturer, Original, Data->ChassisManufacturer, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type3->Type, Original, Data->ChassisType, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type3->Version, Original, Data->ChassisVersion, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type3->SerialNumber, Original, Data->ChassisSerialNumber, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type3->AssetTag, Original, Data->ChassisAssetTag, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type3->BootupState, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type3->PowerSupplyState, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type3->ThermalState, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type3->SecurityStatus, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type3->OemDefined, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type3->Height, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type3->NumberofPowerCords, Original, NULL, NULL);
//
// Leave ContainedElementCount and ContainedElementRecordLength 0.
// Also do not assign anything to SKUNumber.
//
SmbiosFinaliseStruct (Table);
}
/** Type 4
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@param[in] CpuInfo Pointer to a valid pico cpu info structure.
@retval
**/
STATIC
VOID
PatchProcessorInformation (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data,
IN OC_CPU_INFO *CpuInfo
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT8 MinLength;
UINT8 StringIndex;
UINT8 TmpCount;
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_PROCESSOR_INFORMATION, 1);
MinLength = sizeof (*Original.Standard.Type4);
StringIndex = 0;
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_PROCESSOR_INFORMATION, MinLength, 1))) {
return;
}
SMBIOS_OVERRIDE_S (Table, Standard.Type4->Socket, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->ProcessorType, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->ProcessorFamily, Original, NULL, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type4->ProcessorManufacture, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->ProcessorId, Original, NULL, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type4->ProcessorVersion, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->Voltage, Original, NULL, NULL);
//
// Models newer than Sandybridge require quad pumped bus value instead of a front side bus value.
//
if (CpuInfo->Model >= CPU_MODEL_SANDYBRIDGE) {
Table->CurrentPtr.Standard.Type4->ExternalClock = OC_CPU_SNB_QPB_CLOCK;
} else {
Table->CurrentPtr.Standard.Type4->ExternalClock = (UINT16) DivU64x32 (CpuInfo->FSBFrequency, 1000000);
}
Table->CurrentPtr.Standard.Type4->MaxSpeed = (UINT16) DivU64x32 (CpuInfo->CPUFrequency, 1000000);
if (Table->CurrentPtr.Standard.Type4->MaxSpeed % 100 != 0) {
Table->CurrentPtr.Standard.Type4->MaxSpeed = (UINT16) (((Table->CurrentPtr.Standard.Type4->MaxSpeed + 50) / 100) * 100);
}
Table->CurrentPtr.Standard.Type4->CurrentSpeed = Table->CurrentPtr.Standard.Type4->MaxSpeed;
SMBIOS_OVERRIDE_V (Table, Standard.Type4->Status, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->ProcessorUpgrade, Original, NULL, NULL);
Table->CurrentPtr.Standard.Type4->L1CacheHandle = OcSmbiosL1CacheHandle;
Table->CurrentPtr.Standard.Type4->L2CacheHandle = OcSmbiosL2CacheHandle;
Table->CurrentPtr.Standard.Type4->L3CacheHandle = OcSmbiosL3CacheHandle;
SMBIOS_OVERRIDE_S (Table, Standard.Type4->SerialNumber, Original, NULL, &StringIndex, NULL);
//
// Most bootloaders set this to ProcessorVersion, yet Apple does not care and has UNKNOWN.
//
SMBIOS_OVERRIDE_S (Table, Standard.Type4->AssetTag, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type4->PartNumber, Original, NULL, &StringIndex, NULL);
TmpCount = (UINT8) (CpuInfo->CoreCount < 256 ? CpuInfo->CoreCount : 0xFF);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->CoreCount, Original, NULL, &TmpCount);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->EnabledCoreCount, Original, NULL, &TmpCount);
TmpCount = (UINT8) (CpuInfo->ThreadCount < 256 ? CpuInfo->ThreadCount : 0xFF);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->ThreadCount, Original, NULL, &TmpCount);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->ProcessorCharacteristics, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->ProcessorFamily2, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->CoreCount2, Original, NULL, &CpuInfo->CoreCount);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->EnabledCoreCount2, Original, NULL, &CpuInfo->CoreCount);
SMBIOS_OVERRIDE_V (Table, Standard.Type4->ThreadCount2, Original, NULL, &CpuInfo->ThreadCount);
SmbiosFinaliseStruct (Table);
}
/** Type 7
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchCacheInformation (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT16 NumberEntries;
UINT16 EntryNo;
UINT8 MinLength;
UINT8 StringIndex;
UINT16 CacheLevel;
BOOLEAN CacheLevels[3];
ZeroMem (CacheLevels, sizeof (CacheLevels));
NumberEntries = SmbiosGetOriginalStructureCount (SMBIOS_TYPE_CACHE_INFORMATION);
for (EntryNo = 1; EntryNo <= NumberEntries; EntryNo++) {
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_CACHE_INFORMATION, EntryNo);
if (Original.Raw == NULL || !SMBIOS_ACCESSIBLE (Original, Standard.Type7->CacheConfiguration)) {
continue;
}
//
// Check if already done with this cache type.
// Only support L1 to L3 caches.
//
CacheLevel = Original.Standard.Type7->CacheConfiguration & 7U;
if (CacheLevel <= 2 && !CacheLevels[CacheLevel]) {
CacheLevels[CacheLevel] = TRUE;
} else {
continue;
}
MinLength = sizeof (*Original.Standard.Type7);
StringIndex = 0;
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_CACHE_INFORMATION, MinLength, CacheLevel+1))) {
continue;
}
SMBIOS_OVERRIDE_S (Table, Standard.Type7->SocketDesignation, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type7->CacheConfiguration, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type7->MaximumCacheSize, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type7->InstalledSize, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type7->SupportedSRAMType, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type7->CurrentSRAMType, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type7->CacheSpeed, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type7->ErrorCorrectionType, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type7->SystemCacheType, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type7->Associativity, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type7->MaximumCacheSize2, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type7->InstalledSize2, Original, NULL, NULL);
SmbiosFinaliseStruct (Table);
}
}
/** Type 8
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchSystemPorts (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT16 NumberEntries;
UINT16 EntryNo;
UINT8 MinLength;
UINT8 StringIndex;
NumberEntries = SmbiosGetOriginalStructureCount (SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION);
for (EntryNo = 1; EntryNo <= NumberEntries; EntryNo++) {
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, EntryNo);
if (Original.Raw == NULL) {
continue;
}
MinLength = sizeof (*Original.Standard.Type8);
StringIndex = 0;
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_PORT_CONNECTOR_INFORMATION, MinLength, EntryNo))) {
continue;
}
SMBIOS_OVERRIDE_S (Table, Standard.Type8->InternalReferenceDesignator, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type8->InternalConnectorType, Original, NULL, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type8->ExternalReferenceDesignator, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type8->ExternalConnectorType, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type8->PortType, Original, NULL, NULL);
SmbiosFinaliseStruct (Table);
}
}
/** Type 9
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchSystemSlots (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT16 NumberEntries;
UINT16 EntryNo;
UINT8 MinLength;
UINT8 StringIndex;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
EFI_STATUS Status;
UINT64 PciAddress;
UINT8 SecSubBus;
UINT16 ClassCode;
CONST CHAR8 *SlotDesignation;
Status = gBS->LocateProtocol (
&gEfiPciRootBridgeIoProtocolGuid,
NULL,
(VOID **) &PciRootBridgeIo
);
if (EFI_ERROR (Status)) {
PciRootBridgeIo = NULL;
}
NumberEntries = SmbiosGetOriginalStructureCount (SMBIOS_TYPE_SYSTEM_SLOTS);
for (EntryNo = 1; EntryNo <= NumberEntries; EntryNo++) {
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_SYSTEM_SLOTS, EntryNo);
if (Original.Raw == NULL) {
continue;
}
MinLength = sizeof (*Original.Standard.Type9);
StringIndex = 0;
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_SYSTEM_SLOTS, MinLength, EntryNo))) {
continue;
}
SMBIOS_OVERRIDE_V (Table, Standard.Type9->SlotType, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type9->SlotDataBusWidth, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type9->SlotLength, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type9->SlotID, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type9->SlotType, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type9->SlotCharacteristics1, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type9->SlotCharacteristics2, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type9->SegmentGroupNum, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type9->BusNum, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type9->DevFuncNum, Original, NULL, NULL);
//
// Correct SlotDesignation and CurrentUsage if PCI protocol is available.
//
if (PciRootBridgeIo == NULL) {
SMBIOS_OVERRIDE_S (Table, Standard.Type9->SlotDesignation, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type9->CurrentUsage, Original, NULL, NULL);
} else {
SlotDesignation = NULL;
Table->CurrentPtr.Standard.Type9->CurrentUsage = SlotUsageAvailable;
if (Table->CurrentPtr.Standard.Type9->BusNum != 0) {
PciAddress = EFI_PCI_ADDRESS (
BitFieldRead8 (Table->CurrentPtr.Standard.Type9->DevFuncNum, 3, 7),
Table->CurrentPtr.Standard.Type9->BusNum,
BitFieldRead8 (Table->CurrentPtr.Standard.Type9->DevFuncNum, 0, 2),
0
);
} else {
PciAddress = EFI_PCI_ADDRESS (
Table->CurrentPtr.Standard.Type9->BusNum,
BitFieldRead8 (Table->CurrentPtr.Standard.Type9->DevFuncNum, 3, 7),
BitFieldRead8 (Table->CurrentPtr.Standard.Type9->DevFuncNum, 0, 2),
0
);
}
SecSubBus = MAX_UINT8;
ClassCode = MAX_UINT16;
Status = PciRootBridgeIo->Pci.Read (
PciRootBridgeIo,
EfiPciWidthUint8,
PciAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET,
1,
&SecSubBus
);
if (!EFI_ERROR (Status) && SecSubBus != MAX_UINT8) {
Status = PciRootBridgeIo->Pci.Read (
PciRootBridgeIo,
EfiPciWidthUint16,
EFI_PCI_ADDRESS (SecSubBus, 0, 0, 0) + 10,
1,
&ClassCode
);
}
if (!EFI_ERROR (Status) && ClassCode != MAX_UINT16) {
Table->CurrentPtr.Standard.Type9->CurrentUsage = SlotUsageAvailable;
if (ClassCode == 0x0280) {
SlotDesignation = "AirPort";
} else if (ClassCode == 0x0108) {
//
// FIXME: Expand checks since not all nvme uses m.2 slot
//
SlotDesignation = "M.2";
}
}
SMBIOS_OVERRIDE_S (Table, Standard.Type9->SlotDesignation, Original, SlotDesignation, &StringIndex, NULL);
}
SmbiosFinaliseStruct (Table);
}
}
/** Type 16
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchMemoryArray (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT8 MinLength;
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY, 1);
MinLength = sizeof (*Original.Standard.Type16);
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY, MinLength, 1))) {
return;
}
SMBIOS_OVERRIDE_V (Table, Standard.Type16->Location, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type16->Use, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type16->MemoryErrorCorrection, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type16->MaximumCapacity, Original, NULL, NULL);
//
// Do not support memory error information.
//
Table->CurrentPtr.Standard.Type16->MemoryErrorInformationHandle = 0xFFFF;
SMBIOS_OVERRIDE_V (Table, Standard.Type16->NumberOfMemoryDevices, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type16->ExtendedMaximumCapacity, Original, NULL, NULL);
SmbiosFinaliseStruct (Table);
}
/** Type 17
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchMemoryDevice (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data,
IN APPLE_SMBIOS_STRUCTURE_POINTER Original,
IN UINT16 Index,
OUT SMBIOS_HANDLE *Handle
)
{
UINT8 MinLength;
UINT8 StringIndex;
BOOLEAN IsEmpty;
*Handle = OcSmbiosInvalidHandle;
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_MEMORY_DEVICE, Index);
MinLength = sizeof (*Original.Standard.Type17);
StringIndex = 0;
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_MEMORY_DEVICE, MinLength, Index))) {
return;
}
//
// External handles are set below.
//
SMBIOS_OVERRIDE_V (Table, Standard.Type17->TotalWidth, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->DataWidth, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->Size, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->FormFactor, Original, Data->MemoryFormFactor, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->DeviceSet, Original, NULL, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type17->DeviceLocator, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type17->BankLocator, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->MemoryType, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->TypeDetail, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->Speed, Original, NULL, NULL);
//
// Empty modules should have 0 Size according to the spec.
// Original OC implementation relies on TotalWidth, which may be a workaround for some FW.
//
IsEmpty = Table->CurrentPtr.Standard.Type17->Size == 0
|| Table->CurrentPtr.Standard.Type17->TotalWidth == 0;
if (!IsEmpty) {
Table->CurrentPtr.Standard.Type17->MemoryArrayHandle = OcSmbiosPhysicalMemoryArrayHandle;
Table->CurrentPtr.Standard.Type17->MemoryErrorInformationHandle = 0xFFFF;
} else {
//
// Empty slots should have no physical memory array handle.
//
Table->CurrentPtr.Standard.Type17->MemoryArrayHandle = 0xFFFF;
Table->CurrentPtr.Standard.Type17->MemoryErrorInformationHandle = 0xFFFF;
}
SMBIOS_OVERRIDE_S (Table, Standard.Type17->Manufacturer, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type17->SerialNumber, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type17->AssetTag, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type17->PartNumber, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->Attributes, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->ExtendedSize, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->ConfiguredMemoryClockSpeed, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->MinimumVoltage, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->MaximumVoltage, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type17->ConfiguredVoltage, Original, NULL, NULL);
//
// Return assigned handle
//
*Handle = Table->CurrentPtr.Standard.Hdr->Handle;
SmbiosFinaliseStruct (Table);
}
/** Type 19
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchMemoryMappedAddress (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data,
IN OUT OC_SMBIOS_MAPPING *Mapping,
IN OUT UINT16 *MappingNum
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT16 NumberEntries;
UINT16 EntryNo;
UINT8 MinLength;
*MappingNum = 0;
NumberEntries = SmbiosGetOriginalStructureCount (SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS);
for (EntryNo = 1; EntryNo <= NumberEntries; EntryNo++) {
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS, EntryNo);
if (Original.Raw == NULL) {
continue;
}
MinLength = sizeof (*Original.Standard.Type19);
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS, MinLength, EntryNo))) {
continue;
}
SMBIOS_OVERRIDE_V (Table, Standard.Type19->StartingAddress, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type19->EndingAddress, Original, NULL, NULL);
Table->CurrentPtr.Standard.Type19->MemoryArrayHandle = OcSmbiosPhysicalMemoryArrayHandle;
SMBIOS_OVERRIDE_V (Table, Standard.Type19->PartitionWidth, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type19->ExtendedStartingAddress, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type19->ExtendedEndingAddress, Original, NULL, NULL);
if (*MappingNum < OC_SMBIOS_MAX_MAPPING) {
Mapping[*MappingNum].Old = Original.Standard.Hdr->Handle;
Mapping[*MappingNum].New = Table->CurrentPtr.Standard.Hdr->Handle;
(*MappingNum)++;
} else {
//
// The value is reasonably large enough for this to never happen, yet just in case.
//
DEBUG ((DEBUG_WARN, "OC_SMBIOS_MAX_MAPPING exceeded\n"));
}
SmbiosFinaliseStruct (Table);
}
}
/** Type 20
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchMemoryMappedDevice (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data,
IN APPLE_SMBIOS_STRUCTURE_POINTER Original,
IN UINT16 Index,
IN SMBIOS_HANDLE MemoryDeviceHandle,
IN OC_SMBIOS_MAPPING *Mapping,
IN UINT16 MappingNum
)
{
UINT8 MinLength;
UINT16 MapIndex;
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_MEMORY_DEVICE_MAPPED_ADDRESS, Index);
MinLength = sizeof (*Original.Standard.Type20);
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_MEMORY_DEVICE_MAPPED_ADDRESS, MinLength, Index))) {
return;
}
SMBIOS_OVERRIDE_V (Table, Standard.Type20->StartingAddress, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type20->EndingAddress, Original, NULL, NULL);
Table->CurrentPtr.Standard.Type20->MemoryDeviceHandle = MemoryDeviceHandle;
Table->CurrentPtr.Standard.Type20->MemoryArrayMappedAddressHandle = 0xFFFF;
if (Original.Raw != NULL && SMBIOS_ACCESSIBLE(Original, Standard.Type20->MemoryArrayMappedAddressHandle)) {
for (MapIndex = 0; MapIndex < MappingNum; MapIndex++) {
if (Mapping[MapIndex].Old == Original.Standard.Type20->MemoryArrayMappedAddressHandle) {
Table->CurrentPtr.Standard.Type20->MemoryArrayMappedAddressHandle = Mapping[Index].New;
break;
}
}
}
SMBIOS_OVERRIDE_V (Table, Standard.Type20->PartitionRowPosition, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type20->InterleavePosition, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type20->InterleavedDataDepth, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type20->ExtendedStartingAddress, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type20->ExtendedEndingAddress, Original, NULL, NULL);
SmbiosFinaliseStruct (Table);
}
/** Type 22
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchPortableBatteryDevice (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT8 MinLength;
UINT8 StringIndex;
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_PORTABLE_BATTERY, 1);
MinLength = sizeof (*Original.Standard.Type22);
StringIndex = 0;
//
// Do not add batteries where it does not exist (e.g. desktop).
//
if (Original.Raw == NULL) {
return;
}
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_PORTABLE_BATTERY, MinLength, 1))) {
return;
}
SMBIOS_OVERRIDE_S (Table, Standard.Type22->Location, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type22->Manufacturer, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type22->ManufactureDate, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type22->SerialNumber, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type22->DeviceName, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type22->DeviceChemistry, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type22->DeviceCapacity, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type22->DesignVoltage, Original, NULL, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type22->SBDSVersionNumber, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type22->MaximumErrorInBatteryData, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type22->SBDSSerialNumber, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type22->SBDSManufactureDate, Original, NULL, NULL);
SMBIOS_OVERRIDE_S (Table, Standard.Type22->SBDSDeviceChemistry, Original, NULL, &StringIndex, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type22->DesignCapacityMultiplier, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type22->OEMSpecific, Original, NULL, NULL);
SmbiosFinaliseStruct (Table);
}
/** Type 32
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
PatchBootInformation (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT8 MinLength;
Original = SmbiosGetOriginalStructure (SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION, 1);
MinLength = sizeof (*Original.Standard.Type32);
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION, MinLength, 1))) {
return;
}
SMBIOS_OVERRIDE_V (Table, Standard.Type32->Reserved, Original, NULL, NULL);
SMBIOS_OVERRIDE_V (Table, Standard.Type32->BootStatus, Original, NULL, NULL);
SmbiosFinaliseStruct (Table);
}
/** Type 128
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
CreateAppleFirmwareVolume (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data
)
{
UINT8 MinLength;
MinLength = sizeof (*Table->CurrentPtr.Type128);
if (EFI_ERROR (SmbiosInitialiseStruct (Table, APPLE_SMBIOS_TYPE_FIRMWARE_INFORMATION, MinLength, 1))) {
return;
}
Table->CurrentPtr.Type128->FirmwareFeatures = (UINT32)BitFieldRead64 (Data->FirmwareFeatures, 0, 31);
Table->CurrentPtr.Type128->FirmwareFeaturesMask = (UINT32)BitFieldRead64 (Data->FirmwareFeaturesMask, 0, 31);
Table->CurrentPtr.Type128->ExtendedFirmwareFeatures = (UINT32)BitFieldRead64 (Data->FirmwareFeatures, 32, 63);
Table->CurrentPtr.Type128->ExtendedFirmwareFeaturesMask = (UINT32)BitFieldRead64 (Data->FirmwareFeaturesMask, 32, 63);
SmbiosFinaliseStruct (Table);
}
/** Type 131
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@param[in] CpuInfo Pointer to a valid pico cpu info structure.
@retval
**/
STATIC
VOID
CreateAppleProcessorType (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data,
IN OC_CPU_INFO *CpuInfo
)
{
APPLE_SMBIOS_STRUCTURE_POINTER Original;
UINT8 MinLength;
Original.Raw = NULL;
MinLength = sizeof (*Table->CurrentPtr.Type131);
if (EFI_ERROR (SmbiosInitialiseStruct (Table, APPLE_SMBIOS_TYPE_PROCESSOR_TYPE, MinLength, 1))) {
return;
}
SMBIOS_OVERRIDE_V (Table, Type131->ProcessorType.Type, Original, Data->ProcessorType, &CpuInfo->AppleProcessorType);
SmbiosFinaliseStruct (Table);
}
/** Type 132
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@param[in] CpuInfo Pointer to a valid pico cpu info structure.
@retval
**/
STATIC
VOID
CreateAppleProcessorSpeed (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data,
IN OC_CPU_INFO *CpuInfo
)
{
#ifndef OC_PROVIDE_APPLE_PROCESSOR_BUS_SPEED
//
// I believe this table is no longer used.
// The code below may be inaccurate as well, since it expects KHz.
//
(VOID) Table;
(VOID) Data;
(VOID) CpuInfo;
#else
UINT8 MinLength;
MinLength = sizeof (*Table->CurrentPtr.Type132);
if (EFI_ERROR (SmbiosInitialiseStruct (Table, APPLE_SMBIOS_TYPE_PROCESSOR_BUS_SPEED, MinLength, 1))) {
return;
}
if (CpuInfo->Model >= CPU_MODEL_SANDYBRIDGE) {
Table->CurrentPtr.Type132->ProcessorBusSpeed = OC_CPU_SNB_QPB_CLOCK * 1000;
} else {
Table->CurrentPtr.Type132->ProcessorBusSpeed = (UINT16) DivU64x32 (CpuInfo->FSBFrequency, 1000);
}
SmbiosFinaliseStruct (Table);
#endif
}
/** Type 127
@param[in] Table Pointer to location containing the current address within the buffer.
@param[in] Handle Pointer to tocation containing the current handle value.
@retval
**/
STATIC
VOID
CreateSmBiosEndOfTable (
IN OUT OC_SMBIOS_TABLE *Table,
IN OC_SMBIOS_DATA *Data
)
{
UINT8 MinLength;
MinLength = sizeof (*Table->CurrentPtr.Standard.Type127);
if (EFI_ERROR (SmbiosInitialiseStruct (Table, SMBIOS_TYPE_END_OF_TABLE, MinLength, 1))) {
return;
}
SmbiosFinaliseStruct (Table);
}
/**
Lock or unlock legacy region if used
@param Unlock TRUE to unlock, FALSE to lock
**/
STATIC
EFI_STATUS
SmbiosHandleLegacyRegion (
BOOLEAN Unlock
)
{
EFI_STATUS Status;
//
// Not needed for mOriginalSmbios3.
//
if (mOriginalSmbios == NULL) {
return EFI_SUCCESS;
}
if (Unlock) {
if (((UINTN) mOriginalSmbios) < BASE_1MB) {
//
// Enable write access to DMI anchor
//
Status = LegacyRegionUnlock (
(UINT32) ((UINTN) mOriginalSmbios & 0xFFFF8000ULL),
EFI_PAGE_SIZE
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "LegacyRegionUnlock DMI anchor failure - %r\n", Status));
return Status;
}
}
if (((UINTN) mOriginalSmbios->TableAddress) < BASE_1MB) {
//
// Enable write access to DMI table
//
Status = LegacyRegionUnlock (
(UINT32) ((UINTN) mOriginalSmbios->TableAddress & 0xFFFF8000ULL),
EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (mOriginalSmbios->TableLength))
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "LegacyRegionUnlock DMI table failure - %r\n", Status));
return Status;
}
}
} else {
if ((UINTN) mOriginalSmbios->TableAddress < BASE_1MB) {
//
// Lock write access To DMI table
//
Status = LegacyRegionLock (
(UINT32) ((UINTN) mOriginalSmbios->TableAddress & 0xFFFF8000ULL),
EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (mOriginalSmbios->TableLength))
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "LegacyRegionLock DMI table failure - %r\n", Status));
return Status;
}
}
if ((UINTN) mOriginalSmbios < BASE_1MB) {
//
// Lock write access To DMI anchor
//
Status = LegacyRegionLock (
(UINT32) ((UINTN) mOriginalSmbios & 0xFFFF8000ULL),
EFI_PAGE_SIZE
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "LegacyRegionLock DMI anchor failure - %r\n", Status));
return Status;
}
}
}
return EFI_SUCCESS;
}
/**
Prepare new SMBIOS table based on host data.
@param SmbiosTable
@retval EFI_SUCCESS if buffer is ready to be filled.
**/
STATIC
EFI_STATUS
SmbiosPrepareTable (
IN OUT OC_SMBIOS_TABLE *SmbiosTable
)
{
EFI_STATUS Status;
mOriginalSmbios = NULL;
mOriginalSmbios3 = NULL;
mOriginalTableSize = 0;
mOriginalTable.Raw = NULL;
ZeroMem (SmbiosTable, sizeof (*SmbiosTable));
SmbiosTable->Handle = OcSmbiosAutomaticHandle;
Status = EfiGetSystemConfigurationTable (
&gEfiSmbiosTableGuid,
(VOID **) &mOriginalSmbios
);
//
// Perform basic sanity checks. We assume EfiGetSystemConfigurationTable returns trusted data
// in terms of file size at the very least, but try to detect potential issues.
//
if (!EFI_ERROR (Status)) {
if (mOriginalSmbios->EntryPointLength < sizeof (SMBIOS_TABLE_ENTRY_POINT)) {
DEBUG ((DEBUG_WARN, "SmbiosLookupHost entry is too small - %u/%u bytes\n",
mOriginalSmbios->EntryPointLength, (UINT32) sizeof (SMBIOS_TABLE_ENTRY_POINT)));
mOriginalSmbios = NULL;
} else if (mOriginalSmbios->TableAddress == 0 || mOriginalSmbios->TableLength == 0) {
OC_INLINE_STATIC_ASSERT (
sizeof (mOriginalSmbios->TableLength) == sizeof (UINT16)
&& SMBIOS_TABLE_MAX_LENGTH == MAX_UINT16,
"mOriginalTable->TableLength may exceed SMBIOS_TABLE_MAX_LENGTH"
);
DEBUG ((DEBUG_WARN, "SmbiosLookupHost entry has invalid table - %08X of %u bytes\n",
mOriginalSmbios->TableAddress, mOriginalSmbios->TableLength));
mOriginalSmbios = NULL;
}
} else {
DEBUG ((DEBUG_WARN, "SmbiosLookupHost failed to lookup SMBIOSv1 - %r\n", Status));
}
//
// Do similar checks on SMBIOSv3.
//
Status = EfiGetSystemConfigurationTable (
&gEfiSmbios3TableGuid,
(VOID **) &mOriginalSmbios3
);
if (!EFI_ERROR (Status)) {
if (mOriginalSmbios3->EntryPointLength < sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT)) {
DEBUG ((DEBUG_INFO, "SmbiosLookupHost v3 entry is too small - %u/%u bytes\n",
mOriginalSmbios3->EntryPointLength, (UINT32) sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT)));
mOriginalSmbios3 = NULL;
} else if (mOriginalSmbios3->TableAddress == 0 || mOriginalSmbios3->TableMaximumSize == 0) {
OC_INLINE_STATIC_ASSERT (
sizeof (mOriginalSmbios3->TableMaximumSize) == sizeof (UINT32)
&& SMBIOS_3_0_TABLE_MAX_LENGTH == MAX_UINT32,
"mOriginalSmbios3->TableMaximumSize may exceed SMBIOS_3_0_TABLE_MAX_LENGTH"
);
DEBUG ((DEBUG_INFO, "SmbiosLookupHost v3 entry has invalid table - %016LX of %u bytes\n",
mOriginalSmbios3->TableAddress, mOriginalSmbios3->TableMaximumSize));
mOriginalSmbios3 = NULL;
}
} else {
DEBUG ((DEBUG_INFO, "SmbiosLookupHost failed to lookup SMBIOSv3 - %r\n", Status));
}
//
// TODO: I think we may want to try harder.
//
//
// Pad the table length to a page and calculate byte size.
//
if (mOriginalSmbios != NULL) {
mOriginalTableSize = mOriginalSmbios->TableLength;
mOriginalTable.Raw = (UINT8 *)(UINTN) mOriginalSmbios->TableAddress;
} else if (mOriginalSmbios3 != NULL) {
mOriginalTableSize = mOriginalSmbios3->TableMaximumSize;
mOriginalTable.Raw = (UINT8 *)(UINTN) mOriginalSmbios3->TableAddress;
}
if (mOriginalSmbios != NULL) {
DEBUG ((
DEBUG_INFO,
"Found DMI Anchor %08LX v%u.%u Table Address %08LX Length %04X\n",
(UINT64) mOriginalSmbios,
mOriginalSmbios->MajorVersion,
mOriginalSmbios->MinorVersion,
(UINT64) mOriginalSmbios->TableAddress,
mOriginalSmbios->TableLength
));
}
if (mOriginalSmbios3 != NULL) {
DEBUG ((
DEBUG_INFO,
"Found DMI Anchor %08LX v%u.%u Table Address %08LX Length %04X\n",
(UINT64) mOriginalSmbios3,
mOriginalSmbios3->MajorVersion,
mOriginalSmbios3->MinorVersion,
mOriginalSmbios3->TableAddress,
mOriginalSmbios3->TableMaximumSize
));
}
Status = SmbiosExtendTable (SmbiosTable, 1);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_VERBOSE, "SmbiosLookupHost failed to initialise smbios table - %r\n", Status));
}
return Status;
}
STATIC
EFI_STATUS
SmbiosTableAllocate (
IN UINT16 TableLength,
IN OUT SMBIOS_TABLE_ENTRY_POINT **TableEntryPoint,
IN OUT SMBIOS_TABLE_3_0_ENTRY_POINT **TableEntryPoint3,
IN OUT VOID **TableAddress,
IN OUT VOID **TableAddress3
)
{
UINT16 TablePages;
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS TmpAddr;
TablePages = EFI_SIZE_TO_PAGES (TableLength);
*TableEntryPoint = NULL;
*TableEntryPoint3 = NULL;
*TableAddress = NULL;
*TableAddress3 = NULL;
TmpAddr = (BASE_4GB - 1);
Status = gBS->AllocatePages (AllocateMaxAddress, EfiReservedMemoryType, TablePages, &TmpAddr);
if (!EFI_ERROR (Status)) {
*TableAddress = (VOID *) TmpAddr;
TmpAddr = (BASE_4GB - 1);
Status = gBS->AllocatePages (AllocateMaxAddress, EfiReservedMemoryType, 1, &TmpAddr);
if (!EFI_ERROR (Status)) {
*TableEntryPoint = (SMBIOS_TABLE_ENTRY_POINT *) TmpAddr;
if (mOriginalSmbios3 != NULL) {
TmpAddr = (BASE_4GB - 1);
Status = gBS->AllocatePages (AllocateMaxAddress, EfiReservedMemoryType, 1, &TmpAddr);
if (!EFI_ERROR (Status)) {
*TableEntryPoint3 = (SMBIOS_TABLE_3_0_ENTRY_POINT *) TmpAddr;
*TableAddress3 = *TableAddress;
}
}
}
}
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "SmbiosTableAllocate aborts as it cannot allocate SMBIOS pages with %d %d %d\n",
*TableEntryPoint != NULL, *TableAddress != NULL, *TableEntryPoint3 != NULL));
if (*TableEntryPoint != NULL) {
FreePages (*TableEntryPoint, 1);
}
if (*TableEntryPoint3 != NULL) {
FreePages (*TableEntryPoint3, 1);
}
if (*TableAddress != NULL) {
FreePages (*TableAddress, TablePages);
}
return Status;
}
ZeroMem (*TableAddress, TablePages * EFI_PAGE_SIZE);
ZeroMem (*TableEntryPoint, EFI_PAGE_SIZE);
if (mOriginalSmbios3 != NULL) {
ZeroMem (*TableEntryPoint3, EFI_PAGE_SIZE);
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
SmbiosTableApply (
IN OUT OC_SMBIOS_TABLE *SmbiosTable,
IN OC_SMBIOS_UPDATE_MODE Mode
)
{
EFI_STATUS Status;
UINT16 TableLength;
SMBIOS_TABLE_ENTRY_POINT *TableEntryPoint;
SMBIOS_TABLE_3_0_ENTRY_POINT *TableEntryPoint3;
VOID *TableAddress;
VOID *TableAddress3;
ASSERT (Mode == OcSmbiosUpdateCreate
|| Mode == OcSmbiosUpdateOverwrite
|| Mode == OcSmbiosUpdateCustom
|| Mode == OcSmbiosUpdateAuto
);
//
// We check maximum table size during table extension, so this cast is valid.
//
TableLength = (UINT16) (SmbiosTable->CurrentPtr.Raw - SmbiosTable->Table);
if (Mode == OcSmbiosUpdateAuto || Mode == OcSmbiosUpdateOverwrite) {
Status = SmbiosHandleLegacyRegion (TRUE);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "SmbiosTableApply(%u) cannot handle legacy region - %r\n", Mode, Status));
if (Mode == OcSmbiosUpdateOverwrite) {
return Status;
}
//
// Fallback to create mode.
//
Mode = OcSmbiosUpdateCreate;
} else if (mOriginalSmbios == NULL || TableLength > mOriginalSmbios->TableLength
|| mOriginalSmbios->EntryPointLength < sizeof (SMBIOS_TABLE_ENTRY_POINT)) {
DEBUG ((DEBUG_WARN, "SmbiosTableApply(%u) cannot update old SMBIOS (%p, %u, %u) with %u\n",
Mode, mOriginalSmbios, mOriginalSmbios != NULL ? mOriginalSmbios->TableLength : 0,
mOriginalSmbios != NULL ? mOriginalSmbios->EntryPointLength : 0, TableLength));
if (Mode == OcSmbiosUpdateOverwrite) {
return EFI_OUT_OF_RESOURCES;
}
//
// Fallback to create mode.
//
Mode = OcSmbiosUpdateCreate;
} else if (mOriginalSmbios3 != NULL && (TableLength > mOriginalSmbios3->TableMaximumSize
|| mOriginalSmbios3->EntryPointLength < sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT))) {
DEBUG ((DEBUG_INFO, "SmbiosTableApply(%u) cannot fit SMBIOSv3 (%p, %u, %u) with %u\n",
Mode, mOriginalSmbios3, mOriginalSmbios3->EntryPointLength, mOriginalSmbios3->TableMaximumSize, TableLength));
Mode = OcSmbiosUpdateCreate;
} else {
Mode = OcSmbiosUpdateOverwrite;
}
}
ASSERT (Mode != OcSmbiosUpdateAuto);
if (Mode != OcSmbiosUpdateOverwrite) {
Status = SmbiosTableAllocate (
TableLength,
&TableEntryPoint,
&TableEntryPoint3,
&TableAddress,
&TableAddress3
);
if (EFI_ERROR (Status)) {
return Status;
}
} else {
TableEntryPoint = mOriginalSmbios;
TableEntryPoint3 = mOriginalSmbios3;
TableAddress = (VOID *)(UINTN) TableEntryPoint->TableAddress;
ZeroMem (TableEntryPoint, sizeof (SMBIOS_TABLE_ENTRY_POINT));
if (TableEntryPoint3 != NULL) {
TableAddress3 = (VOID *)(UINTN) TableEntryPoint3->TableAddress;
ZeroMem (TableEntryPoint3, sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT));
} else {
TableAddress3 = NULL;
}
}
CopyMem (
TableAddress,
SmbiosTable->Table,
TableLength
);
if (TableAddress3 != NULL && TableAddress3 != TableAddress) {
CopyMem (
TableAddress3,
SmbiosTable->Table,
TableLength
);
}
TableEntryPoint->AnchorString[0] = (UINT8) '_';
TableEntryPoint->AnchorString[1] = (UINT8) 'S';
TableEntryPoint->AnchorString[2] = (UINT8) 'M';
TableEntryPoint->AnchorString[3] = (UINT8) '_';
TableEntryPoint->EntryPointLength = sizeof (SMBIOS_TABLE_ENTRY_POINT);
TableEntryPoint->MajorVersion = 3;
TableEntryPoint->MinorVersion = 2;
TableEntryPoint->MaxStructureSize = SmbiosTable->MaxStructureSize;
TableEntryPoint->IntermediateAnchorString[0] = (UINT8) '_';
TableEntryPoint->IntermediateAnchorString[1] = (UINT8) 'D';
TableEntryPoint->IntermediateAnchorString[2] = (UINT8) 'M';
TableEntryPoint->IntermediateAnchorString[3] = (UINT8) 'I';
TableEntryPoint->IntermediateAnchorString[4] = (UINT8) '_';
TableEntryPoint->TableLength = TableLength;
TableEntryPoint->TableAddress = (UINT32)(UINTN) TableAddress;
TableEntryPoint->NumberOfSmbiosStructures = SmbiosTable->NumberOfStructures;
TableEntryPoint->SmbiosBcdRevision = 0x32;
TableEntryPoint->IntermediateChecksum = CalculateCheckSum8 (
(UINT8 *) TableEntryPoint + OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString),
TableEntryPoint->EntryPointLength - OFFSET_OF (SMBIOS_TABLE_ENTRY_POINT, IntermediateAnchorString)
);
TableEntryPoint->EntryPointStructureChecksum = CalculateCheckSum8 (
(UINT8 *) TableEntryPoint,
TableEntryPoint->EntryPointLength
);
if (TableEntryPoint3 != NULL) {
TableEntryPoint3->AnchorString[0] = (UINT8) '_';
TableEntryPoint3->AnchorString[1] = (UINT8) 'S';
TableEntryPoint3->AnchorString[2] = (UINT8) 'M';
TableEntryPoint3->AnchorString[3] = (UINT8) '3';
TableEntryPoint3->AnchorString[4] = (UINT8) '_';
TableEntryPoint3->EntryPointLength = sizeof (SMBIOS_TABLE_3_0_ENTRY_POINT);
TableEntryPoint3->MajorVersion = 3;
TableEntryPoint3->MinorVersion = 2;
TableEntryPoint3->EntryPointRevision = 1;
TableEntryPoint3->TableMaximumSize = TableLength;
TableEntryPoint3->TableAddress = (UINT64)(UINTN) TableAddress;
TableEntryPoint3->EntryPointStructureChecksum = CalculateCheckSum8 (
(UINT8 *) TableEntryPoint3,
TableEntryPoint3->EntryPointLength
);
}
DEBUG ((
DEBUG_INFO,
"Patched %08LX v%d.%d Table Address %08LX Length %04X %X %X\n",
(UINT64) TableEntryPoint,
TableEntryPoint->MajorVersion,
TableEntryPoint->MinorVersion,
(UINT64) TableEntryPoint->TableAddress,
TableEntryPoint->TableLength,
TableEntryPoint->EntryPointStructureChecksum,
TableEntryPoint->IntermediateChecksum
));
if (Mode == OcSmbiosUpdateOverwrite) {
SmbiosHandleLegacyRegion (FALSE);
} else {
if (TableEntryPoint3 != NULL) {
Status = gBS->InstallConfigurationTable (
&gEfiSmbios3TableGuid,
TableEntryPoint3
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "Failed to install v3 table - %r\n", Status));
}
}
Status = gBS->InstallConfigurationTable (
Mode == OcSmbiosUpdateCustom ? &gOcCustomSmbiosTableGuid : &gEfiSmbiosTableGuid,
TableEntryPoint
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "Failed to install v1 table - %r\n", Status));
return Status;
}
}
return EFI_SUCCESS;
}
/**
@retval EFI_SUCCESS The smbios tables were generated successfully
**/
EFI_STATUS
CreateSmbios (
IN OC_SMBIOS_DATA *Data,
IN OC_SMBIOS_UPDATE_MODE Mode,
IN OC_CPU_INFO *CpuInfo
)
{
EFI_STATUS Status;
OC_SMBIOS_TABLE SmbiosTable;
SMBIOS_HANDLE MemoryDeviceHandle;
APPLE_SMBIOS_STRUCTURE_POINTER MemoryDeviceInfo;
APPLE_SMBIOS_STRUCTURE_POINTER MemoryDeviceAddress;
UINT16 NumberMemoryDevices;
UINT16 NumberMemoryMapped;
UINT16 MemoryDeviceNo;
UINT16 MemoryMappedNo;
OC_SMBIOS_MAPPING *Mapping;
UINT16 MappingNum;
ASSERT (Data != NULL);
Status = SmbiosPrepareTable (&SmbiosTable);
if (EFI_ERROR (Status)) {
return Status;
}
Mapping = AllocatePool (OC_SMBIOS_MAX_MAPPING * sizeof (*Mapping));
if (Mapping == NULL) {
DEBUG ((DEBUG_WARN, "Cannot allocate mapping table\n"));
return EFI_OUT_OF_RESOURCES;
}
PatchBiosInformation (&SmbiosTable, Data);
PatchSystemInformation (&SmbiosTable, Data);
PatchBaseboardInformation (&SmbiosTable, Data);
PatchSystemEnclosure (&SmbiosTable, Data);
PatchProcessorInformation (&SmbiosTable, Data, CpuInfo);
PatchCacheInformation (&SmbiosTable, Data);
PatchSystemPorts (&SmbiosTable, Data);
PatchSystemSlots (&SmbiosTable, Data);
PatchMemoryArray (&SmbiosTable, Data);
PatchMemoryMappedAddress (&SmbiosTable, Data, Mapping, &MappingNum);
NumberMemoryDevices = SmbiosGetOriginalStructureCount (SMBIOS_TYPE_MEMORY_DEVICE);
NumberMemoryMapped = SmbiosGetOriginalStructureCount (SMBIOS_TYPE_MEMORY_DEVICE_MAPPED_ADDRESS);
for (MemoryDeviceNo = 1; MemoryDeviceNo <= NumberMemoryDevices; MemoryDeviceNo++) {
MemoryDeviceInfo = SmbiosGetOriginalStructure (SMBIOS_TYPE_MEMORY_DEVICE, MemoryDeviceNo);
if (MemoryDeviceInfo.Raw == NULL) {
continue;
}
//
// For each memory device we must generate type 17
//
PatchMemoryDevice (
&SmbiosTable,
Data,
MemoryDeviceInfo,
MemoryDeviceNo,
&MemoryDeviceHandle
);
//
// For each occupied memory device we must generate type 20
//
for (MemoryMappedNo = 1; MemoryMappedNo <= NumberMemoryMapped; MemoryMappedNo++) {
MemoryDeviceAddress = SmbiosGetOriginalStructure (SMBIOS_TYPE_MEMORY_DEVICE_MAPPED_ADDRESS, MemoryMappedNo);
if (MemoryDeviceAddress.Raw != NULL
&& SMBIOS_ACCESSIBLE (MemoryDeviceAddress, Standard.Type20->MemoryDeviceHandle)
&& MemoryDeviceAddress.Standard.Type20->MemoryDeviceHandle ==
MemoryDeviceInfo.Standard.Type17->Hdr.Handle) {
PatchMemoryMappedDevice (
&SmbiosTable,
Data,
MemoryDeviceAddress,
MemoryMappedNo,
MemoryDeviceHandle,
Mapping,
MappingNum
);
}
}
}
PatchPortableBatteryDevice (&SmbiosTable, Data);
PatchBootInformation (&SmbiosTable, Data);
CreateAppleProcessorType (&SmbiosTable, Data, CpuInfo);
CreateAppleProcessorSpeed (&SmbiosTable, Data, CpuInfo);
CreateAppleFirmwareVolume (&SmbiosTable, Data);
CreateSmBiosEndOfTable (&SmbiosTable, Data);
FreePool (Mapping);
Status = SmbiosTableApply (&SmbiosTable, Mode);
SmbiosTableFree (&SmbiosTable);
return Status;
}