400 lines
10 KiB
C
400 lines
10 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
Copyright (c) 1992 Digital Equipment Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
palldr.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the code to load the PAL image into memory.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Rod N. Gamache [DEC] 12-Sep-1992
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode only.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "bldr.h"
|
|||
|
#include "stdio.h"
|
|||
|
#include "string.h"
|
|||
|
#include "ntimage.h"
|
|||
|
|
|||
|
#define ALIGN_PAL 0x10000 // Align PAL on 64KB boundary
|
|||
|
#define ALIGN_PAL_PAGE (ALIGN_PAL >> PAGE_SHIFT)
|
|||
|
|
|||
|
extern ULONG BlConsoleOutDeviceId;
|
|||
|
extern ULONG BlConsoleInDeviceId;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
BlLoadPal(
|
|||
|
IN ULONG DeviceId,
|
|||
|
IN TYPE_OF_MEMORY MemoryType,
|
|||
|
IN PCHAR LoadPath,
|
|||
|
IN USHORT ImageType,
|
|||
|
OUT PVOID *ImageBase,
|
|||
|
IN PCHAR LoadDevice
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine attempts to load the PAL file from the specified
|
|||
|
load path.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DeviceId - Supplies the file table index of the device to load the
|
|||
|
specified image file from.
|
|||
|
|
|||
|
MemoryType - Supplies the type of memory to to be assigned to the
|
|||
|
allocated memory descriptor.
|
|||
|
|
|||
|
LoadPath - Supplies a pointer to string descriptor for the name of
|
|||
|
the path to the PAL file to load.
|
|||
|
|
|||
|
ImageBase - Supplies a pointer to a variable that receives the
|
|||
|
address of the PAL image base.
|
|||
|
|
|||
|
LoadDevice - Supplies a pointer to a string descriptor for the name
|
|||
|
of the load device.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ESUCCESS is returned if the specified image file is loaded
|
|||
|
successfully. Otherwise, an unsuccessful status is returned
|
|||
|
that describes the reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CHAR PalName[256];
|
|||
|
CHAR PalFileName[32];
|
|||
|
ARC_STATUS Status;
|
|||
|
CHAR OutputBuffer[256];
|
|||
|
ULONG Count;
|
|||
|
|
|||
|
PIMAGE_NT_HEADERS NtHeaders;
|
|||
|
PIMAGE_SECTION_HEADER SectionHeader;
|
|||
|
PMEMORY_ALLOCATION_DESCRIPTOR PalMemoryDescriptor;
|
|||
|
PMEMORY_ALLOCATION_DESCRIPTOR NewMemoryDescriptor;
|
|||
|
ULONG StartVA;
|
|||
|
PVOID PalImageBase;
|
|||
|
PVOID NewImageBase;
|
|||
|
ULONG PalPage;
|
|||
|
ULONG PageCount;
|
|||
|
ULONG NewPageCount;
|
|||
|
ULONG ActualBase;
|
|||
|
ULONG FreePageCount;
|
|||
|
|
|||
|
Status = BlGeneratePalName( PalFileName );
|
|||
|
|
|||
|
if ( Status != ESUCCESS ) {
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
sprintf(PalName, "%s%s", LoadPath, PalFileName);
|
|||
|
|
|||
|
BlOutputLoadMessage(LoadDevice, PalName);
|
|||
|
Status = BlLoadImage(DeviceId,
|
|||
|
MemoryType,
|
|||
|
PalName,
|
|||
|
ImageType,
|
|||
|
ImageBase);
|
|||
|
|
|||
|
if ( Status != ESUCCESS ) {
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
NtHeaders = RtlImageNtHeader(*ImageBase);
|
|||
|
|
|||
|
if (!NtHeaders) {
|
|||
|
return EBADF;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Compute the address of the section headers and calculate the
|
|||
|
// starting virtual address for the image.
|
|||
|
//
|
|||
|
|
|||
|
SectionHeader =
|
|||
|
(PIMAGE_SECTION_HEADER)((ULONG)NtHeaders + sizeof(ULONG) +
|
|||
|
sizeof(IMAGE_FILE_HEADER) + NtHeaders->FileHeader.SizeOfOptionalHeader);
|
|||
|
|
|||
|
StartVA = SectionHeader->VirtualAddress;
|
|||
|
|
|||
|
PalImageBase = (PVOID)((ULONG)*ImageBase & ~KSEG0_BASE);
|
|||
|
PalPage = (ULONG)PalImageBase >> PAGE_SHIFT;
|
|||
|
|
|||
|
//
|
|||
|
// Check if PAL is aligned correctly. If not, then allocate a new
|
|||
|
// memory descriptor and copy the PAL image to an aligned buffer.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Find the memory descriptor for the PAL image that was loaded,
|
|||
|
// and find the size (in pages) of that loaded image.
|
|||
|
//
|
|||
|
|
|||
|
PalMemoryDescriptor = BlFindMemoryDescriptor(PalPage);
|
|||
|
|
|||
|
PageCount = PalMemoryDescriptor->PageCount;
|
|||
|
|
|||
|
if ( ((ULONG)PalImageBase & (ALIGN_PAL - 1)) != 0 ) {
|
|||
|
|
|||
|
//
|
|||
|
// Calculate new size + alignment requirement, and allocate a new
|
|||
|
// memory descriptor. Use any physical address starting from zero.
|
|||
|
//
|
|||
|
|
|||
|
NewPageCount = PageCount + ALIGN_PAL_PAGE - 1;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate a memory descriptor.
|
|||
|
//
|
|||
|
|
|||
|
Status = BlAllocateDescriptor(MemoryType,
|
|||
|
0,
|
|||
|
NewPageCount,
|
|||
|
&ActualBase);
|
|||
|
|
|||
|
if (Status != ESUCCESS) {
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
NewMemoryDescriptor = BlFindMemoryDescriptor(ActualBase);
|
|||
|
|
|||
|
//
|
|||
|
// Align PAL to 64KB boundary. First, return any free memory at front
|
|||
|
// of PAL image.
|
|||
|
//
|
|||
|
if ( (ActualBase & (ALIGN_PAL_PAGE - 1)) != 0 ) {
|
|||
|
|
|||
|
NewMemoryDescriptor = BlFindMemoryDescriptor(ActualBase);
|
|||
|
|
|||
|
FreePageCount = ALIGN_PAL_PAGE - (ActualBase & (ALIGN_PAL_PAGE-1));
|
|||
|
|
|||
|
BlGenerateDescriptor(NewMemoryDescriptor,
|
|||
|
MemoryFree,
|
|||
|
ActualBase,
|
|||
|
FreePageCount);
|
|||
|
|
|||
|
//
|
|||
|
// Adjust base and pagecount
|
|||
|
//
|
|||
|
|
|||
|
ActualBase = (ActualBase + (ALIGN_PAL - 1 >> PAGE_SHIFT)) &
|
|||
|
~(ALIGN_PAL_PAGE - 1);
|
|||
|
|
|||
|
NewPageCount -= FreePageCount;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Compute the new image base.
|
|||
|
//
|
|||
|
|
|||
|
NewImageBase = (PVOID)(KSEG0_BASE | (ActualBase << PAGE_SHIFT));
|
|||
|
|
|||
|
//
|
|||
|
// Copy PAL from the loaded memory block to the new memory block.
|
|||
|
//
|
|||
|
|
|||
|
PalImageBase = (PVOID)(KSEG0_BASE | (ULONG)PalImageBase);
|
|||
|
RtlMoveMemory(NewImageBase,
|
|||
|
(PVOID)((PUCHAR)PalImageBase + StartVA),
|
|||
|
(PageCount << PAGE_SHIFT) - StartVA);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Free the original memory descriptor.
|
|||
|
//
|
|||
|
|
|||
|
BlGenerateDescriptor(PalMemoryDescriptor,
|
|||
|
MemoryFree,
|
|||
|
PalMemoryDescriptor->BasePage,
|
|||
|
PalMemoryDescriptor->PageCount);
|
|||
|
|
|||
|
*ImageBase = NewImageBase;
|
|||
|
|
|||
|
//
|
|||
|
// Return any blocks free at the end of the new image section.
|
|||
|
//
|
|||
|
|
|||
|
FreePageCount = NewPageCount - PageCount + (StartVA >> PAGE_SHIFT);
|
|||
|
|
|||
|
if ( FreePageCount ) {
|
|||
|
|
|||
|
BlGenerateDescriptor(NewMemoryDescriptor,
|
|||
|
MemoryFree,
|
|||
|
ActualBase + PageCount - (StartVA >> PAGE_SHIFT),
|
|||
|
FreePageCount);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else if ( StartVA != 0 ) {
|
|||
|
|
|||
|
//
|
|||
|
// Move the image down to the start of the memory descriptor
|
|||
|
//
|
|||
|
|
|||
|
PalImageBase = (PVOID)(KSEG0_BASE | (ULONG)PalImageBase);
|
|||
|
|
|||
|
RtlMoveMemory(PalImageBase,
|
|||
|
(PVOID)((PUCHAR)PalImageBase + StartVA),
|
|||
|
(PageCount << PAGE_SHIFT) - StartVA);
|
|||
|
|
|||
|
//
|
|||
|
// Return any blocks free at the end of the image.
|
|||
|
//
|
|||
|
|
|||
|
FreePageCount = StartVA >> PAGE_SHIFT;
|
|||
|
|
|||
|
if ( FreePageCount ) {
|
|||
|
|
|||
|
BlGenerateDescriptor(PalMemoryDescriptor,
|
|||
|
MemoryFree,
|
|||
|
PalPage + PageCount - (StartVA >> PAGE_SHIFT),
|
|||
|
FreePageCount);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return ESUCCESS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ARC_STATUS
|
|||
|
BlGeneratePalName(
|
|||
|
IN PCHAR PalFileName
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine generates the name of the correct PAL file for the current
|
|||
|
system.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
PalFileName - Supplies a pointer to string for the name of the PAL file
|
|||
|
that is generated.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ESUCCESS is returned if the specified PAL file name is generated.
|
|||
|
Otherwise, an unsuccessful status is returned that describes the
|
|||
|
reason for failure.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
CHAR ProcessorName[32] = "";
|
|||
|
PCHAR ProcessorId;
|
|||
|
PCONFIGURATION_COMPONENT ComponentInfo;
|
|||
|
ARC_STATUS Status;
|
|||
|
ULONG Max = 7;
|
|||
|
|
|||
|
//
|
|||
|
// Get the Processor Id Name from the ARC component Database.
|
|||
|
//
|
|||
|
|
|||
|
ComponentInfo = ArcGetChild(NULL); // Get ARC component info
|
|||
|
|
|||
|
while (ComponentInfo != NULL) {
|
|||
|
|
|||
|
if ( ComponentInfo->Class == SystemClass &&
|
|||
|
ComponentInfo->Identifier != NULL ) {
|
|||
|
|
|||
|
ComponentInfo = ArcGetChild(ComponentInfo); // Go Down in tree
|
|||
|
|
|||
|
} else if ( ComponentInfo->Class == ProcessorClass &&
|
|||
|
ComponentInfo->Type == CentralProcessor &&
|
|||
|
ComponentInfo->Identifier != NULL) {
|
|||
|
|
|||
|
strncat(ProcessorName, ComponentInfo->Identifier, 31);
|
|||
|
break;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
ComponentInfo = ArcGetPeer(ComponentInfo); // Look through all entries
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// On older firmware:
|
|||
|
//
|
|||
|
// The ProcessorName is of the form: mmm-rName, where:
|
|||
|
// mmm - is the manufacturer of the processor chip
|
|||
|
// r - is the revision of the processor chip
|
|||
|
// Name - is the name of the processor chip
|
|||
|
//
|
|||
|
// E.G. DEC-321064
|
|||
|
//
|
|||
|
// On newer firmware:
|
|||
|
//
|
|||
|
// The ProcessorName is of the form: mmm-Name-r, where:
|
|||
|
// mmm - is the manufacturer of the processor chip
|
|||
|
// r - is the revision of the processor chip
|
|||
|
// Name - is the name of the processor chip
|
|||
|
//
|
|||
|
// E.G. DEC-21064-3
|
|||
|
//
|
|||
|
|
|||
|
ProcessorId = strchr(ProcessorName, '-');
|
|||
|
|
|||
|
//
|
|||
|
// Load the PAL image into memory. The image will be of the
|
|||
|
// form <LoadPath>\Axxxxx.PAL. Try loading A<processorname>.PAL.
|
|||
|
// If that fails, then try AlphaAXP.pal.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Generate the full path name for the PAL image and load it into
|
|||
|
// memory.
|
|||
|
//
|
|||
|
|
|||
|
Status = EBADF;
|
|||
|
if ( ProcessorId ) {
|
|||
|
CHAR ProcessorIdName[8] = "";
|
|||
|
PCHAR RevisionId;
|
|||
|
ULONG Max = 7;
|
|||
|
|
|||
|
ProcessorId++; // Skip the hyphen
|
|||
|
|
|||
|
//
|
|||
|
// Check for new ProcessorId format, look for the revision id
|
|||
|
// after the processor id.
|
|||
|
//
|
|||
|
RevisionId = strchr(ProcessorId, '-');
|
|||
|
|
|||
|
if ( RevisionId ) {
|
|||
|
*RevisionId = '\0'; // Terminate the processor id
|
|||
|
RevisionId++; // Skip the hyphen
|
|||
|
strncat(ProcessorIdName, RevisionId, 2); // Copy Revision Id
|
|||
|
Max = Max - strlen( ProcessorIdName );
|
|||
|
}
|
|||
|
|
|||
|
strncat(ProcessorIdName, ProcessorId, Max); // Copy Processor Id
|
|||
|
sprintf(PalFileName, "A%s.PAL", ProcessorIdName);
|
|||
|
|
|||
|
Status = ESUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|