Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2510 lines
80 KiB

/*++
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 ([email protected])
Environment:
Kernel mode
Revision History:
Neal Vu ([email protected]), 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;
extern ULONG HalpPlatformPropertiesEfiFlags;
BOOLEAN
HalpCompareEfiGuid (
IN EFI_GUID CheckGuid,
IN EFI_GUID ReferenceGuid
);
BOOLEAN
MmSetPageProtection(
IN PVOID VirtualAddress,
IN SIZE_T NumberOfBytes,
IN ULONG NewProtect
);
EFI_STATUS
HalpCallEfiPhysicalEx(
IN ULONGLONG Arg1,
IN ULONGLONG Arg2,
IN ULONGLONG Arg3,
IN ULONGLONG Arg4,
IN ULONGLONG Arg5,
IN ULONGLONG Arg6,
IN ULONGLONG EP,
IN ULONGLONG GP,
IN ULONGLONG StackPointer,
IN ULONGLONG BackingStorePointer
);
typedef
EFI_STATUS
(*HALP_EFI_CALL)(
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
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 HalpVirtPalProcPointer;
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 0x100000
#define FP_EMUL_ERROR -1
SST_MEMORY_LIST PalCode;
NTSTATUS EfiInitStatus = STATUS_UNSUCCESSFUL;
ULONGLONG PalTrMask;
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 EfiMemoryMapSize,EfiDescriptorSize,EfiMapEntries;
ULONG EfiDescriptorVersion;
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;
UCHAR HalpSetVirtualAddressMapCount;
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()
BOOLEAN
HalpAllocateProcessorPhysicalCallStacks(
VOID
)
/*++
Routine Description:
This function allocates per-processor memory and backstore stacks
used by FW calls in physical mode.
Arguments:
None.
Return Value:
TRUE : Allocation and Initialization were successful.
FALSE : Failure.
--*/
{
PVOID Addr;
SIZE_T Length;
PHYSICAL_ADDRESS PhysicalAddr;
//
// Allocate stack and backing store space for physical mode firmware
// calls.
//
Length = HALP_FW_MEMORY_STACK_SIZE + HALP_FW_BACKING_STORE_SIZE;
PhysicalAddr.QuadPart = 0xffffffffffffffffI64;
Addr = MmAllocateContiguousMemory(Length, PhysicalAddr);
if (Addr == NULL) {
HalDebugPrint((HAL_ERROR, "SAL_PAL: can't allocate stack space for "
"physical mode firmware calls.\n"));
return FALSE;
}
//
// Store a pointer to the allocated stacks in the PCR.
//
PCR->HalReserved[PROCESSOR_PHYSICAL_FW_STACK_INDEX]
= (ULONGLONG) (MmGetPhysicalAddress(Addr).QuadPart);
return TRUE;
} // HalpAllocateProcessorPhysicalCallStacks()
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 HalpIsLion() \
( !strncmp( HalpFixedAcpiDescTable.Header.OEMTableID, "SR460AC", 7 ) )
#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;
}
} 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;
}
//
// If the PAL revision isn't greater than 6.23, don't allow
// SAL_GET_STATE_INFO_CALLS
//
if ( HalpIsLion() ) {
if ( ( HalpSalPalData.PalVersion.PAL_B_Model <= 0x66 ) &&
( HalpSalPalData.PalVersion.PAL_B_Revision <= 0x23 ) ) {
HalpSalPalData.Flags |= HALP_SALPAL_CMC_BROKEN | HALP_SALPAL_CPE_BROKEN;
}
}
}
}
} // HalpInitSalPalWorkArounds()
NTSTATUS
HalpInitializePalTrInfo(
PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This function builds an entry for the PAL in the LoaderBlock's
DtrInfo and ItrInfo arrays. This is split out into its own function
so we can call it early and build the TR_INFO structure before
phase 0 Mm initialization where it is used to build page tables
for the PAL data.
Arguments:
LoaderBlock - Supplies a pointer to the loader parameter block which
contains the DtrInfo and ItrInfo arrays.
Return Value:
STATUS_SUCCESS is returned in all cases, no sanity checks are done
at this point.
--*/
{
PTR_INFO TrInfo;
ULONG PalPageShift;
ULONGLONG PalTrSize;
ULONGLONG PalEnd;
//
// Zero out our data structures.
//
RtlZeroMemory(&HalpSalPalData, sizeof(HalpSalPalData));
RtlZeroMemory(&PalCode, sizeof(SST_MEMORY_LIST));
//
// Describe the position of the PAL code for the rest of the
// HAL.
//
PalCode.PhysicalAddress =
(ULONGLONG) LoaderBlock->u.Ia64.Pal.PhysicalAddressMemoryDescriptor;
PalCode.Length =
LoaderBlock->u.Ia64.Pal.PageSizeMemoryDescriptor << EFI_PAGE_SHIFT;
PalCode.NeedVaReg = TRUE;
PalCode.VirtualAddress = (ULONGLONG) NULL;
//
// Compute the dimensions of the PAL TR. This will be the smallest
// block that is naturally aligned on an even power of 2 bytes.
//
PalTrSize = SIZE_IN_BYTES_16KB;
PalTrMask = MASK_16KB;
PalPageShift = 14;
PalEnd = PalCode.PhysicalAddress + PalCode.Length;
//
// We don't support PAL TRs larger than 16MB, so stop looping if
// we get to that point.
//
while (PalTrMask >= MASK_16MB) {
//
// Stop looping if the entire PAL fits within the current
// TR boundaries.
//
if (PalEnd <= ((PalCode.PhysicalAddress & PalTrMask) + PalTrSize)) {
break;
}
//
// Bump the TR dimensions one level larger.
//
PalTrMask <<= 2;
PalTrSize <<= 2;
PalPageShift += 2;
}
//
// Store a few values for later consumption elsewhere in the HAL.
//
HalpSalPalData.PalTrSize = PalTrSize;
HalpSalPalData.PalTrBase = PalCode.PhysicalAddress & PalTrMask;
//
// Fill in the ItrInfo entry for the PAL.
//
TrInfo = &LoaderBlock->u.Ia64.ItrInfo[ITR_PAL_INDEX];
RtlZeroMemory(TrInfo, sizeof(*TrInfo));
TrInfo->Index = ITR_PAL_INDEX;
TrInfo->PageSize = PalPageShift;
TrInfo->VirtualAddress = HAL_PAL_VIRTUAL_ADDRESS;
TrInfo->PhysicalAddress = PalCode.PhysicalAddress;
//
// Fill in the DtrInfo entry for the PAL.
//
TrInfo = &LoaderBlock->u.Ia64.DtrInfo[DTR_PAL_INDEX];
RtlZeroMemory(TrInfo, sizeof(*TrInfo));
TrInfo->Index = DTR_PAL_INDEX;
TrInfo->PageSize = PalPageShift;
TrInfo->VirtualAddress = HAL_PAL_VIRTUAL_ADDRESS;
TrInfo->PhysicalAddress = PalCode.PhysicalAddress;
return STATUS_SUCCESS;
}
NTSTATUS
HalpDoInitializationForPalCalls(
PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This function virtually maps the PAL code area.
PAL requires a TR mapping, and is mapped using an architected TR, using the
smallest page size to map the entire PAL code region.
Arguments:
LoaderBlock - Supplies a pointer to the Loader parameter block, containing the
physical address of the PAL code.
Return Value:
STATUS_SUCCESS is returned if the mapping was successful, and 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.
--*/
{
ULONGLONG PalPteUlong;
HalpSalPalData.Status = STATUS_SUCCESS;
//
// 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);
//
// Get the wakeup vector. This is passed in the loader block
// it is retrieved in the loader by reading the sal system table.
//
HalpOsBootRendezVector = LoaderBlock->u.Ia64.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;
}
//
// If PAL requires a page size of larger than 16MB, fail.
//
if (PalTrMask < MASK_16MB) {
HalDebugPrint(( HAL_ERROR, "SAL_PAL: More than 16MB was required to map PAL" ));
HalpSalPalData.Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
HalDebugPrint(( HAL_INFO,
"SAL_PAL: For the PAL code located at phys 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 & ~PalTrMask);
ASSERT( PalCode.VirtualAddress == LoaderBlock->u.Ia64.Pal.VirtualAddress);
//
// Setup the ITR to map PAL
//
PalPteUlong = HalpSalPalData.PalTrBase | VALID_KERNEL_EXECUTE_PTE;
KeFillFixedEntryTb((PHARDWARE_PTE)&PalPteUlong,
(PVOID)HAL_PAL_VIRTUAL_ADDRESS,
LoaderBlock->u.Ia64.ItrInfo[ITR_PAL_INDEX].PageSize,
INST_TB_PAL_INDEX);
LoaderBlock->u.Ia64.ItrInfo[ITR_PAL_INDEX].Valid = TRUE;
HalpSalPalData.Status = STATUS_SUCCESS;
HalpVirtPalProcPointer = PalCode.VirtualAddress +
(LoaderBlock->u.Ia64.Pal.PhysicalAddress - PalCode.PhysicalAddress);
return(STATUS_SUCCESS);
}
NTSTATUS
HalpInitSalPal(
PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This function virtually maps the SAL code and SAL data areas. If SAL data
or SAL code areas can be mapped in the same page as the PAL TR, it uses the
same translation. Otherwise, it uses MmMapIoSpace.
Arguments:
LoaderBlock - Supplies a pointer to the Loader parameter block.
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.
Assumptions: The EfiSysTableVirtualPtr is initialized prior by EfiInitialization.
--*/
{
//
// Local declarations
//
ULONG index,i,SstLength;
SAL_PAL_RETURN_VALUES RetVals;
PHYSICAL_ADDRESS physicalAddr;
SAL_STATUS SALstatus;
BOOLEAN MmMappedSalCode, MmMappedSalData;
ULONGLONG physicalSAL, physicalSALGP;
ULONGLONG PhysicalConfigPtr;
ULONGLONG SalOffset;
//SST_MEMORY_LIST SalCode,SalData;
PAL_VERSION_STRUCT minimumPalVersion;
ULONGLONG palStatus;
HalDebugPrint(( HAL_INFO, "SAL_PAL: Entering HalpInitSalPal\n" ));
//
// initialize the system for making PAL calls
//
HalpDoInitializationForPalCalls(LoaderBlock);
//
// 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 = %I64d\n", palStatus ));
}
//
// 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;
} // 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 (*(USHORT UNALIGNED *)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;
}
BOOLEAN
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 FALSE;
}
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);
//
// Allocate the stacks needed to allow physical mode firmware calls
// on this processor.
//
return HalpAllocateProcessorPhysicalCallStacks();
} // HalpInitSalPalNonBsp()
VOID
PrintEfiMemoryDescriptor(
IN EFI_MEMORY_DESCRIPTOR * descriptor
)
{
char * typeStr = "<unknown>";
switch (descriptor->Type) {
case EfiReservedMemoryType: typeStr = "EfiReservedMemoryType"; break;
case EfiLoaderCode: typeStr = "EfiLoaderCode"; break;
case EfiLoaderData: typeStr = "EfiLoaderData"; break;
case EfiBootServicesCode: typeStr = "EfiBootServicesCode"; break;
case EfiBootServicesData: typeStr = "EfiBootServicesData"; break;
case EfiRuntimeServicesCode: typeStr = "EfiRuntimeServicesCode"; break;
case EfiRuntimeServicesData: typeStr = "EfiRuntimeServicesData"; break;
case EfiConventionalMemory: typeStr = "EfiConventionalMemory"; break;
case EfiUnusableMemory: typeStr = "EfiUnusableMemory"; break;
case EfiACPIReclaimMemory: typeStr = "EfiACPIReclaimMemory"; break;
case EfiACPIMemoryNVS: typeStr = "EfiACPIMemoryNVS"; break;
case EfiMemoryMappedIO: typeStr = "EfiMemoryMappedIO"; break;
case EfiMemoryMappedIOPortSpace: typeStr = "EfiMemoryMappedIOPortSpace"; break;
case EfiPalCode: typeStr = "EfiPalCode"; break;
case EfiMaxMemoryType: typeStr = "EfiMaxMemoryType"; break;
}
DbgPrint(" Type=%s(0x%x)\n PhysicalStart=0x%I64x\n VirtualStart=0x%I64x\n NumberOfPages=0x%I64x\n Attribute=0x%I64x\n",
typeStr,
descriptor->Type,
descriptor->PhysicalStart,
descriptor->VirtualStart,
descriptor->NumberOfPages,
descriptor->Attribute);
}
VOID
PrintEfiMemoryMap(
IN EFI_MEMORY_DESCRIPTOR * memoryMapPtr,
IN ULONGLONG numMapEntries
)
{
ULONGLONG index;
DbgPrint("Printing 0x%x EFI memory descriptors\n", numMapEntries);
for (index = 0; index < numMapEntries; ++index) {
PrintEfiMemoryDescriptor(memoryMapPtr);
DbgPrint("\n");
memoryMapPtr = NextMemoryDescriptor(memoryMapPtr, EfiDescriptorSize);
}
}
BOOLEAN
HalpDescriptorContainsAddress(
EFI_MEMORY_DESCRIPTOR *EfiMd,
ULONGLONG PhysicalAddress
)
{
ULONGLONG MdPhysicalStart, MdPhysicalEnd;
MdPhysicalStart = (ULONGLONG)EfiMd->PhysicalStart;
MdPhysicalEnd = MdPhysicalStart + (ULONGLONG)(EfiMd->NumberOfPages << EFI_PAGE_SHIFT);
if ((PhysicalAddress >= MdPhysicalStart) &&
(PhysicalAddress < MdPhysicalEnd)) {
return(TRUE);
}
return(FALSE);
}
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;
SST_MEMORY_LIST SalCode, SalData, SalDataGPOffset;
ULONGLONG SalOffset = 0, SalDataOffset = 0;
MEMORY_CACHING_TYPE cacheType;
RtlZeroMemory(&SalCode, sizeof(SST_MEMORY_LIST));
RtlZeroMemory(&SalData, sizeof(SST_MEMORY_LIST));
RtlZeroMemory(&SalDataGPOffset, sizeof(SST_MEMORY_LIST));
//
// get the sal code, and data filled in with data from the loader block.
//
SalCode.PhysicalAddress = LoaderBlock->u.Ia64.Sal.PhysicalAddress;
SalData.PhysicalAddress = LoaderBlock->u.Ia64.SalGP.PhysicalAddress;
SalDataGPOffset.PhysicalAddress = SalData.PhysicalAddress - (2 * 0x100000);
//
// 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 ));
//
// The round to pages should not be needed below, but this change was made late so I made it
// page aligned size since the old one was just page size.
//
HalpVirtualCommonDataPointer = (PUCHAR)(ExAllocatePool (NonPagedPool, ROUND_TO_PAGES( EfiMemoryMapSize + MemoryMapOffset)));
if (HalpVirtualCommonDataPointer == NULL) {
HalDebugPrint(( HAL_ERROR, "HAL: Common data allocation failed\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
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: Sal: 0x%I64x (offset 0x%I64x) SalGP: 0x%I64x (offset 0x%I64x) SalDataGPOffset: 0x%I64x\n",
SalCode.PhysicalAddress,
SalOffset,
SalData.PhysicalAddress,
SalDataOffset,
SalDataGPOffset.PhysicalAddress
));
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;
ULONGLONG physicalStart = efiMapEntryPtr->PhysicalStart;
ULONGLONG physicalEnd = physicalStart + (efiMapEntryPtr->NumberOfPages << EFI_PAGE_SHIFT);
physicalAddr.QuadPart = efiMapEntryPtr -> PhysicalStart;
//
// To handle video bios mapping issues, HALIA64 maps every EFI MD
// regardless of the EFI_MEMORY_RUNTIME flag.
//
// Implementation Note: ia64ldr ignored 1rst MB range and did not pass
// this memory to MM. MM considers this range as
// IO space.
//
if ( (efiMapEntryPtr->NumberOfPages > 0) && (physicalStart < OptionROMAddress) ) {
ULONGLONG numberOfPages = efiMapEntryPtr->NumberOfPages;
cacheType = (efiMapEntryPtr->Attribute & EFI_MEMORY_UC) ? MmNonCached : MmCached;
efiMapEntryPtr->VirtualStart = (ULONGLONG) (MmMapIoSpace (physicalAddr,
(EFI_PAGE_SIZE) * numberOfPages,
cacheType
));
if ((efiMapEntryPtr->VirtualStart) == 0) {
HalDebugPrint(( HAL_ERROR,
"HAL: Efi Video Bios area PA 0x%I64x, VAddr is NULL\n", physicalStart
));
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));
//
// Initialize known HAL video bios pointers. These pointer must be zero based
//
if (physicalStart == 0x00000) {
HalpLowMemoryBase = (PVOID) efiMapEntryPtr->VirtualStart;
}
if ( physicalStart <= 0xA0000 && physicalEnd > 0xA0000) {
HalpFrameBufferBase = (PVOID)(efiMapEntryPtr->VirtualStart - physicalStart);
}
if ( physicalStart <= 0xC0000 && physicalEnd > 0xC0000 ) {
HalpIoMemoryBase = (PVOID)(efiMapEntryPtr->VirtualStart - physicalStart);
}
}
else if ((efiMapEntryPtr->Attribute) & EFI_MEMORY_RUNTIME)
{
attribute = 1;
switch (efiMapEntryPtr->Type) {
case EfiRuntimeServicesData:
case EfiReservedMemoryType:
case EfiACPIMemoryNVS:
if(efiMapEntryPtr->Type == EfiACPIMemoryNVS) {
//
// note: we allow ACPI NVS to be mapped per the
// firmware's specification instead of forcing it to
// be non-cached. We are relying on the first mapping
// of this range to have the "correct" caching flag, as
// that is the cachability attribute that all
// subsequent mappings of this range (ie., mapping of
// additional data in the same page from ACPI driver
// for a memory operation region, etc.). This semantic
// is enforced by the memory manager.
//
efiMapEntryPtr->VirtualStart = (ULONGLONG) (MmMapIoSpace (physicalAddr,
(SIZE_T)((EFI_PAGE_SIZE)*(efiMapEntryPtr->NumberOfPages)),
(efiMapEntryPtr->Attribute & EFI_MEMORY_UC) ? MmNonCached : MmCached
));
} else {
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/ACPIMemoryNVS 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 ));
if (efiMapEntryPtr->Type == EfiRuntimeServicesData) {
if (HalpDescriptorContainsAddress(efiMapEntryPtr,SalData.PhysicalAddress)) {
//
// save off salgp virtual address
//
SalData.VirtualAddress = efiMapEntryPtr->VirtualStart;
SalDataOffset = SalData.PhysicalAddress - efiMapEntryPtr->PhysicalStart;
HalDebugPrint(( HAL_INFO,
"HAL: prior descriptor contains SalData.PhysicalAddress 0x%I64x\n",
SalData.PhysicalAddress ));
}
if (HalpDescriptorContainsAddress(efiMapEntryPtr,SalDataGPOffset.PhysicalAddress)) {
//
// save off salgp virtual address
//
SalDataGPOffset.VirtualAddress = efiMapEntryPtr->VirtualStart;
//
// Don't overwrite an existing SalDataOffset
// (generated using SalData.PhysicalAddress) since
// SalDataGPOffset is only needed when
// SalData.PhysicalAddress lies outside of the EFI
// memory map.
//
if (SalDataOffset == 0) {
SalDataOffset = SalDataGPOffset.PhysicalAddress - efiMapEntryPtr->PhysicalStart;
}
HalDebugPrint(( HAL_INFO,
"HAL: prior descriptor contains SalDataGPOffset.PhysicalAddress 0x%I64x\n",
SalData.PhysicalAddress ));
}
}
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:
//
// Skip over Option rom addresses. They are not really needed by the EFI runtime
// and most users want it mapped non-cached.
//
cacheType = (efiMapEntryPtr->Attribute & EFI_MEMORY_WB) ? MmCached : MmNonCached;
efiMapEntryPtr->VirtualStart = (ULONGLONG) (MmMapIoSpace (physicalAddr,
(EFI_PAGE_SIZE) * (efiMapEntryPtr->NumberOfPages),
cacheType
));
if ((efiMapEntryPtr->VirtualStart) == 0) {
HalDebugPrint(( HAL_ERROR, "HAL: Efi RunTimeSrvceCode 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));
if (HalpDescriptorContainsAddress(efiMapEntryPtr,SalData.PhysicalAddress)) {
//
// save off salgp virtual address
//
SalData.VirtualAddress = efiMapEntryPtr->VirtualStart;
SalDataOffset = SalData.PhysicalAddress - efiMapEntryPtr->PhysicalStart;
}
if (HalpDescriptorContainsAddress(efiMapEntryPtr,SalDataGPOffset.PhysicalAddress)) {
//
// save off salgp virtual address
//
SalDataGPOffset.VirtualAddress = efiMapEntryPtr->VirtualStart;
//
// Don't overwrite an existing SalDataOffset
// (generated using SalData.PhysicalAddress) since
// SalDataGPOffset is only needed when
// SalData.PhysicalAddress lies outside of the EFI
// memory map.
//
if (SalDataOffset == 0) {
SalDataOffset = SalDataGPOffset.PhysicalAddress - efiMapEntryPtr->PhysicalStart;
}
HalDebugPrint(( HAL_INFO,
"HAL: prior descriptor contains SalDataGPOffset.PhysicalAddress 0x%I64x\n",
SalData.PhysicalAddress ));
}
if (HalpDescriptorContainsAddress(efiMapEntryPtr,SalCode.PhysicalAddress)) {
//
// save off sal code virtual address
//
SalCode.VirtualAddress = efiMapEntryPtr->VirtualStart;
SalOffset = SalCode.PhysicalAddress - 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;
case EfiACPIReclaimMemory:
//
// note: we allow ACPI reclaim memory to be mapped per the
// firmware's specification instead of forcing it to
// be non-cached. We are relying on the first mapping
// of this range to have the "correct" caching flag, as
// that is the cachability attribute that all
// subsequent mappings of this range (ie., mapping of
// additional data in the same page from ACPI driver
// for a memory operation region, etc.). This semantic
// is enforced by the memory manager.
//
efiMapEntryPtr->VirtualStart = (ULONGLONG) (MmMapIoSpace(
physicalAddr,
(SIZE_T)((EFI_PAGE_SIZE)*(efiMapEntryPtr->NumberOfPages)),
(efiMapEntryPtr->Attribute & EFI_MEMORY_UC) ? MmNonCached : MmCached));
if ((efiMapEntryPtr->VirtualStart) == 0) {
HalDebugPrint(( HAL_ERROR, "HAL: Efi ACPI Reclaim 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;
default:
HalDebugPrint(( HAL_INFO, "HAL: Efi CONTROL SHOULD NOT COME HERE\n" ));
HalDebugPrint(( HAL_INFO,
"HAL: NON-SUPPORTED Efi attribute %d & Type 0x%I64x with # of 4K pages 0x%I64x at PA 0x%I64x\n",
attribute,
efiMapEntryPtr->Type,
efiMapEntryPtr->NumberOfPages,
efiMapEntryPtr->PhysicalStart ));
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" ));
//
// setup sal global pointers.
//
if (!SalCode.VirtualAddress) {
HalDebugPrint(( HAL_FATAL_ERROR, "HAL: no virtual address for sal code\n" ));
EfiInitStatus = STATUS_UNSUCCESSFUL;
return (EfiInitStatus);
}
//
// The SAL GP is supposed to point somewhere within the SAL's short data
// segment (.sdata), meaning that we should be able to use it to find
// the SAL data area. Unfortunately most SALs are built using linkers
// that locate GP well outside of .sdata. As a consequence the SAL GP
// lies off of the memory map (not covered by any memory descriptor) on
// some systems. In this case we have no way of finding the descriptor
// that contains the SAL data while needing to relocate the SAL GP based
// upon the virtual address of this unknown descriptor (the data and GP
// need to remain fixed in relationship to one another). We try to detect
// and work around this problem here.
//
if (!SalData.VirtualAddress) {
//
// If we get here we'll need to do some tricks in order to
// generate a virtual address for the SAL data area (basically
// the SAL GP).
//
HalDebugPrint(( HAL_INFO,
"HAL: no virtual address for SalGP found, checking SalDataGPOffset 0x%I64x\n",
SalDataGPOffset.VirtualAddress ));
//
// Check if we found an EFI descriptor 2MB below the physical SAL GP
// address. If we did, add 2MB back to the newly constructed virtual
// address of that descriptor and call it the GP. This method will
// occasionally work because the current linkers typically put the
// GP 2MB outside of .sdata.
//
if (SalDataGPOffset.VirtualAddress) {
HalDebugPrint(( HAL_INFO, "HAL: using SalDataGPOffset.VirtualAddress\n" ));
SalData.VirtualAddress = SalDataGPOffset.VirtualAddress + (2 * 0x100000);
} else {
//
// As a last resort assume that the physical SAL GP address
// is relative to the SAL code memory descriptor. This will
// work as long as SAL code and data share the same EFI memory
// descriptor (otherwise the SAL GP is relative to a SAL data
// memory descriptor that we weren't able to detect). Currently
// there isn't any way to detect the case where SAL data is in
// a different memory descriptor that doesn't contain the SAL GP.
//
HalDebugPrint(( HAL_FATAL_ERROR, "HAL: no virtual address for sal data. Some systems don't seem to care so we're faking this.\n" ));
//
// SalCode.PhysicalAddress is the address of SAL_PROC. Load
// up the virtual address of SAL_PROC and the distance the
// virtual SAL GP should lie away from this point.
//
SalData.VirtualAddress = SalCode.VirtualAddress + SalOffset;
SalDataOffset = SalData.PhysicalAddress - SalCode.PhysicalAddress;
}
}
HalpSalProcPointer = (ULONGLONG) (SalCode.VirtualAddress + SalOffset);
HalpSalProcGlobalPointer = (ULONGLONG) (SalData.VirtualAddress + SalDataOffset);
HalDebugPrint(( HAL_INFO,
"HAL: SalProc: 0x%I64x SalGP: 0x%I64x \n",
HalpSalProcPointer,
HalpSalProcGlobalPointer
));
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
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
)
/*++
Routine Description:
This function is a wrapper for making a physical mode EFI call. This
function's only job is to provide the stack and backing store pointers
needed by HalpCallEfiPhysicalEx.
Arguments:
Arg1 through Arg6 - The arguments to be passed to EFI.
EP - The entry point of the EFI runtime service we want to call.
GP - The global pointer associated with the entry point.
Return Value:
The EFI_STATUS value returned by HalpCallEfiPhysicalEx.
--*/
{
ULONGLONG StackPointer;
ULONGLONG BackingStorePointer;
ULONGLONG StackBase;
//
// Load the addresses of the stack and backing store reserved for
// physical mode EFI calls on this processor.
//
StackBase = PCR->HalReserved[PROCESSOR_PHYSICAL_FW_STACK_INDEX];
StackPointer = GET_FW_STACK_POINTER(StackBase);
BackingStorePointer = GET_FW_BACKING_STORE_POINTER(StackBase);
//
// Branch to the assembly routine that makes the actual EFI call.
//
return HalpCallEfiPhysicalEx(
Arg1,
Arg2,
Arg3,
Arg4,
Arg5,
Arg6,
EP,
GP,
StackPointer,
BackingStorePointer
);
}
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;
HALP_EFI_CALL EfiCall;
//
// Storage for old level
//
KIRQL OldLevel;
//
// Set EfiCall to the physical or virtual mode EFI call dispatcher
// depending upon whether we've made a successful call to SetVirtual
// AddressMap.
//
if (HalpSetVirtualAddressMapCount == 0) {
EfiCall = HalpCallEfiPhysical;
} else {
EfiCall = HalpCallEfiVirtual;
}
//
// Acquire MP Lock
//
KeAcquireSpinLock(&EFIMPLock, &OldLevel);
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;
efiStatus = (EfiCall( (ULONGLONG)Arg1, // VariableNamePtr
(ULONGLONG)Arg2, // VendorGuidPtr
(ULONGLONG)Arg3, // VariableAttributesPtr,
(ULONGLONG)Arg4, // DataSizePtr,
(ULONGLONG)Arg5, // DataPtr,
Arg6,
EP,
GP
));
break;
case EFI_SET_VARIABLE_INDEX:
//
// Dereference the pointer to get the function arguements
//
EP = ((PPLABEL_DESCRIPTOR)EfiVirtualSetVariablePtr) -> EntryPoint;
GP = ((PPLABEL_DESCRIPTOR)EfiVirtualSetVariablePtr) -> GlobalPointer;
efiStatus = (EfiCall( Arg1,
Arg2,
Arg3,
Arg4,
Arg5,
Arg6,
EP,
GP
));
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;
efiStatus = (EfiCall( Arg1,
Arg2,
Arg3,
Arg4,
Arg5,
Arg6,
EP,
GP
));
break;
case EFI_GET_TIME_INDEX:
//
// Dereference the pointer to get the function arguements
//
EP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetTimePtr) -> EntryPoint;
GP = ((PPLABEL_DESCRIPTOR)EfiVirtualGetTimePtr) -> GlobalPointer;
efiStatus = (EfiCall ((ULONGLONG)Arg1, //EFI_TIME
(ULONGLONG)Arg2, //EFI_TIME Capabilities
Arg3,
Arg4,
Arg5,
Arg6,
EP,
GP
));
break;
case EFI_SET_TIME_INDEX:
//
// Dereference the pointer to get the function arguements
//
EP = ((PPLABEL_DESCRIPTOR)EfiVirtualSetTimePtr) -> EntryPoint;
GP = ((PPLABEL_DESCRIPTOR)EfiVirtualSetTimePtr) -> GlobalPointer;
efiStatus = (EfiCall ((ULONGLONG)Arg1, //EFI_TIME
Arg2,
Arg3,
Arg4,
Arg5,
Arg6,
EP,
GP
));
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
);
efiStatus = (EfiCall ((ULONGLONG)EfiMemoryMapSize,
(ULONGLONG)EfiDescriptorSize,
(ULONGLONG)EfiDescriptorVersion,
(ULONGLONG)HalpMemoryMapPhysPtr,
Arg5,
Arg6,
EP,
GP
));
//
// If the call was successful make a note in HalpSetVirtualAddressMap
// Count that EFI is now running in virtual mode.
//
if (efiStatus == EFI_SUCCESS) {
HalpSetVirtualAddressMapCount++;
}
break;
case EFI_RESET_SYSTEM_INDEX:
//
// Dereference the pointer to get the function arguements
//
EP = ((PPLABEL_DESCRIPTOR)EfiResetSystemPtr) -> EntryPoint;
GP = ((PPLABEL_DESCRIPTOR)EfiResetSystemPtr) -> GlobalPointer;
efiStatus = ((EfiCall ( Arg1,
Arg2,
Arg3,
Arg4,
Arg5,
Arg6,
EP,
GP
)));
break;
default:
//
// DebugPrint("EFI: Not supported now\n");
//
efiStatus = EFI_UNSUPPORTED;
break;
}
//
// Release the MP Lock
//
KeReleaseSpinLock (&EFIMPLock, OldLevel);
return efiStatus;
} // HalpCallEfi()
HalpFpErrorPrint (PAL_RETURN pal_ret)
{
ULONGLONG err_nr;
unsigned int qp;
ULONGLONG OpCode;
unsigned int rc;
unsigned int significand_size;
unsigned int ISRlow;
unsigned int f1;
unsigned int sign;
unsigned int exponent;
ULONGLONG 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));
}