Copy riched20
[reactos.git] / reactos / boot / freeldr / freeldr / multiboot.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: Freeloader
4 * FILE: boot/freeldr/freeldr/multiboot.c
5 * PURPOSE: ReactOS Loader
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Hartmut Birr - SMP/PAE Code
8 */
9
10 #include <freeldr.h>
11 #include <internal/i386/ke.h>
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* Base Addres of Kernel in Physical Memory */
17 #define KERNEL_BASE_PHYS 0x200000
18
19 /* Bits to shift to convert a Virtual Address into an Offset in the Page Table */
20 #define PFN_SHIFT 12
21
22 /* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */
23 #define PDE_SHIFT 20
24 #define PDE_SHIFT_PAE 18
25
26
27 /* Converts a Relative Address read from the Kernel into a Physical Address */
28 #define RaToPa(p) \
29 (ULONG_PTR)((ULONG_PTR)p + KERNEL_BASE_PHYS)
30
31 /* Converts a Phsyical Address Pointer into a Page Frame Number */
32 #define PaPtrToPfn(p) \
33 (((ULONG_PTR)&p) >> PFN_SHIFT)
34
35 /* Converts a Phsyical Address into a Page Frame Number */
36 #define PaToPfn(p) \
37 ((p) >> PFN_SHIFT)
38
39 #define STARTUP_BASE 0xF0000000
40 #define HYPERSPACE_BASE 0xF0800000
41 #define APIC_BASE 0xFEC00000
42 #define KPCR_BASE 0xFF000000
43
44 #define LowMemPageTableIndex 0
45 #define StartupPageTableIndex (STARTUP_BASE >> 20) / sizeof(HARDWARE_PTE_X86)
46 #define HyperspacePageTableIndex (HYPERSPACE_BASE >> 20) / sizeof(HARDWARE_PTE_X86)
47 #define KpcrPageTableIndex (KPCR_BASE >> 20) / sizeof(HARDWARE_PTE_X86)
48 #define ApicPageTableIndex (APIC_BASE >> 20) / sizeof(HARDWARE_PTE_X86)
49
50 #define LowMemPageTableIndexPae 0
51 #define StartupPageTableIndexPae (STARTUP_BASE >> 21)
52 #define HyperspacePageTableIndexPae (HYPERSPACE_BASE >> 21)
53 #define KpcrPageTableIndexPae (KPCR_BASE >> 21)
54 #define ApicPageTableIndexPae (APIC_BASE >> 21)
55
56
57 #define KernelEntryPoint (KernelEntry - KERNEL_BASE_PHYS) + KernelBase
58
59 /* Load Address of Next Module */
60 ULONG_PTR NextModuleBase = 0;
61
62 /* Currently Opened Module */
63 PFRLDR_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 KernelEntry;
73
74 /* Page Directory and Tables for non-PAE Systems */
75 extern ULONG_PTR startup_pagedirectory;
76 extern ULONG_PTR lowmem_pagetable;
77 extern ULONG_PTR kernel_pagetable;
78 extern ULONG_PTR hyperspace_pagetable;
79 extern ULONG_PTR _pae_pagedirtable;
80 extern ULONG_PTR apic_pagetable;
81 extern ULONG_PTR kpcr_pagetable;
82
83 /* Page Directory and Tables for PAE Systems */
84 extern ULONG_PTR startup_pagedirectorytable_pae;
85 extern ULONG_PTR startup_pagedirectory_pae;
86 extern ULONG_PTR lowmem_pagetable_pae;
87 extern ULONG_PTR kernel_pagetable_pae;
88 extern ULONG_PTR hyperspace_pagetable_pae;
89 extern ULONG_PTR pagedirtable_pae;
90 extern ULONG_PTR apic_pagetable_pae;
91 extern ULONG_PTR kpcr_pagetable_pae;
92
93 typedef struct _HARDWARE_PTE_X86 {
94 ULONG Valid : 1;
95 ULONG Write : 1;
96 ULONG Owner : 1;
97 ULONG WriteThrough : 1;
98 ULONG CacheDisable : 1;
99 ULONG Accessed : 1;
100 ULONG Dirty : 1;
101 ULONG LargePage : 1;
102 ULONG Global : 1;
103 ULONG CopyOnWrite : 1;
104 ULONG Prototype : 1;
105 ULONG reserved : 1;
106 ULONG PageFrameNumber : 20;
107 } HARDWARE_PTE_X86, *PHARDWARE_PTE_X86;
108
109 typedef struct _HARDWARE_PTE_X64 {
110 ULONG Valid : 1;
111 ULONG Write : 1;
112 ULONG Owner : 1;
113 ULONG WriteThrough : 1;
114 ULONG CacheDisable : 1;
115 ULONG Accessed : 1;
116 ULONG Dirty : 1;
117 ULONG LargePage : 1;
118 ULONG Global : 1;
119 ULONG CopyOnWrite : 1;
120 ULONG Prototype : 1;
121 ULONG reserved : 1;
122 ULONG PageFrameNumber : 20;
123 ULONG reserved2 : 31;
124 ULONG NoExecute : 1;
125 } HARDWARE_PTE_X64, *PHARDWARE_PTE_X64;
126
127 typedef struct _PAGE_DIRECTORY_X86 {
128 HARDWARE_PTE_X86 Pde[1024];
129 } PAGE_DIRECTORY_x86, *PPAGE_DIRECTORY_X86;
130
131 typedef struct _PAGE_DIRECTORY_X64 {
132 HARDWARE_PTE_X64 Pde[2048];
133 } PAGE_DIRECTORY_X64, *PPAGE_DIRECTORY_X64;
134
135 typedef struct _PAGE_DIRECTORY_TABLE_X64 {
136 HARDWARE_PTE_X64 Pde[4];
137 } PAGE_DIRECTORY_TABLE_X64, *PPAGE_DIRECTORY_TABLE_X64;
138
139 /* FUNCTIONS *****************************************************************/
140
141 /*++
142 * FrLdrStartup
143 * INTERNAL
144 *
145 * Prepares the system for loading the Kernel.
146 *
147 * Params:
148 * Magic - Multiboot Magic
149 *
150 * Returns:
151 * None.
152 *
153 * Remarks:
154 * None.
155 *
156 *--*/
157 VOID
158 STDCALL
159 FrLdrStartup(ULONG Magic)
160 {
161 /* Disable Interrupts */
162 Ke386DisableInterrupts();
163
164 /* Re-initalize EFLAGS */
165 Ke386EraseFlags();
166
167 /* Get Kernel Base and Set MmSystemRangeStart */
168 FrLdrGetKernelBase();
169
170 FrLdrGetPaeMode();
171
172 /* Initialize the page directory */
173 FrLdrSetupPageDirectory();
174
175 /* Initialize Paging, Write-Protection and Load NTOSKRNL */
176 FrLdrSetupPae(Magic);
177 }
178
179 /*++
180 * FrLdrSetupPae
181 * INTERNAL
182 *
183 * Configures PAE on a MP System, and sets the PDBR if it's supported, or if
184 * the system is UP.
185 *
186 * Params:
187 * Magic - Multiboot Magic
188 *
189 * Returns:
190 * None.
191 *
192 * Remarks:
193 * None.
194 *
195 *--*/
196 VOID
197 FASTCALL
198 FrLdrSetupPae(ULONG Magic)
199 {
200 ULONG_PTR PageDirectoryBaseAddress = (ULONG_PTR)&startup_pagedirectory;
201 ASMCODE PagedJump;
202
203 if (PaeModeEnabled)
204 {
205 PageDirectoryBaseAddress = (ULONG_PTR)&startup_pagedirectorytable_pae;
206
207 /* Enable PAE */
208 Ke386SetCr4(Ke386GetCr4() | X86_CR4_PAE);
209 }
210
211 /* Set the PDBR */
212 Ke386SetPageTableDirectory(PageDirectoryBaseAddress);
213
214 /* Enable Paging and Write Protect*/
215 Ke386SetCr0(Ke386GetCr0() | X86_CR0_PG | X86_CR0_WP);
216
217 /* Jump to Kernel */
218 PagedJump = (ASMCODE)KernelEntryPoint;
219 PagedJump(Magic, &LoaderBlock);
220 }
221
222 /*++
223 * FrLdrGetKernelBase
224 * INTERNAL
225 *
226 * Gets the Kernel Base to use.
227 *
228 * Params:
229 *
230 * Returns:
231 * None.
232 *
233 * Remarks:
234 * Sets both the FreeLdr internal variable as well as the one which
235 * will be used by the Kernel.
236 *
237 *--*/
238 VOID
239 FASTCALL
240 FrLdrGetKernelBase(VOID)
241 {
242 PCHAR p;
243
244 /* Read Command Line */
245 p = (PCHAR)LoaderBlock.CommandLine;
246 while ((p = strchr(p, '/')) != NULL) {
247
248 /* Find "/3GB" */
249 if (!strnicmp(p + 1, "3GB", 3)) {
250
251 /* Make sure there's nothing following it */
252 if (p[4] == ' ' || p[4] == 0) {
253
254 /* Use 3GB */
255 KernelBase = 0xC0000000;
256 }
257 }
258
259 p++;
260 }
261
262 /* Set KernelBase */
263 LoaderBlock.KernelBase = KernelBase;
264 }
265
266 /*++
267 * FrLdrGetPaeMode
268 * INTERNAL
269 *
270 * Determines whether PAE mode shoudl be enabled or not.
271 *
272 * Params:
273 * None.
274 *
275 * Returns:
276 * None.
277 *
278 * Remarks:
279 * None.
280 *
281 *--*/
282 VOID
283 FASTCALL
284 FrLdrGetPaeMode(VOID)
285 {
286 /* FIXME: Read command line */
287 PaeModeEnabled = FALSE;
288
289 if (PaeModeEnabled)
290 {
291 }
292 }
293
294 /*++
295 * FrLdrSetupPageDirectory
296 * INTERNAL
297 *
298 * Sets up the ReactOS Startup Page Directory.
299 *
300 * Params:
301 * None.
302 *
303 * Returns:
304 * None.
305 *
306 * Remarks:
307 * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure.
308 * As such, please note that PageFrameNumber == PageEntryNumber.
309 *
310 *--*/
311 VOID
312 FASTCALL
313 FrLdrSetupPageDirectory(VOID)
314 {
315 PPAGE_DIRECTORY_X86 PageDir;
316 PPAGE_DIRECTORY_TABLE_X64 PageDirTablePae;
317 PPAGE_DIRECTORY_X64 PageDirPae;
318 ULONG KernelPageTableIndex;
319 ULONG i;
320
321 if (PaeModeEnabled) {
322
323 /* Get the Kernel Table Index */
324 KernelPageTableIndex = (KernelBase >> 21);
325
326 /* Get the Startup Page Directory Table */
327 PageDirTablePae = (PPAGE_DIRECTORY_TABLE_X64)&startup_pagedirectorytable_pae;
328
329 /* Get the Startup Page Directory */
330 PageDirPae = (PPAGE_DIRECTORY_X64)&startup_pagedirectory_pae;
331
332 /* Set the Startup page directory table */
333 for (i = 0; i < 4; i++)
334 {
335 PageDirTablePae->Pde[i].Valid = 1;
336 PageDirTablePae->Pde[i].PageFrameNumber = PaPtrToPfn(startup_pagedirectory_pae) + i;
337 }
338
339 /* Set up the Low Memory PDE */
340 for (i = 0; i < 2; i++)
341 {
342 PageDirPae->Pde[LowMemPageTableIndexPae + i].Valid = 1;
343 PageDirPae->Pde[LowMemPageTableIndexPae + i].Write = 1;
344 PageDirPae->Pde[LowMemPageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(lowmem_pagetable_pae) + i;
345 }
346
347 /* Set up the Kernel PDEs */
348 for (i = 0; i < 3; i++)
349 {
350 PageDirPae->Pde[KernelPageTableIndex + i].Valid = 1;
351 PageDirPae->Pde[KernelPageTableIndex + i].Write = 1;
352 PageDirPae->Pde[KernelPageTableIndex + i].PageFrameNumber = PaPtrToPfn(kernel_pagetable_pae) + i;
353 }
354
355 /* Set up the Startup PDE */
356 for (i = 0; i < 4; i++)
357 {
358 PageDirPae->Pde[StartupPageTableIndexPae + i].Valid = 1;
359 PageDirPae->Pde[StartupPageTableIndexPae + i].Write = 1;
360 PageDirPae->Pde[StartupPageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(startup_pagedirectory_pae) + i;
361 }
362
363 /* Set up the Hyperspace PDE */
364 for (i = 0; i < 2; i++)
365 {
366 PageDirPae->Pde[HyperspacePageTableIndexPae + i].Valid = 1;
367 PageDirPae->Pde[HyperspacePageTableIndexPae + i].Write = 1;
368 PageDirPae->Pde[HyperspacePageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable_pae) + i;
369 }
370
371 /* Set up the Apic PDE */
372 for (i = 0; i < 2; i++)
373 {
374 PageDirPae->Pde[ApicPageTableIndexPae + i].Valid = 1;
375 PageDirPae->Pde[ApicPageTableIndexPae + i].Write = 1;
376 PageDirPae->Pde[ApicPageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(apic_pagetable_pae) + i;
377 }
378
379 /* Set up the KPCR PDE */
380 PageDirPae->Pde[KpcrPageTableIndexPae].Valid = 1;
381 PageDirPae->Pde[KpcrPageTableIndexPae].Write = 1;
382 PageDirPae->Pde[KpcrPageTableIndexPae].PageFrameNumber = PaPtrToPfn(kpcr_pagetable_pae);
383
384 /* Set up Low Memory PTEs */
385 PageDirPae = (PPAGE_DIRECTORY_X64)&lowmem_pagetable_pae;
386 for (i=0; i<1024; i++) {
387
388 PageDirPae->Pde[i].Valid = 1;
389 PageDirPae->Pde[i].Write = 1;
390 PageDirPae->Pde[i].Owner = 1;
391 PageDirPae->Pde[i].PageFrameNumber = i;
392 }
393
394 /* Set up Kernel PTEs */
395 PageDirPae = (PPAGE_DIRECTORY_X64)&kernel_pagetable_pae;
396 for (i=0; i<1536; i++) {
397
398 PageDirPae->Pde[i].Valid = 1;
399 PageDirPae->Pde[i].Write = 1;
400 PageDirPae->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS) + i;
401 }
402
403 /* Set up APIC PTEs */
404 PageDirPae = (PPAGE_DIRECTORY_X64)&apic_pagetable_pae;
405 PageDirPae->Pde[0].Valid = 1;
406 PageDirPae->Pde[0].Write = 1;
407 PageDirPae->Pde[0].CacheDisable = 1;
408 PageDirPae->Pde[0].WriteThrough = 1;
409 PageDirPae->Pde[0].PageFrameNumber = PaToPfn(APIC_BASE);
410 PageDirPae->Pde[0x200].Valid = 1;
411 PageDirPae->Pde[0x200].Write = 1;
412 PageDirPae->Pde[0x200].CacheDisable = 1;
413 PageDirPae->Pde[0x200].WriteThrough = 1;
414 PageDirPae->Pde[0x200].PageFrameNumber = PaToPfn(APIC_BASE + KERNEL_BASE_PHYS);
415
416 /* Set up KPCR PTEs */
417 PageDirPae = (PPAGE_DIRECTORY_X64)&kpcr_pagetable_pae;
418 PageDirPae->Pde[0].Valid = 1;
419 PageDirPae->Pde[0].Write = 1;
420 PageDirPae->Pde[0].PageFrameNumber = 1;
421
422 } else {
423
424 /* Get the Kernel Table Index */
425 KernelPageTableIndex = (KernelBase >> PDE_SHIFT) / sizeof(HARDWARE_PTE_X86);
426
427 /* Get the Startup Page Directory */
428 PageDir = (PPAGE_DIRECTORY_X86)&startup_pagedirectory;
429
430 /* Set up the Low Memory PDE */
431 PageDir->Pde[LowMemPageTableIndex].Valid = 1;
432 PageDir->Pde[LowMemPageTableIndex].Write = 1;
433 PageDir->Pde[LowMemPageTableIndex].PageFrameNumber = PaPtrToPfn(lowmem_pagetable);
434
435 /* Set up the Kernel PDEs */
436 PageDir->Pde[KernelPageTableIndex].Valid = 1;
437 PageDir->Pde[KernelPageTableIndex].Write = 1;
438 PageDir->Pde[KernelPageTableIndex].PageFrameNumber = PaPtrToPfn(kernel_pagetable);
439 PageDir->Pde[KernelPageTableIndex + 1].Valid = 1;
440 PageDir->Pde[KernelPageTableIndex + 1].Write = 1;
441 PageDir->Pde[KernelPageTableIndex + 1].PageFrameNumber = PaPtrToPfn(kernel_pagetable + 4096);
442
443 /* Set up the Startup PDE */
444 PageDir->Pde[StartupPageTableIndex].Valid = 1;
445 PageDir->Pde[StartupPageTableIndex].Write = 1;
446 PageDir->Pde[StartupPageTableIndex].PageFrameNumber = PaPtrToPfn(startup_pagedirectory);
447
448 /* Set up the Hyperspace PDE */
449 PageDir->Pde[HyperspacePageTableIndex].Valid = 1;
450 PageDir->Pde[HyperspacePageTableIndex].Write = 1;
451 PageDir->Pde[HyperspacePageTableIndex].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable);
452
453 /* Set up the Apic PDE */
454 PageDir->Pde[ApicPageTableIndex].Valid = 1;
455 PageDir->Pde[ApicPageTableIndex].Write = 1;
456 PageDir->Pde[ApicPageTableIndex].PageFrameNumber = PaPtrToPfn(apic_pagetable);
457
458 /* Set up the KPCR PDE */
459 PageDir->Pde[KpcrPageTableIndex].Valid = 1;
460 PageDir->Pde[KpcrPageTableIndex].Write = 1;
461 PageDir->Pde[KpcrPageTableIndex].PageFrameNumber = PaPtrToPfn(kpcr_pagetable);
462
463 /* Set up Low Memory PTEs */
464 PageDir = (PPAGE_DIRECTORY_X86)&lowmem_pagetable;
465 for (i=0; i<1024; i++) {
466
467 PageDir->Pde[i].Valid = 1;
468 PageDir->Pde[i].Write = 1;
469 PageDir->Pde[i].Owner = 1;
470 PageDir->Pde[i].PageFrameNumber = PaToPfn(i * PAGE_SIZE);
471 }
472
473 /* Set up Kernel PTEs */
474 PageDir = (PPAGE_DIRECTORY_X86)&kernel_pagetable;
475 for (i=0; i<1536; i++) {
476
477 PageDir->Pde[i].Valid = 1;
478 PageDir->Pde[i].Write = 1;
479 PageDir->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS + i * PAGE_SIZE);
480 }
481
482 /* Set up APIC PTEs */
483 PageDir = (PPAGE_DIRECTORY_X86)&apic_pagetable;
484 PageDir->Pde[0].Valid = 1;
485 PageDir->Pde[0].Write = 1;
486 PageDir->Pde[0].CacheDisable = 1;
487 PageDir->Pde[0].WriteThrough = 1;
488 PageDir->Pde[0].PageFrameNumber = PaToPfn(APIC_BASE);
489 PageDir->Pde[0x200].Valid = 1;
490 PageDir->Pde[0x200].Write = 1;
491 PageDir->Pde[0x200].CacheDisable = 1;
492 PageDir->Pde[0x200].WriteThrough = 1;
493 PageDir->Pde[0x200].PageFrameNumber = PaToPfn(APIC_BASE + KERNEL_BASE_PHYS);
494
495 /* Set up KPCR PTEs */
496 PageDir = (PPAGE_DIRECTORY_X86)&kpcr_pagetable;
497 PageDir->Pde[0].Valid = 1;
498 PageDir->Pde[0].Write = 1;
499 PageDir->Pde[0].PageFrameNumber = 1;
500 }
501 return;
502 }
503
504 /*++
505 * FrLdrMapKernel
506 * INTERNAL
507 *
508 * Maps the Kernel into memory, does PE Section Mapping, initalizes the
509 * uninitialized data sections, and relocates the image.
510 *
511 * Params:
512 * KernelImage - FILE Structure representing the ntoskrnl image file.
513 *
514 * Returns:
515 * TRUE if the Kernel was mapped.
516 *
517 * Remarks:
518 * None.
519 *
520 *--*/
521 BOOL
522 STDCALL
523 FrLdrMapKernel(FILE *KernelImage)
524 {
525 PIMAGE_DOS_HEADER ImageHeader;
526 PIMAGE_NT_HEADERS NtHeader;
527 PIMAGE_SECTION_HEADER Section;
528 ULONG SectionCount;
529 ULONG ImageSize;
530 ULONG_PTR SourceSection;
531 ULONG_PTR TargetSection;
532 ULONG SectionSize;
533 LONG i;
534
535 /* Allocate 1024 bytes for PE Header */
536 ImageHeader = (PIMAGE_DOS_HEADER)MmAllocateMemory(1024);
537
538 /* Make sure it was succesful */
539 if (ImageHeader == NULL) {
540
541 return FALSE;
542 }
543
544 /* Load the first 1024 bytes of the kernel image so we can read the PE header */
545 if (!FsReadFile(KernelImage, 1024, NULL, ImageHeader)) {
546
547 /* Fail if we couldn't read */
548 MmFreeMemory(ImageHeader);
549 return FALSE;
550 }
551
552 /* Now read the MZ header to get the offset to the PE Header */
553 NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)ImageHeader + ImageHeader->e_lfanew);
554
555 /* Save the Image Base */
556 KernelBase = NtHeader->OptionalHeader.ImageBase;
557
558 /* Save Entrypoint */
559 KernelEntry = RaToPa(NtHeader->OptionalHeader.AddressOfEntryPoint);
560
561 /* Save the Image Size */
562 ImageSize = NtHeader->OptionalHeader.SizeOfImage;
563
564 /* Free the Header */
565 MmFreeMemory(ImageHeader);
566
567 /* Set the file pointer to zero */
568 FsSetFilePointer(KernelImage, 0);
569
570 /* Load the file image */
571 FsReadFile(KernelImage, ImageSize, NULL, (PVOID)KERNEL_BASE_PHYS);
572
573 /* Reload the NT Header */
574 NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)KERNEL_BASE_PHYS + ImageHeader->e_lfanew);
575
576 /* Load the first section */
577 Section = IMAGE_FIRST_SECTION(NtHeader);
578 SectionCount = NtHeader->FileHeader.NumberOfSections - 1;
579
580 /* Now go to the last section */
581 Section += SectionCount;
582
583 /* Walk each section backwards */
584 for (i=SectionCount; i >= 0; i--, Section--) {
585
586 /* Get the disk location and the memory location, and the size */
587 SourceSection = RaToPa(Section->PointerToRawData);
588 TargetSection = RaToPa(Section->VirtualAddress);
589 SectionSize = Section->SizeOfRawData;
590
591 /* If the section is already mapped correctly, go to the next */
592 if (SourceSection == TargetSection) continue;
593
594 /* Load it into memory */
595 memmove((PVOID)TargetSection, (PVOID)SourceSection, SectionSize);
596
597 /* Check for unitilizated data */
598 if (Section->SizeOfRawData < Section->Misc.VirtualSize) {
599
600 /* Zero it out */
601 memset((PVOID)RaToPa(Section->VirtualAddress + Section->SizeOfRawData),
602 0,
603 Section->Misc.VirtualSize - Section->SizeOfRawData);
604 }
605 }
606
607 /* Now relocate the file */
608 /* FIXME: ADD RELOC CODE */
609
610 /* Increase the next Load Base */
611 NextModuleBase = ROUND_UP(KERNEL_BASE_PHYS + ImageSize, PAGE_SIZE);
612
613 /* Return Success */
614 return TRUE;
615 }
616
617 ULONG_PTR
618 STDCALL
619 FrLdrLoadModule(FILE *ModuleImage,
620 LPSTR ModuleName,
621 PULONG ModuleSize)
622 {
623 ULONG LocalModuleSize;
624 PFRLDR_MODULE ModuleData;
625 LPSTR NameBuffer;
626 LPSTR TempName;
627
628 /* Get current module data structure and module name string array */
629 ModuleData = &multiboot_modules[LoaderBlock.ModsCount];
630
631 /* Get only the Module Name */
632 do {
633
634 TempName = strchr(ModuleName, '\\');
635
636 if(TempName) {
637 ModuleName = TempName + 1;
638 }
639
640 } while(TempName);
641 NameBuffer = multiboot_module_strings[LoaderBlock.ModsCount];
642
643 /* Get Module Size */
644 LocalModuleSize = FsGetFileSize(ModuleImage);
645
646 /* Fill out Module Data Structure */
647 ModuleData->ModuleStart = NextModuleBase;
648 ModuleData->ModuleEnd = NextModuleBase + LocalModuleSize;
649
650 /* Save name */
651 strcpy(NameBuffer, ModuleName);
652 ModuleData->ModuleName = NameBuffer;
653
654 /* Load the file image */
655 FsReadFile(ModuleImage, LocalModuleSize, NULL, (PVOID)NextModuleBase);
656
657 /* Move to next memory block and increase Module Count */
658 NextModuleBase = ROUND_UP(ModuleData->ModuleEnd, PAGE_SIZE);
659 LoaderBlock.ModsCount++;
660
661 /* Return Module Size if required */
662 if (ModuleSize != NULL) {
663 *ModuleSize = LocalModuleSize;
664 }
665
666 return(ModuleData->ModuleStart);
667 }
668
669 ULONG_PTR
670 STDCALL
671 FrLdrCreateModule(LPSTR ModuleName)
672 {
673 PFRLDR_MODULE ModuleData;
674 LPSTR NameBuffer;
675
676 /* Get current module data structure and module name string array */
677 ModuleData = &multiboot_modules[LoaderBlock.ModsCount];
678 NameBuffer = multiboot_module_strings[LoaderBlock.ModsCount];
679
680 /* Set up the structure */
681 ModuleData->ModuleStart = NextModuleBase;
682 ModuleData->ModuleEnd = -1;
683
684 /* Copy the name */
685 strcpy(NameBuffer, ModuleName);
686 ModuleData->ModuleName = NameBuffer;
687
688 /* Set the current Module */
689 CurrentModule = ModuleData;
690
691 /* Return Module Base Address */
692 return(ModuleData->ModuleStart);
693 }
694
695 BOOL
696 STDCALL
697 FrLdrCloseModule(ULONG_PTR ModuleBase,
698 ULONG ModuleSize)
699 {
700 PFRLDR_MODULE ModuleData = CurrentModule;
701
702 /* Make sure a module is opened */
703 if (ModuleData) {
704
705 /* Make sure this is the right module and that it hasn't been closed */
706 if ((ModuleBase == ModuleData->ModuleStart) && (ModuleData->ModuleEnd == -1)) {
707
708 /* Close the Module */
709 ModuleData->ModuleEnd = ModuleData->ModuleStart + ModuleSize;
710
711 /* Set the next Module Base and increase the number of modules */
712 NextModuleBase = ROUND_UP(ModuleData->ModuleEnd, PAGE_SIZE);
713 LoaderBlock.ModsCount++;
714
715 /* Close the currently opened module */
716 CurrentModule = NULL;
717
718 /* Success */
719 return(TRUE);
720 }
721 }
722
723 /* Failure path */
724 return(FALSE);
725 }