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.
27 /* Base Addres of Kernel in Physical Memory */
28 #define KERNEL_BASE_PHYS 0x200000
30 /* Bits to shift to convert a Virtual Address into an Offset in the Page Table */
33 /* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */
35 #define PDE_SHIFT_PAE 18
38 /* Converts a Relative Address read from the Kernel into a Physical Address */
40 (ULONG_PTR)((ULONG_PTR)p + KERNEL_BASE_PHYS)
42 /* Converts a Phsyical Address Pointer into a Page Frame Number */
43 #define PaPtrToPfn(p) \
44 (((ULONG_PTR)&p) >> PFN_SHIFT)
46 /* Converts a Phsyical Address into a Page Frame Number */
50 #define STARTUP_BASE 0xC0000000
51 #define HYPERSPACE_BASE 0xC0400000
52 #define HYPERSPACE_PAE_BASE 0xC0800000
53 #define APIC_BASE 0xFEC00000
54 #define KPCR_BASE 0xFF000000
56 #define LowMemPageTableIndex 0
57 #define StartupPageTableIndex (STARTUP_BASE >> 22)
58 #define HyperspacePageTableIndex (HYPERSPACE_BASE >> 22)
59 #define KpcrPageTableIndex (KPCR_BASE >> 22)
60 #define ApicPageTableIndex (APIC_BASE >> 22)
62 #define LowMemPageTableIndexPae 0
63 #define StartupPageTableIndexPae (STARTUP_BASE >> 21)
64 #define HyperspacePageTableIndexPae (HYPERSPACE_PAE_BASE >> 21)
65 #define KpcrPageTableIndexPae (KPCR_BASE >> 21)
66 #define ApicPageTableIndexPae (APIC_BASE >> 21)
69 #define KernelEntryPoint (KernelEntry - KERNEL_BASE_PHYS) + KernelBase
71 /* Load Address of Next Module */
72 ULONG_PTR NextModuleBase
= 0;
74 /* Currently Opened Module */
75 PLOADER_MODULE CurrentModule
= NULL
;
77 /* Unrelocated Kernel Base in Virtual Memory */
80 /* Wether PAE is to be used or not */
81 BOOLEAN PaeModeEnabled
;
83 /* Kernel Entrypoint in Physical Memory */
84 ULONG_PTR KernelEntry
;
86 typedef struct _HARDWARE_PTE_X64
{
90 ULONG WriteThrough
: 1;
91 ULONG CacheDisable
: 1;
96 ULONG CopyOnWrite
: 1;
99 ULONG PageFrameNumber
: 20;
100 ULONG reserved2
: 31;
102 } HARDWARE_PTE_X64
, *PHARDWARE_PTE_X64
;
104 typedef struct _PAGE_DIRECTORY_X86
{
105 HARDWARE_PTE_X86 Pde
[1024];
106 } PAGE_DIRECTORY_X86
, *PPAGE_DIRECTORY_X86
;
108 typedef struct _PAGE_DIRECTORY_X64
{
109 HARDWARE_PTE_X64 Pde
[2048];
110 } PAGE_DIRECTORY_X64
, *PPAGE_DIRECTORY_X64
;
112 typedef struct _PAGE_DIRECTORY_TABLE_X64
{
113 HARDWARE_PTE_X64 Pde
[4];
114 } PAGE_DIRECTORY_TABLE_X64
, *PPAGE_DIRECTORY_TABLE_X64
;
116 /* Page Directory and Tables for non-PAE Systems */
117 extern PAGE_DIRECTORY_X86 startup_pagedirectory
;
118 extern PAGE_DIRECTORY_X86 lowmem_pagetable
;
119 extern PAGE_DIRECTORY_X86 kernel_pagetable
;
120 extern ULONG_PTR hyperspace_pagetable
;
121 extern ULONG_PTR _pae_pagedirtable
;
122 extern PAGE_DIRECTORY_X86 apic_pagetable
;
123 extern PAGE_DIRECTORY_X86 kpcr_pagetable
;
125 /* Page Directory and Tables for PAE Systems */
126 extern PAGE_DIRECTORY_TABLE_X64 startup_pagedirectorytable_pae
;
127 extern PAGE_DIRECTORY_X64 startup_pagedirectory_pae
;
128 extern PAGE_DIRECTORY_X64 lowmem_pagetable_pae
;
129 extern PAGE_DIRECTORY_X64 kernel_pagetable_pae
;
130 extern ULONG_PTR hyperspace_pagetable_pae
;
131 extern ULONG_PTR pagedirtable_pae
;
132 extern PAGE_DIRECTORY_X64 apic_pagetable_pae
;
133 extern PAGE_DIRECTORY_X64 kpcr_pagetable_pae
;
135 /* FUNCTIONS *****************************************************************/
141 * Prepares the system for loading the Kernel.
144 * Magic - Multiboot Magic
155 FrLdrStartup(ULONG Magic
)
157 /* Disable Interrupts */
158 Ke386DisableInterrupts();
160 /* Re-initalize EFLAGS */
163 /* Get the PAE Mode */
166 /* Initialize the page directory */
167 FrLdrSetupPageDirectory();
169 /* Initialize Paging, Write-Protection and Load NTOSKRNL */
170 FrLdrSetupPae(Magic
);
177 * Configures PAE on a MP System, and sets the PDBR if it's supported, or if
181 * Magic - Multiboot Magic
192 FrLdrSetupPae(ULONG Magic
)
194 ULONG_PTR PageDirectoryBaseAddress
= (ULONG_PTR
)&startup_pagedirectory
;
199 PageDirectoryBaseAddress
= (ULONG_PTR
)&startup_pagedirectorytable_pae
;
202 Ke386SetCr4(Ke386GetCr4() | X86_CR4_PAE
);
206 Ke386SetPageTableDirectory(PageDirectoryBaseAddress
);
208 /* Enable Paging and Write Protect*/
209 Ke386SetCr0(Ke386GetCr0() | X86_CR0_PG
| X86_CR0_WP
);
212 PagedJump
= (ASMCODE
)(PVOID
)(KernelEntryPoint
);
213 PagedJump(Magic
, &LoaderBlock
);
220 * Gets the Kernel Base to use.
228 * Sets both the FreeLdr internal variable as well as the one which
229 * will be used by the Kernel.
234 FrLdrGetKernelBase(VOID
)
239 LoaderBlock
.KernelBase
= KernelBase
;
241 /* Read Command Line */
242 p
= (PCHAR
)LoaderBlock
.CommandLine
;
243 while ((p
= strchr(p
, '/')) != NULL
) {
246 if (!_strnicmp(p
+ 1, "3GB", 3)) {
248 /* Make sure there's nothing following it */
249 if (p
[4] == ' ' || p
[4] == 0) {
252 KernelBase
= 0xE0000000;
253 LoaderBlock
.KernelBase
= 0xC0000000;
265 * Determines whether PAE mode shoudl be enabled or not.
279 FrLdrGetPaeMode(VOID
)
281 BOOLEAN PaeModeSupported
;
283 PaeModeSupported
= FALSE
;
284 PaeModeEnabled
= FALSE
;
286 if (CpuidSupported() & 1)
288 ULONG eax
, ebx
, ecx
, FeatureBits
;
289 GetCpuid(1, &eax
, &ebx
, &ecx
, &FeatureBits
);
290 if (FeatureBits
& X86_FEATURE_PAE
)
292 PaeModeSupported
= TRUE
;
296 if (PaeModeSupported
)
300 /* Read Command Line */
301 p
= (PCHAR
)LoaderBlock
.CommandLine
;
302 while ((p
= strchr(p
, '/')) != NULL
) {
306 if (!_strnicmp(p
, "PAE", 3)) {
308 /* Make sure there's nothing following it */
309 if (p
[3] == ' ' || p
[3] == 0) {
312 PaeModeEnabled
= TRUE
;
321 * FrLdrSetupPageDirectory
324 * Sets up the ReactOS Startup Page Directory.
333 * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure.
334 * As such, please note that PageFrameNumber == PageEntryNumber.
339 FrLdrSetupPageDirectory(VOID
)
341 PPAGE_DIRECTORY_X86 PageDir
;
342 PPAGE_DIRECTORY_TABLE_X64 PageDirTablePae
;
343 PPAGE_DIRECTORY_X64 PageDirPae
;
344 ULONG KernelPageTableIndex
;
347 if (PaeModeEnabled
) {
349 /* Get the Kernel Table Index */
350 KernelPageTableIndex
= (KernelBase
>> 21);
352 /* Get the Startup Page Directory Table */
353 PageDirTablePae
= (PPAGE_DIRECTORY_TABLE_X64
)&startup_pagedirectorytable_pae
;
355 /* Get the Startup Page Directory */
356 PageDirPae
= (PPAGE_DIRECTORY_X64
)&startup_pagedirectory_pae
;
358 /* Set the Startup page directory table */
359 for (i
= 0; i
< 4; i
++)
361 PageDirTablePae
->Pde
[i
].Valid
= 1;
362 PageDirTablePae
->Pde
[i
].PageFrameNumber
= PaPtrToPfn(startup_pagedirectory_pae
) + i
;
365 /* Set up the Low Memory PDE */
366 for (i
= 0; i
< 2; i
++)
368 PageDirPae
->Pde
[LowMemPageTableIndexPae
+ i
].Valid
= 1;
369 PageDirPae
->Pde
[LowMemPageTableIndexPae
+ i
].Write
= 1;
370 PageDirPae
->Pde
[LowMemPageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(lowmem_pagetable_pae
) + i
;
373 /* Set up the Kernel PDEs */
374 for (i
= 0; i
< 3; i
++)
376 PageDirPae
->Pde
[KernelPageTableIndex
+ i
].Valid
= 1;
377 PageDirPae
->Pde
[KernelPageTableIndex
+ i
].Write
= 1;
378 PageDirPae
->Pde
[KernelPageTableIndex
+ i
].PageFrameNumber
= PaPtrToPfn(kernel_pagetable_pae
) + i
;
381 /* Set up the Startup PDE */
382 for (i
= 0; i
< 4; i
++)
384 PageDirPae
->Pde
[StartupPageTableIndexPae
+ i
].Valid
= 1;
385 PageDirPae
->Pde
[StartupPageTableIndexPae
+ i
].Write
= 1;
386 PageDirPae
->Pde
[StartupPageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(startup_pagedirectory_pae
) + i
;
389 /* Set up the Hyperspace PDE */
390 for (i
= 0; i
< 2; i
++)
392 PageDirPae
->Pde
[HyperspacePageTableIndexPae
+ i
].Valid
= 1;
393 PageDirPae
->Pde
[HyperspacePageTableIndexPae
+ i
].Write
= 1;
394 PageDirPae
->Pde
[HyperspacePageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(hyperspace_pagetable_pae
) + i
;
397 /* Set up the Apic PDE */
398 for (i
= 0; i
< 2; i
++)
400 PageDirPae
->Pde
[ApicPageTableIndexPae
+ i
].Valid
= 1;
401 PageDirPae
->Pde
[ApicPageTableIndexPae
+ i
].Write
= 1;
402 PageDirPae
->Pde
[ApicPageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(apic_pagetable_pae
) + i
;
405 /* Set up the KPCR PDE */
406 PageDirPae
->Pde
[KpcrPageTableIndexPae
].Valid
= 1;
407 PageDirPae
->Pde
[KpcrPageTableIndexPae
].Write
= 1;
408 PageDirPae
->Pde
[KpcrPageTableIndexPae
].PageFrameNumber
= PaPtrToPfn(kpcr_pagetable_pae
);
410 /* Set up Low Memory PTEs */
411 PageDirPae
= (PPAGE_DIRECTORY_X64
)&lowmem_pagetable_pae
;
412 for (i
=0; i
<1024; i
++) {
414 PageDirPae
->Pde
[i
].Valid
= 1;
415 PageDirPae
->Pde
[i
].Write
= 1;
416 PageDirPae
->Pde
[i
].Owner
= 1;
417 PageDirPae
->Pde
[i
].PageFrameNumber
= i
;
420 /* Set up Kernel PTEs */
421 PageDirPae
= (PPAGE_DIRECTORY_X64
)&kernel_pagetable_pae
;
422 for (i
=0; i
<1536; i
++) {
424 PageDirPae
->Pde
[i
].Valid
= 1;
425 PageDirPae
->Pde
[i
].Write
= 1;
426 PageDirPae
->Pde
[i
].PageFrameNumber
= PaToPfn(KERNEL_BASE_PHYS
) + i
;
429 /* Set up APIC PTEs */
430 PageDirPae
= (PPAGE_DIRECTORY_X64
)&apic_pagetable_pae
;
431 PageDirPae
->Pde
[0].Valid
= 1;
432 PageDirPae
->Pde
[0].Write
= 1;
433 PageDirPae
->Pde
[0].CacheDisable
= 1;
434 PageDirPae
->Pde
[0].WriteThrough
= 1;
435 PageDirPae
->Pde
[0].PageFrameNumber
= PaToPfn(APIC_BASE
);
436 PageDirPae
->Pde
[0x200].Valid
= 1;
437 PageDirPae
->Pde
[0x200].Write
= 1;
438 PageDirPae
->Pde
[0x200].CacheDisable
= 1;
439 PageDirPae
->Pde
[0x200].WriteThrough
= 1;
440 PageDirPae
->Pde
[0x200].PageFrameNumber
= PaToPfn(APIC_BASE
+ KERNEL_BASE_PHYS
);
442 /* Set up KPCR PTEs */
443 PageDirPae
= (PPAGE_DIRECTORY_X64
)&kpcr_pagetable_pae
;
444 PageDirPae
->Pde
[0].Valid
= 1;
445 PageDirPae
->Pde
[0].Write
= 1;
446 PageDirPae
->Pde
[0].PageFrameNumber
= 1;
450 /* Get the Kernel Table Index */
451 KernelPageTableIndex
= KernelBase
>> PDE_SHIFT
;
453 /* Get the Startup Page Directory */
454 PageDir
= (PPAGE_DIRECTORY_X86
)&startup_pagedirectory
;
456 /* Set up the Low Memory PDE */
457 PageDir
->Pde
[LowMemPageTableIndex
].Valid
= 1;
458 PageDir
->Pde
[LowMemPageTableIndex
].Write
= 1;
459 PageDir
->Pde
[LowMemPageTableIndex
].PageFrameNumber
= PaPtrToPfn(lowmem_pagetable
);
461 /* Set up the Kernel PDEs */
462 PageDir
->Pde
[KernelPageTableIndex
].Valid
= 1;
463 PageDir
->Pde
[KernelPageTableIndex
].Write
= 1;
464 PageDir
->Pde
[KernelPageTableIndex
].PageFrameNumber
= PaPtrToPfn(kernel_pagetable
);
465 PageDir
->Pde
[KernelPageTableIndex
+ 1].Valid
= 1;
466 PageDir
->Pde
[KernelPageTableIndex
+ 1].Write
= 1;
467 PageDir
->Pde
[KernelPageTableIndex
+ 1].PageFrameNumber
= PaPtrToPfn(kernel_pagetable
+ 4096);
469 /* Set up the Startup PDE */
470 PageDir
->Pde
[StartupPageTableIndex
].Valid
= 1;
471 PageDir
->Pde
[StartupPageTableIndex
].Write
= 1;
472 PageDir
->Pde
[StartupPageTableIndex
].PageFrameNumber
= PaPtrToPfn(startup_pagedirectory
);
474 /* Set up the Hyperspace PDE */
475 PageDir
->Pde
[HyperspacePageTableIndex
].Valid
= 1;
476 PageDir
->Pde
[HyperspacePageTableIndex
].Write
= 1;
477 PageDir
->Pde
[HyperspacePageTableIndex
].PageFrameNumber
= PaPtrToPfn(hyperspace_pagetable
);
479 /* Set up the Apic PDE */
480 PageDir
->Pde
[ApicPageTableIndex
].Valid
= 1;
481 PageDir
->Pde
[ApicPageTableIndex
].Write
= 1;
482 PageDir
->Pde
[ApicPageTableIndex
].PageFrameNumber
= PaPtrToPfn(apic_pagetable
);
484 /* Set up the KPCR PDE */
485 PageDir
->Pde
[KpcrPageTableIndex
].Valid
= 1;
486 PageDir
->Pde
[KpcrPageTableIndex
].Write
= 1;
487 PageDir
->Pde
[KpcrPageTableIndex
].PageFrameNumber
= PaPtrToPfn(kpcr_pagetable
);
489 /* Set up Low Memory PTEs */
490 PageDir
= (PPAGE_DIRECTORY_X86
)&lowmem_pagetable
;
491 for (i
=0; i
<1024; i
++) {
493 PageDir
->Pde
[i
].Valid
= 1;
494 PageDir
->Pde
[i
].Write
= 1;
495 PageDir
->Pde
[i
].Owner
= 1;
496 PageDir
->Pde
[i
].PageFrameNumber
= PaToPfn(i
* PAGE_SIZE
);
499 /* Set up Kernel PTEs */
500 PageDir
= (PPAGE_DIRECTORY_X86
)&kernel_pagetable
;
501 for (i
=0; i
<1536; i
++) {
503 PageDir
->Pde
[i
].Valid
= 1;
504 PageDir
->Pde
[i
].Write
= 1;
505 PageDir
->Pde
[i
].PageFrameNumber
= PaToPfn(KERNEL_BASE_PHYS
+ i
* PAGE_SIZE
);
508 /* Set up APIC PTEs */
509 PageDir
= (PPAGE_DIRECTORY_X86
)&apic_pagetable
;
510 PageDir
->Pde
[0].Valid
= 1;
511 PageDir
->Pde
[0].Write
= 1;
512 PageDir
->Pde
[0].CacheDisable
= 1;
513 PageDir
->Pde
[0].WriteThrough
= 1;
514 PageDir
->Pde
[0].PageFrameNumber
= PaToPfn(APIC_BASE
);
515 PageDir
->Pde
[0x200].Valid
= 1;
516 PageDir
->Pde
[0x200].Write
= 1;
517 PageDir
->Pde
[0x200].CacheDisable
= 1;
518 PageDir
->Pde
[0x200].WriteThrough
= 1;
519 PageDir
->Pde
[0x200].PageFrameNumber
= PaToPfn(APIC_BASE
+ KERNEL_BASE_PHYS
);
521 /* Set up KPCR PTEs */
522 PageDir
= (PPAGE_DIRECTORY_X86
)&kpcr_pagetable
;
523 PageDir
->Pde
[0].Valid
= 1;
524 PageDir
->Pde
[0].Write
= 1;
525 PageDir
->Pde
[0].PageFrameNumber
= 1;
534 * Maps the Kernel into memory, does PE Section Mapping, initalizes the
535 * uninitialized data sections, and relocates the image.
538 * KernelImage - FILE Structure representing the ntoskrnl image file.
541 * TRUE if the Kernel was mapped.
549 FrLdrMapKernel(FILE *KernelImage
)
551 PIMAGE_DOS_HEADER ImageHeader
;
552 PIMAGE_NT_HEADERS NtHeader
;
553 PIMAGE_SECTION_HEADER Section
;
556 ULONG_PTR SourceSection
;
557 ULONG_PTR TargetSection
;
560 PIMAGE_DATA_DIRECTORY RelocationDDir
;
561 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
563 ULONG_PTR Address
, MaxAddress
;
569 /* Allocate 1024 bytes for PE Header */
570 ImageHeader
= (PIMAGE_DOS_HEADER
)MmAllocateMemory(1024);
572 /* Make sure it was succesful */
573 if (ImageHeader
== NULL
) {
578 /* Load the first 1024 bytes of the kernel image so we can read the PE header */
579 if (!FsReadFile(KernelImage
, 1024, NULL
, ImageHeader
)) {
581 /* Fail if we couldn't read */
582 MmFreeMemory(ImageHeader
);
586 /* Now read the MZ header to get the offset to the PE Header */
587 NtHeader
= (PIMAGE_NT_HEADERS
)((PCHAR
)ImageHeader
+ ImageHeader
->e_lfanew
);
589 /* Get Kernel Base */
590 KernelBase
= NtHeader
->OptionalHeader
.ImageBase
;
591 FrLdrGetKernelBase();
593 /* Save Entrypoint */
594 KernelEntry
= RaToPa(NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
596 /* Save the Image Size */
597 ImageSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
599 /* Free the Header */
600 MmFreeMemory(ImageHeader
);
602 /* Set the file pointer to zero */
603 FsSetFilePointer(KernelImage
, 0);
605 /* Load the file image */
606 FsReadFile(KernelImage
, ImageSize
, NULL
, (PVOID
)KERNEL_BASE_PHYS
);
608 /* Reload the NT Header */
609 NtHeader
= (PIMAGE_NT_HEADERS
)((PCHAR
)KERNEL_BASE_PHYS
+ ImageHeader
->e_lfanew
);
611 /* Load the first section */
612 Section
= IMAGE_FIRST_SECTION(NtHeader
);
613 SectionCount
= NtHeader
->FileHeader
.NumberOfSections
- 1;
615 /* Now go to the last section */
616 Section
+= SectionCount
;
618 /* Walk each section backwards */
619 for (i
=(INT
)SectionCount
; i
>= 0; i
--, Section
--) {
621 /* Get the disk location and the memory location, and the size */
622 SourceSection
= RaToPa(Section
->PointerToRawData
);
623 TargetSection
= RaToPa(Section
->VirtualAddress
);
624 SectionSize
= Section
->SizeOfRawData
;
626 /* If the section is already mapped correctly, go to the next */
627 if (SourceSection
== TargetSection
) continue;
629 /* Load it into memory */
630 memmove((PVOID
)TargetSection
, (PVOID
)SourceSection
, SectionSize
);
632 /* Check for unitilizated data */
633 if (Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
) {
636 memset((PVOID
)RaToPa(Section
->VirtualAddress
+ Section
->SizeOfRawData
),
638 Section
->Misc
.VirtualSize
- Section
->SizeOfRawData
);
642 /* Get the Relocation Data Directory */
643 RelocationDDir
= &NtHeader
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
645 /* Get the Relocation Section Start and End*/
646 RelocationDir
= (PIMAGE_BASE_RELOCATION
)(KERNEL_BASE_PHYS
+ RelocationDDir
->VirtualAddress
);
647 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDDir
->Size
);
649 /* Calculate Difference between Real Base and Compiled Base*/
650 Delta
= KernelBase
- NtHeader
->OptionalHeader
.ImageBase
;
652 /* Determine how far we shoudl relocate */
653 MaxAddress
= KERNEL_BASE_PHYS
+ ImageSize
;
655 /* Relocate until we've processed all the blocks */
656 while (RelocationDir
< RelocationEnd
&& RelocationDir
->SizeOfBlock
> 0) {
658 /* See how many Relocation Blocks we have */
659 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
661 /* Calculate the Address of this Directory */
662 Address
= KERNEL_BASE_PHYS
+ RelocationDir
->VirtualAddress
;
664 /* Calculate the Offset of the Type */
665 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
667 for (i
= 0; i
< (INT
)Count
; i
++) {
669 ShortPtr
= (PUSHORT
)(Address
+ (*TypeOffset
& 0xFFF));
671 switch (*TypeOffset
>> 12) {
673 case IMAGE_REL_BASED_ABSOLUTE
:
676 case IMAGE_REL_BASED_HIGH
:
677 *ShortPtr
+= HIWORD(Delta
);
680 case IMAGE_REL_BASED_LOW
:
681 *ShortPtr
+= LOWORD(Delta
);
684 case IMAGE_REL_BASED_HIGHLOW
:
685 LongPtr
= (PULONG
)ShortPtr
;
693 /* Move to the next Relocation Table */
694 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDir
->SizeOfBlock
);
697 /* Increase the next Load Base */
698 NextModuleBase
= ROUND_UP(KERNEL_BASE_PHYS
+ ImageSize
, PAGE_SIZE
);
706 FrLdrLoadModule(FILE *ModuleImage
,
710 ULONG LocalModuleSize
;
711 PLOADER_MODULE ModuleData
;
715 /* Get current module data structure and module name string array */
716 ModuleData
= &reactos_modules
[LoaderBlock
.ModsCount
];
718 /* Get only the Module Name */
721 TempName
= strchr(ModuleName
, '\\');
724 ModuleName
= TempName
+ 1;
728 NameBuffer
= reactos_module_strings
[LoaderBlock
.ModsCount
];
730 /* Get Module Size */
731 LocalModuleSize
= FsGetFileSize(ModuleImage
);
733 /* Fill out Module Data Structure */
734 ModuleData
->ModStart
= NextModuleBase
;
735 ModuleData
->ModEnd
= NextModuleBase
+ LocalModuleSize
;
738 strcpy(NameBuffer
, ModuleName
);
739 ModuleData
->String
= (ULONG_PTR
)NameBuffer
;
741 /* Load the file image */
742 FsReadFile(ModuleImage
, LocalModuleSize
, NULL
, (PVOID
)NextModuleBase
);
744 /* Move to next memory block and increase Module Count */
745 NextModuleBase
= ROUND_UP(ModuleData
->ModEnd
, PAGE_SIZE
);
746 LoaderBlock
.ModsCount
++;
748 /* Return Module Size if required */
749 if (ModuleSize
!= NULL
) {
750 *ModuleSize
= LocalModuleSize
;
753 return(ModuleData
->ModStart
);
758 FrLdrCreateModule(LPCSTR ModuleName
)
760 PLOADER_MODULE ModuleData
;
763 /* Get current module data structure and module name string array */
764 ModuleData
= &reactos_modules
[LoaderBlock
.ModsCount
];
765 NameBuffer
= reactos_module_strings
[LoaderBlock
.ModsCount
];
767 /* Set up the structure */
768 ModuleData
->ModStart
= NextModuleBase
;
769 ModuleData
->ModEnd
= -1;
772 strcpy(NameBuffer
, ModuleName
);
773 ModuleData
->String
= (ULONG_PTR
)NameBuffer
;
775 /* Set the current Module */
776 CurrentModule
= ModuleData
;
778 /* Return Module Base Address */
779 return(ModuleData
->ModStart
);
784 FrLdrCloseModule(ULONG_PTR ModuleBase
,
787 PLOADER_MODULE ModuleData
= CurrentModule
;
789 /* Make sure a module is opened */
792 /* Make sure this is the right module and that it hasn't been closed */
793 if ((ModuleBase
== ModuleData
->ModStart
) && (ModuleData
->ModEnd
== (ULONG_PTR
)-1)) {
795 /* Close the Module */
796 ModuleData
->ModEnd
= ModuleData
->ModStart
+ ModuleSize
;
798 /* Set the next Module Base and increase the number of modules */
799 NextModuleBase
= ROUND_UP(ModuleData
->ModEnd
, PAGE_SIZE
);
800 LoaderBlock
.ModsCount
++;
802 /* Close the currently opened module */
803 CurrentModule
= NULL
;