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