- Move NCI generated files to arch-specific directories
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / loader.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 #define _NTSYSTEM_
21 #include <freeldr.h>
22
23 #define NDEBUG
24 #include <debug.h>
25 #undef DbgPrint
26
27 /* Load Address of Next Module */
28 ULONG_PTR NextModuleBase = KERNEL_BASE_PHYS;
29
30 /* Currently Opened Module */
31 PLOADER_MODULE CurrentModule = NULL;
32
33 /* Unrelocated Kernel Base in Virtual Memory */
34 ULONG_PTR KernelBase;
35
36 /* Kernel Entrypoint in Physical Memory */
37 ULONG_PTR KernelEntry;
38
39 /* Page Directory and Tables for non-PAE Systems */
40 extern PAGE_DIRECTORY_X86 startup_pagedirectory;
41 extern PAGE_DIRECTORY_X86 lowmem_pagetable;
42 extern PAGE_DIRECTORY_X86 kernel_pagetable;
43 extern PAGE_DIRECTORY_X86 hyperspace_pagetable;
44 extern PAGE_DIRECTORY_X86 apic_pagetable;
45 extern PAGE_DIRECTORY_X86 kpcr_pagetable;
46 extern PAGE_DIRECTORY_X86 kuser_pagetable;
47
48 PVOID
49 NTAPI
50 LdrPEGetExportByName(PVOID BaseAddress,
51 PUCHAR SymbolName,
52 USHORT Hint);
53
54 /* FUNCTIONS *****************************************************************/
55
56 /*++
57 * FrLdrStartup
58 * INTERNAL
59 *
60 * Prepares the system for loading the Kernel.
61 *
62 * Params:
63 * Magic - Multiboot Magic
64 *
65 * Returns:
66 * None.
67 *
68 * Remarks:
69 * None.
70 *
71 *--*/
72 VOID
73 NTAPI
74 FrLdrStartup(ULONG Magic)
75 {
76 /* Disable Interrupts */
77 _disable();
78
79 /* Re-initalize EFLAGS */
80 Ke386EraseFlags();
81
82 /* Initialize the page directory */
83 FrLdrSetupPageDirectory();
84
85 /* Initialize Paging, Write-Protection and Load NTOSKRNL */
86 FrLdrSetupPae(Magic);
87 }
88
89 /*++
90 * FrLdrSetupPae
91 * INTERNAL
92 *
93 * Configures PAE on a MP System, and sets the PDBR if it's supported, or if
94 * the system is UP.
95 *
96 * Params:
97 * Magic - Multiboot Magic
98 *
99 * Returns:
100 * None.
101 *
102 * Remarks:
103 * None.
104 *
105 *--*/
106 VOID
107 FASTCALL
108 FrLdrSetupPae(ULONG Magic)
109 {
110 ULONG_PTR PageDirectoryBaseAddress = (ULONG_PTR)&startup_pagedirectory;
111 ASMCODE PagedJump;
112
113 /* Set the PDBR */
114 __writecr3(PageDirectoryBaseAddress);
115
116 /* Enable Paging and Write Protect*/
117 __writecr0(__readcr0() | X86_CR0_PG | X86_CR0_WP);
118
119 /* Jump to Kernel */
120 PagedJump = (ASMCODE)(PVOID)(KernelEntryPoint);
121 PagedJump(Magic, &LoaderBlock);
122 }
123
124 /*++
125 * FrLdrSetupPageDirectory
126 * INTERNAL
127 *
128 * Sets up the ReactOS Startup Page Directory.
129 *
130 * Params:
131 * None.
132 *
133 * Returns:
134 * None.
135 *
136 * Remarks:
137 * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure.
138 * As such, please note that PageFrameNumber == PageEntryNumber.
139 *
140 *--*/
141 VOID
142 FASTCALL
143 FrLdrSetupPageDirectory(VOID)
144 {
145 PPAGE_DIRECTORY_X86 PageDir;
146 ULONG KernelPageTableIndex;
147 ULONG i;
148
149 /* Get the Kernel Table Index */
150 KernelPageTableIndex = KernelBase >> PDE_SHIFT;
151
152 /* Get the Startup Page Directory */
153 PageDir = (PPAGE_DIRECTORY_X86)&startup_pagedirectory;
154
155 /* Set up the Low Memory PDE */
156 PageDir->Pde[LowMemPageTableIndex].Valid = 1;
157 PageDir->Pde[LowMemPageTableIndex].Write = 1;
158 PageDir->Pde[LowMemPageTableIndex].PageFrameNumber = PaPtrToPfn(lowmem_pagetable);
159
160 /* Set up the Kernel PDEs */
161 PageDir->Pde[KernelPageTableIndex].Valid = 1;
162 PageDir->Pde[KernelPageTableIndex].Write = 1;
163 PageDir->Pde[KernelPageTableIndex].PageFrameNumber = PaPtrToPfn(kernel_pagetable);
164 PageDir->Pde[KernelPageTableIndex + 1].Valid = 1;
165 PageDir->Pde[KernelPageTableIndex + 1].Write = 1;
166 PageDir->Pde[KernelPageTableIndex + 1].PageFrameNumber = PaPtrToPfn(kernel_pagetable + 4096);
167
168 /* Set up the Startup PDE */
169 PageDir->Pde[StartupPageTableIndex].Valid = 1;
170 PageDir->Pde[StartupPageTableIndex].Write = 1;
171 PageDir->Pde[StartupPageTableIndex].PageFrameNumber = PaPtrToPfn(startup_pagedirectory);
172
173 /* Set up the Hyperspace PDE */
174 PageDir->Pde[HyperspacePageTableIndex].Valid = 1;
175 PageDir->Pde[HyperspacePageTableIndex].Write = 1;
176 PageDir->Pde[HyperspacePageTableIndex].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable);
177
178 /* Set up the Apic PDE */
179 PageDir->Pde[ApicPageTableIndex].Valid = 1;
180 PageDir->Pde[ApicPageTableIndex].Write = 1;
181 PageDir->Pde[ApicPageTableIndex].PageFrameNumber = PaPtrToPfn(apic_pagetable);
182
183 /* Set up the KPCR PDE */
184 PageDir->Pde[KpcrPageTableIndex].Valid = 1;
185 PageDir->Pde[KpcrPageTableIndex].Write = 1;
186 PageDir->Pde[KpcrPageTableIndex].PageFrameNumber = PaPtrToPfn(kpcr_pagetable);
187
188 /* Set up the KUSER PDE */
189 PageDir->Pde[KuserPageTableIndex].Valid = 1;
190 PageDir->Pde[KuserPageTableIndex].Write = 1;
191 PageDir->Pde[KuserPageTableIndex].PageFrameNumber = PaPtrToPfn(kuser_pagetable);
192
193 /* Set up Low Memory PTEs */
194 PageDir = (PPAGE_DIRECTORY_X86)&lowmem_pagetable;
195 for (i=0; i<1024; i++)
196 {
197 PageDir->Pde[i].Valid = 1;
198 PageDir->Pde[i].Write = 1;
199 PageDir->Pde[i].Owner = 1;
200 PageDir->Pde[i].PageFrameNumber = PaToPfn(i * PAGE_SIZE);
201 }
202
203 /* Set up Kernel PTEs */
204 PageDir = (PPAGE_DIRECTORY_X86)&kernel_pagetable;
205 for (i=0; i<1536; i++)
206 {
207 PageDir->Pde[i].Valid = 1;
208 PageDir->Pde[i].Write = 1;
209 PageDir->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS + i * PAGE_SIZE);
210 }
211
212 /* Set up APIC PTEs */
213 PageDir = (PPAGE_DIRECTORY_X86)&apic_pagetable;
214 PageDir->Pde[0].Valid = 1;
215 PageDir->Pde[0].Write = 1;
216 PageDir->Pde[0].CacheDisable = 1;
217 PageDir->Pde[0].WriteThrough = 1;
218 PageDir->Pde[0].PageFrameNumber = PaToPfn(APIC_BASE);
219 PageDir->Pde[0x200].Valid = 1;
220 PageDir->Pde[0x200].Write = 1;
221 PageDir->Pde[0x200].CacheDisable = 1;
222 PageDir->Pde[0x200].WriteThrough = 1;
223 PageDir->Pde[0x200].PageFrameNumber = PaToPfn(APIC_BASE + KERNEL_BASE_PHYS);
224
225 /* Set up KPCR PTEs */
226 PageDir = (PPAGE_DIRECTORY_X86)&kpcr_pagetable;
227 PageDir->Pde[0].Valid = 1;
228 PageDir->Pde[0].Write = 1;
229 PageDir->Pde[0].PageFrameNumber = 1;
230
231 /* Setup KUSER PTEs */
232 PageDir = (PPAGE_DIRECTORY_X86)&kuser_pagetable;
233 for (i = 0; i < 1024; i++)
234 {
235 /* SEetup each entry */
236 PageDir->Pde[i].Valid = 1;
237 PageDir->Pde[i].Write = 1;
238 PageDir->Pde[i].Owner = 1;
239 PageDir->Pde[i].PageFrameNumber = PaToPfn(KI_USER_SHARED_DATA + i * PAGE_SIZE);
240 }
241 }
242
243 PLOADER_MODULE
244 NTAPI
245 LdrGetModuleObject(PCHAR ModuleName)
246 {
247 ULONG i;
248
249 for (i = 0; i < LoaderBlock.ModsCount; i++)
250 {
251 if (strstr(_strupr((PCHAR)reactos_modules[i].String), _strupr(ModuleName)))
252 {
253 return &reactos_modules[i];
254 }
255 }
256
257 return NULL;
258 }
259
260 PVOID
261 NTAPI
262 LdrPEFixupForward(IN PCHAR ForwardName)
263 {
264 CHAR NameBuffer[128];
265 PCHAR p;
266 PLOADER_MODULE ModuleObject;
267
268 strcpy(NameBuffer, ForwardName);
269 p = strchr(NameBuffer, '.');
270 if (p == NULL) return NULL;
271 *p = 0;
272
273 ModuleObject = LdrGetModuleObject(NameBuffer);
274 if (!ModuleObject)
275 {
276 DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
277 return NULL;
278 }
279
280 return LdrPEGetExportByName((PVOID)ModuleObject->ModStart, (PUCHAR)(p + 1), 0xffff);
281 }
282
283 PVOID
284 NTAPI
285 LdrPEGetExportByName(PVOID BaseAddress,
286 PUCHAR SymbolName,
287 USHORT Hint)
288 {
289 PIMAGE_EXPORT_DIRECTORY ExportDir;
290 PULONG * ExFunctions;
291 PULONG * ExNames;
292 USHORT * ExOrdinals;
293 PVOID ExName;
294 ULONG Ordinal;
295 PVOID Function;
296 LONG minn, maxn, mid, res;
297 ULONG ExportDirSize;
298
299 /* HAL and NTOS use a virtual address, switch it to physical mode */
300 if ((ULONG_PTR)BaseAddress & 0x80000000)
301 {
302 BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - KSEG0_BASE + 0x200000);
303 }
304
305 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
306 RtlImageDirectoryEntryToData(BaseAddress,
307 TRUE,
308 IMAGE_DIRECTORY_ENTRY_EXPORT,
309 &ExportDirSize);
310 if (!ExportDir)
311 {
312 DbgPrint("LdrPEGetExportByName(): no export directory!\n");
313 return NULL;
314 }
315
316 /* The symbol names may be missing entirely */
317 if (!ExportDir->AddressOfNames)
318 {
319 DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n");
320 return NULL;
321 }
322
323 /*
324 * Get header pointers
325 */
326 ExNames = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfNames);
327 ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
328 ExFunctions = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfFunctions);
329
330 /*
331 * Check the hint first
332 */
333 if (Hint < ExportDir->NumberOfNames)
334 {
335 ExName = RVA(BaseAddress, ExNames[Hint]);
336 if (strcmp(ExName, (PCHAR)SymbolName) == 0)
337 {
338 Ordinal = ExOrdinals[Hint];
339 Function = RVA(BaseAddress, ExFunctions[Ordinal]);
340 if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
341 (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
342 {
343 Function = LdrPEFixupForward((PCHAR)Function);
344 if (Function == NULL)
345 {
346 DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function);
347 }
348 return Function;
349 }
350
351 if (Function != NULL) return Function;
352 }
353 }
354
355 /*
356 * Binary search
357 */
358 minn = 0;
359 maxn = ExportDir->NumberOfNames - 1;
360 while (minn <= maxn)
361 {
362 mid = (minn + maxn) / 2;
363
364 ExName = RVA(BaseAddress, ExNames[mid]);
365 res = strcmp(ExName, (PCHAR)SymbolName);
366 if (res == 0)
367 {
368 Ordinal = ExOrdinals[mid];
369 Function = RVA(BaseAddress, ExFunctions[Ordinal]);
370 if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
371 (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
372 {
373 Function = LdrPEFixupForward((PCHAR)Function);
374 if (Function == NULL)
375 {
376 DbgPrint("1: failed to find %s\n", Function);
377 }
378 return Function;
379 }
380 if (Function != NULL)
381 {
382 return Function;
383 }
384 }
385 else if (res > 0)
386 {
387 maxn = mid - 1;
388 }
389 else
390 {
391 minn = mid + 1;
392 }
393 }
394
395 ExName = RVA(BaseAddress, ExNames[mid]);
396 DbgPrint("2: failed to find %s\n",SymbolName);
397 return (PVOID)NULL;
398 }
399
400 NTSTATUS
401 NTAPI
402 LdrPEProcessImportDirectoryEntry(PVOID DriverBase,
403 PLOADER_MODULE LoaderModule,
404 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory)
405 {
406 PVOID* ImportAddressList;
407 PULONG FunctionNameList;
408
409 if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
410 {
411 return STATUS_UNSUCCESSFUL;
412 }
413
414 /* Get the import address list. */
415 ImportAddressList = (PVOID*)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
416
417 /* Get the list of functions to import. */
418 if (ImportModuleDirectory->OriginalFirstThunk != 0)
419 {
420 FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->OriginalFirstThunk);
421 }
422 else
423 {
424 FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
425 }
426
427 /* Walk through function list and fixup addresses. */
428 while (*FunctionNameList != 0L)
429 {
430 if ((*FunctionNameList) & 0x80000000)
431 {
432 DbgPrint("Failed to import ordinal from %s\n", LoaderModule->String);
433 return STATUS_UNSUCCESSFUL;
434 }
435 else
436 {
437 IMAGE_IMPORT_BY_NAME *pe_name;
438 pe_name = RVA(DriverBase, *FunctionNameList);
439 *ImportAddressList = LdrPEGetExportByName((PVOID)LoaderModule->ModStart, pe_name->Name, pe_name->Hint);
440
441 /* Fixup the address to be virtual */
442 *ImportAddressList = (PVOID)((ULONG_PTR)*ImportAddressList + (KSEG0_BASE - 0x200000));
443
444 //DbgPrint("Looked for: %s and found: %p\n", pe_name->Name, *ImportAddressList);
445 if ((*ImportAddressList) == NULL)
446 {
447 DbgPrint("Failed to import %s from %s\n", pe_name->Name, LoaderModule->String);
448 return STATUS_UNSUCCESSFUL;
449 }
450 }
451 ImportAddressList++;
452 FunctionNameList++;
453 }
454 return STATUS_SUCCESS;
455 }
456
457 NTSTATUS
458 NTAPI
459 LdrPEGetOrLoadModule(IN PCHAR ModuleName,
460 IN PCHAR ImportedName,
461 IN PLOADER_MODULE* ImportedModule)
462 {
463 NTSTATUS Status = STATUS_SUCCESS;
464
465 *ImportedModule = LdrGetModuleObject(ImportedName);
466 if (*ImportedModule == NULL)
467 {
468 /*
469 * For now, we only support import-loading the HAL.
470 * Later, FrLdrLoadDriver should be made to share the same
471 * code, and we'll just call it instead.
472 */
473 if (!_stricmp(ImportedName, "hal.dll") ||
474 !_stricmp(ImportedName, "kdcom.dll") ||
475 !_stricmp(ImportedName, "bootvid.dll"))
476 {
477 /* Load the HAL */
478 FrLdrLoadImage(ImportedName, 10, FALSE);
479
480 /* Return the new module */
481 *ImportedModule = LdrGetModuleObject(ImportedName);
482 if (*ImportedModule == NULL)
483 {
484 DbgPrint("Error loading import: %s\n", ImportedName);
485 return STATUS_UNSUCCESSFUL;
486 }
487 }
488 else
489 {
490 DbgPrint("Don't yet support loading new modules from imports\n");
491 Status = STATUS_NOT_IMPLEMENTED;
492 }
493 }
494
495 return Status;
496 }
497
498 NTSTATUS
499 NTAPI
500 LdrPEFixupImports(IN PVOID DllBase,
501 IN PCHAR DllName)
502 {
503 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
504 PCHAR ImportedName;
505 NTSTATUS Status;
506 PLOADER_MODULE ImportedModule;
507 ULONG Size;
508
509 /* Process each import module */
510 ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
511 RtlImageDirectoryEntryToData(DllBase,
512 TRUE,
513 IMAGE_DIRECTORY_ENTRY_IMPORT,
514 &Size);
515 while (ImportModuleDirectory->Name)
516 {
517 /* Check to make sure that import lib is kernel */
518 ImportedName = (PCHAR) DllBase + ImportModuleDirectory->Name;
519 //DbgPrint("Processing imports for file: %s into file: %s\n", DllName, ImportedName);
520
521 Status = LdrPEGetOrLoadModule(DllName, ImportedName, &ImportedModule);
522 if (!NT_SUCCESS(Status)) return Status;
523
524 Status = LdrPEProcessImportDirectoryEntry(DllBase, ImportedModule, ImportModuleDirectory);
525 if (!NT_SUCCESS(Status)) return Status;
526
527 //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName);
528 ImportModuleDirectory++;
529 }
530
531 return STATUS_SUCCESS;
532 }
533
534 ULONG
535 NTAPI
536 FrLdrReMapImage(IN PVOID Base,
537 IN PVOID LoadBase)
538 {
539 PIMAGE_NT_HEADERS NtHeader;
540 PIMAGE_SECTION_HEADER Section;
541 ULONG i, Size, DriverSize = 0;
542
543 /* Get the first section */
544 NtHeader = RtlImageNtHeader(Base);
545 Section = IMAGE_FIRST_SECTION(NtHeader);
546
547 /* Allocate memory for the driver */
548 DriverSize = NtHeader->OptionalHeader.SizeOfImage;
549 LoadBase = MmAllocateMemoryAtAddress(DriverSize, LoadBase);
550 ASSERT(LoadBase);
551
552 /* Copy headers over */
553 RtlMoveMemory(LoadBase, Base, NtHeader->OptionalHeader.SizeOfHeaders);
554
555 /* Copy image sections into virtual section */
556 for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
557 {
558 /* Get the size of this section and check if it's valid */
559 Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize;
560 if (Size <= DriverSize)
561 {
562 if (Section[i].SizeOfRawData)
563 {
564 /* Copy the data from the disk to the image */
565 RtlCopyMemory((PVOID)((ULONG_PTR)LoadBase +
566 Section[i].VirtualAddress),
567 (PVOID)((ULONG_PTR)Base +
568 Section[i].PointerToRawData),
569 Section[i].Misc.VirtualSize >
570 Section[i].SizeOfRawData ?
571 Section[i].SizeOfRawData :
572 Section[i].Misc.VirtualSize);
573 }
574 else
575 {
576 /* Clear the BSS area */
577 RtlZeroMemory((PVOID)((ULONG_PTR)LoadBase +
578 Section[i].VirtualAddress),
579 Section[i].Misc.VirtualSize);
580 }
581 }
582 }
583
584 /* Return the size of the mapped driver */
585 return DriverSize;
586 }
587
588 PVOID
589 NTAPI
590 FrLdrMapImage(IN FILE *Image,
591 IN PCHAR Name,
592 IN ULONG ImageType)
593 {
594 PVOID ImageBase, LoadBase, ReadBuffer;
595 ULONG ImageId = LoaderBlock.ModsCount;
596 ULONG ImageSize;
597 NTSTATUS Status = STATUS_SUCCESS;
598
599 /* Set the virtual (image) and physical (load) addresses */
600 LoadBase = (PVOID)NextModuleBase;
601 ImageBase = RVA(LoadBase , -KERNEL_BASE_PHYS + KSEG0_BASE);
602
603 /* Save the Image Size */
604 ImageSize = FsGetFileSize(Image);
605
606 /* Set the file pointer to zero */
607 FsSetFilePointer(Image, 0);
608
609 /* Allocate a temporary buffer for the read */
610 ReadBuffer = MmAllocateMemory(ImageSize);
611
612 /* Load the file image */
613 FsReadFile(Image, ImageSize, NULL, ReadBuffer);
614
615 /* Map it into virtual memory */
616 ImageSize = FrLdrReMapImage(ReadBuffer, LoadBase);
617
618 /* Free the temporary buffer */
619 MmFreeMemory(ReadBuffer);
620
621 /* Calculate Difference between Real Base and Compiled Base*/
622 Status = LdrRelocateImageWithBias(LoadBase,
623 (ULONG_PTR)ImageBase -
624 (ULONG_PTR)LoadBase,
625 "FreeLdr",
626 STATUS_SUCCESS,
627 STATUS_UNSUCCESSFUL,
628 STATUS_UNSUCCESSFUL);
629 if (!NT_SUCCESS(Status))
630 {
631 /* Fail */
632 DbgPrint("Failed to relocate image: %s\n", Name);
633 return NULL;
634 }
635
636 /* Fill out Module Data Structure */
637 reactos_modules[ImageId].ModStart = (ULONG_PTR)ImageBase;
638 reactos_modules[ImageId].ModEnd = (ULONG_PTR)ImageBase + ImageSize;
639 strcpy(reactos_module_strings[ImageId], Name);
640 reactos_modules[ImageId].String = (ULONG_PTR)reactos_module_strings[ImageId];
641 LoaderBlock.ModsCount++;
642
643 /* Increase the next Load Base */
644 NextModuleBase = ROUND_UP(NextModuleBase + ImageSize, PAGE_SIZE);
645
646 /* Load HAL if this is the kernel */
647 if (ImageType == 1) FrLdrLoadImage("hal.dll", 10, FALSE);
648
649 /* Perform import fixups */
650 LdrPEFixupImports(LoadBase, Name);
651
652 /* Return the final mapped address */
653 return LoadBase;
654 }
655
656 ULONG_PTR
657 NTAPI
658 FrLdrLoadModule(FILE *ModuleImage,
659 LPCSTR ModuleName,
660 PULONG ModuleSize)
661 {
662 ULONG LocalModuleSize;
663 PLOADER_MODULE ModuleData;
664 LPSTR NameBuffer;
665 LPSTR TempName;
666
667 /* Get current module data structure and module name string array */
668 ModuleData = &reactos_modules[LoaderBlock.ModsCount];
669
670 /* Get only the Module Name */
671 do {
672
673 TempName = strchr(ModuleName, '\\');
674
675 if(TempName) {
676 ModuleName = TempName + 1;
677 }
678
679 } while(TempName);
680 NameBuffer = reactos_module_strings[LoaderBlock.ModsCount];
681
682 /* Get Module Size */
683 LocalModuleSize = FsGetFileSize(ModuleImage);
684
685 /* Fill out Module Data Structure */
686 ModuleData->ModStart = NextModuleBase;
687 ModuleData->ModEnd = NextModuleBase + LocalModuleSize;
688
689 /* Save name */
690 strcpy(NameBuffer, ModuleName);
691 ModuleData->String = (ULONG_PTR)NameBuffer;
692
693 /* Load the file image */
694 FsReadFile(ModuleImage, LocalModuleSize, NULL, (PVOID)NextModuleBase);
695
696 /* Move to next memory block and increase Module Count */
697 NextModuleBase = ROUND_UP(ModuleData->ModEnd, PAGE_SIZE);
698 LoaderBlock.ModsCount++;
699 // DbgPrint("NextBase, ImageSize, ModStart, ModEnd %p %p %p %p\n",
700 // NextModuleBase, LocalModuleSize, ModuleData->ModStart, ModuleData->ModEnd);
701
702 /* Return Module Size if required */
703 if (ModuleSize != NULL) {
704 *ModuleSize = LocalModuleSize;
705 }
706
707 return(ModuleData->ModStart);
708 }
709
710 ULONG_PTR
711 NTAPI
712 FrLdrCreateModule(LPCSTR ModuleName)
713 {
714 PLOADER_MODULE ModuleData;
715 LPSTR NameBuffer;
716
717 /* Get current module data structure and module name string array */
718 ModuleData = &reactos_modules[LoaderBlock.ModsCount];
719 NameBuffer = reactos_module_strings[LoaderBlock.ModsCount];
720
721 /* Set up the structure */
722 ModuleData->ModStart = NextModuleBase;
723 ModuleData->ModEnd = -1;
724
725 /* Copy the name */
726 strcpy(NameBuffer, ModuleName);
727 ModuleData->String = (ULONG_PTR)NameBuffer;
728
729 /* Set the current Module */
730 CurrentModule = ModuleData;
731
732 /* Return Module Base Address */
733 return(ModuleData->ModStart);
734 }
735
736 BOOLEAN
737 NTAPI
738 FrLdrCloseModule(ULONG_PTR ModuleBase,
739 ULONG ModuleSize)
740 {
741 PLOADER_MODULE ModuleData = CurrentModule;
742
743 /* Make sure a module is opened */
744 if (ModuleData) {
745
746 /* Make sure this is the right module and that it hasn't been closed */
747 if ((ModuleBase == ModuleData->ModStart) && (ModuleData->ModEnd == (ULONG_PTR)-1)) {
748
749 /* Close the Module */
750 ModuleData->ModEnd = ModuleData->ModStart + ModuleSize;
751
752 /* Set the next Module Base and increase the number of modules */
753 NextModuleBase = ROUND_UP(ModuleData->ModEnd, PAGE_SIZE);
754 LoaderBlock.ModsCount++;
755
756 /* Close the currently opened module */
757 CurrentModule = NULL;
758
759 /* Success */
760 return(TRUE);
761 }
762 }
763
764 /* Failure path */
765 return(FALSE);
766 }