Author: arty
Date: Sun Apr 22 15:05:31 2007
New Revision: 26459
URL:
http://svn.reactos.org/svn/reactos?rev=26459&view=rev
Log:
Load ntoskrnl as elf from disk. This represents a pretty radical
diversion from previous work.
Modified:
branches/powerpc/reactos/boot/freeldr/freeldr/arch/powerpc/boot.s
branches/powerpc/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c
branches/powerpc/reactos/boot/freeldr/freeldr/include/freeldr.h
Modified: branches/powerpc/reactos/boot/freeldr/freeldr/arch/powerpc/boot.s
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/boot/freeldr/fr…
==============================================================================
--- branches/powerpc/reactos/boot/freeldr/freeldr/arch/powerpc/boot.s (original)
+++ branches/powerpc/reactos/boot/freeldr/freeldr/arch/powerpc/boot.s Sun Apr 22 15:05:31
2007
@@ -6,10 +6,9 @@
sync
isync
- lis %r1,stack@ha
- addi %r1,%r1,stack@l
- addi %r1,%r1,16384 - 0x10
-
+ lis %r1,stackend@ha
+ addi %r1,%r1,stackend@l
+
/* Store ofw call addr */
mr %r21,%r5
lis %r10,ofw_call_addr@ha
@@ -89,12 +88,16 @@
.long 0
.long 0
.long 0
-
- .org 0x1000
+
+ .align 4
stack:
.space 0x4000
-
+stackend:
+ .long 0,0,0,0
+
.globl _bss
.section ".bss"
_bss:
.long 0
+
+ .align 4
Modified: branches/powerpc/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/boot/freeldr/fr…
==============================================================================
--- branches/powerpc/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c (original)
+++ branches/powerpc/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c Sun Apr 22 15:05:31
2007
@@ -19,6 +19,8 @@
*/
#include <freeldr.h>
+#include <elf/elf.h>
+#include <elf/reactos.h>
#include <of_call.h>
#include "ppcboot.h"
#include "mmu.h"
@@ -90,6 +92,9 @@
/* Kernel Entrypoint in Physical Memory */
ULONG_PTR KernelEntry;
+
+/* Dummy to bring in memmove */
+PVOID memmove_dummy = memmove;
/* FUNCTIONS *****************************************************************/
@@ -305,6 +310,9 @@
{
PCHAR p;
+ /* Default kernel base at 2GB */
+ KernelBase = 0x80000000;
+
/* Set KernelBase */
LoaderBlock.KernelBase = KernelBase;
@@ -400,171 +408,229 @@
NTAPI
FrLdrMapKernel(FILE *KernelImage)
{
- PIMAGE_DOS_HEADER ImageHeader;
- PIMAGE_NT_HEADERS NtHeader;
+ PIMAGE_DOS_HEADER ImageHeader = 0;
+ PIMAGE_NT_HEADERS NtHeader = 0;
PIMAGE_SECTION_HEADER Section;
ULONG SectionCount;
ULONG ImageSize;
- ULONG_PTR SourceSection;
- ULONG_PTR TargetSection;
- ULONG SectionSize;
- INT i;
- PIMAGE_DATA_DIRECTORY RelocationDDir;
- PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
- ULONG Count;
- ULONG_PTR Address, MaxAddress;
- PUSHORT TypeOffset;
- ULONG_PTR Delta;
- PUSHORT ShortPtr;
- PULONG LongPtr;
+ INT i, j;
PLOADER_MODULE ModuleData;
-
- /* Allocate 1024 bytes for PE Header */
- ImageHeader = (PIMAGE_DOS_HEADER)MmAllocateMemory(1024);
-
- /* Make sure it was succesful */
- if (ImageHeader == NULL) {
-
- return FALSE;
- }
-
- /* Load the first 1024 bytes of the kernel image so we can read the PE header */
- if (!FsReadFile(KernelImage, 1024, NULL, ImageHeader)) {
-
- /* Fail if we couldn't read */
- MmFreeMemory(ImageHeader);
- return FALSE;
- }
-
- /* Now read the MZ header to get the offset to the PE Header */
- NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)ImageHeader + ImageHeader->e_lfanew);
+ int phsize, phnum, shsize, shnum, relsize, SectionAddr = 0;
+ PULONG SectionOffsets;
+ PCHAR sptr;
+ Elf32_Ehdr ehdr;
+ Elf32_Shdr *shdr;
/* Get Kernel Base */
- KernelBase = NtHeader->OptionalHeader.ImageBase;
FrLdrGetKernelBase();
-
- /* Save the Image Size */
- ImageSize = NtHeader->OptionalHeader.SizeOfImage;
-
- /* Free the Header */
- MmFreeMemory(ImageHeader);
-
- /* Set the file pointer to zero */
- FsSetFilePointer(KernelImage, 0);
/* Allocate kernel memory */
KernelMemory = MmAllocateMemory(KernelMemorySize);
-
printf("Kernel Memory @%x\n", (int)KernelMemory);
- /* Save Entrypoint */
- KernelEntry = NtHeader->OptionalHeader.AddressOfEntryPoint;
+ printf("Loading ntoskrnl (elf at %x)\n", KernelBase);
+
+ /* Load the first 1024 bytes of the kernel image so we can read the PE header */
+ if (!FsReadFile(KernelImage, sizeof(ehdr), NULL, &ehdr)) {
+
+ /* Fail if we couldn't read */
+ printf("Couldn't read the elf header\n");
+ return FALSE;
+ }
+
+ printf("Elf header: (%c%c%c type %d machine %d version %d entry %x shoff %x
shentsize %d shnum %d)\n",
+ ehdr.e_ident[1], ehdr.e_ident[2], ehdr.e_ident[3],
+ ehdr.e_type,
+ ehdr.e_machine,
+ ehdr.e_version,
+ ehdr.e_entry,
+ ehdr.e_shoff,
+ ehdr.e_shentsize,
+ ehdr.e_shnum);
+
+ /* Start by getting elf headers */
+ phsize = ehdr.e_phentsize;
+ phnum = ehdr.e_phnum;
+ shsize = ehdr.e_shentsize;
+ shnum = ehdr.e_shnum;
+ sptr = (PCHAR)MmAllocateMemory(shnum * shsize);
+ SectionOffsets = (PULONG)MmAllocateMemory(shnum * sizeof(ULONG));
+
+ /* Read section headers */
+ FsSetFilePointer(KernelImage, ehdr.e_shoff);
+ FsReadFile(KernelImage, shsize * shnum, NULL, sptr);
+
+ printf("Loaded section headers\n");
+
+ /* Now we'll get the PE Header */
+ for( i = 0; i < shnum; i++ )
+ {
+ shdr = (Elf32_Shdr*)(sptr + (i * shsize));
+ printf("Header %d: type %d flags %x\n", i, shdr->sh_type,
shdr->sh_flags);
+ /* Find the PE Header */
+ if (shdr->sh_type == TYPE_PEHEADER)
+ {
+ FsSetFilePointer(KernelImage, shdr->sh_offset);
+ FsReadFile(KernelImage, shdr->sh_size, NULL, KernelMemory);
+ ImageHeader = (PIMAGE_DOS_HEADER)KernelMemory;
+ NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)KernelMemory +
SWAPD(ImageHeader->e_lfanew));
+ printf("NtHeader at %x\n", SWAPD(ImageHeader->e_lfanew));
+ SectionOffsets[i] = 0;
+ printf("SectionAlignment %x\n",
+ SWAPD(NtHeader->OptionalHeader.SectionAlignment));
+ SectionAddr = ROUND_UP
+ (shdr->sh_size, SWAPD(NtHeader->OptionalHeader.SectionAlignment));
+ printf("Header ends at %x\n", SectionAddr);
+ break;
+ }
+ }
+
+ if(i == shnum)
+ {
+ printf("No peheader section encountered :-(\n");
+ return 0;
+ }
+
+ /* Save the Image Size */
+ NtHeader->OptionalHeader.ImageBase = SWAPD(KernelBase);
/* Load the file image */
- FsReadFile(KernelImage, ImageSize, NULL, KernelMemory);
-
- /* Reload the NT Header */
- NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)KernelMemory + ImageHeader->e_lfanew);
-
- /* Load the first section */
Section = IMAGE_FIRST_SECTION(NtHeader);
SectionCount = NtHeader->FileHeader.NumberOfSections - 1;
- /* Now go to the last section */
- Section += SectionCount;
-
- /* Walk each section backwards */
- for (i=(INT)SectionCount; i >= 0; i--, Section--) {
-
- /* Get the disk location and the memory location, and the size */
- SourceSection = RaToPa(Section->PointerToRawData);
- TargetSection = RaToPa(Section->VirtualAddress);
- SectionSize = Section->SizeOfRawData;
-
- /* If the section is already mapped correctly, go to the next */
- if (SourceSection == TargetSection) continue;
-
- /* Load it into memory */
- memmove((PVOID)TargetSection, (PVOID)SourceSection, SectionSize);
-
- /* Check for unitilizated data */
- if (Section->SizeOfRawData < Section->Misc.VirtualSize) {
-
- /* Zero it out */
- memset((PVOID)RaToPa(Section->VirtualAddress +
Section->SizeOfRawData),
- 0,
- Section->Misc.VirtualSize - Section->SizeOfRawData);
+ /* Walk each section */
+ for (i=0; i < SectionCount; i++, Section++)
+ {
+ shdr = (Elf32_Shdr*)(sptr + (i * shsize));
+ if ((shdr->sh_type != SHT_PROGBITS) &&
+ (shdr->sh_type != SHT_NOBITS)) continue;
+
+ SectionOffsets[i] = SectionAddr;
+
+ shdr = (Elf32_Shdr*)(sptr + (i * shsize));
+
+ /* Get the disk location and the memory location, and the size */
+ Section->Misc.VirtualSize = SWAPD(shdr->sh_size);
+ Section->VirtualAddress = SWAPD(SectionAddr);
+ Section->SizeOfRawData = SWAPD(shdr->sh_size);
+ Section->PointerToRawData = SWAPD(shdr->sh_offset);
+
+ if (shdr->sh_type == SHT_PROGBITS)
+ {
+ /* Content area */
+ printf("Loading section %d at %x\n", i, KernelBase + SectionAddr);
+ FsSetFilePointer(KernelImage, shdr->sh_offset);
+ FsReadFile(KernelImage, shdr->sh_size, NULL, KernelMemory + SectionAddr);
+ }
+ else if (shdr->sh_type == SHT_NOBITS)
+ {
+ /* Zero it out */
+ printf("BSS section %d at %x\n", i, KernelBase + SectionAddr);
+ memset(KernelMemory + SectionAddr, 0,
+ ROUND_UP(shdr->sh_size,
+ SWAPD(NtHeader->OptionalHeader.SectionAlignment)));
}
- }
-
- /* Get the Relocation Data Directory */
- RelocationDDir =
&NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
-
- /* Get the Relocation Section Start and End*/
- RelocationDir = (PIMAGE_BASE_RELOCATION)(KernelMemory +
RelocationDDir->VirtualAddress);
- RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir +
RelocationDDir->Size);
-
- /* Calculate Difference between Real Base and Compiled Base*/
- Delta = KernelBase - NtHeader->OptionalHeader.ImageBase;
-
- /* Determine how far we shoudl relocate */
- MaxAddress = (ULONG)KernelMemory + ImageSize;
-
- /* Relocate until we've processed all the blocks */
- while (RelocationDir < RelocationEnd && RelocationDir->SizeOfBlock >
0) {
-
- /* See how many Relocation Blocks we have */
- Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) /
sizeof(USHORT);
-
- /* Calculate the Address of this Directory */
- Address = (ULONG)KernelMemory + RelocationDir->VirtualAddress;
-
- /* Calculate the Offset of the Type */
- TypeOffset = (PUSHORT)(RelocationDir + 1);
-
- for (i = 0; i < (INT)Count; i++) {
-
- ShortPtr = (PUSHORT)(Address + (*TypeOffset & 0xFFF));
-
- switch (*TypeOffset >> 12) {
-
- case IMAGE_REL_BASED_ABSOLUTE:
- break;
-
- case IMAGE_REL_BASED_HIGH:
- *ShortPtr += HIWORD(Delta);
- break;
-
- case IMAGE_REL_BASED_HIGHADJ:
- *ShortPtr +=
- HIWORD(Delta) + ((LOWORD(Delta) & 0x8000) ? 1 : 0);
- break;
-
- case IMAGE_REL_BASED_LOW:
- *ShortPtr += LOWORD(Delta);
- break;
-
- case IMAGE_REL_BASED_HIGHLOW:
- LongPtr = (PULONG)ShortPtr;
- *LongPtr += Delta;
- break;
-
- case IMAGE_REL_BASED_MIPS_JMPADDR:
- LongPtr = (PULONG)ShortPtr;
- *LongPtr = SignExtend24(*LongPtr,Delta);
- break;
-
- default:
- //printf("Unknown relocation %d\n", *TypeOffset >> 12);
- break;
- }
-
- TypeOffset++;
- }
-
- /* Move to the next Relocation Table */
- RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir +
RelocationDir->SizeOfBlock);
- }
+
+ SectionAddr +=
+ ROUND_UP
+ (shdr->sh_size, SWAPD(NtHeader->OptionalHeader.SectionAlignment));
+ }
+
+ ImageSize = SectionAddr;
+ NtHeader->OptionalHeader.SizeOfImage = SWAPD(ImageSize);
+ printf("Total image size is %x\n", ImageSize);
+
+ /* Handle relocation sections */
+ for (Section = IMAGE_FIRST_SECTION(NtHeader), i = 0;
+ i < SectionCount;
+ i++, Section++) {
+ Elf32_Rela reloc = { };
+ ULONG *Target32;
+ USHORT *Target16;
+ int numreloc, relstart, targetSection;
+ Elf32_Sym symbol;
+
+ shdr = (Elf32_Shdr*)(sptr + (i * shsize));
+ /* Only relocs here */
+ if((shdr->sh_type != SHT_REL) &&
+ (shdr->sh_type != SHT_RELA)) continue;
+
+ relstart = shdr->sh_offset;
+ relsize = shdr->sh_type == SHT_RELA ? 12 : 8;
+ numreloc = shdr->sh_size / relsize;
+ targetSection = shdr->sh_info;
+
+ printf("Found reloc section %d (symbols %d target %d)\n",
+ i, shdr->sh_link, shdr->sh_info);
+
+ /* Get the symbol section */
+ shdr = (Elf32_Shdr*)(sptr + (shdr->sh_link * shsize));
+
+ for(j = 0; j < numreloc; j++)
+ {
+ ULONG S,A,P;
+
+ /* Get the reloc */
+ FsSetFilePointer(KernelImage, relstart + (numreloc * relsize));
+ FsReadFile(KernelImage, sizeof(reloc), NULL, &reloc);
+
+ /* Get the symbol */
+ FsSetFilePointer(KernelImage, shdr->sh_offset + ELF32_R_SYM(reloc.r_info) *
sizeof(Elf32_Sym));
+ FsReadFile(KernelImage, sizeof(symbol), NULL, &symbol);
+
+ /* Compute addends */
+ S = symbol.st_value + KernelBase + SectionOffsets[symbol.st_shndx];
+ A = reloc.r_addend;
+ P = reloc.r_offset + KernelBase + SectionOffsets[targetSection];
+
+ Target32 =
+ (ULONG*)(((PCHAR)KernelMemory) + SectionOffsets[targetSection]);
+ Target16 = (USHORT *)Target32;
+
+ switch (ELF32_R_TYPE(reloc.r_info))
+ {
+ case R_PPC_NONE:
+ break;
+ case R_PPC_ADDR32:
+ *Target32 = S + A;
+ break;
+ case R_PPC_UADDR32: /* Special: Treat as RVA */
+ *Target32 = S + A - KernelBase;
+ break;
+ case R_PPC_ADDR24:
+ *Target32 = (ADDR24_MASK & (S+A)) | (*Target32 & ~ADDR24_MASK);
+ break;
+ case R_PPC_REL24:
+ *Target32 = (ADDR24_MASK & (S+A-P)) | (*Target32 & ~ADDR24_MASK);
+ break;
+ case R_PPC_ADDR16_LO:
+ *Target16 = S + A;
+ break;
+ case R_PPC_ADDR16_HA:
+ *Target16 = (S + A + 0x8000) >> 16;
+ break;
+ default:
+ printf("Unknown elf reloc type %x\n", ELF32_R_TYPE(reloc.r_info));
+ break;
+ }
+ }
+ }
+
+#if 0
+ printf("-- Dumping ntoskrnl memory --\n");
+ for (i = 0; i < ImageSize; i++) {
+ if(!(i & 0xf)) {
+ if(i) printf("\n");
+ for (j = 0; j < 8; j++)
+ printf("%x", (((KernelBase + i) << (j * 4)) >> 28) & 0xf);
+ printf(": ");
+ }
+ printf("%x%x ",
+ (*(((PCHAR)KernelMemory)+i)>>4)&0xf,
+ *(((PCHAR)KernelMemory)+i)&0xf);
+ }
+ printf("-- Dump done --\n");
+#endif
ModuleData = &reactos_modules[LoaderBlock.ModsCount];
ModuleData->ModStart = (ULONG)KernelMemory;
Modified: branches/powerpc/reactos/boot/freeldr/freeldr/include/freeldr.h
URL:
http://svn.reactos.org/svn/reactos/branches/powerpc/reactos/boot/freeldr/fr…
==============================================================================
--- branches/powerpc/reactos/boot/freeldr/freeldr/include/freeldr.h (original)
+++ branches/powerpc/reactos/boot/freeldr/freeldr/include/freeldr.h Sun Apr 22 15:05:31
2007
@@ -86,6 +86,8 @@
#include <reactos/helper.h>
/* Needed if debuging is enabled */
#include <comm.h>
+/* endianness utilities */
+#include <bytesex.h>
#define Ke386EraseFlags(x) __asm__ __volatile__("pushl $0 ; popfl\n")