summaryrefslogblamecommitdiffstats
path: root/private/ntos/boot/veneer/vrpehdr.c
blob: d8528ac55d54140f33780af9a14caa379e3e3ad6 (plain) (tree)









































































































































                                                                               
/*++
 *
 * Copyright (c) 1996 FirePower Systems, Inc.
 * Copyright (c) 1995 FirePower Systems, Inc.
 * Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
 * Copyright (c) 1994 FirePower Systems Inc.
 *
 * $RCSfile: vrpehdr.c $
 * $Revision: 1.7 $
 * $Date: 1996/02/17 00:50:30 $
 * $Locker:  $

Module Name:

	vrpehdr.c

Abstract:

	These routines read and parse the Microsoft PE header.

Author:

	Mike Tuciarone  9-May-1994


Revision History:

--*/


#include "veneer.h"




#define	HEADER_CHR	(IMAGE_FILE_EXECUTABLE_IMAGE	| \
			 IMAGE_FILE_BYTES_REVERSED_LO	| \
			 IMAGE_FILE_32BIT_MACHINE	| \
			 IMAGE_FILE_BYTES_REVERSED_HI)

/*
 * For some reason NT 3.5 changed the OSLoader header.
 */
#define	HEADER_CHR_35	(IMAGE_FILE_EXECUTABLE_IMAGE	| \
			 IMAGE_FILE_32BIT_MACHINE	| \
			 IMAGE_FILE_LINE_NUMS_STRIPPED)

void *
load_file(ihandle bootih)
{
	IMAGE_FILE_HEADER FileHdr;
	IMAGE_OPTIONAL_HEADER OptHdr;
	IMAGE_SECTION_HEADER *SecHdr, *hdr;
	int res, size, i;
	PCHAR BaseAddr;

	if ((res = OFRead(bootih, (char *) &FileHdr, IMAGE_SIZEOF_FILE_HEADER))
	    != IMAGE_SIZEOF_FILE_HEADER) {
		fatal("Couldn't read entire file header: got %d\n", res);
	}

	/*
	 * Sanity check.
	 */
	if (FileHdr.Machine != IMAGE_FILE_MACHINE_POWERPC) {
		fatal("Wrong machine type: %x\n", FileHdr.Machine);
	}
#ifdef NOT
	/*
	 * Don't bother to check the flags. They change every release anyway.
	 */
	if ((FileHdr.Characteristics & HEADER_CHR   ) != HEADER_CHR &&
	    (FileHdr.Characteristics & HEADER_CHR_35) != HEADER_CHR_35) {
		fatal("Wrong header characteristics: %x\n",
		    FileHdr.Characteristics);
	}
#endif
	
	size = FileHdr.SizeOfOptionalHeader;
	if ((res = OFRead(bootih, (char *) &OptHdr, size)) != size) {
		fatal("Couldn't read optional header: expect %x got %x\n",
		    size, res);
	}

	/*
	 * More sanity.
	 */
	if (OptHdr.Magic != 0x010b) {
		fatal("Wrong magic number in header: %x\n", OptHdr.Magic);
	}

	/*
	 * Compute image size and claim memory at specified virtual address.
	 * We assume the SizeOfImage field is sufficient.
	 */
	BaseAddr = (PCHAR) OptHdr.ImageBase;
	if (CLAIM(BaseAddr, OptHdr.SizeOfImage) == -1) {
		fatal("Couldn't claim %x bytes of VM at %x\n",
	        OptHdr.SizeOfImage, BaseAddr);
	}
	bzero(BaseAddr, OptHdr.SizeOfImage);

	/*
	 * Allocate section headers.
	 */
	size = FileHdr.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
	SecHdr = (PIMAGE_SECTION_HEADER) malloc(size);
	if ((res = OFRead(bootih, (char *) SecHdr, size)) != size) {
		fatal("Couldn't read section headers: expect %x got %x\n",
		    size, res);
	}

	/*
	 * Loop through section headers, reading in each piece at the
	 * specified virtual address.
	 */
	for (i = 0; i < FileHdr.NumberOfSections; ++i) {
		hdr = &SecHdr[i];
		debug(VRDBG_PE, "Processing section %d: %s\n", i, hdr->Name);
		if (hdr->SizeOfRawData == 0) {
			continue;
		}
		if (OFSeek(bootih, 0, hdr->PointerToRawData) == -1) {
			fatal("seek to offset %x failed\n",
			    hdr->PointerToRawData);
		}
		res = OFRead(bootih,
		    (PCHAR) hdr->VirtualAddress + (ULONG) BaseAddr,
		    hdr->SizeOfRawData);
		if ((ULONG)res != hdr->SizeOfRawData) {
			fatal("Couldn't read data: exp %x got %x\n",
			    hdr->SizeOfRawData, res);
		}
	}
	free((char *)SecHdr);

	return (void *)(BaseAddr + OptHdr.AddressOfEntryPoint);
}