ReactOS  r76032
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 
78 PKPDR_PAGE PdrPage;
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 */
113  LargePte = &PdrPage->PageDir.Pte[StartupPdePageTableIndex];
114  TempLargePte.PageFrameNumber = PaToLargePfn((ULONG_PTR)&PdrPage->PageDir);
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  */
127  PointerPde = &PdrPage->PageDir.Pde[StartupPtePageTableIndex];
128  Pfn = PaPtrToPdePfn(&PdrPage->PageDirPageTable);
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];
140  TempPte.PageFrameNumber = PaPtrToPfn(&PdrPage->PageDirPageTable);
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];
153  TempPde.PageFrameNumber = PaPtrToPdePfn(&PdrPage->VectorPageTable);
154  *PointerPde = TempPde;
155 
156  /* Setup the Vector PTEs */
157  PointerPte = &PdrPage->VectorPageTable.Pte[0xF0];
158  TempPte.PageFrameNumber = 0;
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 */
206  TempPte.Sbo = TempPte.Valid = TempLargePte.LargePage = TempLargePte.Sbo = TempPde.Valid = 1;
207 
208  /* Allocate the 1MB "PDR" (Processor Data Region). Must be 1MB aligned */
209  PdrPage = MmAllocateMemoryAtAddress(sizeof(KPDR_PAGE),
212 
213  /* Setup the Low Memory PDE as an identity-mapped Large Page (1MB) */
214  LargePte = &PdrPage->PageDir.Pte[LowMemPageTableIndex];
215  TempLargePte.PageFrameNumber = PaToLargePfn(IDMAP_BASE);
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  {
223  TempLargePte.PageFrameNumber = Pfn++;
224  *LargePte++ = TempLargePte;
225  }
226 
227  /* Setup the Kernel PDEs */
228  PointerPde = &PdrPage->PageDir.Pde[KernelPageTableIndex];
229  Pfn = PaPtrToPdePfn(PdrPage->KernelPageTable);
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 }
DWORD *typedef PVOID
Definition: winlogon.h:52
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
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
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)
GLenum GLclampf GLint i
Definition: glfuncs.h:14
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
void WinLdrSetupMachineDependent(PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: winldr.c:379
ULONG SecondLevelDcacheFillSize
Definition: macharm.c:28
ULONG_PTR TssBasePage
Definition: winldr.c:27
#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
unsigned char BOOLEAN
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
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