* Sync up to trunk r55544.
[reactos.git] / boot / freeldr / freeldr / arch / powerpc / mboot.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 * Copyright (C) 2005 Alex Ionescu <alex@relsoft.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include <freeldr.h>
22 #include <elf/elf.h>
23 #include <elf/reactos.h>
24 #include <of.h>
25 #include "ppcmmu/mmu.h"
26 #include "compat.h"
27
28 #define NDEBUG
29 #include <debug.h>
30
31 /* We'll check this to see if we're in OFW land */
32 extern of_proxy ofproxy;
33
34 PVOID KernelMemory = 0;
35
36 /* Bits to shift to convert a Virtual Address into an Offset in the Page Table */
37 #define PFN_SHIFT 12
38
39 /* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */
40 #define PDE_SHIFT 22
41 #define PDE_SHIFT_PAE 18
42
43 #define STARTUP_BASE 0xC0000000
44 #define HYPERSPACE_BASE 0xC0400000
45 #define HYPERSPACE_PAE_BASE 0xC0800000
46 #define APIC_BASE 0xFEC00000
47 #define KPCR_BASE 0xFF000000
48
49 #define LowMemPageTableIndex 0
50 #define StartupPageTableIndex (STARTUP_BASE >> 22)
51 #define HyperspacePageTableIndex (HYPERSPACE_BASE >> 22)
52 #define KpcrPageTableIndex (KPCR_BASE >> 22)
53 #define ApicPageTableIndex (APIC_BASE >> 22)
54
55 #define BAT_GRANULARITY (64 * 1024)
56 #define KernelMemorySize (8 * 1024 * 1024)
57 #define XROUNDUP(x,n) ((((ULONG)x) + ((n) - 1)) & (~((n) - 1)))
58
59 char reactos_module_strings[64][256]; // Array to hold module names
60
61 /* Load Address of Next Module */
62 ULONG_PTR NextModuleBase = 0;
63
64 /* Currently Opened Module */
65 PLOADER_MODULE CurrentModule = NULL;
66
67 /* Unrelocated Kernel Base in Virtual Memory */
68 ULONG_PTR KernelBase;
69
70 /* Wether PAE is to be used or not */
71 BOOLEAN PaeModeEnabled;
72
73 /* Kernel Entrypoint in Physical Memory */
74 ULONG_PTR KernelEntryPoint;
75
76 /* Dummy to bring in memmove */
77 PVOID memmove_dummy = memmove;
78
79 PLOADER_MODULE
80 NTAPI
81 LdrGetModuleObject(PCHAR ModuleName);
82
83 NTSTATUS
84 NTAPI
85 LdrPEFixupImports(IN PVOID DllBase,
86 IN PCHAR DllName);
87
88 VOID PpcInitializeMmu(int max);
89
90 /* FUNCTIONS *****************************************************************/
91
92 /*++
93 * FrLdrStartup
94 * INTERNAL
95 *
96 * Prepares the system for loading the Kernel.
97 *
98 * Params:
99 * Magic - Multiboot Magic
100 *
101 * Returns:
102 * None.
103 *
104 * Remarks:
105 * None.
106 *
107 *--*/
108
109 typedef void (*KernelEntryFn)( void * );
110
111 int MmuPageMiss(int trapCode, ppc_trap_frame_t *trap)
112 {
113 int i;
114 printf("TRAP %x\n", trapCode);
115 for( i = 0; i < 40; i++ )
116 printf("r[%d] %x\n", i, trap->gpr[i]);
117 printf("HALT!\n");
118 while(1);
119 }
120
121 typedef struct _ppc_map_set_t {
122 int mapsize;
123 int usecount;
124 ppc_map_info_t *info;
125 } ppc_map_set_t;
126
127 extern int mmu_handle;
128 paddr_t MmuTranslate(paddr_t possibly_virtual)
129 {
130 if (ofproxy)
131 {
132 /* Openfirmware takes liberties with boot-time memory.
133 * if you're in a unitary kernel, it's not as difficult, but since
134 * we rely on loading things into virtual space from here, we need
135 * to detect the mappings so far.
136 */
137 int args[2];
138 args[0] = possibly_virtual;
139 args[1] = 1; /* Marker to tell we want a physical addr */
140 return (paddr_t)ofw_callmethod_ret("translate", mmu_handle, 2, args, 3);
141 }
142 else
143 {
144 /* Other booters don't remap ram */
145 return possibly_virtual;
146 }
147 }
148
149 VOID
150 NTAPI
151 FrLdrAddPageMapping(ppc_map_set_t *set, int proc, paddr_t phys, vaddr_t virt)
152 {
153 int j;
154 paddr_t page = ROUND_DOWN(phys, (1<<PFN_SHIFT));
155
156 if (virt == 0)
157 virt = ROUND_DOWN(page, (1<<PFN_SHIFT));
158 else
159 virt = ROUND_DOWN(virt, (1<<PFN_SHIFT));
160
161 page = MmuTranslate(page);
162
163 //printf("Mapping virt [%x] to phys [%x (from) %x]\n", virt, page, phys);
164
165 for( j = 0; j < set->usecount; j++ )
166 {
167 if(set->info[j].addr == page) return;
168 }
169
170 if (!set->mapsize)
171 {
172 set->mapsize = 0x80;
173 set->info = MmAllocateMemory(0x80 * sizeof(*set->info));
174 }
175 else if (set->mapsize <= set->usecount)
176 {
177 ppc_map_info_t *newinfo = MmAllocateMemory(set->mapsize * 2 * sizeof(*set->info));
178 memcpy(newinfo, set->info, set->mapsize * sizeof(*set->info));
179 MmFreeMemory(set->info);
180 set->info = newinfo;
181 set->mapsize *= 2;
182 }
183
184 set->info[set->usecount].flags = MMU_ALL_RW;
185 set->info[set->usecount].proc = proc;
186 set->info[set->usecount].addr = virt;
187 set->info[set->usecount].phys = page;
188 set->usecount++;
189 }
190
191 extern int _start[], _end[];
192
193 VOID
194 NTAPI
195 FrLdrStartup(ULONG Magic)
196 {
197 ULONG_PTR i, tmp, OldModCount = 0;
198 PCHAR ModHeader;
199 CHAR ModulesTreated[64] = { 0 };
200 ULONG NumberOfEntries = 0, UsedEntries = 0;
201 PPAGE_LOOKUP_TABLE_ITEM FreeLdrMap = MmGetMemoryMap(&NumberOfEntries);
202 ppc_map_set_t memmap = { };
203
204 printf("FrLdrStartup\n");
205
206 /* Disable EE */
207 __asm__("mfmsr %0" : "=r" (tmp));
208 tmp &= 0x7fff;
209 __asm__("mtmsr %0" : : "r" (tmp));
210
211 while(OldModCount != LoaderBlock.ModsCount)
212 {
213 printf("Added %d modules last pass\n",
214 LoaderBlock.ModsCount - OldModCount);
215
216 OldModCount = LoaderBlock.ModsCount;
217
218 for(i = 0; i < LoaderBlock.ModsCount; i++)
219 {
220 if (!ModulesTreated[i])
221 {
222 ModulesTreated[i] = 1;
223 ModHeader = ((PCHAR)reactos_modules[i].ModStart);
224 if(ModHeader[0] == 'M' && ModHeader[1] == 'Z')
225 LdrPEFixupImports
226 ((PVOID)reactos_modules[i].ModStart,
227 (PCHAR)reactos_modules[i].String);
228 }
229 }
230 }
231
232 printf("Starting mmu\n");
233
234 PpcInitializeMmu(0);
235
236 printf("Allocating vsid 0 (kernel)\n");
237 MmuAllocVsid(0, 0xff00);
238
239 /* We'll use vsid 1 for freeldr (expendable) */
240 printf("Allocating vsid 1 (freeldr)\n");
241 MmuAllocVsid(1, 0xff);
242
243 printf("Mapping Freeldr Code (%x-%x)\n", _start, _end);
244
245 /* Map memory zones */
246 /* Freeldr itself */
247 for( i = (int)_start;
248 i < (int)_end;
249 i += (1<<PFN_SHIFT) ) {
250 FrLdrAddPageMapping(&memmap, 1, i, 0);
251 }
252
253 printf("KernelBase %x\n", KernelBase);
254
255 /* Heap pages -- this gets the entire freeldr heap */
256 for( i = 0; i < NumberOfEntries; i++ ) {
257 tmp = i<<PFN_SHIFT;
258 if (FreeLdrMap[i].PageAllocated == LoaderSystemCode) {
259 UsedEntries++;
260 if (tmp >= (ULONG)KernelMemory &&
261 tmp < (ULONG)KernelMemory + KernelMemorySize) {
262 FrLdrAddPageMapping(&memmap, 0, tmp, KernelBase + tmp - (ULONG)KernelMemory);
263 } else {
264 FrLdrAddPageMapping(&memmap, 1, tmp, 0);
265 }
266 }
267 }
268
269 MmuMapPage(memmap.info, memmap.usecount);
270
271 printf("Finished Mapping the Freeldr Heap (used %d pages)\n", UsedEntries);
272
273 printf("Setting initial segments\n");
274 MmuSetVsid(0, 8, 1);
275 MmuSetVsid(8, 16, 0);
276
277 printf("Segments set!\n");
278
279 MmuTurnOn((KernelEntryFn)KernelEntryPoint, &LoaderBlock);
280
281 /* Nothing more */
282 while(1);
283 }
284
285 /*++
286 * FrLdrSetupPae
287 * INTERNAL
288 *
289 * Configures PAE on a MP System, and sets the PDBR if it's supported, or if
290 * the system is UP.
291 *
292 * Params:
293 * Magic - Multiboot Magic
294 *
295 * Returns:
296 * None.
297 *
298 * Remarks:
299 * None.
300 *
301 *--*/
302 VOID
303 FASTCALL
304 FrLdrSetupPae(ULONG Magic)
305 {
306 }
307
308 /*++
309 * FrLdrGetKernelBase
310 * INTERNAL
311 *
312 * Gets the Kernel Base to use.
313 *
314 * Params:
315 *
316 * Returns:
317 * None.
318 *
319 * Remarks:
320 * Sets both the FreeLdr internal variable as well as the one which
321 * will be used by the Kernel.
322 *
323 *--*/
324 VOID
325 FASTCALL
326 FrLdrGetKernelBase(VOID)
327 {
328 PCHAR p;
329
330 /* Default kernel base at 2GB */
331 KernelBase = 0x80800000;
332
333 /* Set KernelBase */
334 LoaderBlock.KernelBase = 0x80000000;
335
336 /* Read Command Line */
337 p = (PCHAR)LoaderBlock.CommandLine;
338 while ((p = strchr(p, '/')) != NULL) {
339
340 /* Find "/3GB" */
341 if (!_strnicmp(p + 1, "3GB", 3)) {
342
343 /* Make sure there's nothing following it */
344 if (p[4] == ' ' || p[4] == 0) {
345
346 /* Use 3GB */
347 KernelBase = 0xE0000000;
348 LoaderBlock.KernelBase = 0xC0000000;
349 }
350 }
351
352 p++;
353 }
354 }
355
356 /*++
357 * FrLdrGetPaeMode
358 * INTERNAL
359 *
360 * Determines whether PAE mode shoudl be enabled or not.
361 *
362 * Params:
363 * None.
364 *
365 * Returns:
366 * None.
367 *
368 * Remarks:
369 * None.
370 *
371 *--*/
372 VOID
373 FASTCALL
374 FrLdrGetPaeMode(VOID)
375 {
376 }
377
378 /*++
379 * FrLdrSetupPageDirectory
380 * INTERNAL
381 *
382 * Sets up the ReactOS Startup Page Directory.
383 *
384 * Params:
385 * None.
386 *
387 * Returns:
388 * None.
389 *
390 * Remarks:
391 * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure.
392 * As such, please note that PageFrameNumber == PageEntryNumber.
393 *
394 *--*/
395 VOID
396 FASTCALL
397 FrLdrSetupPageDirectory(VOID)
398 {
399 }
400
401 /*++
402 * FrLdrMapModule
403 * INTERNAL
404 *
405 * Loads the indicated elf image as PE. The target will appear to be
406 * a PE image whose ImageBase has ever been KernelAddr.
407 *
408 * Params:
409 * Image -- File to load
410 * ImageName -- Name of image for the modules list
411 * MemLoadAddr -- Freeldr address of module
412 * KernelAddr -- Kernel address of module
413 *--*/
414 #define ELF_SECTION(n) ((Elf32_Shdr*)(sptr + (n * shsize)))
415 #define COFF_FIRST_SECTION(h) ((PIMAGE_SECTION_HEADER) ((DWORD)h+FIELD_OFFSET(IMAGE_NT_HEADERS,OptionalHeader)+(SWAPW(((PIMAGE_NT_HEADERS)(h))->FileHeader.SizeOfOptionalHeader))))
416
417 BOOLEAN
418 NTAPI
419 FrLdrMapModule(FILE *KernelImage, PCHAR ImageName, PCHAR MemLoadAddr, ULONG KernelAddr)
420 {
421 PIMAGE_DOS_HEADER ImageHeader = 0;
422 PIMAGE_NT_HEADERS NtHeader = 0;
423 PIMAGE_SECTION_HEADER Section;
424 ULONG SectionCount;
425 ULONG ImageSize;
426 INT i, j;
427 PLOADER_MODULE ModuleData;
428 //int phsize, phnum;
429 int shsize, shnum, relsize, SectionAddr = 0;
430 PCHAR sptr;
431 Elf32_Ehdr ehdr;
432 Elf32_Shdr *shdr;
433 LPSTR TempName;
434
435 TempName = strrchr(ImageName, '\\');
436 if(TempName) TempName++; else TempName = (LPSTR)ImageName;
437 ModuleData = LdrGetModuleObject(TempName);
438
439 if(ModuleData)
440 {
441 return TRUE;
442 }
443
444 if(!KernelAddr)
445 KernelAddr = (ULONG)NextModuleBase - (ULONG)KernelMemory + KernelBase;
446 if(!MemLoadAddr)
447 MemLoadAddr = (PCHAR)NextModuleBase;
448
449 ModuleData = &reactos_modules[LoaderBlock.ModsCount];
450 //printf("Loading file (elf at %x)\n", KernelAddr);
451
452 /* Load the first 1024 bytes of the kernel image so we can read the PE header */
453 if (!FsReadFile(KernelImage, sizeof(ehdr), NULL, &ehdr)) {
454
455 /* Fail if we couldn't read */
456 printf("Couldn't read the elf header\n");
457 return FALSE;
458 }
459
460 /* Start by getting elf headers */
461 //phsize = ehdr.e_phentsize;
462 //phnum = ehdr.e_phnum;
463 shsize = ehdr.e_shentsize;
464 shnum = ehdr.e_shnum;
465 sptr = (PCHAR)MmHeapAlloc(shnum * shsize);
466
467 /* Read section headers */
468 FsSetFilePointer(KernelImage, ehdr.e_shoff);
469 FsReadFile(KernelImage, shsize * shnum, NULL, sptr);
470
471 /* Now we'll get the PE Header */
472 for( i = 0; i < shnum; i++ )
473 {
474 shdr = ELF_SECTION(i);
475 shdr->sh_addr = 0;
476
477 /* Find the PE Header */
478 if (shdr->sh_type == TYPE_PEHEADER)
479 {
480 FsSetFilePointer(KernelImage, shdr->sh_offset);
481 FsReadFile(KernelImage, shdr->sh_size, NULL, MemLoadAddr);
482 ImageHeader = (PIMAGE_DOS_HEADER)MemLoadAddr;
483 NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)MemLoadAddr + SWAPD(ImageHeader->e_lfanew));
484 #if 0
485 printf("NtHeader at %x\n", SWAPD(ImageHeader->e_lfanew));
486 printf("SectionAlignment %x\n",
487 SWAPD(NtHeader->OptionalHeader.SectionAlignment));
488 SectionAddr = ROUND_UP
489 (shdr->sh_size, SWAPD(NtHeader->OptionalHeader.SectionAlignment));
490 printf("Header ends at %x\n", SectionAddr);
491 #endif
492 break;
493 }
494 }
495
496 if(i == shnum)
497 {
498 printf("No peheader section encountered :-(\n");
499 return 0;
500 }
501 #if 0
502 else
503 {
504 printf("DOS SIG: %s\n", (PCHAR)MemLoadAddr);
505 }
506 #endif
507
508 /* Save the Image Base */
509 NtHeader->OptionalHeader.ImageBase = SWAPD(KernelAddr);
510
511 /* Load the file image */
512 Section = COFF_FIRST_SECTION(NtHeader);
513 SectionCount = SWAPW(NtHeader->FileHeader.NumberOfSections);
514
515 /* Walk each section */
516 for (i=0; i < SectionCount; i++, Section++)
517 {
518 shdr = ELF_SECTION((SWAPD(Section->PointerToRawData)+1));
519
520 shdr->sh_addr = SectionAddr = SWAPD(Section->VirtualAddress);
521 shdr->sh_addr += KernelAddr;
522
523 Section->PointerToRawData = SWAPD((Section->VirtualAddress - KernelAddr));
524
525 if (shdr->sh_type != SHT_NOBITS)
526 {
527 /* Content area */
528 printf("Loading section %d at %x (real: %x:%d)\n", i, KernelAddr + SectionAddr, MemLoadAddr+SectionAddr, shdr->sh_size);
529 FsSetFilePointer(KernelImage, shdr->sh_offset);
530 FsReadFile(KernelImage, shdr->sh_size, NULL, MemLoadAddr + SectionAddr);
531 }
532 else
533 {
534 /* Zero it out */
535 printf("BSS section %d at %x\n", i, KernelAddr + SectionAddr);
536 memset(MemLoadAddr + SectionAddr, 0,
537 ROUND_UP(shdr->sh_size,
538 SWAPD(NtHeader->OptionalHeader.SectionAlignment)));
539 }
540 }
541
542 ImageSize = SWAPD(NtHeader->OptionalHeader.SizeOfImage);
543 printf("Total image size is %x\n", ImageSize);
544
545 /* Handle relocation sections */
546 for (i = 0; i < shnum; i++) {
547 Elf32_Rela reloc = { };
548 ULONG *Target32;
549 USHORT *Target16;
550 int numreloc, relstart, targetSection;
551 Elf32_Sym symbol;
552 PCHAR RelocSection, SymbolSection;
553
554 shdr = ELF_SECTION(i);
555 /* Only relocs here */
556 if((shdr->sh_type != SHT_REL) &&
557 (shdr->sh_type != SHT_RELA)) continue;
558
559 relstart = shdr->sh_offset;
560 relsize = shdr->sh_type == SHT_RELA ? 12 : 8;
561 numreloc = shdr->sh_size / relsize;
562 targetSection = shdr->sh_info;
563
564 if (!ELF_SECTION(targetSection)->sh_addr) continue;
565
566 RelocSection = MmHeapAlloc(shdr->sh_size);
567 FsSetFilePointer(KernelImage, relstart);
568 FsReadFile(KernelImage, shdr->sh_size, NULL, RelocSection);
569
570 /* Get the symbol section */
571 shdr = ELF_SECTION(shdr->sh_link);
572
573 SymbolSection = MmHeapAlloc(shdr->sh_size);
574 FsSetFilePointer(KernelImage, shdr->sh_offset);
575 FsReadFile(KernelImage, shdr->sh_size, NULL, SymbolSection);
576
577 for(j = 0; j < numreloc; j++)
578 {
579 ULONG S,A,P;
580
581 /* Get the reloc */
582 memcpy(&reloc, RelocSection + (j * relsize), sizeof(reloc));
583
584 /* Get the symbol */
585 memcpy(&symbol, SymbolSection + (ELF32_R_SYM(reloc.r_info) * sizeof(symbol)), sizeof(symbol));
586
587 /* Compute addends */
588 S = symbol.st_value + ELF_SECTION(symbol.st_shndx)->sh_addr;
589 A = reloc.r_addend;
590 P = reloc.r_offset + ELF_SECTION(targetSection)->sh_addr;
591
592 #if 0
593 printf("Symbol[%d] %d -> %d(%x:%x) -> %x(+%x)@%x\n",
594 ELF32_R_TYPE(reloc.r_info),
595 ELF32_R_SYM(reloc.r_info),
596 symbol.st_shndx,
597 ELF_SECTION(symbol.st_shndx)->sh_addr,
598 symbol.st_value,
599 S,
600 A,
601 P);
602 #endif
603
604 Target32 = (ULONG*)(((PCHAR)MemLoadAddr) + (P - KernelAddr));
605 Target16 = (USHORT *)Target32;
606
607 switch (ELF32_R_TYPE(reloc.r_info))
608 {
609 case R_PPC_NONE:
610 break;
611 case R_PPC_ADDR32:
612 *Target32 = S + A;
613 break;
614 case R_PPC_REL32:
615 *Target32 = S + A - P;
616 break;
617 case R_PPC_UADDR32: /* Special: Treat as RVA */
618 *Target32 = S + A - KernelAddr;
619 break;
620 case R_PPC_ADDR24:
621 *Target32 = (ADDR24_MASK & (S+A)) | (*Target32 & ~ADDR24_MASK);
622 break;
623 case R_PPC_REL24:
624 *Target32 = (ADDR24_MASK & (S+A-P)) | (*Target32 & ~ADDR24_MASK);
625 break;
626 case R_PPC_ADDR16_LO:
627 *Target16 = S + A;
628 break;
629 case R_PPC_ADDR16_HA:
630 *Target16 = (S + A + 0x8000) >> 16;
631 break;
632 default:
633 break;
634 }
635
636 #if 0
637 printf("reloc[%d:%x]: (type %x sym %d val %d) off %x add %x (old %x new %x)\n",
638 j,
639 ((ULONG)Target32) - ((ULONG)MemLoadAddr),
640 ELF32_R_TYPE(reloc.r_info),
641 ELF32_R_SYM(reloc.r_info),
642 symbol.st_value,
643 reloc.r_offset, reloc.r_addend,
644 x, *Target32);
645 #endif
646 }
647
648 MmHeapFree(SymbolSection);
649 MmHeapFree(RelocSection);
650 }
651
652 MmHeapFree(sptr);
653
654 ModuleData->ModStart = (ULONG)MemLoadAddr;
655 /* Increase the next Load Base */
656 NextModuleBase = ROUND_UP((ULONG)MemLoadAddr + ImageSize, PAGE_SIZE);
657 ModuleData->ModEnd = NextModuleBase;
658 ModuleData->String = (ULONG)MmAllocateMemory(strlen(ImageName)+1);
659 strcpy((PCHAR)ModuleData->String, ImageName);
660 printf("Module %s (%x-%x) next at %x\n",
661 ModuleData->String,
662 ModuleData->ModStart,
663 ModuleData->ModEnd,
664 NextModuleBase);
665 LoaderBlock.ModsCount++;
666
667 /* Return Success */
668 return TRUE;
669 }
670
671 /*++
672 * FrLdrMapKernel
673 * INTERNAL
674 *
675 * Maps the Kernel into memory, does PE Section Mapping, initalizes the
676 * uninitialized data sections, and relocates the image.
677 *
678 * Params:
679 * KernelImage - FILE Structure representing the ntoskrnl image file.
680 *
681 * Returns:
682 * TRUE if the Kernel was mapped.
683 *
684 * Remarks:
685 * None.
686 *
687 *--*/
688 BOOLEAN
689 NTAPI
690 FrLdrMapKernel(FILE *KernelImage)
691 {
692 /* Get Kernel Base */
693 FrLdrGetKernelBase();
694
695 /* Allocate kernel memory */
696 KernelMemory = MmAllocateMemory(KernelMemorySize);
697
698 return FrLdrMapModule(KernelImage, "ntoskrnl.exe", KernelMemory, KernelBase);
699 }
700
701 ULONG_PTR
702 NTAPI
703 FrLdrLoadModule(FILE *ModuleImage,
704 LPCSTR ModuleName,
705 PULONG ModuleSize)
706 {
707 ULONG LocalModuleSize;
708 ULONG_PTR ThisModuleBase = NextModuleBase;
709 PLOADER_MODULE ModuleData;
710 LPSTR NameBuffer;
711 LPSTR TempName;
712
713 /* Get current module data structure and module name string array */
714 ModuleData = &reactos_modules[LoaderBlock.ModsCount];
715
716 /* Get only the Module Name */
717 do {
718
719 TempName = strchr(ModuleName, '\\');
720
721 if(TempName) {
722 ModuleName = TempName + 1;
723 }
724
725 } while(TempName);
726 NameBuffer = reactos_module_strings[LoaderBlock.ModsCount];
727
728
729 /* Get Module Size */
730 LocalModuleSize = FsGetFileSize(ModuleImage);
731
732 /* Fill out Module Data Structure */
733 ModuleData->ModStart = NextModuleBase;
734 ModuleData->ModEnd = NextModuleBase + LocalModuleSize;
735
736 /* Save name */
737 strcpy(NameBuffer, ModuleName);
738 ModuleData->String = (ULONG_PTR)NameBuffer;
739
740 /* Load the file image */
741 FsReadFile(ModuleImage, LocalModuleSize, NULL, (PVOID)NextModuleBase);
742
743 /* Move to next memory block and increase Module Count */
744 NextModuleBase = ROUND_UP(ModuleData->ModEnd, PAGE_SIZE);
745 LoaderBlock.ModsCount++;
746
747 /* Return Module Size if required */
748 if (ModuleSize != NULL) {
749 *ModuleSize = LocalModuleSize;
750 }
751
752 printf("Module %s (%x-%x) next at %x\n",
753 ModuleData->String,
754 ModuleData->ModStart,
755 ModuleData->ModEnd,
756 NextModuleBase);
757
758 return ThisModuleBase;
759 }
760
761 PVOID
762 NTAPI
763 FrLdrMapImage(IN FILE *Image, IN PCHAR ShortName, IN ULONG ImageType)
764 {
765 PVOID Result = NULL;
766
767 printf("Loading image %s (type %d)\n", ShortName, ImageType);
768
769 if (ImageType == 1)
770 {
771 if(FrLdrMapKernel(Image))
772 Result = (PVOID)KernelMemory;
773 }
774 else
775 {
776 PVOID ModuleBase = (PVOID)NextModuleBase;
777
778 if(FrLdrMapModule(Image, ShortName, 0, 0))
779 Result = ModuleBase;
780 }
781 return Result;
782 }
783
784 ULONG_PTR
785 NTAPI
786 FrLdrCreateModule(LPCSTR ModuleName)
787 {
788 PLOADER_MODULE ModuleData;
789 LPSTR NameBuffer;
790
791 /* Get current module data structure and module name string array */
792 ModuleData = &reactos_modules[LoaderBlock.ModsCount];
793 NameBuffer = reactos_module_strings[LoaderBlock.ModsCount];
794
795 /* Set up the structure */
796 ModuleData->ModStart = NextModuleBase;
797 ModuleData->ModEnd = -1;
798
799 /* Copy the name */
800 strcpy(NameBuffer, ModuleName);
801 ModuleData->String = (ULONG_PTR)NameBuffer;
802
803 /* Set the current Module */
804 CurrentModule = ModuleData;
805
806 /* Return Module Base Address */
807 return(ModuleData->ModStart);
808 }
809
810 BOOLEAN
811 NTAPI
812 FrLdrCloseModule(ULONG_PTR ModuleBase,
813 ULONG ModuleSize)
814 {
815 PLOADER_MODULE ModuleData = CurrentModule;
816
817 /* Make sure a module is opened */
818 if (ModuleData) {
819
820 /* Make sure this is the right module and that it hasn't been closed */
821 if ((ModuleBase == ModuleData->ModStart) && (ModuleData->ModEnd == MAXULONG_PTR)) {
822
823 /* Close the Module */
824 ModuleData->ModEnd = ModuleData->ModStart + ModuleSize;
825
826 /* Set the next Module Base and increase the number of modules */
827 NextModuleBase = ROUND_UP(ModuleData->ModEnd, PAGE_SIZE);
828 LoaderBlock.ModsCount++;
829
830 /* Close the currently opened module */
831 CurrentModule = NULL;
832
833 /* Success */
834 return(TRUE);
835 }
836 }
837
838 /* Failure path */
839 return(FALSE);
840 }