mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-26 16:47:40 +01:00
2333 lines
93 KiB
C++
2333 lines
93 KiB
C++
/**
|
|
smbios.c
|
|
original idea of SMBIOS patching by mackerintel
|
|
implementation for UEFI smbios table patching
|
|
Slice 2011.
|
|
|
|
portion copyright Intel
|
|
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
|
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.
|
|
|
|
Module Name:
|
|
|
|
SmbiosGen.c
|
|
**/
|
|
|
|
#define DONT_DEFINE_GLOBALS
|
|
|
|
#include <Platform.h> // Only use angled for Platform, else, xcode project won't compile
|
|
#include <Efi.h>
|
|
|
|
#include "smbios.h"
|
|
#include "platformdata.h"
|
|
#include "AcpiPatcher.h"
|
|
#include "guid.h"
|
|
#include "../Platform/CloverVersion.h"
|
|
|
|
#ifndef DEBUG_ALL
|
|
#define DEBUG_SMBIOS 1
|
|
#else
|
|
#define DEBUG_SMBIOS DEBUG_ALL
|
|
#endif
|
|
|
|
#if DEBUG_SMBIOS == 0
|
|
#define DBG(...)
|
|
#else
|
|
#define DBG(...) DebugLog(DEBUG_SMBIOS, __VA_ARGS__)
|
|
#endif
|
|
|
|
#define REMAP_SMBIOS_TABLE_GUID { 0xeb9d2d35, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } }
|
|
|
|
#define MAX_OEM_STRING 256
|
|
|
|
#define ROUND_PAGE(x) ((((unsigned)(x)) + EFI_PAGE_SIZE - 1) & ~(EFI_PAGE_SIZE - 1))
|
|
|
|
|
|
|
|
EFI_GUID *gTableGuidArray[] = {&gEfiSmbiosTableGuid, &gEfiSmbios3TableGuid};
|
|
|
|
constexpr LString8 unknown = "unknown"_XS8;
|
|
|
|
SmbiosDiscoveredSettings g_SmbiosDiscoveredSettings;
|
|
SmbiosInjectedSettings g_SmbiosInjectedSettings;
|
|
const RAM_SLOT_INFO nullRAM_SLOT_INFO;
|
|
const SLOT_DEVICE nullSLOT_DEVICE;
|
|
|
|
//
|
|
// syscl: implement Dell truncate fix
|
|
// remap EFI_SMBIOS_TABLE_1 to new guid to fix Dell
|
|
// SMBIOS Table 1 truncate issue credit David Passmore
|
|
//
|
|
EFI_GUID gRemapEfiSmbiosTableGuid = REMAP_SMBIOS_TABLE_GUID;
|
|
|
|
//EFI_PHYSICAL_ADDRESS *smbiosTable;
|
|
void *Smbios; //pointer to SMBIOS data
|
|
SMBIOS_TABLE_ENTRY_POINT *EntryPoint; //SmbiosEps original
|
|
SMBIOS_TABLE_ENTRY_POINT *SmbiosEpsNew; //new SmbiosEps
|
|
//for patching
|
|
APPLE_SMBIOS_STRUCTURE_POINTER SmbiosTable;
|
|
APPLE_SMBIOS_STRUCTURE_POINTER newSmbiosTable;
|
|
UINT16 NumberOfRecords;
|
|
UINT16 MaxStructureSize;
|
|
UINT8* Current; //pointer to the current end of tables
|
|
EFI_SMBIOS_TABLE_HEADER *Record;
|
|
EFI_SMBIOS_HANDLE Handle;
|
|
EFI_SMBIOS_TYPE Type;
|
|
|
|
UINTN stringNumber;
|
|
UINTN TableSize;
|
|
UINT16 CoreCache = 0;
|
|
UINT16 L1, L2, L3;
|
|
UINT32 MaxMemory = 0;
|
|
UINT32 mTotalSystemMemory;
|
|
UINT64 gTotalMemory;
|
|
UINT16 mHandle3;
|
|
UINT16 mHandle16 = 0x1000;
|
|
UINT16 mHandle17[MAX_RAM_SLOTS];
|
|
UINT16 mHandle19;
|
|
UINT16 mMemory17[MAX_RAM_SLOTS];
|
|
UINT64 mInstalled[MAX_RAM_SLOTS];
|
|
UINT64 mEnabled[MAX_RAM_SLOTS];
|
|
BOOLEAN gMobile;
|
|
UINT8 gBootStatus;
|
|
BOOLEAN Once;
|
|
|
|
MEM_STRUCTURE gRAM;
|
|
|
|
|
|
#define MAX_HANDLE 0xFEFF
|
|
#define SMBIOS_PTR SIGNATURE_32('_','S','M','_')
|
|
#define MAX_TABLE_SIZE 512
|
|
|
|
#define smbios_offsetof(s,m) ( (SMBIOS_TABLE_STRING) ((UINT8*)&((s*)0)->m - (UINT8*)0))
|
|
|
|
SMBIOS_TABLE_STRING SMBIOS_TABLE_TYPE0_STR_IDX[] = {
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE0, Vendor),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE0, BiosVersion),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE0, BiosReleaseDate),
|
|
0x00
|
|
}; // offsets of structures that values are strings for type 0 Bios
|
|
|
|
SMBIOS_TABLE_STRING SMBIOS_TABLE_TYPE1_STR_IDX[] = {
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE1, Manufacturer),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE1, ProductName),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE1, Version),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE1, SerialNumber),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE1, SKUNumber),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE1, Family),
|
|
0x00
|
|
}; // offsets of structures that values are strings for type 1 System
|
|
|
|
SMBIOS_TABLE_STRING SMBIOS_TABLE_TYPE2_STR_IDX[] = {
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE2, Manufacturer),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE2, ProductName),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE2, Version),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE2, SerialNumber),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE2, AssetTag),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE2, LocationInChassis),
|
|
0x00
|
|
}; // offsets of structures that values are strings for type 2 BaseBoard
|
|
|
|
SMBIOS_TABLE_STRING SMBIOS_TABLE_TYPE3_STR_IDX[] = {
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE3, Manufacturer),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE3, Version),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE3, SerialNumber),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE3, AssetTag),
|
|
0x00
|
|
}; // offsets of structures that values are strings for type 3 Chassis
|
|
|
|
SMBIOS_TABLE_STRING SMBIOS_TABLE_TYPE4_STR_IDX[] = {
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE4, Socket),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE4, ProcessorManufacture),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE4, ProcessorVersion),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE4, SerialNumber),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE4, AssetTag),
|
|
smbios_offsetof(SMBIOS_TABLE_TYPE4, PartNumber),
|
|
0x00
|
|
}; // offsets of structures that values are strings for type 3 Chassis
|
|
|
|
/* Functions */
|
|
|
|
// validate the SMBIOS entry point structure
|
|
BOOLEAN IsEntryPointStructureValid (IN SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure)
|
|
{
|
|
UINTN I;
|
|
UINT8 Length;
|
|
UINT8 Checksum = 0;
|
|
UINT8 *BytePtr;
|
|
|
|
if (!EntryPointStructure)
|
|
return FALSE;
|
|
|
|
BytePtr = (UINT8*) EntryPointStructure;
|
|
Length = EntryPointStructure->EntryPointLength;
|
|
|
|
for (I = 0; I < Length; I++) {
|
|
Checksum = Checksum + (UINT8) BytePtr[I];
|
|
}
|
|
|
|
// a valid SMBIOS EPS must have checksum of 0
|
|
return (Checksum == 0);
|
|
}
|
|
|
|
void* FindOemSMBIOSPtr (void)
|
|
{
|
|
UINTN Address;
|
|
|
|
// Search 0x0f0000 - 0x0fffff for SMBIOS Ptr
|
|
for (Address = 0xf0000; Address < 0xfffff; Address += 0x10) {
|
|
if (*(UINT32 *)(Address) == SMBIOS_PTR && IsEntryPointStructureValid((SMBIOS_TABLE_ENTRY_POINT*)Address)) {
|
|
return (void *)Address;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void* GetSmbiosTablesFromHob (void)
|
|
{
|
|
EFI_PHYSICAL_ADDRESS *Table;
|
|
EFI_PEI_HOB_POINTERS GuidHob;
|
|
|
|
GuidHob.Raw = (__typeof_am__(GuidHob.Raw))GetFirstGuidHob (&gEfiSmbiosTableGuid);
|
|
if (GuidHob.Raw != NULL) {
|
|
Table = (__typeof__(Table))GET_GUID_HOB_DATA (GuidHob.Guid);
|
|
if (Table != NULL) {
|
|
return (void *)(UINTN)*Table;
|
|
}
|
|
}
|
|
GuidHob.Raw = (__typeof_am__(GuidHob.Raw))GetFirstGuidHob (&gEfiSmbios3TableGuid);
|
|
if (GuidHob.Raw != NULL) {
|
|
Table = (__typeof_am__(Table))GET_GUID_HOB_DATA (GuidHob.Guid);
|
|
if (Table != NULL) {
|
|
return (void *)(UINTN)*Table;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void* GetSmbiosTablesFromConfigTables (void)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_PHYSICAL_ADDRESS *Table;
|
|
|
|
Status = EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid, (void **)&Table);
|
|
if (EFI_ERROR(Status) || Table == NULL) {
|
|
Table = NULL;
|
|
Status = EfiGetSystemConfigurationTable (&gEfiSmbios3TableGuid, (void **)&Table);
|
|
if (EFI_ERROR(Status)) {
|
|
Table = NULL;
|
|
}
|
|
}
|
|
return Table;
|
|
}
|
|
|
|
// This function determines ascii string length ending by space.
|
|
// search restricted to MaxLen, for example
|
|
// iStrLen("ABC ", 20) == 3
|
|
// if MaxLen=0 then as usual strlen but bugless
|
|
UINTN iStrLen(CONST CHAR8* String, UINTN MaxLen)
|
|
{
|
|
UINTN Len = 0;
|
|
CONST CHAR8* BA;
|
|
if(MaxLen > 0) {
|
|
for (Len=0; Len<MaxLen; Len++) {
|
|
if (String[Len] == 0) {
|
|
break;
|
|
}
|
|
}
|
|
BA = &String[Len - 1];
|
|
while ((Len != 0) && ((*BA == ' ') || (*BA == 0))) {
|
|
BA--; Len--;
|
|
}
|
|
} else {
|
|
BA = String;
|
|
while(*BA){BA++; Len++;}
|
|
}
|
|
return Len;
|
|
}
|
|
|
|
|
|
// Internal functions for flat SMBIOS
|
|
|
|
UINT16 SmbiosTableLength (APPLE_SMBIOS_STRUCTURE_POINTER SmbiosTableN)
|
|
{
|
|
CHAR8 *AChar;
|
|
UINT16 Length;
|
|
|
|
AChar = (CHAR8 *)(SmbiosTableN.Raw + SmbiosTableN.Hdr->Length);
|
|
while ((*AChar != 0) || (*(AChar + 1) != 0)) {
|
|
AChar ++; //stop at 00 - first 0
|
|
}
|
|
Length = (UINT16)((UINTN)AChar - (UINTN)SmbiosTableN.Raw + 2); //length includes 00
|
|
return Length;
|
|
}
|
|
|
|
|
|
EFI_SMBIOS_HANDLE LogSmbiosTable (APPLE_SMBIOS_STRUCTURE_POINTER SmbiosTableN)
|
|
{
|
|
UINT16 Length = SmbiosTableLength(SmbiosTableN);
|
|
if (Length > MaxStructureSize) {
|
|
MaxStructureSize = Length;
|
|
}
|
|
CopyMem(Current, SmbiosTableN.Raw, Length);
|
|
Current += Length;
|
|
NumberOfRecords++;
|
|
return SmbiosTableN.Hdr->Handle;
|
|
}
|
|
|
|
// the procedure insert Buffer into SmbiosTable by copy and update Field
|
|
// the Buffer restricted by zero or by space
|
|
EFI_STATUS UpdateSmbiosString(OUT APPLE_SMBIOS_STRUCTURE_POINTER SmbiosTableN,
|
|
SMBIOS_TABLE_STRING* Field, const XString8& Buffer)
|
|
{
|
|
CHAR8* AString;
|
|
CHAR8* C1; //pointers for copy
|
|
CHAR8* C2;
|
|
UINTN Length = SmbiosTableLength(SmbiosTableN);
|
|
UINTN ALength, BLength;
|
|
UINT8 IndexStr = 1;
|
|
|
|
if ((SmbiosTableN.Raw == NULL) || Buffer.isEmpty() || !Field) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
AString = (CHAR8*)(SmbiosTableN.Raw + SmbiosTableN.Hdr->Length); //first string
|
|
while (IndexStr != *Field) {
|
|
if (*AString) {
|
|
IndexStr++;
|
|
}
|
|
while (*AString != 0) AString++; //skip string at index
|
|
AString++; //next string
|
|
if (*AString == 0) {
|
|
//this is end of the table
|
|
if (*Field == 0) {
|
|
AString[1] = 0; //one more zero
|
|
}
|
|
*Field = IndexStr; //index of the next string that is empty
|
|
if (IndexStr == 1) {
|
|
AString--; //first string has no leading zero
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
// AString is at place to copy
|
|
ALength = iStrLen(AString, 0);
|
|
BLength = iStrLen(Buffer.c_str(), MAX_OEM_STRING);
|
|
// DBG("Table type %d field %d\n", SmbiosTable.Hdr->Type, *Field);
|
|
// DBG("Old string length=%d new length=%d\n", ALength, BLength);
|
|
if (BLength > ALength) {
|
|
//Shift right
|
|
C1 = (CHAR8*)SmbiosTableN.Raw + Length; //old end
|
|
C2 = C1 + BLength - ALength; //new end
|
|
*C2 = 0;
|
|
while (C1 != AString) *(--C2) = *(--C1);
|
|
|
|
} else if (BLength < ALength) {
|
|
//Shift left
|
|
C1 = AString + ALength; //old start
|
|
C2 = AString + BLength; //new start
|
|
while (C1 != ((CHAR8*)SmbiosTableN.Raw + Length)) {
|
|
*C2++ = *C1++;
|
|
}
|
|
*C2 = 0;
|
|
*(--C2) = 0; //end of table
|
|
}
|
|
//DBG("UpdateSmbiosString() -> CopyMem %s %lld\n", Buffer.c_str(), BLength);
|
|
CopyMem(AString, Buffer.c_str(), BLength);
|
|
*(AString + BLength) = 0; // not sure there is 0
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
APPLE_SMBIOS_STRUCTURE_POINTER GetSmbiosTableFromType (SMBIOS_TABLE_ENTRY_POINT *SmbiosPoint,
|
|
UINT8 SmbiosType, UINTN IndexTable)
|
|
{
|
|
APPLE_SMBIOS_STRUCTURE_POINTER SmbiosTableN;
|
|
UINTN SmbiosTypeIndex;
|
|
|
|
SmbiosTypeIndex = 0;
|
|
SmbiosTableN.Raw = (UINT8 *)((UINTN)SmbiosPoint->TableAddress);
|
|
if (SmbiosTableN.Raw == NULL) {
|
|
return SmbiosTableN;
|
|
}
|
|
while ((SmbiosTypeIndex != IndexTable) || (SmbiosTableN.Hdr->Type != SmbiosType)) {
|
|
if (SmbiosTableN.Hdr->Type == SMBIOS_TYPE_END_OF_TABLE) {
|
|
SmbiosTableN.Raw = NULL;
|
|
return SmbiosTableN;
|
|
}
|
|
if (SmbiosTableN.Hdr->Type == SmbiosType) {
|
|
SmbiosTypeIndex++;
|
|
}
|
|
SmbiosTableN.Raw = (UINT8 *)(SmbiosTableN.Raw + SmbiosTableLength (SmbiosTableN));
|
|
}
|
|
return SmbiosTableN;
|
|
}
|
|
|
|
CHAR8* GetSmbiosString (APPLE_SMBIOS_STRUCTURE_POINTER SmbiosTableN, SMBIOS_TABLE_STRING StringN)
|
|
{
|
|
CHAR8 *AString;
|
|
UINT8 Ind;
|
|
|
|
Ind = 1;
|
|
AString = (CHAR8 *)(SmbiosTableN.Raw + SmbiosTableN.Hdr->Length); //first string
|
|
while (Ind != StringN) {
|
|
while (*AString != 0) {
|
|
AString ++;
|
|
}
|
|
AString ++; //skip zero ending
|
|
if (*AString == 0) {
|
|
return AString; //this is end of the table
|
|
}
|
|
Ind++;
|
|
}
|
|
|
|
return AString; //return pointer to Ascii string
|
|
}
|
|
|
|
void AddSmbiosEndOfTable()
|
|
{
|
|
SMBIOS_STRUCTURE* StructurePtr = (SMBIOS_STRUCTURE*)Current;
|
|
StructurePtr->Type = SMBIOS_TYPE_END_OF_TABLE;
|
|
StructurePtr->Length = sizeof(SMBIOS_STRUCTURE);
|
|
StructurePtr->Handle = SMBIOS_TYPE_INACTIVE; //spec 2.7 p.120
|
|
Current += sizeof(SMBIOS_STRUCTURE);
|
|
*Current++ = 0;
|
|
*Current++ = 0; //double 0 at the end
|
|
NumberOfRecords++;
|
|
}
|
|
|
|
void UniquifySmbiosTableStr (APPLE_SMBIOS_STRUCTURE_POINTER SmbiosTableN, SMBIOS_TABLE_STRING* str_idx)
|
|
{
|
|
INTN i, j;
|
|
SMBIOS_TABLE_STRING cmp_idx;
|
|
SMBIOS_TABLE_STRING cmp_str;
|
|
SMBIOS_TABLE_STRING ref_str;
|
|
|
|
if (0 == str_idx[0]) return; // SMBIOS doesn't have string structures, just return;
|
|
for (i = 1; ;i++) {
|
|
cmp_idx = str_idx[i];
|
|
if (0 == cmp_idx) break;
|
|
cmp_str = SmbiosTableN.Raw[cmp_idx];
|
|
if (0 == cmp_str) continue; // if string is undefine, continue
|
|
for (j = 0; j < i; j++) {
|
|
ref_str = SmbiosTableN.Raw[str_idx[j]];
|
|
if (cmp_str == ref_str) {
|
|
SmbiosTableN.Raw[cmp_idx] = 0; // pretend the string doesn't exist
|
|
// UpdateSmbiosString(SmbiosTableN, &SmbiosTableN.Raw[cmp_idx], GetSmbiosString(SmbiosTableN, ref_str));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Patching Functions */
|
|
void PatchTableType0(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
// BIOS information
|
|
//
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_BIOS_INFORMATION, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
// DBG("SmbiosTable: Type 0 (Bios Information) not found!\n");
|
|
return;
|
|
}
|
|
TableSize = SmbiosTableLength(SmbiosTable);
|
|
ZeroMem((void*)newSmbiosTable.Type0, MAX_TABLE_SIZE);
|
|
CopyMem((void*)newSmbiosTable.Type0, (void*)SmbiosTable.Type0, TableSize); //can't point to union
|
|
/* Real Mac
|
|
BIOS Information (Type 0)
|
|
Raw Data:
|
|
Header and Data:
|
|
00 18 2E 00 01 02 00 00 03 7F 80 98 01 00 00 00
|
|
00 00 C1 02 00 01 FF FF
|
|
Strings:
|
|
Apple Inc.
|
|
MBP81.88Z.0047.B22.1109281426
|
|
09/28/11
|
|
|
|
*/
|
|
newSmbiosTable.Type0->BiosSegment = 0; //like in Mac
|
|
newSmbiosTable.Type0->SystemBiosMajorRelease = 0;
|
|
newSmbiosTable.Type0->SystemBiosMinorRelease = 1;
|
|
// newSmbiosTable.Type0->BiosCharacteristics.BiosCharacteristicsNotSupported = 0;
|
|
// newSmbiosTable.Type0->BIOSCharacteristicsExtensionBytes[1] |= 8; //UefiSpecificationSupported;
|
|
//Slice: ----------------------
|
|
//there is a bug in AppleSMBIOS-42 v1.7
|
|
//to eliminate this I have to zero first byte in the field
|
|
*(UINT8*)&newSmbiosTable.Type0->BiosCharacteristics = 0;
|
|
//dunno about latest version but there is a way to set good characteristics
|
|
//if use patched AppleSMBIOS
|
|
//----------------
|
|
Once = TRUE;
|
|
|
|
UniquifySmbiosTableStr(newSmbiosTable, SMBIOS_TABLE_TYPE0_STR_IDX);
|
|
|
|
if ( smbiosSettings.BiosVendor.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type0->Vendor, smbiosSettings.BiosVendor);
|
|
}
|
|
if( smbiosSettings.BiosVersionUsed.notEmpty() ) {
|
|
if( smbiosSettings.EfiVersionUsed.notEmpty() ) {
|
|
DBG("UpdateSmbiosString : BiosVersion=EfiVersion=%s\n", smbiosSettings.EfiVersionUsed.c_str());
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type0->BiosVersion, smbiosSettings.EfiVersionUsed);
|
|
} else {
|
|
DBG("UpdateSmbiosString : BiosVersion=RomVersion=%s\n", smbiosSettings.BiosVersionUsed.c_str());
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type0->BiosVersion, smbiosSettings.BiosVersionUsed);
|
|
}
|
|
}else{
|
|
DBG("UpdateSmbiosString : BiosVersion no update\n");
|
|
}
|
|
if( smbiosSettings.ReleaseDateUsed.notEmpty() ) {
|
|
DBG("UpdateSmbiosString : ReleaseDate=%s\n", smbiosSettings.ReleaseDateUsed.c_str());
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type0->BiosReleaseDate, smbiosSettings.ReleaseDateUsed);
|
|
}else{
|
|
DBG("UpdateSmbiosString : ReleaseDate no update\n");
|
|
}
|
|
Handle = LogSmbiosTable(newSmbiosTable);
|
|
}
|
|
|
|
void GetTableType1(SmbiosDiscoveredSettings* smbiosSettings)
|
|
{
|
|
CHAR8* s;
|
|
// System Information
|
|
//
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_SYSTEM_INFORMATION, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
DBG("SmbiosTable: Type 1 (System Information) not found!\n");
|
|
return;
|
|
}
|
|
|
|
//smbiosSettings.SmUUID = GuidLEToXString8(SmbiosTable.Type1->Uuid); // is this is a bug, this uuid might be BE, not LE, or should we use the "variant" field
|
|
s = GetSmbiosString(SmbiosTable, SmbiosTable.Type1->ProductName);
|
|
smbiosSettings->OEMProductFromSmbios.strncpy(s, iStrLen(s, 64)); //strncpy take care of ending zero
|
|
|
|
return;
|
|
}
|
|
XString8 getSmUUIDFromSmbios()
|
|
{
|
|
// System Information
|
|
//
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_SYSTEM_INFORMATION, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
DBG("SmbiosTable: Type 1 (System Information) not found!\n");
|
|
return nullGuidAsString;
|
|
}
|
|
|
|
// XString8 g = GuidBeToXString8(SmbiosTable.Type1->Uuid); // should we use the "variant" field to know if it's LE or BE
|
|
XString8 g = GuidLEToXString8(SmbiosTable.Type1->Uuid); // 2021-04 : this is a bug, the UUID will be swapped (read as a LE, sent as a BE). I leave for now because it doesn't really matter.
|
|
return g;
|
|
}
|
|
|
|
void PatchTableType1(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
// System Information
|
|
//
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_SYSTEM_INFORMATION, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
return;
|
|
}
|
|
|
|
//Increase table size
|
|
UINTN Size = SmbiosTable.Type1->Hdr.Length; //old size
|
|
TableSize = SmbiosTableLength(SmbiosTable); //including strings
|
|
UINTN NewSize = 27; //sizeof(SMBIOS_TABLE_TYPE1);
|
|
ZeroMem((void*)newSmbiosTable.Type1, MAX_TABLE_SIZE);
|
|
CopyMem((void*)newSmbiosTable.Type1, (void*)SmbiosTable.Type1, Size); //copy main table
|
|
CopyMem((CHAR8*)newSmbiosTable.Type1+NewSize, (CHAR8*)SmbiosTable.Type1+Size, TableSize - Size); //copy strings
|
|
newSmbiosTable.Type1->Hdr.Length = (UINT8)NewSize;
|
|
|
|
UniquifySmbiosTableStr(newSmbiosTable, SMBIOS_TABLE_TYPE1_STR_IDX);
|
|
|
|
newSmbiosTable.Type1->WakeUpType = SystemWakeupTypePowerSwitch;
|
|
Once = TRUE;
|
|
|
|
EFI_GUID SmUUID;
|
|
// macOs take all guid as BE guid, irrespective to the variant.
|
|
StrToGuidBE(smbiosSettings.SmUUID, &SmUUID);
|
|
if((SmUUID.Data3 & 0xF000) != 0) {
|
|
CopyMem((void*)&newSmbiosTable.Type1->Uuid, (void*)&SmUUID, sizeof(SmUUID));
|
|
}
|
|
|
|
if( smbiosSettings.ManufactureName.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type1->Manufacturer, smbiosSettings.ManufactureName);
|
|
}
|
|
if( smbiosSettings.ProductName.notEmpty() ){
|
|
DBG("%s : UpdateSmbiosString ProductName=%s\n", __PRETTY_FUNCTION__, smbiosSettings.ProductName.c_str());
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type1->ProductName, smbiosSettings.ProductName);
|
|
}
|
|
if( smbiosSettings.SystemVersion.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type1->Version, smbiosSettings.SystemVersion);
|
|
}
|
|
if( smbiosSettings.SerialNr.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type1->SerialNumber, smbiosSettings.SerialNr);
|
|
//DBG("%s : UpdateSmbiosString SerialNr=%s\n", __PRETTY_FUNCTION__, smbiosSettings.SerialNr.c_str());
|
|
}
|
|
if( smbiosSettings.BoardNumber.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type1->SKUNumber, smbiosSettings.BoardNumber); //iMac17,1 - there is nothing
|
|
}
|
|
if( smbiosSettings.FamilyName.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type1->Family, smbiosSettings.FamilyName);
|
|
}
|
|
|
|
Handle = LogSmbiosTable(newSmbiosTable);
|
|
return;
|
|
}
|
|
|
|
void GetTableType2(SmbiosDiscoveredSettings* smbiosSettings)
|
|
{
|
|
CHAR8* s;
|
|
// System Information
|
|
//
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
return;
|
|
}
|
|
|
|
s = GetSmbiosString(SmbiosTable, SmbiosTable.Type2->ProductName);
|
|
smbiosSettings->OEMBoardFromSmbios.strncpy(s, iStrLen(s, 64) + 1);
|
|
s = GetSmbiosString(SmbiosTable, SmbiosTable.Type2->Manufacturer);
|
|
smbiosSettings->OEMVendorFromSmbios.strncpy(s, iStrLen(s, 64) + 1);
|
|
}
|
|
|
|
|
|
void PatchTableType2(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
// BaseBoard Information
|
|
//
|
|
UINTN NewSize = 0x10; //sizeof(SMBIOS_TABLE_TYPE2);
|
|
ZeroMem((void*)newSmbiosTable.Type2, MAX_TABLE_SIZE);
|
|
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
MsgLog("SmbiosTable: Type 2 (BaseBoard Information) not found, create new\n");
|
|
//Create new one
|
|
newSmbiosTable.Type2->Hdr.Type = 2;
|
|
newSmbiosTable.Type2->Hdr.Handle = 0x0200; //common rule
|
|
|
|
} else {
|
|
UINTN Size = SmbiosTable.Type2->Hdr.Length; //old size
|
|
TableSize = SmbiosTableLength(SmbiosTable); //including strings
|
|
|
|
if (NewSize > Size) {
|
|
CopyMem((void*)newSmbiosTable.Type2, (void*)SmbiosTable.Type2, Size); //copy main table
|
|
CopyMem((CHAR8*)newSmbiosTable.Type2 + NewSize, (CHAR8*)SmbiosTable.Type2 + Size, TableSize - Size); //copy strings
|
|
} else {
|
|
CopyMem((void*)newSmbiosTable.Type2, (void*)SmbiosTable.Type2, TableSize); //copy full table
|
|
}
|
|
}
|
|
|
|
newSmbiosTable.Type2->Hdr.Length = (UINT8)NewSize;
|
|
newSmbiosTable.Type2->ChassisHandle = mHandle3; //from GetTableType3
|
|
newSmbiosTable.Type2->BoardType = smbiosSettings.BoardType;
|
|
ZeroMem((void*)&newSmbiosTable.Type2->FeatureFlag, sizeof(BASE_BOARD_FEATURE_FLAGS));
|
|
newSmbiosTable.Type2->FeatureFlag.Motherboard = 1;
|
|
newSmbiosTable.Type2->FeatureFlag.Replaceable = 1;
|
|
if (smbiosSettings.BoardType == 11) {
|
|
newSmbiosTable.Type2->FeatureFlag.Removable = 1;
|
|
}
|
|
Once = TRUE;
|
|
|
|
UniquifySmbiosTableStr(newSmbiosTable, SMBIOS_TABLE_TYPE2_STR_IDX);
|
|
|
|
if( smbiosSettings.BoardManufactureName.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type2->Manufacturer, smbiosSettings.BoardManufactureName);
|
|
}
|
|
if( smbiosSettings.BoardNumber.notEmpty() ){
|
|
DBG("%s : UpdateSmbiosString ProductName=BoardNumber=%s\n", __PRETTY_FUNCTION__, smbiosSettings.BoardNumber.c_str());
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type2->ProductName, smbiosSettings.BoardNumber);
|
|
}
|
|
if( smbiosSettings.BoardVersion.notEmpty() ){
|
|
DBG("%s : UpdateSmbiosString Version=BoardVersion=%s\n", __PRETTY_FUNCTION__, smbiosSettings.BoardVersion.c_str());
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type2->Version, smbiosSettings.BoardVersion); //iMac17,1 - there is ProductName
|
|
}
|
|
if( smbiosSettings.BoardSerialNumber.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type2->SerialNumber, smbiosSettings.BoardSerialNumber);
|
|
}
|
|
if( smbiosSettings.LocationInChassis.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type2->LocationInChassis, smbiosSettings.LocationInChassis);
|
|
}
|
|
//what about Asset Tag??? Not used in real mac. till now.
|
|
|
|
//Slice - for the table2 one patch more needed
|
|
/* spec
|
|
Field 0x0E - Identifies the number (0 to 255) of Contained Object Handles that follow
|
|
Field 0x0F - A list of handles of other structures (for example, Baseboard, Processor, Port, System Slots, Memory Device) that are contained by this baseboard
|
|
It may be good before our patching but changed after. We should at least check if all tables mentioned here are present in final structure
|
|
I just set 0 as in iMac11
|
|
*/
|
|
newSmbiosTable.Type2->NumberOfContainedObjectHandles = 0;
|
|
|
|
Handle = LogSmbiosTable(newSmbiosTable);
|
|
return;
|
|
}
|
|
|
|
bool getMobileFromSmbios()
|
|
{
|
|
// System Chassis Information
|
|
//
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
//DBG("SmbiosTable: Type 3 (System Chassis Information) not found!\n");
|
|
return false;
|
|
}
|
|
mHandle3 = SmbiosTable.Type3->Hdr.Handle;
|
|
return ((SmbiosTable.Type3->Type) >= 8) && (SmbiosTable.Type3->Type != 0x0D); //iMac is desktop!
|
|
}
|
|
|
|
void GetTableType3(SmbiosDiscoveredSettings* smbiosSettings)
|
|
{
|
|
// System Chassis Information
|
|
//
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
DBG("SmbiosTable: Type 3 (System Chassis Information) not found!\n");
|
|
gMobile = FALSE; //default value
|
|
return;
|
|
}
|
|
mHandle3 = SmbiosTable.Type3->Hdr.Handle;
|
|
gMobile = ((SmbiosTable.Type3->Type) >= 8) && (SmbiosTable.Type3->Type != 0x0D); //iMac is desktop!
|
|
|
|
return;
|
|
}
|
|
|
|
void PatchTableType3(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
// System Chassis Information
|
|
//
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
// DBG("SmbiosTable: Type 3 (System Chassis Information) not found!\n");
|
|
return;
|
|
}
|
|
UINTN Size = SmbiosTable.Type3->Hdr.Length; //old size
|
|
TableSize = SmbiosTableLength(SmbiosTable); //including strings
|
|
UINTN NewSize = 0x15; //sizeof(SMBIOS_TABLE_TYPE3);
|
|
ZeroMem((void*)newSmbiosTable.Type3, MAX_TABLE_SIZE);
|
|
|
|
if (NewSize > Size) {
|
|
CopyMem((void*)newSmbiosTable.Type3, (void*)SmbiosTable.Type3, Size); //copy main table
|
|
CopyMem((CHAR8*)newSmbiosTable.Type3 + NewSize, (CHAR8*)SmbiosTable.Type3 + Size, TableSize - Size); //copy strings
|
|
newSmbiosTable.Type3->Hdr.Length = (UINT8)NewSize;
|
|
} else {
|
|
CopyMem((void*)newSmbiosTable.Type3, (void*)SmbiosTable.Type3, TableSize); //copy full table
|
|
}
|
|
|
|
newSmbiosTable.Type3->BootupState = ChassisStateSafe;
|
|
newSmbiosTable.Type3->PowerSupplyState = ChassisStateSafe;
|
|
newSmbiosTable.Type3->ThermalState = ChassisStateOther;
|
|
newSmbiosTable.Type3->SecurityStatus = ChassisSecurityStatusOther; //ChassisSecurityStatusNone;
|
|
newSmbiosTable.Type3->NumberofPowerCords = 1;
|
|
newSmbiosTable.Type3->ContainedElementCount = 0;
|
|
newSmbiosTable.Type3->ContainedElementRecordLength = 0;
|
|
Once = TRUE;
|
|
|
|
UniquifySmbiosTableStr(newSmbiosTable, SMBIOS_TABLE_TYPE3_STR_IDX);
|
|
|
|
if (smbiosSettings.ChassisType != 0) {
|
|
newSmbiosTable.Type3->Type = smbiosSettings.ChassisType;
|
|
}
|
|
|
|
if( smbiosSettings.ChassisManufacturer.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type3->Manufacturer, smbiosSettings.ChassisManufacturer);
|
|
}
|
|
//SIC! According to iMac there must be the BoardNumber
|
|
if( smbiosSettings.BoardNumber.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type3->Version, smbiosSettings.BoardNumber);
|
|
}
|
|
if( smbiosSettings.SerialNr.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type3->SerialNumber, smbiosSettings.SerialNr);
|
|
//DBG("%s : UpdateSmbiosString SerialNr=%s\n", __PRETTY_FUNCTION__, smbiosSettings.SerialNr.c_str());
|
|
}
|
|
if( smbiosSettings.ChassisAssetTag.notEmpty() ){
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type3->AssetTag, smbiosSettings.ChassisAssetTag);
|
|
}
|
|
|
|
Handle = LogSmbiosTable(newSmbiosTable);
|
|
return;
|
|
}
|
|
|
|
void GetTableType4(SmbiosDiscoveredSettings* smbiosSettings)
|
|
{
|
|
// Processor Information
|
|
//
|
|
INTN res = 0;
|
|
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
DBG("SmbiosTable: Type 4 (Processor Information) not found!\n");
|
|
return;
|
|
}
|
|
|
|
res = (SmbiosTable.Type4->ExternalClock * 3 + 2) % 100;
|
|
if (res > 2) {
|
|
res = 0;
|
|
} else {
|
|
res = SmbiosTable.Type4->ExternalClock % 10;
|
|
}
|
|
|
|
smbiosSettings->ExternalClock = (UINT32)((SmbiosTable.Type4->ExternalClock * 1000) + (res * 110));//MHz->kHz
|
|
|
|
//snwprintf(gSettings.BusSpeed, 10, "%d", smbiosSettings.ExternalClock);
|
|
//gSettings.BusSpeed = smbiosSettings.ExternalClock; //why duplicate??
|
|
smbiosSettings->CurrentSpeed = SmbiosTable.Type4->CurrentSpeed;
|
|
smbiosSettings->MaxSpeed = SmbiosTable.Type4->MaxSpeed;
|
|
|
|
size_t off = OFFSET_OF(SMBIOS_TABLE_TYPE4, EnabledCoreCount);
|
|
if (SmbiosTable.Type4->Hdr.Length > off) { //Smbios >= 2.5
|
|
smbiosSettings->EnabledCores = SmbiosTable.Type4->EnabledCoreCount;
|
|
} else {
|
|
smbiosSettings->EnabledCores = 0; //to change later
|
|
}
|
|
|
|
//snwprintf(gSettings.CpuFreqMHz, 10, "%d", smbiosSettings.CurrentSpeed);
|
|
//gSettings.CpuFreqMHz = smbiosSettings.CurrentSpeed;
|
|
|
|
return;
|
|
}
|
|
|
|
void PatchTableType4(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
// Processor Information
|
|
//
|
|
UINTN AddBrand = 0;
|
|
UINT16 ProcChar = 0;
|
|
|
|
//Note. iMac11,2 has four tables for CPU i3
|
|
UINTN CpuNumber;
|
|
|
|
// DBG("BrandString=%s\n", BrandStr);
|
|
for (CpuNumber = 0; CpuNumber < smbiosSettings.Cores; CpuNumber++) {
|
|
// Get Table Type4
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, CpuNumber);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
break;
|
|
}
|
|
// we make SMBios v2.4 while it may be older so we have to increase size
|
|
UINTN Size = SmbiosTable.Type4->Hdr.Length; //old size
|
|
TableSize = SmbiosTableLength(SmbiosTable); //including strings
|
|
AddBrand = 0;
|
|
if (SmbiosTable.Type4->ProcessorVersion == 0) { //if no BrandString we can add
|
|
AddBrand = 48;
|
|
}
|
|
UINTN NewSize = sizeof(SMBIOS_TABLE_TYPE4);
|
|
ZeroMem((void*)newSmbiosTable.Type4, MAX_TABLE_SIZE);
|
|
CopyMem((void*)newSmbiosTable.Type4, (void*)SmbiosTable.Type4, Size); //copy main table
|
|
CopyMem((CHAR8*)newSmbiosTable.Type4+NewSize, (CHAR8*)SmbiosTable.Type4+Size, TableSize - Size); //copy strings
|
|
newSmbiosTable.Type4->Hdr.Length = (UINT8)NewSize;
|
|
|
|
newSmbiosTable.Type4->MaxSpeed = (UINT16)smbiosSettings.MaxSpeed;
|
|
//old version has no such fields. Fill now
|
|
if (Size <= 0x20){
|
|
//sanity check and clear
|
|
newSmbiosTable.Type4->SerialNumber = 0;
|
|
newSmbiosTable.Type4->AssetTag = 0;
|
|
newSmbiosTable.Type4->PartNumber = 0;
|
|
}
|
|
if (Size <= 0x23) { //Smbios <=2.3
|
|
newSmbiosTable.Type4->CoreCount = smbiosSettings.Cores;
|
|
newSmbiosTable.Type4->ThreadCount = smbiosSettings.Threads;
|
|
newSmbiosTable.Type4->ProcessorCharacteristics = (UINT16)smbiosSettings.Features;
|
|
} //else we propose DMI data is better then cpuid().
|
|
// if (newSmbiosTable.Type4->CoreCount < newSmbiosTable.Type4->EnabledCoreCount) {
|
|
// newSmbiosTable.Type4->EnabledCoreCount = smbiosSettings.Cores;
|
|
// }
|
|
|
|
//DBG("insert ExternalClock: %d MHz\n", (INT32)(DivU64x32(smbiosSettings.ExternalClock, Kilo)));
|
|
newSmbiosTable.Type4->ExternalClock = (UINT16)DivU64x32 (smbiosSettings.ExternalClock, Kilo);
|
|
newSmbiosTable.Type4->EnabledCoreCount = smbiosSettings.EnabledCores;
|
|
//some verifications
|
|
if ((newSmbiosTable.Type4->ThreadCount < newSmbiosTable.Type4->CoreCount) ||
|
|
newSmbiosTable.Type4->ThreadCount > newSmbiosTable.Type4->CoreCount * 2) {
|
|
newSmbiosTable.Type4->ThreadCount = smbiosSettings.Threads;
|
|
}
|
|
|
|
UniquifySmbiosTableStr(newSmbiosTable, SMBIOS_TABLE_TYPE4_STR_IDX);
|
|
|
|
// TODO: Set SmbiosTable.Type4->ProcessorFamily for all implemented CPU models
|
|
Once = TRUE;
|
|
if (smbiosSettings.Model == CPU_MODEL_ATOM) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelAtom;
|
|
}
|
|
if ((smbiosSettings.Model == CPU_MODEL_DOTHAN) ||
|
|
(smbiosSettings.Model == CPU_MODEL_YONAH)) {
|
|
if (smbiosSettings.Mobile) {
|
|
newSmbiosTable.Type4->ProcessorUpgrade = ProcessorUpgradeSocket478;
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCoreSoloMobile;
|
|
if (smbiosSettings.Cores == 2) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCoreDuoMobile;
|
|
}
|
|
} else {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCoreSolo;
|
|
if (smbiosSettings.Cores == 2) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCoreDuo;
|
|
}
|
|
}
|
|
}
|
|
if (smbiosSettings.Model == CPU_MODEL_MEROM) {
|
|
if (smbiosSettings.Mobile) {
|
|
if (smbiosSettings.Cores==2) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCore2DuoMobile;
|
|
}
|
|
if (smbiosSettings.Cores==1) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCore2SoloMobile;
|
|
}
|
|
} else { // Conroe
|
|
newSmbiosTable.Type4->ProcessorUpgrade = ProcessorUpgradeSocketLGA775;
|
|
if (smbiosSettings.Cores>2) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCore2Quad;
|
|
} else
|
|
if (smbiosSettings.Cores==2) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCore2Extreme;
|
|
}
|
|
if (smbiosSettings.Cores==1) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCore2Solo;
|
|
}
|
|
}
|
|
}
|
|
if (smbiosSettings.Model == CPU_MODEL_PENRYN) {
|
|
if (smbiosSettings.Mobile) {
|
|
if (smbiosSettings.Cores>2) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCore2ExtremeMobile;
|
|
}
|
|
if (smbiosSettings.Cores==2) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCore2DuoMobile;
|
|
}
|
|
|
|
} else {
|
|
newSmbiosTable.Type4->ProcessorUpgrade = ProcessorUpgradeSocketLGA775;
|
|
if (smbiosSettings.Cores>2) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCore2Quad;
|
|
} else if (smbiosSettings.Cores==2) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCore2;
|
|
} else {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCore2Solo;
|
|
}
|
|
if ( smbiosSettings.BrandString.contains("Celeron") ) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyDualCoreIntelCeleron;
|
|
} else if ( smbiosSettings.BrandString.contains("Extreme") ) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCore2Extreme;
|
|
}
|
|
}
|
|
}
|
|
if (smbiosSettings.Model >= CPU_MODEL_NEHALEM) {
|
|
if ( smbiosSettings.BrandString.contains("i3") )
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCoreI3;
|
|
if ( smbiosSettings.BrandString.contains("i5") )
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCoreI5;
|
|
if ( smbiosSettings.BrandString.contains("i7") )
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCoreI7;
|
|
}
|
|
//spec 2.7 page 48 note 3
|
|
if ((newSmbiosTable.Type4->ProcessorFamily == ProcessorFamilyIntelCore2)
|
|
&& smbiosSettings.Mobile) {
|
|
newSmbiosTable.Type4->ProcessorFamily = ProcessorFamilyIntelCore2DuoMobile;
|
|
}
|
|
|
|
// Set CPU Attributes
|
|
newSmbiosTable.Type4->L1CacheHandle = L1;
|
|
newSmbiosTable.Type4->L2CacheHandle = L2;
|
|
newSmbiosTable.Type4->L3CacheHandle = L3;
|
|
newSmbiosTable.Type4->ProcessorType = CentralProcessor;
|
|
newSmbiosTable.Type4->ProcessorId.Signature.ProcessorSteppingId = smbiosSettings.Stepping;
|
|
newSmbiosTable.Type4->ProcessorId.Signature.ProcessorModel = (smbiosSettings.Model & 0xF);
|
|
newSmbiosTable.Type4->ProcessorId.Signature.ProcessorFamily = smbiosSettings.Family;
|
|
newSmbiosTable.Type4->ProcessorId.Signature.ProcessorType = smbiosSettings.Type;
|
|
newSmbiosTable.Type4->ProcessorId.Signature.ProcessorXModel = smbiosSettings.Extmodel;
|
|
newSmbiosTable.Type4->ProcessorId.Signature.ProcessorXFamily = smbiosSettings.Extfamily;
|
|
// CopyMem((void*)&newSmbiosTable.Type4->ProcessorId.FeatureFlags, (void*)&smbiosSettings.Features, 4);
|
|
// newSmbiosTable.Type4->ProcessorId.FeatureFlags = (PROCESSOR_FEATURE_FLAGS)(UINT32)smbiosSettings.Features;
|
|
if (Size <= 0x26) {
|
|
newSmbiosTable.Type4->ProcessorFamily2 = newSmbiosTable.Type4->ProcessorFamily;
|
|
ProcChar |= (smbiosSettings.ExtFeatures & CPUID_EXTFEATURE_EM64T)?0x04:0;
|
|
ProcChar |= (smbiosSettings.Cores > 1)?0x08:0;
|
|
ProcChar |= (smbiosSettings.Cores < smbiosSettings.Threads)?0x10:0;
|
|
ProcChar |= (smbiosSettings.ExtFeatures & CPUID_EXTFEATURE_XD)?0x20:0;
|
|
ProcChar |= (smbiosSettings.Features & CPUID_FEATURE_VMX)?0x40:0;
|
|
ProcChar |= (smbiosSettings.Features & CPUID_FEATURE_EST)?0x80:0;
|
|
newSmbiosTable.Type4->ProcessorCharacteristics = ProcChar;
|
|
}
|
|
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type4->Socket, "U2E1"_XS8);
|
|
|
|
XString8 BrandStr;
|
|
BrandStr.takeValueFrom(smbiosSettings.BrandString);
|
|
if (AddBrand) {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type4->ProcessorVersion, BrandStr);
|
|
}
|
|
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type4->AssetTag, BrandStr); //like mac
|
|
// looks to be MicroCode revision
|
|
if(smbiosSettings.MicroCode > 0){
|
|
BrandStr.S8Printf("%llX", smbiosSettings.MicroCode);
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type4->SerialNumber, BrandStr);
|
|
}
|
|
|
|
#ifdef JIEF_DEBUG
|
|
DBG("newSmbiosTable.Type4->AssetTag=%d\n", newSmbiosTable.Type4->AssetTag);
|
|
DBG("newSmbiosTable.Type4->CoreCount=%d\n", newSmbiosTable.Type4->CoreCount);
|
|
DBG("newSmbiosTable.Type4->CoreCount2=%d\n", newSmbiosTable.Type4->CoreCount2);
|
|
DBG("newSmbiosTable.Type4->CurrentSpeed=%d\n", newSmbiosTable.Type4->CurrentSpeed);
|
|
DBG("newSmbiosTable.Type4->EnabledCoreCount=%d\n", newSmbiosTable.Type4->EnabledCoreCount);
|
|
DBG("newSmbiosTable.Type4->EnabledCoreCount2=%d\n", newSmbiosTable.Type4->EnabledCoreCount2);
|
|
DBG("newSmbiosTable.Type4->ExternalClock=%d\n", newSmbiosTable.Type4->ExternalClock);
|
|
DBG("newSmbiosTable.Type4->L1CacheHandle=%d\n", newSmbiosTable.Type4->L1CacheHandle);
|
|
DBG("newSmbiosTable.Type4->L2CacheHandle=%d\n", newSmbiosTable.Type4->L2CacheHandle);
|
|
DBG("newSmbiosTable.Type4->L3CacheHandle=%d\n", newSmbiosTable.Type4->L3CacheHandle);
|
|
DBG("newSmbiosTable.Type4->MaxSpeed=%d\n", newSmbiosTable.Type4->MaxSpeed);
|
|
DBG("newSmbiosTable.Type4->PartNumber=%d\n", newSmbiosTable.Type4->PartNumber);
|
|
DBG("newSmbiosTable.Type4->ProcessorCharacteristics=%d\n", newSmbiosTable.Type4->ProcessorCharacteristics);
|
|
DBG("newSmbiosTable.Type4->ProcessorFamily=%d\n", newSmbiosTable.Type4->ProcessorFamily);
|
|
DBG("newSmbiosTable.Type4->ProcessorFamily2=%d\n", newSmbiosTable.Type4->ProcessorFamily2);
|
|
DBG("newSmbiosTable.Type4->ProcessorId.FeatureFlags=%d\n", *(UINT32*)&newSmbiosTable.Type4->ProcessorId.FeatureFlags);
|
|
DBG("newSmbiosTable.Type4->ProcessorId.Signatur=%d\n", *(UINT32*)&newSmbiosTable.Type4->ProcessorId.Signature);
|
|
DBG("newSmbiosTable.Type4->ProcessorManufacture=%d\n", newSmbiosTable.Type4->ProcessorManufacture);
|
|
DBG("newSmbiosTable.Type4->ProcessorType=%d\n", newSmbiosTable.Type4->ProcessorType);
|
|
DBG("newSmbiosTable.Type4->ProcessorUpgrade=%d\n", newSmbiosTable.Type4->ProcessorUpgrade);
|
|
DBG("newSmbiosTable.Type4->ProcessorVersion=%d\n", newSmbiosTable.Type4->ProcessorVersion);
|
|
DBG("newSmbiosTable.Type4->SerialNumber=%d\n", newSmbiosTable.Type4->SerialNumber);
|
|
DBG("newSmbiosTable.Type4->Socket=%d\n", newSmbiosTable.Type4->Socket);
|
|
DBG("newSmbiosTable.Type4->Status=%d\n", newSmbiosTable.Type4->Status);
|
|
DBG("newSmbiosTable.Type4->ThreadCount=%d\n", newSmbiosTable.Type4->ThreadCount);
|
|
DBG("newSmbiosTable.Type4->ThreadCount2=%d\n", newSmbiosTable.Type4->ThreadCount2);
|
|
DBG("newSmbiosTable.Type4->Voltage=%d\n", *(UINT8*)&newSmbiosTable.Type4->Voltage);
|
|
#endif
|
|
|
|
Handle = LogSmbiosTable(newSmbiosTable);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void PatchTableType6(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
UINT8 SizeField = 0;
|
|
//
|
|
// MemoryModule (TYPE 6)
|
|
|
|
// This table is obsolete accoding to Spec but Apple still using it so
|
|
// copy existing table if found, no patches will be here
|
|
// we can have more then 1 module.
|
|
for (size_t Index = 0; Index < MAX_RAM_SLOTS; Index++) {
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_MEMORY_MODULE_INFORMATON,Index);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
// MsgLog("SMBIOS Table 6 index %d not found\n", Index);
|
|
continue;
|
|
}
|
|
SizeField = SmbiosTable.Type6->InstalledSize.InstalledOrEnabledSize & 0x7F;
|
|
if (SizeField < 0x7D) {
|
|
mInstalled[Index] = LShiftU64(1ULL, 20 + SizeField);
|
|
} else if (SizeField == 0x7F) {
|
|
mInstalled[Index] = 0;
|
|
} else
|
|
mInstalled[Index] = 4096ULL * (1024ULL * 1024ULL);
|
|
MsgLog("Table 6 MEMORY_MODULE %zu Installed %llX ", Index, mInstalled[Index]);
|
|
if (SizeField >= 0x7D) {
|
|
mEnabled[Index] = 0;
|
|
} else
|
|
mEnabled[Index] = LShiftU64(1ULL, 20 + ((UINT8)SmbiosTable.Type6->EnabledSize.InstalledOrEnabledSize & 0x7F));
|
|
MsgLog("... enabled %llX \n", mEnabled[Index]);
|
|
LogSmbiosTable(SmbiosTable);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void PatchTableType7(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
// Cache Information
|
|
//
|
|
//TODO - should be separate table for each CPU core
|
|
//new handle for each core and attach Type4 tables for individual Type7
|
|
// Handle = 0x0700 + CoreN<<2 + CacheN (4-level cache is supported
|
|
// L1[CoreN] = Handle
|
|
|
|
BOOLEAN correctSD = FALSE;
|
|
|
|
//according to spec for Smbios v2.0 max handle is 0xFFFE, for v>2.0 (we made 2.6) max handle=0xFEFF.
|
|
// Value 0xFFFF means no cache
|
|
L1 = 0xFFFF; // L1 Cache
|
|
L2 = 0xFFFF; // L2 Cache
|
|
L3 = 0xFFFF; // L3 Cache
|
|
|
|
// Get Table Type7 and set CPU Caches
|
|
for (size_t Index = 0; Index < MAX_CACHE_COUNT; Index++) {
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_CACHE_INFORMATION, Index);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
break;
|
|
}
|
|
TableSize = SmbiosTableLength(SmbiosTable);
|
|
ZeroMem((void*)newSmbiosTable.Type7, MAX_TABLE_SIZE);
|
|
CopyMem((void*)newSmbiosTable.Type7, (void*)SmbiosTable.Type7, TableSize);
|
|
correctSD = (newSmbiosTable.Type7->SocketDesignation == 0);
|
|
CoreCache = newSmbiosTable.Type7->CacheConfiguration & 3;
|
|
Once = TRUE;
|
|
|
|
//SSocketD = "L1-Cache";
|
|
if(correctSD) {
|
|
XString8 SSocketD = S8Printf("L%c-Cache", 0x31 + CoreCache);
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type7->SocketDesignation, SSocketD);
|
|
}
|
|
Handle = LogSmbiosTable(newSmbiosTable);
|
|
switch (CoreCache) {
|
|
case 0:
|
|
L1 = Handle;
|
|
break;
|
|
case 1:
|
|
L2 = Handle;
|
|
break;
|
|
case 2:
|
|
L3 = Handle;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void PatchTableType9(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
//
|
|
// System Slots (Type 9)
|
|
/*
|
|
SlotDesignation: PCI1
|
|
System Slot Type: PCI
|
|
System Slot Data Bus Width: 32 bit
|
|
System Slot Current Usage: Available
|
|
System Slot Length: Short length
|
|
System Slot Type: PCI
|
|
Slot Id: the value present in the Slot Number field of the PCI Interrupt Routing table entry that is associated with this slot is: 1
|
|
Slot characteristics 1: Provides 3.3 Volts | Slot's opening is shared with another slot, e.g. PCI/EISA shared slot. |
|
|
Slot characteristics 2: PCI slot supports Power Management Enable (PME#) signal |
|
|
SegmentGroupNum: 0x4350
|
|
BusNum: 0x49
|
|
DevFuncNum: 0x31
|
|
|
|
Real Mac always contain Airport table 9 as
|
|
09 0D xx xx 01 A5 08 03 03 00 00 04 06 "AirPort"
|
|
*/
|
|
//usage in macOS:
|
|
// SlotID == value of Name(_SUN, SlotID) 8bit
|
|
// SlotDesignation == name to "AAPL,slot-name"
|
|
// SlotType = 32bit PCI/SlotTypePciExpressX1/x4/x16
|
|
// real PC -> PCI, real Mac -> PCIe
|
|
|
|
#ifdef JIEF_DEBUG
|
|
for (uint64_t Index = 0; Index <= 15; Index++) {
|
|
DBG("SlotDevice[%lld].BusNum = %d\n", Index, smbiosSettings.SlotDevices.getSlotForIndex(Index).BusNum);
|
|
DBG("SlotDevice[%lld].DevFuncNum = %d\n", Index, smbiosSettings.SlotDevices.getSlotForIndex(Index).DevFuncNum);
|
|
DBG("SlotDevice[%lld].SegmentGroupNum = %d\n", Index, smbiosSettings.SlotDevices.getSlotForIndex(Index).SegmentGroupNum);
|
|
DBG("SlotDevice[%lld].SlotID = %hhd\n", Index, smbiosSettings.SlotDevices.getSlotForIndex(Index).SlotID);
|
|
DBG("SlotDevice[%lld].SlotType = %d\n", Index, smbiosSettings.SlotDevices.getSlotForIndex(Index).SlotType);
|
|
DBG("SlotDevice[%lld].SlotName = %s\n", Index, smbiosSettings.SlotDevices.getSlotForIndex(Index).SlotName.c_str());
|
|
DBG("SlotDevice[%lld].Valid = %d\n", Index, smbiosSettings.SlotDevices.isSlotForIndexValid(Index));
|
|
}
|
|
#endif
|
|
|
|
for (size_t Index = 0; Index < 15; Index++) {
|
|
if (smbiosSettings.SlotDevices.isSlotForIndexValid(Index)) {
|
|
INTN Dev, Func;
|
|
ZeroMem((void*)newSmbiosTable.Type9, MAX_TABLE_SIZE);
|
|
newSmbiosTable.Type9->Hdr.Type = EFI_SMBIOS_TYPE_SYSTEM_SLOTS;
|
|
newSmbiosTable.Type9->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE9);
|
|
newSmbiosTable.Type9->Hdr.Handle = (UINT16)(0x0900 + Index);
|
|
newSmbiosTable.Type9->SlotDesignation = 1;
|
|
newSmbiosTable.Type9->SlotType = smbiosSettings.SlotDevices.getSlotForIndex(Index).SlotType;
|
|
newSmbiosTable.Type9->SlotDataBusWidth = SlotDataBusWidth1X;
|
|
newSmbiosTable.Type9->CurrentUsage = SlotUsageAvailable;
|
|
newSmbiosTable.Type9->SlotLength = SlotLengthShort;
|
|
newSmbiosTable.Type9->SlotID = smbiosSettings.SlotDevices.getSlotForIndex(Index).SlotID;
|
|
newSmbiosTable.Type9->SlotCharacteristics1.Provides33Volts = 1;
|
|
newSmbiosTable.Type9->SlotCharacteristics2.HotPlugDevicesSupported = 1;
|
|
// take this from PCI bus for WiFi card
|
|
newSmbiosTable.Type9->SegmentGroupNum = smbiosSettings.SlotDevices.getSlotForIndex(Index).SegmentGroupNum;
|
|
newSmbiosTable.Type9->BusNum = smbiosSettings.SlotDevices.getSlotForIndex(Index).BusNum;
|
|
newSmbiosTable.Type9->DevFuncNum = smbiosSettings.SlotDevices.getSlotForIndex(Index).DevFuncNum;
|
|
//
|
|
Dev = smbiosSettings.SlotDevices.getSlotForIndex(Index).DevFuncNum >> 3;
|
|
Func = smbiosSettings.SlotDevices.getSlotForIndex(Index).DevFuncNum & 7;
|
|
DBG("insert table 9 for dev %llX:%llX\n", Dev, Func);
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type9->SlotDesignation, smbiosSettings.SlotDevices.getSlotForIndex(Index).SlotName);
|
|
LogSmbiosTable(newSmbiosTable);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void PatchTableType11(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
// CHAR8 *OEMString = "Apple inc. uses Clover"; //something else here?
|
|
// System Information
|
|
//
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_OEM_STRINGS, 0);
|
|
if (SmbiosTable.Raw != NULL) {
|
|
MsgLog("Table 11 present, but rewritten for us\n");
|
|
}
|
|
// TableSize = SmbiosTableLength(SmbiosTable);
|
|
ZeroMem((void*)newSmbiosTable.Type11, MAX_TABLE_SIZE);
|
|
// CopyMem((void*)newSmbiosTable.Type11, (void*)SmbiosTable.Type11, 5); //minimum, other bytes = 0
|
|
newSmbiosTable.Type11->Hdr.Type = EFI_SMBIOS_TYPE_OEM_STRINGS;
|
|
newSmbiosTable.Type11->Hdr.Length = 5;
|
|
newSmbiosTable.Type11->Hdr.Handle = 0x0B00; //common rule
|
|
|
|
newSmbiosTable.Type11->StringCount = 1;
|
|
//
|
|
// ZeroMem(OEMString, MAX_OEM_STRING);
|
|
// AsciiStrCatS(OEMString, MAX_OEM_STRING, "Apple ROM Version.\n");
|
|
// //AsciiStrCatS(OEMString, MAX_OEM_STRING, " BIOS ID:");
|
|
// //AsciiStrnCatS(OEMString, MAX_OEM_STRING, smbiosSettings.RomVersion, iStrLen(smbiosSettings.RomVersion, 64));
|
|
// // AsciiStrCatS(OEMString, MAX_OEM_STRING, "\n EFI Version:");
|
|
// // AsciiStrnCatS(OEMString, MAX_OEM_STRING, smbiosSettings.EfiVersion, iStrLen(smbiosSettings.EfiVersion, 64));
|
|
// AsciiStrCatS(OEMString, MAX_OEM_STRING, " Board-ID : ");
|
|
// AsciiStrnCatS(OEMString, MAX_OEM_STRING, smbiosSettings.BoardNumber, iStrLen(smbiosSettings.BoardNumber, 64));
|
|
// snprintf(TempRev, MAX_OEM_STRING, "\n⌘ Powered by %s\n", gRevisionStr);
|
|
// AsciiStrCatS(OEMString, MAX_OEM_STRING, TempRev);
|
|
#ifdef JIEF_DEBUG
|
|
XString8 OEMString = S8Printf("⌘ Powered by %s\n", gBuildId.c_str());
|
|
#else
|
|
XString8 OEMString = S8Printf("Apple ROM Version.\nBoard-ID : %s\n⌘ Powered by %s\n", smbiosSettings.BoardNumber.c_str(), gRevisionStr);
|
|
#endif
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type11->StringCount, OEMString);
|
|
|
|
LogSmbiosTable(newSmbiosTable);
|
|
return;
|
|
}
|
|
|
|
//some unused but interesting tables. Just log as is
|
|
#define NUM_OTHER_TYPES 14
|
|
const UINT8 tableTypes[] = {8, 10, 13, 18, 21, 22, 27, 28, 32, 33, 41, 129, 217, 219};
|
|
|
|
void PatchTableTypeSome()
|
|
{
|
|
for (UINTN IndexType = 0; IndexType < sizeof(tableTypes); IndexType++) {
|
|
for (size_t Index = 0; Index < 32; Index++) {
|
|
SmbiosTable = GetSmbiosTableFromType(EntryPoint, tableTypes[IndexType], Index);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
continue;
|
|
}
|
|
LogSmbiosTable(SmbiosTable);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void GetTableType16(SmbiosDiscoveredSettings* smbiosSettings)
|
|
{
|
|
// Physical Memory Array
|
|
//
|
|
mTotalSystemMemory = 0; //later we will add to the value, here initialize it
|
|
smbiosSettings->RamSlotCount = 0;
|
|
for (size_t Index = 0; Index < 8; Index++) { //how many tables there may be?
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY, Index);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
// DBG("SmbiosTable: Type 16 (Physical Memory Array) not found!\n");
|
|
continue;
|
|
}
|
|
DBG("Type 16 Index = %zu\n", Index);
|
|
smbiosSettings->RamSlotCount += SmbiosTable.Type16->NumberOfMemoryDevices;
|
|
}
|
|
if ( smbiosSettings->RamSlotCount == 0 ) {
|
|
DBG("Total Memory Slots Count is adjusted from 0 to %d\n", MAX_RAM_SLOTS);
|
|
smbiosSettings->RamSlotCount = MAX_RAM_SLOTS;
|
|
}else{
|
|
//Jief_Machak: VMWare report 64 memory slots !!! MAX_RAM_SLOTS is currently 24. Crash is PatchTable17.
|
|
if ( smbiosSettings->RamSlotCount > MAX_RAM_SLOTS ) {
|
|
DBG("Total Memory Slots Count is adjusted from %d to %d\n", smbiosSettings->RamSlotCount, MAX_RAM_SLOTS);
|
|
smbiosSettings->RamSlotCount = MAX_RAM_SLOTS;
|
|
}else{
|
|
DBG("Total Memory Slots Count = %d\n", smbiosSettings->RamSlotCount);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void PatchTableType16(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
// Physical Memory Array
|
|
//
|
|
|
|
// Get Table Type16 and set Device Count
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
DBG("SmbiosTable: Type 16 (Physical Memory Array) not found!\n");
|
|
return;
|
|
}
|
|
TableSize = SmbiosTableLength(SmbiosTable);
|
|
ZeroMem((void*)newSmbiosTable.Type16, MAX_TABLE_SIZE);
|
|
CopyMem((void*)newSmbiosTable.Type16, (void*)SmbiosTable.Type16, TableSize);
|
|
newSmbiosTable.Type16->Hdr.Handle = mHandle16;
|
|
// Slice - I am not sure if I want these values
|
|
// newSmbiosTable.Type16->Location = MemoryArrayLocationProprietaryAddonCard;
|
|
// newSmbiosTable.Type16->Use = MemoryArrayUseSystemMemory;
|
|
// newSmbiosTable.Type16->MemoryErrorCorrection = MemoryErrorCorrectionMultiBitEcc;
|
|
// MemoryErrorInformationHandle
|
|
newSmbiosTable.Type16->MemoryErrorInformationHandle = 0xFFFF;
|
|
newSmbiosTable.Type16->NumberOfMemoryDevices = MIN(smbiosSettings.RamSlotCount, MAX_RAM_SLOTS);
|
|
DBG("NumberOfMemoryDevices = %d\n", MIN(smbiosSettings.RamSlotCount, MAX_RAM_SLOTS));
|
|
LogSmbiosTable(newSmbiosTable);
|
|
}
|
|
|
|
void GetTableType17(SmbiosDiscoveredSettings* smbiosSettings)
|
|
{
|
|
// Memory Device
|
|
//
|
|
BOOLEAN Found;
|
|
|
|
// Get Table Type17 and count Size
|
|
for (size_t Index = 0; Index < smbiosSettings->RamSlotCount; Index++) { //how many tables there may be?
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_MEMORY_DEVICE, Index);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
// DBG("SmbiosTable: Type 17 (Memory Device number %d) not found!\n", Index);
|
|
continue;
|
|
}
|
|
#ifndef JIEF_DEBUG // it's all 0 in VMWare
|
|
DBG("Type 17 Index = %zu\n", Index);
|
|
#endif
|
|
//gDMI->CntMemorySlots++;
|
|
if (SmbiosTable.Type17->MemoryErrorInformationHandle < 0xFFFE) {
|
|
DBG("Table has error information, checking\n"); //why skipping?
|
|
// Why trust it if it has an error? I guess we could look
|
|
// up the error handle and determine certain errors may
|
|
// be skipped where others may not but it seems easier
|
|
// to just skip all entries that have an error - apianti
|
|
// will try
|
|
Found = FALSE;
|
|
for (INTN Index2 = 0; Index2 < 24; Index2++) {
|
|
newSmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_32BIT_MEMORY_ERROR_INFORMATION, Index2);
|
|
if (newSmbiosTable.Raw == NULL) {
|
|
continue;
|
|
}
|
|
if (newSmbiosTable.Type18->Hdr.Handle == SmbiosTable.Type17->MemoryErrorInformationHandle) {
|
|
Found = TRUE;
|
|
DBG("Found memory information in table 18/%lld, type=0x%X, operation=0x%X syndrome=0x%X\n", Index2,
|
|
newSmbiosTable.Type18->ErrorType,
|
|
newSmbiosTable.Type18->ErrorOperation,
|
|
newSmbiosTable.Type18->VendorSyndrome);
|
|
switch (newSmbiosTable.Type18->ErrorType) {
|
|
case MemoryErrorOk:
|
|
DBG("...memory OK\n");
|
|
break;
|
|
case MemoryErrorCorrected:
|
|
DBG("...memory errors corrected\n");
|
|
break;
|
|
case MemoryErrorChecksum:
|
|
DBG("...error type: Checksum\n");
|
|
break;
|
|
default:
|
|
DBG("...error type not shown\n");
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (Found) {
|
|
if ((newSmbiosTable.Type18->ErrorType != MemoryErrorOk) &&
|
|
(newSmbiosTable.Type18->ErrorType != MemoryErrorCorrected)) {
|
|
DBG("skipping wrong module\n");
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
// Determine if slot has size
|
|
if (SmbiosTable.Type17->Size > 0) {
|
|
gRAM.SMBIOS[Index].InUse = TRUE;
|
|
gRAM.SMBIOS[Index].ModuleSize = SmbiosTable.Type17->Size;
|
|
if (SmbiosTable.Type17->Size == 0x7FFF) {
|
|
gRAM.SMBIOS[Index].ModuleSize = SmbiosTable.Type17->ExtendedSize;
|
|
}
|
|
}
|
|
// Determine if module frequency is sane value
|
|
if ((SmbiosTable.Type17->Speed > 0) && (SmbiosTable.Type17->Speed <= MAX_RAM_FREQUENCY)) {
|
|
gRAM.SMBIOS[Index].InUse = TRUE;
|
|
gRAM.SMBIOS[Index].Frequency = SmbiosTable.Type17->Speed;
|
|
if (SmbiosTable.Type17->Speed > gRAM.Frequency) {
|
|
gRAM.Frequency = SmbiosTable.Type17->Speed;
|
|
}
|
|
} else {
|
|
#ifndef JIEF_DEBUG // always the case in VMWare
|
|
DBG("Ignoring insane frequency value %dMHz\n", SmbiosTable.Type17->Speed);
|
|
#endif
|
|
}
|
|
// Fill rest of information if in use
|
|
if (gRAM.SMBIOS[Index].InUse) {
|
|
++(gRAM.SMBIOSInUse);
|
|
gRAM.SMBIOS[Index].Vendor.takeValueFrom(GetSmbiosString(SmbiosTable, SmbiosTable.Type17->Manufacturer));
|
|
gRAM.SMBIOS[Index].Vendor.trim();
|
|
gRAM.SMBIOS[Index].SerialNo.takeValueFrom(GetSmbiosString(SmbiosTable, SmbiosTable.Type17->SerialNumber));
|
|
gRAM.SMBIOS[Index].SerialNo.trim();
|
|
gRAM.SMBIOS[Index].PartNo.takeValueFrom(GetSmbiosString(SmbiosTable, SmbiosTable.Type17->PartNumber));
|
|
gRAM.SMBIOS[Index].PartNo.trim();
|
|
}
|
|
// DBG("CntMemorySlots = %d\n", gDMI->CntMemorySlots)
|
|
// DBG("gDMI->MemoryModules = %d\n", gDMI->MemoryModules)
|
|
if ((SmbiosTable.Type17->Speed > 0) && (SmbiosTable.Type17->Speed <= MAX_RAM_FREQUENCY)) {
|
|
DBG("SmbiosTable.Type17->Speed = %dMHz\n", gRAM.SMBIOS[Index].Frequency);
|
|
DBG("SmbiosTable.Type17->Size = %dMB\n", gRAM.SMBIOS[Index].ModuleSize);
|
|
DBG("SmbiosTable.Type17->Bank/Device = %s %s\n", GetSmbiosString(SmbiosTable, SmbiosTable.Type17->BankLocator), GetSmbiosString(SmbiosTable, SmbiosTable.Type17->DeviceLocator));
|
|
DBG("SmbiosTable.Type17->Vendor = %s\n", gRAM.SMBIOS[Index].Vendor.c_str());
|
|
DBG("SmbiosTable.Type17->SerialNumber = %s\n", gRAM.SMBIOS[Index].SerialNo.c_str());
|
|
DBG("SmbiosTable.Type17->PartNumber = %s\n", gRAM.SMBIOS[Index].PartNo.c_str());
|
|
}
|
|
|
|
/*
|
|
if ((SmbiosTable.Type17->Size & 0x8000) == 0) {
|
|
mTotalSystemMemory += SmbiosTable.Type17->Size; //Mb
|
|
mMemory17[Index] = (UINT16)(SmbiosTable.Type17->Size > 0 ? mTotalSystemMemory : 0);
|
|
}
|
|
DBG("mTotalSystemMemory = %d\n", mTotalSystemMemory);
|
|
*/
|
|
}
|
|
}
|
|
|
|
void PatchTableType17(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
XString8 deviceLocator;
|
|
XString8 bankLocator;
|
|
UINT8 channelMap[MAX_RAM_SLOTS];
|
|
UINT8 expectedCount = 0;
|
|
UINT8 channels = 2;
|
|
BOOLEAN insertingEmpty = TRUE;
|
|
BOOLEAN trustSMBIOS = ((gRAM.SPDInUse == 0) || smbiosSettings.TrustSMBIOS);
|
|
BOOLEAN wrongSMBIOSBanks = FALSE;
|
|
BOOLEAN isMacPro = FALSE;
|
|
MACHINE_TYPES Model = GetModelFromString(smbiosSettings.ProductName);
|
|
if ((Model == MacPro31) || (Model == MacPro41) || (Model == MacPro51) || (Model == MacPro61)) {
|
|
isMacPro = TRUE;
|
|
}
|
|
// Inject user memory tables
|
|
if (smbiosSettings.InjectMemoryTables)
|
|
{
|
|
DBG("Injecting user memory modules to SMBIOS\n");
|
|
if (smbiosSettings.Memory.SlotCounts == 0) {
|
|
DBG("User SMBIOS contains no memory modules\n");
|
|
return;
|
|
}
|
|
// Check channels
|
|
auto UserChannels = smbiosSettings.Memory.UserChannels;
|
|
if ( UserChannels == 0 || UserChannels > 8 ) {
|
|
UserChannels = 1;
|
|
}
|
|
auto SlotCounts = smbiosSettings.Memory.SlotCounts;
|
|
if ( SlotCounts >= MAX_RAM_SLOTS ) {
|
|
SlotCounts = MAX_RAM_SLOTS;
|
|
}
|
|
DBG("Channels: %d\n", UserChannels);
|
|
// Setup interleaved channel map
|
|
if (channels >= 2) {
|
|
UINT8 doubleChannels = (UINT8)UserChannels << 1;
|
|
for (size_t Index = 0; Index < MAX_RAM_SLOTS; ++Index) {
|
|
channelMap[Index] = (UINT8)(((Index / doubleChannels) * doubleChannels) +
|
|
((Index / UserChannels) % 2) + ((Index % UserChannels) << 1));
|
|
}
|
|
} else {
|
|
for (size_t Index = 0; Index < MAX_RAM_SLOTS; ++Index) {
|
|
channelMap[Index] = (UINT8)Index;
|
|
}
|
|
}
|
|
DBG("Interleave:");
|
|
for (size_t Index = 0; Index < MAX_RAM_SLOTS; ++Index) {
|
|
DBG(" %d", channelMap[Index]);
|
|
}
|
|
DBG("\n");
|
|
// Memory Device
|
|
//
|
|
// Inject tables
|
|
#ifdef JIEF_DEBUG
|
|
DBG("gSettings.Smbios.Memory.SlotCounts=%d\n", smbiosSettings.Memory.SlotCounts);
|
|
DBG("gSettings.Smbios.Memory.UserChannels=%d\n", smbiosSettings.Memory.UserChannels);
|
|
for (uint64_t Index = 0; Index < smbiosSettings.Memory.SlotCounts; Index++) {
|
|
DBG("gSettings.Smbios.Memory.User[%lld].Frequency=%d\n", Index, smbiosSettings.Memory.getSlotInfoForSlotID(Index).Frequency);
|
|
DBG("gSettings.Smbios.Memory.User[%lld].InUse=%d\n", Index, smbiosSettings.Memory.getSlotInfoForSlotID(Index).InUse);
|
|
DBG("gSettings.Smbios.Memory.User[%lld].ModuleSize=%d\n", Index, smbiosSettings.Memory.getSlotInfoForSlotID(Index).ModuleSize);
|
|
DBG("gSettings.Smbios.Memory.User[%lld].PartNo=%s\n", Index, smbiosSettings.Memory.getSlotInfoForSlotID(Index).PartNo.c_str());
|
|
DBG("gSettings.Smbios.Memory.User[%lld].SerialNo=%s\n", Index, smbiosSettings.Memory.getSlotInfoForSlotID(Index).SerialNo.c_str());
|
|
DBG("gSettings.Smbios.Memory.User[%lld].Type=%d\n", Index, smbiosSettings.Memory.getSlotInfoForSlotID(Index).Type);
|
|
DBG("gSettings.Smbios.Memory.User[%lld].Vendor=%s\n", Index, smbiosSettings.Memory.getSlotInfoForSlotID(Index).Vendor.c_str());
|
|
}
|
|
#endif
|
|
|
|
for (size_t Index = 0; Index < SlotCounts; Index++) {
|
|
UINTN UserIndex = channelMap[Index];
|
|
UINT8 bank = (UINT8)(Index / UserChannels);
|
|
ZeroMem((void*)newSmbiosTable.Type17, MAX_TABLE_SIZE);
|
|
newSmbiosTable.Type17->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE;
|
|
newSmbiosTable.Type17->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE17);
|
|
newSmbiosTable.Type17->TotalWidth = 0xFFFF;
|
|
newSmbiosTable.Type17->DataWidth = 0xFFFF;
|
|
newSmbiosTable.Type17->Hdr.Handle = (UINT16)(0x1100 + UserIndex);
|
|
newSmbiosTable.Type17->FormFactor = (UINT8)(gMobile ? MemoryFormFactorSodimm : MemoryFormFactorDimm);
|
|
newSmbiosTable.Type17->TypeDetail.Synchronous = TRUE;
|
|
newSmbiosTable.Type17->DeviceSet = bank + 1;
|
|
newSmbiosTable.Type17->MemoryArrayHandle = mHandle16;
|
|
if (isMacPro) {
|
|
deviceLocator.S8Printf("DIMM%zd", Index + 1);
|
|
} else {
|
|
deviceLocator.S8Printf("DIMM%d", bank);
|
|
bankLocator.S8Printf("BANK %zu", Index % channels);
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->BankLocator, bankLocator);
|
|
}
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->DeviceLocator, deviceLocator);
|
|
if ((smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).InUse) && (smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).ModuleSize > 0)) {
|
|
DBG("user SMBIOS data:\n");
|
|
DBG("SmbiosTable.Type17->Vendor = %s\n", smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).Vendor.c_str());
|
|
DBG("SmbiosTable.Type17->SerialNumber = %s\n", smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).SerialNo.c_str());
|
|
DBG("SmbiosTable.Type17->PartNumber = %s\n", smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).PartNo.c_str());
|
|
|
|
if (smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).Vendor.notEmpty()) {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->Manufacturer, smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).Vendor);
|
|
} else {
|
|
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->Manufacturer, unknown);
|
|
}
|
|
if (smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).SerialNo.notEmpty()) {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->SerialNumber, smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).SerialNo);
|
|
} else {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->SerialNumber, unknown);
|
|
}
|
|
if (smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).PartNo.notEmpty()) {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->PartNumber, smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).PartNo);
|
|
} else {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->PartNumber, unknown);
|
|
}
|
|
newSmbiosTable.Type17->Speed = (UINT16)smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).Frequency;
|
|
if (smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).ModuleSize > 0x7FFF) {
|
|
newSmbiosTable.Type17->Size = 0x7FFF;
|
|
newSmbiosTable.Type17->ExtendedSize = smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).ModuleSize;
|
|
mTotalSystemMemory += newSmbiosTable.Type17->ExtendedSize; //Mb
|
|
} else {
|
|
newSmbiosTable.Type17->Size = (UINT16)smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).ModuleSize;
|
|
mTotalSystemMemory += newSmbiosTable.Type17->Size; //Mb
|
|
}
|
|
newSmbiosTable.Type17->MemoryType = smbiosSettings.Memory.getSlotInfoForSlotID(UserIndex).Type;
|
|
if ((newSmbiosTable.Type17->MemoryType != MemoryTypeDdr2) &&
|
|
(newSmbiosTable.Type17->MemoryType != MemoryTypeDdr4) &&
|
|
(newSmbiosTable.Type17->MemoryType != MemoryTypeDdr)) {
|
|
newSmbiosTable.Type17->MemoryType = MemoryTypeDdr3;
|
|
}
|
|
DBG("%s %s %dMHz %dMB(Ext:%dMB)\n", bankLocator.c_str(), deviceLocator.c_str(), newSmbiosTable.Type17->Speed,
|
|
newSmbiosTable.Type17->Size, newSmbiosTable.Type17->ExtendedSize);
|
|
mMemory17[Index] = (UINT16)mTotalSystemMemory;
|
|
// DBG("mTotalSystemMemory = %d\n", mTotalSystemMemory);
|
|
} else {
|
|
DBG("%s %s EMPTY\n", bankLocator.c_str(), deviceLocator.c_str());
|
|
}
|
|
newSmbiosTable.Type17->MemoryErrorInformationHandle = 0xFFFF;
|
|
mHandle17[Index] = LogSmbiosTable(newSmbiosTable);
|
|
}
|
|
if (mTotalSystemMemory > 0) {
|
|
DBG("mTotalSystemMemory = %d\n", mTotalSystemMemory);
|
|
}
|
|
return;
|
|
}
|
|
// Prevent inserting empty tables
|
|
if ((gRAM.SPDInUse == 0) && (gRAM.SMBIOSInUse == 0)) {
|
|
DBG("SMBIOS and SPD contain no modules in use\n");
|
|
return;
|
|
}
|
|
// Detect whether the SMBIOS is trusted information
|
|
if (trustSMBIOS) {
|
|
if (gRAM.SMBIOSInUse != 0) {
|
|
if (gRAM.SPDInUse != 0) {
|
|
if (gRAM.SPDInUse != gRAM.SMBIOSInUse) {
|
|
// Prefer the SPD information
|
|
if (gRAM.SPDInUse > gRAM.SMBIOSInUse) {
|
|
DBG("Not trusting SMBIOS because SPD reports more modules...\n");
|
|
trustSMBIOS = FALSE;
|
|
} else if (gRAM.SPD[0].InUse || !gRAM.SMBIOS[0].InUse) {
|
|
if (gRAM.SPDInUse > 1) {
|
|
DBG("Not trusting SMBIOS because SPD reports different modules...\n");
|
|
trustSMBIOS = FALSE;
|
|
} else if (gRAM.SMBIOSInUse == 1) {
|
|
channels = 1;
|
|
}
|
|
} else if (gRAM.SPDInUse == 1) {
|
|
// The SMBIOS may contain table for built-in module
|
|
if (gRAM.SMBIOSInUse <= 2) {
|
|
if (!gRAM.SMBIOS[0].InUse || !gRAM.SPD[2].InUse ||
|
|
(gRAM.SMBIOS[0].Frequency != gRAM.SPD[2].Frequency) ||
|
|
(gRAM.SMBIOS[0].ModuleSize != gRAM.SPD[2].ModuleSize)) {
|
|
channels = 1;
|
|
}
|
|
} else {
|
|
DBG("Not trusting SMBIOS because SPD reports only one module...\n");
|
|
trustSMBIOS = FALSE;
|
|
}
|
|
} else {
|
|
DBG("Not trusting SMBIOS because SPD reports less modules...\n");
|
|
trustSMBIOS = FALSE;
|
|
}
|
|
} else if (gRAM.SPD[0].InUse != gRAM.SMBIOS[0].InUse) {
|
|
// Never trust a sneaky SMBIOS!
|
|
DBG("Not trusting SMBIOS because it's being sneaky...\n");
|
|
trustSMBIOS = FALSE;
|
|
}
|
|
} else if (gRAM.SMBIOSInUse == 1) {
|
|
channels = 1;
|
|
}
|
|
}
|
|
}
|
|
if (trustSMBIOS) {
|
|
DBG("Trusting SMBIOS...\n");
|
|
}
|
|
// Determine expected slot count
|
|
expectedCount = (smbiosSettings.Memory.SlotCounts != 0) ? smbiosSettings.Memory.SlotCounts : gRAM.SPDInUse;
|
|
if (trustSMBIOS) {
|
|
// Use the smbios in use count
|
|
if (expectedCount < gRAM.SMBIOSInUse) {
|
|
expectedCount = gRAM.SMBIOSInUse;
|
|
}
|
|
// Check if smbios has a good total count
|
|
if ( (!gMobile || smbiosSettings.RamSlotCount == 2) && expectedCount < smbiosSettings.RamSlotCount ) {
|
|
if ( smbiosSettings.RamSlotCount > MAX_UINT8 ) {
|
|
log_technical_bug("smbiosSettings.RamSlotCount > MAX_UINT8");
|
|
expectedCount = MAX_RAM_SLOTS;
|
|
}else{
|
|
expectedCount = (UINT8)smbiosSettings.RamSlotCount;
|
|
}
|
|
}
|
|
} else {
|
|
// Use default value of two for mobile or four for desktop
|
|
if (gMobile) {
|
|
if (expectedCount < 2) {
|
|
expectedCount = 2;
|
|
}
|
|
} else if (expectedCount < 4) {
|
|
expectedCount = 4;
|
|
}
|
|
}
|
|
// Check for interleaved channels
|
|
if (channels >= 2) {
|
|
wrongSMBIOSBanks = ((gRAM.SMBIOS[1].InUse != gRAM.SPD[1].InUse) ||
|
|
(gRAM.SMBIOS[1].ModuleSize != gRAM.SPD[1].ModuleSize));
|
|
}
|
|
if (wrongSMBIOSBanks) {
|
|
DBG("Detected alternating SMBIOS channel banks\n");
|
|
}
|
|
// Determine if using triple or quadruple channel
|
|
if (smbiosSettings.Memory.UserChannels != 0) {
|
|
channels = smbiosSettings.Memory.UserChannels;
|
|
} else if (gRAM.SPDInUse == 0) {
|
|
if (trustSMBIOS) {
|
|
if ((gRAM.SMBIOSInUse % 4) == 0) {
|
|
// Quadruple channel
|
|
if ((wrongSMBIOSBanks &&
|
|
(gRAM.SMBIOS[0].InUse == gRAM.SMBIOS[1].InUse) &&
|
|
(gRAM.SMBIOS[0].InUse == gRAM.SMBIOS[2].InUse) &&
|
|
(gRAM.SMBIOS[0].InUse == gRAM.SMBIOS[3].InUse) &&
|
|
(gRAM.SMBIOS[0].ModuleSize == gRAM.SMBIOS[1].ModuleSize) &&
|
|
(gRAM.SMBIOS[0].ModuleSize == gRAM.SMBIOS[2].ModuleSize) &&
|
|
(gRAM.SMBIOS[0].ModuleSize == gRAM.SMBIOS[3].ModuleSize)) ||
|
|
((gRAM.SMBIOS[0].InUse == gRAM.SMBIOS[2].InUse) &&
|
|
(gRAM.SMBIOS[0].InUse == gRAM.SMBIOS[4].InUse) &&
|
|
(gRAM.SMBIOS[0].InUse == gRAM.SMBIOS[6].InUse) &&
|
|
(gRAM.SMBIOS[0].ModuleSize == gRAM.SMBIOS[2].ModuleSize) &&
|
|
(gRAM.SMBIOS[0].ModuleSize == gRAM.SMBIOS[4].ModuleSize) &&
|
|
(gRAM.SMBIOS[0].ModuleSize == gRAM.SMBIOS[6].ModuleSize))) {
|
|
channels = 4;
|
|
}
|
|
} else if ((gRAM.SMBIOSInUse % 3) == 0) {
|
|
// Triple channel
|
|
if ((wrongSMBIOSBanks &&
|
|
(gRAM.SMBIOS[0].InUse == gRAM.SMBIOS[1].InUse) &&
|
|
(gRAM.SMBIOS[0].InUse == gRAM.SMBIOS[2].InUse) &&
|
|
(gRAM.SMBIOS[0].ModuleSize == gRAM.SMBIOS[1].ModuleSize) &&
|
|
(gRAM.SMBIOS[0].ModuleSize == gRAM.SMBIOS[2].ModuleSize)) ||
|
|
((gRAM.SMBIOS[0].InUse == gRAM.SMBIOS[2].InUse) &&
|
|
(gRAM.SMBIOS[0].InUse == gRAM.SMBIOS[4].InUse) &&
|
|
(gRAM.SMBIOS[0].ModuleSize == gRAM.SMBIOS[2].ModuleSize) &&
|
|
(gRAM.SMBIOS[0].ModuleSize == gRAM.SMBIOS[4].ModuleSize))) {
|
|
channels = 3;
|
|
}
|
|
} else if (!wrongSMBIOSBanks && ((gRAM.SMBIOSInUse % 2) != 0)) {
|
|
channels = 1;
|
|
}
|
|
}
|
|
} else if ((gRAM.SPDInUse % 4) == 0) {
|
|
// Quadruple channel
|
|
if ((gRAM.SPD[0].InUse == gRAM.SPD[2].InUse) &&
|
|
(gRAM.SPD[0].InUse == gRAM.SPD[4].InUse) &&
|
|
(gRAM.SPD[0].InUse == gRAM.SPD[6].InUse) &&
|
|
(gRAM.SPD[0].ModuleSize == gRAM.SPD[2].ModuleSize) &&
|
|
(gRAM.SPD[0].ModuleSize == gRAM.SPD[4].ModuleSize) &&
|
|
(gRAM.SPD[0].ModuleSize == gRAM.SPD[6].ModuleSize)) {
|
|
channels = 4;
|
|
}
|
|
} else if ((gRAM.SPDInUse % 3) == 0) {
|
|
// Triple channel
|
|
if ((gRAM.SPD[0].InUse == gRAM.SPD[2].InUse) &&
|
|
(gRAM.SPD[0].InUse == gRAM.SPD[4].InUse) &&
|
|
(gRAM.SPD[0].ModuleSize == gRAM.SPD[2].ModuleSize) &&
|
|
(gRAM.SPD[0].ModuleSize == gRAM.SPD[4].ModuleSize)) {
|
|
channels = 3;
|
|
}
|
|
} else if ((gRAM.SPD[0].InUse != gRAM.SPD[2].InUse) ||
|
|
((gRAM.SPDInUse % 2) != 0)) {
|
|
channels = 1;
|
|
}
|
|
// Can't have less than the number of channels
|
|
if (expectedCount < channels) {
|
|
expectedCount = channels;
|
|
}
|
|
if (expectedCount > 0) {
|
|
--expectedCount;
|
|
}
|
|
DBG("Channels: %d\n", channels);
|
|
// Setup interleaved channel map
|
|
if (channels >= 2) {
|
|
UINT8 doubleChannels = (UINT8)channels << 1;
|
|
for (size_t Index = 0; Index < MAX_RAM_SLOTS; ++Index) {
|
|
channelMap[Index] = (UINT8)(((Index / doubleChannels) * doubleChannels) +
|
|
((Index / channels) % 2) + ((Index % channels) << 1));
|
|
}
|
|
} else {
|
|
for (size_t Index = 0; Index < MAX_RAM_SLOTS; ++Index) {
|
|
channelMap[Index] = (UINT8)Index;
|
|
}
|
|
}
|
|
DBG("Interleave:");
|
|
for (size_t Index = 0; Index < MAX_RAM_SLOTS; ++Index) {
|
|
DBG(" %d", channelMap[Index]);
|
|
}
|
|
DBG("\n");
|
|
// Memory Device
|
|
//
|
|
for (size_t Index = 0; Index < smbiosSettings.RamSlotCount; Index++) {
|
|
UINTN SMBIOSIndex = wrongSMBIOSBanks ? Index : channelMap[Index];
|
|
UINTN SPDIndex = channelMap[Index];
|
|
UINT8 bank = (UINT8)Index / channels;
|
|
if (!insertingEmpty && (Index > expectedCount) &&
|
|
!gRAM.SPD[SPDIndex].InUse && (!trustSMBIOS || !gRAM.SMBIOS[SMBIOSIndex].InUse)) {
|
|
continue;
|
|
}
|
|
SmbiosTable = GetSmbiosTableFromType(EntryPoint, EFI_SMBIOS_TYPE_MEMORY_DEVICE, SMBIOSIndex);
|
|
if (trustSMBIOS && gRAM.SMBIOS[SMBIOSIndex].InUse && (SmbiosTable.Raw != NULL)) {
|
|
DBG("trusted SMBIOS data:\n");
|
|
DBG("SmbiosTable.Type17->Vendor = %s\n", gRAM.SMBIOS[SMBIOSIndex].Vendor.c_str());
|
|
DBG("SmbiosTable.Type17->SerialNumber = %s\n", gRAM.SMBIOS[SMBIOSIndex].SerialNo.c_str());
|
|
DBG("SmbiosTable.Type17->PartNumber = %s\n", gRAM.SMBIOS[SMBIOSIndex].PartNo.c_str());
|
|
|
|
TableSize = SmbiosTableLength(SmbiosTable);
|
|
CopyMem((void*)newSmbiosTable.Type17, (void *)SmbiosTable.Type17, TableSize);
|
|
newSmbiosTable.Type17->AssetTag = 0;
|
|
if ( gRAM.SMBIOS[SMBIOSIndex].Vendor.notEmpty() ) {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->Manufacturer, gRAM.SMBIOS[SMBIOSIndex].Vendor);
|
|
// gSettings.MemoryManufacturer.takeValueFrom(gRAM.SMBIOS[SMBIOSIndex].Vendor);
|
|
} else {
|
|
// newSmbiosTable.Type17->Manufacturer = 0;
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->Manufacturer, unknown);
|
|
}
|
|
if ( gRAM.SMBIOS[SMBIOSIndex].SerialNo.notEmpty() ) {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->SerialNumber, gRAM.SMBIOS[SMBIOSIndex].SerialNo);
|
|
// gSettings.MemorySerialNumber.takeValueFrom(gRAM.SMBIOS[SMBIOSIndex].SerialNo);
|
|
} else {
|
|
// newSmbiosTable.Type17->SerialNumber = 0;
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->SerialNumber, unknown);
|
|
}
|
|
if ( gRAM.SMBIOS[SMBIOSIndex].PartNo.notEmpty() ) {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->PartNumber, gRAM.SMBIOS[SMBIOSIndex].PartNo);
|
|
// gSettings.MemoryPartNumber.takeValueFrom(gRAM.SMBIOS[SMBIOSIndex].PartNo);
|
|
DBG(" partNum=%s\n", gRAM.SMBIOS[SMBIOSIndex].PartNo.c_str());
|
|
} else {
|
|
// newSmbiosTable.Type17->PartNumber = 0;
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->PartNumber, unknown);
|
|
DBG(" partNum unknown\n");
|
|
}
|
|
} else {
|
|
ZeroMem((void*)newSmbiosTable.Type17, MAX_TABLE_SIZE);
|
|
newSmbiosTable.Type17->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_DEVICE;
|
|
newSmbiosTable.Type17->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE17);
|
|
newSmbiosTable.Type17->TotalWidth = 0xFFFF;
|
|
newSmbiosTable.Type17->DataWidth = 0xFFFF;
|
|
}
|
|
Once = TRUE;
|
|
newSmbiosTable.Type17->Hdr.Handle = (UINT16)(0x1100 + Index);
|
|
newSmbiosTable.Type17->FormFactor = (UINT8)(gMobile ? MemoryFormFactorSodimm : MemoryFormFactorDimm);
|
|
newSmbiosTable.Type17->TypeDetail.Synchronous = TRUE;
|
|
newSmbiosTable.Type17->DeviceSet = bank + 1;
|
|
newSmbiosTable.Type17->MemoryArrayHandle = mHandle16;
|
|
|
|
if (gRAM.SPD[SPDIndex].InUse) {
|
|
DBG("SPD data in use:\n");
|
|
DBG("SmbiosTable.Type17->Vendor = %s\n", gRAM.SPD[SPDIndex].Vendor.c_str());
|
|
DBG("SmbiosTable.Type17->SerialNumber = %s\n", gRAM.SPD[SPDIndex].SerialNo.c_str());
|
|
DBG("SmbiosTable.Type17->PartNumber = %s\n", gRAM.SPD[SPDIndex].PartNo.c_str());
|
|
|
|
if ( gRAM.SPD[SPDIndex].Vendor.notEmpty() ) {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->Manufacturer, gRAM.SPD[SPDIndex].Vendor);
|
|
// gSettings.MemoryManufacturer.takeValueFrom(gRAM.SPD[SPDIndex].Vendor);
|
|
} else {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->Manufacturer, unknown);
|
|
}
|
|
if ( gRAM.SPD[SPDIndex].SerialNo.notEmpty() ) {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->SerialNumber, gRAM.SPD[SPDIndex].SerialNo);
|
|
// gSettings.MemorySerialNumber.takeValueFrom(gRAM.SPD[SPDIndex].SerialNo);
|
|
} else {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->SerialNumber, unknown);
|
|
}
|
|
if ( gRAM.SPD[SPDIndex].PartNo.notEmpty() ) {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->PartNumber, gRAM.SPD[SPDIndex].PartNo);
|
|
// gSettings.MemoryPartNumber.takeValueFrom(gRAM.SPD[SPDIndex].PartNo);
|
|
} else {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->PartNumber, unknown);
|
|
}
|
|
if (gRAM.Frequency > gRAM.SPD[SPDIndex].Frequency) {
|
|
newSmbiosTable.Type17->Speed = (UINT16)gRAM.Frequency;
|
|
} else {
|
|
newSmbiosTable.Type17->Speed = (UINT16)gRAM.SPD[SPDIndex].Frequency;
|
|
}
|
|
if (gRAM.SPD[SPDIndex].ModuleSize > 0x7FFF) {
|
|
newSmbiosTable.Type17->Size = 0x7FFF;
|
|
newSmbiosTable.Type17->ExtendedSize = gRAM.SPD[SPDIndex].ModuleSize;
|
|
} else {
|
|
newSmbiosTable.Type17->Size = (UINT16)gRAM.SPD[SPDIndex].ModuleSize;
|
|
}
|
|
newSmbiosTable.Type17->MemoryType = gRAM.SPD[SPDIndex].Type;
|
|
}
|
|
if (trustSMBIOS && gRAM.SMBIOS[SMBIOSIndex].InUse &&
|
|
(newSmbiosTable.Type17->Speed < (UINT16)gRAM.SMBIOS[SMBIOSIndex].Frequency)) {
|
|
DBG("Type17->Speed corrected by SMBIOS from %dMHz to %dMHz\n", newSmbiosTable.Type17->Speed, gRAM.SMBIOS[SMBIOSIndex].Frequency);
|
|
newSmbiosTable.Type17->Speed = (UINT16)gRAM.SMBIOS[SMBIOSIndex].Frequency;
|
|
}
|
|
if (trustSMBIOS && gRAM.SMBIOS[SMBIOSIndex].InUse &&
|
|
gRAM.SMBIOS[SMBIOSIndex].Vendor.notEmpty() &&
|
|
( gRAM.SPD[SPDIndex].Vendor.isEmpty() || gRAM.SPD[SPDIndex].Vendor == "NoName"_XS8 )
|
|
) {
|
|
DBG("Type17->Manufacturer corrected by SMBIOS from NoName to %s\n", gRAM.SMBIOS[SMBIOSIndex].Vendor.c_str());
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->Manufacturer, gRAM.SMBIOS[SMBIOSIndex].Vendor);
|
|
}
|
|
|
|
// gSettings.MemorySpeed.S8Printf("%d", newSmbiosTable.Type17->Speed);
|
|
|
|
// Assume DDR3 unless explicitly set to DDR2/DDR/DDR4
|
|
if ((newSmbiosTable.Type17->MemoryType != MemoryTypeDdr2) &&
|
|
(newSmbiosTable.Type17->MemoryType != MemoryTypeDdr4) &&
|
|
(newSmbiosTable.Type17->MemoryType != MemoryTypeDdr)) {
|
|
newSmbiosTable.Type17->MemoryType = MemoryTypeDdr3;
|
|
}
|
|
|
|
//now I want to update deviceLocator and bankLocator
|
|
if (isMacPro) {
|
|
deviceLocator.S8Printf("DIMM%zd", Index + 1);
|
|
bankLocator.setEmpty();
|
|
} else {
|
|
deviceLocator.S8Printf("DIMM%d", bank);
|
|
bankLocator.S8Printf("BANK %zu", Index % channels);
|
|
}
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->DeviceLocator, deviceLocator);
|
|
if (isMacPro) {
|
|
newSmbiosTable.Type17->BankLocator = 0; //like in MacPro5,1
|
|
} else {
|
|
UpdateSmbiosString(newSmbiosTable, &newSmbiosTable.Type17->BankLocator, bankLocator);
|
|
}
|
|
DBG("SMBIOS Type 17 Index = %zd => %llu %llu:\n", Index, SMBIOSIndex, SPDIndex);
|
|
if (newSmbiosTable.Type17->Size == 0) {
|
|
DBG("%s %s EMPTY\n", bankLocator.c_str(), deviceLocator.c_str());
|
|
newSmbiosTable.Type17->MemoryType = 0; //MemoryTypeUnknown;
|
|
} else {
|
|
insertingEmpty = FALSE;
|
|
DBG("%s %s %dMHz %dMB(Ext:%dMB)\n", bankLocator.c_str(), deviceLocator.c_str(), newSmbiosTable.Type17->Speed,
|
|
newSmbiosTable.Type17->Size, newSmbiosTable.Type17->ExtendedSize);
|
|
if (newSmbiosTable.Type17->Size == 0x7FFF) {
|
|
mTotalSystemMemory += newSmbiosTable.Type17->ExtendedSize; //Mb
|
|
} else {
|
|
mTotalSystemMemory += newSmbiosTable.Type17->Size; //Mb
|
|
}
|
|
mMemory17[Index] = (UINT16)mTotalSystemMemory;
|
|
// DBG("mTotalSystemMemory = %d\n", mTotalSystemMemory);
|
|
}
|
|
newSmbiosTable.Type17->MemoryErrorInformationHandle = 0xFFFF;
|
|
if (smbiosSettings.Attribute != -1) {
|
|
newSmbiosTable.Type17->Attributes = smbiosSettings.Attribute;
|
|
}
|
|
mHandle17[Index] = LogSmbiosTable(newSmbiosTable);
|
|
}
|
|
if (mTotalSystemMemory > 0) {
|
|
DBG("mTotalSystemMemory = %d\n", mTotalSystemMemory);
|
|
}
|
|
}
|
|
|
|
void
|
|
PatchTableType19 (const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
//
|
|
// Generate Memory Array Mapped Address info (TYPE 19)
|
|
//
|
|
/*
|
|
/// This structure provides the address mapping for a Physical Memory Array.
|
|
/// One structure is present for each contiguous address range described.
|
|
///
|
|
typedef struct {
|
|
SMBIOS_STRUCTURE Hdr;
|
|
UINT32 StartingAddress;
|
|
UINT32 EndingAddress;
|
|
UINT16 MemoryArrayHandle;
|
|
UINT8 PartitionWidth;
|
|
} SMBIOS_TABLE_TYPE19;
|
|
|
|
*/
|
|
//Slice - I created one table as a sum of all other. It is needed for SetupBrowser
|
|
UINT32 TotalEnd = 0;
|
|
UINT8 PartWidth = 1;
|
|
UINT16 SomeHandle = 0x1300; //as a common rule handle=(type<<8 + index)
|
|
for (size_t Index = 0; Index < smbiosSettings.RamSlotCount; Index++) {
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS, Index);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
continue;
|
|
}
|
|
if (SmbiosTable.Type19->EndingAddress > TotalEnd) {
|
|
TotalEnd = SmbiosTable.Type19->EndingAddress;
|
|
}
|
|
PartWidth = SmbiosTable.Type19->PartitionWidth;
|
|
//SomeHandle = SmbiosTable.Type19->Hdr.Handle;
|
|
}
|
|
if (TotalEnd == 0) {
|
|
TotalEnd = (UINT32)(LShiftU64(mTotalSystemMemory, 10) - 1);
|
|
}
|
|
gTotalMemory = LShiftU64(mTotalSystemMemory, 20);
|
|
ZeroMem((void*)newSmbiosTable.Type19, MAX_TABLE_SIZE);
|
|
newSmbiosTable.Type19->Hdr.Type = EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS;
|
|
newSmbiosTable.Type19->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE19);
|
|
newSmbiosTable.Type19->Hdr.Handle = SomeHandle;
|
|
newSmbiosTable.Type19->MemoryArrayHandle = mHandle16;
|
|
newSmbiosTable.Type19->StartingAddress = 0;
|
|
newSmbiosTable.Type19->EndingAddress = TotalEnd;
|
|
newSmbiosTable.Type19->PartitionWidth = PartWidth;
|
|
mHandle19 = LogSmbiosTable(newSmbiosTable);
|
|
return ;
|
|
}
|
|
|
|
void PatchTableType20 (const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
UINTN j = 0, k = 0, m = 0;
|
|
//
|
|
// Generate Memory Array Mapped Address info (TYPE 20)
|
|
// not needed neither for Apple nor for EFI
|
|
m = 0;
|
|
for (size_t Index = 0; Index < smbiosSettings.RamSlotCount; Index++) {
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_MEMORY_DEVICE_MAPPED_ADDRESS, Index);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
return ;
|
|
}
|
|
TableSize = SmbiosTableLength(SmbiosTable);
|
|
ZeroMem((void*)newSmbiosTable.Type20, MAX_TABLE_SIZE);
|
|
CopyMem((void*)newSmbiosTable.Type20, (void*)SmbiosTable.Type20, TableSize);
|
|
for (j=0; j < smbiosSettings.RamSlotCount; j++) {
|
|
//EndingAddress in kb while mMemory in Mb
|
|
if ((UINT32)(mMemory17[j] << 10) > newSmbiosTable.Type20->EndingAddress) {
|
|
newSmbiosTable.Type20->MemoryDeviceHandle = mHandle17[j];
|
|
k = newSmbiosTable.Type20->EndingAddress;
|
|
m += mMemory17[j];
|
|
DBG("Type20[%zu]->End = 0x%llX, Type17[%llu] = %llX\n",
|
|
Index, k, j, m);
|
|
// DBG(" MemoryDeviceHandle = 0x%X\n", newSmbiosTable.Type20->MemoryDeviceHandle);
|
|
mMemory17[j] = 0; // used
|
|
break;
|
|
}
|
|
// DBG("\n");
|
|
}
|
|
|
|
newSmbiosTable.Type20->MemoryArrayMappedAddressHandle = mHandle19;
|
|
//
|
|
// Record Smbios Type 20
|
|
//
|
|
LogSmbiosTable(newSmbiosTable);
|
|
}
|
|
return ;
|
|
}
|
|
|
|
void GetTableType32(SmbiosDiscoveredSettings* smbiosSettings)
|
|
{
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
return;
|
|
}
|
|
gBootStatus = SmbiosTable.Type32->BootStatus;
|
|
}
|
|
|
|
/**
|
|
* Apple Specific Structures.
|
|
* Firmware Table, FirmwareVolume (TYPE 128).
|
|
*/
|
|
void PatchTableType128(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
/**
|
|
* Useful information.
|
|
*
|
|
* FW_REGION_RESERVED = 0,
|
|
* FW_REGION_RECOVERY = 1,
|
|
* FW_REGION_MAIN = 2,
|
|
* gHob->MemoryAbove1MB.PhysicalStart + ResourceLength or fix as 0x200000 - 0x600000,
|
|
* FW_REGION_NVRAM = 3,
|
|
* FW_REGION_CONFIG = 4,
|
|
* FW_REGION_DIAGVAULT = 5.
|
|
*/
|
|
|
|
// Get the existing 128 table if exists.
|
|
//SmbiosTable = GetSmbiosTableFromType (EntryPoint, 128, 0);
|
|
|
|
// initialise new table
|
|
ZeroMem((void*)newSmbiosTable.Type128, MAX_TABLE_SIZE);
|
|
|
|
// common rules
|
|
newSmbiosTable.Type128->Hdr.Type = 128;
|
|
newSmbiosTable.Type128->Hdr.Length = sizeof(SMBIOS_TABLE_TYPE128);
|
|
newSmbiosTable.Type128->Hdr.Handle = 0x8000;
|
|
|
|
// set firmware-features, example: 0x80001417, imac11,2 -> 0x1403.
|
|
newSmbiosTable.Type128->FirmwareFeatures = smbiosSettings.FirmwareFeatures;
|
|
// set firmware-features mask
|
|
newSmbiosTable.Type128->FirmwareFeaturesMask = smbiosSettings.FirmwareFeaturesMask;
|
|
|
|
/**
|
|
* TODO: I have an idea that region should be the same as Efivar.bin
|
|
* @author Slice
|
|
*/
|
|
newSmbiosTable.Type128->RegionCount = 1;
|
|
newSmbiosTable.Type128->RegionType[0] = FW_REGION_MAIN;
|
|
//UpAddress = mTotalSystemMemory << 20; //Mb -> b
|
|
//gHob->MemoryAbove1MB.PhysicalStart;
|
|
newSmbiosTable.Type128->FlashMap[0].StartAddress = 0xFFE00000; //0xF0000;
|
|
//gHob->MemoryAbove1MB.PhysicalStart + gHob->MemoryAbove1MB.ResourceLength - 1;
|
|
newSmbiosTable.Type128->FlashMap[0].EndAddress = 0xFFEFFFFF;
|
|
//newSmbiosTable.Type128->RegionType[1] = FW_REGION_NVRAM; //Efivar
|
|
//newSmbiosTable.Type128->FlashMap[1].StartAddress = 0x15000; //0xF0000;
|
|
//newSmbiosTable.Type128->FlashMap[1].EndAddress = 0x1FFFF;
|
|
//region type=1 also present in mac
|
|
|
|
// log the new, 128, sbmios table
|
|
LogSmbiosTable(newSmbiosTable);
|
|
return ;
|
|
}
|
|
|
|
void PatchTableType130(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
//
|
|
// MemorySPD (TYPE 130)
|
|
// TODO: read SPD and place here. But for a what?
|
|
//
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, 130, 0);
|
|
if (SmbiosTable.Raw == NULL) {
|
|
return ;
|
|
}
|
|
//
|
|
// Log Smbios Record Type130
|
|
//
|
|
LogSmbiosTable(SmbiosTable);
|
|
return ;
|
|
}
|
|
|
|
|
|
|
|
void PatchTableType131(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
// Get Table Type131
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, 131, 0);
|
|
if (SmbiosTable.Raw != NULL) {
|
|
MsgLog("Table 131 is present, CPUType=%hX\n", SmbiosTable.Type131->ProcessorType.Type);
|
|
MsgLog("Change to: %hX\n", smbiosSettings.CpuType);
|
|
}
|
|
|
|
ZeroMem((void*)newSmbiosTable.Type131, MAX_TABLE_SIZE);
|
|
newSmbiosTable.Type131->Hdr.Type = 131;
|
|
newSmbiosTable.Type131->Hdr.Length = sizeof(SMBIOS_STRUCTURE)+2;
|
|
newSmbiosTable.Type131->Hdr.Handle = 0x8300; //common rule
|
|
// Patch ProcessorType
|
|
newSmbiosTable.Type131->ProcessorType.Type = smbiosSettings.CpuType;
|
|
Handle = LogSmbiosTable(newSmbiosTable);
|
|
return;
|
|
}
|
|
|
|
void PatchTableType132(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
if (!smbiosSettings.SetTable132) {
|
|
//DBG("disabled Table 132\n");
|
|
return;
|
|
}
|
|
|
|
// Get Table Type132
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, 132, 0);
|
|
if (SmbiosTable.Raw != NULL) {
|
|
MsgLog("Table 132 is present, QPI=%hX\n", SmbiosTable.Type132->ProcessorBusSpeed);
|
|
MsgLog("Change to: %hX\n", smbiosSettings.QPI);
|
|
}
|
|
|
|
ZeroMem((void*)newSmbiosTable.Type132, MAX_TABLE_SIZE);
|
|
newSmbiosTable.Type132->Hdr.Type = 132;
|
|
newSmbiosTable.Type132->Hdr.Length = sizeof(SMBIOS_STRUCTURE)+2;
|
|
newSmbiosTable.Type132->Hdr.Handle = 0x8400; //ugly
|
|
|
|
// Patch ProcessorBusSpeed
|
|
if(smbiosSettings.QPI){
|
|
newSmbiosTable.Type132->ProcessorBusSpeed = smbiosSettings.QPI;
|
|
} else {
|
|
newSmbiosTable.Type132->ProcessorBusSpeed = (UINT16)(LShiftU64(DivU64x32(smbiosSettings.ExternalClock, Kilo), 2));
|
|
}
|
|
|
|
Handle = LogSmbiosTable(newSmbiosTable);
|
|
return;
|
|
}
|
|
|
|
void PatchTableType133(const SmbiosInjectedSettings& smbiosSettings)
|
|
{
|
|
if (smbiosSettings.gPlatformFeature == 0xFFFF) {
|
|
return;
|
|
}
|
|
// Get Table Type133
|
|
SmbiosTable = GetSmbiosTableFromType (EntryPoint, 133, 0);
|
|
if (SmbiosTable.Raw != NULL) {
|
|
MsgLog("Table 133 is present, PlatformFeature=%llX\n", SmbiosTable.Type133->PlatformFeature);
|
|
MsgLog("Change to: %llX\n", smbiosSettings.gPlatformFeature);
|
|
}
|
|
ZeroMem((void*)newSmbiosTable.Type133, MAX_TABLE_SIZE);
|
|
newSmbiosTable.Type133->Hdr.Type = 133;
|
|
newSmbiosTable.Type133->Hdr.Length = sizeof(SMBIOS_STRUCTURE)+8;
|
|
newSmbiosTable.Type133->Hdr.Handle = 0x8500; //ugly
|
|
// newSmbiosTable.Type133->PlatformFeature = smbiosSettings.gPlatformFeature;
|
|
CopyMem((void*)&newSmbiosTable.Type133->PlatformFeature, (void*)&smbiosSettings.gPlatformFeature, 8);
|
|
Handle = LogSmbiosTable(newSmbiosTable);
|
|
return;
|
|
}
|
|
|
|
EFI_STATUS PrepatchSmbios(SmbiosDiscoveredSettings* smbiosSettings)
|
|
{
|
|
EFI_STATUS Status = EFI_SUCCESS;
|
|
UINTN BufferLen;
|
|
EFI_PHYSICAL_ADDRESS BufferPtr;
|
|
// UINTN Index;
|
|
DbgHeader("Get Smbios");
|
|
|
|
// Get SMBIOS Tables
|
|
Smbios = FindOemSMBIOSPtr();
|
|
// DBG("OEM SMBIOS EPS=%p\n", Smbios);
|
|
// DBG("OEM Tables = %X\n", ((SMBIOS_TABLE_ENTRY_POINT*)Smbios)->TableAddress);
|
|
if (!Smbios) {
|
|
// DBG("Original SMBIOS System Table not found! Getting from Hob...\n");
|
|
Smbios = GetSmbiosTablesFromHob();
|
|
// DBG("HOB SMBIOS EPS=%p\n", Smbios);
|
|
if (!Smbios) {
|
|
// DBG("And here SMBIOS System Table not found! Trying System table ...\n");
|
|
// this should work on any UEFI
|
|
Smbios = GetSmbiosTablesFromConfigTables();
|
|
// DBG("ConfigTables SMBIOS EPS=%p\n", Smbios);
|
|
if (!Smbios) {
|
|
// DBG("And here SMBIOS System Table not found! Exiting...\n");
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
}
|
|
}
|
|
|
|
//original EPS and tables
|
|
EntryPoint = (SMBIOS_TABLE_ENTRY_POINT*)Smbios; //yes, it is old SmbiosEPS
|
|
// Smbios = (void*)(UINT32)EntryPoint->TableAddress; // here is flat Smbios database. Work with it
|
|
//how many we need to add for tables 128, 130, 131, 132 and for strings?
|
|
BufferLen = 0x20 + EntryPoint->TableLength + 64 * 10;
|
|
//new place for EPS and tables. Allocated once for both
|
|
BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
|
|
Status = gBS->AllocatePages (AllocateMaxAddress, EfiACPIMemoryNVS, /*EfiACPIReclaimMemory, */
|
|
EFI_SIZE_TO_PAGES(BufferLen), &BufferPtr);
|
|
if (EFI_ERROR(Status)) {
|
|
// DBG("There is error allocating pages in EfiACPIMemoryNVS!\n");
|
|
Status = gBS->AllocatePages (AllocateMaxAddress, /*EfiACPIMemoryNVS, */EfiACPIReclaimMemory,
|
|
ROUND_PAGE(BufferLen)/EFI_PAGE_SIZE, &BufferPtr);
|
|
if (EFI_ERROR(Status)) {
|
|
// DBG("There is error allocating pages in EfiACPIReclaimMemory!\n");
|
|
}
|
|
}
|
|
// DBG("Buffer @ %p\n", BufferPtr);
|
|
if (BufferPtr) {
|
|
SmbiosEpsNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr; //this is new EPS
|
|
} else {
|
|
SmbiosEpsNew = EntryPoint; //is it possible?!
|
|
}
|
|
ZeroMem(SmbiosEpsNew, BufferLen);
|
|
// DBG("New EntryPoint = %p\n", SmbiosEpsNew);
|
|
NumberOfRecords = 0;
|
|
MaxStructureSize = 0;
|
|
//preliminary fill EntryPoint with some data
|
|
CopyMem((void *)SmbiosEpsNew, (void *)EntryPoint, sizeof(SMBIOS_TABLE_ENTRY_POINT));
|
|
|
|
|
|
Smbios = (void*)(SmbiosEpsNew + 1); //this is a C-language trick. I hate it but use. +1 means +sizeof(SMBIOS_TABLE_ENTRY_POINT)
|
|
Current = (UINT8*)Smbios; //begin fill tables from here
|
|
SmbiosEpsNew->TableAddress = (UINT32)(UINTN)Current;
|
|
SmbiosEpsNew->EntryPointLength = sizeof(SMBIOS_TABLE_ENTRY_POINT); // no matter on other versions
|
|
if (smbiosSettings->SmbiosVersion != 0) {
|
|
SmbiosEpsNew->MajorVersion = (UINT8)(smbiosSettings->SmbiosVersion >> 8);
|
|
SmbiosEpsNew->MinorVersion = (UINT8)(smbiosSettings->SmbiosVersion & 0xFF);
|
|
SmbiosEpsNew->SmbiosBcdRevision = (SmbiosEpsNew->MajorVersion << 4) + SmbiosEpsNew->MinorVersion;
|
|
}
|
|
else {
|
|
//old behavior
|
|
SmbiosEpsNew->MajorVersion = 2;
|
|
SmbiosEpsNew->MinorVersion = 4;
|
|
SmbiosEpsNew->SmbiosBcdRevision = 0x24; //Slice - we want to have v2.6 but Apple still uses 2.4, let it be default value
|
|
}
|
|
|
|
//Collect information for use in menu
|
|
GetTableType1(smbiosSettings);
|
|
GetTableType2(smbiosSettings);
|
|
GetTableType3(smbiosSettings);
|
|
GetTableType4(smbiosSettings);
|
|
GetTableType16(smbiosSettings);
|
|
GetTableType17(smbiosSettings);
|
|
GetTableType32(smbiosSettings); //get BootStatus here to decide what to do
|
|
MsgLog("Boot status=%hhX\n", gBootStatus);
|
|
//for example the bootloader may go to Recovery is BootStatus is Fail
|
|
return Status;
|
|
}
|
|
|
|
void PatchSmbios(const SmbiosInjectedSettings& smbiosSettings) //continue
|
|
{
|
|
|
|
DbgHeader("PatchSmbios");
|
|
|
|
newSmbiosTable.Raw = (UINT8*)AllocateZeroPool(MAX_TABLE_SIZE);
|
|
//Slice - order of patching is significant
|
|
PatchTableType0(smbiosSettings);
|
|
PatchTableType1(smbiosSettings);
|
|
PatchTableType2(smbiosSettings);
|
|
PatchTableType3(smbiosSettings);
|
|
PatchTableType7(smbiosSettings); //we should know handles before patch Table4
|
|
PatchTableType4(smbiosSettings);
|
|
// PatchTableType6(smbiosSettings);
|
|
PatchTableType9(smbiosSettings);
|
|
if (!smbiosSettings.NoRomInfo) {
|
|
PatchTableType11(smbiosSettings);
|
|
}
|
|
PatchTableTypeSome();
|
|
PatchTableType17(smbiosSettings);
|
|
PatchTableType16(smbiosSettings);
|
|
PatchTableType19(smbiosSettings);
|
|
PatchTableType20(smbiosSettings);
|
|
PatchTableType128(smbiosSettings);
|
|
PatchTableType130(smbiosSettings);
|
|
PatchTableType131(smbiosSettings);
|
|
PatchTableType132(smbiosSettings);
|
|
PatchTableType133(smbiosSettings);
|
|
AddSmbiosEndOfTable();
|
|
if(MaxStructureSize > MAX_TABLE_SIZE){
|
|
// DBG("Too long SMBIOS!\n");
|
|
}
|
|
FreePool((void*)newSmbiosTable.Raw);
|
|
|
|
// there is no need to keep all tables in numeric order. It is not needed
|
|
// neither by specs nor by AppleSmbios.kext
|
|
}
|
|
|
|
void FinalizeSmbios(const SmbiosInjectedSettings& smbiosSettings) //continue
|
|
{
|
|
EFI_PEI_HOB_POINTERS GuidHob;
|
|
EFI_PEI_HOB_POINTERS HobStart;
|
|
EFI_PHYSICAL_ADDRESS *Table = NULL;
|
|
//UINTN TableLength = 0;
|
|
// BOOLEAN FoundTable3 = FALSE;
|
|
|
|
// Get Hob List
|
|
HobStart.Raw = (__typeof_am__(HobStart.Raw))GetHobList();
|
|
|
|
if (HobStart.Raw != NULL) {
|
|
// find SMBIOS in hob
|
|
for (size_t Index = 0; Index < sizeof (gTableGuidArray) / sizeof (*gTableGuidArray); ++Index) {
|
|
GuidHob.Raw = (__typeof_am__(HobStart.Raw))GetNextGuidHob (gTableGuidArray[Index], HobStart.Raw);
|
|
if (GuidHob.Raw != NULL) {
|
|
Table = (__typeof_am__(Table))GET_GUID_HOB_DATA (GuidHob.Guid);
|
|
//TableLength = GET_GUID_HOB_DATA_SIZE (GuidHob);
|
|
if (Table != NULL) {
|
|
if (Index != 0) {
|
|
// FoundTable3 = TRUE; //don't know how to use it. Real Mac have table3 in the format of table2
|
|
DBG("Found SMBIOS3 Table\n");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Install SMBIOS in Config table
|
|
SmbiosEpsNew->TableLength = (UINT16)((UINT32)(UINTN)Current - (UINT32)(UINTN)Smbios);
|
|
SmbiosEpsNew->NumberOfSmbiosStructures = NumberOfRecords;
|
|
SmbiosEpsNew->MaxStructureSize = MaxStructureSize;
|
|
SmbiosEpsNew->IntermediateChecksum = 0;
|
|
SmbiosEpsNew->IntermediateChecksum = (UINT8)(256 - Checksum8((UINT8*)SmbiosEpsNew + 0x10, SmbiosEpsNew->EntryPointLength - 0x10));
|
|
SmbiosEpsNew->EntryPointStructureChecksum = 0;
|
|
SmbiosEpsNew->EntryPointStructureChecksum = (UINT8)(256 - Checksum8((UINT8*)SmbiosEpsNew, SmbiosEpsNew->EntryPointLength));
|
|
//DBG("SmbiosEpsNew->TableLength = %d\n", SmbiosEpsNew->TableLength);
|
|
//DBG("SmbiosEpsNew->EntryPointLength = %d\n", SmbiosEpsNew->EntryPointLength);
|
|
//DBG("SmbiosEpsNew->MaxStructureSize = %d\n", SmbiosEpsNew->MaxStructureSize);
|
|
//DBG("DMI checksum = %d\n", Checksum8((UINT8*)SmbiosEpsNew, SmbiosEpsNew->EntryPointLength));
|
|
//XString8 tmpDbg;
|
|
//XString8 tmptmpDbg;
|
|
//tmpDbg.dataSized(SmbiosEpsNew->TableLength*3+5*SmbiosEpsNew->TableLength/32+128);
|
|
//for ( size_t i = 0 ; i < SmbiosEpsNew->TableLength ; ) {
|
|
// size_t j;
|
|
// for ( j = 0 ; j < SmbiosEpsNew->TableLength && j < 32 ; j++ ) {
|
|
//// DBG("%02x ", ((UINT8*)(SmbiosEpsNew+1))[i+j] );
|
|
// tmptmpDbg.S8Printf("%02x ", ((UINT8*)(SmbiosEpsNew+1))[i+j] );
|
|
// tmpDbg.strcat(tmptmpDbg);
|
|
// }
|
|
//// DBG(" - ");
|
|
// tmptmpDbg.S8Printf(" - ");
|
|
// tmpDbg.strcat(tmptmpDbg);
|
|
// for ( j = 0 ; j < SmbiosEpsNew->TableLength && j < 32 ; j++ ) {
|
|
// UINT8 c = ((UINT8*)(SmbiosEpsNew+1))[i+j];
|
|
//// DBG("%c ", c > 32 ? c : '.');
|
|
// tmptmpDbg.S8Printf("%c", c > 32 ? c : '.');
|
|
// tmpDbg.strcat(tmptmpDbg);
|
|
// }
|
|
//// DBG("\n");
|
|
// tmptmpDbg.S8Printf("\n");
|
|
// tmpDbg.strcat(tmptmpDbg);
|
|
// i += j;
|
|
//}
|
|
//DBG("%s", tmpDbg.c_str());
|
|
//auto foo = SmbiosEpsNew;
|
|
|
|
//
|
|
// syscl: one more step: check if we need remap SMBIOS Table Type 1 Guid
|
|
//
|
|
// to fix Dell's SMBIOS truncate credit David Passmore
|
|
//
|
|
if (smbiosSettings.KPDELLSMBIOS)
|
|
{
|
|
//
|
|
// syscl: remap smbios table 1 guid
|
|
//
|
|
DBG("Remap smbios table type 1 guid.\n");
|
|
gBS->InstallConfigurationTable (&gRemapEfiSmbiosTableGuid, (void*)SmbiosEpsNew);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// use origin smbios guid table
|
|
//
|
|
DBG("Use origin smbios table type 1 guid.\n");
|
|
gBS->InstallConfigurationTable (&gEfiSmbiosTableGuid, (void*)SmbiosEpsNew);
|
|
}
|
|
|
|
gST->Hdr.CRC32 = 0;
|
|
gBS->CalculateCrc32 ((UINT8 *) &gST->Hdr, gST->Hdr.HeaderSize, &gST->Hdr.CRC32);
|
|
|
|
//
|
|
// Fix it in Hob list
|
|
//
|
|
// No smbios in Hob list on Aptio, so no need to update it there.
|
|
// But even if it would be there, loading of macOS would overwrite it
|
|
// since this list on my board is inside space needed for kernel
|
|
// (ha! like many other UEFI stuff).
|
|
// It's enough to add it to Conf.table.
|
|
//
|
|
if (Table != NULL) {
|
|
//PauseForKey(L"installing SMBIOS in Hob\n");
|
|
*Table = (UINT32)(UINTN)SmbiosEpsNew;
|
|
}
|
|
// egSaveFile(NULL, SWPrintf("%ls\\misc\\smbios.bin", self.getCloverDirFullPath().wc_str()).wc_str(), (UINT8*)(UINTN)SmbiosEpsNew, SmbiosEpsNew->TableLength);
|
|
return;
|
|
}
|
|
|
|
|