windows-nt/Source/XPSP1/NT/base/boot/efi/sumain.c
2020-09-26 16:20:57 +08:00

1491 lines
48 KiB
C

/*++
Copyright (c) 1991 Microsoft Corporation
Copyright (c) 1998 Intel Corporation
Module Name:
sumain.c
Abstract:
SuMain() sets up NT specific data structures for OsLoader.c. This
is necessary since we don't have the ARC firmware to do the work
for us. SuMain() is call by SuSetup() which is an assembly level
routine that does IA64 specific setup.
Author:
Allen Kay (akay) 19-May-95
--*/
#include "bldr.h"
#include "sudata.h"
#include "sal.h"
#include "efi.h"
#include "efip.h"
#include "bootia64.h"
#include "smbios.h"
extern EFI_SYSTEM_TABLE *EfiST;
//
// External functions
//
extern VOID NtProcessStartup();
extern VOID SuFillExportTable();
extern VOID CpuSpecificWork();
extern EFI_STATUS
GetSystemConfigurationTable(
IN EFI_GUID *TableGuid,
IN OUT VOID **Table
);
//
// Define export entry table.
//
PVOID ExportEntryTable[ExMaximumRoutine];
// M E M O R Y D E S C R I P T O R
//
// Memory Descriptor - each contiguous block of physical memory is
// described by a Memory Descriptor. The descriptors are a table, with
// the last entry having a BlockBase and BlockSize of zero. A pointer
// to the beginning of this table is passed as part of the BootContext
// Record to the OS Loader.
//
BOOT_CONTEXT BootContext;
//
// Global EFI data
//
#define EFI_ARRAY_SIZE 100
#define EFI_PAGE_SIZE 4096
#define EFI_PAGE_SHIFT 12
#define MEM_4K 0x1000
#define MEM_8K 0x2000
#define MEM_16K 0x4000
#define MEM_64K 0x10000
#define MEM_256K 0x40000
#define MEM_1M 0x100000
#define MEM_4M 0x400000
#define MEM_16M 0x1000000
#define MEM_64M 0x4000000
#define MEM_256M 0x10000000
EFI_HANDLE EfiImageHandle;
EFI_SYSTEM_TABLE *EfiST;
EFI_BOOT_SERVICES *EfiBS;
EFI_RUNTIME_SERVICES *EfiRS;
PSST_HEADER SalSystemTable;
PVOID AcpiTable;
PVOID SMBiosTable;
//
// contains the memory map key so we can compare the consistency of the memory map
// at loader entry time to loader exit time.
//
ULONGLONG MemoryMapKey;
//
// EFI GUID defines
//
EFI_GUID EfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
EFI_GUID EfiDevicePathProtocol = DEVICE_PATH_PROTOCOL;
EFI_GUID EfiDeviceIoProtocol = DEVICE_IO_PROTOCOL;
EFI_GUID EfiBlockIoProtocol = BLOCK_IO_PROTOCOL;
EFI_GUID EfiDiskIoProtocol = DISK_IO_PROTOCOL;
EFI_GUID EfiFilesystemProtocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
EFI_GUID AcpiTable_Guid = ACPI_TABLE_GUID;
EFI_GUID SmbiosTableGuid = SMBIOS_TABLE_GUID;
EFI_GUID SalSystemTableGuid = SAL_SYSTEM_TABLE_GUID;
//
// PAL, SAL, and IO port space data
//
ULONGLONG PalProcVirtual;
ULONGLONG PalProcPhysical;
ULONGLONG PalPhysicalBase = 0;
ULONGLONG PalTrPs;
ULONGLONG IoPortPhysicalBase;
ULONGLONG IoPortTrPs;
//
// Function Prototypes
//
VOID
GetPalProcEntryPoint(
IN PSST_HEADER SalSystemTable
);
ULONG
GetDevPathSize(
IN EFI_DEVICE_PATH *DevPath
);
VOID
ConstructMemoryDescriptors(
VOID
);
MEMORY_TYPE
EfiToArcType (
UINT32 Type
);
VOID
AdjustMemoryDescriptorSizes(
VOID
);
#if DBG
#define DBG_TRACE(_X) EfiST->ConOut->OutputString(EfiST->ConOut, (_X))
#else
#define DBG_TRACE(_X)
#endif
#ifdef FORCE_CD_BOOT
EFI_HANDLE
GetCd(
);
EFI_HANDLE
GetCdTest(
VOID
);
#endif // for FORCE_CD_BOOT
VOID
SuMain(
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Main entrypoint of the SU module. Control is passed from the boot
sector to startup.asm which does some run-time fixups on the stack
and data segments and then passes control here.
Arguments:
None
Returns:
Does not return. Passes control to the OS loader
--*/
{
PIMAGE_DOS_HEADER DosHeader;
PIMAGE_NT_HEADERS NtHeader;
PIMAGE_FILE_HEADER FileHeader;
PIMAGE_OPTIONAL_HEADER OptionalHeader;
PIMAGE_SECTION_HEADER SectionHeader;
ULONG NumberOfSections;
BOOLEAN ResourceFound = FALSE;
ULONGLONG Source,Destination;
ULONGLONG VirtualSize;
ULONGLONG SizeOfRawData;
USHORT Section;
EFI_GUID EfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
EFI_HANDLE EfiHandleArray[EFI_ARRAY_SIZE];
ULONG EfiHandleArraySize = EFI_ARRAY_SIZE * sizeof(EFI_HANDLE);
EFI_DEVICE_PATH *EfiDevicePath;
EFI_LOADED_IMAGE *EfiImageInfo;
EFI_HANDLE DeviceHandle;
EFI_STATUS Status;
EFI_DEVICE_PATH *DevicePath, *TestPath;
EFI_DEVICE_PATH_ALIGNED TestPathAligned;
HARDDRIVE_DEVICE_PATH *HdDevicePath;
ACPI_HID_DEVICE_PATH *AcpiDevicePath;
ATAPI_DEVICE_PATH *AtapiDevicePath;
SCSI_DEVICE_PATH *ScsiDevicePath;
IPv4_DEVICE_PATH *IpV4DevicePath;
IPv6_DEVICE_PATH *IpV6DevicePath;
UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *UnknownDevicePath;
UCHAR MemoryMap[EFI_PAGE_SIZE];
ULONGLONG MemoryMapSize = EFI_PAGE_SIZE;
EFI_MEMORY_DESCRIPTOR *EfiMd;
ULONGLONG DescriptorSize;
ULONG DescriptorVersion;
ULONG i;
ULONGLONG PalSize;
ULONGLONG PalEnd;
ULONGLONG IoPortSize;
ULONGLONG MdPhysicalEnd;
PBOOT_DEVICE_ATAPI BootDeviceAtapi;
PBOOT_DEVICE_SCSI BootDeviceScsi;
PBOOT_DEVICE_FLOPPY BootDeviceFloppy;
PBOOT_DEVICE_IPv4 BootDeviceIpV4;
PBOOT_DEVICE_IPv6 BootDeviceIpV6;
PBOOT_DEVICE_UNKNOWN BootDeviceUnknown;
PSMBIOS_EPS_HEADER SMBiosEPSHeader;
PUCHAR SMBiosEPSPtr;
UCHAR CheckSum;
//
// EFI global variables
//
EfiImageHandle = ImageHandle;
EfiST = SystemTable;
EfiBS = SystemTable->BootServices;
EfiRS = SystemTable->RuntimeServices;
DBG_TRACE(L"SuMain: entry\r\n");
//
// Get the SAL System Table
//
Status = GetSystemConfigurationTable(&SalSystemTableGuid, &SalSystemTable);
if (EFI_ERROR(Status)) {
EfiST->ConOut->OutputString(EfiST->ConOut,
L"SuMain: HandleProtocol failed\n");
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
}
#if 0
//
// Get the MPS Table
//
Status = GetSystemConfigurationTable(&MpsTableGuid, &MpsTable);
if (EFI_ERROR(Status)) {
EfiST->ConOut->OutputString(EfiST->ConOut,
L"SuMain: HandleProtocol failed\n");
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
}
#endif
//
// Get the ACPI Tables
//
//
// Get the ACPI 2.0 Table, if present
//
//DbgPrint("Looking for ACPi 2.0\n");
Status = GetSystemConfigurationTable(&AcpiTable_Guid, &AcpiTable);
if (EFI_ERROR(Status)) {
//DbgPrint("returned error\n");
AcpiTable = NULL;
}
//DbgPrint("AcpiTable: %p\n", AcpiTable);
if (!AcpiTable) {
EfiST->ConOut->OutputString(EfiST->ConOut,
L"SuMain: HandleProtocol failed\n");
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
}
//
// Get the SMBIOS Table
//
Status = GetSystemConfigurationTable(&SmbiosTableGuid, &SMBiosTable);
if (EFI_ERROR(Status)) {
//DbgPrint("returned error\n");
SMBiosTable = NULL;
} else {
//
// Validate SMBIOS EPS Header
//
SMBiosEPSHeader = (PSMBIOS_EPS_HEADER)SMBiosTable;
SMBiosEPSPtr = (PUCHAR)SMBiosTable;
if ((*((PULONG)SMBiosEPSHeader->Signature) == SMBIOS_EPS_SIGNATURE) &&
(SMBiosEPSHeader->Length >= sizeof(SMBIOS_EPS_HEADER)) &&
(*((PULONG)SMBiosEPSHeader->Signature2) == DMI_EPS_SIGNATURE) &&
(SMBiosEPSHeader->Signature2[4] == '_' ))
{
CheckSum = 0;
for (i = 0; i < SMBiosEPSHeader->Length ; i++)
{
CheckSum += SMBiosEPSPtr[i];
}
if (CheckSum != 0)
{
DBG_TRACE(L"SMBios Table has bad checksum.....\n");
SMBiosTable = NULL;
} else {
DBG_TRACE(L"SMBios Table has been validated.....\n");
}
} else {
DBG_TRACE(L"SMBios Table is incorrectly formed.....\n");
SMBiosTable = NULL;
}
}
//
// Get the image info for NTLDR
//
Status = EfiBS->HandleProtocol (
ImageHandle,
&EfiLoadedImageProtocol,
&EfiImageInfo
);
if (EFI_ERROR(Status)) {
EfiST->ConOut->OutputString(EfiST->ConOut,
L"SuMain: HandleProtocol failed\n");
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
}
//
// Get device path of the DeviceHandle associated with this image handle.
//
Status = EfiBS->HandleProtocol (
EfiImageInfo->DeviceHandle,
&EfiDevicePathProtocol,
&DevicePath
);
if (EFI_ERROR(Status)) {
EfiST->ConOut->OutputString(EfiST->ConOut,
L"SuMain: HandleProtocol failed\r\n");
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
}
//
// Get the MediaType and Partition information and save them in the
// BootContext.
//
EfiAlignDp( &TestPathAligned,
DevicePath,
DevicePathNodeLength(DevicePath) );
TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
while (TestPath->Type != END_DEVICE_PATH_TYPE) {
if (TestPath->Type == MESSAGING_DEVICE_PATH) {
if (TestPath->SubType == MSG_ATAPI_DP) {
AtapiDevicePath = (ATAPI_DEVICE_PATH *) TestPath;
BootContext.BusType = BootBusAtapi;
BootDeviceAtapi = (PBOOT_DEVICE_ATAPI) &(BootContext.BootDevice);
BootDeviceAtapi->PrimarySecondary = AtapiDevicePath->PrimarySecondary;
BootDeviceAtapi->SlaveMaster = AtapiDevicePath->SlaveMaster;
BootDeviceAtapi->Lun = AtapiDevicePath->Lun;
} else if (TestPath->SubType == MSG_SCSI_DP) {
ScsiDevicePath = (SCSI_DEVICE_PATH *) TestPath;
BootContext.BusType = BootBusScsi;
BootDeviceScsi = (PBOOT_DEVICE_SCSI) &(BootContext.BootDevice);
BootDeviceScsi->Pun = ScsiDevicePath->Pun;
BootDeviceScsi->Lun = ScsiDevicePath->Lun;
} else if (TestPath->SubType == MSG_MAC_ADDR_DP) {
BootContext.MediaType = BootMediaTcpip;
} else if (TestPath->SubType == MSG_IPv4_DP) {
IpV4DevicePath = (IPv4_DEVICE_PATH *) TestPath;
BootContext.MediaType = BootMediaTcpip;
BootDeviceIpV4 = (PBOOT_DEVICE_IPv4) &(BootContext.BootDevice);
BootDeviceIpV4->RemotePort = IpV4DevicePath->RemotePort;
BootDeviceIpV4->LocalPort = IpV4DevicePath->LocalPort;
RtlCopyMemory(&BootDeviceIpV4->Ip, &IpV4DevicePath->LocalIpAddress, sizeof(EFI_IPv4_ADDRESS));
} else if (TestPath->SubType == MSG_IPv6_DP) {
IpV6DevicePath = (IPv6_DEVICE_PATH *) TestPath;
BootContext.MediaType = BootMediaTcpip;
BootDeviceIpV6 = (PBOOT_DEVICE_IPv6) &(BootContext.BootDevice);
BootDeviceIpV6->RemotePort = IpV6DevicePath->RemotePort;
BootDeviceIpV6->LocalPort = IpV6DevicePath->LocalPort;
#if 0
BootDeviceIpV6->Ip = IpV6DevicePath->Ip;
#endif
}
} else if (TestPath->Type == ACPI_DEVICE_PATH) {
AcpiDevicePath = (ACPI_HID_DEVICE_PATH *) TestPath;
if (AcpiDevicePath->HID == EISA_ID(PNP_EISA_ID_CONST, 0x0303)) {
BootDeviceFloppy = (PBOOT_DEVICE_FLOPPY) &(BootContext.BootDevice);
BootDeviceFloppy->DriveNumber = AcpiDevicePath->UID;
}
} else if (TestPath->Type == HARDWARE_DEVICE_PATH) {
if (TestPath->SubType == HW_VENDOR_DP) {
UnknownDevicePath = (UNKNOWN_DEVICE_VENDOR_DEVICE_PATH *) TestPath;
BootDeviceUnknown = (PBOOT_DEVICE_UNKNOWN) &(BootContext.BootDevice);
RtlCopyMemory( &(BootDeviceUnknown->Guid),
&(UnknownDevicePath->DevicePath.Guid),
sizeof(EFI_GUID));
BootContext.BusType = BootBusVendor;
BootDeviceUnknown->LegacyDriveLetter = UnknownDevicePath->LegacyDriveLetter;
}
} else if (TestPath->Type == MEDIA_DEVICE_PATH) {
BootContext.MediaType = TestPath->SubType;
if (TestPath->SubType == MEDIA_HARDDRIVE_DP) {
HdDevicePath = (HARDDRIVE_DEVICE_PATH *) TestPath;
BootContext.MediaType = BootMediaHardDisk;
BootContext.PartitionNumber = (UCHAR) HdDevicePath->PartitionNumber;
} else if (TestPath->SubType == MEDIA_CDROM_DP) {
BootContext.MediaType = BootMediaCdrom;
}
}
DevicePath = NextDevicePathNode(DevicePath);
EfiAlignDp( &TestPathAligned,
DevicePath,
DevicePathNodeLength(DevicePath) );
TestPath = (EFI_DEVICE_PATH *) &TestPathAligned;
}
#ifdef FORCE_CD_BOOT
BootContext.MediaType = BootMediaCdrom;
#endif
//
// Fill out the rest of BootContext fields
//
DosHeader = EfiImageInfo->ImageBase;
NtHeader = (PIMAGE_NT_HEADERS) ((PUCHAR) DosHeader + DosHeader->e_lfanew);
FileHeader = &(NtHeader->FileHeader);
OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
((PUCHAR)FileHeader + sizeof(IMAGE_FILE_HEADER));
SectionHeader = (PIMAGE_SECTION_HEADER) ((PUCHAR)OptionalHeader +
FileHeader->SizeOfOptionalHeader);
BootContext.ExternalServicesTable = (PEXTERNAL_SERVICES_TABLE)
&ExportEntryTable;
BootContext.MachineType = MACHINE_TYPE_ISA;
BootContext.OsLoaderBase = (ULONG_PTR)EfiImageInfo->ImageBase;
BootContext.OsLoaderExports = (ULONG_PTR)EfiImageInfo->ImageBase +
OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
//
// Calculate the start address and the end address of OS loader.
//
BootContext.OsLoaderStart = (ULONG_PTR)EfiImageInfo->ImageBase +
SectionHeader->VirtualAddress;
BootContext.OsLoaderEnd = (ULONG_PTR)EfiImageInfo->ImageBase +
SectionHeader->SizeOfRawData;
for (Section=FileHeader->NumberOfSections ; Section-- ; SectionHeader++) {
Destination = (ULONG_PTR)EfiImageInfo->ImageBase + SectionHeader->VirtualAddress;
VirtualSize = SectionHeader->Misc.VirtualSize;
SizeOfRawData = SectionHeader->SizeOfRawData;
if (VirtualSize == 0) {
VirtualSize = SizeOfRawData;
}
if (Destination < BootContext.OsLoaderStart) {
BootContext.OsLoaderStart = Destination;
}
if (Destination+VirtualSize > BootContext.OsLoaderEnd) {
BootContext.OsLoaderEnd = Destination+VirtualSize;
}
}
//
// Find .rsrc section
//
SectionHeader = (PIMAGE_SECTION_HEADER) ((PUCHAR)OptionalHeader +
FileHeader->SizeOfOptionalHeader);
NumberOfSections = FileHeader->NumberOfSections;
while (NumberOfSections) {
if (_stricmp(SectionHeader->Name, ".rsrc")==0) {
BootContext.ResourceDirectory =
(ULONGLONG) ((ULONG_PTR)EfiImageInfo->ImageBase + SectionHeader->VirtualAddress);
BootContext.ResourceOffset = (ULONGLONG)((LONG)SectionHeader->VirtualAddress);
ResourceFound = TRUE;
}
++SectionHeader;
--NumberOfSections;
}
if (ResourceFound == FALSE) {
EfiST->ConOut->OutputString(EfiST->ConOut,
L"SuMain: Resource section not found\n");
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
}
DBG_TRACE( L"SuMain: About to call NtProcessStartup\r\n");
//
// See if someone called us w/ a TFTP restart block.
//
if( EfiImageInfo->LoadOptionsSize == (sizeof(TFTP_RESTART_BLOCK)) ) {
//
// Likely. Make sure it's really a TFTP restart block and if so, go retrieve all
// its contents.
//
if( EfiImageInfo->LoadOptions != NULL ) {
extern TFTP_RESTART_BLOCK gTFTPRestartBlock;
PTFTP_RESTART_BLOCK restartBlock = NULL;
restartBlock = (PTFTP_RESTART_BLOCK)(EfiImageInfo->LoadOptions);
RtlCopyMemory( &gTFTPRestartBlock,
restartBlock,
sizeof(TFTP_RESTART_BLOCK) );
DBG_TRACE( L"SuMain: copied TFTP_RESTART_BLOCK into gTFTPRestartBlock\r\n");
}
}
ConstructMemoryDescriptors( );
GetPalProcEntryPoint( SalSystemTable );
//
// Applies CPU specific workarounds
//
CpuSpecificWork();
SuFillExportTable( );
NtProcessStartup( &BootContext );
}
VOID
ConstructMemoryDescriptors(
VOID
)
/*++
Routine Description:
Builds up memory descriptors for the OS loader. This routine queries EFI
for it's memory map (a variable sized array of EFI_MEMORY_DESCRIPTOR's).
It then allocates sufficient space for the MDArray global (a variable sized
array of ARC-based MEMORY_DESCRIPTOR's.) The routine then maps the EFI
memory map to the ARC memory map, carving out all of the conventional
memory space for the EFI loader to help keep the memory map intact. We
must leave behind some amount of memory for the EFI boot services to use,
which we allocate as conventional memory in our map.
Arguments:
None
Returns:
Nothing. Fills in the MDArray global variable. If this routine encounters
an error, it is treated as fatal and the program exits.
--*/
{
EFI_STATUS Status;
ULONGLONG MemoryMapSize = 0;
EFI_MEMORY_DESCRIPTOR *EfiMd;
ULONGLONG DescriptorSize;
ULONG DescriptorVersion;
ULONG i;
ULONGLONG PalSize;
ULONGLONG PalEnd;
ULONGLONG IoPortSize;
ULONGLONG MdPhysicalStart;
ULONGLONG MdPhysicalEnd;
ULONGLONG MdPhysicalSize;
//
// Get memory map info from EFI firmware
//
// To do this, we first find out how much space we need by calling
// with an empty buffer.
//
EfiMd = NULL;
Status = EfiBS->GetMemoryMap (
&MemoryMapSize,
EfiMd,
&MemoryMapKey,
&DescriptorSize,
&DescriptorVersion
);
if (Status != EFI_BUFFER_TOO_SMALL) {
EfiST->ConOut->OutputString(EfiST->ConOut,
L"SuMain: GetMemoryMap failed\n");
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
}
//
// We are going to make three extra allocations before we call GetMemoryMap
// again, so add some extra space.
//
// 1. EfiMD
// 2. MDarray
// 3. Split out memory above and below 80MB (on ia64)
//
MemoryMapSize += 3*DescriptorSize;
i = (ULONG) MemoryMapSize;
//
// now allocate space for the EFI-based memory map and assign it to the loader
//
Status = EfiBS->AllocatePool(EfiLoaderData,i,&EfiMd);
if (EFI_ERROR(Status)) {
DBG_TRACE( L"SuMain: AllocatePool failed\n");
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
}
//
// now Allocate and zero the MDArray, which is the native loader memory
// map which we need to map the EFI memory map to.
//
// The MDArray has one entry for each EFI_MEMORY_DESCRIPTOR, and each entry
// is MEMORY_DESCRIPTOR large.
//
i=((ULONG)(MemoryMapSize / DescriptorSize)+1)*sizeof (MEMORY_DESCRIPTOR);
Status = EfiBS->AllocatePool(EfiLoaderData,i,&MDArray);
if (EFI_ERROR(Status)) {
DBG_TRACE (L"SuMain: AllocatePool failed\n");
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
}
//
// caution, this is 0 based!
//
MaxDescriptors = (ULONG)((MemoryMapSize / DescriptorSize)+1);
RtlZeroMemory (MDArray,i);
if ((EfiMd == NULL)) {
DBG_TRACE (L"SuMain: Failed to Allocate Memory for the descriptor lists\n");
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
}
//
// we have all of the memory allocated at this point, so retreive the
// memory map again, which should succeed the second time.
//
Status = EfiBS->GetMemoryMap (
&MemoryMapSize,
EfiMd,
&MemoryMapKey,
&DescriptorSize,
&DescriptorVersion
);
if (EFI_ERROR(Status)) {
DBG_TRACE(L"SuMain: GetMemoryMap failed\n");
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
}
//
// now walk the EFI_MEMORY_DESCRIPTOR array, mapping each
// entry to an arc-based MEMORY_DESCRIPTOR.
//
// MemoryMapSize contains actual size of the memory descriptor array.
//
for (i = 0; MemoryMapSize > 0; i++) {
#if DBG_MEMORY
wsprintf( DebugBuffer,
L"PageStart (%x), Size (%x), Type (%x)\r\n",
(EfiMd->PhysicalStart >> EFI_PAGE_SHIFT),
EfiMd->NumberOfPages,
EfiMd->Type);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
DBG_EFI_PAUSE();
#endif
if (EfiMd->NumberOfPages > 0) {
MdPhysicalStart = EfiMd->PhysicalStart;
MdPhysicalEnd = EfiMd->PhysicalStart + (EfiMd->NumberOfPages << EFI_PAGE_SHIFT);
MdPhysicalSize = MdPhysicalEnd - MdPhysicalStart;
#if DBG_MEMORY
wsprintf( DebugBuffer,
L"PageStart %x (%x), PageEnd %x (%x), Type (%x)\r\n",
MdPhysicalStart, (EfiMd->PhysicalStart >> EFI_PAGE_SHIFT),
MdPhysicalEnd, (EfiMd->PhysicalStart >>EFI_PAGE_SHIFT) + EfiMd->NumberOfPages,
EfiMd->Type);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
DBG_EFI_PAUSE();
#endif
//
// Insert conventional memory descriptors with WB flag set
// into NT loader memory descriptor list.
//
if ( (EfiMd->Type == EfiConventionalMemory) &&
((EfiMd->Attribute & EFI_MEMORY_WB) == EFI_MEMORY_WB) ) {
ULONGLONG AmountOfMemory;
ULONG NumberOfEfiPages;
BOOLEAN FirstTime = TRUE;
//
// Allocate pages between the start and _80MB line for
// the loader to manage. We don't use anything above this range, so
// just leave that memory alone
//
if ((MdPhysicalStart < (_80MB << PAGE_SHIFT)) &&
(MdPhysicalEnd > (_80MB << PAGE_SHIFT))) {
AmountOfMemory = (_80MB << PAGE_SHIFT) - EfiMd->PhysicalStart;
//
// record the pages in EFI page size
//
NumberOfEfiPages = (ULONG)(AmountOfMemory >> EFI_PAGE_SHIFT);
//
// try to align it.
//
if ((NumberOfEfiPages % ((1 << PAGE_SHIFT) >> EFI_PAGE_SHIFT) != 0) &&
(NumberOfEfiPages + (PAGE_SHIFT - EFI_PAGE_SHIFT) <= EfiMd->NumberOfPages )) {
NumberOfEfiPages += (PAGE_SHIFT - EFI_PAGE_SHIFT);
}
Status = EfiBS->AllocatePages ( AllocateAddress,
EfiLoaderData,
NumberOfEfiPages,
&(EfiMd->PhysicalStart) );
#if DBG_MEMORY
wsprintf( DebugBuffer,
L"allocate pages @ %x size = %x\r\n",
(EfiMd->PhysicalStart >> EFI_PAGE_SHIFT),
NumberOfEfiPages);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
DBG_EFI_PAUSE();
#endif
if (EFI_ERROR(Status)) {
EfiST->ConOut->OutputString(EfiST->ConOut,
L"SuMain: AllocPages failed\n");
EfiBS->Exit(EfiImageHandle, Status, 0, 0);
}
MdPhysicalEnd = MdPhysicalStart + (NumberOfEfiPages << EFI_PAGE_SHIFT);
MdPhysicalSize = MdPhysicalEnd - MdPhysicalStart;
//
// If PalPhysicalBase is not 0, then do not report the memory
// from the end of PAL to the next larger page size to avoid
// memory aliasing in the kernel.
//
// we assume that we get the PAL memory in the memory map
// before any conventional memory
//
while (1) {
if (PalPhysicalBase != 0) {
//
// If the descriptor is completely before or after
// the PAL base, just insert it like a normal descriptor
//
if ( ((MdPhysicalStart < PalPhysicalBase) &&
(MdPhysicalEnd <= PalPhysicalBase)) ||
(MdPhysicalStart >= PalEnd)) {
InsertDescriptor( (ULONG)(MdPhysicalStart >> EFI_PAGE_SHIFT),
(ULONG)(MdPhysicalSize >> EFI_PAGE_SHIFT),
MemoryFirmwareTemporary );
}
//
// else the descriptors must somehow overlap (how
// could this be possible?
//
else {
if (MdPhysicalStart < PalPhysicalBase) {
ASSERT( MdPhysicalEnd > PalPhysicalBase );
EfiST->ConOut->OutputString(EfiST->ConOut,
L"SuMain: overlapping descriptor with PAL #1\n");
//
// Insert a descriptor from the start of
// the memory range to the start of the PAL
// code
//
InsertDescriptor( (ULONG)(MdPhysicalStart >> EFI_PAGE_SHIFT),
(ULONG)((PalPhysicalBase - MdPhysicalStart) >> EFI_PAGE_SHIFT),
EfiToArcType(EfiMd->Type));
}
if (MdPhysicalEnd > PalEnd) {
//
// Insert a descriptor from the end of the
// PAL code to the end of the memory range
//
InsertDescriptor( (ULONG)(PalEnd >> EFI_PAGE_SHIFT),
(ULONG)((MdPhysicalEnd - PalEnd) >> EFI_PAGE_SHIFT),
EfiToArcType(EfiMd->Type));
}
}
} else {
//
// Insert the descriptor
//
// hack -- set the memory type to "permanent" so that we
// don't merge it with the prior descriptor. We'll set it
// back to the correct type after we return.
//
InsertDescriptor( (ULONG)(MdPhysicalStart >> EFI_PAGE_SHIFT),
(ULONG)((ULONGLONG)MdPhysicalSize >> EFI_PAGE_SHIFT),
FirstTime? LoaderFree : LoaderFirmwarePermanent);
}
if (!FirstTime) {
MDArray[NumberDescriptors-1].MemoryType = LoaderFirmwareTemporary;
break;
} else {
//
// go through again with the rest of the memory descriptor
//
MdPhysicalEnd = MdPhysicalStart + (EfiMd->NumberOfPages << EFI_PAGE_SHIFT);
MdPhysicalStart += MdPhysicalSize;
MdPhysicalSize = MdPhysicalEnd - MdPhysicalStart;
#if DBG_MEMORY
wsprintf( DebugBuffer,
L"change start @ %x --> @ %x size %x --> %x\r\n",
(EfiMd->PhysicalStart >> EFI_PAGE_SHIFT),
(MdPhysicalStart >> EFI_PAGE_SHIFT),
EfiMd->NumberOfPages,
(EfiMd->NumberOfPages-NumberOfEfiPages) );
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
DBG_EFI_PAUSE();
#endif
FirstTime = FALSE;
}
}
} else {
//
// just insert it
//
InsertDescriptor( (ULONG)(MdPhysicalStart >> EFI_PAGE_SHIFT),
(ULONG)((ULONGLONG)MdPhysicalSize >> EFI_PAGE_SHIFT),
EfiToArcType(EfiMd->Type));
}
} else if ( (EfiMd->Type == EfiLoaderCode) ||
(EfiMd->Type == EfiLoaderData) ) {
//
// just insert EfiLoaderCode and EfiLoaderData verbatim
//
InsertDescriptor( (ULONG)(MdPhysicalStart >> EFI_PAGE_SHIFT),
(ULONG)(MdPhysicalSize >> EFI_PAGE_SHIFT),
EfiToArcType(EfiMd->Type));
} else if (EfiMd->Type == EfiPalCode) {
//
// save off the Pal stuff for later
//
PalPhysicalBase = EfiMd->PhysicalStart;
PalSize = EfiMd->NumberOfPages << EFI_PAGE_SHIFT;
PalEnd = EfiMd->PhysicalStart + PalSize;
MEM_SIZE_TO_PS(PalSize, PalTrPs);
} else if (EfiMd->Type == EfiMemoryMappedIOPortSpace) {
//
// save off the Io stuff for later
//
IoPortPhysicalBase = EfiMd->PhysicalStart;
IoPortSize = EfiMd->NumberOfPages << EFI_PAGE_SHIFT;
MEM_SIZE_TO_PS(IoPortSize, IoPortTrPs);
} else if (EfiMd->Type == EfiMemoryMappedIO) {
//
// just ignore this type since it's not real memory -- the
// system can use ACPI tables to get at this later on.
//
} else {
//
// some other type -- just insert it without any changes
//
InsertDescriptor( (ULONG)(MdPhysicalStart >> EFI_PAGE_SHIFT),
(ULONG)(MdPhysicalSize >> EFI_PAGE_SHIFT),
EfiToArcType(EfiMd->Type));
}
}
EfiMd = (EFI_MEMORY_DESCRIPTOR *) ( (PUCHAR) EfiMd + DescriptorSize );
MemoryMapSize -= DescriptorSize;
}
//
// we've built the memory descriptors with EFI_PAGE_SIZE resolution.
// if the page sizes don't match, we post-process it here to get the
// resolution correct
//
if (PAGE_SHIFT != EFI_PAGE_SHIFT) {
AdjustMemoryDescriptorSizes();
}
}
VOID
GetPalProcEntryPoint(
IN PSST_HEADER SalSystemTable
)
{
PVOID NextEntry;
PPAL_SAL_ENTRY_POINT PalSalEntryPoint;
PSAL_MEMORY_DESCRIPTOR PSalMem;
ULONG PalFreeEnd;
ULONGLONG PalProcOffset;
ULONG i;
//
// Get PalProc entry point from SAL System Table
//
NextEntry = (PUCHAR) SalSystemTable + sizeof(SST_HEADER);
for (i = 0; i < SalSystemTable->EntryCount; i++) {
switch ( *(PUCHAR)NextEntry ) {
case PAL_SAL_EP_TYPE:
PalSalEntryPoint = (PPAL_SAL_ENTRY_POINT) NextEntry;
PalProcPhysical = PalSalEntryPoint->PalEntryPoint;
PalProcOffset = PalPhysicalBase - PalProcPhysical;
PalProcVirtual = VIRTUAL_PAL_BASE + PalProcOffset;
((PPAL_SAL_ENTRY_POINT)NextEntry)++;
break;
case SAL_MEMORY_TYPE:
((PSAL_MEMORY_DESCRIPTOR)NextEntry)++;
break;
case PLATFORM_FEATURES_TYPE:
((PPLATFORM_FEATURES)NextEntry)++;
break;
case TRANSLATION_REGISTER_TYPE:
((PTRANSLATION_REGISTER)NextEntry)++;
break;
case PTC_COHERENCE_TYPE:
((PPTC_COHERENCE_DOMAIN)NextEntry)++;
break;
case AP_WAKEUP_TYPE:
((PAP_WAKEUP_DESCRIPTOR)NextEntry)++;
break;
default:
EfiST->ConOut->OutputString(EfiST->ConOut,
L"SST: Invalid SST entry\n");
EfiBS->Exit(EfiImageHandle, 0, 0, 0);
}
}
}
ULONG
GetDevPathSize(
IN EFI_DEVICE_PATH *DevPath
)
{
EFI_DEVICE_PATH *Start;
//
// Search for the end of the device path structure
//
Start = DevPath;
while (DevPath->Type != END_DEVICE_PATH_TYPE) {
DevPath = NextDevicePathNode(DevPath);
}
//
// Compute the size
//
return ((UCHAR) DevPath - (UCHAR) Start);
}
MEMORY_TYPE
EfiToArcType (
UINT32 Type
)
/*++
Routine Description:
Maps an EFI memory type to an Arc memory type. We only care about a few
kinds of memory, so this list is incomplete.
Arguments:
Type - an EFI memory type
Returns:
A MEMORY_TYPE enumerated type.
--*/
{
MEMORY_TYPE typeRet=MemoryFirmwarePermanent;
switch (Type) {
case EfiLoaderCode:
{
typeRet=MemoryLoadedProgram; // This gets claimed later
break;
}
case EfiLoaderData:
case EfiBootServicesCode:
case EfiBootServicesData:
{
typeRet=MemoryFirmwareTemporary;
break;
}
case EfiConventionalMemory:
{
typeRet=MemoryFree;
break;
}
case EfiUnusableMemory:
{
typeRet=MemoryBad;
break;
}
default:
//
// all others are memoryfirmwarepermanent
//
break;
}
return typeRet;
}
VOID
InsertDescriptor (
ULONG BasePage,
ULONG NumberOfPages,
MEMORY_TYPE MemoryType
)
/*++
Routine Description:
This routine inserts a descriptor into the correct place in the
memory descriptor list.
The descriptors come in in EFI_PAGE_SIZE pages and must be
converted to PAGE_SIZE pages. This significantly complicates things,
as we must page align the start of descriptors and hte lengths of the
descriptors.
What we do is the following: we store the descriptors in the MDArray with
EFI_PAGE_SIZE resolution. When we do an insertion, we check if we can
coellesce the current entry with the prior entry (we assume our memory map
is sorted), keeping in mind that we want to ensure our entries are always
modulo PAGE_SIZE.
After we've added all of the entries with this routine, we have a post
processing step that converts all of the (modulo PAGE_SIZE) MDArray entries
into PAGE_SIZE resolution.
Arguments:
BasePage - Base page that the memory starts at.
NumberOfPages - The number of pages starting at memory block to be inserted.
MemoryType - An arc memory type describing the memory.
Return Value:
None. Updates MDArray global memory array.
--*/
{
MEMORY_DESCRIPTOR *CurrentEntry, *PriorEntry;
ULONG NewBasePage, NewNumberOfPages;
BOOLEAN MustCoellesce = FALSE;
BOOLEAN ShrinkPrior;
//
// Search the spot to insert the new descriptor.
//
// We assume that there are no holes in our array.
//
CurrentEntry = (MEMORY_DESCRIPTOR *)&MDArray[NumberDescriptors];
//
// if this is the first entry, just insert it
//
if (NumberDescriptors == 0) {
CurrentEntry->BasePage = BasePage;
CurrentEntry->PageCount = NumberOfPages;
CurrentEntry->MemoryType = MemoryType;
//
// The MDArray is already zeroed out so no need to zero out the next entry.
//
NumberDescriptors++;
#if DBG
wsprintf( DebugBuffer,
L"insert new descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
NumberDescriptors, MaxDescriptors, BasePage, NumberOfPages, MemoryType);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
#endif
return;
}
PriorEntry = (MEMORY_DESCRIPTOR *)&MDArray[NumberDescriptors-1];
//
// The last entry had better be empty or the descriptor list is
// somehow corrupted.
//
if (CurrentEntry->PageCount != 0) {
EfiST->ConOut->OutputString(EfiST->ConOut,
L"SuMain: Inconsistent Descriptor count in InsertDescriptor!\r\n");
EfiBS->Exit(EfiImageHandle, 0, 0, 0);
}
//
// if the memory type matches the prior entry's memory type, just merge
// the two together
//
if (PriorEntry->MemoryType == MemoryType) {
//
// validate that the array is really sorted correctly
//
if (PriorEntry->BasePage + PriorEntry->PageCount != BasePage) {
#if DBG
wsprintf( DebugBuffer,
L"SuMain: Inconsistent descriptor, PriorEntry->BasePage %x, PriorEntry->PageCount %x, BasePage = %x, type = %x -- insert new descriptor\r\n",
PriorEntry->BasePage,
PriorEntry->PageCount,
BasePage, MemoryType);
EfiST->ConOut->OutputString(EfiST->ConOut,DebugBuffer);
#endif
CurrentEntry->BasePage = BasePage;
CurrentEntry->PageCount = NumberOfPages;
CurrentEntry->MemoryType = MemoryType;
NumberDescriptors++;
#if DBG
wsprintf( DebugBuffer,
L"insert new descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
NumberDescriptors, MaxDescriptors, BasePage, NumberOfPages, MemoryType);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
#endif
return;
} else {
PriorEntry->PageCount += NumberOfPages;
#if DBG
wsprintf( DebugBuffer,
L"merge descriptor #%x of %x, BasePage %x, NumberOfPages %x --> %x, Type (%x)\r\n",
NumberDescriptors,
MaxDescriptors,
PriorEntry->BasePage,
PriorEntry->PageCount - NumberOfPages,
PriorEntry->PageCount,
MemoryType);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
#endif
return;
}
}
//
// check if the current starting address is module PAGE_SIZE. If it is,
// then we know that we must try to coellesce it with the prior entry.
//
//
NewBasePage = BasePage;
NewNumberOfPages = NumberOfPages;
if (BasePage % (1 << (PAGE_SHIFT - EFI_PAGE_SHIFT)) != 0) {
#if DBG
wsprintf( DebugBuffer,
L"must coellesce because base page %x isn't module PAGE_SIZE (%x mod %x = %x).\r\n",
BasePage,
(PAGE_SHIFT - EFI_PAGE_SHIFT),
(1 << (PAGE_SHIFT - EFI_PAGE_SHIFT)),
BasePage % (1 << (PAGE_SHIFT - EFI_PAGE_SHIFT)) );
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
#endif
MustCoellesce = TRUE;
}
if (PriorEntry->PageCount % (1 << (PAGE_SHIFT - EFI_PAGE_SHIFT)) != 0 ) {
#if DBG
wsprintf(
DebugBuffer,
L"must coellesce because prior page count %x isn't module PAGE_SIZE (%x mod %x = %x).\r\n",
PriorEntry->PageCount,
(PAGE_SHIFT - EFI_PAGE_SHIFT),
(1 << (PAGE_SHIFT - EFI_PAGE_SHIFT)),
PriorEntry->PageCount % (1 << (PAGE_SHIFT - EFI_PAGE_SHIFT)) );
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
#endif
MustCoellesce = TRUE;
}
if (MustCoellesce) {
if (PriorEntry->BasePage + PriorEntry->PageCount != BasePage) {
#if DBG
wsprintf( DebugBuffer,
L"SuMain: Inconsistent descriptor, PriorEntry->BasePage %x, PriorEntry->PageCount %x, BasePage = %x, type = %x -- insert new descriptor\r\n",
PriorEntry->BasePage,
PriorEntry->PageCount,
BasePage, MemoryType);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
#endif
MustCoellesce = FALSE;
}
}
if (MustCoellesce) {
switch( MemoryType ) {
case MemoryFirmwarePermanent:
//
// if the current type is permanent, we must steal from the prior entry
//
ShrinkPrior = TRUE;
break;
case MemoryLoadedProgram:
if (PriorEntry->MemoryType == MemoryFirmwarePermanent) {
ShrinkPrior = FALSE;
} else {
ShrinkPrior = TRUE;
}
break;
case MemoryFirmwareTemporary:
if (PriorEntry->MemoryType == MemoryFirmwarePermanent ||
PriorEntry->MemoryType == MemoryLoadedProgram) {
ShrinkPrior = FALSE;
} else {
ShrinkPrior = TRUE;
}
break;
case MemoryFree:
ShrinkPrior = FALSE;
break;
case MemoryBad:
ShrinkPrior = TRUE;
break;
default:
EfiST->ConOut->OutputString(EfiST->ConOut,
L"SuMain: bad memory type in InsertDescriptor\r\n");
EfiBS->Exit(EfiImageHandle, 0, 0, 0);
}
if (ShrinkPrior) {
//
// If the prior entry is small enough, we just convert the whole
// thing to the new type.
//
if (PriorEntry->PageCount <= (PAGE_SHIFT - EFI_PAGE_SHIFT)) {
PriorEntry->PageCount += NumberOfPages;
PriorEntry->MemoryType = MemoryType;
#if DBG
wsprintf( DebugBuffer,
L"adjust prior descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
NumberDescriptors,
MaxDescriptors,
PriorEntry->BasePage,
PriorEntry->PageCount ,
PriorEntry->MemoryType);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
#endif
return;
} else {
//
// we just steal part of the prior entry.
//
PriorEntry->PageCount -= (PAGE_SHIFT - EFI_PAGE_SHIFT);
NewNumberOfPages += (PAGE_SHIFT - EFI_PAGE_SHIFT);
NewBasePage -= (PAGE_SHIFT - EFI_PAGE_SHIFT);
#if DBG
wsprintf( DebugBuffer,
L"shrink earlier descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
NumberDescriptors,
MaxDescriptors,
PriorEntry->BasePage,
PriorEntry->PageCount,
PriorEntry->MemoryType);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
#endif
}
} else {
//
// If the current entry is small enough, we just convert the whole
// thing to the prior type.
//
if (NumberOfPages <= (PAGE_SHIFT - EFI_PAGE_SHIFT)) {
PriorEntry->PageCount += NumberOfPages;
#if DBG
wsprintf( DebugBuffer,
L"adjust prior descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
NumberDescriptors,
MaxDescriptors,
PriorEntry->BasePage,
PriorEntry->PageCount ,
PriorEntry->MemoryType);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
#endif
return;
} else {
//
// we just steal part of the new entry, adding it to the last
// entry
//
PriorEntry->PageCount += (PAGE_SHIFT - EFI_PAGE_SHIFT);
NewNumberOfPages -= (PAGE_SHIFT - EFI_PAGE_SHIFT);
NewBasePage += (PAGE_SHIFT - EFI_PAGE_SHIFT);
#if DBG
wsprintf( DebugBuffer,
L"grow earlier descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
NumberDescriptors,
MaxDescriptors,
PriorEntry->BasePage,
PriorEntry->PageCount,
PriorEntry->MemoryType);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
#endif
}
}
}
//
// we have now adjusted the prior entry, just insert whatever remains
//
CurrentEntry->BasePage = NewBasePage;
CurrentEntry->PageCount = NewNumberOfPages;
CurrentEntry->MemoryType = MemoryType;
NumberDescriptors++;
#if DBG
wsprintf( DebugBuffer,
L"insert new descriptor #%x of %x, BasePage %x, NumberOfPages %x, Type (%x)\r\n",
NumberDescriptors,
MaxDescriptors,
CurrentEntry->BasePage,
CurrentEntry->PageCount,
CurrentEntry->MemoryType);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
#endif
return;
}
#if 0
#define DBG_OUT(_X) \
(EfiST->ConOut->OutputString(EfiST->ConOut, (_X))); \
while (!BlGetKey());
void DbgOut(PWSTR Str) {
if (Str)
DBG_OUT(Str)
}
#endif
#ifdef FORCE_CD_BOOT
void EfiDbg(PWCHAR szStr) {
DBG_TRACE(szStr);
}
#endif // for FORCE_CD_BOOT
VOID
AdjustMemoryDescriptorSizes(
VOID
)
/*++
Routine Description:
If the EFI_PAGE_SIZE doesn't match PAGE_SIZE, this routine will
adjust the page sizes to be in PAGE_SIZE resolution.
We assume that the MDArray is already in modulo PAGE_SIZE chunks
Arguments:
None.
Returns:
None. Adjusts MDArray global variable.
--*/
{
ULONG i;
MEMORY_DESCRIPTOR *CurrentEntry;
ULONGLONG Scratch;
for (i = 0; i < NumberDescriptors; i++ ) {
CurrentEntry = (MEMORY_DESCRIPTOR *)&MDArray[i];
#if 1
Scratch = (ULONGLONG)CurrentEntry->BasePage << EFI_PAGE_SHIFT;
Scratch = Scratch >> PAGE_SHIFT;
CurrentEntry->BasePage = (ULONG)Scratch;
Scratch = (ULONGLONG)CurrentEntry->PageCount << EFI_PAGE_SHIFT;
Scratch = Scratch >> PAGE_SHIFT;
CurrentEntry->PageCount = (ULONG)Scratch;
if (CurrentEntry->PageCount == 0) {
wsprintf( DebugBuffer,
L"SuMain: Invalid descriptor size smaller than PAGE_SIZE, BasePage %x, type = %x\r\n",
CurrentEntry->BasePage,
CurrentEntry->MemoryType);
EfiST->ConOut->OutputString( EfiST->ConOut, DebugBuffer);
}
#else
CurrentEntry->BasePage = (ULONG)(ULONGLONG)(((ULONGLONG)(CurrentEntry->BasePage << EFI_PAGE_SHIFT)) >> PAGE_SHIFT);
CurrentEntry->PageCount = (ULONG)((ULONGLONG)(CurrentEntry->PageCount << EFI_PAGE_SHIFT) >> PAGE_SHIFT);
#endif
}
}