477 lines
12 KiB
C
477 lines
12 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
miscc.c
|
||
|
||
Abstract:
|
||
|
||
This file contains misc. functions used by NTLDR.
|
||
|
||
Author:
|
||
|
||
Allen Kay (akay) 03-Mar-1999
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "bldr.h"
|
||
#include "stdio.h"
|
||
#include "bootia64.h"
|
||
#include "efi.h"
|
||
#include "extern.h"
|
||
|
||
typedef struct _PAL_RETURN_VALUES {
|
||
ULONGLONG ReturnValue0;
|
||
ULONGLONG ReturnValue1;
|
||
ULONGLONG ReturnValue2;
|
||
ULONGLONG ReturnValue3;
|
||
} PAL_RETURN_VALUES, *PPAL_RETURN_VALUES;
|
||
|
||
typedef union _PAL_REVISION {
|
||
struct {
|
||
ULONGLONG PalBRevLower:4;
|
||
ULONGLONG PalBRevUpper:4;
|
||
ULONGLONG PalBModel:8;
|
||
ULONGLONG Reserved0:8;
|
||
ULONGLONG PalVendor:8;
|
||
ULONGLONG PalARevision:8;
|
||
ULONGLONG PalAModel:8;
|
||
ULONGLONG Reserved1:16;
|
||
};
|
||
ULONGLONG PalVersion;
|
||
} PAL_REVISION;
|
||
|
||
extern
|
||
PAL_RETURN_VALUES
|
||
BlpPalProc(
|
||
IN ULONGLONG FunctionIndex,
|
||
IN ULONGLONG Arg1,
|
||
IN ULONGLONG Arg2,
|
||
IN ULONGLONG Arg3
|
||
);
|
||
|
||
|
||
VOID
|
||
CallPal(
|
||
IN ULONGLONG FunctionIndex,
|
||
IN ULONGLONG Argument0,
|
||
IN ULONGLONG Argument1,
|
||
IN ULONGLONG Argument2,
|
||
OUT PULONGLONG ReturnValue0,
|
||
OUT PULONGLONG ReturnValue1,
|
||
OUT PULONGLONG ReturnValue2,
|
||
OUT PULONGLONG ReturnValue3
|
||
)
|
||
{
|
||
PAL_RETURN_VALUES RetVal;
|
||
|
||
RetVal = BlpPalProc(FunctionIndex, Argument0, Argument1, Argument2);
|
||
*ReturnValue0 = RetVal.ReturnValue0;
|
||
*ReturnValue1 = RetVal.ReturnValue1;
|
||
*ReturnValue2 = RetVal.ReturnValue2;
|
||
*ReturnValue3 = RetVal.ReturnValue3;
|
||
}
|
||
|
||
VOID
|
||
ReadProcessorConfigInfo(
|
||
PPROCESSOR_CONFIG_INFO ProcessorConfigInfo
|
||
)
|
||
{
|
||
ULONGLONG Status;
|
||
ULONGLONG Reserved;
|
||
|
||
if ((PUCHAR) ProcessorConfigInfo >= (PUCHAR) KSEG0_BASE) {
|
||
(PUCHAR) ProcessorConfigInfo -= KSEG0_BASE;
|
||
}
|
||
|
||
CallPal (
|
||
PAL_VM_PAGE_SIZE,
|
||
0,
|
||
0,
|
||
0,
|
||
&Status,
|
||
&ProcessorConfigInfo->InsertPageSizeInfo,
|
||
&ProcessorConfigInfo->PurgePageSizeInfo,
|
||
&Reserved
|
||
);
|
||
|
||
if (Status) {
|
||
EfiST->ConOut->OutputString(EfiST->ConOut,
|
||
L"ReadProcessorConfigInfo: PAL call PAL_VM_PAGE_SIZE failed.\n\r");
|
||
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
||
}
|
||
|
||
CallPal (
|
||
PAL_VM_SUMMARY,
|
||
0,
|
||
0,
|
||
0,
|
||
&Status,
|
||
&ProcessorConfigInfo->VmSummaryInfo1.Ulong64,
|
||
&ProcessorConfigInfo->VmSummaryInfo2.Ulong64,
|
||
&Reserved
|
||
);
|
||
|
||
if (Status) {
|
||
EfiST->ConOut->OutputString(EfiST->ConOut,
|
||
L"ReadProcessorConfigInfo: PAL call PAL_VM_SUMMARY failed.\n\r");
|
||
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
||
}
|
||
|
||
CallPal (
|
||
PAL_RSE_INFO,
|
||
0,
|
||
0,
|
||
0,
|
||
&Status,
|
||
&ProcessorConfigInfo->NumOfPhysStackedRegs,
|
||
&ProcessorConfigInfo->RseHints,
|
||
&Reserved
|
||
);
|
||
|
||
if (Status) {
|
||
EfiST->ConOut->OutputString(EfiST->ConOut,
|
||
L"ReadProcessorConfigInfo: PAL call PAL_RSE_INFO failed.\n\r");
|
||
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
||
}
|
||
|
||
CallPal (
|
||
PAL_PTCE_INFO,
|
||
0,
|
||
0,
|
||
0,
|
||
&Status,
|
||
&ProcessorConfigInfo->PtceInfo.PtceBase,
|
||
&ProcessorConfigInfo->PtceInfo.PtceTcCount.Ulong64,
|
||
&ProcessorConfigInfo->PtceInfo.PtceStrides.Ulong64
|
||
);
|
||
|
||
if (Status) {
|
||
EfiST->ConOut->OutputString(EfiST->ConOut,
|
||
L"ReadProcessorConfigInfo: PAL call PAL_PTCE_INFO failed.\n\r");
|
||
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
||
}
|
||
|
||
CallPal (
|
||
PAL_PROC_GET_FEATURES,
|
||
0,
|
||
0,
|
||
0,
|
||
&Status,
|
||
&ProcessorConfigInfo->FeaturesImplemented.Ulong64,
|
||
&ProcessorConfigInfo->FeaturesCurSetting.Ulong64,
|
||
&ProcessorConfigInfo->FeaturesSoftControl.Ulong64
|
||
);
|
||
|
||
if (Status) {
|
||
EfiST->ConOut->OutputString(EfiST->ConOut,
|
||
L"ReadProcessorConfigInfo: PAL call PAL_PROC_GET_FEATURES failed.\n\r");
|
||
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
||
}
|
||
}
|
||
|
||
|
||
VOID
|
||
CpuSpecificWork(
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine checks for CPU ID and applies processor specific workarounds.
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Returns:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONGLONG CpuId;
|
||
ULONGLONG CpuFamily;
|
||
|
||
CpuId = __getReg(CV_IA64_CPUID3);
|
||
CpuFamily = (CpuId >> 24) & 0xff;
|
||
|
||
//
|
||
// if the processor is an Itanium...
|
||
//
|
||
if (CpuFamily == 7) {
|
||
|
||
//
|
||
// We must ensure that the processor and PAL are supported before continuing.
|
||
//
|
||
|
||
EnforcePostB2Processor();
|
||
EnforcePostVersion16PAL();
|
||
EfiCheckFirmwareRevision();
|
||
|
||
#if 0
|
||
//
|
||
// This is redundant since A2 < B3
|
||
//
|
||
CheckForPreA2Processors();
|
||
#endif
|
||
}
|
||
}
|
||
|
||
VOID
|
||
EnforcePostB2Processor(
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine checks enforces that the system has a post B2 processor stepping.
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Returns:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONGLONG CpuId3;
|
||
|
||
CpuId3 = __getReg(CV_IA64_CPUID3);
|
||
|
||
#if 0
|
||
{
|
||
WCHAR Buffer[256];
|
||
ULONGLONG x;
|
||
|
||
x = (CpuId3 >> 0) & 0xff;
|
||
wsprintf(Buffer, L"Number = %x\r\n", x);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
x = (CpuId3 >> 8) & 0xff;
|
||
wsprintf(Buffer, L"Revision = %x\r\n", x);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
x = (CpuId3 >> 16) & 0xff;
|
||
wsprintf(Buffer, L"Model = %x\r\n", x);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
x = (CpuId3 >> 24) & 0xff;
|
||
wsprintf(Buffer, L"Family = %x\r\n", x);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
x = (CpuId3 >> 32) & 0xff;
|
||
wsprintf(Buffer, L"Archrev = %x\r\n", x);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
DBG_EFI_PAUSE();
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Block Processor steppings below B3
|
||
//
|
||
// Note: this switch came from: ntos\ke\ia64\initkr.c
|
||
//
|
||
switch (CpuId3) {
|
||
case 0x0007000004: // Itanium, A stepping
|
||
case 0x0007000104: // Itanium, B0 stepping
|
||
case 0x0007000204: // Itanium, B1 stepping
|
||
case 0x0007000304: // Itanium, B2 stepping
|
||
//
|
||
// unsupported steppings
|
||
//
|
||
EfiST->ConOut->OutputString(EfiST->ConOut,
|
||
L"Your Itanium system contains a pre-B3 stepping processor.\n\r");
|
||
EfiST->ConOut->OutputString(EfiST->ConOut,
|
||
L"You need to upgrade it to a B3 or later stepping to run Win64.\n\r");
|
||
EfiBS->Exit(EfiImageHandle, 0, 0, 0);
|
||
break;
|
||
|
||
case 0x0007000404: // Itanium, B3 stepping
|
||
case 0x0007000504: // Itanium, B4 stepping
|
||
case 0x0007000604: // Itanium, C0 or later stepping
|
||
default:
|
||
//
|
||
// supported steppings, do nothing
|
||
//
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
VOID
|
||
EnforcePostVersion16PAL(
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine enforces that the system has a PAL version >= 20.
|
||
|
||
Note:
|
||
|
||
The return value from get PAL version call has the
|
||
PAL B model and revision has the least significant
|
||
16 bits (Intel IA-64 Architecture Software Developer's Manual, Rav. 1.0, Page 11-109).
|
||
We should be using this to determine a minimum PAL revision for the firmware.
|
||
The first byte has the PAL_B_revision which is a monotonically increasing number
|
||
and is 0x17 for Lion 71b and 0x20 for Softsur 103b.
|
||
The PAL_B model indicates the stepping of the processor supported (We can ignore this one).
|
||
So we need to be using PAL B revision for our minimum firmware test.
|
||
|
||
Just an FYI:
|
||
There is a disconnect in the PAL_REVISION structure and what appears to be the specified
|
||
PAL revision layout. We use PAL_B_REVISION to get the PAL version rather than PAL_A_REVISION.
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Returns:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONGLONG Status;
|
||
PAL_REVISION MinimumPalVersion;
|
||
PAL_REVISION CurrentPalVersion;
|
||
ULONGLONG Reserved;
|
||
|
||
#define MIN_PAL_REVISION 0x23
|
||
|
||
CallPal (
|
||
PAL_VERSION,
|
||
0,
|
||
0,
|
||
0,
|
||
&Status,
|
||
&MinimumPalVersion.PalVersion,
|
||
&CurrentPalVersion.PalVersion,
|
||
&Reserved
|
||
);
|
||
|
||
if (Status) {
|
||
EfiST->ConOut->OutputString(EfiST->ConOut,
|
||
L"CheckForPreA2Processors: PAL call PAL_VERSION failed.\n\r");
|
||
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
||
}
|
||
|
||
#if 0
|
||
{
|
||
WCHAR Buffer[256];
|
||
|
||
wsprintf(Buffer, L"PalBRevLower = %x\r\n", CurrentPalVersion.PalBRevLower);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
wsprintf(Buffer, L"PalBRevUpper = %x\r\n", CurrentPalVersion.PalBRevUpper);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
wsprintf(Buffer, L"PalBModel = %x\r\n", CurrentPalVersion.PalBModel);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
wsprintf(Buffer, L"Reserved0 = %x\r\n", CurrentPalVersion.Reserved0);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
wsprintf(Buffer, L"PalVendor = %x\r\n", CurrentPalVersion.PalVendor);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
wsprintf(Buffer, L"PalARevision = %x\r\n", CurrentPalVersion.PalARevision);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
wsprintf(Buffer, L"PalAModel = %x\r\n", CurrentPalVersion.PalAModel);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
wsprintf(Buffer, L"Reserved1 = %x\r\n", CurrentPalVersion.Reserved1);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
DBG_EFI_PAUSE();
|
||
}
|
||
#endif
|
||
|
||
if (CurrentPalVersion.PalARevision < MIN_PAL_REVISION) {
|
||
WCHAR Buffer[256];
|
||
|
||
wsprintf(Buffer, L"Your Itanium system's PAL version is less than 0x%x.\n\r", MIN_PAL_REVISION);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
wsprintf(Buffer, L"You need to upgrade it to version 0x%x or later to run Win64.\n\r", MIN_PAL_REVISION);
|
||
EfiST->ConOut->OutputString(EfiST->ConOut, Buffer);
|
||
|
||
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
CheckForPreA2Processors(
|
||
)
|
||
{
|
||
ULONGLONG Status;
|
||
PAL_REVISION MinimumPalVersion;
|
||
PAL_REVISION CurrentPalVersion;
|
||
ULONGLONG Reserved;
|
||
|
||
CallPal (
|
||
PAL_VERSION,
|
||
0,
|
||
0,
|
||
0,
|
||
&Status,
|
||
&MinimumPalVersion.PalVersion,
|
||
&CurrentPalVersion.PalVersion,
|
||
&Reserved
|
||
);
|
||
|
||
if (Status) {
|
||
EfiST->ConOut->OutputString(EfiST->ConOut,
|
||
L"CheckForPreA2Processors: PAL call PAL_VERSION failed.\n\r");
|
||
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
||
}
|
||
|
||
//
|
||
// If PalBRevUpper if 0, 1, 3 or 4 then it is A0/A1 stepping.
|
||
//
|
||
if (CurrentPalVersion.PalBModel == 0) {
|
||
if ( (CurrentPalVersion.PalBRevUpper == 0) ||
|
||
(CurrentPalVersion.PalBRevUpper == 1) ||
|
||
(CurrentPalVersion.PalBRevUpper == 3) ||
|
||
(CurrentPalVersion.PalBRevUpper == 4) ) {
|
||
|
||
//
|
||
// Since PAL version 27 supports A2 and A3 but
|
||
// it returns 0, we need to special case this and
|
||
// just return.
|
||
//
|
||
if ((CurrentPalVersion.PalBRevUpper == 0) &&
|
||
(CurrentPalVersion.PalBRevLower == 0) ) {
|
||
return;
|
||
}
|
||
|
||
EfiST->ConOut->OutputString(EfiST->ConOut,
|
||
L"Your Itanium system contains an pre-A2 stepping processor.\n\r");
|
||
EfiST->ConOut->OutputString(EfiST->ConOut,
|
||
L"You need to upgrade it to an A2 or later stepping to run Win64.\n\r");
|
||
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
||
}
|
||
}
|
||
}
|
||
|