ReactOS  0.4.12-dev-396-g37af787
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 
16 #define PFN_SHIFT 12
17 #define LARGE_PFN_SHIFT 20
18 
19 #define PTE_BASE 0xC0000000
20 #define PDE_BASE 0xC0400000
21 #define PDR_BASE 0xFFD00000
22 #define VECTOR_BASE 0xFFFF0000
23 
24 #ifdef _ZOOM2_
25 #define IDMAP_BASE 0x81000000
26 #define MMIO_BASE 0x10000000
27 #else
28 #define IDMAP_BASE 0x00000000
29 #define MMIO_BASE 0x10000000
30 #endif
31 
32 #define LowMemPageTableIndex (IDMAP_BASE >> PDE_SHIFT)
33 #define MmioPageTableIndex (MMIO_BASE >> PDE_SHIFT)
34 #define KernelPageTableIndex (KSEG0_BASE >> PDE_SHIFT)
35 #define StartupPtePageTableIndex (PTE_BASE >> PDE_SHIFT)
36 #define StartupPdePageTableIndex (PDE_BASE >> PDE_SHIFT)
37 #define PdrPageTableIndex (PDR_BASE >> PDE_SHIFT)
38 #define VectorPageTableIndex (VECTOR_BASE >> PDE_SHIFT)
39 
40 #ifndef _ZOOM2_
43 #else
44 PVOID MempPdrBaseAddress = (PVOID)0x81100000;
45 PVOID MempKernelBaseAddress = (PVOID)0x80000000;
46 #endif
47 
48 /* Converts a Physical Address into a Page Frame Number */
49 #define PaToPfn(p) ((p) >> PFN_SHIFT)
50 #define PaToLargePfn(p) ((p) >> LARGE_PFN_SHIFT)
51 #define PaPtrToPfn(p) (((ULONG_PTR)(p)) >> PFN_SHIFT)
52 
53 /* Converts a Physical Address into a Coarse Page Table PFN */
54 #define PaPtrToPdePfn(p) (((ULONG_PTR)(p)) >> CPT_SHIFT)
55 
56 typedef struct _KPDR_PAGE
57 {
58  PAGE_DIRECTORY_ARM PageDir; // 0xC0400000 [0xFFD00000]
59  CHAR HyperSpace[233 * PAGE_SIZE]; // 0xC0404000 [0xFFD04000]
60  PAGE_TABLE_ARM KernelPageTable[3]; // 0xC04ED000 [0xFFDED000]
61  CHAR SharedData[PAGE_SIZE]; // 0xC04F0000 [0xFFDF0000]
62  CHAR KernelStack[KERNEL_STACK_SIZE]; // 0xC04F1000 [0xFFDF1000]
63  CHAR PanicStack[KERNEL_STACK_SIZE]; // 0xC04F4000 [0xFFDF4000]
64  CHAR InterruptStack[KERNEL_STACK_SIZE]; // 0xC04F7000 [0xFFDF7000]
65  CHAR InitialProcess[PAGE_SIZE]; // 0xC04FA000 [0xFFDFA000]
66  CHAR InitialThread[PAGE_SIZE]; // 0xC04FB000 [0xFFDFB000]
67  CHAR Prcb[PAGE_SIZE]; // 0xC04FC000 [0xFFDFC000]
68  PAGE_TABLE_ARM PageDirPageTable; // 0xC04FD000 [0xFFDFD000]
69  PAGE_TABLE_ARM VectorPageTable; // 0xC04FE000 [0xFFDFE000]
70  CHAR Pcr[PAGE_SIZE]; // 0xC04FF000 [0xFFDFF000]
72 
73 C_ASSERT(sizeof(KPDR_PAGE) == (1 * 1024 * 1024));
74 
79 
80 /* FUNCTIONS **************************************************************/
81 
82 BOOLEAN
84  IN PFN_NUMBER NumberOfPages,
85  IN BOOLEAN KernelMapping)
86 {
87  return TRUE;
88 }
89 
90 VOID
92 {
93  return;
94 }
95 
96 VOID
98 {
99  return;
100 }
101 
102 static
103 BOOLEAN
105 {
106  ULONG i;
107  PHARDWARE_PTE_ARMV6 PointerPte;
108  PHARDWARE_PDE_ARMV6 PointerPde;
109  PHARDWARE_LARGE_PTE_ARMV6 LargePte;
110  PFN_NUMBER Pfn;
111 
112  /* Setup the Startup PDE */
115  *LargePte = TempLargePte;
116 
117  /* Map-in the PDR */
118  LargePte = &PdrPage->PageDir.Pte[PdrPageTableIndex];
119  *LargePte = TempLargePte;
120 
121  /* After this point, any MiAddressToPde is guaranteed not to fault */
122 
123  /*
124  * Link them in the Startup PDE.
125  * Note these are the entries in the PD at (MiAddressToPde(PTE_BASE)).
126  */
129  for (i = 0; i < 4; i++)
130  {
131  TempPde.PageFrameNumber = Pfn++;
132  *PointerPde++ = TempPde;
133  }
134 
135  /*
136  * Now map these page tables in PTE space (MiAddressToPte(PTE_BASE)).
137  * Note that they all live on a single page, since each is 1KB.
138  */
139  PointerPte = &PdrPage->PageDirPageTable.Pte[0x300];
141  *PointerPte = TempPte;
142 
143  /*
144  * After this point, MiAddressToPte((PDE_BASE) to MiAddressToPte(PDE_TOP))
145  * is guaranteed not to fault.
146  * Any subsequent page allocation will first need its page table created
147  * and mapped in the PTE_BASE first, then the page table itself will be
148  * editable through its flat PTE address.
149  */
150 
151  /* Setup the Vector PDE */
152  PointerPde = &PdrPage->PageDir.Pde[VectorPageTableIndex];
154  *PointerPde = TempPde;
155 
156  /* Setup the Vector PTEs */
157  PointerPte = &PdrPage->VectorPageTable.Pte[0xF0];
159  *PointerPte = TempPte;
160 
161  /* TODO: Map in the kernel CPTs */
162  return TRUE;
163 }
164 
165 VOID
167  IN PVOID *GdtIdt,
170 {
171  PKPDR_PAGE PdrPage = (PVOID)0xFFD00000;
172 
173  /* Load cache information */
174  LoaderBlock->u.Arm.FirstLevelDcacheSize = FirstLevelDcacheSize;
175  LoaderBlock->u.Arm.FirstLevelDcacheFillSize = FirstLevelDcacheFillSize;
176  LoaderBlock->u.Arm.FirstLevelIcacheSize = FirstLevelIcacheSize;
177  LoaderBlock->u.Arm.FirstLevelIcacheFillSize = FirstLevelIcacheFillSize;
178  LoaderBlock->u.Arm.SecondLevelDcacheSize = SecondLevelDcacheSize;
179  LoaderBlock->u.Arm.SecondLevelDcacheFillSize = SecondLevelDcacheFillSize;
180  LoaderBlock->u.Arm.SecondLevelIcacheSize = SecondLevelIcacheSize;
181  LoaderBlock->u.Arm.SecondLevelIcacheFillSize = SecondLevelIcacheSize;
182 
183  /* Write initial context information */
184  LoaderBlock->KernelStack = (ULONG_PTR)PdrPage->KernelStack;
185  LoaderBlock->KernelStack += KERNEL_STACK_SIZE;
186  LoaderBlock->u.Arm.PanicStack = (ULONG_PTR)PdrPage->PanicStack;
187  LoaderBlock->u.Arm.PanicStack += KERNEL_STACK_SIZE;
188  LoaderBlock->u.Arm.InterruptStack = (ULONG_PTR)PdrPage->InterruptStack;
189  LoaderBlock->u.Arm.InterruptStack += KERNEL_STACK_SIZE;
190  LoaderBlock->Prcb = (ULONG_PTR)PdrPage->Prcb;
191  LoaderBlock->Process = (ULONG_PTR)PdrPage->InitialProcess;
192  LoaderBlock->Thread = (ULONG_PTR)PdrPage->InitialThread;
193 }
194 
195 static
196 BOOLEAN
198 {
199  ULONG i;
200  PHARDWARE_PTE_ARMV6 PointerPte;
201  PHARDWARE_PDE_ARMV6 PointerPde;
202  PHARDWARE_LARGE_PTE_ARMV6 LargePte;
203  PFN_NUMBER Pfn;
204 
205  /* Setup templates */
207 
208  /* Allocate the 1MB "PDR" (Processor Data Region). Must be 1MB aligned */
212 
213  /* Setup the Low Memory PDE as an identity-mapped Large Page (1MB) */
214  LargePte = &PdrPage->PageDir.Pte[LowMemPageTableIndex];
216  *LargePte = TempLargePte;
217 
218  /* Setup the MMIO PDE as two identity mapped large pages -- the kernel will blow these away later */
219  LargePte = &PdrPage->PageDir.Pte[MmioPageTableIndex];
220  Pfn = PaToLargePfn(MMIO_BASE);
221  for (i = 0; i < 2; i++)
222  {
224  *LargePte++ = TempLargePte;
225  }
226 
227  /* Setup the Kernel PDEs */
228  PointerPde = &PdrPage->PageDir.Pde[KernelPageTableIndex];
230  for (i = 0; i < 12; i++)
231  {
232  TempPde.PageFrameNumber = Pfn;
233  *PointerPde++ = TempPde;
234  Pfn++;
235  }
236 
237  /* Setup the Kernel PTEs */
238  PointerPte = PdrPage->KernelPageTable[0].Pte;
240  for (i = 0; i < 3072; i++)
241  {
242  TempPte.PageFrameNumber = Pfn++;
243  *PointerPte++ = TempPte;
244  }
245 
246  /* Done */
247  return TRUE;
248 }
249 
250 VOID
252 {
253  ARM_CONTROL_REGISTER ControlRegister;
254  ARM_TTB_REGISTER TtbRegister;
255  ARM_DOMAIN_REGISTER DomainRegister;
256 
257  /* Set the TTBR */
258  TtbRegister.AsUlong = (ULONG_PTR)&PdrPage->PageDir;
259  ASSERT(TtbRegister.Reserved == 0);
261 
262  /* Disable domains and simply use access bits on PTEs */
263  DomainRegister.AsUlong = 0;
264  DomainRegister.Domain0 = ClientDomain;
265  KeArmDomainRegisterSet(DomainRegister);
266 
267  /* Enable ARMv6+ paging (MMU), caches and the access bit */
268  ControlRegister = KeArmControlRegisterGet();
269  ControlRegister.MmuEnabled = TRUE;
270  ControlRegister.ICacheEnabled = TRUE;
271  ControlRegister.DCacheEnabled = TRUE;
272  ControlRegister.ForceAp = TRUE;
273  ControlRegister.ExtendedPageTables = TRUE;
274  KeArmControlRegisterSet(ControlRegister);
275 }
276 
277 VOID
279  PLOADER_PARAMETER_BLOCK LoaderBlock)
280 {
281 }
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:32
CHAR Pcr[PAGE_SIZE]
Definition: winldr.c:70
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:77
PVOID MempPdrBaseAddress
Definition: winldr.c:41
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:29
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:65
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:54
#define MmioPageTableIndex
Definition: winldr.c:33
PAGE_DIRECTORY_ARM PageDir
Definition: winldr.c:58
PVOID MempKernelBaseAddress
Definition: winldr.c:42
ULONG PageFrameNumber
Definition: mmtypes.h:74
PAGE_TABLE_ARM PageDirPageTable
Definition: winldr.c:68
#define StartupPdePageTableIndex
Definition: winldr.c:36
PAGE_TABLE_ARM KernelPageTable[3]
Definition: winldr.c:60
#define KernelPageTableIndex
Definition: winldr.c:34
HARDWARE_PTE_ARMV6 TempPte
Definition: winldr.c:75
#define KERNEL_STACK_SIZE
#define PaToLargePfn(p)
Definition: winldr.c:50
static BOOLEAN MempAllocatePageTables(VOID)
Definition: winldr.c:197
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
PKPDR_PAGE PdrPage
Definition: winldr.c:78
#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
VOID WinLdrSetupForNt(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PVOID *GdtIdt, IN ULONG *PcrBasePage, IN ULONG *TssBasePage)
Definition: winldr.c:166
ULONG ExtendedPageTables
Definition: ketypes.h:494
PAGE_TABLE_ARM VectorPageTable
Definition: winldr.c:69
#define VectorPageTableIndex
Definition: winldr.c:38
ULONG SecondLevelIcacheSize
Definition: macharm.c:29
CHAR InitialThread[PAGE_SIZE]
Definition: winldr.c:66
#define IDMAP_BASE
Definition: winldr.c:28
#define PdrPageTableIndex
Definition: winldr.c:37
CHAR KernelStack[KERNEL_STACK_SIZE]
Definition: winldr.c:62
CHAR HyperSpace[233 *PAGE_SIZE]
Definition: winldr.c:59
static BOOLEAN WinLdrMapSpecialPages(ULONG PcrBasePage)
Definition: winldr.c:104
CHAR SharedData[PAGE_SIZE]
Definition: winldr.c:61
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
CHAR Prcb[PAGE_SIZE]
Definition: winldr.c:67
PVOID GdtIdt
Definition: winldr.c:25
CHAR InterruptStack[KERNEL_STACK_SIZE]
Definition: winldr.c:64
#define PaPtrToPfn(p)
Definition: winldr.c:51
ULONG FirstLevelIcacheFillSize
Definition: macharm.c:26
CHAR PanicStack[KERNEL_STACK_SIZE]
Definition: winldr.c:63
ULONG PageFrameNumber
Definition: mmtypes.h:109
#define StartupPtePageTableIndex
Definition: winldr.c:35
HARDWARE_LARGE_PTE_ARMV6 TempLargePte
Definition: winldr.c:76
struct _KPDR_PAGE KPDR_PAGE
FORCEINLINE VOID KeArmTranslationTableRegisterSet(IN ARM_TTB_REGISTER Ttb)
Definition: intrin_i.h:145