mirror of https://github.com/lianthony/NT4.0
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.
301 lines
7.5 KiB
301 lines
7.5 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
fwload.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the ARC software loadable functions.
|
|
|
|
Author:
|
|
|
|
Lluis Abello (lluis) 19-Sep-1991
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "fwp.h"
|
|
#include "string.h"
|
|
#include "ntimage.h"
|
|
#include "duobase.h"
|
|
|
|
|
|
//
|
|
// s_flags values
|
|
//
|
|
|
|
#define STYP_REG 0x00000000
|
|
#define STYP_TEXT 0x00000020
|
|
#define STYP_INIT 0x80000000
|
|
#define STYP_RDATA 0x00000100
|
|
#define STYP_DATA 0x00000040
|
|
#define STYP_LIT8 0x08000000
|
|
#define STYP_LIT4 0x10000000
|
|
#define STYP_SDATA 0x00000200
|
|
#define STYP_SBSS 0x00000080
|
|
#define STYP_BSS 0x00000400
|
|
#define STYP_LIB 0x40000000
|
|
#define STYP_UCODE 0x00000800
|
|
#define S_NRELOC_OVFL 0x20000000
|
|
|
|
ULONG FwActualBasePage;
|
|
ULONG FwPageCount;
|
|
|
|
|
|
ARC_STATUS
|
|
FwLoad (
|
|
IN PCHAR ImagePath,
|
|
IN ULONG TopAddress,
|
|
OUT PULONG EntryAddress,
|
|
OUT PULONG LowAddress
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine attempts to load the specified file from the specified
|
|
device.
|
|
|
|
Arguments:
|
|
|
|
ImagePath - Supplies a pointer to the path of the file to load.
|
|
|
|
TopAddress - Supplies the top address of a region of memory into which
|
|
the file is to be loaded.
|
|
|
|
EntryAddress - Supplies a pointer to a variable to receive the entry point
|
|
of the image, if defined.
|
|
|
|
LowAddress - Supplies a pointer to a variable to receive the low address
|
|
of the loaded file.
|
|
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG ActualBase;
|
|
ULONG SectionBase;
|
|
ULONG SectionOffset;
|
|
ULONG SectionIndex;
|
|
ULONG Count;
|
|
PIMAGE_FILE_HEADER FileHeader;
|
|
ULONG FileId;
|
|
ULONG Index;
|
|
UCHAR LocalBuffer[SECTOR_SIZE+128];
|
|
PUCHAR LocalPointer;
|
|
ULONG NumberOfSections;
|
|
PFW_MEMORY_DESCRIPTOR FwMemoryDescriptor;
|
|
PMEMORY_DESCRIPTOR MemoryDescriptor;
|
|
PIMAGE_OPTIONAL_HEADER OptionalHeader;
|
|
PIMAGE_SECTION_HEADER SectionHeader;
|
|
ARC_STATUS Status;
|
|
LARGE_INTEGER SeekPosition;
|
|
ULONG SectionFlags;
|
|
|
|
//
|
|
// Align the buffer on a Dcache line size.
|
|
//
|
|
|
|
LocalPointer = (PVOID) ((ULONG) ((PCHAR) LocalBuffer + KeGetDcacheFillSize() - 1)
|
|
& ~(KeGetDcacheFillSize() - 1));
|
|
|
|
//
|
|
// Set the image start address to null.
|
|
//
|
|
|
|
*EntryAddress = 0;
|
|
|
|
//
|
|
// Attempt to open the load file.
|
|
//
|
|
|
|
Status = FwOpen(ImagePath, ArcOpenReadOnly, &FileId);
|
|
if (Status != ESUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Read the image header from the file.
|
|
//
|
|
|
|
Status = FwRead(FileId, LocalPointer, SECTOR_SIZE, &Count);
|
|
if (Status != ESUCCESS) {
|
|
FwClose(FileId);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Get a pointer to the file header and begin processing it.
|
|
//
|
|
|
|
FileHeader = (PIMAGE_FILE_HEADER)LocalPointer;
|
|
OptionalHeader =
|
|
(PIMAGE_OPTIONAL_HEADER)(LocalPointer + sizeof(IMAGE_FILE_HEADER));
|
|
SectionHeader =
|
|
(PIMAGE_SECTION_HEADER)(LocalPointer + sizeof(IMAGE_FILE_HEADER) +
|
|
FileHeader->SizeOfOptionalHeader);
|
|
|
|
//
|
|
// If the image file is not the specified type, then return bad image
|
|
// type status.
|
|
//
|
|
|
|
if (!((FileHeader->Machine == IMAGE_FILE_MACHINE_R3000) ||
|
|
(FileHeader->Machine == IMAGE_FILE_MACHINE_R4000)) ||
|
|
((FileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == 0)) {
|
|
FwClose(FileId);
|
|
ScsiDebugPrint(1,"Bad File Header\n");
|
|
return EBADF;
|
|
}
|
|
|
|
//
|
|
// If the image cannot be relocated, set the ActualBase to the code base,
|
|
// and compute the image size by subtracting the code base from the data
|
|
// base plus the size of the data. If the image can be relocated,
|
|
// set ActualBase to the TopAddress minus the image size, and compute the
|
|
// image size by adding the size of the code, initialized data, and
|
|
// uninitialized data.
|
|
//
|
|
|
|
NumberOfSections = FileHeader->NumberOfSections;
|
|
|
|
if ((FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) != 0) {
|
|
ActualBase = OptionalHeader->BaseOfCode;
|
|
FwPageCount = (OptionalHeader->BaseOfData + OptionalHeader->SizeOfInitializedData) -
|
|
ActualBase;
|
|
} else {
|
|
ScsiDebugPrint(1,"Relocatable file not supported\n");
|
|
FwClose(FileId);
|
|
return EBADF;
|
|
}
|
|
|
|
//
|
|
// Check That the program is linked at the right place
|
|
//
|
|
if (((ActualBase+FwPageCount) & ~KSEG1_BASE) > (TopAddress & ~KSEG1_BASE)) {
|
|
FwClose(FileId);
|
|
return EBADF;
|
|
}
|
|
|
|
//
|
|
// Convert ActualBasePage and PageCount to be in units of pages instead of
|
|
// bytes.
|
|
//
|
|
|
|
FwActualBasePage = (ActualBase & 0x1fffffff) >> PAGE_SHIFT;
|
|
|
|
if (strcmp((PCHAR)&SectionHeader[NumberOfSections - 1].Name, ".debug") == 0) {
|
|
NumberOfSections -= 1;
|
|
FwPageCount -= SectionHeader[NumberOfSections].SizeOfRawData;
|
|
}
|
|
|
|
FwPageCount = (FwPageCount + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
|
|
|
*LowAddress = ActualBase | KSEG0_BASE;
|
|
|
|
//
|
|
// Return the entry address to the caller.
|
|
//
|
|
|
|
*EntryAddress = ((ActualBase | KSEG0_BASE) +
|
|
(OptionalHeader->AddressOfEntryPoint - OptionalHeader->BaseOfCode)
|
|
);
|
|
|
|
|
|
//
|
|
// Scan through the sections and either read them into memory or clear
|
|
// the memory as appropriate.
|
|
//
|
|
|
|
SectionOffset = 0;
|
|
for (Index = 0; Index < NumberOfSections; Index += 1) {
|
|
|
|
//
|
|
// Compute the destination address for the current section.
|
|
//
|
|
SectionBase = SectionHeader->VirtualAddress | KSEG0_BASE;
|
|
|
|
//
|
|
// If the section is code, initialized data, or other, then read
|
|
// the code or data into memory.
|
|
//
|
|
|
|
if ((SectionHeader->Characteristics &
|
|
(STYP_TEXT | STYP_INIT | STYP_RDATA | STYP_DATA | STYP_SDATA)) != 0) {
|
|
|
|
SeekPosition.LowPart = SectionHeader->PointerToRawData;
|
|
SeekPosition.HighPart = 0;
|
|
Status = FwSeek(FileId,
|
|
&SeekPosition,
|
|
SeekAbsolute);
|
|
|
|
if (Status != ESUCCESS) {
|
|
break;
|
|
}
|
|
|
|
Status = FwRead(FileId,
|
|
(PVOID)SectionBase,
|
|
SectionHeader->SizeOfRawData,
|
|
&Count);
|
|
|
|
if (Status != ESUCCESS) {
|
|
ScsiDebugPrint(1,"Section read error %lx\n",Status);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Set the offset of the next section
|
|
//
|
|
SectionOffset += SectionHeader->SizeOfRawData;
|
|
|
|
//
|
|
// If the section is uninitialized data, then zero the specifed memory.
|
|
//
|
|
|
|
} else if ((SectionHeader->Characteristics & (STYP_BSS | STYP_SBSS)) != 0) {
|
|
|
|
RtlZeroMemory((PVOID)(SectionBase), SectionHeader->SizeOfRawData);
|
|
|
|
//
|
|
// Set the offset of the next section
|
|
//
|
|
|
|
SectionOffset += SectionHeader->SizeOfRawData;
|
|
|
|
}
|
|
|
|
SectionHeader += 1;
|
|
ScsiDebugPrint(2,"Section successfully read\n");
|
|
}
|
|
|
|
|
|
//
|
|
// Close file and return completion status.
|
|
//
|
|
FwClose(FileId);
|
|
if (Status == ESUCCESS) {
|
|
|
|
//
|
|
// Flush the instruction and data caches.
|
|
//
|
|
|
|
FwSweepIcache();
|
|
FwSweepDcache();
|
|
|
|
}
|
|
return Status;
|
|
}
|