You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
760 lines
21 KiB
760 lines
21 KiB
/*++
|
|
|
|
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"
|
|
|
|
|
|
WCHAR EfiBuffer[256];
|
|
|
|
void
|
|
EfiPrintf(
|
|
IN PWCHAR Format,
|
|
...
|
|
)
|
|
{
|
|
va_list arglist;
|
|
|
|
va_start(arglist, Format);
|
|
|
|
if (_vsnwprintf( EfiBuffer, sizeof(EfiBuffer), Format, arglist) > 0) {
|
|
EfiPrint(EfiBuffer);
|
|
}
|
|
|
|
}
|
|
|
|
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;
|
|
ULONGLONG CacheLevels;
|
|
ULONGLONG UniqueCaches;
|
|
ULONGLONG CacheIndex;
|
|
IA64_CACHE_INFO1 CacheInfo1;
|
|
IA64_CACHE_INFO2 CacheInfo2;
|
|
|
|
if ((PUCHAR) ProcessorConfigInfo >= (PUCHAR) KSEG0_BASE) {
|
|
ProcessorConfigInfo = (PPROCESSOR_CONFIG_INFO)((PUCHAR)ProcessorConfigInfo - KSEG0_BASE);
|
|
}
|
|
|
|
ProcessorConfigInfo->CpuId3 = __getReg(CV_IA64_CPUID3);
|
|
|
|
CallPal (
|
|
PAL_VM_PAGE_SIZE,
|
|
0,
|
|
0,
|
|
0,
|
|
&Status,
|
|
&ProcessorConfigInfo->InsertPageSizeInfo,
|
|
&ProcessorConfigInfo->PurgePageSizeInfo,
|
|
&Reserved
|
|
);
|
|
|
|
if (Status) {
|
|
EfiPrint(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) {
|
|
EfiPrint(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) {
|
|
EfiPrint(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) {
|
|
EfiPrint(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) {
|
|
EfiPrint(L"ReadProcessorConfigInfo: PAL call PAL_PROC_GET_FEATURES failed.\n\r");
|
|
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
|
}
|
|
|
|
CallPal(
|
|
PAL_CACHE_SUMMARY,
|
|
0,
|
|
0,
|
|
0,
|
|
&Status,
|
|
&CacheLevels,
|
|
&UniqueCaches,
|
|
&Reserved
|
|
);
|
|
|
|
if (Status) {
|
|
EfiPrint(L"ReadProcessorConfigInfo: PAL call PAL_CACHE_SUMMARY failed.\r\n");
|
|
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
|
}
|
|
|
|
if (CacheLevels < 2) {
|
|
|
|
EfiPrint(L"ReadProcessorConfigInfo: Invalid number of Cache Levels.\r\n");
|
|
EfiBS->Exit(EfiImageHandle, (EFI_STATUS)-1, 0, 0);
|
|
}
|
|
|
|
ProcessorConfigInfo->NumberOfCacheLevels = CONFIG_INFO_CACHE_LEVELS;
|
|
ProcessorConfigInfo->LargestCacheLine = 0;
|
|
|
|
if (CacheLevels < CONFIG_INFO_CACHE_LEVELS) {
|
|
ProcessorConfigInfo->NumberOfCacheLevels = (ULONG) CacheLevels;
|
|
}
|
|
|
|
|
|
for (CacheIndex = 0; CacheIndex < ProcessorConfigInfo->NumberOfCacheLevels; CacheIndex++) {
|
|
|
|
CallPal(
|
|
PAL_CACHE_INFO,
|
|
CacheIndex, // Cache Level
|
|
2, // Data or Unified Cache
|
|
0, // Not used
|
|
&Status,
|
|
&ProcessorConfigInfo->CacheInfo1[CONFIG_INFO_DCACHE][CacheIndex].Ulong64,
|
|
&ProcessorConfigInfo->CacheInfo2[CONFIG_INFO_DCACHE][CacheIndex].Ulong64,
|
|
&Reserved
|
|
);
|
|
|
|
if (Status != 0) {
|
|
EfiPrintf(L"ReadProcessorConfigInfo: PAL call PAL_CACHE_INFO D cache failed. Index = %d, Status = %d\r\n", CacheIndex, Status);
|
|
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
|
}
|
|
|
|
//
|
|
// Detemine the largest stride for memory allocation.
|
|
//
|
|
|
|
if ((1UL << ProcessorConfigInfo->CacheInfo1[CONFIG_INFO_DCACHE][CacheIndex].LineSize) >
|
|
ProcessorConfigInfo->LargestCacheLine) {
|
|
|
|
ProcessorConfigInfo->LargestCacheLine =
|
|
1UL << ProcessorConfigInfo->CacheInfo1[CONFIG_INFO_DCACHE][CacheIndex].LineSize;
|
|
}
|
|
|
|
//
|
|
// If this is a unified cache then data and instructions are the same so skip
|
|
// the instruction cache.
|
|
//
|
|
|
|
if (ProcessorConfigInfo->CacheInfo1[CONFIG_INFO_DCACHE][CacheIndex].Unified) {
|
|
|
|
ProcessorConfigInfo->CacheInfo1[CONFIG_INFO_ICACHE][CacheIndex] = ProcessorConfigInfo->CacheInfo1[CONFIG_INFO_DCACHE][CacheIndex];
|
|
ProcessorConfigInfo->CacheInfo2[CONFIG_INFO_ICACHE][CacheIndex] = ProcessorConfigInfo->CacheInfo2[CONFIG_INFO_DCACHE][CacheIndex];
|
|
|
|
continue;
|
|
}
|
|
|
|
CallPal(
|
|
PAL_CACHE_INFO,
|
|
CacheIndex, // Cache Level
|
|
1, // Instruction Cache
|
|
0, // Not used
|
|
&Status,
|
|
&ProcessorConfigInfo->CacheInfo1[CONFIG_INFO_ICACHE][CacheIndex].Ulong64,
|
|
&ProcessorConfigInfo->CacheInfo2[CONFIG_INFO_ICACHE][CacheIndex].Ulong64,
|
|
&Reserved
|
|
);
|
|
|
|
if (Status != 0) {
|
|
EfiPrintf(L"ReadProcessorConfigInfo: PAL call PAL_CACHE_INFO I cache failed. Index = %d, Status = %d\r\n", CacheIndex, Status);
|
|
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Scan the any remaining cache levels for a the maximum line size value.
|
|
//
|
|
|
|
for (CacheIndex = ProcessorConfigInfo->NumberOfCacheLevels; CacheIndex < CacheLevels; CacheIndex++) {
|
|
|
|
CallPal(
|
|
PAL_CACHE_INFO,
|
|
CacheIndex, // Cache Level
|
|
2, // Data Cache
|
|
0, // Not used
|
|
&Status,
|
|
&CacheInfo1.Ulong64,
|
|
&CacheInfo2.Ulong64,
|
|
&Reserved
|
|
);
|
|
|
|
if (Status != 0) {
|
|
EfiPrintf(L"ReadProcessorConfigInfo: PAL call PAL_CACHE_INFO Line failed. Index = %d, Status = %d\r\n", CacheIndex, Status);
|
|
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
|
}
|
|
|
|
//
|
|
// Detemine the largest stride for memory allocation.
|
|
//
|
|
|
|
if ((1UL << CacheInfo1.LineSize) > ProcessorConfigInfo->LargestCacheLine) {
|
|
|
|
ProcessorConfigInfo->LargestCacheLine = 1UL << CacheInfo1.LineSize;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// We need to retrieve the stride value for the "FC" instruction. Since the
|
|
// "FC" instruction isn't targetted at a specific cache rather it is
|
|
// supposed to flush all the caches the stride value should be the same for
|
|
// all cache levels. Unfortunately this isn't currently true for
|
|
// Itanium systems.
|
|
//
|
|
// Fortunately the value for Level 2 (index 1) is correct on both Itanium
|
|
// and McKinley systems. So we will just retrieve it.
|
|
//
|
|
|
|
ProcessorConfigInfo->CacheFlushStride = 1 << (ProcessorConfigInfo->CacheInfo1[CONFIG_INFO_DCACHE][1].Stride);
|
|
|
|
#if 0
|
|
{
|
|
|
|
//
|
|
// Dump out all the cache info for debugging purposes.
|
|
//
|
|
EfiPrintf(L"ReadProcessorConfigInfo: CacheLevels = %d, UniqueCaches = %d\r\n", CacheLevels, UniqueCaches);
|
|
EfiPrintf(L"ReadProcessorConfigInfo: CacheFlushStride = %d, LargestCacheLine = %d\r\n", ProcessorConfigInfo->CacheFlushStride, ProcessorConfigInfo->LargestCacheLine);
|
|
|
|
for (CacheIndex = 0; CacheIndex < (2 * CacheLevels); CacheIndex++) {
|
|
|
|
CallPal(
|
|
PAL_CACHE_INFO,
|
|
CacheIndex >> 1,
|
|
(CacheIndex & 0x01) + 1,
|
|
0,
|
|
&Status,
|
|
&CacheInfo1.Ulong64,
|
|
&CacheInfo2.Ulong64,
|
|
&Reserved
|
|
);
|
|
|
|
if (Status == 0) {
|
|
|
|
EfiPrintf(L"ReadProcessorConfigInfo: CacheLevel(%s) = %d, ConfigInfo1 = 0x%I64X, ConfigInfo2 = 0x%I64X\r\n",
|
|
(CacheIndex & 0x01) ? L"Data" : L"Instruction",
|
|
CacheIndex >> 1,
|
|
CacheInfo1.Ulong64, CacheInfo2.Ulong64);
|
|
|
|
EfiPrintf(L" Stride = %d, LineSize = %d, Associativity = %d, Attributes = %d, Unified = %d\r\n",
|
|
CacheInfo1.Stride,
|
|
CacheInfo1.LineSize,
|
|
CacheInfo1.Associativity,
|
|
CacheInfo1.Attributes,
|
|
CacheInfo1.Unified
|
|
);
|
|
|
|
EfiPrintf(L" LoadHints = %d, StoreHints = %d, LoadLatency = %d, StoreLatency = %d\r\n",
|
|
CacheInfo1.LoadHints,
|
|
CacheInfo1.StoreHints,
|
|
CacheInfo1.LoadLatency,
|
|
CacheInfo1.StoreLatency
|
|
);
|
|
|
|
EfiPrintf(L" CacheSize = %d, TagMSBit = %d, TagLSBit = %d, AliasBoundary = %d\r\n",
|
|
CacheInfo2.Size,
|
|
CacheInfo2.TagLeastBit,
|
|
CacheInfo2.TagMostBit,
|
|
CacheInfo2.Alias);
|
|
|
|
} else {
|
|
|
|
EfiPrintf(L"ReadProcessorConfigInfo: PAL call PAL_CACHE_INFO failed, Status = %d.\r\n", Status);
|
|
|
|
// EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
|
}
|
|
}
|
|
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// IA64 Debug Registers info.
|
|
//
|
|
|
|
CallPal (
|
|
PAL_DEBUG_INFO,
|
|
0,
|
|
0,
|
|
0,
|
|
&ProcessorConfigInfo->DebugInfo.Status,
|
|
&ProcessorConfigInfo->DebugInfo.InstDebugRegisterPairs,
|
|
&ProcessorConfigInfo->DebugInfo.DataDebugRegisterPairs,
|
|
0
|
|
);
|
|
|
|
if (ProcessorConfigInfo->DebugInfo.Status) {
|
|
#if DBG
|
|
EfiPrint(L"ReadProcessorConfigInfo: PAL call PAL_DEBUG_INFO failed.\n\r");
|
|
EfiPrint(L"ReadProcessorConfigInfo: Fixing DebugInfo with architected default values.\n\r");
|
|
#endif
|
|
ProcessorConfigInfo->DebugInfo.InstDebugRegisterPairs = NUMBER_OF_DEBUG_REGISTER_PAIRS;
|
|
ProcessorConfigInfo->DebugInfo.DataDebugRegisterPairs = NUMBER_OF_DEBUG_REGISTER_PAIRS;
|
|
}
|
|
|
|
//
|
|
// IA64 Performance Monitor Registers info.
|
|
//
|
|
|
|
CallPal (
|
|
PAL_PERF_MON_INFO,
|
|
(ULONGLONG)&ProcessorConfigInfo->PerfMonInfo.PerfMonCnfgMask[0],
|
|
0,
|
|
0,
|
|
&ProcessorConfigInfo->PerfMonInfo.Status,
|
|
&ProcessorConfigInfo->PerfMonInfo.Ulong64,
|
|
0,
|
|
0
|
|
);
|
|
|
|
if (ProcessorConfigInfo->PerfMonInfo.Status) {
|
|
|
|
//
|
|
// Workaround known family or models values.
|
|
//
|
|
|
|
ULONGLONG cpuFamily = (ProcessorConfigInfo->CpuId3 >> 24) && 0xff;
|
|
ULONGLONG counterWidth = 47; // Default McKinley-core Family PMU.
|
|
|
|
if ( cpuFamily == 7 ) {
|
|
counterWidth = 32;
|
|
}
|
|
|
|
#if DBG
|
|
EfiPrint(L"ReadProcessorConfigInfo: PAL call PAL_PERF_MON_INFO failed.\n\r");
|
|
EfiPrint(L"ReadProcessorConfigInfo: Fixing PerfMonInfo with architected default values.\n\r");
|
|
#endif
|
|
|
|
ProcessorConfigInfo->PerfMonInfo.PerfMonGenericPairs = NUMBER_OF_PERFMON_REGISTER_PAIRS;
|
|
ProcessorConfigInfo->PerfMonInfo.ImplementedCounterWidth = counterWidth;
|
|
ProcessorConfigInfo->PerfMonInfo.ProcessorCyclesEventType = 0x12;
|
|
ProcessorConfigInfo->PerfMonInfo.RetiredInstructionBundlesEventType = 0x8;
|
|
ProcessorConfigInfo->PerfMonInfo.PerfMonCnfgMask[0] = (UCHAR)0xff;
|
|
ProcessorConfigInfo->PerfMonInfo.PerfMonCnfgMask[1] = (UCHAR)0xff;
|
|
ProcessorConfigInfo->PerfMonInfo.PerfMonDataMask[0] = (UCHAR)0xff;
|
|
ProcessorConfigInfo->PerfMonInfo.PerfMonDataMask[1] = (UCHAR)0xff;
|
|
ProcessorConfigInfo->PerfMonInfo.PerfMonDataMask[2] = (UCHAR)0x03;
|
|
ProcessorConfigInfo->PerfMonInfo.ProcessorCyclesMask[0] = (UCHAR)0xf0;
|
|
ProcessorConfigInfo->PerfMonInfo.RetiredInstructionBundlesMask[0] = (UCHAR)0xf0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
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);
|
|
EfiPrint(Buffer);
|
|
|
|
x = (CpuId3 >> 8) & 0xff;
|
|
wsprintf(Buffer, L"Revision = %x\r\n", x);
|
|
EfiPrint(Buffer);
|
|
|
|
x = (CpuId3 >> 16) & 0xff;
|
|
wsprintf(Buffer, L"Model = %x\r\n", x);
|
|
EfiPrint(Buffer);
|
|
|
|
x = (CpuId3 >> 24) & 0xff;
|
|
wsprintf(Buffer, L"Family = %x\r\n", x);
|
|
EfiPrint(Buffer);
|
|
|
|
x = (CpuId3 >> 32) & 0xff;
|
|
wsprintf(Buffer, L"Archrev = %x\r\n", x);
|
|
EfiPrint(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
|
|
//
|
|
EfiPrint(L"Your Itanium system contains a pre-B3 stepping processor.\n\r");
|
|
EfiPrint(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) {
|
|
EfiPrint(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);
|
|
EfiPrint(Buffer);
|
|
|
|
wsprintf(Buffer, L"PalBRevUpper = %x\r\n", CurrentPalVersion.PalBRevUpper);
|
|
EfiPrint(Buffer);
|
|
|
|
wsprintf(Buffer, L"PalBModel = %x\r\n", CurrentPalVersion.PalBModel);
|
|
EfiPrint(Buffer);
|
|
|
|
wsprintf(Buffer, L"Reserved0 = %x\r\n", CurrentPalVersion.Reserved0);
|
|
EfiPrint(Buffer);
|
|
|
|
wsprintf(Buffer, L"PalVendor = %x\r\n", CurrentPalVersion.PalVendor);
|
|
EfiPrint(Buffer);
|
|
|
|
wsprintf(Buffer, L"PalARevision = %x\r\n", CurrentPalVersion.PalARevision);
|
|
EfiPrint(Buffer);
|
|
|
|
wsprintf(Buffer, L"PalAModel = %x\r\n", CurrentPalVersion.PalAModel);
|
|
EfiPrint(Buffer);
|
|
|
|
wsprintf(Buffer, L"Reserved1 = %x\r\n", CurrentPalVersion.Reserved1);
|
|
EfiPrint(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);
|
|
EfiPrint(Buffer);
|
|
|
|
wsprintf(Buffer, L"To upgrade system's PAL version, please update the system's firmware.\n\r");
|
|
EfiPrint(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) {
|
|
EfiPrint(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;
|
|
}
|
|
|
|
EfiPrint(L"Your Itanium system contains an pre-A2 stepping processor.\n\r");
|
|
EfiPrint(L"You need to upgrade it to an A2 or later stepping to run Win64.\n\r");
|
|
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
|
|
}
|
|
}
|
|
}
|
|
|