3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 * Copyright (C) 2005 Alex Ionescu <alex@relsoft.net>
5 * Copyright (C) 2005 Hartmut Birr <hartmut.birr@gmx.de>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include <../arch/i386/hardware.h>
24 #include <internal/i386/ke.h>
29 /* Base Addres of Kernel in Physical Memory */
30 #define KERNEL_BASE_PHYS 0x200000
32 /* Bits to shift to convert a Virtual Address into an Offset in the Page Table */
35 /* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */
37 #define PDE_SHIFT_PAE 18
40 /* Converts a Relative Address read from the Kernel into a Physical Address */
42 (ULONG_PTR)((ULONG_PTR)p + KERNEL_BASE_PHYS)
44 /* Converts a Phsyical Address Pointer into a Page Frame Number */
45 #define PaPtrToPfn(p) \
46 (((ULONG_PTR)&p) >> PFN_SHIFT)
48 /* Converts a Phsyical Address into a Page Frame Number */
52 #define STARTUP_BASE 0xC0000000
53 #define HYPERSPACE_BASE 0xC0400000
54 #define HYPERSPACE_PAE_BASE 0xC0800000
55 #define APIC_BASE 0xFEC00000
56 #define KPCR_BASE 0xFF000000
58 #define LowMemPageTableIndex 0
59 #define StartupPageTableIndex (STARTUP_BASE >> 22)
60 #define HyperspacePageTableIndex (HYPERSPACE_BASE >> 22)
61 #define KpcrPageTableIndex (KPCR_BASE >> 22)
62 #define ApicPageTableIndex (APIC_BASE >> 22)
64 #define LowMemPageTableIndexPae 0
65 #define StartupPageTableIndexPae (STARTUP_BASE >> 21)
66 #define HyperspacePageTableIndexPae (HYPERSPACE_PAE_BASE >> 21)
67 #define KpcrPageTableIndexPae (KPCR_BASE >> 21)
68 #define ApicPageTableIndexPae (APIC_BASE >> 21)
71 #define KernelEntryPoint (KernelEntry - KERNEL_BASE_PHYS) + KernelBase
73 /* Load Address of Next Module */
74 ULONG_PTR NextModuleBase
= 0;
76 /* Currently Opened Module */
77 PLOADER_MODULE CurrentModule
= NULL
;
79 /* Unrelocated Kernel Base in Virtual Memory */
82 /* Wether PAE is to be used or not */
83 BOOLEAN PaeModeEnabled
;
85 /* Kernel Entrypoint in Physical Memory */
86 ULONG_PTR KernelEntry
;
88 typedef struct _HARDWARE_PTE_X64
{
92 ULONG WriteThrough
: 1;
93 ULONG CacheDisable
: 1;
98 ULONG CopyOnWrite
: 1;
101 ULONG PageFrameNumber
: 20;
102 ULONG reserved2
: 31;
104 } HARDWARE_PTE_X64
, *PHARDWARE_PTE_X64
;
106 typedef struct _PAGE_DIRECTORY_X86
{
107 HARDWARE_PTE_X86 Pde
[1024];
108 } PAGE_DIRECTORY_X86
, *PPAGE_DIRECTORY_X86
;
110 typedef struct _PAGE_DIRECTORY_X64
{
111 HARDWARE_PTE_X64 Pde
[2048];
112 } PAGE_DIRECTORY_X64
, *PPAGE_DIRECTORY_X64
;
114 typedef struct _PAGE_DIRECTORY_TABLE_X64
{
115 HARDWARE_PTE_X64 Pde
[4];
116 } PAGE_DIRECTORY_TABLE_X64
, *PPAGE_DIRECTORY_TABLE_X64
;
118 /* Page Directory and Tables for non-PAE Systems */
119 extern PAGE_DIRECTORY_X86 startup_pagedirectory
;
120 extern PAGE_DIRECTORY_X86 lowmem_pagetable
;
121 extern PAGE_DIRECTORY_X86 kernel_pagetable
;
122 extern ULONG_PTR hyperspace_pagetable
;
123 extern ULONG_PTR _pae_pagedirtable
;
124 extern PAGE_DIRECTORY_X86 apic_pagetable
;
125 extern PAGE_DIRECTORY_X86 kpcr_pagetable
;
127 /* Page Directory and Tables for PAE Systems */
128 extern PAGE_DIRECTORY_TABLE_X64 startup_pagedirectorytable_pae
;
129 extern PAGE_DIRECTORY_X64 startup_pagedirectory_pae
;
130 extern PAGE_DIRECTORY_X64 lowmem_pagetable_pae
;
131 extern PAGE_DIRECTORY_X64 kernel_pagetable_pae
;
132 extern ULONG_PTR hyperspace_pagetable_pae
;
133 extern ULONG_PTR pagedirtable_pae
;
134 extern PAGE_DIRECTORY_X64 apic_pagetable_pae
;
135 extern PAGE_DIRECTORY_X64 kpcr_pagetable_pae
;
137 /* FUNCTIONS *****************************************************************/
143 * Prepares the system for loading the Kernel.
146 * Magic - Multiboot Magic
157 FrLdrStartup(ULONG Magic
)
159 /* Disable Interrupts */
160 Ke386DisableInterrupts();
162 /* Re-initalize EFLAGS */
165 /* Get the PAE Mode */
168 /* Initialize the page directory */
169 FrLdrSetupPageDirectory();
171 /* Initialize Paging, Write-Protection and Load NTOSKRNL */
172 FrLdrSetupPae(Magic
);
179 * Configures PAE on a MP System, and sets the PDBR if it's supported, or if
183 * Magic - Multiboot Magic
194 FrLdrSetupPae(ULONG Magic
)
196 ULONG_PTR PageDirectoryBaseAddress
= (ULONG_PTR
)&startup_pagedirectory
;
201 PageDirectoryBaseAddress
= (ULONG_PTR
)&startup_pagedirectorytable_pae
;
204 Ke386SetCr4(Ke386GetCr4() | X86_CR4_PAE
);
208 Ke386SetPageTableDirectory(PageDirectoryBaseAddress
);
210 /* Enable Paging and Write Protect*/
211 Ke386SetCr0(Ke386GetCr0() | X86_CR0_PG
| X86_CR0_WP
);
214 PagedJump
= (ASMCODE
)(PVOID
)(KernelEntryPoint
);
215 PagedJump(Magic
, &LoaderBlock
);
222 * Gets the Kernel Base to use.
230 * Sets both the FreeLdr internal variable as well as the one which
231 * will be used by the Kernel.
236 FrLdrGetKernelBase(VOID
)
241 LoaderBlock
.KernelBase
= KernelBase
;
243 /* Read Command Line */
244 p
= (PCHAR
)LoaderBlock
.CommandLine
;
245 while ((p
= strchr(p
, '/')) != NULL
) {
248 if (!strnicmp(p
+ 1, "3GB", 3)) {
250 /* Make sure there's nothing following it */
251 if (p
[4] == ' ' || p
[4] == 0) {
254 KernelBase
= 0xE0000000;
255 LoaderBlock
.KernelBase
= 0xC0000000;
267 * Determines whether PAE mode shoudl be enabled or not.
281 FrLdrGetPaeMode(VOID
)
283 BOOLEAN PaeModeSupported
;
285 PaeModeSupported
= FALSE
;
286 PaeModeEnabled
= FALSE
;
288 if (CpuidSupported() & 1)
290 ULONG eax
, ebx
, ecx
, FeatureBits
;
291 GetCpuid(1, &eax
, &ebx
, &ecx
, &FeatureBits
);
292 if (FeatureBits
& X86_FEATURE_PAE
)
294 PaeModeSupported
= TRUE
;
298 if (PaeModeSupported
)
302 /* Read Command Line */
303 p
= (PCHAR
)LoaderBlock
.CommandLine
;
304 while ((p
= strchr(p
, '/')) != NULL
) {
308 if (!strnicmp(p
, "PAE", 3)) {
310 /* Make sure there's nothing following it */
311 if (p
[3] == ' ' || p
[3] == 0) {
314 PaeModeEnabled
= TRUE
;
323 * FrLdrSetupPageDirectory
326 * Sets up the ReactOS Startup Page Directory.
335 * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure.
336 * As such, please note that PageFrameNumber == PageEntryNumber.
341 FrLdrSetupPageDirectory(VOID
)
343 PPAGE_DIRECTORY_X86 PageDir
;
344 PPAGE_DIRECTORY_TABLE_X64 PageDirTablePae
;
345 PPAGE_DIRECTORY_X64 PageDirPae
;
346 ULONG KernelPageTableIndex
;
349 if (PaeModeEnabled
) {
351 /* Get the Kernel Table Index */
352 KernelPageTableIndex
= (KernelBase
>> 21);
354 /* Get the Startup Page Directory Table */
355 PageDirTablePae
= (PPAGE_DIRECTORY_TABLE_X64
)&startup_pagedirectorytable_pae
;
357 /* Get the Startup Page Directory */
358 PageDirPae
= (PPAGE_DIRECTORY_X64
)&startup_pagedirectory_pae
;
360 /* Set the Startup page directory table */
361 for (i
= 0; i
< 4; i
++)
363 PageDirTablePae
->Pde
[i
].Valid
= 1;
364 PageDirTablePae
->Pde
[i
].PageFrameNumber
= PaPtrToPfn(startup_pagedirectory_pae
) + i
;
367 /* Set up the Low Memory PDE */
368 for (i
= 0; i
< 2; i
++)
370 PageDirPae
->Pde
[LowMemPageTableIndexPae
+ i
].Valid
= 1;
371 PageDirPae
->Pde
[LowMemPageTableIndexPae
+ i
].Write
= 1;
372 PageDirPae
->Pde
[LowMemPageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(lowmem_pagetable_pae
) + i
;
375 /* Set up the Kernel PDEs */
376 for (i
= 0; i
< 3; i
++)
378 PageDirPae
->Pde
[KernelPageTableIndex
+ i
].Valid
= 1;
379 PageDirPae
->Pde
[KernelPageTableIndex
+ i
].Write
= 1;
380 PageDirPae
->Pde
[KernelPageTableIndex
+ i
].PageFrameNumber
= PaPtrToPfn(kernel_pagetable_pae
) + i
;
383 /* Set up the Startup PDE */
384 for (i
= 0; i
< 4; i
++)
386 PageDirPae
->Pde
[StartupPageTableIndexPae
+ i
].Valid
= 1;
387 PageDirPae
->Pde
[StartupPageTableIndexPae
+ i
].Write
= 1;
388 PageDirPae
->Pde
[StartupPageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(startup_pagedirectory_pae
) + i
;
391 /* Set up the Hyperspace PDE */
392 for (i
= 0; i
< 2; i
++)
394 PageDirPae
->Pde
[HyperspacePageTableIndexPae
+ i
].Valid
= 1;
395 PageDirPae
->Pde
[HyperspacePageTableIndexPae
+ i
].Write
= 1;
396 PageDirPae
->Pde
[HyperspacePageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(hyperspace_pagetable_pae
) + i
;
399 /* Set up the Apic PDE */
400 for (i
= 0; i
< 2; i
++)
402 PageDirPae
->Pde
[ApicPageTableIndexPae
+ i
].Valid
= 1;
403 PageDirPae
->Pde
[ApicPageTableIndexPae
+ i
].Write
= 1;
404 PageDirPae
->Pde
[ApicPageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(apic_pagetable_pae
) + i
;
407 /* Set up the KPCR PDE */
408 PageDirPae
->Pde
[KpcrPageTableIndexPae
].Valid
= 1;
409 PageDirPae
->Pde
[KpcrPageTableIndexPae
].Write
= 1;
410 PageDirPae
->Pde
[KpcrPageTableIndexPae
].PageFrameNumber
= PaPtrToPfn(kpcr_pagetable_pae
);
412 /* Set up Low Memory PTEs */
413 PageDirPae
= (PPAGE_DIRECTORY_X64
)&lowmem_pagetable_pae
;
414 for (i
=0; i
<1024; i
++) {
416 PageDirPae
->Pde
[i
].Valid
= 1;
417 PageDirPae
->Pde
[i
].Write
= 1;
418 PageDirPae
->Pde
[i
].Owner
= 1;
419 PageDirPae
->Pde
[i
].PageFrameNumber
= i
;
422 /* Set up Kernel PTEs */
423 PageDirPae
= (PPAGE_DIRECTORY_X64
)&kernel_pagetable_pae
;
424 for (i
=0; i
<1536; i
++) {
426 PageDirPae
->Pde
[i
].Valid
= 1;
427 PageDirPae
->Pde
[i
].Write
= 1;
428 PageDirPae
->Pde
[i
].PageFrameNumber
= PaToPfn(KERNEL_BASE_PHYS
) + i
;
431 /* Set up APIC PTEs */
432 PageDirPae
= (PPAGE_DIRECTORY_X64
)&apic_pagetable_pae
;
433 PageDirPae
->Pde
[0].Valid
= 1;
434 PageDirPae
->Pde
[0].Write
= 1;
435 PageDirPae
->Pde
[0].CacheDisable
= 1;
436 PageDirPae
->Pde
[0].WriteThrough
= 1;
437 PageDirPae
->Pde
[0].PageFrameNumber
= PaToPfn(APIC_BASE
);
438 PageDirPae
->Pde
[0x200].Valid
= 1;
439 PageDirPae
->Pde
[0x200].Write
= 1;
440 PageDirPae
->Pde
[0x200].CacheDisable
= 1;
441 PageDirPae
->Pde
[0x200].WriteThrough
= 1;
442 PageDirPae
->Pde
[0x200].PageFrameNumber
= PaToPfn(APIC_BASE
+ KERNEL_BASE_PHYS
);
444 /* Set up KPCR PTEs */
445 PageDirPae
= (PPAGE_DIRECTORY_X64
)&kpcr_pagetable_pae
;
446 PageDirPae
->Pde
[0].Valid
= 1;
447 PageDirPae
->Pde
[0].Write
= 1;
448 PageDirPae
->Pde
[0].PageFrameNumber
= 1;
452 /* Get the Kernel Table Index */
453 KernelPageTableIndex
= KernelBase
>> PDE_SHIFT
;
455 /* Get the Startup Page Directory */
456 PageDir
= (PPAGE_DIRECTORY_X86
)&startup_pagedirectory
;
458 /* Set up the Low Memory PDE */
459 PageDir
->Pde
[LowMemPageTableIndex
].Valid
= 1;
460 PageDir
->Pde
[LowMemPageTableIndex
].Write
= 1;
461 PageDir
->Pde
[LowMemPageTableIndex
].PageFrameNumber
= PaPtrToPfn(lowmem_pagetable
);
463 /* Set up the Kernel PDEs */
464 PageDir
->Pde
[KernelPageTableIndex
].Valid
= 1;
465 PageDir
->Pde
[KernelPageTableIndex
].Write
= 1;
466 PageDir
->Pde
[KernelPageTableIndex
].PageFrameNumber
= PaPtrToPfn(kernel_pagetable
);
467 PageDir
->Pde
[KernelPageTableIndex
+ 1].Valid
= 1;
468 PageDir
->Pde
[KernelPageTableIndex
+ 1].Write
= 1;
469 PageDir
->Pde
[KernelPageTableIndex
+ 1].PageFrameNumber
= PaPtrToPfn(kernel_pagetable
+ 4096);
471 /* Set up the Startup PDE */
472 PageDir
->Pde
[StartupPageTableIndex
].Valid
= 1;
473 PageDir
->Pde
[StartupPageTableIndex
].Write
= 1;
474 PageDir
->Pde
[StartupPageTableIndex
].PageFrameNumber
= PaPtrToPfn(startup_pagedirectory
);
476 /* Set up the Hyperspace PDE */
477 PageDir
->Pde
[HyperspacePageTableIndex
].Valid
= 1;
478 PageDir
->Pde
[HyperspacePageTableIndex
].Write
= 1;
479 PageDir
->Pde
[HyperspacePageTableIndex
].PageFrameNumber
= PaPtrToPfn(hyperspace_pagetable
);
481 /* Set up the Apic PDE */
482 PageDir
->Pde
[ApicPageTableIndex
].Valid
= 1;
483 PageDir
->Pde
[ApicPageTableIndex
].Write
= 1;
484 PageDir
->Pde
[ApicPageTableIndex
].PageFrameNumber
= PaPtrToPfn(apic_pagetable
);
486 /* Set up the KPCR PDE */
487 PageDir
->Pde
[KpcrPageTableIndex
].Valid
= 1;
488 PageDir
->Pde
[KpcrPageTableIndex
].Write
= 1;
489 PageDir
->Pde
[KpcrPageTableIndex
].PageFrameNumber
= PaPtrToPfn(kpcr_pagetable
);
491 /* Set up Low Memory PTEs */
492 PageDir
= (PPAGE_DIRECTORY_X86
)&lowmem_pagetable
;
493 for (i
=0; i
<1024; i
++) {
495 PageDir
->Pde
[i
].Valid
= 1;
496 PageDir
->Pde
[i
].Write
= 1;
497 PageDir
->Pde
[i
].Owner
= 1;
498 PageDir
->Pde
[i
].PageFrameNumber
= PaToPfn(i
* PAGE_SIZE
);
501 /* Set up Kernel PTEs */
502 PageDir
= (PPAGE_DIRECTORY_X86
)&kernel_pagetable
;
503 for (i
=0; i
<1536; i
++) {
505 PageDir
->Pde
[i
].Valid
= 1;
506 PageDir
->Pde
[i
].Write
= 1;
507 PageDir
->Pde
[i
].PageFrameNumber
= PaToPfn(KERNEL_BASE_PHYS
+ i
* PAGE_SIZE
);
510 /* Set up APIC PTEs */
511 PageDir
= (PPAGE_DIRECTORY_X86
)&apic_pagetable
;
512 PageDir
->Pde
[0].Valid
= 1;
513 PageDir
->Pde
[0].Write
= 1;
514 PageDir
->Pde
[0].CacheDisable
= 1;
515 PageDir
->Pde
[0].WriteThrough
= 1;
516 PageDir
->Pde
[0].PageFrameNumber
= PaToPfn(APIC_BASE
);
517 PageDir
->Pde
[0x200].Valid
= 1;
518 PageDir
->Pde
[0x200].Write
= 1;
519 PageDir
->Pde
[0x200].CacheDisable
= 1;
520 PageDir
->Pde
[0x200].WriteThrough
= 1;
521 PageDir
->Pde
[0x200].PageFrameNumber
= PaToPfn(APIC_BASE
+ KERNEL_BASE_PHYS
);
523 /* Set up KPCR PTEs */
524 PageDir
= (PPAGE_DIRECTORY_X86
)&kpcr_pagetable
;
525 PageDir
->Pde
[0].Valid
= 1;
526 PageDir
->Pde
[0].Write
= 1;
527 PageDir
->Pde
[0].PageFrameNumber
= 1;
536 * Maps the Kernel into memory, does PE Section Mapping, initalizes the
537 * uninitialized data sections, and relocates the image.
540 * KernelImage - FILE Structure representing the ntoskrnl image file.
543 * TRUE if the Kernel was mapped.
551 FrLdrMapKernel(FILE *KernelImage
)
553 PIMAGE_DOS_HEADER ImageHeader
;
554 PIMAGE_NT_HEADERS NtHeader
;
555 PIMAGE_SECTION_HEADER Section
;
558 ULONG_PTR SourceSection
;
559 ULONG_PTR TargetSection
;
562 PIMAGE_DATA_DIRECTORY RelocationDDir
;
563 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
565 ULONG_PTR Address
, MaxAddress
;
571 /* Allocate 1024 bytes for PE Header */
572 ImageHeader
= (PIMAGE_DOS_HEADER
)MmAllocateMemory(1024);
574 /* Make sure it was succesful */
575 if (ImageHeader
== NULL
) {
580 /* Load the first 1024 bytes of the kernel image so we can read the PE header */
581 if (!FsReadFile(KernelImage
, 1024, NULL
, ImageHeader
)) {
583 /* Fail if we couldn't read */
584 MmFreeMemory(ImageHeader
);
588 /* Now read the MZ header to get the offset to the PE Header */
589 NtHeader
= (PIMAGE_NT_HEADERS
)((PCHAR
)ImageHeader
+ ImageHeader
->e_lfanew
);
591 /* Get Kernel Base */
592 KernelBase
= NtHeader
->OptionalHeader
.ImageBase
;
593 FrLdrGetKernelBase();
595 /* Save Entrypoint */
596 KernelEntry
= RaToPa(NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
598 /* Save the Image Size */
599 ImageSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
601 /* Free the Header */
602 MmFreeMemory(ImageHeader
);
604 /* Set the file pointer to zero */
605 FsSetFilePointer(KernelImage
, 0);
607 /* Load the file image */
608 FsReadFile(KernelImage
, ImageSize
, NULL
, (PVOID
)KERNEL_BASE_PHYS
);
610 /* Reload the NT Header */
611 NtHeader
= (PIMAGE_NT_HEADERS
)((PCHAR
)KERNEL_BASE_PHYS
+ ImageHeader
->e_lfanew
);
613 /* Load the first section */
614 Section
= IMAGE_FIRST_SECTION(NtHeader
);
615 SectionCount
= NtHeader
->FileHeader
.NumberOfSections
- 1;
617 /* Now go to the last section */
618 Section
+= SectionCount
;
620 /* Walk each section backwards */
621 for (i
=(INT
)SectionCount
; i
>= 0; i
--, Section
--) {
623 /* Get the disk location and the memory location, and the size */
624 SourceSection
= RaToPa(Section
->PointerToRawData
);
625 TargetSection
= RaToPa(Section
->VirtualAddress
);
626 SectionSize
= Section
->SizeOfRawData
;
628 /* If the section is already mapped correctly, go to the next */
629 if (SourceSection
== TargetSection
) continue;
631 /* Load it into memory */
632 memmove((PVOID
)TargetSection
, (PVOID
)SourceSection
, SectionSize
);
634 /* Check for unitilizated data */
635 if (Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
) {
638 memset((PVOID
)RaToPa(Section
->VirtualAddress
+ Section
->SizeOfRawData
),
640 Section
->Misc
.VirtualSize
- Section
->SizeOfRawData
);
644 /* Get the Relocation Data Directory */
645 RelocationDDir
= &NtHeader
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
647 /* Get the Relocation Section Start and End*/
648 RelocationDir
= (PIMAGE_BASE_RELOCATION
)(KERNEL_BASE_PHYS
+ RelocationDDir
->VirtualAddress
);
649 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDDir
->Size
);
651 /* Calculate Difference between Real Base and Compiled Base*/
652 Delta
= KernelBase
- NtHeader
->OptionalHeader
.ImageBase
;
654 /* Determine how far we shoudl relocate */
655 MaxAddress
= KERNEL_BASE_PHYS
+ ImageSize
;
657 /* Relocate until we've processed all the blocks */
658 while (RelocationDir
< RelocationEnd
&& RelocationDir
->SizeOfBlock
> 0) {
660 /* See how many Relocation Blocks we have */
661 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
663 /* Calculate the Address of this Directory */
664 Address
= KERNEL_BASE_PHYS
+ RelocationDir
->VirtualAddress
;
666 /* Calculate the Offset of the Type */
667 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
669 for (i
= 0; i
< (INT
)Count
; i
++) {
671 ShortPtr
= (PUSHORT
)(Address
+ (*TypeOffset
& 0xFFF));
673 switch (*TypeOffset
>> 12) {
675 case IMAGE_REL_BASED_ABSOLUTE
:
678 case IMAGE_REL_BASED_HIGH
:
679 *ShortPtr
+= HIWORD(Delta
);
682 case IMAGE_REL_BASED_LOW
:
683 *ShortPtr
+= LOWORD(Delta
);
686 case IMAGE_REL_BASED_HIGHLOW
:
687 LongPtr
= (PULONG
)ShortPtr
;
695 /* Move to the next Relocation Table */
696 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDir
->SizeOfBlock
);
699 /* Increase the next Load Base */
700 NextModuleBase
= ROUND_UP(KERNEL_BASE_PHYS
+ ImageSize
, PAGE_SIZE
);
708 FrLdrLoadModule(FILE *ModuleImage
,
712 ULONG LocalModuleSize
;
713 PLOADER_MODULE ModuleData
;
717 /* Get current module data structure and module name string array */
718 ModuleData
= &reactos_modules
[LoaderBlock
.ModsCount
];
720 /* Get only the Module Name */
723 TempName
= strchr(ModuleName
, '\\');
726 ModuleName
= TempName
+ 1;
730 NameBuffer
= reactos_module_strings
[LoaderBlock
.ModsCount
];
732 /* Get Module Size */
733 LocalModuleSize
= FsGetFileSize(ModuleImage
);
735 /* Fill out Module Data Structure */
736 ModuleData
->ModStart
= NextModuleBase
;
737 ModuleData
->ModEnd
= NextModuleBase
+ LocalModuleSize
;
740 strcpy(NameBuffer
, ModuleName
);
741 ModuleData
->String
= (ULONG_PTR
)NameBuffer
;
743 /* Load the file image */
744 FsReadFile(ModuleImage
, LocalModuleSize
, NULL
, (PVOID
)NextModuleBase
);
746 /* Move to next memory block and increase Module Count */
747 NextModuleBase
= ROUND_UP(ModuleData
->ModEnd
, PAGE_SIZE
);
748 LoaderBlock
.ModsCount
++;
750 /* Return Module Size if required */
751 if (ModuleSize
!= NULL
) {
752 *ModuleSize
= LocalModuleSize
;
755 return(ModuleData
->ModStart
);
760 FrLdrCreateModule(LPSTR ModuleName
)
762 PLOADER_MODULE ModuleData
;
765 /* Get current module data structure and module name string array */
766 ModuleData
= &reactos_modules
[LoaderBlock
.ModsCount
];
767 NameBuffer
= reactos_module_strings
[LoaderBlock
.ModsCount
];
769 /* Set up the structure */
770 ModuleData
->ModStart
= NextModuleBase
;
771 ModuleData
->ModEnd
= -1;
774 strcpy(NameBuffer
, ModuleName
);
775 ModuleData
->String
= (ULONG_PTR
)NameBuffer
;
777 /* Set the current Module */
778 CurrentModule
= ModuleData
;
780 /* Return Module Base Address */
781 return(ModuleData
->ModStart
);
786 FrLdrCloseModule(ULONG_PTR ModuleBase
,
789 PLOADER_MODULE ModuleData
= CurrentModule
;
791 /* Make sure a module is opened */
794 /* Make sure this is the right module and that it hasn't been closed */
795 if ((ModuleBase
== ModuleData
->ModStart
) && (ModuleData
->ModEnd
== (ULONG_PTR
)-1)) {
797 /* Close the Module */
798 ModuleData
->ModEnd
= ModuleData
->ModStart
+ ModuleSize
;
800 /* Set the next Module Base and increase the number of modules */
801 NextModuleBase
= ROUND_UP(ModuleData
->ModEnd
, PAGE_SIZE
);
802 LoaderBlock
.ModsCount
++;
804 /* Close the currently opened module */
805 CurrentModule
= NULL
;