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