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.
27 /* Page Directory and Tables for non-PAE Systems */
28 extern ULONG_PTR NextModuleBase
;
29 extern ULONG_PTR KernelBase
;
30 extern ROS_KERNEL_ENTRY_POINT KernelEntryPoint
;
32 PPAGE_DIRECTORY_AMD64 pPML4
;
34 /* FUNCTIONS *****************************************************************/
40 * Prepares the system for loading the Kernel.
43 * Magic - Multiboot Magic
54 FrLdrStartup(ULONG Magic
)
56 /* Disable Interrupts */
59 /* Re-initalize EFLAGS */
62 /* Initialize the page directory */
63 FrLdrSetupPageDirectory();
65 /* Set the new PML4 */
66 __writecr3((ULONGLONG
)pPML4
);
68 DbgPrint((DPRINT_WARNING
, "Jumping to kernel @ %p.\n", KernelEntryPoint
));
71 (*KernelEntryPoint
)(Magic
, &LoaderBlock
);
76 FrLdrGetOrCreatePageDir(PPAGE_DIRECTORY_AMD64 pDir
, ULONG Index
)
78 PPAGE_DIRECTORY_AMD64 pSubDir
;
83 if (!pDir
->Pde
[Index
].Valid
)
85 pSubDir
= MmAllocateMemoryWithType(PAGE_SIZE
, LoaderSpecialMemory
);
88 RtlZeroMemory(pSubDir
, PAGE_SIZE
);
89 pDir
->Pde
[Index
].PageFrameNumber
= (ULONGLONG
)pSubDir
/ PAGE_SIZE
;
90 pDir
->Pde
[Index
].Valid
= 1;
91 pDir
->Pde
[Index
].Write
= 1;
95 pSubDir
= (PPAGE_DIRECTORY_AMD64
)((ULONGLONG
)(pDir
->Pde
[Index
].PageFrameNumber
) * PAGE_SIZE
);
101 FrLdrMapSinglePage(ULONGLONG VirtualAddress
, ULONGLONG PhysicalAddress
)
103 PPAGE_DIRECTORY_AMD64 pDir3
, pDir2
, pDir1
;
106 pDir3
= FrLdrGetOrCreatePageDir(pPML4
, VAtoIndex4(VirtualAddress
));
107 pDir2
= FrLdrGetOrCreatePageDir(pDir3
, VAtoIndex3(VirtualAddress
));
108 pDir1
= FrLdrGetOrCreatePageDir(pDir2
, VAtoIndex2(VirtualAddress
));
113 Index
= VAtoIndex1(VirtualAddress
);
114 if (pDir1
->Pde
[Index
].Valid
)
119 pDir1
->Pde
[Index
].Valid
= 1;
120 pDir1
->Pde
[Index
].Write
= 1;
121 pDir1
->Pde
[Index
].PageFrameNumber
= PhysicalAddress
/ PAGE_SIZE
;
127 FrLdrMapRangeOfPages(ULONGLONG VirtualAddress
, ULONGLONG PhysicalAddress
, ULONG cPages
)
131 for (i
= 0; i
< cPages
; i
++)
133 if (!FrLdrMapSinglePage(VirtualAddress
, PhysicalAddress
))
137 VirtualAddress
+= PAGE_SIZE
;
138 PhysicalAddress
+= PAGE_SIZE
;
145 * FrLdrSetupPageDirectory
148 * Sets up the ReactOS Startup Page Directory.
157 * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure.
158 * As such, please note that PageFrameNumber == PageEntryNumber.
163 FrLdrSetupPageDirectory(VOID
)
167 /* Allocate a Page for the PML4 */
168 pPML4
= MmAllocateMemoryWithType(4096, LoaderSpecialMemory
);
172 /* The page tables are located at 0xfffff68000000000
173 * We create a recursive self mapping through all 4 levels at
174 * virtual address 0xfffff6fb7dbedf68 */
175 pPML4
->Pde
[VAtoIndex4(PML4_BASE
)].Valid
= 1;
176 pPML4
->Pde
[VAtoIndex4(PML4_BASE
)].Write
= 1;
177 pPML4
->Pde
[VAtoIndex4(PML4_BASE
)].PageFrameNumber
= PtrToPfn(PML4_BASE
);
179 ASSERT(VAtoIndex4(PML4_BASE
) == 0x1ed);
180 ASSERT(VAtoIndex3(PML4_BASE
) == 0x1ed);
181 ASSERT(VAtoIndex2(PML4_BASE
) == 0x1ed);
182 ASSERT(VAtoIndex1(PML4_BASE
) == 0x1ed);
184 /* Setup low memory pages */
185 if (FrLdrMapRangeOfPages(0, 0, 1024) < 1024)
187 DbgPrint((DPRINT_WARNING
, "Could not map low memory pages.\n"));
190 /* Setup kernel pages */
191 KernelPages
= (ROUND_TO_PAGES(NextModuleBase
- KERNEL_BASE_PHYS
) / PAGE_SIZE
);
192 DbgPrint((DPRINT_WARNING
, "Trying to map %d pages for kernel.\n", KernelPages
));
193 if (FrLdrMapRangeOfPages(KernelBase
, KERNEL_BASE_PHYS
, KernelPages
) != KernelPages
)
195 DbgPrint((DPRINT_WARNING
, "Could not map %d kernel pages.\n", KernelPages
));