diff --git a/reactos/boot/freeldr/freeldr/arch/arm/boot.s b/reactos/boot/freeldr/freeldr/arch/arm/boot.s
index 2683274ef96..87f44853405 100644
--- a/reactos/boot/freeldr/freeldr/arch/arm/boot.s
+++ b/reactos/boot/freeldr/freeldr/arch/arm/boot.s
@@ -23,6 +23,7 @@
/* GLOBALS ********************************************************************/
.global _start
+.global ArmTranslationTable
.section startup
/* BOOT CODE ******************************************************************/
@@ -42,11 +43,12 @@ _start:
msr cpsr, r1
//
- // Turn off caches
+ // Turn off caches and the MMU
//
mrc p15, 0, r1, c1, c0, 0
bic r1, r1, #C1_DCACHE_CONTROL
bic r1, r1, #C1_ICACHE_CONTROL
+ bic r1, r1, #C1_MMU_CONTROL
mcr p15, 0, r1, c1, c0, 0
//
@@ -65,6 +67,8 @@ _start:
// r0 contains the ARM_BOARD_CONFIGURATION_DATA structure
//
bx lr
+
+/* BOOT STACK *****************************************************************/
L_BootStackEnd:
.long BootStackEnd
@@ -77,3 +81,9 @@ BootStack:
.space 0x4000
BootStackEnd:
.long 0
+
+/* INITIAL PAGE TABLE *********************************************************/
+
+.section pagedata
+ArmTranslationTable:
+ .space 0x4000
diff --git a/reactos/boot/freeldr/freeldr/arch/arm/stubs.c b/reactos/boot/freeldr/freeldr/arch/arm/stubs.c
index 42ced45b823..0517f96d46f 100644
--- a/reactos/boot/freeldr/freeldr/arch/arm/stubs.c
+++ b/reactos/boot/freeldr/freeldr/arch/arm/stubs.c
@@ -12,7 +12,185 @@
/* GLOBALS ********************************************************************/
+typedef union _ARM_PTE
+{
+ union
+ {
+ struct
+ {
+ ULONG Type:2;
+ ULONG Unused:30;
+ } Fault;
+ struct
+ {
+ ULONG Type:2;
+ ULONG Reserved:3;
+ ULONG Domain:4;
+ ULONG Ignored:1;
+ ULONG BaseAddress:22;
+ } Coarse;
+ struct
+ {
+ ULONG Type:2;
+ ULONG Buffered:1;
+ ULONG Cached:1;
+ ULONG Reserved:1;
+ ULONG Domain:4;
+ ULONG Ignored:1;
+ ULONG Access:2;
+ ULONG Ignored1:8;
+ ULONG BaseAddress:12;
+ } Section;
+ struct
+ {
+ ULONG Type:2;
+ ULONG Reserved:3;
+ ULONG Domain:4;
+ ULONG Ignored:3;
+ ULONG BaseAddress:20;
+ } Fine;
+ } L1;
+ union
+ {
+ struct
+ {
+ ULONG Type:2;
+ ULONG Unused:30;
+ } Fault;
+ struct
+ {
+ ULONG Type:2;
+ ULONG Buffered:1;
+ ULONG Cached:1;
+ ULONG Access0:2;
+ ULONG Access1:2;
+ ULONG Access2:2;
+ ULONG Access3:2;
+ ULONG Ignored:4;
+ ULONG BaseAddress:16;
+ } Large;
+ struct
+ {
+ ULONG Type:2;
+ ULONG Buffered:1;
+ ULONG Cached:1;
+ ULONG Access0:2;
+ ULONG Access1:2;
+ ULONG Access2:2;
+ ULONG Access3:2;
+ ULONG BaseAddress:20;
+ } Small;
+ struct
+ {
+ ULONG Type:2;
+ ULONG Buffered:1;
+ ULONG Cached:1;
+ ULONG Access0:2;
+ ULONG Ignored:4;
+ ULONG BaseAddress:22;
+ } Tiny;
+ } L2;
+ ULONG AsUlong;
+} ARM_PTE, *PARM_PTE;
+
+typedef struct _ARM_TRANSLATION_TABLE
+{
+ ARM_PTE Pte[4096];
+} ARM_TRANSLATION_TABLE, *PARM_TRANSLATION_TABLE;
+
+typedef union _ARM_TTB_REGISTER
+{
+ struct
+ {
+ ULONG Reserved:14;
+ ULONG BaseAddress:18;
+ };
+ ULONG AsUlong;
+} ARM_TTB_REGISTER;
+
+typedef enum _ARM_L1_PTE_TYPE
+{
+ FaultPte,
+ CoarsePte,
+ SectionPte,
+ FinePte
+} ARM_L1_PTE_TYPE;
+
+typedef enum _ARM_PTE_ACCESS
+{
+ FaultAccess,
+ SupervisorAccess,
+ SharedAccess,
+ UserAccess
+} ARM_PTE_ACCESS;
+
+typedef enum _ARM_DOMAIN
+{
+ FaultDomain,
+ ClientDomain,
+ InvalidDomain,
+ ManagerDomain
+} ARM_DOMAIN;
+
+typedef union _ARM_DOMAIN_REGISTER
+{
+ struct
+ {
+ ULONG Domain0:2;
+ ULONG Domain1:2;
+ ULONG Domain2:2;
+ ULONG Domain3:2;
+ ULONG Domain4:2;
+ ULONG Domain5:2;
+ ULONG Domain6:2;
+ ULONG Domain7:2;
+ ULONG Domain8:2;
+ ULONG Domain9:2;
+ ULONG Domain10:2;
+ ULONG Domain11:2;
+ ULONG Domain12:2;
+ ULONG Domain13:2;
+ ULONG Domain14:2;
+ ULONG Domain15:2;
+ };
+ ULONG AsUlong;
+} ARM_DOMAIN_REGISTER;
+
+typedef union _ARM_CONTROL_REGISTER
+{
+ struct
+ {
+ ULONG MmuEnabled:1;
+ ULONG AlignmentFaultsEnabled:1;
+ ULONG DCacheEnabled:1;
+ ULONG Sbo:3;
+ ULONG BigEndianEnabled:1;
+ ULONG System:1;
+ ULONG Rom:1;
+ ULONG Sbz:2;
+ ULONG ICacheEnabled:1;
+ ULONG HighVectors:1;
+ ULONG RoundRobinReplacementEnabled:1;
+ ULONG Armv4Compat:1;
+ ULONG Sbo1:1;
+ ULONG Sbz1:1;
+ ULONG Sbo2:1;
+ ULONG Reserved:14;
+ };
+ ULONG AsUlong;
+} ARM_CONTROL_REGISTER, *PARM_CONTROL_REGISTER;
+
+typedef enum _ARM_DOMAINS
+{
+ Domain0
+} ARM_DOMAINS;
+
+#define TTB_SHIFT 20
+
ULONG PageDirectoryStart, PageDirectoryEnd;
+LOADER_PARAMETER_BLOCK ArmLoaderBlock;
+LOADER_PARAMETER_EXTENSION ArmExtension;
+extern ARM_TRANSLATION_TABLE ArmTranslationTable;
/* FUNCTIONS ******************************************************************/
@@ -41,10 +219,183 @@ ArmDiskGetCacheableBlockCount(IN ULONG DriveNumber)
return FALSE;
}
+ARM_CONTROL_REGISTER
+FORCEINLINE
+ArmControlRegisterGet(VOID)
+{
+ ARM_CONTROL_REGISTER Value;
+ __asm__ __volatile__ ("mrc p15, 0, %0, c1, c0, 0" : "=r"(Value.AsUlong) : : "cc");
+ return Value;
+}
+
+VOID
+FORCEINLINE
+ArmControlRegisterSet(IN ARM_CONTROL_REGISTER ControlRegister)
+{
+ __asm__ __volatile__ ("mcr p15, 0, %0, c1, c0, 0; b ." : : "r"(ControlRegister.AsUlong) : "cc");
+}
+
+VOID
+FORCEINLINE
+ArmMmuTtbSet(IN ARM_TTB_REGISTER Ttb)
+{
+ __asm__ __volatile__ ("mcr p15, 0, %0, c2, c0, 0" : : "r"(Ttb.AsUlong) : "cc");
+}
+
+VOID
+FORCEINLINE
+ArmMmuDomainRegisterSet(IN ARM_DOMAIN_REGISTER DomainRegister)
+{
+ __asm__ __volatile__ ("mcr p15, 0, %0, c3, c0, 0" : : "r"(DomainRegister.AsUlong) : "cc");
+}
+
+VOID
+ArmSetupPageDirectory(VOID)
+{
+ ARM_TTB_REGISTER TtbRegister;
+ ARM_DOMAIN_REGISTER DomainRegister;
+ ARM_PTE Pte;
+ ULONG i;
+ PARM_TRANSLATION_TABLE TranslationTable;
+
+ //
+ // Allocate translation table buffer.
+ // During bootstrap, this will be a simple L1 (Master) Page Table with
+ // Section entries for KSEG0 and the first MB of RAM.
+ //
+ TranslationTable = &ArmTranslationTable;
+ if (!TranslationTable) return;
+
+ //
+ // Set it as the TTB
+ //
+ TtbRegister.AsUlong = (ULONG)TranslationTable;
+ ASSERT(TtbRegister.Reserved == 0);
+ TuiPrintf("CP15 C2: %x\n", TtbRegister);
+ ArmMmuTtbSet(TtbRegister);
+
+ //
+ // Use Domain 0, enforce AP bits (client)
+ //
+ DomainRegister.AsUlong = 0;
+ DomainRegister.Domain0 = ClientDomain;
+ TuiPrintf("CP15 C3: %x\n", DomainRegister);
+ ArmMmuDomainRegisterSet(DomainRegister);
+
+ //
+ // Set Fault PTEs everywhere
+ //
+ RtlZeroMemory(TranslationTable, 4096 * sizeof(ARM_PTE));
+
+ //
+ // Build the template PTE
+ //
+ Pte.L1.Section.Type = SectionPte;
+ Pte.L1.Section.Buffered = FALSE;
+ Pte.L1.Section.Cached = FALSE;
+ Pte.L1.Section.Reserved = 1; // ARM926EJ-S manual recommends setting to 1
+ Pte.L1.Section.Domain = Domain0;
+ Pte.L1.Section.Access = SupervisorAccess;
+ Pte.L1.Section.BaseAddress = KSEG0_BASE >> TTB_SHIFT;
+ Pte.L1.Section.Ignored = Pte.L1.Section.Ignored1 = 0;
+ TuiPrintf("Template PTE: %x\n", Pte.AsUlong);
+ TuiPrintf("Base: %x %x\n", KSEG0_BASE, Pte.L1.Section.BaseAddress);
+
+ //
+ // Map KSEG0 (0x80000000 - 0xA0000000)
+ //
+ TuiPrintf("First PTE Index: %x\n", KSEG0_BASE >> TTB_SHIFT);
+ TuiPrintf("Last PTE Index: %x\n", ((KSEG0_BASE + 0x20000000) >> TTB_SHIFT));
+ for (i = (KSEG0_BASE >> TTB_SHIFT); i < ((KSEG0_BASE + 0x20000000) >> TTB_SHIFT); i++)
+ {
+ //
+ // Update the PTE base address (next MB)
+ //
+ Pte.L1.Section.BaseAddress++;
+ TranslationTable->Pte[i] = Pte;
+ }
+
+ //
+ // Identity map the first MB of memory
+ //
+ TuiPrintf("Last KSEG0 PTE: %x %x\n", i, Pte.AsUlong);
+ Pte.L1.Section.BaseAddress = 0;
+ TranslationTable->Pte[0] = Pte;
+}
+
+VOID
+ArmSetupPagingAndJump(IN ULONG Magic)
+{
+ ARM_CONTROL_REGISTER ControlRegister;
+
+ //
+ // This is it! Once we enable the MMU we're in a totally different universe.
+ // Cross our fingers: We mapped the bottom 1MB of memory, so FreeLDR and
+ // boot-data is still there. We also mapped the kernel, and made our
+ // allocations | KSEG0_BASE. If any of this isn't true, we're dead.
+ //
+ TuiPrintf("Crossing the Rubicon!\n");
+
+ //
+ // Enable MMU, DCache and ICache
+ //
+ ControlRegister = ArmControlRegisterGet();
+ TuiPrintf("CP15 C1: %x\n", ControlRegister);
+ ControlRegister.MmuEnabled = TRUE;
+ ControlRegister.ICacheEnabled = TRUE;
+ ControlRegister.DCacheEnabled = TRUE;
+ TuiPrintf("CP15 C1: %x\n", ControlRegister);
+ ArmControlRegisterSet(ControlRegister);
+
+ //
+ // Are we still alive?
+ //
+ while (TRUE);
+}
+
VOID
ArmPrepareForReactOS(IN BOOLEAN Setup)
-{
- while (TRUE);
+{
+ //
+ // Initialize the loader block
+ //
+ InitializeListHead(&ArmLoaderBlock.BootDriverListHead);
+ InitializeListHead(&ArmLoaderBlock.LoadOrderListHead);
+ InitializeListHead(&ArmLoaderBlock.MemoryDescriptorListHead);
+
+ //
+ // Setup the extension and setup block
+ //
+ ArmLoaderBlock.Extension = &ArmExtension;
+ ArmLoaderBlock.SetupLdrBlock = NULL;
+
+ //
+ // TODO: Setup memory descriptors
+ //
+
+ //
+ // TODO: Setup registry data
+ //
+
+ //
+ // TODO: Setup ARC Hardware tree data
+ //
+
+ //
+ // TODO: Setup NLS data
+ //
+
+ //
+ // TODO: Setup boot-driver data
+ //
+
+ //
+ // TODO: Setup extension parameters
+ //
+
+ //
+ // TODO: Setup ARM-specific block
+ //
}
PCONFIGURATION_COMPONENT_DATA
@@ -167,5 +518,21 @@ MachInit(IN PCCH CommandLine)
VOID
FrLdrStartup(IN ULONG Magic)
{
- while (TRUE);
+ //
+ // Disable interrupts (aleady done)
+ //
+
+ //
+ // Set proper CPSR (already done)
+ //
+
+ //
+ // Initialize the page directory
+ //
+ ArmSetupPageDirectory();
+
+ //
+ // Initialize paging and load NTOSKRNL
+ //
+ ArmSetupPagingAndJump(Magic);
}
diff --git a/reactos/boot/freeldr/freeldr/freeldr.rbuild b/reactos/boot/freeldr/freeldr/freeldr.rbuild
index 6cd9a656394..303c2efa21c 100644
--- a/reactos/boot/freeldr/freeldr/freeldr.rbuild
+++ b/reactos/boot/freeldr/freeldr/freeldr.rbuild
@@ -31,6 +31,7 @@
libcntpr
-lgcc
-static
+ -Wl,--section-start,pagedata=0x50000