ReactOS 0.4.15-dev-5666-gc548b97
winldr.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Boot Loader
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: boot/freeldr/freeldr/arch/arm/winldr.c
5 * PURPOSE: ARM Kernel Loader
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9/* INCLUDES ***************************************************************/
10
11#include <freeldr.h>
12#include <debug.h>
13#include <internal/arm/mm.h>
15#include "../../winldr.h"
16
17#define PFN_SHIFT 12
18#define LARGE_PFN_SHIFT 20
19
20#define PTE_BASE 0xC0000000
21#define PDE_BASE 0xC0400000
22#define PDR_BASE 0xFFD00000
23#define VECTOR_BASE 0xFFFF0000
24
25#ifdef _ZOOM2_
26#define IDMAP_BASE 0x81000000
27#define MMIO_BASE 0x10000000
28#else
29#define IDMAP_BASE 0x00000000
30#define MMIO_BASE 0x10000000
31#endif
32
33#define LowMemPageTableIndex (IDMAP_BASE >> PDE_SHIFT)
34#define MmioPageTableIndex (MMIO_BASE >> PDE_SHIFT)
35#define KernelPageTableIndex (KSEG0_BASE >> PDE_SHIFT)
36#define StartupPtePageTableIndex (PTE_BASE >> PDE_SHIFT)
37#define StartupPdePageTableIndex (PDE_BASE >> PDE_SHIFT)
38#define PdrPageTableIndex (PDR_BASE >> PDE_SHIFT)
39#define VectorPageTableIndex (VECTOR_BASE >> PDE_SHIFT)
40
41#ifndef _ZOOM2_
44#else
45PVOID MempPdrBaseAddress = (PVOID)0x81100000;
47#endif
48
49/* Converts a Physical Address into a Page Frame Number */
50#define PaToPfn(p) ((p) >> PFN_SHIFT)
51#define PaToLargePfn(p) ((p) >> LARGE_PFN_SHIFT)
52#define PaPtrToPfn(p) (((ULONG_PTR)(p)) >> PFN_SHIFT)
53
54/* Converts a Physical Address into a Coarse Page Table PFN */
55#define PaPtrToPdePfn(p) (((ULONG_PTR)(p)) >> CPT_SHIFT)
56
57typedef struct _KPDR_PAGE
58{
59 PAGE_DIRECTORY_ARM PageDir; // 0xC0400000 [0xFFD00000]
60 CHAR HyperSpace[233 * PAGE_SIZE]; // 0xC0404000 [0xFFD04000]
61 PAGE_TABLE_ARM KernelPageTable[3]; // 0xC04ED000 [0xFFDED000]
62 CHAR SharedData[PAGE_SIZE]; // 0xC04F0000 [0xFFDF0000]
63 CHAR KernelStack[KERNEL_STACK_SIZE]; // 0xC04F1000 [0xFFDF1000]
64 CHAR PanicStack[KERNEL_STACK_SIZE]; // 0xC04F4000 [0xFFDF4000]
65 CHAR InterruptStack[KERNEL_STACK_SIZE]; // 0xC04F7000 [0xFFDF7000]
66 CHAR InitialProcess[PAGE_SIZE]; // 0xC04FA000 [0xFFDFA000]
67 CHAR InitialThread[PAGE_SIZE]; // 0xC04FB000 [0xFFDFB000]
68 CHAR Prcb[PAGE_SIZE]; // 0xC04FC000 [0xFFDFC000]
69 PAGE_TABLE_ARM PageDirPageTable; // 0xC04FD000 [0xFFDFD000]
70 PAGE_TABLE_ARM VectorPageTable; // 0xC04FE000 [0xFFDFE000]
71 CHAR Pcr[PAGE_SIZE]; // 0xC04FF000 [0xFFDFF000]
73
74C_ASSERT(sizeof(KPDR_PAGE) == (1 * 1024 * 1024));
75
80
81/* FUNCTIONS **************************************************************/
82
85 IN PFN_NUMBER NumberOfPages,
86 IN BOOLEAN KernelMapping)
87{
88 return TRUE;
89}
90
91VOID
93{
94 return;
95}
96
97VOID
99{
100 return;
101}
102
103static
106{
107 ULONG i;
108 PHARDWARE_PTE_ARMV6 PointerPte;
109 PHARDWARE_PDE_ARMV6 PointerPde;
111 PFN_NUMBER Pfn;
112
113 /* Setup the Startup PDE */
116 *LargePte = TempLargePte;
117
118 /* Map-in the PDR */
119 LargePte = &PdrPage->PageDir.Pte[PdrPageTableIndex];
120 *LargePte = TempLargePte;
121
122 /* After this point, any MiAddressToPde is guaranteed not to fault */
123
124 /*
125 * Link them in the Startup PDE.
126 * Note these are the entries in the PD at (MiAddressToPde(PTE_BASE)).
127 */
130 for (i = 0; i < 4; i++)
131 {
132 TempPde.PageFrameNumber = Pfn++;
133 *PointerPde++ = TempPde;
134 }
135
136 /*
137 * Now map these page tables in PTE space (MiAddressToPte(PTE_BASE)).
138 * Note that they all live on a single page, since each is 1KB.
139 */
140 PointerPte = &PdrPage->PageDirPageTable.Pte[0x300];
142 *PointerPte = TempPte;
143
144 /*
145 * After this point, MiAddressToPte((PDE_BASE) to MiAddressToPte(PDE_TOP))
146 * is guaranteed not to fault.
147 * Any subsequent page allocation will first need its page table created
148 * and mapped in the PTE_BASE first, then the page table itself will be
149 * editable through its flat PTE address.
150 */
151
152 /* Setup the Vector PDE */
153 PointerPde = &PdrPage->PageDir.Pde[VectorPageTableIndex];
155 *PointerPde = TempPde;
156
157 /* Setup the Vector PTEs */
158 PointerPte = &PdrPage->VectorPageTable.Pte[0xF0];
160 *PointerPte = TempPte;
161
162 /* TODO: Map in the kernel CPTs */
163 return TRUE;
164}
165
166VOID
168 IN PVOID *GdtIdt,
171{
172 PKPDR_PAGE PdrPage = (PVOID)0xFFD00000;
173
174 /* Load cache information */
175 LoaderBlock->u.Arm.FirstLevelDcacheSize = FirstLevelDcacheSize;
176 LoaderBlock->u.Arm.FirstLevelDcacheFillSize = FirstLevelDcacheFillSize;
177 LoaderBlock->u.Arm.FirstLevelIcacheSize = FirstLevelIcacheSize;
178 LoaderBlock->u.Arm.FirstLevelIcacheFillSize = FirstLevelIcacheFillSize;
179 LoaderBlock->u.Arm.SecondLevelDcacheSize = SecondLevelDcacheSize;
180 LoaderBlock->u.Arm.SecondLevelDcacheFillSize = SecondLevelDcacheFillSize;
181 LoaderBlock->u.Arm.SecondLevelIcacheSize = SecondLevelIcacheSize;
182 LoaderBlock->u.Arm.SecondLevelIcacheFillSize = SecondLevelIcacheSize;
183
184 /* Write initial context information */
185 LoaderBlock->KernelStack = (ULONG_PTR)PdrPage->KernelStack;
186 LoaderBlock->KernelStack += KERNEL_STACK_SIZE;
187 LoaderBlock->u.Arm.PanicStack = (ULONG_PTR)PdrPage->PanicStack;
188 LoaderBlock->u.Arm.PanicStack += KERNEL_STACK_SIZE;
189 LoaderBlock->u.Arm.InterruptStack = (ULONG_PTR)PdrPage->InterruptStack;
190 LoaderBlock->u.Arm.InterruptStack += KERNEL_STACK_SIZE;
191 LoaderBlock->Prcb = (ULONG_PTR)PdrPage->Prcb;
192 LoaderBlock->Process = (ULONG_PTR)PdrPage->InitialProcess;
193 LoaderBlock->Thread = (ULONG_PTR)PdrPage->InitialThread;
194}
195
196static
199{
200 ULONG i;
201 PHARDWARE_PTE_ARMV6 PointerPte;
202 PHARDWARE_PDE_ARMV6 PointerPde;
204 PFN_NUMBER Pfn;
205
206 /* Setup templates */
208
209 /* Allocate the 1MB "PDR" (Processor Data Region). Must be 1MB aligned */
213
214 /* Setup the Low Memory PDE as an identity-mapped Large Page (1MB) */
217 *LargePte = TempLargePte;
218
219 /* Setup the MMIO PDE as two identity mapped large pages -- the kernel will blow these away later */
221 Pfn = PaToLargePfn(MMIO_BASE);
222 for (i = 0; i < 2; i++)
223 {
225 *LargePte++ = TempLargePte;
226 }
227
228 /* Setup the Kernel PDEs */
229 PointerPde = &PdrPage->PageDir.Pde[KernelPageTableIndex];
231 for (i = 0; i < 12; i++)
232 {
234 *PointerPde++ = TempPde;
235 Pfn++;
236 }
237
238 /* Setup the Kernel PTEs */
239 PointerPte = PdrPage->KernelPageTable[0].Pte;
241 for (i = 0; i < 3072; i++)
242 {
243 TempPte.PageFrameNumber = Pfn++;
244 *PointerPte++ = TempPte;
245 }
246
247 /* Done */
248 return TRUE;
249}
250
251VOID
253{
254 ARM_CONTROL_REGISTER ControlRegister;
255 ARM_TTB_REGISTER TtbRegister;
256 ARM_DOMAIN_REGISTER DomainRegister;
257
258 /* Set the TTBR */
259 TtbRegister.AsUlong = (ULONG_PTR)&PdrPage->PageDir;
260 ASSERT(TtbRegister.Reserved == 0);
262
263 /* Disable domains and simply use access bits on PTEs */
264 DomainRegister.AsUlong = 0;
265 DomainRegister.Domain0 = ClientDomain;
266 KeArmDomainRegisterSet(DomainRegister);
267
268 /* Enable ARMv6+ paging (MMU), caches and the access bit */
269 ControlRegister = KeArmControlRegisterGet();
270 ControlRegister.MmuEnabled = TRUE;
271 ControlRegister.ICacheEnabled = TRUE;
272 ControlRegister.DCacheEnabled = TRUE;
273 ControlRegister.ForceAp = TRUE;
274 ControlRegister.ExtendedPageTables = TRUE;
275 KeArmControlRegisterSet(ControlRegister);
276}
277
278VOID
280 PLOADER_PARAMETER_BLOCK LoaderBlock)
281{
282}
unsigned char BOOLEAN
PVOID GdtIdt
Definition: winldr.c:25
BOOLEAN MempSetupPaging(IN PFN_NUMBER StartPage, IN PFN_NUMBER NumberOfPages, IN BOOLEAN KernelMapping)
Definition: winldr.c:170
static BOOLEAN MempAllocatePageTables(VOID)
Definition: winldr.c:33
ULONG_PTR TssBasePage
Definition: winldr.c:27
ULONG_PTR PcrBasePage
Definition: winldr.c:26
VOID MempUnmapPage(PFN_NUMBER Page)
Definition: winldr.c:204
VOID WinLdrSetProcessorContext(void)
Definition: winldr.c:348
VOID MempDump(VOID)
Definition: winldr.c:429
void WinLdrSetupMachineDependent(PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: winldr.c:379
#define PaPtrToPdePfn(p)
Definition: winldr.c:55
PVOID MempPdrBaseAddress
Definition: winldr.c:42
struct _KPDR_PAGE * PKPDR_PAGE
#define KernelPageTableIndex
Definition: winldr.c:35
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
VOID WinLdrSetupForNt(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PVOID *GdtIdt, IN PULONG PcrBasePage, IN PULONG TssBasePage)
Definition: winldr.c:167
#define StartupPdePageTableIndex
Definition: winldr.c:37
PKPDR_PAGE PdrPage
Definition: winldr.c:79
struct _KPDR_PAGE KPDR_PAGE
#define PaPtrToPfn(p)
Definition: winldr.c:52
#define StartupPtePageTableIndex
Definition: winldr.c:36
#define IDMAP_BASE
Definition: winldr.c:29
#define VectorPageTableIndex
Definition: winldr.c:39
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78
HARDWARE_LARGE_PTE_ARMV6 TempLargePte
Definition: winldr.c:77
#define PdrPageTableIndex
Definition: winldr.c:38
#define PaToLargePfn(p)
Definition: winldr.c:51
#define LowMemPageTableIndex
Definition: winldr.c:33
PVOID MempKernelBaseAddress
Definition: winldr.c:43
#define MmioPageTableIndex
Definition: winldr.c:34
#define MMIO_BASE
Definition: winldr.c:30
static BOOLEAN WinLdrMapSpecialPages(void)
Definition: winldr.c:394
FORCEINLINE VOID KeArmControlRegisterSet(IN ARM_CONTROL_REGISTER ControlRegister)
Definition: intrin_i.h:135
FORCEINLINE VOID KeArmDomainRegisterSet(IN ARM_DOMAIN_REGISTER DomainRegister)
Definition: intrin_i.h:155
FORCEINLINE ARM_CONTROL_REGISTER KeArmControlRegisterGet(VOID)
Definition: intrin_i.h:18
FORCEINLINE VOID KeArmTranslationTableRegisterSet(IN ARM_TTB_REGISTER Ttb)
Definition: intrin_i.h:145
@ ClientDomain
Definition: hardware.h:62
PVOID MmAllocateMemoryAtAddress(SIZE_T MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:85
#define TRUE
Definition: types.h:120
#define ULONG_PTR
Definition: config.h:101
#define PAGE_SIZE
Definition: env_spec_w32.h:49
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define C_ASSERT(e)
Definition: intsafe.h:73
unsigned int * PULONG
Definition: retypes.h:1
void * PVOID
Definition: retypes.h:9
unsigned int ULONG
Definition: retypes.h:1
ULONG FirstLevelIcacheFillSize
Definition: macharm.c:26
ULONG SecondLevelDcacheSize
Definition: macharm.c:27
ULONG FirstLevelDcacheFillSize
Definition: macharm.c:24
ULONG FirstLevelIcacheSize
Definition: macharm.c:25
ULONG SecondLevelIcacheSize
Definition: macharm.c:29
ULONG FirstLevelDcacheSize
Definition: macharm.c:23
ULONG SecondLevelDcacheFillSize
Definition: macharm.c:28
#define ASSERT(a)
Definition: mode.c:44
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1298
@ LoaderMemoryData
Definition: arc.h:147
#define KERNEL_STACK_SIZE
ULONG PFN_NUMBER
Definition: ke.h:9
ULONG PageFrameNumber
Definition: mmtypes.h:74
ULONG PageFrameNumber
Definition: mmtypes.h:109
PAGE_TABLE_ARM PageDirPageTable
Definition: winldr.c:69
CHAR KernelStack[KERNEL_STACK_SIZE]
Definition: winldr.c:63
PAGE_TABLE_ARM KernelPageTable[3]
Definition: winldr.c:61
CHAR Pcr[PAGE_SIZE]
Definition: winldr.c:71
PAGE_TABLE_ARM VectorPageTable
Definition: winldr.c:70
CHAR Prcb[PAGE_SIZE]
Definition: winldr.c:68
CHAR InitialThread[PAGE_SIZE]
Definition: winldr.c:67
CHAR InterruptStack[KERNEL_STACK_SIZE]
Definition: winldr.c:65
CHAR HyperSpace[233 *PAGE_SIZE]
Definition: winldr.c:60
PAGE_DIRECTORY_ARM PageDir
Definition: winldr.c:59
CHAR InitialProcess[PAGE_SIZE]
Definition: winldr.c:66
CHAR PanicStack[KERNEL_STACK_SIZE]
Definition: winldr.c:64
CHAR SharedData[PAGE_SIZE]
Definition: winldr.c:62
HARDWARE_LARGE_PTE_ARMV6 Pte[4096]
Definition: hardware.h:53
HARDWARE_PDE_ARMV6 Pde[4096]
Definition: hardware.h:52
HARDWARE_PTE_ARMV6 Pte[1024]
Definition: hardware.h:44
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
ULONG ExtendedPageTables
Definition: ketypes.h:513
int WINAPI StartPage(_In_ HDC)
char CHAR
Definition: xmlstorage.h:175