2 * COPYRIGHT: See COPYING in the top level directory
4 * FILE: boot/freeldr/freeldr/multiboot.c
5 * PURPOSE: ReactOS Loader
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Hartmut Birr - SMP/PAE Code
11 #include <internal/i386/ke.h>
16 /* Base Addres of Kernel in Physical Memory */
17 #define KERNEL_BASE_PHYS 0x200000
19 /* Bits to shift to convert a Virtual Address into an Offset in the Page Table */
22 /* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */
24 #define PDE_SHIFT_PAE 18
27 /* Converts a Relative Address read from the Kernel into a Physical Address */
29 (ULONG_PTR)((ULONG_PTR)p + KERNEL_BASE_PHYS)
31 /* Converts a Phsyical Address Pointer into a Page Frame Number */
32 #define PaPtrToPfn(p) \
33 (((ULONG_PTR)&p) >> PFN_SHIFT)
35 /* Converts a Phsyical Address into a Page Frame Number */
39 #define STARTUP_BASE 0xF0000000
40 #define HYPERSPACE_BASE 0xF0800000
41 #define APIC_BASE 0xFEC00000
42 #define KPCR_BASE 0xFF000000
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)
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)
57 #define KernelEntryPoint (KernelEntry - KERNEL_BASE_PHYS) + KernelBase
59 /* Load Address of Next Module */
60 ULONG_PTR NextModuleBase
= 0;
62 /* Currently Opened Module */
63 PFRLDR_MODULE CurrentModule
= NULL
;
65 /* Unrelocated Kernel Base in Virtual Memory */
68 /* Wether PAE is to be used or not */
69 BOOLEAN PaeModeEnabled
;
71 /* Kernel Entrypoint in Physical Memory */
72 ULONG_PTR KernelEntry
;
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
;
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
;
93 typedef struct _HARDWARE_PTE_X86
{
97 ULONG WriteThrough
: 1;
98 ULONG CacheDisable
: 1;
103 ULONG CopyOnWrite
: 1;
106 ULONG PageFrameNumber
: 20;
107 } HARDWARE_PTE_X86
, *PHARDWARE_PTE_X86
;
109 typedef struct _HARDWARE_PTE_X64
{
113 ULONG WriteThrough
: 1;
114 ULONG CacheDisable
: 1;
119 ULONG CopyOnWrite
: 1;
122 ULONG PageFrameNumber
: 20;
123 ULONG reserved2
: 31;
125 } HARDWARE_PTE_X64
, *PHARDWARE_PTE_X64
;
127 typedef struct _PAGE_DIRECTORY_X86
{
128 HARDWARE_PTE_X86 Pde
[1024];
129 } PAGE_DIRECTORY_x86
, *PPAGE_DIRECTORY_X86
;
131 typedef struct _PAGE_DIRECTORY_X64
{
132 HARDWARE_PTE_X64 Pde
[2048];
133 } PAGE_DIRECTORY_X64
, *PPAGE_DIRECTORY_X64
;
135 typedef struct _PAGE_DIRECTORY_TABLE_X64
{
136 HARDWARE_PTE_X64 Pde
[4];
137 } PAGE_DIRECTORY_TABLE_X64
, *PPAGE_DIRECTORY_TABLE_X64
;
139 /* FUNCTIONS *****************************************************************/
145 * Prepares the system for loading the Kernel.
148 * Magic - Multiboot Magic
159 FrLdrStartup(ULONG Magic
)
161 /* Disable Interrupts */
162 Ke386DisableInterrupts();
164 /* Re-initalize EFLAGS */
167 /* Get the PAE Mode */
170 /* Initialize the page directory */
171 FrLdrSetupPageDirectory();
173 /* Initialize Paging, Write-Protection and Load NTOSKRNL */
174 FrLdrSetupPae(Magic
);
181 * Configures PAE on a MP System, and sets the PDBR if it's supported, or if
185 * Magic - Multiboot Magic
196 FrLdrSetupPae(ULONG Magic
)
198 ULONG_PTR PageDirectoryBaseAddress
= (ULONG_PTR
)&startup_pagedirectory
;
203 PageDirectoryBaseAddress
= (ULONG_PTR
)&startup_pagedirectorytable_pae
;
206 Ke386SetCr4(Ke386GetCr4() | X86_CR4_PAE
);
210 Ke386SetPageTableDirectory(PageDirectoryBaseAddress
);
212 /* Enable Paging and Write Protect*/
213 Ke386SetCr0(Ke386GetCr0() | X86_CR0_PG
| X86_CR0_WP
);
216 PagedJump
= (ASMCODE
)KernelEntryPoint
;
217 PagedJump(Magic
, &LoaderBlock
);
224 * Gets the Kernel Base to use.
232 * Sets both the FreeLdr internal variable as well as the one which
233 * will be used by the Kernel.
238 FrLdrGetKernelBase(VOID
)
242 /* Read Command Line */
243 p
= (PCHAR
)LoaderBlock
.CommandLine
;
244 while ((p
= strchr(p
, '/')) != NULL
) {
247 if (!strnicmp(p
+ 1, "3GB", 3)) {
249 /* Make sure there's nothing following it */
250 if (p
[4] == ' ' || p
[4] == 0) {
253 KernelBase
= 0xC0000000;
261 LoaderBlock
.KernelBase
= KernelBase
;
268 * Determines whether PAE mode shoudl be enabled or not.
282 FrLdrGetPaeMode(VOID
)
284 /* FIXME: Read command line */
285 PaeModeEnabled
= FALSE
;
293 * FrLdrSetupPageDirectory
296 * Sets up the ReactOS Startup Page Directory.
305 * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure.
306 * As such, please note that PageFrameNumber == PageEntryNumber.
311 FrLdrSetupPageDirectory(VOID
)
313 PPAGE_DIRECTORY_X86 PageDir
;
314 PPAGE_DIRECTORY_TABLE_X64 PageDirTablePae
;
315 PPAGE_DIRECTORY_X64 PageDirPae
;
316 ULONG KernelPageTableIndex
;
319 if (PaeModeEnabled
) {
321 /* Get the Kernel Table Index */
322 KernelPageTableIndex
= (KernelBase
>> 21);
324 /* Get the Startup Page Directory Table */
325 PageDirTablePae
= (PPAGE_DIRECTORY_TABLE_X64
)&startup_pagedirectorytable_pae
;
327 /* Get the Startup Page Directory */
328 PageDirPae
= (PPAGE_DIRECTORY_X64
)&startup_pagedirectory_pae
;
330 /* Set the Startup page directory table */
331 for (i
= 0; i
< 4; i
++)
333 PageDirTablePae
->Pde
[i
].Valid
= 1;
334 PageDirTablePae
->Pde
[i
].PageFrameNumber
= PaPtrToPfn(startup_pagedirectory_pae
) + i
;
337 /* Set up the Low Memory PDE */
338 for (i
= 0; i
< 2; i
++)
340 PageDirPae
->Pde
[LowMemPageTableIndexPae
+ i
].Valid
= 1;
341 PageDirPae
->Pde
[LowMemPageTableIndexPae
+ i
].Write
= 1;
342 PageDirPae
->Pde
[LowMemPageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(lowmem_pagetable_pae
) + i
;
345 /* Set up the Kernel PDEs */
346 for (i
= 0; i
< 3; i
++)
348 PageDirPae
->Pde
[KernelPageTableIndex
+ i
].Valid
= 1;
349 PageDirPae
->Pde
[KernelPageTableIndex
+ i
].Write
= 1;
350 PageDirPae
->Pde
[KernelPageTableIndex
+ i
].PageFrameNumber
= PaPtrToPfn(kernel_pagetable_pae
) + i
;
353 /* Set up the Startup PDE */
354 for (i
= 0; i
< 4; i
++)
356 PageDirPae
->Pde
[StartupPageTableIndexPae
+ i
].Valid
= 1;
357 PageDirPae
->Pde
[StartupPageTableIndexPae
+ i
].Write
= 1;
358 PageDirPae
->Pde
[StartupPageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(startup_pagedirectory_pae
) + i
;
361 /* Set up the Hyperspace PDE */
362 for (i
= 0; i
< 2; i
++)
364 PageDirPae
->Pde
[HyperspacePageTableIndexPae
+ i
].Valid
= 1;
365 PageDirPae
->Pde
[HyperspacePageTableIndexPae
+ i
].Write
= 1;
366 PageDirPae
->Pde
[HyperspacePageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(hyperspace_pagetable_pae
) + i
;
369 /* Set up the Apic PDE */
370 for (i
= 0; i
< 2; i
++)
372 PageDirPae
->Pde
[ApicPageTableIndexPae
+ i
].Valid
= 1;
373 PageDirPae
->Pde
[ApicPageTableIndexPae
+ i
].Write
= 1;
374 PageDirPae
->Pde
[ApicPageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(apic_pagetable_pae
) + i
;
377 /* Set up the KPCR PDE */
378 PageDirPae
->Pde
[KpcrPageTableIndexPae
].Valid
= 1;
379 PageDirPae
->Pde
[KpcrPageTableIndexPae
].Write
= 1;
380 PageDirPae
->Pde
[KpcrPageTableIndexPae
].PageFrameNumber
= PaPtrToPfn(kpcr_pagetable_pae
);
382 /* Set up Low Memory PTEs */
383 PageDirPae
= (PPAGE_DIRECTORY_X64
)&lowmem_pagetable_pae
;
384 for (i
=0; i
<1024; i
++) {
386 PageDirPae
->Pde
[i
].Valid
= 1;
387 PageDirPae
->Pde
[i
].Write
= 1;
388 PageDirPae
->Pde
[i
].Owner
= 1;
389 PageDirPae
->Pde
[i
].PageFrameNumber
= i
;
392 /* Set up Kernel PTEs */
393 PageDirPae
= (PPAGE_DIRECTORY_X64
)&kernel_pagetable_pae
;
394 for (i
=0; i
<1536; i
++) {
396 PageDirPae
->Pde
[i
].Valid
= 1;
397 PageDirPae
->Pde
[i
].Write
= 1;
398 PageDirPae
->Pde
[i
].PageFrameNumber
= PaToPfn(KERNEL_BASE_PHYS
) + i
;
401 /* Set up APIC PTEs */
402 PageDirPae
= (PPAGE_DIRECTORY_X64
)&apic_pagetable_pae
;
403 PageDirPae
->Pde
[0].Valid
= 1;
404 PageDirPae
->Pde
[0].Write
= 1;
405 PageDirPae
->Pde
[0].CacheDisable
= 1;
406 PageDirPae
->Pde
[0].WriteThrough
= 1;
407 PageDirPae
->Pde
[0].PageFrameNumber
= PaToPfn(APIC_BASE
);
408 PageDirPae
->Pde
[0x200].Valid
= 1;
409 PageDirPae
->Pde
[0x200].Write
= 1;
410 PageDirPae
->Pde
[0x200].CacheDisable
= 1;
411 PageDirPae
->Pde
[0x200].WriteThrough
= 1;
412 PageDirPae
->Pde
[0x200].PageFrameNumber
= PaToPfn(APIC_BASE
+ KERNEL_BASE_PHYS
);
414 /* Set up KPCR PTEs */
415 PageDirPae
= (PPAGE_DIRECTORY_X64
)&kpcr_pagetable_pae
;
416 PageDirPae
->Pde
[0].Valid
= 1;
417 PageDirPae
->Pde
[0].Write
= 1;
418 PageDirPae
->Pde
[0].PageFrameNumber
= 1;
422 /* Get the Kernel Table Index */
423 KernelPageTableIndex
= (KernelBase
>> PDE_SHIFT
) / sizeof(HARDWARE_PTE_X86
);
425 /* Get the Startup Page Directory */
426 PageDir
= (PPAGE_DIRECTORY_X86
)&startup_pagedirectory
;
428 /* Set up the Low Memory PDE */
429 PageDir
->Pde
[LowMemPageTableIndex
].Valid
= 1;
430 PageDir
->Pde
[LowMemPageTableIndex
].Write
= 1;
431 PageDir
->Pde
[LowMemPageTableIndex
].PageFrameNumber
= PaPtrToPfn(lowmem_pagetable
);
433 /* Set up the Kernel PDEs */
434 PageDir
->Pde
[KernelPageTableIndex
].Valid
= 1;
435 PageDir
->Pde
[KernelPageTableIndex
].Write
= 1;
436 PageDir
->Pde
[KernelPageTableIndex
].PageFrameNumber
= PaPtrToPfn(kernel_pagetable
);
437 PageDir
->Pde
[KernelPageTableIndex
+ 1].Valid
= 1;
438 PageDir
->Pde
[KernelPageTableIndex
+ 1].Write
= 1;
439 PageDir
->Pde
[KernelPageTableIndex
+ 1].PageFrameNumber
= PaPtrToPfn(kernel_pagetable
+ 4096);
441 /* Set up the Startup PDE */
442 PageDir
->Pde
[StartupPageTableIndex
].Valid
= 1;
443 PageDir
->Pde
[StartupPageTableIndex
].Write
= 1;
444 PageDir
->Pde
[StartupPageTableIndex
].PageFrameNumber
= PaPtrToPfn(startup_pagedirectory
);
446 /* Set up the Hyperspace PDE */
447 PageDir
->Pde
[HyperspacePageTableIndex
].Valid
= 1;
448 PageDir
->Pde
[HyperspacePageTableIndex
].Write
= 1;
449 PageDir
->Pde
[HyperspacePageTableIndex
].PageFrameNumber
= PaPtrToPfn(hyperspace_pagetable
);
451 /* Set up the Apic PDE */
452 PageDir
->Pde
[ApicPageTableIndex
].Valid
= 1;
453 PageDir
->Pde
[ApicPageTableIndex
].Write
= 1;
454 PageDir
->Pde
[ApicPageTableIndex
].PageFrameNumber
= PaPtrToPfn(apic_pagetable
);
456 /* Set up the KPCR PDE */
457 PageDir
->Pde
[KpcrPageTableIndex
].Valid
= 1;
458 PageDir
->Pde
[KpcrPageTableIndex
].Write
= 1;
459 PageDir
->Pde
[KpcrPageTableIndex
].PageFrameNumber
= PaPtrToPfn(kpcr_pagetable
);
461 /* Set up Low Memory PTEs */
462 PageDir
= (PPAGE_DIRECTORY_X86
)&lowmem_pagetable
;
463 for (i
=0; i
<1024; i
++) {
465 PageDir
->Pde
[i
].Valid
= 1;
466 PageDir
->Pde
[i
].Write
= 1;
467 PageDir
->Pde
[i
].Owner
= 1;
468 PageDir
->Pde
[i
].PageFrameNumber
= PaToPfn(i
* PAGE_SIZE
);
471 /* Set up Kernel PTEs */
472 PageDir
= (PPAGE_DIRECTORY_X86
)&kernel_pagetable
;
473 for (i
=0; i
<1536; i
++) {
475 PageDir
->Pde
[i
].Valid
= 1;
476 PageDir
->Pde
[i
].Write
= 1;
477 PageDir
->Pde
[i
].PageFrameNumber
= PaToPfn(KERNEL_BASE_PHYS
+ i
* PAGE_SIZE
);
480 /* Set up APIC PTEs */
481 PageDir
= (PPAGE_DIRECTORY_X86
)&apic_pagetable
;
482 PageDir
->Pde
[0].Valid
= 1;
483 PageDir
->Pde
[0].Write
= 1;
484 PageDir
->Pde
[0].CacheDisable
= 1;
485 PageDir
->Pde
[0].WriteThrough
= 1;
486 PageDir
->Pde
[0].PageFrameNumber
= PaToPfn(APIC_BASE
);
487 PageDir
->Pde
[0x200].Valid
= 1;
488 PageDir
->Pde
[0x200].Write
= 1;
489 PageDir
->Pde
[0x200].CacheDisable
= 1;
490 PageDir
->Pde
[0x200].WriteThrough
= 1;
491 PageDir
->Pde
[0x200].PageFrameNumber
= PaToPfn(APIC_BASE
+ KERNEL_BASE_PHYS
);
493 /* Set up KPCR PTEs */
494 PageDir
= (PPAGE_DIRECTORY_X86
)&kpcr_pagetable
;
495 PageDir
->Pde
[0].Valid
= 1;
496 PageDir
->Pde
[0].Write
= 1;
497 PageDir
->Pde
[0].PageFrameNumber
= 1;
506 * Maps the Kernel into memory, does PE Section Mapping, initalizes the
507 * uninitialized data sections, and relocates the image.
510 * KernelImage - FILE Structure representing the ntoskrnl image file.
513 * TRUE if the Kernel was mapped.
521 FrLdrMapKernel(FILE *KernelImage
)
523 PIMAGE_DOS_HEADER ImageHeader
;
524 PIMAGE_NT_HEADERS NtHeader
;
525 PIMAGE_SECTION_HEADER Section
;
528 ULONG_PTR SourceSection
;
529 ULONG_PTR TargetSection
;
532 PIMAGE_DATA_DIRECTORY RelocationDDir
;
533 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
535 ULONG_PTR Address
, MaxAddress
;
541 /* Allocate 1024 bytes for PE Header */
542 ImageHeader
= (PIMAGE_DOS_HEADER
)MmAllocateMemory(1024);
544 /* Make sure it was succesful */
545 if (ImageHeader
== NULL
) {
550 /* Load the first 1024 bytes of the kernel image so we can read the PE header */
551 if (!FsReadFile(KernelImage
, 1024, NULL
, ImageHeader
)) {
553 /* Fail if we couldn't read */
554 MmFreeMemory(ImageHeader
);
558 /* Now read the MZ header to get the offset to the PE Header */
559 NtHeader
= (PIMAGE_NT_HEADERS
)((PCHAR
)ImageHeader
+ ImageHeader
->e_lfanew
);
561 /* Get Kernel Base */
562 KernelBase
= NtHeader
->OptionalHeader
.ImageBase
;
563 FrLdrGetKernelBase();
565 /* Save Entrypoint */
566 KernelEntry
= RaToPa(NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
568 /* Save the Image Size */
569 ImageSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
571 /* Free the Header */
572 MmFreeMemory(ImageHeader
);
574 /* Set the file pointer to zero */
575 FsSetFilePointer(KernelImage
, 0);
577 /* Load the file image */
578 FsReadFile(KernelImage
, ImageSize
, NULL
, (PVOID
)KERNEL_BASE_PHYS
);
580 /* Reload the NT Header */
581 NtHeader
= (PIMAGE_NT_HEADERS
)((PCHAR
)KERNEL_BASE_PHYS
+ ImageHeader
->e_lfanew
);
583 /* Load the first section */
584 Section
= IMAGE_FIRST_SECTION(NtHeader
);
585 SectionCount
= NtHeader
->FileHeader
.NumberOfSections
- 1;
587 /* Now go to the last section */
588 Section
+= SectionCount
;
590 /* Walk each section backwards */
591 for (i
=SectionCount
; i
>= 0; i
--, Section
--) {
593 /* Get the disk location and the memory location, and the size */
594 SourceSection
= RaToPa(Section
->PointerToRawData
);
595 TargetSection
= RaToPa(Section
->VirtualAddress
);
596 SectionSize
= Section
->SizeOfRawData
;
598 /* If the section is already mapped correctly, go to the next */
599 if (SourceSection
== TargetSection
) continue;
601 /* Load it into memory */
602 memmove((PVOID
)TargetSection
, (PVOID
)SourceSection
, SectionSize
);
604 /* Check for unitilizated data */
605 if (Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
) {
608 memset((PVOID
)RaToPa(Section
->VirtualAddress
+ Section
->SizeOfRawData
),
610 Section
->Misc
.VirtualSize
- Section
->SizeOfRawData
);
614 /* Get the Relocation Data Directory */
615 RelocationDDir
= &NtHeader
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
617 /* Get the Relocation Section Start and End*/
618 RelocationDir
= (PIMAGE_BASE_RELOCATION
)(KERNEL_BASE_PHYS
+ RelocationDDir
->VirtualAddress
);
619 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDDir
->Size
);
621 /* Calculate Difference between Real Base and Compiled Base*/
622 Delta
= KernelBase
- NtHeader
->OptionalHeader
.ImageBase
;
624 /* Determine how far we shoudl relocate */
625 MaxAddress
= KERNEL_BASE_PHYS
+ ImageSize
;
627 /* Relocate until we've processed all the blocks */
628 while (RelocationDir
< RelocationEnd
&& RelocationDir
->SizeOfBlock
> 0) {
630 /* See how many Relocation Blocks we have */
631 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
633 /* Calculate the Address of this Directory */
634 Address
= KERNEL_BASE_PHYS
+ RelocationDir
->VirtualAddress
;
636 /* Calculate the Offset of the Type */
637 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
639 for (i
= 0; i
< Count
; i
++) {
641 ShortPtr
= (PUSHORT
)(Address
+ (*TypeOffset
& 0xFFF));
643 /* Don't relocate after the end of the loaded driver */
644 if ((ULONG_PTR
)ShortPtr
>= MaxAddress
) break;
646 switch (*TypeOffset
>> 12) {
648 case IMAGE_REL_BASED_ABSOLUTE
:
651 case IMAGE_REL_BASED_HIGH
:
652 *ShortPtr
+= HIWORD(Delta
);
655 case IMAGE_REL_BASED_LOW
:
656 *ShortPtr
+= LOWORD(Delta
);
659 case IMAGE_REL_BASED_HIGHLOW
:
660 LongPtr
= (PULONG
)ShortPtr
;
668 /* Move to the next Relocation Table */
669 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDir
->SizeOfBlock
);
672 /* Increase the next Load Base */
673 NextModuleBase
= ROUND_UP(KERNEL_BASE_PHYS
+ ImageSize
, PAGE_SIZE
);
681 FrLdrLoadModule(FILE *ModuleImage
,
685 ULONG LocalModuleSize
;
686 PFRLDR_MODULE ModuleData
;
690 /* Get current module data structure and module name string array */
691 ModuleData
= &multiboot_modules
[LoaderBlock
.ModsCount
];
693 /* Get only the Module Name */
696 TempName
= strchr(ModuleName
, '\\');
699 ModuleName
= TempName
+ 1;
703 NameBuffer
= multiboot_module_strings
[LoaderBlock
.ModsCount
];
705 /* Get Module Size */
706 LocalModuleSize
= FsGetFileSize(ModuleImage
);
708 /* Fill out Module Data Structure */
709 ModuleData
->ModuleStart
= NextModuleBase
;
710 ModuleData
->ModuleEnd
= NextModuleBase
+ LocalModuleSize
;
713 strcpy(NameBuffer
, ModuleName
);
714 ModuleData
->ModuleName
= NameBuffer
;
716 /* Load the file image */
717 FsReadFile(ModuleImage
, LocalModuleSize
, NULL
, (PVOID
)NextModuleBase
);
719 /* Move to next memory block and increase Module Count */
720 NextModuleBase
= ROUND_UP(ModuleData
->ModuleEnd
, PAGE_SIZE
);
721 LoaderBlock
.ModsCount
++;
723 /* Return Module Size if required */
724 if (ModuleSize
!= NULL
) {
725 *ModuleSize
= LocalModuleSize
;
728 return(ModuleData
->ModuleStart
);
733 FrLdrCreateModule(LPSTR ModuleName
)
735 PFRLDR_MODULE ModuleData
;
738 /* Get current module data structure and module name string array */
739 ModuleData
= &multiboot_modules
[LoaderBlock
.ModsCount
];
740 NameBuffer
= multiboot_module_strings
[LoaderBlock
.ModsCount
];
742 /* Set up the structure */
743 ModuleData
->ModuleStart
= NextModuleBase
;
744 ModuleData
->ModuleEnd
= -1;
747 strcpy(NameBuffer
, ModuleName
);
748 ModuleData
->ModuleName
= NameBuffer
;
750 /* Set the current Module */
751 CurrentModule
= ModuleData
;
753 /* Return Module Base Address */
754 return(ModuleData
->ModuleStart
);
759 FrLdrCloseModule(ULONG_PTR ModuleBase
,
762 PFRLDR_MODULE ModuleData
= CurrentModule
;
764 /* Make sure a module is opened */
767 /* Make sure this is the right module and that it hasn't been closed */
768 if ((ModuleBase
== ModuleData
->ModuleStart
) && (ModuleData
->ModuleEnd
== -1)) {
770 /* Close the Module */
771 ModuleData
->ModuleEnd
= ModuleData
->ModuleStart
+ ModuleSize
;
773 /* Set the next Module Base and increase the number of modules */
774 NextModuleBase
= ROUND_UP(ModuleData
->ModuleEnd
, PAGE_SIZE
);
775 LoaderBlock
.ModsCount
++;
777 /* Close the currently opened module */
778 CurrentModule
= NULL
;