3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 * Copyright (C) 2005 Alex Ionescu <alex@relsoft.net>
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.
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.
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.
26 /* Base Addres of Kernel in Physical Memory */
27 #define KERNEL_BASE_PHYS 0x200000
29 /* Bits to shift to convert a Virtual Address into an Offset in the Page Table */
32 /* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */
34 #define PDE_SHIFT_PAE 18
37 /* Converts a Relative Address read from the Kernel into a Physical Address */
39 (ULONG_PTR)((ULONG_PTR)p + KERNEL_BASE_PHYS)
41 /* Converts a Physical Address Pointer into a Page Frame Number */
42 #define PaPtrToPfn(p) \
43 (((ULONG_PTR)&p) >> PFN_SHIFT)
45 /* Converts a Physical Address into a Page Frame Number */
49 #define STARTUP_BASE 0xC0000000
50 #define HYPERSPACE_BASE 0xC0400000
51 #define HYPERSPACE_PAE_BASE 0xC0800000
52 #define APIC_BASE 0xFEC00000
53 #define KPCR_BASE 0xFF000000
55 #define LowMemPageTableIndex 0
56 #define StartupPageTableIndex (STARTUP_BASE >> 22)
57 #define HyperspacePageTableIndex (HYPERSPACE_BASE >> 22)
58 #define KpcrPageTableIndex (KPCR_BASE >> 22)
59 #define ApicPageTableIndex (APIC_BASE >> 22)
61 #define LowMemPageTableIndexPae 0
62 #define StartupPageTableIndexPae (STARTUP_BASE >> 21)
63 #define HyperspacePageTableIndexPae (HYPERSPACE_PAE_BASE >> 21)
64 #define KpcrPageTableIndexPae (KPCR_BASE >> 21)
65 #define ApicPageTableIndexPae (APIC_BASE >> 21)
68 #define KernelEntryPoint (KernelEntry - KERNEL_BASE_PHYS) + KernelBase
70 /* Load Address of Next Module */
71 ULONG_PTR NextModuleBase
= 0;
73 /* Currently Opened Module */
74 PLOADER_MODULE CurrentModule
= NULL
;
76 /* Unrelocated Kernel Base in Virtual Memory */
79 /* Whether PAE is to be used or not */
80 BOOLEAN PaeModeEnabled
;
82 /* Kernel Entrypoint in Physical Memory */
83 ULONG_PTR KernelEntry
;
85 typedef struct _HARDWARE_PTE_X64
{
89 ULONG WriteThrough
: 1;
90 ULONG CacheDisable
: 1;
95 ULONG CopyOnWrite
: 1;
98 ULONG PageFrameNumber
: 20;
101 } HARDWARE_PTE_X64
, *PHARDWARE_PTE_X64
;
103 typedef struct _PAGE_DIRECTORY_X86
{
104 HARDWARE_PTE Pde
[1024];
105 } PAGE_DIRECTORY_X86
, *PPAGE_DIRECTORY_X86
;
107 typedef struct _PAGE_DIRECTORY_X64
{
108 HARDWARE_PTE_X64 Pde
[2048];
109 } PAGE_DIRECTORY_X64
, *PPAGE_DIRECTORY_X64
;
111 typedef struct _PAGE_DIRECTORY_TABLE_X64
{
112 HARDWARE_PTE_X64 Pde
[4];
113 } PAGE_DIRECTORY_TABLE_X64
, *PPAGE_DIRECTORY_TABLE_X64
;
115 /* Page Directory and Tables for non-PAE Systems */
116 extern PAGE_DIRECTORY_X86 startup_pagedirectory
;
117 extern PAGE_DIRECTORY_X86 lowmem_pagetable
;
118 extern PAGE_DIRECTORY_X86 kernel_pagetable
;
119 extern ULONG_PTR hyperspace_pagetable
;
120 extern ULONG_PTR _pae_pagedirtable
;
121 extern PAGE_DIRECTORY_X86 apic_pagetable
;
122 extern PAGE_DIRECTORY_X86 kpcr_pagetable
;
124 /* Page Directory and Tables for PAE Systems */
125 extern PAGE_DIRECTORY_TABLE_X64 startup_pagedirectorytable_pae
;
126 extern PAGE_DIRECTORY_X64 startup_pagedirectory_pae
;
127 extern PAGE_DIRECTORY_X64 lowmem_pagetable_pae
;
128 extern PAGE_DIRECTORY_X64 kernel_pagetable_pae
;
129 extern ULONG_PTR hyperspace_pagetable_pae
;
130 extern ULONG_PTR pagedirtable_pae
;
131 extern PAGE_DIRECTORY_X64 apic_pagetable_pae
;
132 extern PAGE_DIRECTORY_X64 kpcr_pagetable_pae
;
134 /* FUNCTIONS *****************************************************************/
140 * Prepares the system for loading the Kernel.
143 * Magic - Multiboot Magic
154 FrLdrStartup(ULONG Magic
)
156 /* Disable Interrupts */
159 /* Re-initalize EFLAGS */
162 /* Get the PAE Mode */
165 /* Initialize the page directory */
166 FrLdrSetupPageDirectory();
168 /* Initialize Paging, Write-Protection and Load NTOSKRNL */
169 FrLdrSetupPae(Magic
);
176 * Configures PAE on a MP System, and sets the PDBR if it's supported, or if
180 * Magic - Multiboot Magic
191 FrLdrSetupPae(ULONG Magic
)
193 ULONG_PTR PageDirectoryBaseAddress
= (ULONG_PTR
)&startup_pagedirectory
;
198 PageDirectoryBaseAddress
= (ULONG_PTR
)&startup_pagedirectorytable_pae
;
201 __writecr4(__readcr4() | X86_CR4_PAE
);
205 __writecr3(PageDirectoryBaseAddress
);
207 /* Enable Paging and Write Protect*/
208 __writecr0(__readcr0() | X86_CR0_PG
| X86_CR0_WP
);
211 PagedJump
= (ASMCODE
)(PVOID
)(KernelEntryPoint
);
212 PagedJump(Magic
, &LoaderBlock
);
219 * Gets the Kernel Base to use.
227 * Sets both the FreeLdr internal variable as well as the one which
228 * will be used by the Kernel.
233 FrLdrGetKernelBase(VOID
)
238 LoaderBlock
.KernelBase
= KernelBase
;
240 /* Read Command Line */
241 p
= (PCHAR
)LoaderBlock
.CommandLine
;
242 while ((p
= strchr(p
, '/')) != NULL
) {
245 if (!_strnicmp(p
+ 1, "3GB", 3)) {
247 /* Make sure there's nothing following it */
248 if (p
[4] == ' ' || p
[4] == 0) {
251 KernelBase
= 0xE0000000;
252 LoaderBlock
.KernelBase
= 0xC0000000;
264 * Determines whether PAE mode should be enabled or not.
278 FrLdrGetPaeMode(VOID
)
280 BOOLEAN PaeModeSupported
;
282 PaeModeSupported
= FALSE
;
283 PaeModeEnabled
= FALSE
;
285 if (CpuidSupported() & 1)
287 ULONG eax
, ebx
, ecx
, FeatureBits
;
288 GetCpuid(1, &eax
, &ebx
, &ecx
, &FeatureBits
);
289 if (FeatureBits
& X86_FEATURE_PAE
)
291 PaeModeSupported
= TRUE
;
295 if (PaeModeSupported
)
299 /* Read Command Line */
300 p
= (PCHAR
)LoaderBlock
.CommandLine
;
301 while ((p
= strchr(p
, '/')) != NULL
) {
305 if (!_strnicmp(p
, "PAE", 3)) {
307 /* Make sure there's nothing following it */
308 if (p
[3] == ' ' || p
[3] == 0) {
311 PaeModeEnabled
= TRUE
;
320 * FrLdrSetupPageDirectory
323 * Sets up the ReactOS Startup Page Directory.
332 * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure.
333 * As such, please note that PageFrameNumber == PageEntryNumber.
338 FrLdrSetupPageDirectory(VOID
)
340 PPAGE_DIRECTORY_X86 PageDir
;
341 PPAGE_DIRECTORY_TABLE_X64 PageDirTablePae
;
342 PPAGE_DIRECTORY_X64 PageDirPae
;
343 ULONG KernelPageTableIndex
;
346 if (PaeModeEnabled
) {
348 /* Get the Kernel Table Index */
349 KernelPageTableIndex
= (KernelBase
>> 21);
351 /* Get the Startup Page Directory Table */
352 PageDirTablePae
= (PPAGE_DIRECTORY_TABLE_X64
)&startup_pagedirectorytable_pae
;
354 /* Get the Startup Page Directory */
355 PageDirPae
= (PPAGE_DIRECTORY_X64
)&startup_pagedirectory_pae
;
357 /* Set the Startup page directory table */
358 for (i
= 0; i
< 4; i
++)
360 PageDirTablePae
->Pde
[i
].Valid
= 1;
361 PageDirTablePae
->Pde
[i
].PageFrameNumber
= PaPtrToPfn(startup_pagedirectory_pae
) + i
;
364 /* Set up the Low Memory PDE */
365 for (i
= 0; i
< 2; i
++)
367 PageDirPae
->Pde
[LowMemPageTableIndexPae
+ i
].Valid
= 1;
368 PageDirPae
->Pde
[LowMemPageTableIndexPae
+ i
].Write
= 1;
369 PageDirPae
->Pde
[LowMemPageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(lowmem_pagetable_pae
) + i
;
372 /* Set up the Kernel PDEs */
373 for (i
= 0; i
< 3; i
++)
375 PageDirPae
->Pde
[KernelPageTableIndex
+ i
].Valid
= 1;
376 PageDirPae
->Pde
[KernelPageTableIndex
+ i
].Write
= 1;
377 PageDirPae
->Pde
[KernelPageTableIndex
+ i
].PageFrameNumber
= PaPtrToPfn(kernel_pagetable_pae
) + i
;
380 /* Set up the Startup PDE */
381 for (i
= 0; i
< 4; i
++)
383 PageDirPae
->Pde
[StartupPageTableIndexPae
+ i
].Valid
= 1;
384 PageDirPae
->Pde
[StartupPageTableIndexPae
+ i
].Write
= 1;
385 PageDirPae
->Pde
[StartupPageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(startup_pagedirectory_pae
) + i
;
388 /* Set up the Hyperspace PDE */
389 for (i
= 0; i
< 2; i
++)
391 PageDirPae
->Pde
[HyperspacePageTableIndexPae
+ i
].Valid
= 1;
392 PageDirPae
->Pde
[HyperspacePageTableIndexPae
+ i
].Write
= 1;
393 PageDirPae
->Pde
[HyperspacePageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(hyperspace_pagetable_pae
) + i
;
396 /* Set up the Apic PDE */
397 for (i
= 0; i
< 2; i
++)
399 PageDirPae
->Pde
[ApicPageTableIndexPae
+ i
].Valid
= 1;
400 PageDirPae
->Pde
[ApicPageTableIndexPae
+ i
].Write
= 1;
401 PageDirPae
->Pde
[ApicPageTableIndexPae
+ i
].PageFrameNumber
= PaPtrToPfn(apic_pagetable_pae
) + i
;
404 /* Set up the KPCR PDE */
405 PageDirPae
->Pde
[KpcrPageTableIndexPae
].Valid
= 1;
406 PageDirPae
->Pde
[KpcrPageTableIndexPae
].Write
= 1;
407 PageDirPae
->Pde
[KpcrPageTableIndexPae
].PageFrameNumber
= PaPtrToPfn(kpcr_pagetable_pae
);
409 /* Set up Low Memory PTEs */
410 PageDirPae
= (PPAGE_DIRECTORY_X64
)&lowmem_pagetable_pae
;
411 for (i
=0; i
<1024; i
++) {
413 PageDirPae
->Pde
[i
].Valid
= 1;
414 PageDirPae
->Pde
[i
].Write
= 1;
415 PageDirPae
->Pde
[i
].Owner
= 1;
416 PageDirPae
->Pde
[i
].PageFrameNumber
= i
;
419 /* Set up Kernel PTEs */
420 PageDirPae
= (PPAGE_DIRECTORY_X64
)&kernel_pagetable_pae
;
421 for (i
=0; i
<1536; i
++) {
423 PageDirPae
->Pde
[i
].Valid
= 1;
424 PageDirPae
->Pde
[i
].Write
= 1;
425 PageDirPae
->Pde
[i
].PageFrameNumber
= PaToPfn(KERNEL_BASE_PHYS
) + i
;
428 /* Set up APIC PTEs */
429 PageDirPae
= (PPAGE_DIRECTORY_X64
)&apic_pagetable_pae
;
430 PageDirPae
->Pde
[0].Valid
= 1;
431 PageDirPae
->Pde
[0].Write
= 1;
432 PageDirPae
->Pde
[0].CacheDisable
= 1;
433 PageDirPae
->Pde
[0].WriteThrough
= 1;
434 PageDirPae
->Pde
[0].PageFrameNumber
= PaToPfn(APIC_BASE
);
435 PageDirPae
->Pde
[0x200].Valid
= 1;
436 PageDirPae
->Pde
[0x200].Write
= 1;
437 PageDirPae
->Pde
[0x200].CacheDisable
= 1;
438 PageDirPae
->Pde
[0x200].WriteThrough
= 1;
439 PageDirPae
->Pde
[0x200].PageFrameNumber
= PaToPfn(APIC_BASE
+ KERNEL_BASE_PHYS
);
441 /* Set up KPCR PTEs */
442 PageDirPae
= (PPAGE_DIRECTORY_X64
)&kpcr_pagetable_pae
;
443 PageDirPae
->Pde
[0].Valid
= 1;
444 PageDirPae
->Pde
[0].Write
= 1;
445 PageDirPae
->Pde
[0].PageFrameNumber
= 1;
449 /* Get the Kernel Table Index */
450 KernelPageTableIndex
= KernelBase
>> PDE_SHIFT
;
452 /* Get the Startup Page Directory */
453 PageDir
= (PPAGE_DIRECTORY_X86
)&startup_pagedirectory
;
455 /* Set up the Low Memory PDE */
456 PageDir
->Pde
[LowMemPageTableIndex
].Valid
= 1;
457 PageDir
->Pde
[LowMemPageTableIndex
].Write
= 1;
458 PageDir
->Pde
[LowMemPageTableIndex
].PageFrameNumber
= PaPtrToPfn(lowmem_pagetable
);
460 /* Set up the Kernel PDEs */
461 PageDir
->Pde
[KernelPageTableIndex
].Valid
= 1;
462 PageDir
->Pde
[KernelPageTableIndex
].Write
= 1;
463 PageDir
->Pde
[KernelPageTableIndex
].PageFrameNumber
= PaPtrToPfn(kernel_pagetable
);
464 PageDir
->Pde
[KernelPageTableIndex
+ 1].Valid
= 1;
465 PageDir
->Pde
[KernelPageTableIndex
+ 1].Write
= 1;
466 PageDir
->Pde
[KernelPageTableIndex
+ 1].PageFrameNumber
= PaPtrToPfn(kernel_pagetable
+ 4096);
468 /* Set up the Startup PDE */
469 PageDir
->Pde
[StartupPageTableIndex
].Valid
= 1;
470 PageDir
->Pde
[StartupPageTableIndex
].Write
= 1;
471 PageDir
->Pde
[StartupPageTableIndex
].PageFrameNumber
= PaPtrToPfn(startup_pagedirectory
);
473 /* Set up the Hyperspace PDE */
474 PageDir
->Pde
[HyperspacePageTableIndex
].Valid
= 1;
475 PageDir
->Pde
[HyperspacePageTableIndex
].Write
= 1;
476 PageDir
->Pde
[HyperspacePageTableIndex
].PageFrameNumber
= PaPtrToPfn(hyperspace_pagetable
);
478 /* Set up the Apic PDE */
479 PageDir
->Pde
[ApicPageTableIndex
].Valid
= 1;
480 PageDir
->Pde
[ApicPageTableIndex
].Write
= 1;
481 PageDir
->Pde
[ApicPageTableIndex
].PageFrameNumber
= PaPtrToPfn(apic_pagetable
);
483 /* Set up the KPCR PDE */
484 PageDir
->Pde
[KpcrPageTableIndex
].Valid
= 1;
485 PageDir
->Pde
[KpcrPageTableIndex
].Write
= 1;
486 PageDir
->Pde
[KpcrPageTableIndex
].PageFrameNumber
= PaPtrToPfn(kpcr_pagetable
);
488 /* Set up Low Memory PTEs */
489 PageDir
= (PPAGE_DIRECTORY_X86
)&lowmem_pagetable
;
490 for (i
=0; i
<1024; i
++) {
492 PageDir
->Pde
[i
].Valid
= 1;
493 PageDir
->Pde
[i
].Write
= 1;
494 PageDir
->Pde
[i
].Owner
= 1;
495 PageDir
->Pde
[i
].PageFrameNumber
= PaToPfn(i
* PAGE_SIZE
);
498 /* Set up Kernel PTEs */
499 PageDir
= (PPAGE_DIRECTORY_X86
)&kernel_pagetable
;
500 for (i
=0; i
<1536; i
++) {
502 PageDir
->Pde
[i
].Valid
= 1;
503 PageDir
->Pde
[i
].Write
= 1;
504 PageDir
->Pde
[i
].PageFrameNumber
= PaToPfn(KERNEL_BASE_PHYS
+ i
* PAGE_SIZE
);
507 /* Set up APIC PTEs */
508 PageDir
= (PPAGE_DIRECTORY_X86
)&apic_pagetable
;
509 PageDir
->Pde
[0].Valid
= 1;
510 PageDir
->Pde
[0].Write
= 1;
511 PageDir
->Pde
[0].CacheDisable
= 1;
512 PageDir
->Pde
[0].WriteThrough
= 1;
513 PageDir
->Pde
[0].PageFrameNumber
= PaToPfn(APIC_BASE
);
514 PageDir
->Pde
[0x200].Valid
= 1;
515 PageDir
->Pde
[0x200].Write
= 1;
516 PageDir
->Pde
[0x200].CacheDisable
= 1;
517 PageDir
->Pde
[0x200].WriteThrough
= 1;
518 PageDir
->Pde
[0x200].PageFrameNumber
= PaToPfn(APIC_BASE
+ KERNEL_BASE_PHYS
);
520 /* Set up KPCR PTEs */
521 PageDir
= (PPAGE_DIRECTORY_X86
)&kpcr_pagetable
;
522 PageDir
->Pde
[0].Valid
= 1;
523 PageDir
->Pde
[0].Write
= 1;
524 PageDir
->Pde
[0].PageFrameNumber
= 1;
533 * Maps the Kernel into memory, does PE Section Mapping, initalizes the
534 * uninitialized data sections, and relocates the image.
537 * KernelImage - FILE Structure representing the ntoskrnl image file.
540 * TRUE if the Kernel was mapped.
548 FrLdrMapKernel(FILE *KernelImage
)
550 PIMAGE_DOS_HEADER ImageHeader
;
551 PIMAGE_NT_HEADERS NtHeader
;
552 PIMAGE_SECTION_HEADER Section
;
555 ULONG_PTR SourceSection
;
556 ULONG_PTR TargetSection
;
559 PIMAGE_DATA_DIRECTORY RelocationDDir
;
560 PIMAGE_BASE_RELOCATION RelocationDir
, RelocationEnd
;
562 ULONG_PTR Address
, MaxAddress
;
568 /* Allocate 1024 bytes for PE Header */
569 ImageHeader
= (PIMAGE_DOS_HEADER
)MmAllocateMemory(1024);
571 /* Make sure it was succesful */
572 if (ImageHeader
== NULL
) {
577 /* Load the first 1024 bytes of the kernel image so we can read the PE header */
578 if (!FsReadFile(KernelImage
, 1024, NULL
, ImageHeader
)) {
580 /* Fail if we couldn't read */
581 MmFreeMemory(ImageHeader
);
585 /* Now read the MZ header to get the offset to the PE Header */
586 NtHeader
= (PIMAGE_NT_HEADERS
)((PCHAR
)ImageHeader
+ ImageHeader
->e_lfanew
);
588 /* Get Kernel Base */
589 KernelBase
= NtHeader
->OptionalHeader
.ImageBase
;
590 FrLdrGetKernelBase();
592 /* Save Entrypoint */
593 KernelEntry
= RaToPa(NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
595 /* Save the Image Size */
596 ImageSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
598 /* Free the Header */
599 MmFreeMemory(ImageHeader
);
601 /* Set the file pointer to zero */
602 FsSetFilePointer(KernelImage
, 0);
604 /* Load the file image */
605 FsReadFile(KernelImage
, ImageSize
, NULL
, (PVOID
)KERNEL_BASE_PHYS
);
607 /* Reload the NT Header */
608 NtHeader
= (PIMAGE_NT_HEADERS
)((PCHAR
)KERNEL_BASE_PHYS
+ ImageHeader
->e_lfanew
);
610 /* Load the first section */
611 Section
= IMAGE_FIRST_SECTION(NtHeader
);
612 SectionCount
= NtHeader
->FileHeader
.NumberOfSections
- 1;
614 /* Now go to the last section */
615 Section
+= SectionCount
;
617 /* Walk each section backwards */
618 for (i
=(INT
)SectionCount
; i
>= 0; i
--, Section
--) {
620 /* Get the disk location and the memory location, and the size */
621 SourceSection
= RaToPa(Section
->PointerToRawData
);
622 TargetSection
= RaToPa(Section
->VirtualAddress
);
623 SectionSize
= Section
->SizeOfRawData
;
625 /* If the section is already mapped correctly, go to the next */
626 if (SourceSection
== TargetSection
) continue;
628 /* Load it into memory */
629 memmove((PVOID
)TargetSection
, (PVOID
)SourceSection
, SectionSize
);
631 /* Check for unitilizated data */
632 if (Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
) {
635 memset((PVOID
)RaToPa(Section
->VirtualAddress
+ Section
->SizeOfRawData
),
637 Section
->Misc
.VirtualSize
- Section
->SizeOfRawData
);
641 /* Get the Relocation Data Directory */
642 RelocationDDir
= &NtHeader
->OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
];
644 /* Get the Relocation Section Start and End*/
645 RelocationDir
= (PIMAGE_BASE_RELOCATION
)(KERNEL_BASE_PHYS
+ RelocationDDir
->VirtualAddress
);
646 RelocationEnd
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDDir
->Size
);
648 /* Calculate Difference between Real Base and Compiled Base*/
649 Delta
= KernelBase
- NtHeader
->OptionalHeader
.ImageBase
;
651 /* Determine how far we shoudl relocate */
652 MaxAddress
= KERNEL_BASE_PHYS
+ ImageSize
;
654 /* Relocate until we've processed all the blocks */
655 while (RelocationDir
< RelocationEnd
&& RelocationDir
->SizeOfBlock
> 0) {
657 /* See how many Relocation Blocks we have */
658 Count
= (RelocationDir
->SizeOfBlock
- sizeof(IMAGE_BASE_RELOCATION
)) / sizeof(USHORT
);
660 /* Calculate the Address of this Directory */
661 Address
= KERNEL_BASE_PHYS
+ RelocationDir
->VirtualAddress
;
663 /* Calculate the Offset of the Type */
664 TypeOffset
= (PUSHORT
)(RelocationDir
+ 1);
666 for (i
= 0; i
< (INT
)Count
; i
++) {
668 ShortPtr
= (PUSHORT
)(Address
+ (*TypeOffset
& 0xFFF));
670 switch (*TypeOffset
>> 12) {
672 case IMAGE_REL_BASED_ABSOLUTE
:
675 case IMAGE_REL_BASED_HIGH
:
676 *ShortPtr
+= HIWORD(Delta
);
679 case IMAGE_REL_BASED_LOW
:
680 *ShortPtr
+= LOWORD(Delta
);
683 case IMAGE_REL_BASED_HIGHLOW
:
684 LongPtr
= (PULONG
)ShortPtr
;
692 /* Move to the next Relocation Table */
693 RelocationDir
= (PIMAGE_BASE_RELOCATION
)((ULONG_PTR
)RelocationDir
+ RelocationDir
->SizeOfBlock
);
696 /* Fill out Module Data Structure */
697 reactos_modules
[0].ModStart
= KernelBase
;
698 reactos_modules
[0].ModEnd
= KernelBase
+ ImageSize
;
699 strcpy(reactos_module_strings
[0], "ntoskrnl.exe");
700 reactos_modules
[0].String
= (ULONG_PTR
)reactos_module_strings
[0];
701 LoaderBlock
.ModsCount
++;
703 /* Increase the next Load Base */
704 NextModuleBase
= ROUND_UP(KERNEL_BASE_PHYS
+ ImageSize
, PAGE_SIZE
);
712 FrLdrLoadModule(FILE *ModuleImage
,
716 ULONG LocalModuleSize
;
717 PLOADER_MODULE ModuleData
;
721 /* Get current module data structure and module name string array */
722 ModuleData
= &reactos_modules
[LoaderBlock
.ModsCount
];
724 /* Get only the Module Name */
727 TempName
= strchr(ModuleName
, '\\');
730 ModuleName
= TempName
+ 1;
734 NameBuffer
= reactos_module_strings
[LoaderBlock
.ModsCount
];
736 /* Get Module Size */
737 LocalModuleSize
= FsGetFileSize(ModuleImage
);
739 /* Fill out Module Data Structure */
740 ModuleData
->ModStart
= NextModuleBase
;
741 ModuleData
->ModEnd
= NextModuleBase
+ LocalModuleSize
;
744 strcpy(NameBuffer
, ModuleName
);
745 ModuleData
->String
= (ULONG_PTR
)NameBuffer
;
747 /* Load the file image */
748 FsReadFile(ModuleImage
, LocalModuleSize
, NULL
, (PVOID
)NextModuleBase
);
750 /* Move to next memory block and increase Module Count */
751 NextModuleBase
= ROUND_UP(ModuleData
->ModEnd
, PAGE_SIZE
);
752 LoaderBlock
.ModsCount
++;
754 /* Return Module Size if required */
755 if (ModuleSize
!= NULL
) {
756 *ModuleSize
= LocalModuleSize
;
759 return(ModuleData
->ModStart
);
764 FrLdrCreateModule(LPCSTR ModuleName
)
766 PLOADER_MODULE ModuleData
;
769 /* Get current module data structure and module name string array */
770 ModuleData
= &reactos_modules
[LoaderBlock
.ModsCount
];
771 NameBuffer
= reactos_module_strings
[LoaderBlock
.ModsCount
];
773 /* Set up the structure */
774 ModuleData
->ModStart
= NextModuleBase
;
775 ModuleData
->ModEnd
= -1;
778 strcpy(NameBuffer
, ModuleName
);
779 ModuleData
->String
= (ULONG_PTR
)NameBuffer
;
781 /* Set the current Module */
782 CurrentModule
= ModuleData
;
784 /* Return Module Base Address */
785 return(ModuleData
->ModStart
);
790 FrLdrCloseModule(ULONG_PTR ModuleBase
,
793 PLOADER_MODULE ModuleData
= CurrentModule
;
795 /* Make sure a module is opened */
798 /* Make sure this is the right module and that it hasn't been closed */
799 if ((ModuleBase
== ModuleData
->ModStart
) && (ModuleData
->ModEnd
== (ULONG_PTR
)-1)) {
801 /* Close the Module */
802 ModuleData
->ModEnd
= ModuleData
->ModStart
+ ModuleSize
;
804 /* Set the next Module Base and increase the number of modules */
805 NextModuleBase
= ROUND_UP(ModuleData
->ModEnd
, PAGE_SIZE
);
806 LoaderBlock
.ModsCount
++;
808 /* Close the currently opened module */
809 CurrentModule
= NULL
;