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