Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmboot.c
Go to the documentation of this file.
00001 /* 00002 * FreeLoader 00003 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com> 00004 * Copyright (C) 2005 Alex Ionescu <alex@relsoft.net> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License along 00017 * with this program; if not, write to the Free Software Foundation, Inc., 00018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00019 */ 00020 00021 #include <freeldr.h> 00022 #include <elf/elf.h> 00023 #include <elf/reactos.h> 00024 #include <of.h> 00025 #include "ppcmmu/mmu.h" 00026 #include "compat.h" 00027 00028 #define NDEBUG 00029 #include <debug.h> 00030 00031 /* We'll check this to see if we're in OFW land */ 00032 extern of_proxy ofproxy; 00033 00034 PVOID KernelMemory = 0; 00035 00036 /* Bits to shift to convert a Virtual Address into an Offset in the Page Table */ 00037 #define PFN_SHIFT 12 00038 00039 /* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */ 00040 #define PDE_SHIFT 22 00041 #define PDE_SHIFT_PAE 18 00042 00043 #define STARTUP_BASE 0xC0000000 00044 #define HYPERSPACE_BASE 0xC0400000 00045 #define HYPERSPACE_PAE_BASE 0xC0800000 00046 #define APIC_BASE 0xFEC00000 00047 #define KPCR_BASE 0xFF000000 00048 00049 #define LowMemPageTableIndex 0 00050 #define StartupPageTableIndex (STARTUP_BASE >> 22) 00051 #define HyperspacePageTableIndex (HYPERSPACE_BASE >> 22) 00052 #define KpcrPageTableIndex (KPCR_BASE >> 22) 00053 #define ApicPageTableIndex (APIC_BASE >> 22) 00054 00055 #define BAT_GRANULARITY (64 * 1024) 00056 #define KernelMemorySize (8 * 1024 * 1024) 00057 #define XROUNDUP(x,n) ((((ULONG)x) + ((n) - 1)) & (~((n) - 1))) 00058 00059 char reactos_module_strings[64][256]; // Array to hold module names 00060 00061 /* Load Address of Next Module */ 00062 ULONG_PTR NextModuleBase = 0; 00063 00064 /* Currently Opened Module */ 00065 PLOADER_MODULE CurrentModule = NULL; 00066 00067 /* Unrelocated Kernel Base in Virtual Memory */ 00068 ULONG_PTR KernelBase; 00069 00070 /* Wether PAE is to be used or not */ 00071 BOOLEAN PaeModeEnabled; 00072 00073 /* Kernel Entrypoint in Physical Memory */ 00074 ULONG_PTR KernelEntryPoint; 00075 00076 /* Dummy to bring in memmove */ 00077 PVOID memmove_dummy = memmove; 00078 00079 PLOADER_MODULE 00080 NTAPI 00081 LdrGetModuleObject(PCHAR ModuleName); 00082 00083 NTSTATUS 00084 NTAPI 00085 LdrPEFixupImports(IN PVOID DllBase, 00086 IN PCHAR DllName); 00087 00088 VOID PpcInitializeMmu(int max); 00089 00090 /* FUNCTIONS *****************************************************************/ 00091 00092 /*++ 00093 * FrLdrStartup 00094 * INTERNAL 00095 * 00096 * Prepares the system for loading the Kernel. 00097 * 00098 * Params: 00099 * Magic - Multiboot Magic 00100 * 00101 * Returns: 00102 * None. 00103 * 00104 * Remarks: 00105 * None. 00106 * 00107 *--*/ 00108 00109 typedef void (*KernelEntryFn)( void * ); 00110 00111 int MmuPageMiss(int trapCode, ppc_trap_frame_t *trap) 00112 { 00113 int i; 00114 printf("TRAP %x\n", trapCode); 00115 for( i = 0; i < 40; i++ ) 00116 printf("r[%d] %x\n", i, trap->gpr[i]); 00117 printf("HALT!\n"); 00118 while(1); 00119 } 00120 00121 typedef struct _ppc_map_set_t { 00122 int mapsize; 00123 int usecount; 00124 ppc_map_info_t *info; 00125 } ppc_map_set_t; 00126 00127 extern int mmu_handle; 00128 paddr_t MmuTranslate(paddr_t possibly_virtual) 00129 { 00130 if (ofproxy) 00131 { 00132 /* Openfirmware takes liberties with boot-time memory. 00133 * if you're in a unitary kernel, it's not as difficult, but since 00134 * we rely on loading things into virtual space from here, we need 00135 * to detect the mappings so far. 00136 */ 00137 int args[2]; 00138 args[0] = possibly_virtual; 00139 args[1] = 1; /* Marker to tell we want a physical addr */ 00140 return (paddr_t)ofw_callmethod_ret("translate", mmu_handle, 2, args, 3); 00141 } 00142 else 00143 { 00144 /* Other booters don't remap ram */ 00145 return possibly_virtual; 00146 } 00147 } 00148 00149 VOID 00150 NTAPI 00151 FrLdrAddPageMapping(ppc_map_set_t *set, int proc, paddr_t phys, vaddr_t virt) 00152 { 00153 int j; 00154 paddr_t page = ROUND_DOWN(phys, (1<<PFN_SHIFT)); 00155 00156 if (virt == 0) 00157 virt = ROUND_DOWN(page, (1<<PFN_SHIFT)); 00158 else 00159 virt = ROUND_DOWN(virt, (1<<PFN_SHIFT)); 00160 00161 page = MmuTranslate(page); 00162 00163 //printf("Mapping virt [%x] to phys [%x (from) %x]\n", virt, page, phys); 00164 00165 for( j = 0; j < set->usecount; j++ ) 00166 { 00167 if(set->info[j].addr == page) return; 00168 } 00169 00170 if (!set->mapsize) 00171 { 00172 set->mapsize = 0x80; 00173 set->info = MmAllocateMemory(0x80 * sizeof(*set->info)); 00174 } 00175 else if (set->mapsize <= set->usecount) 00176 { 00177 ppc_map_info_t *newinfo = MmAllocateMemory(set->mapsize * 2 * sizeof(*set->info)); 00178 memcpy(newinfo, set->info, set->mapsize * sizeof(*set->info)); 00179 MmFreeMemory(set->info); 00180 set->info = newinfo; 00181 set->mapsize *= 2; 00182 } 00183 00184 set->info[set->usecount].flags = MMU_ALL_RW; 00185 set->info[set->usecount].proc = proc; 00186 set->info[set->usecount].addr = virt; 00187 set->info[set->usecount].phys = page; 00188 set->usecount++; 00189 } 00190 00191 extern int _start[], _end[]; 00192 00193 VOID 00194 NTAPI 00195 FrLdrStartup(ULONG Magic) 00196 { 00197 ULONG_PTR i, tmp, OldModCount = 0; 00198 PCHAR ModHeader; 00199 CHAR ModulesTreated[64] = { 0 }; 00200 ULONG NumberOfEntries = 0, UsedEntries = 0; 00201 PPAGE_LOOKUP_TABLE_ITEM FreeLdrMap = MmGetMemoryMap(&NumberOfEntries); 00202 ppc_map_set_t memmap = { }; 00203 00204 printf("FrLdrStartup\n"); 00205 00206 /* Disable EE */ 00207 __asm__("mfmsr %0" : "=r" (tmp)); 00208 tmp &= 0x7fff; 00209 __asm__("mtmsr %0" : : "r" (tmp)); 00210 00211 while(OldModCount != LoaderBlock.ModsCount) 00212 { 00213 printf("Added %d modules last pass\n", 00214 LoaderBlock.ModsCount - OldModCount); 00215 00216 OldModCount = LoaderBlock.ModsCount; 00217 00218 for(i = 0; i < LoaderBlock.ModsCount; i++) 00219 { 00220 if (!ModulesTreated[i]) 00221 { 00222 ModulesTreated[i] = 1; 00223 ModHeader = ((PCHAR)reactos_modules[i].ModStart); 00224 if(ModHeader[0] == 'M' && ModHeader[1] == 'Z') 00225 LdrPEFixupImports 00226 ((PVOID)reactos_modules[i].ModStart, 00227 (PCHAR)reactos_modules[i].String); 00228 } 00229 } 00230 } 00231 00232 printf("Starting mmu\n"); 00233 00234 PpcInitializeMmu(0); 00235 00236 printf("Allocating vsid 0 (kernel)\n"); 00237 MmuAllocVsid(0, 0xff00); 00238 00239 /* We'll use vsid 1 for freeldr (expendable) */ 00240 printf("Allocating vsid 1 (freeldr)\n"); 00241 MmuAllocVsid(1, 0xff); 00242 00243 printf("Mapping Freeldr Code (%x-%x)\n", _start, _end); 00244 00245 /* Map memory zones */ 00246 /* Freeldr itself */ 00247 for( i = (int)_start; 00248 i < (int)_end; 00249 i += (1<<PFN_SHIFT) ) { 00250 FrLdrAddPageMapping(&memmap, 1, i, 0); 00251 } 00252 00253 printf("KernelBase %x\n", KernelBase); 00254 00255 /* Heap pages -- this gets the entire freeldr heap */ 00256 for( i = 0; i < NumberOfEntries; i++ ) { 00257 tmp = i<<PFN_SHIFT; 00258 if (FreeLdrMap[i].PageAllocated == LoaderSystemCode) { 00259 UsedEntries++; 00260 if (tmp >= (ULONG)KernelMemory && 00261 tmp < (ULONG)KernelMemory + KernelMemorySize) { 00262 FrLdrAddPageMapping(&memmap, 0, tmp, KernelBase + tmp - (ULONG)KernelMemory); 00263 } else { 00264 FrLdrAddPageMapping(&memmap, 1, tmp, 0); 00265 } 00266 } 00267 } 00268 00269 MmuMapPage(memmap.info, memmap.usecount); 00270 00271 printf("Finished Mapping the Freeldr Heap (used %d pages)\n", UsedEntries); 00272 00273 printf("Setting initial segments\n"); 00274 MmuSetVsid(0, 8, 1); 00275 MmuSetVsid(8, 16, 0); 00276 00277 printf("Segments set!\n"); 00278 00279 MmuTurnOn((KernelEntryFn)KernelEntryPoint, &LoaderBlock); 00280 00281 /* Nothing more */ 00282 while(1); 00283 } 00284 00285 /*++ 00286 * FrLdrSetupPae 00287 * INTERNAL 00288 * 00289 * Configures PAE on a MP System, and sets the PDBR if it's supported, or if 00290 * the system is UP. 00291 * 00292 * Params: 00293 * Magic - Multiboot Magic 00294 * 00295 * Returns: 00296 * None. 00297 * 00298 * Remarks: 00299 * None. 00300 * 00301 *--*/ 00302 VOID 00303 FASTCALL 00304 FrLdrSetupPae(ULONG Magic) 00305 { 00306 } 00307 00308 /*++ 00309 * FrLdrGetKernelBase 00310 * INTERNAL 00311 * 00312 * Gets the Kernel Base to use. 00313 * 00314 * Params: 00315 * 00316 * Returns: 00317 * None. 00318 * 00319 * Remarks: 00320 * Sets both the FreeLdr internal variable as well as the one which 00321 * will be used by the Kernel. 00322 * 00323 *--*/ 00324 VOID 00325 FASTCALL 00326 FrLdrGetKernelBase(VOID) 00327 { 00328 PCHAR p; 00329 00330 /* Default kernel base at 2GB */ 00331 KernelBase = 0x80800000; 00332 00333 /* Set KernelBase */ 00334 LoaderBlock.KernelBase = 0x80000000; 00335 00336 /* Read Command Line */ 00337 p = (PCHAR)LoaderBlock.CommandLine; 00338 while ((p = strchr(p, '/')) != NULL) { 00339 00340 /* Find "/3GB" */ 00341 if (!_strnicmp(p + 1, "3GB", 3)) { 00342 00343 /* Make sure there's nothing following it */ 00344 if (p[4] == ' ' || p[4] == 0) { 00345 00346 /* Use 3GB */ 00347 KernelBase = 0xE0000000; 00348 LoaderBlock.KernelBase = 0xC0000000; 00349 } 00350 } 00351 00352 p++; 00353 } 00354 } 00355 00356 /*++ 00357 * FrLdrGetPaeMode 00358 * INTERNAL 00359 * 00360 * Determines whether PAE mode shoudl be enabled or not. 00361 * 00362 * Params: 00363 * None. 00364 * 00365 * Returns: 00366 * None. 00367 * 00368 * Remarks: 00369 * None. 00370 * 00371 *--*/ 00372 VOID 00373 FASTCALL 00374 FrLdrGetPaeMode(VOID) 00375 { 00376 } 00377 00378 /*++ 00379 * FrLdrSetupPageDirectory 00380 * INTERNAL 00381 * 00382 * Sets up the ReactOS Startup Page Directory. 00383 * 00384 * Params: 00385 * None. 00386 * 00387 * Returns: 00388 * None. 00389 * 00390 * Remarks: 00391 * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure. 00392 * As such, please note that PageFrameNumber == PageEntryNumber. 00393 * 00394 *--*/ 00395 VOID 00396 FASTCALL 00397 FrLdrSetupPageDirectory(VOID) 00398 { 00399 } 00400 00401 /*++ 00402 * FrLdrMapModule 00403 * INTERNAL 00404 * 00405 * Loads the indicated elf image as PE. The target will appear to be 00406 * a PE image whose ImageBase has ever been KernelAddr. 00407 * 00408 * Params: 00409 * Image -- File to load 00410 * ImageName -- Name of image for the modules list 00411 * MemLoadAddr -- Freeldr address of module 00412 * KernelAddr -- Kernel address of module 00413 *--*/ 00414 #define ELF_SECTION(n) ((Elf32_Shdr*)(sptr + (n * shsize))) 00415 #define COFF_FIRST_SECTION(h) ((PIMAGE_SECTION_HEADER) ((DWORD)h+FIELD_OFFSET(IMAGE_NT_HEADERS,OptionalHeader)+(SWAPW(((PIMAGE_NT_HEADERS)(h))->FileHeader.SizeOfOptionalHeader)))) 00416 00417 BOOLEAN 00418 NTAPI 00419 FrLdrMapModule(FILE *KernelImage, PCHAR ImageName, PCHAR MemLoadAddr, ULONG KernelAddr) 00420 { 00421 PIMAGE_DOS_HEADER ImageHeader = 0; 00422 PIMAGE_NT_HEADERS NtHeader = 0; 00423 PIMAGE_SECTION_HEADER Section; 00424 ULONG SectionCount; 00425 ULONG ImageSize; 00426 INT i, j; 00427 PLOADER_MODULE ModuleData; 00428 //int phsize, phnum; 00429 int shsize, shnum, relsize, SectionAddr = 0; 00430 PCHAR sptr; 00431 Elf32_Ehdr ehdr; 00432 Elf32_Shdr *shdr; 00433 LPSTR TempName; 00434 00435 TempName = strrchr(ImageName, '\\'); 00436 if(TempName) TempName++; else TempName = (LPSTR)ImageName; 00437 ModuleData = LdrGetModuleObject(TempName); 00438 00439 if(ModuleData) 00440 { 00441 return TRUE; 00442 } 00443 00444 if(!KernelAddr) 00445 KernelAddr = (ULONG)NextModuleBase - (ULONG)KernelMemory + KernelBase; 00446 if(!MemLoadAddr) 00447 MemLoadAddr = (PCHAR)NextModuleBase; 00448 00449 ModuleData = &reactos_modules[LoaderBlock.ModsCount]; 00450 //printf("Loading file (elf at %x)\n", KernelAddr); 00451 00452 /* Load the first 1024 bytes of the kernel image so we can read the PE header */ 00453 if (!FsReadFile(KernelImage, sizeof(ehdr), NULL, &ehdr)) { 00454 00455 /* Fail if we couldn't read */ 00456 printf("Couldn't read the elf header\n"); 00457 return FALSE; 00458 } 00459 00460 /* Start by getting elf headers */ 00461 //phsize = ehdr.e_phentsize; 00462 //phnum = ehdr.e_phnum; 00463 shsize = ehdr.e_shentsize; 00464 shnum = ehdr.e_shnum; 00465 sptr = (PCHAR)MmHeapAlloc(shnum * shsize); 00466 00467 /* Read section headers */ 00468 FsSetFilePointer(KernelImage, ehdr.e_shoff); 00469 FsReadFile(KernelImage, shsize * shnum, NULL, sptr); 00470 00471 /* Now we'll get the PE Header */ 00472 for( i = 0; i < shnum; i++ ) 00473 { 00474 shdr = ELF_SECTION(i); 00475 shdr->sh_addr = 0; 00476 00477 /* Find the PE Header */ 00478 if (shdr->sh_type == TYPE_PEHEADER) 00479 { 00480 FsSetFilePointer(KernelImage, shdr->sh_offset); 00481 FsReadFile(KernelImage, shdr->sh_size, NULL, MemLoadAddr); 00482 ImageHeader = (PIMAGE_DOS_HEADER)MemLoadAddr; 00483 NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)MemLoadAddr + SWAPD(ImageHeader->e_lfanew)); 00484 #if 0 00485 printf("NtHeader at %x\n", SWAPD(ImageHeader->e_lfanew)); 00486 printf("SectionAlignment %x\n", 00487 SWAPD(NtHeader->OptionalHeader.SectionAlignment)); 00488 SectionAddr = ROUND_UP 00489 (shdr->sh_size, SWAPD(NtHeader->OptionalHeader.SectionAlignment)); 00490 printf("Header ends at %x\n", SectionAddr); 00491 #endif 00492 break; 00493 } 00494 } 00495 00496 if(i == shnum) 00497 { 00498 printf("No peheader section encountered :-(\n"); 00499 return 0; 00500 } 00501 #if 0 00502 else 00503 { 00504 printf("DOS SIG: %s\n", (PCHAR)MemLoadAddr); 00505 } 00506 #endif 00507 00508 /* Save the Image Base */ 00509 NtHeader->OptionalHeader.ImageBase = SWAPD(KernelAddr); 00510 00511 /* Load the file image */ 00512 Section = COFF_FIRST_SECTION(NtHeader); 00513 SectionCount = SWAPW(NtHeader->FileHeader.NumberOfSections); 00514 00515 /* Walk each section */ 00516 for (i=0; i < SectionCount; i++, Section++) 00517 { 00518 shdr = ELF_SECTION((SWAPD(Section->PointerToRawData)+1)); 00519 00520 shdr->sh_addr = SectionAddr = SWAPD(Section->VirtualAddress); 00521 shdr->sh_addr += KernelAddr; 00522 00523 Section->PointerToRawData = SWAPD((Section->VirtualAddress - KernelAddr)); 00524 00525 if (shdr->sh_type != SHT_NOBITS) 00526 { 00527 /* Content area */ 00528 printf("Loading section %d at %x (real: %x:%d)\n", i, KernelAddr + SectionAddr, MemLoadAddr+SectionAddr, shdr->sh_size); 00529 FsSetFilePointer(KernelImage, shdr->sh_offset); 00530 FsReadFile(KernelImage, shdr->sh_size, NULL, MemLoadAddr + SectionAddr); 00531 } 00532 else 00533 { 00534 /* Zero it out */ 00535 printf("BSS section %d at %x\n", i, KernelAddr + SectionAddr); 00536 memset(MemLoadAddr + SectionAddr, 0, 00537 ROUND_UP(shdr->sh_size, 00538 SWAPD(NtHeader->OptionalHeader.SectionAlignment))); 00539 } 00540 } 00541 00542 ImageSize = SWAPD(NtHeader->OptionalHeader.SizeOfImage); 00543 printf("Total image size is %x\n", ImageSize); 00544 00545 /* Handle relocation sections */ 00546 for (i = 0; i < shnum; i++) { 00547 Elf32_Rela reloc = { }; 00548 ULONG *Target32; 00549 USHORT *Target16; 00550 int numreloc, relstart, targetSection; 00551 Elf32_Sym symbol; 00552 PCHAR RelocSection, SymbolSection; 00553 00554 shdr = ELF_SECTION(i); 00555 /* Only relocs here */ 00556 if((shdr->sh_type != SHT_REL) && 00557 (shdr->sh_type != SHT_RELA)) continue; 00558 00559 relstart = shdr->sh_offset; 00560 relsize = shdr->sh_type == SHT_RELA ? 12 : 8; 00561 numreloc = shdr->sh_size / relsize; 00562 targetSection = shdr->sh_info; 00563 00564 if (!ELF_SECTION(targetSection)->sh_addr) continue; 00565 00566 RelocSection = MmHeapAlloc(shdr->sh_size); 00567 FsSetFilePointer(KernelImage, relstart); 00568 FsReadFile(KernelImage, shdr->sh_size, NULL, RelocSection); 00569 00570 /* Get the symbol section */ 00571 shdr = ELF_SECTION(shdr->sh_link); 00572 00573 SymbolSection = MmHeapAlloc(shdr->sh_size); 00574 FsSetFilePointer(KernelImage, shdr->sh_offset); 00575 FsReadFile(KernelImage, shdr->sh_size, NULL, SymbolSection); 00576 00577 for(j = 0; j < numreloc; j++) 00578 { 00579 ULONG S,A,P; 00580 00581 /* Get the reloc */ 00582 memcpy(&reloc, RelocSection + (j * relsize), sizeof(reloc)); 00583 00584 /* Get the symbol */ 00585 memcpy(&symbol, SymbolSection + (ELF32_R_SYM(reloc.r_info) * sizeof(symbol)), sizeof(symbol)); 00586 00587 /* Compute addends */ 00588 S = symbol.st_value + ELF_SECTION(symbol.st_shndx)->sh_addr; 00589 A = reloc.r_addend; 00590 P = reloc.r_offset + ELF_SECTION(targetSection)->sh_addr; 00591 00592 #if 0 00593 printf("Symbol[%d] %d -> %d(%x:%x) -> %x(+%x)@%x\n", 00594 ELF32_R_TYPE(reloc.r_info), 00595 ELF32_R_SYM(reloc.r_info), 00596 symbol.st_shndx, 00597 ELF_SECTION(symbol.st_shndx)->sh_addr, 00598 symbol.st_value, 00599 S, 00600 A, 00601 P); 00602 #endif 00603 00604 Target32 = (ULONG*)(((PCHAR)MemLoadAddr) + (P - KernelAddr)); 00605 Target16 = (USHORT *)Target32; 00606 00607 switch (ELF32_R_TYPE(reloc.r_info)) 00608 { 00609 case R_PPC_NONE: 00610 break; 00611 case R_PPC_ADDR32: 00612 *Target32 = S + A; 00613 break; 00614 case R_PPC_REL32: 00615 *Target32 = S + A - P; 00616 break; 00617 case R_PPC_UADDR32: /* Special: Treat as RVA */ 00618 *Target32 = S + A - KernelAddr; 00619 break; 00620 case R_PPC_ADDR24: 00621 *Target32 = (ADDR24_MASK & (S+A)) | (*Target32 & ~ADDR24_MASK); 00622 break; 00623 case R_PPC_REL24: 00624 *Target32 = (ADDR24_MASK & (S+A-P)) | (*Target32 & ~ADDR24_MASK); 00625 break; 00626 case R_PPC_ADDR16_LO: 00627 *Target16 = S + A; 00628 break; 00629 case R_PPC_ADDR16_HA: 00630 *Target16 = (S + A + 0x8000) >> 16; 00631 break; 00632 default: 00633 break; 00634 } 00635 00636 #if 0 00637 printf("reloc[%d:%x]: (type %x sym %d val %d) off %x add %x (old %x new %x)\n", 00638 j, 00639 ((ULONG)Target32) - ((ULONG)MemLoadAddr), 00640 ELF32_R_TYPE(reloc.r_info), 00641 ELF32_R_SYM(reloc.r_info), 00642 symbol.st_value, 00643 reloc.r_offset, reloc.r_addend, 00644 x, *Target32); 00645 #endif 00646 } 00647 00648 MmHeapFree(SymbolSection); 00649 MmHeapFree(RelocSection); 00650 } 00651 00652 MmHeapFree(sptr); 00653 00654 ModuleData->ModStart = (ULONG)MemLoadAddr; 00655 /* Increase the next Load Base */ 00656 NextModuleBase = ROUND_UP((ULONG)MemLoadAddr + ImageSize, PAGE_SIZE); 00657 ModuleData->ModEnd = NextModuleBase; 00658 ModuleData->String = (ULONG)MmAllocateMemory(strlen(ImageName)+1); 00659 strcpy((PCHAR)ModuleData->String, ImageName); 00660 printf("Module %s (%x-%x) next at %x\n", 00661 ModuleData->String, 00662 ModuleData->ModStart, 00663 ModuleData->ModEnd, 00664 NextModuleBase); 00665 LoaderBlock.ModsCount++; 00666 00667 /* Return Success */ 00668 return TRUE; 00669 } 00670 00671 /*++ 00672 * FrLdrMapKernel 00673 * INTERNAL 00674 * 00675 * Maps the Kernel into memory, does PE Section Mapping, initalizes the 00676 * uninitialized data sections, and relocates the image. 00677 * 00678 * Params: 00679 * KernelImage - FILE Structure representing the ntoskrnl image file. 00680 * 00681 * Returns: 00682 * TRUE if the Kernel was mapped. 00683 * 00684 * Remarks: 00685 * None. 00686 * 00687 *--*/ 00688 BOOLEAN 00689 NTAPI 00690 FrLdrMapKernel(FILE *KernelImage) 00691 { 00692 /* Get Kernel Base */ 00693 FrLdrGetKernelBase(); 00694 00695 /* Allocate kernel memory */ 00696 KernelMemory = MmAllocateMemory(KernelMemorySize); 00697 00698 return FrLdrMapModule(KernelImage, "ntoskrnl.exe", KernelMemory, KernelBase); 00699 } 00700 00701 ULONG_PTR 00702 NTAPI 00703 FrLdrLoadModule(FILE *ModuleImage, 00704 LPCSTR ModuleName, 00705 PULONG ModuleSize) 00706 { 00707 ULONG LocalModuleSize; 00708 ULONG_PTR ThisModuleBase = NextModuleBase; 00709 PLOADER_MODULE ModuleData; 00710 LPSTR NameBuffer; 00711 LPSTR TempName; 00712 00713 /* Get current module data structure and module name string array */ 00714 ModuleData = &reactos_modules[LoaderBlock.ModsCount]; 00715 00716 /* Get only the Module Name */ 00717 do { 00718 00719 TempName = strchr(ModuleName, '\\'); 00720 00721 if(TempName) { 00722 ModuleName = TempName + 1; 00723 } 00724 00725 } while(TempName); 00726 NameBuffer = reactos_module_strings[LoaderBlock.ModsCount]; 00727 00728 00729 /* Get Module Size */ 00730 LocalModuleSize = FsGetFileSize(ModuleImage); 00731 00732 /* Fill out Module Data Structure */ 00733 ModuleData->ModStart = NextModuleBase; 00734 ModuleData->ModEnd = NextModuleBase + LocalModuleSize; 00735 00736 /* Save name */ 00737 strcpy(NameBuffer, ModuleName); 00738 ModuleData->String = (ULONG_PTR)NameBuffer; 00739 00740 /* Load the file image */ 00741 FsReadFile(ModuleImage, LocalModuleSize, NULL, (PVOID)NextModuleBase); 00742 00743 /* Move to next memory block and increase Module Count */ 00744 NextModuleBase = ROUND_UP(ModuleData->ModEnd, PAGE_SIZE); 00745 LoaderBlock.ModsCount++; 00746 00747 /* Return Module Size if required */ 00748 if (ModuleSize != NULL) { 00749 *ModuleSize = LocalModuleSize; 00750 } 00751 00752 printf("Module %s (%x-%x) next at %x\n", 00753 ModuleData->String, 00754 ModuleData->ModStart, 00755 ModuleData->ModEnd, 00756 NextModuleBase); 00757 00758 return ThisModuleBase; 00759 } 00760 00761 PVOID 00762 NTAPI 00763 FrLdrMapImage(IN FILE *Image, IN PCHAR ShortName, IN ULONG ImageType) 00764 { 00765 PVOID Result = NULL; 00766 00767 printf("Loading image %s (type %d)\n", ShortName, ImageType); 00768 00769 if (ImageType == 1) 00770 { 00771 if(FrLdrMapKernel(Image)) 00772 Result = (PVOID)KernelMemory; 00773 } 00774 else 00775 { 00776 PVOID ModuleBase = (PVOID)NextModuleBase; 00777 00778 if(FrLdrMapModule(Image, ShortName, 0, 0)) 00779 Result = ModuleBase; 00780 } 00781 return Result; 00782 } 00783 00784 ULONG_PTR 00785 NTAPI 00786 FrLdrCreateModule(LPCSTR ModuleName) 00787 { 00788 PLOADER_MODULE ModuleData; 00789 LPSTR NameBuffer; 00790 00791 /* Get current module data structure and module name string array */ 00792 ModuleData = &reactos_modules[LoaderBlock.ModsCount]; 00793 NameBuffer = reactos_module_strings[LoaderBlock.ModsCount]; 00794 00795 /* Set up the structure */ 00796 ModuleData->ModStart = NextModuleBase; 00797 ModuleData->ModEnd = -1; 00798 00799 /* Copy the name */ 00800 strcpy(NameBuffer, ModuleName); 00801 ModuleData->String = (ULONG_PTR)NameBuffer; 00802 00803 /* Set the current Module */ 00804 CurrentModule = ModuleData; 00805 00806 /* Return Module Base Address */ 00807 return(ModuleData->ModStart); 00808 } 00809 00810 BOOLEAN 00811 NTAPI 00812 FrLdrCloseModule(ULONG_PTR ModuleBase, 00813 ULONG ModuleSize) 00814 { 00815 PLOADER_MODULE ModuleData = CurrentModule; 00816 00817 /* Make sure a module is opened */ 00818 if (ModuleData) { 00819 00820 /* Make sure this is the right module and that it hasn't been closed */ 00821 if ((ModuleBase == ModuleData->ModStart) && (ModuleData->ModEnd == MAXULONG_PTR)) { 00822 00823 /* Close the Module */ 00824 ModuleData->ModEnd = ModuleData->ModStart + ModuleSize; 00825 00826 /* Set the next Module Base and increase the number of modules */ 00827 NextModuleBase = ROUND_UP(ModuleData->ModEnd, PAGE_SIZE); 00828 LoaderBlock.ModsCount++; 00829 00830 /* Close the currently opened module */ 00831 CurrentModule = NULL; 00832 00833 /* Success */ 00834 return(TRUE); 00835 } 00836 } 00837 00838 /* Failure path */ 00839 return(FALSE); 00840 } Generated on Sat May 26 2012 04:17:54 for ReactOS by
1.7.6.1
|