Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenwinldr.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Boot Loader 00003 * LICENSE: BSD - See COPYING.ARM in the top level directory 00004 * FILE: boot/freeldr/arch/arm/loader.c 00005 * PURPOSE: ARM Kernel Loader 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 */ 00008 00009 /* INCLUDES ***************************************************************/ 00010 00011 #include <freeldr.h> 00012 #include <debug.h> 00013 #include <internal/arm/mm.h> 00014 #include <internal/arm/intrin_i.h> 00015 00016 #define PFN_SHIFT 12 00017 #define LARGE_PFN_SHIFT 20 00018 00019 #define PTE_BASE 0xC0000000 00020 #define PDE_BASE 0xC0400000 00021 #define PDR_BASE 0xFFD00000 00022 #define VECTOR_BASE 0xFFFF0000 00023 00024 #ifdef _ZOOM2_ 00025 #define IDMAP_BASE 0x81000000 00026 #define MMIO_BASE 0x10000000 00027 #else 00028 #define IDMAP_BASE 0x00000000 00029 #define MMIO_BASE 0x10000000 00030 #endif 00031 00032 #define LowMemPageTableIndex (IDMAP_BASE >> PDE_SHIFT) 00033 #define MmioPageTableIndex (MMIO_BASE >> PDE_SHIFT) 00034 #define KernelPageTableIndex (KSEG0_BASE >> PDE_SHIFT) 00035 #define StartupPtePageTableIndex (PTE_BASE >> PDE_SHIFT) 00036 #define StartupPdePageTableIndex (PDE_BASE >> PDE_SHIFT) 00037 #define PdrPageTableIndex (PDR_BASE >> PDE_SHIFT) 00038 #define VectorPageTableIndex (VECTOR_BASE >> PDE_SHIFT) 00039 00040 #ifndef _ZOOM2_ 00041 PVOID MempPdrBaseAddress = (PVOID)0x70000; 00042 PVOID MempKernelBaseAddress = (PVOID)0; 00043 #else 00044 PVOID MempPdrBaseAddress = (PVOID)0x81100000; 00045 PVOID MempKernelBaseAddress = (PVOID)0x80000000; 00046 #endif 00047 00048 /* Converts a Physical Address into a Page Frame Number */ 00049 #define PaToPfn(p) ((p) >> PFN_SHIFT) 00050 #define PaToLargePfn(p) ((p) >> LARGE_PFN_SHIFT) 00051 #define PaPtrToPfn(p) (((ULONG_PTR)(p)) >> PFN_SHIFT) 00052 00053 /* Converts a Physical Address into a Coarse Page Table PFN */ 00054 #define PaPtrToPdePfn(p) (((ULONG_PTR)(p)) >> CPT_SHIFT) 00055 00056 typedef struct _KPDR_PAGE 00057 { 00058 PAGE_DIRECTORY_ARM PageDir; // 0xC0400000 [0xFFD00000] 00059 CHAR HyperSpace[233 * PAGE_SIZE]; // 0xC0404000 [0xFFD04000] 00060 PAGE_TABLE_ARM KernelPageTable[3]; // 0xC04ED000 [0xFFDED000] 00061 CHAR SharedData[PAGE_SIZE]; // 0xC04F0000 [0xFFDF0000] 00062 CHAR KernelStack[KERNEL_STACK_SIZE]; // 0xC04F1000 [0xFFDF1000] 00063 CHAR PanicStack[KERNEL_STACK_SIZE]; // 0xC04F4000 [0xFFDF4000] 00064 CHAR InterruptStack[KERNEL_STACK_SIZE]; // 0xC04F7000 [0xFFDF7000] 00065 CHAR InitialProcess[PAGE_SIZE]; // 0xC04FA000 [0xFFDFA000] 00066 CHAR InitialThread[PAGE_SIZE]; // 0xC04FB000 [0xFFDFB000] 00067 CHAR Prcb[PAGE_SIZE]; // 0xC04FC000 [0xFFDFC000] 00068 PAGE_TABLE_ARM PageDirPageTable; // 0xC04FD000 [0xFFDFD000] 00069 PAGE_TABLE_ARM VectorPageTable; // 0xC04FE000 [0xFFDFE000] 00070 CHAR Pcr[PAGE_SIZE]; // 0xC04FF000 [0xFFDFF000] 00071 } KPDR_PAGE, *PKPDR_PAGE; 00072 00073 C_ASSERT(sizeof(KPDR_PAGE) == (1 * 1024 * 1024)); 00074 00075 HARDWARE_PTE_ARMV6 TempPte; 00076 HARDWARE_LARGE_PTE_ARMV6 TempLargePte; 00077 HARDWARE_PDE_ARMV6 TempPde; 00078 PKPDR_PAGE PdrPage; 00079 00080 /* FUNCTIONS **************************************************************/ 00081 00082 BOOLEAN 00083 MempSetupPaging(IN PFN_NUMBER StartPage, 00084 IN PFN_COUNT NumberOfPages) 00085 { 00086 return TRUE; 00087 } 00088 00089 VOID 00090 MempUnmapPage(IN PFN_NUMBER Page) 00091 { 00092 return; 00093 } 00094 00095 VOID 00096 MempDump(VOID) 00097 { 00098 return; 00099 } 00100 00101 BOOLEAN 00102 WinLdrMapSpecialPages(ULONG PcrBasePage) 00103 { 00104 ULONG i; 00105 PHARDWARE_PTE_ARMV6 PointerPte; 00106 PHARDWARE_PDE_ARMV6 PointerPde; 00107 PHARDWARE_LARGE_PTE_ARMV6 LargePte; 00108 PFN_NUMBER Pfn; 00109 00110 /* Setup the Startup PDE */ 00111 LargePte = &PdrPage->PageDir.Pte[StartupPdePageTableIndex]; 00112 TempLargePte.PageFrameNumber = PaToLargePfn((ULONG_PTR)&PdrPage->PageDir); 00113 *LargePte = TempLargePte; 00114 00115 /* Map-in the PDR */ 00116 LargePte = &PdrPage->PageDir.Pte[PdrPageTableIndex]; 00117 *LargePte = TempLargePte; 00118 00119 /* After this point, any MiAddressToPde is guaranteed not to fault */ 00120 00121 /* 00122 * Link them in the Startup PDE. 00123 * Note these are the entries in the PD at (MiAddressToPde(PTE_BASE)). 00124 */ 00125 PointerPde = &PdrPage->PageDir.Pde[StartupPtePageTableIndex]; 00126 Pfn = PaPtrToPdePfn(&PdrPage->PageDirPageTable); 00127 for (i = 0; i < 4; i++) 00128 { 00129 TempPde.PageFrameNumber = Pfn++; 00130 *PointerPde++ = TempPde; 00131 } 00132 00133 /* 00134 * Now map these page tables in PTE space (MiAddressToPte(PTE_BASE)). 00135 * Note that they all live on a single page, since each is 1KB. 00136 */ 00137 PointerPte = &PdrPage->PageDirPageTable.Pte[0x300]; 00138 TempPte.PageFrameNumber = PaPtrToPfn(&PdrPage->PageDirPageTable); 00139 *PointerPte = TempPte; 00140 00141 /* 00142 * After this point, MiAddressToPte((PDE_BASE) to MiAddressToPte(PDE_TOP)) 00143 * is guaranteed not to fault. 00144 * Any subsequent page allocation will first need its page table created 00145 * and mapped in the PTE_BASE first, then the page table itself will be 00146 * editable through its flat PTE address. 00147 */ 00148 00149 /* Setup the Vector PDE */ 00150 PointerPde = &PdrPage->PageDir.Pde[VectorPageTableIndex]; 00151 TempPde.PageFrameNumber = PaPtrToPdePfn(&PdrPage->VectorPageTable); 00152 *PointerPde = TempPde; 00153 00154 /* Setup the Vector PTEs */ 00155 PointerPte = &PdrPage->VectorPageTable.Pte[0xF0]; 00156 TempPte.PageFrameNumber = 0; 00157 *PointerPte = TempPte; 00158 00159 /* TODO: Map in the kernel CPTs */ 00160 return TRUE; 00161 } 00162 00163 VOID 00164 WinLdrSetupForNt(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 00165 IN PVOID *GdtIdt, 00166 IN ULONG *PcrBasePage, 00167 IN ULONG *TssBasePage) 00168 { 00169 PKPDR_PAGE PdrPage = (PVOID)0xFFD00000; 00170 00171 /* Load cache information */ 00172 LoaderBlock->u.Arm.FirstLevelDcacheSize = FirstLevelDcacheSize; 00173 LoaderBlock->u.Arm.FirstLevelDcacheFillSize = FirstLevelDcacheFillSize; 00174 LoaderBlock->u.Arm.FirstLevelIcacheSize = FirstLevelIcacheSize; 00175 LoaderBlock->u.Arm.FirstLevelIcacheFillSize = FirstLevelIcacheFillSize; 00176 LoaderBlock->u.Arm.SecondLevelDcacheSize = SecondLevelDcacheSize; 00177 LoaderBlock->u.Arm.SecondLevelDcacheFillSize = SecondLevelDcacheFillSize; 00178 LoaderBlock->u.Arm.SecondLevelIcacheSize = SecondLevelIcacheSize; 00179 LoaderBlock->u.Arm.SecondLevelIcacheFillSize = SecondLevelIcacheSize; 00180 00181 /* Write initial context information */ 00182 LoaderBlock->KernelStack = (ULONG_PTR)PdrPage->KernelStack; 00183 LoaderBlock->KernelStack += KERNEL_STACK_SIZE; 00184 LoaderBlock->u.Arm.PanicStack = (ULONG_PTR)PdrPage->PanicStack; 00185 LoaderBlock->u.Arm.PanicStack += KERNEL_STACK_SIZE; 00186 LoaderBlock->u.Arm.InterruptStack = (ULONG_PTR)PdrPage->InterruptStack; 00187 LoaderBlock->u.Arm.InterruptStack += KERNEL_STACK_SIZE; 00188 LoaderBlock->Prcb = (ULONG_PTR)PdrPage->Prcb; 00189 LoaderBlock->Process = (ULONG_PTR)PdrPage->InitialProcess; 00190 LoaderBlock->Thread = (ULONG_PTR)PdrPage->InitialThread; 00191 } 00192 00193 BOOLEAN 00194 MempAllocatePageTables(VOID) 00195 { 00196 ULONG i; 00197 PHARDWARE_PTE_ARMV6 PointerPte; 00198 PHARDWARE_PDE_ARMV6 PointerPde; 00199 PHARDWARE_LARGE_PTE_ARMV6 LargePte; 00200 PFN_NUMBER Pfn; 00201 00202 /* Setup templates */ 00203 TempPte.Sbo = TempPte.Valid = TempLargePte.LargePage = TempLargePte.Sbo = TempPde.Valid = 1; 00204 00205 /* Allocate the 1MB "PDR" (Processor Data Region). Must be 1MB aligned */ 00206 PdrPage = MmAllocateMemoryAtAddress(sizeof(KPDR_PAGE), 00207 MempPdrBaseAddress, 00208 LoaderMemoryData); 00209 00210 /* Setup the Low Memory PDE as an identity-mapped Large Page (1MB) */ 00211 LargePte = &PdrPage->PageDir.Pte[LowMemPageTableIndex]; 00212 TempLargePte.PageFrameNumber = PaToLargePfn(IDMAP_BASE); 00213 *LargePte = TempLargePte; 00214 00215 /* Setup the MMIO PDE as two identity mapped large pages -- the kernel will blow these away later */ 00216 LargePte = &PdrPage->PageDir.Pte[MmioPageTableIndex]; 00217 Pfn = PaToLargePfn(MMIO_BASE); 00218 for (i = 0; i < 2; i++) 00219 { 00220 TempLargePte.PageFrameNumber = Pfn++; 00221 *LargePte++ = TempLargePte; 00222 } 00223 00224 /* Setup the Kernel PDEs */ 00225 PointerPde = &PdrPage->PageDir.Pde[KernelPageTableIndex]; 00226 Pfn = PaPtrToPdePfn(PdrPage->KernelPageTable); 00227 for (i = 0; i < 12; i++) 00228 { 00229 TempPde.PageFrameNumber = Pfn; 00230 *PointerPde++ = TempPde; 00231 Pfn++; 00232 } 00233 00234 /* Setup the Kernel PTEs */ 00235 PointerPte = PdrPage->KernelPageTable[0].Pte; 00236 Pfn = PaPtrToPfn(MempKernelBaseAddress); 00237 for (i = 0; i < 3072; i++) 00238 { 00239 TempPte.PageFrameNumber = Pfn++; 00240 *PointerPte++ = TempPte; 00241 } 00242 00243 /* Done */ 00244 return TRUE; 00245 } 00246 00247 VOID 00248 WinLdrSetProcessorContext(PVOID GdtIdt, 00249 IN ULONG Pcr, 00250 IN ULONG Tss) 00251 { 00252 ARM_CONTROL_REGISTER ControlRegister; 00253 ARM_TTB_REGISTER TtbRegister; 00254 ARM_DOMAIN_REGISTER DomainRegister; 00255 00256 /* Set the TTBR */ 00257 TtbRegister.AsUlong = (ULONG_PTR)&PdrPage->PageDir; 00258 ASSERT(TtbRegister.Reserved == 0); 00259 KeArmTranslationTableRegisterSet(TtbRegister); 00260 00261 /* Disable domains and simply use access bits on PTEs */ 00262 DomainRegister.AsUlong = 0; 00263 DomainRegister.Domain0 = ClientDomain; 00264 KeArmDomainRegisterSet(DomainRegister); 00265 00266 /* Enable ARMv6+ paging (MMU), caches and the access bit */ 00267 ControlRegister = KeArmControlRegisterGet(); 00268 ControlRegister.MmuEnabled = TRUE; 00269 ControlRegister.ICacheEnabled = TRUE; 00270 ControlRegister.DCacheEnabled = TRUE; 00271 ControlRegister.ForceAp = TRUE; 00272 ControlRegister.ExtendedPageTables = TRUE; 00273 KeArmControlRegisterSet(ControlRegister); 00274 } Generated on Sat May 26 2012 04:17:51 for ReactOS by
1.7.6.1
|