windows-nt/Source/XPSP1/NT/base/hals/halia64/ia64/i64efi.c
2020-09-26 16:20:57 +08:00

2375 lines
76 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1995 Intel Corporation
Module Name:
i64efi.c
Abstract:
This module implements the routines that transfer control
from the kernel to the EFI code.
Author:
Bernard Lint
M. Jayakumar (Muthurajan.Jayakumar@hotmail.com)
Environment:
Kernel mode
Revision History:
Neal Vu (neal.vu@intel.com), 03-Apr-2001:
Added HalpGetSmBiosVersion.
--*/
#include "halp.h"
#include "arc.h"
#include "arccodes.h"
#include "i64fw.h"
#include "floatem.h"
#include "fpswa.h"
#include <smbios.h>
extern ULONGLONG PhysicalIOBase;
BOOLEAN
HalpCompareEfiGuid (
IN EFI_GUID CheckGuid,
IN EFI_GUID ReferenceGuid
);
BOOLEAN
MmSetPageProtection(
IN PVOID VirtualAddress,
IN SIZE_T NumberOfBytes,
IN ULONG NewProtect
);
EFI_STATUS
HalpCallEfiPhysical(
IN ULONGLONG Arg1,
IN ULONGLONG Arg2,
IN ULONGLONG Arg3,
IN ULONGLONG Arg4,
IN ULONGLONG Arg5,
IN ULONGLONG Arg6,
IN ULONGLONG EP,
IN ULONGLONG GP
);
EFI_STATUS
HalpCallEfiVirtual(
IN ULONGLONG Arg1,
IN ULONGLONG Arg2,
IN ULONGLONG Arg3,
IN ULONGLONG Arg4,
IN ULONGLONG Arg5,
IN ULONGLONG Arg6,
IN ULONGLONG EP,
IN ULONGLONG GP
);
LONG
HalFpEmulate(
ULONG trap_type,
BUNDLE *pbundle,
ULONGLONG *pipsr,
ULONGLONG *pfpsr,
ULONGLONG *pisr,
ULONGLONG *ppreds,
ULONGLONG *pifs,
FP_STATE *fp_state
);
BOOLEAN
HalEFIFpSwa(
VOID
);
VOID
HalpFpswaPlabelFixup(
EFI_MEMORY_DESCRIPTOR *EfiVirtualMemoryMapPtr,
ULONGLONG MapEntries,
ULONGLONG EfiDescriptorSize,
PPLABEL_DESCRIPTOR PlabelPointer
);
PUCHAR
HalpGetSmBiosVersion (
IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
//
// External global data
//
extern HALP_SAL_PAL_DATA HalpSalPalData;
extern ULONGLONG HalpPalProcPointer;
extern ULONGLONG HalpSalProcPointer;
extern ULONGLONG HalpSalProcGlobalPointer;
extern KSPIN_LOCK HalpSalSpinLock;
extern KSPIN_LOCK HalpSalStateInfoSpinLock;
extern KSPIN_LOCK HalpMcaSpinLock;
extern KSPIN_LOCK HalpInitSpinLock;
extern KSPIN_LOCK HalpCmcSpinLock;
extern KSPIN_LOCK HalpCpeSpinLock;
#define VENDOR_SPECIFIC_GUID \
{ 0xa3c72e56, 0x4c35, 0x11d3, 0x8a, 0x03, 0x0, 0xa0, 0xc9, 0x06, 0xad, 0xec }
#define ConfigGuidOffset 0x100
#define ConfigTableOffset 0x200
#define VariableNameOffset 0x100
#define VendorGuidOffset 0x200
#define AttributeOffset 0x300
#define DataSizeOffset 0x400
#define DataBufferOffset 0x500
#define EndOfCommonDataOffset 0x600
//
// Read Variable and Write Variable will not be called till the copying out of
// Memory Descriptors is done. Because the lock is released before copying and we are using
// the same offset for read/write variable as well as memory layout calls.
//
#define MemoryMapSizeOffset 0x100
#define DescriptorSizeOffset 0x200
#define DescriptorVersionOffset 0x300
#define MemoryMapOffset 0x400
#define OptionROMAddress 0xC0000
#define FP_EMUL_ERROR -1
SST_MEMORY_LIST PalCode;
NTSTATUS EfiInitStatus;
ULONGLONG PalTrMask;
PUCHAR HalpConfigGuidVirtualPtr, HalpConfigGuidPhysPtr;
PUCHAR HalpConfigTableVirtualPtr;
PUCHAR HalpConfigTablePhysPtr;
EFI_CONFIGURATION_TABLE *EfiConfigTableVirtualPtr;
EFI_CONFIGURATION_TABLE EfiConfigTable;
EFI_GUID CheckGuid;
EFI_GUID SalGuid = SAL_SYSTEM_TABLE_GUID;
EFI_GUID VendorGuid;
PUCHAR HalpVendorGuidPhysPtr;
PUCHAR HalpVendorGuidVirtualPtr;
EFI_SYSTEM_TABLE *EfiSysTableVirtualPtr;
EFI_SYSTEM_TABLE *EfiSysTableVirtualPtrCpy;
EFI_RUNTIME_SERVICES *EfiRSVirtualPtr;
EFI_BOOT_SERVICES *EfiBootVirtualPtr;
PLABEL_DESCRIPTOR *EfiVirtualGetVariablePtr; // Get Variable
PLABEL_DESCRIPTOR *EfiVirtualGetNextVariableNamePtr; // Get NextVariable Name
PLABEL_DESCRIPTOR *EfiVirtualSetVariablePtr; // Set Variable
PLABEL_DESCRIPTOR *EfiVirtualGetTimePtr; // Get Time
PLABEL_DESCRIPTOR *EfiVirtualSetTimePtr; // Set Time
PLABEL_DESCRIPTOR *EfiSetVirtualAddressMapPtr; // Set Virtual Address Map
PLABEL_DESCRIPTOR *EfiResetSystemPtr; // Reboot
PULONGLONG AttributePtr;
ULONGLONG EfiAttribute;
PULONGLONG DataSizePtr;
ULONGLONG EfiDataSize;
ULONGLONG EfiConfigTableSize, EfiMemoryMapSize,EfiDescriptorSize,EfiMapEntries;
ULONG EfiDescriptorVersion;
PULONGLONG HalpPhysBSPointer;
PULONGLONG HalpPhysStackPointer;
PUCHAR HalpVirtualEfiSalPalDataPointer;
PUCHAR HalpPhysEfiSalPalDataPointer;
PUCHAR HalpVirtualCommonDataPointer;
PUCHAR HalpPhysCommonDataPointer;
PUCHAR HalpVariableNamePhysPtr;
PUCHAR HalpVariableAttributesPhysPtr;
PUCHAR HalpDataSizePhysPtr;
PUCHAR HalpDataPhysPtr;
PUCHAR HalpMemoryMapSizePhysPtr;
PUCHAR HalpMemoryMapPhysPtr;
PUCHAR HalpDescriptorSizePhysPtr;
PUCHAR HalpDescriptorVersionPhysPtr;
PUCHAR HalpVariableNameVirtualPtr;
PUCHAR HalpVariableAttributesVirtualPtr;
PUCHAR HalpDataSizeVirtualPtr;
PUCHAR HalpDataVirtualPtr;
PUCHAR HalpCommonDataEndPtr;
PUCHAR HalpMemoryMapSizeVirtualPtr;
PVOID HalpMemoryMapVirtualPtr;
PUCHAR HalpDescriptorSizeVirtualPtr;
PUCHAR HalpDescriptorVersionVirtualPtr;
EFI_FPSWA HalpFpEmulate;
KSPIN_LOCK EFIMPLock;
ULONG HalpOsBootRendezVector;
BOOLEAN
HalpCompareEfiGuid (
IN EFI_GUID CheckGuid,
IN EFI_GUID ReferenceGuid
)
/*++
--*/
{
USHORT i;
USHORT TotalArrayLength = 8;
if (CheckGuid.Data1 != ReferenceGuid.Data1) {
return FALSE;
} else if (CheckGuid.Data2 != ReferenceGuid.Data2) {
return FALSE;
} else if (CheckGuid.Data3 != ReferenceGuid.Data3) {
return FALSE;
}
for (i = 0; i != TotalArrayLength; i++) {
if (CheckGuid.Data4[i] != ReferenceGuid.Data4[i])
return FALSE;
}
return TRUE;
} // HalpCompareEfiGuid()
VOID
HalpInitSalPalWorkArounds(
VOID
)
/*++
Routine Description:
This function determines and initializes the FW workarounds.
Arguments:
None.
Return Value:
None.
Globals:
Notes: This function is being called at the end of HalpInitSalPal.
It should not access SST members if this SAL table is unmapped.
--*/
{
NTSTATUS status;
extern FADT HalpFixedAcpiDescTable;
#define HalpIsIntelOEM() \
( !_strnicmp( HalpFixedAcpiDescTable.Header.OEMID, "INTEL", 5 ) )
#define HalpIsBigSur() \
( !strncmp( HalpFixedAcpiDescTable.Header.OEMTableID, "W460GXBS", 8 ) )
#define HalpIsIntelBigSur() \
( HalpIsIntelOEM() && HalpIsBigSur() )
if ( HalpIsIntelOEM() ) {
//
// If Intel BigSur and FW build < 103 (checked as Pal_A_Revision < 0x20),
// enable the SAL_GET_STATE_INFO log id increment workaround.
//
if ( HalpIsBigSur() ) {
if ( HalpSalPalData.PalVersion.PAL_A_Revision < 0x20 ) {
HalpSalPalData.Flags |= HALP_SALPAL_FIX_MCE_LOG_ID;
HalpSalPalData.Flags |= HALP_SALPAL_FIX_MP_SAFE;
}
//
// HALP_SALPAL_MCE_MODINFO_CPUINDINFO_OMITTED 04/12/2001:
// FW omits completely ERROR_PROCESSOR.CpuIdInfo field in the log.
// Softsur: This is fixed with developer FW SoftMca3 05/09/2001.
// Lion : ?
//
// HALP_SALPAL_MCE_PROCESSOR_STATICINFO_PARTIAL 04/12/2001:
// FW does not pad invalid processor staticinfo fields.
// We do not know when it is going to be fixed.
//
if ( HalpSalPalData.PalVersion.PAL_A_Revision < 0x21 ) {
HalpSalPalData.Flags |= HALP_SALPAL_MCE_PROCESSOR_CPUIDINFO_OMITTED;
}
HalpSalPalData.Flags |= HALP_SALPAL_MCE_PROCESSOR_STATICINFO_PARTIAL;
}
else {
//
// If Intel Lion and FW build < 78b (checked as SalRevision < 0x300),
// enable the SAL_GET_STATE_INFO log id increment workaround.
//
if ( HalpSalPalData.SalRevision.Revision < 0x300 ) {
HalpSalPalData.Flags |= HALP_SALPAL_FIX_MCE_LOG_ID;
HalpSalPalData.Flags |= HALP_SALPAL_FIX_MP_SAFE;
}
HalpSalPalData.Flags |= HALP_SALPAL_MCE_PROCESSOR_CPUIDINFO_OMITTED;
HalpSalPalData.Flags |= HALP_SALPAL_MCE_PROCESSOR_STATICINFO_PARTIAL;
}
}
return;
} // HalpInitSalPalWorkArounds()
NTSTATUS
HalpInitSalPal(
PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This function extracts data from the SAL system table, virtually maps the
SAL code, SAL data, and PAL code areas. PAL requires a TR mapping, and
is mapped using an architected TR, using the smallest page size to map
the entire PAL code region. If SAL data or SAL code areas can be mapped in
the same page, it uses the same translation. Otherwise, it uses MmMapIoSpace.
Arguments:
LoaderBlock - Supplies a pointer to the Loader parameter block, containing the
physical address of the SAL system table.
Return Value:
STATUS_SUCCESS is returned if the mappings were successful, and SAL/PAL calls can
be made. Otherwise, STATUS_UNSUCCESSFUL is returned if it cannot virtually map
the areas or if PAL requires a page larger than 16MB.
Assumptions: The EfiSysTableVirtualPtr is initialized prior by EfiInitialization.
--*/
{
//
// Local declarations
//
PSAL_PAL_ENTRY_POINT FwEntry;
PSST_MEMORY_DESCRIPTOR SstMemoryDescriptor;
PAP_WAKEUP_DESCRIPTOR ApWakeupDescriptor;
PVOID NextEntry, FwCodeSpace;
UCHAR Checksum;
PUCHAR CheckBuf;
ULONG index,i,SstLength;
SAL_PAL_RETURN_VALUES RetVals;
PHYSICAL_ADDRESS physicalAddr;
SAL_STATUS SALstatus;
BOOLEAN LargerThan16Mb, MmMappedSalCode, MmMappedSalData;
ULONGLONG physicalEfiST,physicalSST;
ULONGLONG physicalPAL, physicalSAL, physicalSALGP;
ULONGLONG PhysicalConfigPtr;
SST_MEMORY_LIST SalCode,SalData, FwCode;
BOOLEAN FoundSalTable;
ULONGLONG palStatus;
PAL_VERSION_STRUCT minimumPalVersion;
ULONG PalPageShift;
ULONGLONG PalPteUlong;
HalpVirtualEfiSalPalDataPointer = (PUCHAR)(ExAllocatePool (NonPagedPool, PAGE_SIZE));
HalpConfigTableVirtualPtr = HalpVirtualEfiSalPalDataPointer + ConfigTableOffset;
HalpConfigGuidVirtualPtr = HalpVirtualEfiSalPalDataPointer + ConfigGuidOffset;
HalpPhysEfiSalPalDataPointer = (PUCHAR)((MmGetPhysicalAddress(HalpVirtualEfiSalPalDataPointer)).QuadPart);
HalpConfigTablePhysPtr = HalpPhysEfiSalPalDataPointer + ConfigTableOffset;
HalpConfigGuidPhysPtr = HalpPhysEfiSalPalDataPointer + ConfigGuidOffset;
EfiConfigTableVirtualPtr = &EfiConfigTable;
EfiConfigTableSize = (ULONGLONG) sizeof(EFI_CONFIGURATION_TABLE);
HalDebugPrint(( HAL_INFO, "SAL_PAL: Entering HalpInitSalPal\n" ));
FoundSalTable = FALSE;
//
// Extract SST physical address out of EFI table
//
PhysicalConfigPtr = (ULONGLONG) EfiSysTableVirtualPtrCpy -> ConfigurationTable;
for (index = 0; (FoundSalTable == FALSE) && (index <= (EfiSysTableVirtualPtr->NumberOfTableEntries)); index = index + 1) {
physicalAddr.QuadPart = PhysicalConfigPtr;
EfiConfigTableVirtualPtr = MmMapIoSpace(physicalAddr, sizeof(EFI_CONFIGURATION_TABLE),MmCached);
if (EfiConfigTableVirtualPtr == NULL) {
HalDebugPrint(( HAL_ERROR, "SAL_PAL: Efi Config Table Virtual Addr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
CheckGuid = EfiConfigTableVirtualPtr -> VendorGuid;
PhysicalConfigPtr = PhysicalConfigPtr + EfiConfigTableSize;
HalDebugPrint(( HAL_INFO,
"SAL_PAL: Found new ConfigPhysPtr 0x%I64x points to tablesize 0x%I64x\n",
PhysicalConfigPtr, EfiConfigTableSize ));
// if (CheckGuid.Data1 == 0xeb9d2d32)
if (HalpCompareEfiGuid(CheckGuid, SalGuid)) {
FoundSalTable = TRUE;
}
}
physicalSST = (ULONGLONG) EfiConfigTableVirtualPtr -> VendorTable;
//
// Zero out internal structures
//
RtlZeroMemory(&HalpSalPalData, sizeof(HalpSalPalData));
RtlZeroMemory(&SalCode, sizeof(SST_MEMORY_LIST));
RtlZeroMemory(&PalCode, sizeof(SST_MEMORY_LIST));
RtlZeroMemory(&SalData, sizeof(SST_MEMORY_LIST));
RtlZeroMemory(&FwCode, sizeof(SST_MEMORY_LIST));
//
// Initialize flags
//
MmMappedSalCode = FALSE;
MmMappedSalData = FALSE;
HalpSalPalData.Status = STATUS_SUCCESS;
//
// Map the SST, get the length of entire SST to remap the rest of it
//
physicalAddr.QuadPart = physicalSST;
HalpSalPalData.SalSystemTable = MmMapIoSpace(physicalAddr,sizeof(SST_HEADER),MmCached);
if (HalpSalPalData.SalSystemTable) {
//
// Save SAL revision in case we decide to unmap it later on.
//
HalpSalPalData.SalRevision.Revision = HalpSalPalData.SalSystemTable->SalRev;
HalDebugPrint(( HAL_INFO,
"SAL_PAL: Found SST SAL v%d.%d (XXTF:%d) at PhysAddr 0x%I64x & mapped to VirtAddr 0x%I64x\n",
HalpSalPalData.SalRevision.Major,
HalpSalPalData.SalRevision.Minor,
HalpSalPalData.SalRevision.Revision,
physicalSST,
HalpSalPalData.SalSystemTable));
SstLength=HalpSalPalData.SalSystemTable->Length;
MmUnmapIoSpace((PVOID)HalpSalPalData.SalSystemTable,sizeof(SST_HEADER));
HalpSalPalData.SalSystemTable = MmMapIoSpace(physicalAddr,SstLength,MmCached);
} else {
HalDebugPrint(( HAL_INFO, "SAL_PAL: Couldn't virtually map SST (PhysAddr: 0x%I64x)\n", physicalSST ));
HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
HalDebugPrint(( HAL_INFO,
"SAL_PAL: Mapped all of SST for PhysAddr 0x%I64x at VirtAddr 0x%I64x for %d bytes\n",
physicalSST,
HalpSalPalData.SalSystemTable, SstLength ));
//
// Because the checksum is maybe not computed and verified by the OS loader before the
// hand-off to the kernel, let's do a checksum and verify it.
//
Checksum=0;
CheckBuf= (PUCHAR) HalpSalPalData.SalSystemTable;
for (i=0; i < SstLength; i++) {
Checksum += CheckBuf[i];
}
if (Checksum) {
HalDebugPrint(( HAL_ERROR, "SAL_PAL: Checksum is BAD with value of %d, should be 0\n", Checksum ));
MmUnmapIoSpace((PVOID)HalpSalPalData.SalSystemTable,SstLength);
HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
HalDebugPrint(( HAL_INFO, "SAL_PAL: Checksum is GOOD\n" ));
//
// Pull out the SAL/PAL entrypoint and memory descriptor information we need by iterating
// over the entire SST.
//
NextEntry = (PUCHAR)(((PUCHAR) HalpSalPalData.SalSystemTable) + sizeof(SST_HEADER));
for (i = 0; i < HalpSalPalData.SalSystemTable->EntryCount; i++) {
switch ( *(PUCHAR)NextEntry ) {
case SAL_PAL_ENTRY_POINT_TYPE:
//
// It is assumed only one Entry Point Type in the SST but we do not currently
// impose this in this code.
//
FwEntry = (PSAL_PAL_ENTRY_POINT)NextEntry;
physicalSAL = FwEntry->SalEntryPoint;
physicalPAL = FwEntry->PalEntryPoint;
physicalSALGP = FwEntry->GlobalPointer;
HalDebugPrint(( HAL_INFO,
"SAL_PAL: SAL_PROC PhysAddr at 0x%I64x\n"
"SAL_PAL: PAL_PROC PhysAddr at 0x%I64x\n"
"SAL_PAL: SAL_GP PhysAddr at 0x%I64x\n",
physicalSAL,
physicalPAL,
physicalSALGP
));
((PSAL_PAL_ENTRY_POINT)NextEntry)++;
break;
case SST_MEMORY_DESCRIPTOR_TYPE:
//
// It is assumed only one REGULAR_MEMORY entry for PAL_CODE_MEM, SAL_CODE_MEM and
// SAL_DATA_MEM. However, we do not currently impose this in the code.
//
SstMemoryDescriptor = (PSST_MEMORY_DESCRIPTOR)NextEntry;
HalDebugPrint(( HAL_INFO,
"SAL_PAL: MemDesc for PhysAddr 0x%I64x (%I64d KB) - VaReg:%d,Type:%d,Use:%d\n",
SstMemoryDescriptor->MemoryAddress,(ULONGLONG)SstMemoryDescriptor->Length * 4,
SstMemoryDescriptor->NeedVaReg,SstMemoryDescriptor->MemoryType,SstMemoryDescriptor->MemoryUsage
));
if (SstMemoryDescriptor->MemoryType == REGULAR_MEMORY) {
switch(SstMemoryDescriptor->MemoryUsage) {
case PAL_CODE_MEM:
PalCode.PhysicalAddress = SstMemoryDescriptor->MemoryAddress;
PalCode.Length = SstMemoryDescriptor->Length << 12;
PalCode.NeedVaReg = SstMemoryDescriptor->NeedVaReg;
break;
case SAL_CODE_MEM:
SalCode.PhysicalAddress = SstMemoryDescriptor->MemoryAddress;
SalCode.Length = SstMemoryDescriptor->Length << 12;
SalCode.NeedVaReg = SstMemoryDescriptor->NeedVaReg;
break;
case SAL_DATA_MEM:
SalData.PhysicalAddress = SstMemoryDescriptor->MemoryAddress;
SalData.Length = SstMemoryDescriptor->Length << 12;
SalData.NeedVaReg = SstMemoryDescriptor->NeedVaReg;
break;
case FW_RESERVED:
// We need to virtually map and count these areas for NVM access.
// We should keep a list of all such regions and would allocate an
// array of virtual address mappings for each NVM region for later
// use when accessing variables.
// No NVM support currently, so ignore for now.
break;
default:
break;
}
} else if ((SstMemoryDescriptor->MemoryType == FIRMWARE_CODE) &&
(SstMemoryDescriptor->MemoryUsage == FW_SAL_PAL)) {
FwCode.PhysicalAddress = SstMemoryDescriptor->MemoryAddress;
FwCode.Length = SstMemoryDescriptor->Length << 12;
FwCode.NeedVaReg = SstMemoryDescriptor->NeedVaReg;
}
((PSST_MEMORY_DESCRIPTOR)NextEntry)++;
break;
case PLATFORM_FEATURES_TYPE:
// We ignore this entry for now...
((PPLATFORM_FEATURES)NextEntry)++;
break;
case TRANSLATION_REGISTER_TYPE:
// We ignore this entry for now...
((PTRANSLATION_REGISTER)NextEntry)++;
break;
case PTC_COHERENCE_DOMAIN_TYPE:
// We ignore this entry for now...
((PPTC_COHERENCE_DOMAIN)NextEntry)++;
break;
case AP_WAKEUP_DESCRIPTOR_TYPE:
ApWakeupDescriptor = (PAP_WAKEUP_DESCRIPTOR)NextEntry;
HalpOsBootRendezVector = (ULONG) ApWakeupDescriptor->WakeupVector;
if ((HalpOsBootRendezVector < 0x100 ) && (HalpOsBootRendezVector > 0xF)) {
HalDebugPrint(( HAL_INFO, "SAL_PAL: Found Valid WakeupVector: 0x%x\n",
HalpOsBootRendezVector ));
} else {
HalDebugPrint(( HAL_INFO, "SAL_PAL: Invalid WakeupVector.Using Default: 0x%x\n",
DEFAULT_OS_RENDEZ_VECTOR ));
HalpOsBootRendezVector = DEFAULT_OS_RENDEZ_VECTOR;
}
((PAP_WAKEUP_DESCRIPTOR)NextEntry)++;
break;
default:
HalDebugPrint(( HAL_ERROR,
"SAL_PAL: EntryType %d is bad at VirtAddr 0x%I64x, Aborting\n",
*(PUCHAR)NextEntry,
NextEntry ));
// An unknown SST Type was found, so we can't continue
MmUnmapIoSpace((PVOID)HalpSalPalData.SalSystemTable,SstLength);
HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
}
//
// Initialize the HAL private spinlocks
//
// - HalpSalSpinLock, HalpSalStateInfoSpinLock are used for MP synchronization of the
// SAL calls that are not MP-safe.
// - HalpMcaSpinLock is used for defining an MCA monarch and MP synchrnonization of shared
// HAL MCA resources during OS_MCA calls.
//
KeInitializeSpinLock(&HalpSalSpinLock);
KeInitializeSpinLock(&HalpSalStateInfoSpinLock);
KeInitializeSpinLock(&HalpMcaSpinLock);
KeInitializeSpinLock(&HalpInitSpinLock);
KeInitializeSpinLock(&HalpCmcSpinLock);
KeInitializeSpinLock(&HalpCpeSpinLock);
//
// Unmap the SalSystemTable since we will be mapping all PAL and SAL code, and SAL data area
// which includes SST.
//
// TEMP TEMP TEMP. we are not unmapping
//
// MmUnmapIoSpace((PVOID)HalpSalPalData.SalSystemTable,SstLength);
//
// Make sure we found all of our entries for mapping
//
if (!(SalCode.Length && SalData.Length && PalCode.Length && FwCode.Length)) {
HalDebugPrint(( HAL_ERROR, "SAL_PAL: One or more of the SalCode, SalData, PalCode, or FwCode spaces not in SST\n" ));
HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
//
// Since PAL will need to use only 1 TR, figure out the page size to use for mapping PAL,
// starting at 16KB, and trying 64KB, 256KB, 1MB, 4MB, and 16MB.
//
HalpSalPalData.PalTrSize = SIZE_IN_BYTES_16KB;
PalTrMask = MASK_16KB;
PalPageShift = 14;
LargerThan16Mb = 1;
while (PalTrMask >= MASK_16MB) {
// Check if it entirely fits in the given page
if ( (PalCode.PhysicalAddress + PalCode.Length) <=
( (PalCode.PhysicalAddress & PalTrMask) + HalpSalPalData.PalTrSize) ) {
LargerThan16Mb = 0;
break;
}
// Try the next page size, incrementing in multiples of 4 from 16KB to 16MB
PalTrMask <<= 2;
HalpSalPalData.PalTrSize <<= 2;
PalPageShift += 2;
}
//
// If PAL requires a page size of larger than 16MB, fail.
//
if (LargerThan16Mb) {
HalDebugPrint(( HAL_ERROR, "SAL_PAL: More than 16MB was required to map PAL" ));
HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
//
// Set the page size aligned address that fits PAL
//
HalpSalPalData.PalTrBase = PalCode.PhysicalAddress & PalTrMask;
HalDebugPrint(( HAL_INFO,
"SAL_PAL: For the PAL code located at 0x%I64x - length 0x%I64x, the TrMask is 0x%I64x and TrSize is %d Kbytes\n",
PalCode.PhysicalAddress,
PalCode.Length,
PalTrMask,
HalpSalPalData.PalTrSize/1024 ));
//
// Map the PAL code at a architected address reserved for SAL/PAL
//
// PAL is known to have an alignment of 256KB.
//
PalCode.VirtualAddress = HAL_PAL_VIRTUAL_ADDRESS + (PalCode.PhysicalAddress - HalpSalPalData.PalTrBase);
//
// Setup the ITR and DTRs to map PAL
//
PalPteUlong = HalpSalPalData.PalTrBase | VALID_KERNEL_EXECUTE_PTE;
KeFillFixedEntryTb((PHARDWARE_PTE)&PalPteUlong,
(PVOID)HAL_PAL_VIRTUAL_ADDRESS,
PalPageShift,
INST_TB_PAL_INDEX);
KeFillFixedEntryTb((PHARDWARE_PTE)&PalPteUlong,
(PVOID)HAL_PAL_VIRTUAL_ADDRESS,
PalPageShift,
DATA_TB_PAL_INDEX);
//
// SAL has no specific virtual mapping translation requirement. It can use TCs to map the
// SAL code regions and the SAL data regions.
// SAL requires virtual address translations for descriptors like PAL code areas (to be able
// to call PAL for SAL), SAL code, SAL data and NVM areas. SAL_UPDATE_PAL requires a virtual
// mapping of the FW ROM area to perform the update. The latter could be done using TCs.
//
// First check if the SAL code fits in the same page as PAL.
// If it does, then use that mapping, otherwise, create a mapping using MmMapIoSpace and
// mark it executable.
//
if ((SalCode.PhysicalAddress >= HalpSalPalData.PalTrBase) &&
((SalCode.PhysicalAddress + SalCode.Length) <= (HalpSalPalData.PalTrBase + HalpSalPalData.PalTrSize))) {
SalCode.VirtualAddress = HAL_PAL_VIRTUAL_ADDRESS + (SalCode.PhysicalAddress - HalpSalPalData.PalTrBase);
}
else {
physicalAddr.QuadPart = SalCode.PhysicalAddress;
SalCode.VirtualAddress = (ULONGLONG) MmMapIoSpace(physicalAddr, (ULONG)SalCode.Length, MmCached);
if (!SalCode.VirtualAddress) {
HalDebugPrint(( HAL_ERROR, "SAL_PAL: Failed to map the SAL code region\n" ));
goto SalPalCleanup;
}
HalDebugPrint(( HAL_INFO, "SAL_PAL: Starting to mark %d bytes of SAL code executable\n", SalCode.Length ));
//
// Temporarily commented out for Mm bug of clearing the dirty bit.
// We will enable this.
//
// MmSetPageProtection((PVOID)SalCode.VirtualAddress,
// SalCode.Length,
// 0x40 /* PAGE_EXECUTE_READWRITE */);
//
MmMappedSalCode=TRUE;
}
//
// Same check for SAL data:
// Check if the SAL data fits in the same page as PAL.
// If it does, then use that mapping, otherwise, create a mapping using MmMapIoSpace
//
if ((SalData.PhysicalAddress >= HalpSalPalData.PalTrBase) &&
((SalData.PhysicalAddress + SalData.Length) <= (HalpSalPalData.PalTrBase + HalpSalPalData.PalTrSize))) {
SalData.VirtualAddress = HAL_PAL_VIRTUAL_ADDRESS + (SalData.PhysicalAddress - HalpSalPalData.PalTrBase);
} else {
physicalAddr.QuadPart = SalData.PhysicalAddress;
SalData.VirtualAddress = (ULONGLONG) MmMapIoSpace(physicalAddr, (ULONG)SalData.Length, MmCached);
if (!SalData.VirtualAddress) {
HalDebugPrint(( HAL_ERROR, "SAL_PAL: Failed to map the SAL data region\n" ));
goto SalPalCleanup;
}
MmMappedSalData=TRUE;
}
HalDebugPrint(( HAL_INFO, "SAL_PAL: Mapped SAL code for PhysAddr 0x%I64x at VirtAddr 0x%I64x for %d bytes\n"
"SAL_PAL: Mapped PAL code for PhysAddr 0x%I64x at VirtAddr 0x%I64x for %d bytes\n"
"SAL_PAL: Mapped SAL data for PhysAddr 0x%I64x at VirtAddr 0x%I64x for %d bytes\n",
SalCode.PhysicalAddress, SalCode.VirtualAddress, SalCode.Length,
PalCode.PhysicalAddress, PalCode.VirtualAddress, PalCode.Length,
SalData.PhysicalAddress, SalData.VirtualAddress, SalData.Length
));
// Store virtual address pointers of SST, SAL_PROC, PAL_PROC, and GP for use later
// (VirtualAddr = VirtualAddrBase + PhysicalOffset) where (PhysicalOffset = physicalAddr - PhysicalBase)
// We are not ensuring SST is within the SAL code area
// ASSERT((physicalSST > SalCode.PhysicalAddress) && (physicalSST < (SalCode.PhysicalAddress + SalCode.Length)));
// HalpSalPalData.SalSystemTable = (PSST_HEADER) (SalCode.VirtualAddress + (physicalSST - SalCode.PhysicalAddress));
HalpSalProcPointer = (ULONGLONG) (SalCode.VirtualAddress + (physicalSAL - SalCode.PhysicalAddress));
HalpSalProcGlobalPointer = (ULONGLONG) (SalCode.VirtualAddress + (physicalSALGP - SalCode.PhysicalAddress));
HalpPalProcPointer = (ULONGLONG) (PalCode.VirtualAddress + (physicalPAL - PalCode.PhysicalAddress));
//
// Go map the firmware code space
//
// SAL_UPDATE_PAL requires a virtual mapping of the ROM area to perform the update.
//
HalDebugPrint(( HAL_INFO, "SAL_PAL: Mapping and Registering Virtual Address of FwCode area\n" ));
physicalAddr.QuadPart = FwCode.PhysicalAddress;
FwCodeSpace = MmMapIoSpace(physicalAddr, (ULONG) FwCode.Length, MmCached);
//
// Get the PAL version.
//
palStatus = HalCallPal(PAL_VERSION,
0,
0,
0,
NULL,
&minimumPalVersion.ReturnValue,
&HalpSalPalData.PalVersion.ReturnValue,
NULL);
if (palStatus != SAL_STATUS_SUCCESS) {
HalDebugPrint(( HAL_ERROR, "SAL_PAL: Get PAL version number failed. Status = d\n" ));
}
//
// Retrieve SmBiosVersion and save the pointer into HalpSalPalData. Note:
// HalpGetSmBiosVersion will allocate a buffer for SmBiosVersion.
//
HalpSalPalData.SmBiosVersion = HalpGetSmBiosVersion(LoaderBlock);
//
// Determine and Initialize HAL private SAL/PAL WorkArounds if any.
//
HalpInitSalPalWorkArounds();
// We completed initialization
HalDebugPrint(( HAL_INFO, "SAL_PAL: Exiting HalpSalPalInitialization with SUCCESS\n" ));
return HalpSalPalData.Status;
// Cleanup the mappings and get out of here...
SalPalCleanup:
if (MmMappedSalData) {
MmUnmapIoSpace((PVOID) SalData.VirtualAddress, (ULONG) SalData.Length);
}
if (MmMappedSalCode) {
MmUnmapIoSpace((PVOID) SalCode.VirtualAddress, (ULONG) SalCode.Length);
}
HalDebugPrint(( HAL_ERROR, "SAL_PAL: Exiting HalpSalPalInitialization with ERROR!!!\n" ));
HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
return HalpSalPalData.Status;
} // HalpInitSalPal()
PUCHAR
HalpGetSmBiosVersion (
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This function retrieves the SmBiosVersion string from the BIOS structure
table, allocates memory for the buffer, copies the string to the buffer,
and returns a pointer to this buffer. If unsuccessful, this function
returns a NULL.
Arguments:
LoaderBlock - Pointer to the loader parameter block.
Return Value:
Pointer to a buffer that contains SmBiosVersion string.
--*/
{
PSMBIOS_EPS_HEADER SMBiosEPSHeader;
PDMIBIOS_EPS_HEADER DMIBiosEPSHeader;
USHORT SMBiosTableLength;
USHORT SMBiosTableNumberStructures;
PUCHAR SmBiosVersion;
PHYSICAL_ADDRESS SMBiosTablePhysicalAddress;
PUCHAR SMBiosDataVirtualAddress;
UCHAR Type;
UCHAR Length;
UCHAR BiosVersionStringNumber;
UCHAR chr;
USHORT i;
PUCHAR pBuffer;
BOOLEAN Found;
if (LoaderBlock->Extension->Size < sizeof(LOADER_PARAMETER_EXTENSION)) {
HalDebugPrint((HAL_ERROR, "HalpGetSmBiosVersion: Invalid LoaderBlock extension size\n"));
return NULL;
}
SMBiosEPSHeader = (PSMBIOS_EPS_HEADER)LoaderBlock->Extension->SMBiosEPSHeader;
//
// Verify SM Bios Header signature
//
if ((SMBiosEPSHeader == NULL) || (strncmp((PUCHAR)SMBiosEPSHeader, "_SM_", 4) != 0)) {
HalDebugPrint((HAL_ERROR, "HalpGetSmBiosVersion: Invalid SMBiosEPSHeader\n"));
return NULL;
}
DMIBiosEPSHeader = (PDMIBIOS_EPS_HEADER)&SMBiosEPSHeader->Signature2[0];
//
// Verify DMI Bios Header signature
//
if ((DMIBiosEPSHeader == NULL) || (strncmp((PUCHAR)DMIBiosEPSHeader, "_DMI_", 5) != 0)) {
HalDebugPrint((HAL_ERROR, "HalpGetSmBiosVersion: Invalid DMIBiosEPSHeader\n"));
return NULL;
}
SMBiosTablePhysicalAddress.HighPart = 0;
SMBiosTablePhysicalAddress.LowPart = DMIBiosEPSHeader->StructureTableAddress;
SMBiosTableLength = DMIBiosEPSHeader->StructureTableLength;
SMBiosTableNumberStructures = DMIBiosEPSHeader->NumberStructures;
//
// Map SMBiosTable to virtual address
//
SMBiosDataVirtualAddress = MmMapIoSpace(SMBiosTablePhysicalAddress,
SMBiosTableLength,
MmCached
);
if (!SMBiosDataVirtualAddress) {
HalDebugPrint((HAL_ERROR, "HalpGetSmBiosVersion: Failed to map SMBiosTablePhysicalAddress\n"));
return NULL;
}
//
// The Spec doesn't say that SmBios Type 0 structure has to be the first
// structure at this entry point... so we have to traverse through memory
// to find the right one.
//
i = 0;
Found = FALSE;
while (i < SMBiosTableNumberStructures && !Found) {
i++;
Type = (UCHAR)SMBiosDataVirtualAddress[SMBIOS_STRUCT_HEADER_TYPE_FIELD];
if (Type == 0) {
Found = TRUE;
}
else {
//
// Advance to the next structure
//
SMBiosDataVirtualAddress += SMBiosDataVirtualAddress[SMBIOS_STRUCT_HEADER_LENGTH_FIELD];
// Get pass trailing string-list by looking for a double-null
while (*(PUSHORT)SMBiosDataVirtualAddress != 0) {
SMBiosDataVirtualAddress++;
}
SMBiosDataVirtualAddress += 2;
}
}
if (!Found) {
HalDebugPrint((HAL_ERROR, "HalpGetSmBiosVersion: Could not find Type 0 structure\n"));
return NULL;
}
//
// Extract BIOS Version string from the SmBios Type 0 Structure
//
Length = SMBiosDataVirtualAddress[SMBIOS_STRUCT_HEADER_LENGTH_FIELD];
BiosVersionStringNumber = SMBiosDataVirtualAddress[SMBIOS_TYPE0_STRUCT_BIOSVER_FIELD];
//
// Text strings begin right after the formatted portion of the structure.
//
pBuffer = (PUCHAR)&SMBiosDataVirtualAddress[Length];
//
// Get to the beginning of SmBiosVersion string
//
for (i = 0; i < BiosVersionStringNumber - 1; i++) {
do {
chr = *pBuffer;
pBuffer++;
} while (chr != '\0');
}
//
// Allocate memory for SmBiosVersion string and copy content of
// pBuffer to SmBiosVersion.
//
SmBiosVersion = ExAllocatePool(NonPagedPool, strlen(pBuffer)+1);
if (!SmBiosVersion) {
HalDebugPrint((HAL_ERROR, "HalpGetSmBiosVersion: Failed to allocate memory for SmBiosVersion\n"));
return NULL;
}
strcpy(SmBiosVersion, pBuffer);
MmUnmapIoSpace(SMBiosDataVirtualAddress,
SMBiosTableLength
);
return SmBiosVersion;
}
VOID
HalpInitSalPalNonBsp(
VOID
)
/*++
Routine Description:
This function is called for the non-BSP processors to simply set up the same
TR registers that HalpInitSalPal does for the BSP processor.
Arguments:
None
Return Value:
None
--*/
{
ULONG PalPageShift;
ULONGLONG PalPteUlong;
ULONGLONG PalTrSize;
// If we successfully initialized in HalpSalPalInitialization, then set-up the TR
if (!NT_SUCCESS(HalpSalPalData.Status)) {
return;
}
PalTrSize = HalpSalPalData.PalTrSize;
PalPageShift = 14;
while (PalTrSize > ((ULONGLONG)1 << PalPageShift)) {
PalPageShift += 2;
}
PalPteUlong = HalpSalPalData.PalTrBase | VALID_KERNEL_EXECUTE_PTE;
KeFillFixedEntryTb((PHARDWARE_PTE)&PalPteUlong,
(PVOID)HAL_PAL_VIRTUAL_ADDRESS,
PalPageShift,
INST_TB_PAL_INDEX);
KeFillFixedEntryTb((PHARDWARE_PTE)&PalPteUlong,
(PVOID)HAL_PAL_VIRTUAL_ADDRESS,
PalPageShift,
DATA_TB_PAL_INDEX);
} // HalpInitSalPalNonBsp()
NTSTATUS
HalpEfiInitialization(
PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This function
Arguments:
LoaderBlock - Supplies a pointer to the Loader parameter block, containing the
physical address of the EFI system table.
Return Value:
STATUS_SUCCESS is returned if the mappings were successful, and EFI calls can
be made. Otherwise, STATUS_UNSUCCESSFUL is returned.
--*/
{
//
// Local declarations
//
EFI_MEMORY_DESCRIPTOR *efiMapEntryPtr, *efiVirtualMemoryMapPtr;
EFI_STATUS status;
ULONGLONG index, mapEntries;
ULONGLONG physicalEfiST, physicalEfiMemoryMapPtr, physicalRunTimeServicesPtr;
ULONGLONG physicalEfiGetVariable, physicalEfiGetNextVariableName, physicalEfiSetVariable;
ULONGLONG physicalEfiGetTime, physicalEfiSetTime;
ULONGLONG physicalEfiSetVirtualAddressMap, physicalEfiResetSystem;
PHYSICAL_ADDRESS physicalAddr;
ULONGLONG physicalPlabel_Fpswa;
FPSWA_INTERFACE *interfacePtr;
PVOID tmpPtr;
//
// First, get the physical address of the fpswa entry point PLABEL.
//
if (LoaderBlock->u.Ia64.FpswaInterface != (ULONG_PTR) NULL) {
physicalAddr.QuadPart = LoaderBlock->u.Ia64.FpswaInterface;
interfacePtr = MmMapIoSpace(physicalAddr,
sizeof(FPSWA_INTERFACE),
MmCached
);
if (interfacePtr == NULL) {
HalDebugPrint(( HAL_FATAL_ERROR, "FpswaInterfacePtr is Null. Efi handle not available\n"));
KeBugCheckEx(FP_EMULATION_ERROR, 0, 0, 0, 0);
return STATUS_UNSUCCESSFUL;
}
physicalPlabel_Fpswa = (ULONGLONG)(interfacePtr->Fpswa);
}
else {
HalDebugPrint(( HAL_FATAL_ERROR, "HAL: EFI FpswaInterface is not available\n"));
KeBugCheckEx(FP_EMULATION_ERROR, 0, 0, 0, 0);
return STATUS_UNSUCCESSFUL;
}
physicalEfiST = LoaderBlock->u.Ia64.EfiSystemTable;
physicalAddr.QuadPart = physicalEfiST;
EfiSysTableVirtualPtr = MmMapIoSpace( physicalAddr, sizeof(EFI_SYSTEM_TABLE), MmCached);
if (EfiSysTableVirtualPtr == NULL) {
HalDebugPrint(( HAL_ERROR, "HAL: EfiSystem Table Virtual Addr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
EfiSysTableVirtualPtrCpy = EfiSysTableVirtualPtr;
physicalRunTimeServicesPtr = (ULONGLONG) EfiSysTableVirtualPtr->RuntimeServices;
physicalAddr.QuadPart = physicalRunTimeServicesPtr;
EfiRSVirtualPtr = MmMapIoSpace(physicalAddr, sizeof(EFI_RUNTIME_SERVICES),MmCached);
if (EfiRSVirtualPtr == NULL) {
HalDebugPrint(( HAL_ERROR, "HAL: Run Time Table Virtual Addr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
EfiMemoryMapSize = LoaderBlock->u.Ia64.EfiMemMapParam.MemoryMapSize;
EfiDescriptorSize = LoaderBlock->u.Ia64.EfiMemMapParam.DescriptorSize;
EfiDescriptorVersion = LoaderBlock->u.Ia64.EfiMemMapParam.DescriptorVersion;
physicalEfiMemoryMapPtr = (ULONGLONG)LoaderBlock->u.Ia64.EfiMemMapParam.MemoryMap;
physicalAddr.QuadPart = physicalEfiMemoryMapPtr;
efiVirtualMemoryMapPtr = MmMapIoSpace (physicalAddr, EfiMemoryMapSize, MmCached);
if (efiVirtualMemoryMapPtr == NULL) {
HalDebugPrint(( HAL_ERROR, "HAL: Virtual Set Memory Map Virtual Addr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
//
// #define VENDOR_SPECIFIC_GUID \
// { 0xa3c72e56, 0x4c35, 0x11d3, 0x8a, 0x03, 0x0, 0xa0, 0xc9, 0x06, 0xad, 0xec }
//
VendorGuid.Data1 = 0x8be4df61;
VendorGuid.Data2 = 0x93ca;
VendorGuid.Data3 = 0x11d2;
VendorGuid.Data4[0] = 0xaa;
VendorGuid.Data4[1] = 0x0d;
VendorGuid.Data4[2] = 0x00;
VendorGuid.Data4[3] = 0xe0;
VendorGuid.Data4[4] = 0x98;
VendorGuid.Data4[5] = 0x03;
VendorGuid.Data4[6] = 0x2b;
VendorGuid.Data4[7] = 0x8c;
HalDebugPrint(( HAL_INFO,
"HAL: EFI SystemTable VA = 0x%I64x, PA = 0x%I64x\n"
"HAL: EFI RunTimeServices VA = 0x%I64x, PA = 0x%I64x\n"
"HAL: EFI MemoryMapPtr VA = 0x%I64x, PA = 0x%I64x\n"
"HAL: EFI MemoryMap Size = 0x%I64x\n"
"HAL: EFI Descriptor Size = 0x%I64x\n",
EfiSysTableVirtualPtr,
physicalEfiST,
EfiRSVirtualPtr,
physicalRunTimeServicesPtr,
efiVirtualMemoryMapPtr,
physicalEfiMemoryMapPtr,
EfiMemoryMapSize,
EfiDescriptorSize
));
// GetVariable
physicalEfiGetVariable = (ULONGLONG) (EfiRSVirtualPtr -> GetVariable);
physicalAddr.QuadPart = physicalEfiGetVariable;
EfiVirtualGetVariablePtr = MmMapIoSpace (physicalAddr, sizeof(PLABEL_DESCRIPTOR), MmCached);
if (EfiVirtualGetVariablePtr == NULL) {
HalDebugPrint(( HAL_ERROR, "HAL: EfiGetVariable Virtual Addr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
HalDebugPrint(( HAL_INFO, "HAL: EFI GetVariable VA = 0x%I64x, PA = 0x%I64x\n",
EfiVirtualGetVariablePtr, physicalEfiGetVariable ));
// GetNextVariableName
physicalEfiGetNextVariableName = (ULONGLONG) (EfiRSVirtualPtr -> GetNextVariableName);
physicalAddr.QuadPart = physicalEfiGetNextVariableName;
EfiVirtualGetNextVariableNamePtr = MmMapIoSpace (physicalAddr,sizeof(PLABEL_DESCRIPTOR),MmCached);
if (EfiVirtualGetNextVariableNamePtr == NULL) {
HalDebugPrint(( HAL_ERROR, "HAL: EfiVirtual Get Next Variable Name Ptr Addr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
//SetVariable
physicalEfiSetVariable = (ULONGLONG) (EfiRSVirtualPtr -> SetVariable);
physicalAddr.QuadPart = physicalEfiSetVariable;
EfiVirtualSetVariablePtr = MmMapIoSpace (physicalAddr, sizeof(PLABEL_DESCRIPTOR), MmCached);
if (EfiVirtualSetVariablePtr == NULL) {
HalDebugPrint(( HAL_ERROR, "HAL: EfiVariableSetVariable Pointer dr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
HalDebugPrint(( HAL_INFO, "HAL: EFI Set Variable VA = 0x%I64x, PA = 0x%I64x\n",
EfiVirtualSetVariablePtr, physicalEfiSetVariable ));
//GetTime
physicalEfiGetTime = (ULONGLONG) (EfiRSVirtualPtr -> GetTime);
physicalAddr.QuadPart = physicalEfiGetTime;
EfiVirtualGetTimePtr = MmMapIoSpace (physicalAddr, sizeof(PLABEL_DESCRIPTOR), MmCached);
if (EfiVirtualGetTimePtr == NULL) {
HalDebugPrint(( HAL_ERROR, "HAL: EfiGetTime Virtual Addr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
HalDebugPrint(( HAL_INFO, "HAL: EFI GetTime VA = 0x%I64x, PA = 0x%I64x\n",
EfiVirtualGetTimePtr, physicalEfiGetTime ));
//SetTime
physicalEfiSetTime = (ULONGLONG) (EfiRSVirtualPtr -> SetTime);
physicalAddr.QuadPart = physicalEfiSetTime;
EfiVirtualSetTimePtr = MmMapIoSpace (physicalAddr, sizeof(PLABEL_DESCRIPTOR), MmCached);
if (EfiVirtualSetTimePtr == NULL) {
HalDebugPrint(( HAL_ERROR, "HAL: EfiSetTime Virtual Addr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
HalDebugPrint(( HAL_INFO, "HAL: EFI SetTime VA = 0x%I64x, PA = 0x%I64x\n",
EfiVirtualSetTimePtr, physicalEfiSetTime ));
//SetVirtualAddressMap
physicalEfiSetVirtualAddressMap = (ULONGLONG) (EfiRSVirtualPtr -> SetVirtualAddressMap);
physicalAddr.QuadPart = physicalEfiSetVirtualAddressMap;
EfiSetVirtualAddressMapPtr = MmMapIoSpace (physicalAddr, sizeof(PLABEL_DESCRIPTOR), MmCached);
if (EfiSetVirtualAddressMapPtr == NULL) {
HalDebugPrint(( HAL_ERROR, "HAL: Efi Set VirtualMapPointer Virtual Addr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
HalDebugPrint(( HAL_INFO, "HAL: EFI SetVirtualAddressMap VA = 0x%I64x, PA = 0x%I64x\n",
EfiSetVirtualAddressMapPtr, physicalEfiSetVirtualAddressMap ));
//ResetSystem
physicalEfiResetSystem = (ULONGLONG) (EfiRSVirtualPtr -> ResetSystem);
physicalAddr.QuadPart = physicalEfiResetSystem;
EfiResetSystemPtr = MmMapIoSpace (physicalAddr, sizeof(PLABEL_DESCRIPTOR), MmCached);
if (EfiResetSystemPtr == NULL) {
HalDebugPrint(( HAL_ERROR,"HAL: Efi Reset System Virtual Addr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
HalDebugPrint(( HAL_INFO, "HAL: EFI ResetSystem VA = 0x%I64x, PA = 0x%I64x\n",
EfiResetSystemPtr, physicalEfiResetSystem ));
//
// Allocate one page for Backing store
//
physicalAddr.QuadPart = 0xffffffffffffffffI64;
tmpPtr = MmAllocateContiguousMemory( PAGE_SIZE, physicalAddr );
HalpPhysBSPointer = (PULONGLONG)( ( MmGetPhysicalAddress( tmpPtr ) ).QuadPart );
//
// Allocate one page for the Stack, then make sure the base pointer
// is assigned to the high address of this block since the stack
// grows down.
//
tmpPtr = MmAllocateContiguousMemory( PAGE_SIZE, physicalAddr );
HalpPhysStackPointer = (PULONGLONG)( ( MmGetPhysicalAddress( tmpPtr ) ).QuadPart + PAGE_SIZE - 16);
HalpVirtualCommonDataPointer = (PUCHAR)(ExAllocatePool (NonPagedPool, PAGE_SIZE));
HalpVariableNameVirtualPtr = HalpVirtualCommonDataPointer + VariableNameOffset;
HalpVendorGuidVirtualPtr = HalpVirtualCommonDataPointer + VendorGuidOffset;
HalpVariableAttributesVirtualPtr = HalpVirtualCommonDataPointer + AttributeOffset;
HalpDataSizeVirtualPtr = HalpVirtualCommonDataPointer + DataSizeOffset;
HalpDataVirtualPtr = HalpVirtualCommonDataPointer + DataBufferOffset;
HalpCommonDataEndPtr = HalpVirtualCommonDataPointer + EndOfCommonDataOffset;
HalpMemoryMapSizeVirtualPtr = HalpVirtualCommonDataPointer + MemoryMapSizeOffset;
HalpMemoryMapVirtualPtr = (PUCHAR)(HalpVirtualCommonDataPointer + MemoryMapOffset);
HalpDescriptorSizeVirtualPtr = HalpVirtualCommonDataPointer + DescriptorSizeOffset;
HalpDescriptorVersionVirtualPtr = HalpVirtualCommonDataPointer + DescriptorVersionOffset;
HalpPhysCommonDataPointer = (PUCHAR)((MmGetPhysicalAddress(HalpVirtualCommonDataPointer)).QuadPart);
HalpVariableNamePhysPtr = HalpPhysCommonDataPointer + VariableNameOffset;
HalpVendorGuidPhysPtr = HalpPhysCommonDataPointer + VendorGuidOffset;
HalpVariableAttributesPhysPtr = HalpPhysCommonDataPointer + AttributeOffset;
HalpDataSizePhysPtr = HalpPhysCommonDataPointer + DataSizeOffset;
HalpDataPhysPtr = HalpPhysCommonDataPointer + DataBufferOffset;
HalpMemoryMapSizePhysPtr = HalpPhysCommonDataPointer + MemoryMapSizeOffset;
HalpMemoryMapPhysPtr = HalpPhysCommonDataPointer + MemoryMapOffset;
HalpDescriptorSizePhysPtr = HalpPhysCommonDataPointer + DescriptorSizeOffset;
HalpDescriptorVersionPhysPtr = HalpPhysCommonDataPointer + DescriptorVersionOffset;
AttributePtr = &EfiAttribute;
DataSizePtr = &EfiDataSize;
RtlCopyMemory ((PULONGLONG)HalpMemoryMapVirtualPtr,
efiVirtualMemoryMapPtr,
(ULONG)(EfiMemoryMapSize)
);
//
// Now, extract SAL, PAL information from the loader parameter block and
// initializes HAL SAL, PAL definitions.
//
// N.B 10/2000:
// We do not check the return status of HalpInitSalPal(). We should. FIXFIX.
// In case of failure, we currently flag HalpSalPalData.Status as unsuccessful.
//
HalpInitSalPal(LoaderBlock);
//
// Initialize Spin Lock
//
KeInitializeSpinLock(&EFIMPLock);
ASSERT (EfiDescriptorVersion == EFI_MEMORY_DESCRIPTOR_VERSION);
// if (EfiDescriptorVersion != EFI_MEMORY_DESCRIPTION_VERSION) {
// HalDebugPrint(HAL_ERROR,("Efi Memory Map Pointer VAddr is NULL\n"));
// EfiInitStatus = STATUS_UNSUCCESSFUL;
// return STATUS_UNSUCCESSFUL;
// }
HalDebugPrint(( HAL_INFO, "HAL: Creating EFI virtual address mapping\n" ));
efiMapEntryPtr = efiVirtualMemoryMapPtr;
if (efiMapEntryPtr == NULL) {
HalDebugPrint(( HAL_ERROR, "HAL: Efi Memory Map Pointer VAddr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
mapEntries = EfiMemoryMapSize/EfiDescriptorSize;
HalDebugPrint(( HAL_INFO, "HAL: EfiMemoryMapSize: 0x%I64x & EfiDescriptorSize: 0x%I64x & #of entries: 0x%I64x\n",
EfiMemoryMapSize,
EfiDescriptorSize,
mapEntries ));
HalDebugPrint(( HAL_INFO, "HAL: Efi RunTime Attribute will be printed as 1\n" ));
for (index = 0; index < mapEntries; index= index + 1) {
BOOLEAN attribute = 0;
physicalAddr.QuadPart = efiMapEntryPtr -> PhysicalStart;
if ((efiMapEntryPtr->Attribute) & EFI_MEMORY_RUNTIME) {
attribute = 1;
switch (efiMapEntryPtr->Type) {
case EfiRuntimeServicesData:
case EfiReservedMemoryType:
efiMapEntryPtr->VirtualStart = (ULONGLONG) (MmMapIoSpace (physicalAddr,
(SIZE_T)((EFI_PAGE_SIZE)*(efiMapEntryPtr->NumberOfPages)),
(efiMapEntryPtr->Attribute & EFI_MEMORY_WB) ? MmCached : MmNonCached
));
if ((efiMapEntryPtr->VirtualStart) == 0) {
HalDebugPrint(( HAL_ERROR, "HAL: Efi RunTimeSrvceData/RsrvdMemory area VAddr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
HalDebugPrint(( HAL_INFO,
"HAL: Efi attribute %d & Type 0x%I64x with # of 4k pages 0x%I64x at PA 0x%I64x & mapped to VA 0x%I64x\n",
attribute,
efiMapEntryPtr->Type,
efiMapEntryPtr->NumberOfPages,
efiMapEntryPtr->PhysicalStart,
efiMapEntryPtr->VirtualStart ));
break;
case EfiPalCode:
efiMapEntryPtr->VirtualStart = PalCode.VirtualAddress;
HalDebugPrint(( HAL_INFO,
"HAL: Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x & mapped to VA 0x%I64x\n",
attribute,
efiMapEntryPtr->Type,
efiMapEntryPtr->NumberOfPages,
efiMapEntryPtr->PhysicalStart,
efiMapEntryPtr->VirtualStart ));
break;
case EfiRuntimeServicesCode:
if(physicalAddr.QuadPart != OptionROMAddress) {
efiMapEntryPtr->VirtualStart = (ULONGLONG) (MmMapIoSpace (physicalAddr,
(EFI_PAGE_SIZE) * (efiMapEntryPtr->NumberOfPages),
MmCached
));
if ((efiMapEntryPtr->VirtualStart) == 0) {
HalDebugPrint(( HAL_ERROR, "HAL: Efi RunTimeSrvceCode area VAddr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
//
// Give Execution previlege
//
//
// Temporarily commented out. Will be enabled once Mm does not clear dirty bit here.
//
// MmSetPageProtection ((PVOID)(efiMapEntryPtr->VirtualStart),
// (EFI_PAGE_SIZE) * (efiMapEntryPtr->NumberOfPages),
// 0x40 /* PAGE_EXECUTE_READWRITE */
// );
HalDebugPrint(( HAL_INFO,
"HAL: Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x & mapped to VA 0x%I64x\n",
attribute,
efiMapEntryPtr->Type,
efiMapEntryPtr->NumberOfPages,
efiMapEntryPtr->PhysicalStart,
efiMapEntryPtr->VirtualStart));
break;
} else {
efiMapEntryPtr->VirtualStart = OptionROMAddress;
HalDebugPrint(( HAL_INFO,
"HAL: Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x. NOT MAPPED\n",
attribute,
efiMapEntryPtr->Type,
efiMapEntryPtr->NumberOfPages,
efiMapEntryPtr->PhysicalStart ));
break;
}
case EfiMemoryMappedIO:
efiMapEntryPtr->VirtualStart = (ULONGLONG) (MmMapIoSpace (physicalAddr,
(EFI_PAGE_SIZE) * (efiMapEntryPtr->NumberOfPages),
MmNonCached
));
if ((efiMapEntryPtr->VirtualStart) == 0) {
HalDebugPrint(( HAL_ERROR, "HAL: Efi MemoryMappedIO VAddr is NULL\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
HalDebugPrint(( HAL_INFO,
"HAL: Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x & mapped to VA 0x%I64x\n",
attribute,
efiMapEntryPtr->Type,
efiMapEntryPtr->NumberOfPages,
efiMapEntryPtr->PhysicalStart,
efiMapEntryPtr->VirtualStart ));
break;
case EfiMemoryMappedIOPortSpace:
efiMapEntryPtr->VirtualStart = VIRTUAL_IO_BASE;
HalDebugPrint(( HAL_INFO,
"HAL: Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x ALREADY mapped to VA 0x%I64x\n",
attribute,
efiMapEntryPtr->Type,
efiMapEntryPtr->NumberOfPages,
efiMapEntryPtr->PhysicalStart,
efiMapEntryPtr->VirtualStart ));
break;
default:
HalDebugPrint(( HAL_INFO, "HAL: Efi CONTROL SHOULD NOT COME HERE \n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
break;
}
} else {
HalDebugPrint(( HAL_INFO,
"HAL: Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x ALREADY mapped to VA 0x%I64x\n",
attribute,
efiMapEntryPtr->Type,
efiMapEntryPtr->NumberOfPages,
efiMapEntryPtr->PhysicalStart,
efiMapEntryPtr->VirtualStart ));
}
efiMapEntryPtr = NextMemoryDescriptor(efiMapEntryPtr,EfiDescriptorSize);
}
status = HalpCallEfi(EFI_SET_VIRTUAL_ADDRESS_MAP_INDEX,
(ULONGLONG)EfiMemoryMapSize,
(ULONGLONG)EfiDescriptorSize,
(ULONGLONG)EfiDescriptorVersion,
(ULONGLONG)efiVirtualMemoryMapPtr,
0,
0,
0,
0
);
HalDebugPrint(( HAL_INFO, "HAL: Returned from SetVirtualAddressMap: 0x%Ix\n", status ));
if (EFI_ERROR( status )) {
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
HalDebugPrint(( HAL_INFO, "HAL: EFI Virtual Address mapping done...\n" ));
EfiInitStatus = STATUS_SUCCESS;
//
// Execute some validity checks on the floating point software assist.
//
if (LoaderBlock->u.Ia64.FpswaInterface != (ULONG_PTR) NULL) {
PPLABEL_DESCRIPTOR plabelPointer;
HalpFpEmulate = interfacePtr->Fpswa;
if (HalpFpEmulate == NULL ) {
HalDebugPrint(( HAL_FATAL_ERROR, "HAL: EfiFpswa Virtual Addr is NULL\n" ));
KeBugCheckEx(FP_EMULATION_ERROR, 0, 0, 0, 0);
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
plabelPointer = (PPLABEL_DESCRIPTOR) HalpFpEmulate;
if ((plabelPointer->EntryPoint & 0xe000000000000000) == 0) {
HalDebugPrint(( HAL_FATAL_ERROR, "HAL: EfiFpswa Instruction Addr is bougus\n" ));
KeBugCheckEx(FP_EMULATION_ERROR, 0, 0, 0, 0);
}
}
return STATUS_SUCCESS;
} // HalpEfiInitialization()
EFI_STATUS
HalpCallEfi(
IN ULONGLONG FunctionId,
IN ULONGLONG Arg1,
IN ULONGLONG Arg2,
IN ULONGLONG Arg3,
IN ULONGLONG Arg4,
IN ULONGLONG Arg5,
IN ULONGLONG Arg6,
IN ULONGLONG Arg7,
IN ULONGLONG Arg8
)
/*++
Routine Description:
:9
This function is a wrapper function for making a EFI call. Callers within the
HAL must use this function to call the EFI.
Arguments:
FunctionId - The EFI function
Arg1-Arg7 - EFI defined arguments for each call
ReturnValues - A pointer to an array of 4 64-bit return values
Return Value:
SAL's return status, return value 0, is returned in addition to the ReturnValues structure
being filled
--*/
{
ULONGLONG EP, GP;
EFI_STATUS efiStatus;
//
// Storage for old level
//
KIRQL OldLevel;
if (((FunctionId != EFI_SET_VIRTUAL_ADDRESS_MAP_INDEX) || (FunctionId != EFI_RESET_SYSTEM_INDEX))
&& (!NT_SUCCESS(EfiInitStatus))) {
return EFI_UNSUPPORTED;
}
switch (FunctionId) {
case EFI_GET_VARIABLE_INDEX:
//
// Dereference the pointer to get the function arguements
//
EP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetVariablePtr) -> EntryPoint;
GP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetVariablePtr) -> GlobalPointer;
//
// Acquire MP Lock
//
KeAcquireSpinLock (&EFIMPLock, &OldLevel);
efiStatus = (HalpCallEfiVirtual( (ULONGLONG)Arg1, // VariableNamePtr
(ULONGLONG)Arg2, // VendorGuidPtr
(ULONGLONG)Arg3, // VariableAttributesPtr,
(ULONGLONG)Arg4, // DataSizePtr,
(ULONGLONG)Arg5, // DataPtr,
Arg6,
EP,
GP
));
//
// Release the MP Lock
//
KeReleaseSpinLock (&EFIMPLock, OldLevel);
break;
case EFI_SET_VARIABLE_INDEX:
//
// Dereference the pointer to get the function arguements
//
EP = ((PPLABEL_DESCRIPTOR)EfiVirtualSetVariablePtr) -> EntryPoint;
GP = ((PPLABEL_DESCRIPTOR)EfiVirtualSetVariablePtr) -> GlobalPointer;
//
// Acquire MP Lock
//
KeAcquireSpinLock (&EFIMPLock, &OldLevel);
efiStatus = (HalpCallEfiVirtual( Arg1,
Arg2,
Arg3,
Arg4,
Arg5,
Arg6,
EP,
GP
));
//
// Release the MP Lock
//
KeReleaseSpinLock (&EFIMPLock, OldLevel);
break;
case EFI_GET_NEXT_VARIABLE_NAME_INDEX:
//
// Dereference the pointer to get the function arguements
//
EP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetNextVariableNamePtr) -> EntryPoint;
GP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetNextVariableNamePtr) -> GlobalPointer;
//
// Acquire MP Lock
//
KeAcquireSpinLock (&EFIMPLock, &OldLevel);
efiStatus = (HalpCallEfiVirtual( Arg1,
Arg2,
Arg3,
Arg4,
Arg5,
Arg6,
EP,
GP
));
//
// Release the MP Lock
//
KeReleaseSpinLock (&EFIMPLock, OldLevel);
break;
case EFI_GET_TIME_INDEX:
//
// Dereference the pointer to get the function arguements
//
EP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetTimePtr) -> EntryPoint;
GP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetTimePtr) -> GlobalPointer;
//
// Acquire MP Lock
//
KeAcquireSpinLock (&EFIMPLock, &OldLevel);
efiStatus = (HalpCallEfiVirtual ((ULONGLONG)Arg1, //EFI_TIME
(ULONGLONG)Arg2, //EFI_TIME Capabilities
Arg3,
Arg4,
Arg5,
Arg6,
EP,
GP
));
//
// Release the MP Lock
//
KeReleaseSpinLock (&EFIMPLock, OldLevel);
break;
case EFI_SET_TIME_INDEX:
//
// Dereference the pointer to get the function arguements
//
EP = ((PPLABEL_DESCRIPTOR)EfiVirtualSetTimePtr) -> EntryPoint;
GP = ((PPLABEL_DESCRIPTOR)EfiVirtualSetTimePtr) -> GlobalPointer;
//
// Acquire MP Lock
//
KeAcquireSpinLock (&EFIMPLock, &OldLevel);
efiStatus = (HalpCallEfiVirtual ((ULONGLONG)Arg1, //EFI_TIME
Arg2,
Arg3,
Arg4,
Arg5,
Arg6,
EP,
GP
));
//
// Release the MP Lock
//
KeReleaseSpinLock (&EFIMPLock, OldLevel);
break;
case EFI_SET_VIRTUAL_ADDRESS_MAP_INDEX:
//
// Dereference the pointer to get the function arguements
//
EP = ((PPLABEL_DESCRIPTOR)EfiSetVirtualAddressMapPtr) -> EntryPoint;
GP = ((PPLABEL_DESCRIPTOR)EfiSetVirtualAddressMapPtr) -> GlobalPointer;
//
// Arg 1 and 5 are virtual mode pointers. We need to convert to physical
//
RtlCopyMemory (HalpMemoryMapVirtualPtr,
(PULONGLONG)Arg4,
(ULONG)EfiMemoryMapSize
);
//
// Acquire MP Lock
//
KeAcquireSpinLock (&EFIMPLock, &OldLevel);
efiStatus = (HalpCallEfiPhysical ((ULONGLONG)EfiMemoryMapSize,
(ULONGLONG)EfiDescriptorSize,
(ULONGLONG)EfiDescriptorVersion,
(ULONGLONG)HalpMemoryMapPhysPtr,
Arg5,
Arg6,
EP,
GP
));
//
// Release the MP Lock
//
KeReleaseSpinLock (&EFIMPLock, OldLevel);
break;
case EFI_RESET_SYSTEM_INDEX:
//
// Dereference the pointer to get the function arguements
//
EP = ((PPLABEL_DESCRIPTOR)EfiResetSystemPtr) -> EntryPoint;
GP = ((PPLABEL_DESCRIPTOR)EfiResetSystemPtr) -> GlobalPointer;
//
// Acquire MP Lock
//
KeAcquireSpinLock (&EFIMPLock, &OldLevel);
efiStatus = ((HalpCallEfiVirtual ( Arg1,
Arg2,
Arg3,
Arg4,
Arg5,
Arg6,
EP,
GP
)));
//
// Release the MP Lock
//
KeReleaseSpinLock (&EFIMPLock, OldLevel);
break;
default:
//
// DebugPrint("EFI: Not supported now\n");
//
efiStatus = EFI_UNSUPPORTED;
break;
}
return efiStatus;
} // HalpCallEfi()
HalpFpErrorPrint (PAL_RETURN pal_ret)
{
EM_uint64_t err_nr;
unsigned int qp;
EM_uint64_t OpCode;
unsigned int rc;
unsigned int significand_size;
unsigned int ISRlow;
unsigned int f1;
unsigned int sign;
unsigned int exponent;
EM_uint64_t significand;
unsigned int new_trap_type;
err_nr = pal_ret.err1 >> 56;
switch (err_nr) {
case 1:
// err_nr = 1 in err1, bits 63-56
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: template FXX is invalid\n"));
break;
case 2:
// err_nr = 2 in err1, bits 63-56
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: instruction slot 3 is not valid \n"));
break;
case 3:
// err_nr = 3 in err1, bits 63-56
// qp in err1, bits 31-0
qp = (unsigned int) pal_ret.err1 & 0xffffffff;
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: qualifying predicate PR[%ud] = 0 \n",qp));
break;
case 4:
// err_nr = 4 in err1, bits 63-56
// OpCode in err2, bits 63-0
OpCode = pal_ret.err2;
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: instruction opcode %8x%8x not recognized \n",
(unsigned int)((OpCode >> 32) & 0xffffffff),(unsigned int)(OpCode & 0xffffffff)));
break;
case 5:
// err_nr = 5 in err1, bits 63-56
// rc in err1, bits 31-0 (1-0)
rc = (unsigned int) pal_ret.err1 & 0xffffffff;
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: invalid rc = %ud\n", rc));
break;
case 6:
// err_nr = 6 in err1, bits 63-56
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: cannot determine the computation model \n"));
break;
case 7:
// err_nr = 7 in err1, bits 63-56
// significand_size in err1, bits 55-32
// ISRlow in err1, bits 31-0
// f1 in err2, bits 63-32
// tmp_fp.sign in err2, bit 17
// tmp_fp.exponent in err2, bits 16-0
// tmp_fp.significand in err3
significand_size = (unsigned int)((pal_ret.err1 >> 32) & 0xffffff);
ISRlow = (unsigned int) (pal_ret.err1 & 0xffffffff);
f1 = (unsigned int) ((pal_ret.err2 >> 32) & 0xffffffff);
sign = (unsigned int) ((pal_ret.err2 >> 17) & 0x01);
exponent = (unsigned int) (pal_ret.err2 & 0x1ffff);
significand = pal_ret.err3;
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: incorrect significand \
size %ud for ISRlow = %4.4x and FR[%ud] = %1.1x %5.5x %8x%8x\n",
significand_size, ISRlow, f1, sign, exponent,
(unsigned int)((significand >> 32) & 0xffffffff),
(unsigned int)(significand & 0xffffffff)));
break;
case 8:
// err_nr = 8 in err1, bits 63-56
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: non-tiny result\n"));
break;
case 9:
// err_nr = 9 in err1, bits 63-56
// significand_size in err1, bits 31-0
significand_size = (unsigned int) pal_ret.err1 & 0xffffffff;
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: incorrect significand \
size %ud\n", significand_size));
break;
case 10:
// err_nr = 10 in err1, bits 63-56
// rc in err1, bits 31-0
rc = (unsigned int) (pal_ret.err1 & 0xffffffff);
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: invalid rc = %ud for \
non-SIMD F1 instruction\n", rc));
break;
case 11:
// err_nr = 11 in err1, bits 63-56
// ISRlow & 0x0ffff in err1, bits 31-0
ISRlow = (unsigned int) (pal_ret.err1 & 0xffffffff);
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: SWA trap code invoked \
with F1 instruction, w/o O or U set in ISR.code = %x\n", ISRlow));
break;
case 12:
// err_nr = 12 in err1, bits 63-56
// ISRlow & 0x0ffff in err1, bits 31-0
ISRlow = (unsigned int) (pal_ret.err1 & 0xffffffff);
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: SWA trap code invoked \
with SIMD F1 instruction, w/o O or U set in ISR.code = %x\n", ISRlow));
break;
case 13:
// err_nr = 13 in err1, bits 63-56
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: non-tiny result low\n"));
break;
case 14:
// err_nr = 14 in err1, bits 63-56
// rc in err1, bits 31-0
rc = (unsigned int) (pal_ret.err1 & 0xffffffff);
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: invalid rc = %ud for \
SIMD F1 instruction\n", rc));
break;
case 15:
// err_nr = 15 in err1, bits 63-56
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: non-tiny result high\n"));
break;
case 16:
// err_nr = 16 in err1, bits 63-56
// OpCode in err2, bits 63-0
OpCode = pal_ret.err2;
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: instruction opcode %8x%8x \
not valid for SWA trap\n", (unsigned int)((OpCode >> 32) & 0xffffffff),
(unsigned int)(OpCode & 0xffffffff)));
break;
case 17:
// err_nr = 17 in err1, bits 63-56
// OpCode in err2, bits 63-0
// ISRlow in err3, bits 31-0
OpCode = pal_ret.err2;
ISRlow = (unsigned int) (pal_ret.err3 & 0xffffffff);
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: fp_emulate () called w/o \
trap_type FPFLT or FPTRAP, OpCode = %8x%8x, and ISR code = %x\n",
(unsigned int)((OpCode >> 32) & 0xffffffff),
(unsigned int)(OpCode & 0xffffffff), ISRlow));
break;
case 18:
// err_nr = 18 in err1, bits 63-56
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: SWA fault repeated\n"));
break;
case 19:
// err_nr = 19 in err1, bits 63-56
// new_trap_type in err1, bits 31-0
new_trap_type = (unsigned int) (pal_ret.err1 & 0xffffffff);
HalDebugPrint(( HAL_ERROR, "fp_emulate () Internal Error: new_trap_type = %x\n",
new_trap_type));
break;
default:
// error
HalDebugPrint(( HAL_ERROR, "Incorrect err_nr = %8x%8x from fp_emulate ()\n",
(unsigned int)((err_nr >> 32) & 0xffffffff),
(unsigned int)(err_nr & 0xffffffff)));
}
}
LONG
HalFpEmulate (
ULONG trap_type,
BUNDLE *pbundle,
ULONGLONG *pipsr,
ULONGLONG *pfpsr,
ULONGLONG *pisr,
ULONGLONG *ppreds,
ULONGLONG *pifs,
FP_STATE *fp_state
)
/*++
Routine Description:
This function is a wrapper function to make fp_emulate() call
to EFI FPSWA driver.
Arguments:
trap_type - indicating which FP trap it is.
pbundle - bundle where this trap occurred
pipsr - IPSR value
pfpsr - FPSR value
pisr - ISR value
ppreds - value of predicate registers
pifs - IFS value
fp_state - floating point registers
Return Value:
return IEEE result of the floating point operation
--*/
{
PAL_RETURN ret;
ret = (*HalpFpEmulate) (
trap_type,
pbundle,
pipsr,
pfpsr,
pisr,
ppreds,
pifs,
fp_state
);
if (ret.retval == FP_EMUL_ERROR) {
HalpFpErrorPrint (ret);
}
return ((LONG) (ret.retval));
}