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