/*++ Copyright (c) 1991 Microsoft Corporation Module Name: coffldr.c Abstract: This module implements the code to load COFF format image into memory and relocate it if necessary. Author: David N. Cutler (davec) 10-May-1991 Environment: Kernel mode only. Revision History: --*/ #include "bldr.h" #include "firmware.h" #include "string.h" #include "ntimage.h" ARC_STATUS FwLoadImage( IN PCHAR LoadFile, OUT PVOID *TransferRoutine ) /*++ Routine Description: This routine attempts to load the specified file from the specified device. Arguments: LoadFile - Supplies a pointer to string descriptor for the name of the file to load. TransferRoutine - Supplies the address of where to store the start address for the image. 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 BasePage; ULONG Count; PIMAGE_FILE_HEADER CoffHeader; PIMAGE_OPTIONAL_HEADER OptionalHeader; PIMAGE_SECTION_HEADER SectionHeader; ULONG FileId; ULONG Index; UCHAR LocalBuffer[SECTOR_SIZE+32]; PUCHAR LocalPointer; PFW_MEMORY_DESCRIPTOR MemoryDescriptor; ULONG PageCount; ARC_STATUS Status; LARGE_INTEGER SeekValue; // // Align the buffer on a Dcache fill size. // LocalPointer = (PVOID)((ULONG)((PCHAR)LocalBuffer + PCR->FirstLevelDcacheFillSize - 1) & ~(PCR->FirstLevelDcacheFillSize - 1)); // // Set the image start address to null. // *TransferRoutine = NULL; // // Attempt to open the load file. // // ****** temp ****** // // This will eventually use FwOpen rather than BlOpen. For now both // BlOpen and FwOpen share a single copy of the file table in the // firmware loader. Eventually there will be a separate file table // for the firmware loader and the boot loader. // // ****** temp ****** // Status = BlOpen(2, LoadFile, 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. // CoffHeader = (PIMAGE_FILE_HEADER)LocalPointer; OptionalHeader = (PIMAGE_OPTIONAL_HEADER)((ULONG)CoffHeader + sizeof(IMAGE_FILE_HEADER)); SectionHeader = (PIMAGE_SECTION_HEADER)((ULONG)CoffHeader + sizeof(IMAGE_FILE_HEADER) + CoffHeader->SizeOfOptionalHeader); // // If the image file is not the specified type, then return bad image // type status. // if (((CoffHeader->Machine != IMAGE_TYPE_R3000) && (CoffHeader->Machine != IMAGE_TYPE_R4000)) || ((CoffHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) == 0)) { FwClose(FileId); return EBADF; } // // ******* add code ****** // // Code needs to be added here to find the appropriate piece of memory // to put the loaded image in. // // ******* add code ****** // // // Return the transfer routine to the caller. // *TransferRoutine = (PVOID)OptionalHeader->AddressOfEntryPoint; // // Scan through the sections and either read them into memory or clear // the memory as appropriate. // for (Index = 0; Index < CoffHeader->NumberOfSections; Index += 1) { // // If the section is a code or initialized data section, then read // the code or data into memory. // if (((SectionHeader->Characteristics & IMAGE_SCN_CNT_CODE) != 0) || ((SectionHeader->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) != 0)) { SeekValue.LowPart = SectionHeader->PointerToRawData; SeekValue.HighPart = 0; Status = FwSeek(FileId, &SeekValue, SeekAbsolute); if (Status != ESUCCESS) { break; } Status = FwRead(FileId, (PVOID)SectionHeader->VirtualAddress, SectionHeader->SizeOfRawData, &Count); if (Status != ESUCCESS) { break; } // // If the section is uninitialized data, then zero the specifed memory. // } else if ((SectionHeader->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0) { RtlZeroMemory((PVOID)SectionHeader->VirtualAddress, SectionHeader->SizeOfRawData); // // Unknown section type. // } else { Status = EBADF; break; } SectionHeader += 1; } // // Close file, allocate a memory descriptor if necessary, and return // completion status. // FwClose(FileId); if (Status == ESUCCESS) { // // ****** temp ****** // // default the address of the memory descriptor for now. // // ****** temp ****** // MemoryDescriptor = &FwMemoryTable[2]; // // Compute the starting page and the number of pages that are consumed // by the loaded image, and then allocate a memory descriptor for the // allocated region. // BasePage = (OptionalHeader->BaseOfCode & 0xfffffff) >> PAGE_SHIFT; PageCount = (((OptionalHeader->BaseOfData & 0xfffffff) + OptionalHeader->SizeOfInitializedData + OptionalHeader->SizeOfUninitializedData + PAGE_SIZE - 1) >> PAGE_SHIFT) - BasePage; FwGenerateDescriptor(MemoryDescriptor, MemoryLoadedProgram, BasePage, PageCount); } return Status; }