ReactOS  0.4.14-dev-614-gbfd8a84
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>
14 #include <internal/arm/intrin_i.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
45 PVOID MempPdrBaseAddress = (PVOID)0x81100000;
46 PVOID MempKernelBaseAddress = (PVOID)0x80000000;
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 
57 typedef 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 
74 C_ASSERT(sizeof(KPDR_PAGE) == (1 * 1024 * 1024));
75 
80 
81 /* FUNCTIONS **************************************************************/
82 
83 BOOLEAN
85  IN PFN_NUMBER NumberOfPages,
86  IN BOOLEAN KernelMapping)
87 {
88  return TRUE;
89 }
90 
91 VOID
93 {
94  return;
95 }
96 
97 VOID
99 {
100  return;
101 }
102 
103 static
104 BOOLEAN
106 {
107  ULONG i;
108  PHARDWARE_PTE_ARMV6 PointerPte;
109  PHARDWARE_PDE_ARMV6 PointerPde;
110  PHARDWARE_LARGE_PTE_ARMV6 LargePte;
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 
166 VOID
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 
196 static
197 BOOLEAN
199 {
200  ULONG i;
201  PHARDWARE_PTE_ARMV6 PointerPte;
202  PHARDWARE_PDE_ARMV6 PointerPde;
203  PHARDWARE_LARGE_PTE_ARMV6 LargePte;
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) */
215  LargePte = &PdrPage->PageDir.Pte[LowMemPageTableIndex];
217  *LargePte = TempLargePte;
218 
219  /* Setup the MMIO PDE as two identity mapped large pages -- the kernel will blow these away later */
220  LargePte = &PdrPage->PageDir.Pte[MmioPageTableIndex];
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  {
233  TempPde.PageFrameNumber = Pfn;
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 
251 VOID
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 
278 VOID
280  PLOADER_PARAMETER_BLOCK LoaderBlock)
281 {
282 }
VOID MempDump(VOID)
Definition: winldr.c:429
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
FORCEINLINE VOID KeArmDomainRegisterSet(IN ARM_DOMAIN_REGISTER DomainRegister)
Definition: intrin_i.h:155
HARDWARE_PDE_ARMV6 Pde[4096]
Definition: hardware.h:52
ULONG FirstLevelIcacheSize
Definition: macharm.c:25
#define LowMemPageTableIndex
Definition: winldr.c:33
CHAR Pcr[PAGE_SIZE]
Definition: winldr.c:71
FORCEINLINE ARM_CONTROL_REGISTER KeArmControlRegisterGet(VOID)
Definition: intrin_i.h:18
VOID WinLdrSetProcessorContext(void)
Definition: winldr.c:348
char CHAR
Definition: xmlstorage.h:175
VOID MempUnmapPage(PFN_NUMBER Page)
Definition: winldr.c:204
ULONG FirstLevelDcacheSize
Definition: macharm.c:23
HARDWARE_PDE_ARMV6 TempPde
Definition: winldr.c:78
PVOID MempPdrBaseAddress
Definition: winldr.c:42
HARDWARE_LARGE_PTE_ARMV6 Pte[4096]
Definition: hardware.h:53
struct _KPDR_PAGE * PKPDR_PAGE
BOOLEAN MempSetupPaging(IN PFN_NUMBER StartPage, IN PFN_NUMBER NumberOfPages, IN BOOLEAN KernelMapping)
Definition: winldr.c:170
ULONG_PTR PcrBasePage
Definition: winldr.c:26
ULONG SecondLevelDcacheSize
Definition: macharm.c:27
#define MMIO_BASE
Definition: winldr.c:30
C_ASSERT(sizeof(KPDR_PAGE)==(1 *1024 *1024))
uint32_t ULONG_PTR
Definition: typedefs.h:63
int WINAPI StartPage(_In_ HDC)
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
ULONG PFN_NUMBER
Definition: ke.h:8
CHAR InitialProcess[PAGE_SIZE]
Definition: winldr.c:66
VOID WinLdrSetupForNt(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PVOID *GdtIdt, IN PULONG PcrBasePage, IN PULONG TssBasePage)
Definition: winldr.c:167
FORCEINLINE VOID KeArmControlRegisterSet(IN ARM_CONTROL_REGISTER ControlRegister)
Definition: intrin_i.h:135
unsigned char BOOLEAN
void WinLdrSetupMachineDependent(PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: winldr.c:379
ULONG SecondLevelDcacheFillSize
Definition: macharm.c:28
ULONG_PTR TssBasePage
Definition: winldr.c:27
void * PVOID
Definition: retypes.h:9
#define PaPtrToPdePfn(p)
Definition: winldr.c:55
#define MmioPageTableIndex
Definition: winldr.c:34
PAGE_DIRECTORY_ARM PageDir
Definition: winldr.c:59
PVOID MempKernelBaseAddress
Definition: winldr.c:43
ULONG PageFrameNumber
Definition: mmtypes.h:74
PAGE_TABLE_ARM PageDirPageTable
Definition: winldr.c:69
#define StartupPdePageTableIndex
Definition: winldr.c:37
PAGE_TABLE_ARM KernelPageTable[3]
Definition: winldr.c:61
#define KernelPageTableIndex
Definition: winldr.c:35
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:76
#define KERNEL_STACK_SIZE
#define PaToLargePfn(p)
Definition: winldr.c:51
static BOOLEAN MempAllocatePageTables(VOID)
Definition: winldr.c:198
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
PKPDR_PAGE PdrPage
Definition: winldr.c:79
#define PAGE_SIZE
Definition: env_spec_w32.h:49
PVOID MmAllocateMemoryAtAddress(SIZE_T MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType)
Definition: mm.c:85
ULONG FirstLevelDcacheFillSize
Definition: macharm.c:24
HARDWARE_PTE_ARMV6 Pte[1024]
Definition: hardware.h:44
ULONG ExtendedPageTables
Definition: ketypes.h:512
PAGE_TABLE_ARM VectorPageTable
Definition: winldr.c:70
#define VectorPageTableIndex
Definition: winldr.c:39
ULONG SecondLevelIcacheSize
Definition: macharm.c:29
CHAR InitialThread[PAGE_SIZE]
Definition: winldr.c:67
#define IDMAP_BASE
Definition: winldr.c:29
#define PdrPageTableIndex
Definition: winldr.c:38
unsigned int * PULONG
Definition: retypes.h:1
CHAR KernelStack[KERNEL_STACK_SIZE]
Definition: winldr.c:63
CHAR HyperSpace[233 *PAGE_SIZE]
Definition: winldr.c:60
static BOOLEAN WinLdrMapSpecialPages(ULONG PcrBasePage)
Definition: winldr.c:105
CHAR SharedData[PAGE_SIZE]
Definition: winldr.c:62
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
CHAR Prcb[PAGE_SIZE]
Definition: winldr.c:68
PVOID GdtIdt
Definition: winldr.c:25
CHAR InterruptStack[KERNEL_STACK_SIZE]
Definition: winldr.c:65
#define PaPtrToPfn(p)
Definition: winldr.c:52
ULONG FirstLevelIcacheFillSize
Definition: macharm.c:26
CHAR PanicStack[KERNEL_STACK_SIZE]
Definition: winldr.c:64
ULONG PageFrameNumber
Definition: mmtypes.h:109
#define StartupPtePageTableIndex
Definition: winldr.c:36
HARDWARE_LARGE_PTE_ARMV6 TempLargePte
Definition: winldr.c:77
struct _KPDR_PAGE KPDR_PAGE
FORCEINLINE VOID KeArmTranslationTableRegisterSet(IN ARM_TTB_REGISTER Ttb)
Definition: intrin_i.h:145