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