OcCpuLib: Implement Apple nForce CPU frequency reading

This commit is contained in:
vit9696 2021-03-13 01:12:43 +03:00
parent 6f914f98be
commit 5a69caa7e0
8 changed files with 273 additions and 5 deletions

View File

@ -15,7 +15,8 @@ OpenCore Changelog
- Fixed OpenCanopy sometimes cutting off shown boot entries
- Further improved CPU frequency calculation on legacy CPUs
- Fixed SMBIOS SMC version encoding sequence
- Implemented TSC frequency reading from Apple Platform Info
- Added TSC frequency reading from Apple Platform Info
- Added TSC frequency reading for Apple devices with nForce chipsets
#### v0.6.7
- Fixed ocvalidate return code to be non-zero when issues are found

View File

@ -128,7 +128,7 @@ OcLoadAndRunImage (
@param[in] PlatformInfo Apple Platform Info protocol.
@param[in] DataGuid Resource GUID identifier.
@param[in,out] Size Maximum size allowed.
@param[in,out] Size Maximum size allowed, updated to actual size on success.
@param[out] Data Data read from Apple Platform Info protocol.
@retval EFI_SUCCESS on success.
@ -141,13 +141,31 @@ OcReadApplePlatformFirstData (
OUT VOID *Data
);
/**
Read first data from Apple Platform Info protocol allocating memory from pool.
@param[in] PlatformInfo Apple Platform Info protocol.
@param[in] DataGuid Resource GUID identifier.
@param[in,out] Size Size of the entry.
@param[out] Data Data read from Apple Platform Info protocol allocated from pool.
@retval EFI_SUCCESS on success.
**/
EFI_STATUS
OcReadApplePlatformFirstDataAlloc (
IN APPLE_PLATFORM_INFO_DATABASE_PROTOCOL *PlatformInfo,
IN EFI_GUID *DataGuid,
OUT UINT32 *Size,
OUT VOID **Data
);
/**
Read data from Apple Platform Info protocol.
@param[in] PlatformInfo Apple Platform Info protocol.
@param[in] DataGuid Resource GUID identifier.
@param[in] HobGuid Hob GUID identifier.
@param[in,out] Size Maximum size allowed.
@param[in,out] Size Maximum size allowed, updated to actual size on success.
@param[out] Data Data read from Apple Platform Info protocol.
@retval EFI_SUCCESS on success.

View File

@ -20,6 +20,14 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
// gAppleFsbFrequencyPlatformInfoGuid
extern EFI_GUID gAppleFsbFrequencyPlatformInfoGuid;
// APPLE_FSB_FREQUENCY_LIST_PLATFORM_INFO_GUID
#define APPLE_FSB_FREQUENCY_LIST_PLATFORM_INFO_GUID \
{ 0xF55EE371, 0xD19E, 0x4AAA, \
{ 0xA9, 0x7B, 0xC1, 0xB1, 0x28, 0x4C, 0xB3, 0x7C } }
// gAppleFsbFrequencyListPlatformInfoGuid
extern EFI_GUID gAppleFsbFrequencyListPlatformInfoGuid;
// APPLE_PLATFORM_INFO_KEYBOARD_GUID
#define APPLE_PLATFORM_INFO_KEYBOARD_GUID \
{ 0x51871CB9, 0xE25D, 0x44B4, \

View File

@ -0,0 +1,93 @@
/*++
Copyright (c) 2004, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
CpuIO.h
Abstract:
CPU IO Protocol as defined in Tiano
This code abstracts the CPU IO Protocol
--*/
#ifndef _CPUIO_H_
#define _CPUIO_H_
#define EFI_CPU_IO_PROTOCOL_GUID \
{ \
0xB0732526, 0x38C8, 0x4b40, { 0x88, 0x77, 0x61, 0xC7, 0xB0, 0x6A, 0xAC, 0x45 } \
}
typedef struct EFI_CPU_IO_PROTOCOL_ EFI_CPU_IO_PROTOCOL;
//
// *******************************************************
// EFI_CPU_IO_PROTOCOL_WIDTH
// *******************************************************
//
typedef enum {
EfiCpuIoWidthUint8,
EfiCpuIoWidthUint16,
EfiCpuIoWidthUint32,
EfiCpuIoWidthUint64,
EfiCpuIoWidthFifoUint8,
EfiCpuIoWidthFifoUint16,
EfiCpuIoWidthFifoUint32,
EfiCpuIoWidthFifoUint64,
EfiCpuIoWidthFillUint8,
EfiCpuIoWidthFillUint16,
EfiCpuIoWidthFillUint32,
EfiCpuIoWidthFillUint64,
EfiCpuIoWidthMaximum
} EFI_CPU_IO_PROTOCOL_WIDTH;
//
// *******************************************************
// EFI_CPU_IO_PROTOCOL_IO_MEM
// *******************************************************
//
typedef
EFI_STATUS
EFIAPI
(EFIAPI *EFI_CPU_IO_PROTOCOL_IO_MEM) (
IN EFI_CPU_IO_PROTOCOL * This,
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
IN UINT64 Address,
IN UINTN Count,
IN OUT VOID *Buffer
);
//
// *******************************************************
// EFI_CPU_IO_PROTOCOL_ACCESS
// *******************************************************
//
typedef struct {
EFI_CPU_IO_PROTOCOL_IO_MEM Read;
EFI_CPU_IO_PROTOCOL_IO_MEM Write;
} EFI_CPU_IO_PROTOCOL_ACCESS;
//
// *******************************************************
// EFI_CPU_IO_PROTOCOL
// *******************************************************
//
typedef struct EFI_CPU_IO_PROTOCOL_ {
EFI_CPU_IO_PROTOCOL_ACCESS Mem;
EFI_CPU_IO_PROTOCOL_ACCESS Io;
} EFI_CPU_IO_PROTOCOL;
extern EFI_GUID gEfiCpuIoProtocolGuid;
#endif

View File

@ -15,6 +15,8 @@
#include <Uefi.h>
#include <Guid/OcVariable.h>
#include <Guid/AppleHob.h>
#include <Guid/ApplePlatformInfo.h>
#include <IndustryStandard/CpuId.h>
#include <IndustryStandard/GenericIch.h>
#include <Protocol/PciIo.h>
@ -22,6 +24,7 @@
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/IoLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/OcCpuLib.h>
#include <Library/PciLib.h>
#include <Library/OcMiscLib.h>
@ -226,6 +229,59 @@ InternalCalculateTSCFromPMTimer (
return TSCFrequency;
}
STATIC
UINT64
InternalSelectAppleFsbFrequency (
IN UINT64 *FsbFrequency,
IN UINT32 FsbFrequncyCount
)
{
UINT32 Freq;
if (FsbFrequncyCount < 5) {
return 0 /* Invalid */;
}
//
// This one is for nForce MCP89 installed in MacBook7,1.
// Not sure what it reads from.
//
Freq = IoRead32 (0x580);
DEBUG ((
DEBUG_INFO,
"OCCPU: Selecting freq by %u from %Lu %Lu %Lu %Lu %Lu\n",
Freq,
FsbFrequency[0],
FsbFrequency[1],
FsbFrequency[2],
FsbFrequency[3],
FsbFrequency[4]
));
Freq /= 1000000;
if (Freq == 16) {
return FsbFrequency[0];
}
if (Freq >= 1063 && Freq <= 1069) {
return FsbFrequency[0];
}
if (Freq >= 530 && Freq <= 536) {
return FsbFrequency[1];
}
if (Freq >= 797 && Freq <= 803) {
return FsbFrequency[2];
}
if (Freq >= 663 && Freq <= 669) {
return FsbFrequency[3];
}
if (Freq >= 1330 && Freq <= 1336) {
return FsbFrequency[4];
}
return 0 /* Invalid */;
}
UINT64
InternalCalculateTSCFromApplePlatformInfo (
OUT UINT64 *FSBFrequency OPTIONAL,
@ -242,6 +298,7 @@ InternalCalculateTSCFromApplePlatformInfo (
EFI_STATUS Status;
APPLE_PLATFORM_INFO_DATABASE_PROTOCOL *PlatformInfo;
UINT32 Size;
UINT64 *FsbFreqs;
if (Recalculate) {
ObtainedFreqs = FALSE;
@ -279,8 +336,27 @@ InternalCalculateTSCFromApplePlatformInfo (
&FsbFreq
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCCPU: Failed to get FSBFrequency data using HOB method - %r\n", Status));
return 0;
DEBUG ((DEBUG_INFO, "OCCPU: Failed to get FSBFrequency data using HOB method - %r, trying legacy\n", Status));
Status = OcReadApplePlatformFirstDataAlloc (
PlatformInfo,
&gAppleFsbFrequencyListPlatformInfoGuid,
&Size,
(VOID **) &FsbFreqs
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCCPU: Failed to get FSBFrequency data using legacy method - %r\n", Status));
return 0;
}
if (Size < sizeof (UINT64) || Size % sizeof (UINT64) != 0) {
DEBUG ((DEBUG_INFO, "OCCPU: Invalid FSBFrequency list size %u - %r\n", Size, Status));
FreePool (FsbFreqs);
return 0;
}
FsbFreq = InternalSelectAppleFsbFrequency (FsbFreqs, Size / sizeof (UINT64));
FreePool (FsbFreqs);
}
}

View File

@ -40,6 +40,7 @@
[Guids]
gAppleFsbFrequencyPlatformInfoGuid
gAppleFsbFrequencyListPlatformInfoGuid
gAppleFsbFrequencyPlatformInfoIndexHobGuid
gOcVendorVariableGuid

View File

@ -20,6 +20,7 @@
#include <Pi/PiHob.h>
#include <Library/HobLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
EFI_STATUS
OcReadApplePlatformFirstData (
@ -85,6 +86,70 @@ OcReadApplePlatformFirstData (
return Status;
}
EFI_STATUS
OcReadApplePlatformFirstDataAlloc (
IN APPLE_PLATFORM_INFO_DATABASE_PROTOCOL *PlatformInfo,
IN EFI_GUID *DataGuid,
OUT UINT32 *Size,
OUT VOID **Data
)
{
EFI_STATUS Status;
UINT32 DataSize;
ASSERT (Size != NULL);
ASSERT (Data != NULL);
ASSERT (DataGuid != NULL);
Status = PlatformInfo->GetFirstDataSize (
PlatformInfo,
DataGuid,
&DataSize
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_INFO,
"OCCPU: No first platform data size for %g - %r\n",
DataGuid,
Status
));
return Status;
}
*Data = AllocatePool (DataSize);
if (*Data == NULL) {
DEBUG ((
DEBUG_INFO,
"OCCPU: Cannot alloc %u for first platform data %g\n",
DataSize,
DataGuid
));
return EFI_OUT_OF_RESOURCES;
}
Status = PlatformInfo->GetFirstData (
PlatformInfo,
DataGuid,
*Data,
&DataSize
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_INFO,
"OCCPU: No first platform data for %g with %u - %r\n",
DataGuid,
DataSize,
Status
));
FreePool (*Data);
return Status;
}
*Size = DataSize;
return Status;
}
EFI_STATUS
OcReadApplePlatformData (
IN APPLE_PLATFORM_INFO_DATABASE_PROTOCOL *PlatformInfo,

View File

@ -359,6 +359,9 @@
## Include/Apple/Guid/ApplePlatformInfo.h
gAppleFsbFrequencyPlatformInfoGuid = { 0xD1A04D55, 0x75B9, 0x41A3, { 0x90, 0x36, 0x8F, 0x4A, 0x26, 0x1C, 0xBB, 0xA2 }}
## Include/Apple/Guid/ApplePlatformInfo.h
gAppleFsbFrequencyListPlatformInfoGuid = { 0xF55EE371, 0xD19E, 0x4AAA, { 0xA9, 0x7B, 0xC1, 0xB1, 0x28, 0x4C, 0xB3, 0x7C }}
## Include/Apple/Guid/ApplePlatformInfo.h
gAppleKeyboardPlatformInfoGuid = { 0x51871CB9, 0xE25D, 0x44B4, { 0x96, 0x99, 0x0E, 0xE8, 0x64, 0x4C, 0xED, 0x69 }}
@ -513,6 +516,9 @@
## Include/Intel/Protocol/ConsoleControl.h
gEfiConsoleControlProtocolGuid = { 0xF42F7782, 0x012E, 0x4C12, { 0x99, 0x56, 0x49, 0xF9, 0x43, 0x04, 0xF7, 0x21 }}
## Include/Intel/Protocol/CpuIo.h
gEfiCpuIoProtocolGuid = { 0xB0732526, 0x38C8, 0x4b40, { 0x88, 0x77, 0x61, 0xC7, 0xB0, 0x6A, 0xAC, 0x45 }}
## Include/Intel/Protocol/DataHub.h
gEfiDataHubProtocolGuid = { 0xAE80D021, 0x618E, 0x11D4, { 0xBC, 0xD7, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }}