2375 lines
76 KiB
C
2375 lines
76 KiB
C
|
||
/*++
|
||
|
||
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));
|
||
}
|