From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/boot/veneer/vrload.c | 1035 +++++++++++++++++++++++++++++++++++++ 1 file changed, 1035 insertions(+) create mode 100644 private/ntos/boot/veneer/vrload.c (limited to 'private/ntos/boot/veneer/vrload.c') diff --git a/private/ntos/boot/veneer/vrload.c b/private/ntos/boot/veneer/vrload.c new file mode 100644 index 000000000..9fdfc412d --- /dev/null +++ b/private/ntos/boot/veneer/vrload.c @@ -0,0 +1,1035 @@ +/* + * + * Copyright (c) 1995 FirePower Systems, Inc. + * Copyright (c) 1994 FirePower Systems Inc. + * + * $RCSfile: vrload.c $ + * $Revision: 1.12 $ + * $Date: 1996/04/15 02:55:48 $ + * $Locker: $ + * + * + * Module Name: + * vrload.c + * + * Author: + * Shin Iwamoto at FirePower Systems Inc. + * + * History: + * 28-Jul-94 Shin Iwamoto at FirePower Systems Inc. + * Added for DOS signature of PE in VrLoad(); + * 18-Jul-94 Shin Iwamoto at FirePower Systems Inc. + * Created. + */ + + +#include "veneer.h" + +#define XXX_MAKE_DESCRIPTOR + +// +// This must be defined in some header file. But for 3.5 it is not defined. +// +#define IMAGE_FILE_16BIT_MACHINE 0x0040 + + +typedef struct _VR_MEMORY_DESCRIPTOR { + struct _VR_MEMORY_DESCRIPTOR *NextEntry; + MEMORY_DESCRIPTOR MemoryEntry; +} VR_MEMORY_DESCRIPTOR, *PVR_MEMORY_DESCRIPTOR; + +extern PVR_MEMORY_DESCRIPTOR VrMemoryListOrig; + +// +// Some type definitions. +// +typedef struct _SECTION_RELOCATION_ENTRY { + ULONG FixupValue; + ULONG PointerToRelocations; + USHORT NumberOfRelocations; +} SECTION_RELOCATION_ENTRY, *PSECTION_RELOCATION_ENTRY; + +// +// Some definitions. +// +// These must be defined in veneer.h or ntimage.h? +// +#define HEADER_CHAR (IMAGE_FILE_EXECUTABLE_IMAGE | \ + IMAGE_FILE_BYTES_REVERSED_LO | \ + IMAGE_FILE_32BIT_MACHINE | \ + IMAGE_FILE_BYTES_REVERSED_HI) +#define HEADER_NOCHAR (IMAGE_FILE_16BIT_MACHINE | \ + IMAGE_FILE_DLL) +#define OPTIONAL_MAGIC_STD 0x010B + +// +// Section numbers for local relocation entries +// +#define R_SN_TEXT 0 +#define R_SN_DATA 1 +#define R_SN_BSS 2 +#define R_SN_MAX 3 + + +#define MAX_ARGUMENT (512 - sizeof(ULONG) - 16*sizeof(PUCHAR)) +typedef struct _SAVED_ARGUMENTS { + ULONG Argc; + PUCHAR Argv[16]; + UCHAR Arguments[MAX_ARGUMENT]; +} SAVED_ARGUMENTS, *PSAVED_ARGUMENTS; + + +STATIC PSAVED_ARGUMENTS SavedArgs; +STATIC ULONG VrActualBasePage; +STATIC ULONG VrPageCount; + + +// +// Function declarations. +// +ARC_STATUS +VrRelocateImage( + IN ULONG FileId, + IN PSECTION_RELOCATION_ENTRY RelocationTable, + IN ULONG NumberOfSections, + IN ULONG PointerToSymbolTable + ); +VOID +VrCopyArguments( + IN ULONG Argc, + IN PCHAR Argv[] + ); +ARC_STATUS +VrGenerateDescriptor( + IN PMEMORY_DESCRIPTOR MemoryDescriptor, + IN MEMORY_TYPE MemoryType, + IN ULONG BasePage, + IN ULONG PageCount + ); +VOID +VrResetMemory( + VOID + ); +VOID +PxInvoke( + IN ULONG EntryAddress, + IN ULONG StackAddress, + IN ULONG Argc, + IN PCHAR Argv[], + IN PCHAR Envp[] + ); +VOID +InsertMemDescriptor( + IN PVR_MEMORY_DESCRIPTOR MemDescriptor + ); + + +/* + * Name: VrLoad + * + * Description: + * This function reads a program into memory at a specified address + * an;d stores the execution address. + * + * 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. + * LoaAddress - 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 unsuccessufl status is returned that describes the reason + * for failure. + * + */ +ARC_STATUS +VrLoad( + IN PCHAR ImagePath, + IN ULONG TopAddress, + OUT PULONG EntryAddress, + OUT PULONG LowAddress + ) +{ + PSECTION_RELOCATION_ENTRY RelocationTable; + IMAGE_DOS_HEADER DosHeader; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER OptionalHeader; + PIMAGE_SECTION_HEADER SectionHeader, SHeader; + ULONG FileId, NumberOfSections, Count; + ULONG ActualBase, ClaimSize, SectionOffset; + LARGE_INTEGER SeekPosition; + ARC_STATUS Status; + LONG NT_Signature; + LONG size, i; + PCHAR ReadAddr; + ULONG ReadSize; + + + debug(VRDBG_LOAD, "VrLoad: Entry - ImagePath: %s TopAddress: %x\n", + ImagePath, TopAddress); + + // + // Attempt to open the load file. + // + if ((Status = VrOpen(ImagePath, ArcOpenReadOnly, &FileId)) != ESUCCESS) { + return Status; + } + + // + // Read DOS Signature. + // + if ((Status = VrRead(FileId, &DosHeader, 2, &Count)) != ESUCCESS) { + (VOID)VrClose(FileId); + return Status; + } + + // + // If the file isn't a PE file including DOS header, + // it's probably a COFF file. + // + if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) { + bcopy((char *)&DosHeader, (char *)&FileHeader, 2); + ReadAddr = (PCHAR)&FileHeader + 2; + ReadSize = IMAGE_SIZEOF_FILE_HEADER - 2; + goto DirectCOFF; + } + + // + // Read the remainder of DOS header. + // + if ((Status = VrRead(FileId, (PCHAR)&DosHeader+2, sizeof(DosHeader) - 2, + &Count)) != ESUCCESS) { + (VOID)VrClose(FileId); + return Status; + } + if (Count != sizeof(DosHeader) - 2) { + (VOID)VrClose(FileId); + return EBADF; // XXXX + } + SeekPosition.HighPart = 0; + SeekPosition.LowPart = DosHeader.e_lfanew; + if (Status = VrSeek(FileId, &SeekPosition, SeekAbsolute)) { + (VOID)VrClose(FileId); + return EBADF; // XXXX + } + + // + // Read NT Signature and confirm it. + // + if ((Status = VrRead(FileId, &NT_Signature, sizeof(NT_Signature), &Count)) + != ESUCCESS) { + (VOID)VrClose(FileId); + return Status; + } + if (Count != sizeof(NT_Signature) || NT_Signature != IMAGE_NT_SIGNATURE) { + (VOID)VrClose(FileId); + return EBADF; // XXXX + } + + ReadAddr = (PCHAR)&FileHeader; + ReadSize = IMAGE_SIZEOF_FILE_HEADER; + + DirectCOFF: + // + // Read the image header from the file. + // + if ((Status = VrRead(FileId, ReadAddr, ReadSize, &Count)) != ESUCCESS) { + (VOID)VrClose(FileId); + return Status; + } + if (Count != ReadSize) { + (VOID)VrClose(FileId); + return EBADF; // XXXX + } + + // + // Check the header. + // + if ((FileHeader.Machine != IMAGE_FILE_MACHINE_POWERPC) || + ((FileHeader.Characteristics & HEADER_CHAR) != HEADER_CHAR) || + ((FileHeader.Characteristics & HEADER_NOCHAR) != 0) ) { + + (VOID)VrClose(FileId); + return ENOEXEC; + } + + // + // Read the optional header. + // + if ((Status = VrRead(FileId, &OptionalHeader, + FileHeader.SizeOfOptionalHeader, &Count)) != ESUCCESS) { + (VOID)VrClose(FileId); + return Status; + } + if (Count != FileHeader.SizeOfOptionalHeader) { + (VOID)VrClose(FileId); + return EBADF; // XXXX + } + + // + // More check with the optional header. + // + if (OptionalHeader.Magic != OPTIONAL_MAGIC_STD) { + (VOID)VrClose(FileId); + return ENOEXEC; + } + + // + // 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 data size. If the image can be relocated, + // set ActualBase to the TopAddress minus the image size, compute + // image size by adding the code size, initialized data, and + // uninitialized data. + // + if ((FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) != 0) { + ActualBase = OptionalHeader.BaseOfCode; + ClaimSize = OptionalHeader.BaseOfData + + OptionalHeader.SizeOfInitializedData - ActualBase; + } else { + ClaimSize = OptionalHeader.SizeOfCode + + OptionalHeader.SizeOfInitializedData + + OptionalHeader.SizeOfUninitializedData; + // ActualBase = OptionalHeader.ImageBase; +#ifdef XXX_I_KNOW_PE + ActualBase = (TopAddress - ClaimSize) & ~(PAGE_SIZE - 1); +#else + ActualBase = OptionalHeader.ImageBase; + ActualBase &= 0x7fffffff; +#endif XXX_I_KNOW_PE + } + + // + // Allocate and read the section headers. + // + size = FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); + SectionHeader = (PIMAGE_SECTION_HEADER)malloc(size); + if ((Status = VrRead(FileId, (PCHAR)SectionHeader, size, &Count)) + != ESUCCESS) { + (VOID)VrClose(FileId); + return Status; + } + if (Count != (ULONG) size) { + (VOID)VrClose(FileId); + return EBADF; // XXXX + } + + // + // + // + NumberOfSections = FileHeader.NumberOfSections; + if (strcmp((PCHAR)(SectionHeader[NumberOfSections-1].Name), ".debug") + == 0) { + NumberOfSections--; + ClaimSize -= SectionHeader[NumberOfSections].SizeOfRawData; + } + + // + // Allocate the relocation table. + // + size = NumberOfSections * sizeof(SECTION_RELOCATION_ENTRY); + RelocationTable = (PSECTION_RELOCATION_ENTRY) malloc(size); + + // + // Zero the relocation table. + // + bzero((char *)RelocationTable, size); + + // + // Convert ClaimSize to be page-aligned. + // + ClaimSize = (ClaimSize + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + + // + // Convert ActualBase and ClaimSize to be in units of pages instead of + // bytes. This is the interface between VrExecute and VrLoad. + // + VrActualBasePage = (ActualBase & 0x7fffffff) >> PAGE_SHIFT; + VrPageCount = ClaimSize >> PAGE_SHIFT; + + // + // Claim memory at specified virtual address + // + if (claim((void *)ActualBase, ClaimSize) == -1) { + fatal("Veneer: Couldn't claim %x bytes of VM at %x\n", + ClaimSize, ActualBase); + } + + // + // Set output parametes. + // + *LowAddress = ActualBase; +#ifdef XXX_I_KNOW_PE + *EntryAddress = ActualBase + + (OptionalHeader.AddressOfEntryPoint - OptionalHeader.BaseOfCode); +#else + *EntryAddress = ActualBase + OptionalHeader.AddressOfEntryPoint; +#endif XXX_I_KNOW_PE + + // + // Scan through the sections and either read them into memory or + // clear the memory as appropriate. + // + SectionOffset = 0; + for (i = 0, SHeader = SectionHeader; (ULONG) i < NumberOfSections; + i++, SHeader++) { + ULONG SectionBase; + + if ((FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) != 0) { + SectionBase = SHeader->VirtualAddress; + } else { +#ifdef XXX_I_KNOW_PE + SectionBase = ActualBase + SectionOffset; +#else + SectionBase = ActualBase + SHeader->VirtualAddress; +#endif XXX_I_KNOW_PE + + (RelocationTable+i)->PointerToRelocations = + SHeader->PointerToRelocations; + (RelocationTable+i)->NumberOfRelocations = + SHeader->NumberOfRelocations; + (RelocationTable+i)->FixupValue = + SectionBase - SHeader->VirtualAddress; + } + + // + // If the section is code or initialized data, then read + // the code or data into memory. + // + if ((SHeader->Characteristics & ( IMAGE_SCN_CNT_CODE | + IMAGE_SCN_CNT_INITIALIZED_DATA) ) != 0) { + SeekPosition.LowPart = SHeader->PointerToRawData; + SeekPosition.HighPart = 0; + if ((Status = VrSeek(FileId, &SeekPosition, SeekAbsolute)) + != ESUCCESS) { + break; + } + if ((Status = VrRead(FileId, (PVOID)SectionBase, + SHeader->SizeOfRawData, &Count)) != ESUCCESS) { + break; + } + if (Count != SHeader->SizeOfRawData) { + Status = EBADF; // XXXX + break; + } + + // + // Set the offset of the next section. + // + SectionOffset += SHeader->SizeOfRawData; + } else + if ((SHeader->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) + != 0) { + bzero((PVOID)SectionBase, SHeader->SizeOfRawData); + + // + // Set the offset of the next section. + // + SectionOffset += SHeader->SizeOfRawData; + } + } + + // + // If code has to be relocated, do so. + // + if ((FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) == 0) { + if (ActualBase != OptionalHeader.ImageBase) { + Status = VrRelocateImage( FileId, RelocationTable, + NumberOfSections, + FileHeader.PointerToSymbolTable); + } + } + + // + // Deallocate allocated area and close the file. + // + free((char*) SectionHeader); + free((char*) RelocationTable); + (VOID)VrClose(FileId); + + debug(VRDBG_LOAD, "VrLoad: Exit - EntryAddress: %x LowAddress: %x Status:%d\n", + *EntryAddress, *LowAddress, Status); + + return Status; +} + + + +/* + * Name: VrInvoke + * + * Description: + * This function invokes a previously loaded program. + * + * Arguments: + * EntryAddress- Supplies the execution address of the program to be loaded. + * StackAddress- Supplies the stack address that is used to reset the stack + * pointer before the program is invoked. + * Argc - Supplies the argument count for the program. + * Argv - Supplies a pointer to the argument list for the program. + * Envp - Supplies a pointer to the environment for the program. + * + * Return Value: + * ESUCCESS is returned if the address is invalid. + * EFAULT indicates an invalid address. + * + */ +ARC_STATUS +VrInvoke( + IN ULONG EntryAddress, + IN ULONG StackAddress, + IN ULONG Argc, + IN PCHAR Argv[], + IN PCHAR Envp[] + ) +{ + // + // Check for aligend address. + // + if ((EntryAddress & 0x3) == 0 && (StackAddress & 0x3) == 0) { +#ifdef notdef + free(VrDescriptorMemory); + VrMemoryListOrig = (PVR_MEMORY_DESCRIPTOR)NULL; +#endif // notdef + + PxInvoke(EntryAddress, StackAddress, Argc, Argv, Envp); + } else { + return EFAULT; + } + + return ESUCCESS; +} + + + +/* + * Name: VrExecute + * + * Description: + * This function reads the program specified by ImagePath into memory + * and then starts the program. If the loaded program returns, then + * control returns to the platform firmware, not to the caller. + * + * Arguments: + * ImagePath - Supplies a pointer to the pathname of the program + * to be loaded. + * Argc - Supplies the argument count for the program. + * Argv - Supplies a pointer to the argument list for the program. + * Envp - Supplies a pointer to the environment for the program. + * + * Return Value: + * ESUCCESS is returned if the address is invalid. + * EFAULT indicates an invalid address. + * + */ +ARC_STATUS +VrExecute( + IN PCHAR ImagePath, + IN ULONG Argc, + IN PCHAR Argv[], + IN PCHAR Envp[] + ) +{ + ARC_STATUS Status; + PMEMORY_DESCRIPTOR MemoryDescriptor; + ULONG BottomAddress; + CHAR TempPath[256]; + PULONG TransferRoutine; + + if (strlen(ImagePath) >= sizeof(TempPath)) { + return ENAMETOOLONG; + } + + // + // Copy the Arguments to a safe place as they can be in the running + // program space which can be overwritten by the program about + // to be loaded. + // + (VOID)VrCopyArguments(Argc, Argv); + strcpy(TempPath, ImagePath); + + // + // Reinitialize the memory descriptors + // + VrResetMemory(); + + // + // Look for a piece of free memory. + // + MemoryDescriptor = VrGetMemoryDescriptor(NULL); + while (MemoryDescriptor != NULL ) { + + // + // If the memory is at least 4 megabytes and is free attempt to + // load the program. + // + if ((MemoryDescriptor->MemoryType == MemoryFree) + && (MemoryDescriptor->PageCount >= 1024)) { + + // + // Set the top address to the top of the descriptor. + // + Status = VrLoad(TempPath, + ((MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) + << PAGE_SHIFT), + (PULONG)&TransferRoutine, + &BottomAddress); + + if (Status == ESUCCESS) { + + // + // Find the actual area of memory that was used, and generate + // a descriptor for it. Also, claim the according memory + // from OpenFirmware. + // +#ifdef XXX_MAKE_DESCRIPTOR + MemoryDescriptor = VrGetMemoryDescriptor(NULL); + while (MemoryDescriptor != NULL) { + if ((MemoryDescriptor->MemoryType == MemoryFree) + && (VrActualBasePage >= MemoryDescriptor->BasePage) + && ((VrActualBasePage + VrPageCount) <= + (MemoryDescriptor->BasePage + + MemoryDescriptor->PageCount)) ) { + break; + } + MemoryDescriptor = VrGetMemoryDescriptor(MemoryDescriptor); + } + if (MemoryDescriptor != NULL) { + Status = VrGenerateDescriptor(MemoryDescriptor, +#ifdef EXEC_MEM_TO_LOADED + MemoryLoadedProgram, +#else + MemoryFirmwareTemporary, +#endif // EXEC_MEM_TO_LOADED + VrActualBasePage, + VrPageCount); + if (Status != ESUCCESS) { + return Status; + } +#endif // XXX_MAKE_DESCRIPTOR + + + Status = VrInvoke((ULONG)TransferRoutine, + BottomAddress, + SavedArgs->Argc, + SavedArgs->Argv, + Envp ); +#ifdef EXEC_MEM_TO_LOADED +#else + MemoryDescriptor->MemoryType = MemoryLoadedProgram; +#endif // EXEC_MEM_TO_LOADED + return Status; + +#ifdef XXX_MAKE_DESCRIPTOR + } +#endif // XXX_MAKE_DESCRIPTOR + } + if (Status != ENOMEM) { + return Status; + } + } + + MemoryDescriptor = VrGetMemoryDescriptor(MemoryDescriptor); + } + + return ENOMEM; +} + + +/* + * Name: VrLoadInitialize + * + * Description: + * This routine initializes the firmware load services. + * + * Arguments: + * None. + * + * Return Value: + * None. + * + */ +VOID +VrLoadInitialize( + VOID + ) +{ + debug(VRDBG_ENTRY, "VrLoadInitialize BEGIN....\n"); + (PARC_LOAD_ROUTINE) + SYSTEM_BLOCK->FirmwareVector[LoadRoutine] = VrLoad; + + (PARC_INVOKE_ROUTINE) + SYSTEM_BLOCK->FirmwareVector[InvokeRoutine] = VrInvoke; + + (PARC_EXECUTE_ROUTINE) + SYSTEM_BLOCK->FirmwareVector[ExecuteRoutine] = VrExecute; + + SavedArgs = new(SAVED_ARGUMENTS); + debug(VRDBG_ENTRY, "VrLoadInitialize ....END\n"); +} + + +/* + * Name: VrRelocateImage + * + * Description: + * This function relocates an image file that was not loaded into memory + * at the prefered address. + * + * Arguments: + * FileId - Supplies the file identifier for the image file. + * RelocationTable + * - Supplies a pointer to a table of section relocation info. + * + * Return Value: + * ESUCCESS is returned in the scan if\s successful. Otherwise, return + * an unsuccessful status. + * + */ +STATIC +ARC_STATUS +VrRelocateImage( + IN ULONG FileId, + IN PSECTION_RELOCATION_ENTRY RelocationTable, + IN ULONG NumberOfSections, + IN ULONG PointerToSymbolTable + ) +{ + IMAGE_RELOCATION RelocationEntry; + IMAGE_SYMBOL ImageSymbol; + LARGE_INTEGER SeekPosition; + ULONG Section, Index, Count, Offset; + PULONG FixupAddress; + ARC_STATUS Status; + + // + // Read the relocation table for each section. + // + for (Section = 0; Section < NumberOfSections; Section++) { + for (Index = 0; Index < RelocationTable[Section].NumberOfRelocations; + Index++) { + if (Index == 0) { + SeekPosition.LowPart = + RelocationTable[Section].PointerToRelocations; + SeekPosition.HighPart = 0; + if ((Status = VrSeek(FileId, &SeekPosition, SeekAbsolute)) + != ESUCCESS) { + return Status; + } + } + if ((Status = VrRead(FileId, (PCHAR)&RelocationEntry, + sizeof(RelocationEntry), &Count)) != ESUCCESS) { + return Status; + } + if (Count != sizeof(RelocationEntry)) { + return EBADF; + } + + // + // Get the address for the fixup. + // + FixupAddress = (PULONG)RelocationEntry.VirtualAddress + + RelocationTable[Section].FixupValue; + + // + // Read the symbol table. + // + SeekPosition.LowPart = PointerToSymbolTable + + RelocationEntry.SymbolTableIndex * sizeof(IMAGE_SYMBOL); + if ((Status = VrRead(FileId, (PCHAR)&ImageSymbol, + sizeof(ImageSymbol), &Count)) != ESUCCESS) { + return Status; + } + if (Count != sizeof(ImageSymbol)) { + return EBADF; + } + + // + // Apply the fixup. + // + if (ImageSymbol.StorageClass != IMAGE_SYM_CLASS_EXTERNAL) { + Offset = RelocationTable[ImageSymbol.SectionNumber].FixupValue; + } else { + Offset = 0; + } + + switch (RelocationEntry.Type) { + + // + // Absolute - no fixup required. + // + case IMAGE_REL_PPC_ABSOLUTE: + break; + + // + // 32-bit address - relocate the entire address. + // + case IMAGE_REL_PPC_ADDR32: + *FixupAddress += (ULONG)Offset; + break; + + // + // 26-bit address, 26-bit PC-relative offset + // + case IMAGE_REL_PPC_ADDR24: + case IMAGE_REL_PPC_REL24: + *FixupAddress = ((*FixupAddress) & 0xfc000003) + + ((*FixupAddress) & 0x03fffffc + (Offset << 2)) & 0x03fffffc; + break; + + // + // 16-bit address, 16-bit offset from TOC base + // + case IMAGE_REL_PPC_ADDR16: + case IMAGE_REL_PPC_TOCREL16: + *FixupAddress = ((*FixupAddress) & 0xffff0000) + + ((*FixupAddress) & 0x0000ffff + Offset) & 0x0000ffff; + break; + + // + // 14-bit address, 14-bit PC-relative offset, + // 14-bit offset from TOC base + // + case IMAGE_REL_PPC_ADDR14: + case IMAGE_REL_PPC_REL14: + case IMAGE_REL_PPC_TOCREL14: + *FixupAddress = ((*FixupAddress) & 0xffff0003) + + ((*FixupAddress) & 0x0000fffc + (Offset << 2)) & 0x0000fffc; + break; + + default: + fatal("Veneer: unknown relocation type %d\n", + RelocationEntry.Type); + } + } + } + + return ESUCCESS; +} + + +/* + * Name: VrCopyArguments + * + * Description: + * This routine copies the supplied arguments into the Veneer space. + * + * Arguments: + * Argc, Argv - Supply the arguments to be copied. + * + * Return Value: + * None. + * + */ +STATIC VOID +VrCopyArguments( + IN ULONG Argc, + IN PCHAR Argv[] + ) +{ + PUCHAR Source, Destination; + ULONG Index; + + SavedArgs->Argc = Argc; + Destination = &SavedArgs->Arguments[0]; + for (Index = 0; Index < Argc; Index++) { + Source = Argv[Index]; + SavedArgs->Argv[Index] = Destination; + while (*Destination++ = *Source++) ; + } +} + + +/* + * Name: VrResetMemory + * + * Description: + * This loops through and clears all of the appropriate memory, + * releasing the memory to OpenFirmware, and then calls VrCreateMemory + * to reset the memory descriptors. + * + * Arguments: + * None. + * + * Return Value: + * None. + * + */ +VOID +VrResetMemory( + VOID + ) +{ + PMEMORY_DESCRIPTOR MemoryDescriptor; + PVR_MEMORY_DESCRIPTOR CurDesc, FreeDesc; + + // + // Release all memory not used by the firmware. + // + MemoryDescriptor = VrGetMemoryDescriptor(NULL); + while (MemoryDescriptor != NULL) { + +#ifdef notdef + DisplayMemoryDescriptor(MemoryDescriptor); +#endif // notdef + + if ((MemoryDescriptor->MemoryType == MemoryLoadedProgram) || + (MemoryDescriptor->MemoryType == MemoryFreeContiguous)) { + + bzero((PVOID) (MemoryDescriptor->BasePage << PAGE_SHIFT), + (MemoryDescriptor->PageCount << PAGE_SHIFT)); + + OFRelease((PVOID)(MemoryDescriptor->BasePage << PAGE_SHIFT), + (MemoryDescriptor->PageCount << PAGE_SHIFT)); + } + + MemoryDescriptor = VrGetMemoryDescriptor(MemoryDescriptor); + } + + CurDesc = VrMemoryListOrig; + while(CurDesc != NULL) { + FreeDesc = CurDesc; + CurDesc = CurDesc->NextEntry; + free((char*)FreeDesc); + } + VrMemoryListOrig = (PVR_MEMORY_DESCRIPTOR) NULL; + VrCreateMemoryDescriptors(); +} + + +/* + * Name: VrGenerateDescriptor + * + * Description: + * This routine allocates a new memory descriptor to describe the + * specified region of memory. + * + * Arguments: + * MemoryDescriptor - Supplies a pointer to a free memory descriptor + * from which the specified memory is to be allocated. + * MemoryType - Supplies the type that is assigned to the allocated + * memory. + * BasePage - Supplies the base page number. + * PageCount - Supplies the number of pages. + * + * Return Value: + * + */ +ARC_STATUS +VrGenerateDescriptor( + IN PMEMORY_DESCRIPTOR MemoryDescriptor, + IN MEMORY_TYPE MemoryType, + IN ULONG BasePage, + IN ULONG PageCount + ) +{ + PVR_MEMORY_DESCRIPTOR MemDescriptor, NewDescriptor; + ULONG Offset; + + + MemDescriptor = (PVR_MEMORY_DESCRIPTOR) MemoryDescriptor; + + // + // Claim the memory from OpenFirmware. + // + if ((claim((void *)(BasePage << PAGE_SHIFT), PageCount << PAGE_SHIFT)) + == -1) { + return ENOMEM; + } + + // + // If the specified region totally consumes the free region, then no + // additional descriptors need to be allocated. If the specified region + // is at the start or end of the free region, then only one descriptor + // needs to be allocated. Otherwise, two additional descriptors need to + // be allocated. + // + Offset = BasePage - MemDescriptor->MemoryEntry.BasePage; + if ((Offset == 0) && (PageCount == MemDescriptor->MemoryEntry.PageCount)) { + + // + // The specified region totally consumes the free region. + // + MemDescriptor->MemoryEntry.MemoryType = MemoryType; + + } else { + + // + // A memory descriptor must be generated to describe the allocated + // memory. + // + NewDescriptor = new(VR_MEMORY_DESCRIPTOR); + NewDescriptor->MemoryEntry.MemoryType = MemoryType; + NewDescriptor->MemoryEntry.BasePage = BasePage; + NewDescriptor->MemoryEntry.PageCount = PageCount; + + // + // Insert Memory Descriptor List. + // + InsertMemDescriptor(NewDescriptor); + + // + // Determine whether an additional memory descriptor must be generated. + // + if (BasePage == MemDescriptor->MemoryEntry.BasePage) { + MemDescriptor->MemoryEntry.BasePage += PageCount; + MemDescriptor->MemoryEntry.PageCount -= PageCount; + } else { + if ((Offset + PageCount) == (MemDescriptor->MemoryEntry.BasePage + + MemDescriptor->MemoryEntry.PageCount)) { + + // + // The specified region lies at the end of the free region. + // + MemDescriptor->MemoryEntry.PageCount -= PageCount; + + } else { + + // + // The specified region lies in the middle of the free region. + // Another memory descriptor must be generated. + // + NewDescriptor = new(VR_MEMORY_DESCRIPTOR); + NewDescriptor->MemoryEntry.MemoryType = MemoryFree; + NewDescriptor->MemoryEntry.BasePage = BasePage + PageCount; + NewDescriptor->MemoryEntry.PageCount = + MemDescriptor->MemoryEntry.PageCount - PageCount - Offset; + + // + // Insert Memory Descriptor List. + // + InsertMemDescriptor(NewDescriptor); + + + MemDescriptor->MemoryEntry.PageCount = Offset; + } + } + } + + return ESUCCESS; +} + + +VOID +InsertMemDescriptor( + IN PVR_MEMORY_DESCRIPTOR MemDescriptor + ) +{ + PVR_MEMORY_DESCRIPTOR Entry; + + for (Entry = VrMemoryListOrig; Entry; Entry = Entry->NextEntry) { + if ((Entry->MemoryEntry.BasePage < MemDescriptor->MemoryEntry.BasePage) + && ((Entry->NextEntry == NULL) || + (Entry->NextEntry->MemoryEntry.BasePage > + MemDescriptor->MemoryEntry.BasePage))) { + + MemDescriptor->NextEntry = Entry->NextEntry; + Entry->NextEntry = MemDescriptor; + break; + } + } +} -- cgit v1.2.3