--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+ \r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "CpuDxe.h" \r
+\r
+//FIXME: Will not compile on non-ARMv7 builds\r
+#include <Chipset/ArmV7.h>\r
+\r
+VOID\r
+ExceptionHandlersStart (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+ExceptionHandlersEnd (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+CommonExceptionEntry (\r
+ VOID\r
+ );\r
+\r
+VOID\r
+AsmCommonExceptionEntry (\r
+ VOID\r
+ );\r
+\r
+\r
+EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_ARM_EXCEPTION + 1];\r
+EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_ARM_EXCEPTION + 1];\r
+\r
+\r
+\r
+/**\r
+ This function registers and enables the handler specified by InterruptHandler for a processor \r
+ interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the \r
+ handler for the processor interrupt or exception type specified by InterruptType is uninstalled. \r
+ The installed handler is called once for each processor interrupt or exception.\r
+\r
+ @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts\r
+ are enabled and FALSE if interrupts are disabled.\r
+ @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called\r
+ when a processor interrupt occurs. If this parameter is NULL, then the handler\r
+ will be uninstalled.\r
+\r
+ @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.\r
+ @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was\r
+ previously installed.\r
+ @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not\r
+ previously installed.\r
+ @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterInterruptHandler (\r
+ IN EFI_EXCEPTION_TYPE InterruptType,\r
+ IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
+ )\r
+{\r
+ if (InterruptType > MAX_ARM_EXCEPTION) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ gExceptionHandlers[InterruptType] = InterruptHandler;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+\r
+VOID\r
+EFIAPI\r
+CommonCExceptionHandler (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
+ )\r
+{\r
+ if (ExceptionType <= MAX_ARM_EXCEPTION) {\r
+ if (gExceptionHandlers[ExceptionType]) {\r
+ gExceptionHandlers[ExceptionType] (ExceptionType, SystemContext);\r
+ return;\r
+ }\r
+ } else {\r
+ DEBUG ((EFI_D_ERROR, "Unknown exception type %d from %08x\n", ExceptionType, SystemContext.SystemContextArm->PC));\r
+ ASSERT (FALSE);\r
+ }\r
+ \r
+ if (ExceptionType == EXCEPT_ARM_SOFTWARE_INTERRUPT) {\r
+ //\r
+ // ARM JTAG debuggers some times use this vector, so it is not an error to get one\r
+ //\r
+ return;\r
+ }\r
+\r
+ DefaultExceptionHandler (ExceptionType, SystemContext);\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+InitializeExceptions (\r
+ IN EFI_CPU_ARCH_PROTOCOL *Cpu\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Offset;\r
+ UINTN Length;\r
+ UINTN Index;\r
+ BOOLEAN IrqEnabled;\r
+ BOOLEAN FiqEnabled;\r
+ EFI_PHYSICAL_ADDRESS Base;\r
+ UINT32 *VectorBase;\r
+\r
+ Status = EFI_SUCCESS;\r
+ ZeroMem (gExceptionHandlers,sizeof(*gExceptionHandlers));\r
+\r
+ //\r
+ // Disable interrupts\r
+ //\r
+ Cpu->GetInterruptState (Cpu, &IrqEnabled);\r
+ Cpu->DisableInterrupt (Cpu);\r
+\r
+ //\r
+ // EFI does not use the FIQ, but a debugger might so we must disable \r
+ // as we take over the exception vectors. \r
+ //\r
+ FiqEnabled = ArmGetFiqState ();\r
+ ArmDisableFiq ();\r
+\r
+ if (FeaturePcdGet(PcdRelocateVectorTable) == TRUE) {\r
+ //\r
+ // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.\r
+ //\r
+ Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;\r
+\r
+ // Check if the exception vector is in the low address\r
+ if (PcdGet32 (PcdCpuVectorBaseAddress) == 0x0) {\r
+ // Set SCTLR.V to 0 to enable VBAR to be used\r
+ ArmSetLowVectors ();\r
+ } else {\r
+ ArmSetHighVectors ();\r
+ }\r
+\r
+ //\r
+ // Reserve space for the exception handlers\r
+ //\r
+ Base = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdCpuVectorBaseAddress);\r
+ VectorBase = (UINT32 *)(UINTN)Base;\r
+ Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode, EFI_SIZE_TO_PAGES (Length), &Base);\r
+ // If the request was for memory that's not in the memory map (which is often the case for 0x00000000\r
+ // on embedded systems, for example, we don't want to hang up. So we'll check here for a status of\r
+ // EFI_NOT_FOUND, and continue in that case.\r
+ if (EFI_ERROR(Status) && (Status != EFI_NOT_FOUND)) {\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ if (FeaturePcdGet(PcdDebuggerExceptionSupport) == TRUE) {\r
+ // Save existing vector table, in case debugger is already hooked in\r
+ CopyMem ((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof (gDebuggerExceptionHandlers));\r
+ }\r
+\r
+ // Copy our assembly code into the page that contains the exception vectors.\r
+ CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);\r
+\r
+ //\r
+ // Patch in the common Assembly exception handler\r
+ //\r
+ Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;\r
+ *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;\r
+\r
+ //\r
+ // Initialize the C entry points for interrupts\r
+ //\r
+ for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {\r
+ if (!FeaturePcdGet(PcdDebuggerExceptionSupport) ||\r
+ (gDebuggerExceptionHandlers[Index] == 0) || (gDebuggerExceptionHandlers[Index] == (VOID *)(UINTN)0xEAFFFFFE)) {\r
+ // Exception handler contains branch to vector location (jmp $) so no handler\r
+ // NOTE: This code assumes vectors are ARM and not Thumb code\r
+ Status = RegisterInterruptHandler (Index, NULL);\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ // If the debugger has already hooked put its vector back\r
+ VectorBase[Index] = (UINT32)(UINTN)gDebuggerExceptionHandlers[Index];\r
+ }\r
+ }\r
+\r
+ // Flush Caches since we updated executable stuff\r
+ InvalidateInstructionCacheRange ((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length);\r
+\r
+ //Note: On ARM processor with the Security Extension, the Vector Table can be located anywhere in the memory.\r
+ // The Vector Base Address Register defines the location\r
+ ArmWriteVBar (PcdGet32(PcdCpuVectorBaseAddress));\r
+ } else {\r
+ // The Vector table must be 32-byte aligned\r
+ ASSERT(((UINT32)ExceptionHandlersStart & ((1 << 5)-1)) == 0);\r
+\r
+ // We do not copy the Exception Table at PcdGet32(PcdCpuVectorBaseAddress). We just set Vector Base Address to point into CpuDxe code.\r
+ ArmWriteVBar ((UINT32)ExceptionHandlersStart);\r
+ }\r
+\r
+ if (FiqEnabled) {\r
+ ArmEnableFiq ();\r
+ }\r
+\r
+ if (IrqEnabled) {\r
+ // \r
+ // Restore interrupt state\r
+ //\r
+ Status = Cpu->EnableInterrupt (Cpu);\r
+ }\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>\r
+Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>\r
+\r
+This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+\r
+--*/\r
+\r
+#include "CpuDxe.h"\r
+\r
+// First Level Descriptors\r
+typedef UINT32 ARM_FIRST_LEVEL_DESCRIPTOR;\r
+\r
+// Second Level Descriptors\r
+typedef UINT32 ARM_PAGE_TABLE_ENTRY;\r
+\r
+EFI_STATUS \r
+SectionToGcdAttributes (\r
+ IN UINT32 SectionAttributes,\r
+ OUT UINT64 *GcdAttributes\r
+ )\r
+{\r
+ *GcdAttributes = 0;\r
+\r
+ // determine cacheability attributes\r
+ switch(SectionAttributes & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) {\r
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED:\r
+ *GcdAttributes |= EFI_MEMORY_UC;\r
+ break;\r
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE:\r
+ *GcdAttributes |= EFI_MEMORY_UC;\r
+ break;\r
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:\r
+ *GcdAttributes |= EFI_MEMORY_WT;\r
+ break;\r
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC:\r
+ *GcdAttributes |= EFI_MEMORY_WB;\r
+ break;\r
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE:\r
+ *GcdAttributes |= EFI_MEMORY_WC;\r
+ break;\r
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC:\r
+ *GcdAttributes |= EFI_MEMORY_WB;\r
+ break;\r
+ case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE:\r
+ *GcdAttributes |= EFI_MEMORY_UC;\r
+ break;\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ // determine protection attributes\r
+ switch(SectionAttributes & TT_DESCRIPTOR_SECTION_AP_MASK) {\r
+ case TT_DESCRIPTOR_SECTION_AP_NO_NO: // no read, no write\r
+ //*GcdAttributes |= EFI_MEMORY_WP | EFI_MEMORY_RP;\r
+ break;\r
+\r
+ case TT_DESCRIPTOR_SECTION_AP_RW_NO:\r
+ case TT_DESCRIPTOR_SECTION_AP_RW_RW:\r
+ // normal read/write access, do not add additional attributes\r
+ break;\r
+\r
+ // read only cases map to write-protect\r
+ case TT_DESCRIPTOR_SECTION_AP_RO_NO:\r
+ case TT_DESCRIPTOR_SECTION_AP_RO_RO:\r
+ *GcdAttributes |= EFI_MEMORY_WP;\r
+ break;\r
+\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ // now process eXectue Never attribute\r
+ if ((SectionAttributes & TT_DESCRIPTOR_SECTION_XN_MASK) != 0 ) {\r
+ *GcdAttributes |= EFI_MEMORY_XP;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PageToGcdAttributes (\r
+ IN UINT32 PageAttributes,\r
+ OUT UINT64 *GcdAttributes\r
+ )\r
+{\r
+ *GcdAttributes = 0;\r
+\r
+ // determine cacheability attributes\r
+ switch(PageAttributes & TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK) {\r
+ case TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED:\r
+ *GcdAttributes |= EFI_MEMORY_UC;\r
+ break;\r
+ case TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE:\r
+ *GcdAttributes |= EFI_MEMORY_UC;\r
+ break;\r
+ case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:\r
+ *GcdAttributes |= EFI_MEMORY_WT;\r
+ break;\r
+ case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_NO_ALLOC:\r
+ *GcdAttributes |= EFI_MEMORY_WB;\r
+ break;\r
+ case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE:\r
+ *GcdAttributes |= EFI_MEMORY_WC;\r
+ break;\r
+ case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC:\r
+ *GcdAttributes |= EFI_MEMORY_WB;\r
+ break;\r
+ case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_SHAREABLE_DEVICE:\r
+ *GcdAttributes |= EFI_MEMORY_UC;\r
+ break;\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ // determine protection attributes\r
+ switch(PageAttributes & TT_DESCRIPTOR_PAGE_AP_MASK) {\r
+ case TT_DESCRIPTOR_PAGE_AP_NO_NO: // no read, no write\r
+ //*GcdAttributes |= EFI_MEMORY_WP | EFI_MEMORY_RP;\r
+ break;\r
+\r
+ case TT_DESCRIPTOR_PAGE_AP_RW_NO:\r
+ case TT_DESCRIPTOR_PAGE_AP_RW_RW:\r
+ // normal read/write access, do not add additional attributes\r
+ break;\r
+\r
+ // read only cases map to write-protect\r
+ case TT_DESCRIPTOR_PAGE_AP_RO_NO:\r
+ case TT_DESCRIPTOR_PAGE_AP_RO_RO:\r
+ *GcdAttributes |= EFI_MEMORY_WP;\r
+ break;\r
+\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ // now process eXectue Never attribute\r
+ if ((PageAttributes & TT_DESCRIPTOR_PAGE_XN_MASK) != 0 ) {\r
+ *GcdAttributes |= EFI_MEMORY_XP;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Searches memory descriptors covered by given memory range.\r
+\r
+ This function searches into the Gcd Memory Space for descriptors\r
+ (from StartIndex to EndIndex) that contains the memory range\r
+ specified by BaseAddress and Length.\r
+\r
+ @param MemorySpaceMap Gcd Memory Space Map as array.\r
+ @param NumberOfDescriptors Number of descriptors in map.\r
+ @param BaseAddress BaseAddress for the requested range.\r
+ @param Length Length for the requested range.\r
+ @param StartIndex Start index into the Gcd Memory Space Map.\r
+ @param EndIndex End index into the Gcd Memory Space Map.\r
+\r
+ @retval EFI_SUCCESS Search successfully.\r
+ @retval EFI_NOT_FOUND The requested descriptors does not exist.\r
+\r
+**/\r
+EFI_STATUS\r
+SearchGcdMemorySpaces (\r
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
+ IN UINTN NumberOfDescriptors,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ OUT UINTN *StartIndex,\r
+ OUT UINTN *EndIndex\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ *StartIndex = 0;\r
+ *EndIndex = 0;\r
+ for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
+ if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&\r
+ BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
+ *StartIndex = Index;\r
+ }\r
+ if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&\r
+ BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
+ *EndIndex = Index;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ Sets the attributes for a specified range in Gcd Memory Space Map.\r
+\r
+ This function sets the attributes for a specified range in\r
+ Gcd Memory Space Map.\r
+\r
+ @param MemorySpaceMap Gcd Memory Space Map as array\r
+ @param NumberOfDescriptors Number of descriptors in map\r
+ @param BaseAddress BaseAddress for the range\r
+ @param Length Length for the range\r
+ @param Attributes Attributes to set\r
+\r
+ @retval EFI_SUCCESS Memory attributes set successfully\r
+ @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space\r
+\r
+**/\r
+EFI_STATUS\r
+SetGcdMemorySpaceAttributes (\r
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
+ IN UINTN NumberOfDescriptors,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN StartIndex;\r
+ UINTN EndIndex;\r
+ EFI_PHYSICAL_ADDRESS RegionStart;\r
+ UINT64 RegionLength;\r
+\r
+ //\r
+ // Get all memory descriptors covered by the memory range\r
+ //\r
+ Status = SearchGcdMemorySpaces (\r
+ MemorySpaceMap,\r
+ NumberOfDescriptors,\r
+ BaseAddress,\r
+ Length,\r
+ &StartIndex,\r
+ &EndIndex\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Go through all related descriptors and set attributes accordingly\r
+ //\r
+ for (Index = StartIndex; Index <= EndIndex; Index++) {\r
+ if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
+ continue;\r
+ }\r
+ //\r
+ // Calculate the start and end address of the overlapping range\r
+ //\r
+ if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {\r
+ RegionStart = BaseAddress;\r
+ } else {\r
+ RegionStart = MemorySpaceMap[Index].BaseAddress;\r
+ }\r
+ if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
+ RegionLength = BaseAddress + Length - RegionStart;\r
+ } else {\r
+ RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;\r
+ }\r
+ //\r
+ // Set memory attributes according to MTRR attribute and the original attribute of descriptor\r
+ //\r
+ gDS->SetMemorySpaceAttributes (\r
+ RegionStart,\r
+ RegionLength,\r
+ (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)\r
+ );\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SyncCacheConfigPage (\r
+ IN UINT32 SectionIndex,\r
+ IN UINT32 FirstLevelDescriptor,\r
+ IN UINTN NumberOfDescriptors,\r
+ IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
+ IN OUT EFI_PHYSICAL_ADDRESS *NextRegionBase,\r
+ IN OUT UINT64 *NextRegionLength,\r
+ IN OUT UINT32 *NextSectionAttributes\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 i;\r
+ volatile ARM_PAGE_TABLE_ENTRY *SecondLevelTable;\r
+ UINT32 NextPageAttributes = 0;\r
+ UINT32 PageAttributes = 0;\r
+ UINT32 BaseAddress;\r
+ UINT64 GcdAttributes;\r
+\r
+ // Get the Base Address from FirstLevelDescriptor;\r
+ BaseAddress = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(SectionIndex << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
+\r
+ // Convert SectionAttributes into PageAttributes\r
+ NextPageAttributes =\r
+ TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY(*NextSectionAttributes,0) |\r
+ TT_DESCRIPTOR_CONVERT_TO_PAGE_AP(*NextSectionAttributes);\r
+\r
+ // obtain page table base\r
+ SecondLevelTable = (ARM_PAGE_TABLE_ENTRY *)(FirstLevelDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);\r
+\r
+ for (i=0; i < TRANSLATION_TABLE_PAGE_COUNT; i++) {\r
+ if ((SecondLevelTable[i] & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) {\r
+ // extract attributes (cacheability and permissions)\r
+ PageAttributes = SecondLevelTable[i] & (TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK | TT_DESCRIPTOR_PAGE_AP_MASK);\r
+\r
+ if (NextPageAttributes == 0) {\r
+ // start on a new region\r
+ *NextRegionLength = 0;\r
+ *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);\r
+ NextPageAttributes = PageAttributes;\r
+ } else if (PageAttributes != NextPageAttributes) {\r
+ // Convert Section Attributes into GCD Attributes\r
+ Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
+ SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes);\r
+\r
+ // start on a new region\r
+ *NextRegionLength = 0;\r
+ *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);\r
+ NextPageAttributes = PageAttributes;\r
+ }\r
+ } else if (NextPageAttributes != 0) {\r
+ // Convert Page Attributes into GCD Attributes\r
+ Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
+ SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes);\r
+\r
+ *NextRegionLength = 0;\r
+ *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);\r
+ NextPageAttributes = 0;\r
+ }\r
+ *NextRegionLength += TT_DESCRIPTOR_PAGE_SIZE;\r
+ }\r
+\r
+ // Convert back PageAttributes into SectionAttributes\r
+ *NextSectionAttributes =\r
+ TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY(NextPageAttributes,0) |\r
+ TT_DESCRIPTOR_CONVERT_TO_SECTION_AP(NextPageAttributes);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+SyncCacheConfig (\r
+ IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 i;\r
+ EFI_PHYSICAL_ADDRESS NextRegionBase;\r
+ UINT64 NextRegionLength;\r
+ UINT32 NextSectionAttributes = 0;\r
+ UINT32 SectionAttributes = 0;\r
+ UINT64 GcdAttributes;\r
+ volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r
+ UINTN NumberOfDescriptors;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
+\r
+\r
+ DEBUG ((EFI_D_PAGE, "SyncCacheConfig()\n"));\r
+\r
+ // This code assumes MMU is enabled and filed with section translations\r
+ ASSERT (ArmMmuEnabled ());\r
+\r
+ //\r
+ // Get the memory space map from GCD\r
+ //\r
+ MemorySpaceMap = NULL;\r
+ Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+\r
+ // The GCD implementation maintains its own copy of the state of memory space attributes. GCD needs\r
+ // to know what the initial memory space attributes are. The CPU Arch. Protocol does not provide a\r
+ // GetMemoryAttributes function for GCD to get this so we must resort to calling GCD (as if we were\r
+ // a client) to update its copy of the attributes. This is bad architecture and should be replaced\r
+ // with a way for GCD to query the CPU Arch. driver of the existing memory space attributes instead.\r
+\r
+ // obtain page table base\r
+ FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)(ArmGetTTBR0BaseAddress ());\r
+\r
+ // Get the first region\r
+ NextSectionAttributes = FirstLevelTable[0] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK);\r
+\r
+ // iterate through each 1MB descriptor\r
+ NextRegionBase = NextRegionLength = 0;\r
+ for (i=0; i < TRANSLATION_TABLE_SECTION_COUNT; i++) {\r
+ if ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) {\r
+ // extract attributes (cacheability and permissions)\r
+ SectionAttributes = FirstLevelTable[i] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK);\r
+\r
+ if (NextSectionAttributes == 0) {\r
+ // start on a new region\r
+ NextRegionLength = 0;\r
+ NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
+ NextSectionAttributes = SectionAttributes;\r
+ } else if (SectionAttributes != NextSectionAttributes) {\r
+ // Convert Section Attributes into GCD Attributes\r
+ Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
+ SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);\r
+\r
+ // start on a new region\r
+ NextRegionLength = 0;\r
+ NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
+ NextSectionAttributes = SectionAttributes;\r
+ }\r
+ NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;\r
+ } else if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(FirstLevelTable[i])) {\r
+ Status = SyncCacheConfigPage (\r
+ i,FirstLevelTable[i],\r
+ NumberOfDescriptors, MemorySpaceMap,\r
+ &NextRegionBase,&NextRegionLength,&NextSectionAttributes);\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ // We do not support yet 16MB sections\r
+ ASSERT ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) != TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION);\r
+\r
+ // start on a new region\r
+ if (NextSectionAttributes != 0) {\r
+ // Convert Section Attributes into GCD Attributes\r
+ Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
+ SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);\r
+\r
+ NextRegionLength = 0;\r
+ NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
+ NextSectionAttributes = 0;\r
+ }\r
+ NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;\r
+ }\r
+ } // section entry loop\r
+\r
+ if (NextSectionAttributes != 0) {\r
+ // Convert Section Attributes into GCD Attributes\r
+ Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
+ SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+UpdatePageEntries (\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes,\r
+ IN EFI_PHYSICAL_ADDRESS VirtualMask\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 EntryValue;\r
+ UINT32 EntryMask;\r
+ UINT32 FirstLevelIdx;\r
+ UINT32 Offset;\r
+ UINT32 NumPageEntries;\r
+ UINT32 Descriptor;\r
+ UINT32 p;\r
+ UINT32 PageTableIndex;\r
+ UINT32 PageTableEntry;\r
+ UINT32 CurrentPageTableEntry;\r
+ VOID *Mva;\r
+\r
+ volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r
+ volatile ARM_PAGE_TABLE_ENTRY *PageTable;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ // EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)\r
+ // EntryValue: values at bit positions specified by EntryMask\r
+ EntryMask = TT_DESCRIPTOR_PAGE_TYPE_MASK;\r
+ EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE;\r
+ // Although the PI spec is unclear on this the GCD guarantees that only\r
+ // one Attribute bit is set at a time, so we can safely use a switch statement\r
+ switch (Attributes) {\r
+ case EFI_MEMORY_UC:\r
+ // modify cacheability attributes\r
+ EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r
+ // map to strongly ordered\r
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0\r
+ break;\r
+\r
+ case EFI_MEMORY_WC:\r
+ // modify cacheability attributes\r
+ EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r
+ // map to normal non-cachable\r
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0\r
+ break;\r
+\r
+ case EFI_MEMORY_WT:\r
+ // modify cacheability attributes\r
+ EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r
+ // write through with no-allocate\r
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0\r
+ break;\r
+\r
+ case EFI_MEMORY_WB:\r
+ // modify cacheability attributes\r
+ EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r
+ // write back (with allocate)\r
+ EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1\r
+ break;\r
+\r
+ case EFI_MEMORY_WP:\r
+ case EFI_MEMORY_XP:\r
+ case EFI_MEMORY_UCE:\r
+ // cannot be implemented UEFI definition unclear for ARM\r
+ // Cause a page fault if these ranges are accessed.\r
+ EntryValue = TT_DESCRIPTOR_PAGE_TYPE_FAULT;\r
+ DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): setting page %lx with unsupported attribute %x will page fault on access\n", BaseAddress, Attributes));\r
+ break;\r
+\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ // Obtain page table base\r
+ FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r
+\r
+ // Calculate number of 4KB page table entries to change\r
+ NumPageEntries = Length / TT_DESCRIPTOR_PAGE_SIZE;\r
+ \r
+ // Iterate for the number of 4KB pages to change\r
+ Offset = 0;\r
+ for(p = 0; p < NumPageEntries; p++) {\r
+ // Calculate index into first level translation table for page table value\r
+ \r
+ FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress + Offset) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r
+ ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);\r
+\r
+ // Read the descriptor from the first level page table\r
+ Descriptor = FirstLevelTable[FirstLevelIdx];\r
+\r
+ // Does this descriptor need to be converted from section entry to 4K pages?\r
+ if (!TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(Descriptor)) {\r
+ Status = ConvertSectionToPages (FirstLevelIdx << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
+ if (EFI_ERROR(Status)) {\r
+ // Exit for loop\r
+ break; \r
+ } \r
+ \r
+ // Re-read descriptor\r
+ Descriptor = FirstLevelTable[FirstLevelIdx];\r
+ }\r
+\r
+ // Obtain page table base address\r
+ PageTable = (ARM_PAGE_TABLE_ENTRY *)TT_DESCRIPTOR_PAGE_BASE_ADDRESS(Descriptor);\r
+\r
+ // Calculate index into the page table\r
+ PageTableIndex = ((BaseAddress + Offset) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;\r
+ ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);\r
+\r
+ // Get the entry\r
+ CurrentPageTableEntry = PageTable[PageTableIndex];\r
+\r
+ // Mask off appropriate fields\r
+ PageTableEntry = CurrentPageTableEntry & ~EntryMask;\r
+\r
+ // Mask in new attributes and/or permissions\r
+ PageTableEntry |= EntryValue;\r
+\r
+ if (VirtualMask != 0) {\r
+ // Make this virtual address point at a physical page\r
+ PageTableEntry &= ~VirtualMask;\r
+ }\r
+ \r
+ if (CurrentPageTableEntry != PageTableEntry) {\r
+ Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SECTION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT));\r
+ if ((CurrentPageTableEntry & TT_DESCRIPTOR_PAGE_CACHEABLE_MASK) == TT_DESCRIPTOR_PAGE_CACHEABLE_MASK) {\r
+ // The current section mapping is cacheable so Clean/Invalidate the MVA of the page\r
+ // Note assumes switch(Attributes), not ARMv7 possibilities\r
+ WriteBackInvalidateDataCacheRange (Mva, TT_DESCRIPTOR_PAGE_SIZE);\r
+ }\r
+\r
+ // Only need to update if we are changing the entry \r
+ PageTable[PageTableIndex] = PageTableEntry; \r
+ ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], Mva);\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ Offset += TT_DESCRIPTOR_PAGE_SIZE;\r
+ \r
+ } // End first level translation table loop\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+UpdateSectionEntries (\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes,\r
+ IN EFI_PHYSICAL_ADDRESS VirtualMask\r
+ )\r
+{\r
+ EFI_STATUS Status = EFI_SUCCESS;\r
+ UINT32 EntryMask;\r
+ UINT32 EntryValue;\r
+ UINT32 FirstLevelIdx;\r
+ UINT32 NumSections;\r
+ UINT32 i;\r
+ UINT32 CurrentDescriptor;\r
+ UINT32 Descriptor;\r
+ VOID *Mva;\r
+ volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r
+\r
+ // EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)\r
+ // EntryValue: values at bit positions specified by EntryMask\r
+\r
+ // Make sure we handle a section range that is unmapped \r
+ EntryMask = TT_DESCRIPTOR_SECTION_TYPE_MASK;\r
+ EntryValue = TT_DESCRIPTOR_SECTION_TYPE_SECTION;\r
+\r
+ // Although the PI spec is unclear on this the GCD guarantees that only\r
+ // one Attribute bit is set at a time, so we can safely use a switch statement\r
+ switch(Attributes) {\r
+ case EFI_MEMORY_UC:\r
+ // modify cacheability attributes\r
+ EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r
+ // map to strongly ordered\r
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0\r
+ break;\r
+\r
+ case EFI_MEMORY_WC:\r
+ // modify cacheability attributes\r
+ EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r
+ // map to normal non-cachable\r
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0\r
+ break;\r
+\r
+ case EFI_MEMORY_WT:\r
+ // modify cacheability attributes\r
+ EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r
+ // write through with no-allocate\r
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0\r
+ break;\r
+\r
+ case EFI_MEMORY_WB:\r
+ // modify cacheability attributes\r
+ EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r
+ // write back (with allocate)\r
+ EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1\r
+ break;\r
+\r
+ case EFI_MEMORY_WP:\r
+ case EFI_MEMORY_XP:\r
+ case EFI_MEMORY_RP:\r
+ case EFI_MEMORY_UCE:\r
+ // cannot be implemented UEFI definition unclear for ARM\r
+ // Cause a page fault if these ranges are accessed.\r
+ EntryValue = TT_DESCRIPTOR_SECTION_TYPE_FAULT;\r
+ DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): setting section %lx with unsupported attribute %x will page fault on access\n", BaseAddress, Attributes));\r
+ break;\r
+\r
+\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ // obtain page table base\r
+ FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r
+\r
+ // calculate index into first level translation table for start of modification\r
+ FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r
+ ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);\r
+\r
+ // calculate number of 1MB first level entries this applies to\r
+ NumSections = Length / TT_DESCRIPTOR_SECTION_SIZE;\r
+ \r
+ // iterate through each descriptor\r
+ for(i=0; i<NumSections; i++) {\r
+ CurrentDescriptor = FirstLevelTable[FirstLevelIdx + i];\r
+\r
+ // has this descriptor already been coverted to pages?\r
+ if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(CurrentDescriptor)) {\r
+ // forward this 1MB range to page table function instead\r
+ Status = UpdatePageEntries ((FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT, TT_DESCRIPTOR_SECTION_SIZE, Attributes, VirtualMask);\r
+ } else {\r
+ // still a section entry\r
+ \r
+ // mask off appropriate fields\r
+ Descriptor = CurrentDescriptor & ~EntryMask;\r
+\r
+ // mask in new attributes and/or permissions\r
+ Descriptor |= EntryValue;\r
+ if (VirtualMask != 0) {\r
+ Descriptor &= ~VirtualMask;\r
+ }\r
+\r
+ if (CurrentDescriptor != Descriptor) {\r
+ Mva = (VOID *)(UINTN)(((UINTN)FirstLevelTable) << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
+ if ((CurrentDescriptor & TT_DESCRIPTOR_SECTION_CACHEABLE_MASK) == TT_DESCRIPTOR_SECTION_CACHEABLE_MASK) {\r
+ // The current section mapping is cacheable so Clean/Invalidate the MVA of the section\r
+ // Note assumes switch(Attributes), not ARMv7 possabilities\r
+ WriteBackInvalidateDataCacheRange (Mva, SIZE_1MB);\r
+ }\r
+\r
+ // Only need to update if we are changing the descriptor \r
+ FirstLevelTable[FirstLevelIdx + i] = Descriptor;\r
+ ArmUpdateTranslationTableEntry ((VOID *)&FirstLevelTable[FirstLevelIdx + i], Mva);\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS \r
+ConvertSectionToPages (\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS PageTableAddr;\r
+ UINT32 FirstLevelIdx;\r
+ UINT32 SectionDescriptor;\r
+ UINT32 PageTableDescriptor;\r
+ UINT32 PageDescriptor;\r
+ UINT32 Index;\r
+\r
+ volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r
+ volatile ARM_PAGE_TABLE_ENTRY *PageTable;\r
+\r
+ DEBUG ((EFI_D_PAGE, "Converting section at 0x%x to pages\n", (UINTN)BaseAddress));\r
+\r
+ // Obtain page table base\r
+ FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r
+\r
+ // Calculate index into first level translation table for start of modification\r
+ FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r
+ ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);\r
+\r
+ // Get section attributes and convert to page attributes\r
+ SectionDescriptor = FirstLevelTable[FirstLevelIdx];\r
+ PageDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE;\r
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY(SectionDescriptor,0);\r
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_AP(SectionDescriptor);\r
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_XN(SectionDescriptor,0);\r
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_NG(SectionDescriptor);\r
+ PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_S(SectionDescriptor);\r
+\r
+ // Allocate a page table for the 4KB entries (we use up a full page even though we only need 1KB)\r
+ Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, 1, &PageTableAddr);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ PageTable = (volatile ARM_PAGE_TABLE_ENTRY *)(UINTN)PageTableAddr;\r
+\r
+ // Write the page table entries out\r
+ for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) {\r
+ PageTable[Index] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseAddress + (Index << 12)) | PageDescriptor;\r
+ }\r
+\r
+ // Flush d-cache so descriptors make it back to uncached memory for subsequent table walks\r
+ WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)PageTableAddr, TT_DESCRIPTOR_PAGE_SIZE);\r
+\r
+ // Formulate page table entry, Domain=0, NS=0\r
+ PageTableDescriptor = (((UINTN)PageTableAddr) & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) | TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;\r
+\r
+ // Write the page table entry out, replacing section entry\r
+ FirstLevelTable[FirstLevelIdx] = PageTableDescriptor;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+SetMemoryAttributes (\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes,\r
+ IN EFI_PHYSICAL_ADDRESS VirtualMask\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ \r
+ if(((BaseAddress & 0xFFFFF) == 0) && ((Length & 0xFFFFF) == 0)) {\r
+ // Is the base and length a multiple of 1 MB?\r
+ DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): MMU section 0x%x length 0x%x to %lx\n", (UINTN)BaseAddress, (UINTN)Length, Attributes));\r
+ Status = UpdateSectionEntries (BaseAddress, Length, Attributes, VirtualMask);\r
+ } else {\r
+ // Base and/or length is not a multiple of 1 MB\r
+ DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): MMU page 0x%x length 0x%x to %lx\n", (UINTN)BaseAddress, (UINTN)Length, Attributes));\r
+ Status = UpdatePageEntries (BaseAddress, Length, Attributes, VirtualMask);\r
+ }\r
+\r
+ // Flush d-cache so descriptors make it back to uncached memory for subsequent table walks\r
+ // flush and invalidate pages\r
+ //TODO: Do we really need to invalidate the caches everytime we change the memory attributes ?\r
+ ArmCleanInvalidateDataCache ();\r
+\r
+ ArmInvalidateInstructionCache ();\r
+\r
+ // Invalidate all TLB entries so changes are synced\r
+ ArmInvalidateTlb ();\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function modifies the attributes for the memory region specified by BaseAddress and\r
+ Length from their current attributes to the attributes specified by Attributes.\r
+\r
+ @param This The EFI_CPU_ARCH_PROTOCOL instance.\r
+ @param BaseAddress The physical address that is the start address of a memory region.\r
+ @param Length The size in bytes of the memory region.\r
+ @param Attributes The bit mask of attributes to set for the memory region.\r
+\r
+ @retval EFI_SUCCESS The attributes were set for the memory region.\r
+ @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
+ BaseAddress and Length cannot be modified.\r
+ @retval EFI_INVALID_PARAMETER Length is zero.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
+ the memory resource range.\r
+ @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
+ resource range specified by BaseAddress and Length.\r
+ The bit mask of attributes is not support for the memory resource\r
+ range specified by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CpuSetMemoryAttributes (\r
+ IN EFI_CPU_ARCH_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(%lx, %lx, %lx)\n", BaseAddress, Length, Attributes));\r
+ if ( ((BaseAddress & ~TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK) != 0) || ((Length & ~TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK) != 0)){\r
+ // minimum granularity is SIZE_4KB (4KB on ARM)\r
+ DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(%lx, %lx, %lx): minimum ganularity is SIZE_4KB\n", BaseAddress, Length, Attributes));\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ \r
+ return SetMemoryAttributes (BaseAddress, Length, Attributes, 0);\r
+}\r
+\r
+\r
+\r
+//\r
+// Add a new protocol to support \r
+//\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuConvertPagesToUncachedVirtualAddress (\r
+ IN VIRTUAL_UNCACHED_PAGES_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS Address,\r
+ IN UINTN Length,\r
+ IN EFI_PHYSICAL_ADDRESS VirtualMask,\r
+ OUT UINT64 *Attributes OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
+ \r
+ \r
+ if (Attributes != NULL) {\r
+ Status = gDS->GetMemorySpaceDescriptor (Address, &GcdDescriptor);\r
+ if (!EFI_ERROR (Status)) {\r
+ *Attributes = GcdDescriptor.Attributes;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Make this address range page fault if accessed. If it is a DMA buffer than this would \r
+ // be the PCI address. Code should always use the CPU address, and we will or in VirtualMask\r
+ // to that address. \r
+ //\r
+ Status = SetMemoryAttributes (Address, Length, EFI_MEMORY_WP, 0);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_UC, VirtualMask);\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "ConvertPagesToUncachedVirtualAddress()\n Unmapped 0x%08lx Mapped 0x%08lx 0x%x bytes\n", Address, Address | VirtualMask, Length));\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+CpuReconvertPages (\r
+ IN VIRTUAL_UNCACHED_PAGES_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS Address,\r
+ IN UINTN Length,\r
+ IN EFI_PHYSICAL_ADDRESS VirtualMask,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((DEBUG_INFO | DEBUG_LOAD, "CpuReconvertPages(%lx, %x, %lx, %lx)\n", Address, Length, VirtualMask, Attributes));\r
+ \r
+ //\r
+ // Unmap the alaised Address\r
+ //\r
+ Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_WP, 0);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Restore atttributes\r
+ //\r
+ Status = SetMemoryAttributes (Address, Length, Attributes, 0);\r
+ }\r
+ \r
+ return Status;\r
+}\r
+\r
+\r
+VIRTUAL_UNCACHED_PAGES_PROTOCOL gVirtualUncachedPages = {\r
+ CpuConvertPagesToUncachedVirtualAddress,\r
+ CpuReconvertPages\r
+};\r
#\r
\r
[Sources.ARM]\r
- Mmu.c\r
- Exception.c\r
+ ArmV6/Mmu.c\r
+ ArmV6/Exception.c\r
ArmV6/ExceptionSupport.asm | RVCT\r
ArmV6/ExceptionSupport.S | GCC\r
\r
+++ /dev/null
-/** @file\r
-\r
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
- \r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "CpuDxe.h" \r
-\r
-//FIXME: Will not compile on non-ARMv7 builds\r
-#include <Chipset/ArmV7.h>\r
-\r
-VOID\r
-ExceptionHandlersStart (\r
- VOID\r
- );\r
-\r
-VOID\r
-ExceptionHandlersEnd (\r
- VOID\r
- );\r
-\r
-VOID\r
-CommonExceptionEntry (\r
- VOID\r
- );\r
-\r
-VOID\r
-AsmCommonExceptionEntry (\r
- VOID\r
- );\r
-\r
-\r
-EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_ARM_EXCEPTION + 1];\r
-EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_ARM_EXCEPTION + 1];\r
-\r
-\r
-\r
-/**\r
- This function registers and enables the handler specified by InterruptHandler for a processor \r
- interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the \r
- handler for the processor interrupt or exception type specified by InterruptType is uninstalled. \r
- The installed handler is called once for each processor interrupt or exception.\r
-\r
- @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts\r
- are enabled and FALSE if interrupts are disabled.\r
- @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called\r
- when a processor interrupt occurs. If this parameter is NULL, then the handler\r
- will be uninstalled.\r
-\r
- @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.\r
- @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was\r
- previously installed.\r
- @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not\r
- previously installed.\r
- @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.\r
-\r
-**/\r
-EFI_STATUS\r
-RegisterInterruptHandler (\r
- IN EFI_EXCEPTION_TYPE InterruptType,\r
- IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
- )\r
-{\r
- if (InterruptType > MAX_ARM_EXCEPTION) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- if ((InterruptHandler != NULL) && (gExceptionHandlers[InterruptType] != NULL)) {\r
- return EFI_ALREADY_STARTED;\r
- }\r
-\r
- gExceptionHandlers[InterruptType] = InterruptHandler;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-\r
-\r
-VOID\r
-EFIAPI\r
-CommonCExceptionHandler (\r
- IN EFI_EXCEPTION_TYPE ExceptionType,\r
- IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
- if (ExceptionType <= MAX_ARM_EXCEPTION) {\r
- if (gExceptionHandlers[ExceptionType]) {\r
- gExceptionHandlers[ExceptionType] (ExceptionType, SystemContext);\r
- return;\r
- }\r
- } else {\r
- DEBUG ((EFI_D_ERROR, "Unknown exception type %d from %08x\n", ExceptionType, SystemContext.SystemContextArm->PC));\r
- ASSERT (FALSE);\r
- }\r
- \r
- if (ExceptionType == EXCEPT_ARM_SOFTWARE_INTERRUPT) {\r
- //\r
- // ARM JTAG debuggers some times use this vector, so it is not an error to get one\r
- //\r
- return;\r
- }\r
-\r
- DefaultExceptionHandler (ExceptionType, SystemContext);\r
-}\r
-\r
-\r
-\r
-EFI_STATUS\r
-InitializeExceptions (\r
- IN EFI_CPU_ARCH_PROTOCOL *Cpu\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Offset;\r
- UINTN Length;\r
- UINTN Index;\r
- BOOLEAN IrqEnabled;\r
- BOOLEAN FiqEnabled;\r
- EFI_PHYSICAL_ADDRESS Base;\r
- UINT32 *VectorBase;\r
-\r
- Status = EFI_SUCCESS;\r
- ZeroMem (gExceptionHandlers,sizeof(*gExceptionHandlers));\r
-\r
- //\r
- // Disable interrupts\r
- //\r
- Cpu->GetInterruptState (Cpu, &IrqEnabled);\r
- Cpu->DisableInterrupt (Cpu);\r
-\r
- //\r
- // EFI does not use the FIQ, but a debugger might so we must disable \r
- // as we take over the exception vectors. \r
- //\r
- FiqEnabled = ArmGetFiqState ();\r
- ArmDisableFiq ();\r
-\r
- if (FeaturePcdGet(PcdRelocateVectorTable) == TRUE) {\r
- //\r
- // Copy an implementation of the ARM exception vectors to PcdCpuVectorBaseAddress.\r
- //\r
- Length = (UINTN)ExceptionHandlersEnd - (UINTN)ExceptionHandlersStart;\r
-\r
- // Check if the exception vector is in the low address\r
- if (PcdGet32 (PcdCpuVectorBaseAddress) == 0x0) {\r
- // Set SCTLR.V to 0 to enable VBAR to be used\r
- ArmSetLowVectors ();\r
- } else {\r
- ArmSetHighVectors ();\r
- }\r
-\r
- //\r
- // Reserve space for the exception handlers\r
- //\r
- Base = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdCpuVectorBaseAddress);\r
- VectorBase = (UINT32 *)(UINTN)Base;\r
- Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode, EFI_SIZE_TO_PAGES (Length), &Base);\r
- // If the request was for memory that's not in the memory map (which is often the case for 0x00000000\r
- // on embedded systems, for example, we don't want to hang up. So we'll check here for a status of\r
- // EFI_NOT_FOUND, and continue in that case.\r
- if (EFI_ERROR(Status) && (Status != EFI_NOT_FOUND)) {\r
- ASSERT_EFI_ERROR (Status);\r
- }\r
-\r
- if (FeaturePcdGet(PcdDebuggerExceptionSupport) == TRUE) {\r
- // Save existing vector table, in case debugger is already hooked in\r
- CopyMem ((VOID *)gDebuggerExceptionHandlers, (VOID *)VectorBase, sizeof (gDebuggerExceptionHandlers));\r
- }\r
-\r
- // Copy our assembly code into the page that contains the exception vectors.\r
- CopyMem ((VOID *)VectorBase, (VOID *)ExceptionHandlersStart, Length);\r
-\r
- //\r
- // Patch in the common Assembly exception handler\r
- //\r
- Offset = (UINTN)CommonExceptionEntry - (UINTN)ExceptionHandlersStart;\r
- *(UINTN *) ((UINT8 *)(UINTN)PcdGet32 (PcdCpuVectorBaseAddress) + Offset) = (UINTN)AsmCommonExceptionEntry;\r
-\r
- //\r
- // Initialize the C entry points for interrupts\r
- //\r
- for (Index = 0; Index <= MAX_ARM_EXCEPTION; Index++) {\r
- if (!FeaturePcdGet(PcdDebuggerExceptionSupport) ||\r
- (gDebuggerExceptionHandlers[Index] == 0) || (gDebuggerExceptionHandlers[Index] == (VOID *)(UINTN)0xEAFFFFFE)) {\r
- // Exception handler contains branch to vector location (jmp $) so no handler\r
- // NOTE: This code assumes vectors are ARM and not Thumb code\r
- Status = RegisterInterruptHandler (Index, NULL);\r
- ASSERT_EFI_ERROR (Status);\r
- } else {\r
- // If the debugger has already hooked put its vector back\r
- VectorBase[Index] = (UINT32)(UINTN)gDebuggerExceptionHandlers[Index];\r
- }\r
- }\r
-\r
- // Flush Caches since we updated executable stuff\r
- InvalidateInstructionCacheRange ((VOID *)PcdGet32(PcdCpuVectorBaseAddress), Length);\r
-\r
- //Note: On ARM processor with the Security Extension, the Vector Table can be located anywhere in the memory.\r
- // The Vector Base Address Register defines the location\r
- ArmWriteVBar (PcdGet32(PcdCpuVectorBaseAddress));\r
- } else {\r
- // The Vector table must be 32-byte aligned\r
- ASSERT(((UINT32)ExceptionHandlersStart & ((1 << 5)-1)) == 0);\r
-\r
- // We do not copy the Exception Table at PcdGet32(PcdCpuVectorBaseAddress). We just set Vector Base Address to point into CpuDxe code.\r
- ArmWriteVBar ((UINT32)ExceptionHandlersStart);\r
- }\r
-\r
- if (FiqEnabled) {\r
- ArmEnableFiq ();\r
- }\r
-\r
- if (IrqEnabled) {\r
- // \r
- // Restore interrupt state\r
- //\r
- Status = Cpu->EnableInterrupt (Cpu);\r
- }\r
-\r
- return Status;\r
-}\r
+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>\r
-Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>\r
-\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-\r
---*/\r
-\r
-#include "CpuDxe.h"\r
-\r
-// First Level Descriptors\r
-typedef UINT32 ARM_FIRST_LEVEL_DESCRIPTOR;\r
-\r
-// Second Level Descriptors\r
-typedef UINT32 ARM_PAGE_TABLE_ENTRY;\r
-\r
-EFI_STATUS \r
-SectionToGcdAttributes (\r
- IN UINT32 SectionAttributes,\r
- OUT UINT64 *GcdAttributes\r
- )\r
-{\r
- *GcdAttributes = 0;\r
-\r
- // determine cacheability attributes\r
- switch(SectionAttributes & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) {\r
- case TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED:\r
- *GcdAttributes |= EFI_MEMORY_UC;\r
- break;\r
- case TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE:\r
- *GcdAttributes |= EFI_MEMORY_UC;\r
- break;\r
- case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:\r
- *GcdAttributes |= EFI_MEMORY_WT;\r
- break;\r
- case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC:\r
- *GcdAttributes |= EFI_MEMORY_WB;\r
- break;\r
- case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE:\r
- *GcdAttributes |= EFI_MEMORY_WC;\r
- break;\r
- case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC:\r
- *GcdAttributes |= EFI_MEMORY_WB;\r
- break;\r
- case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE:\r
- *GcdAttributes |= EFI_MEMORY_UC;\r
- break;\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- // determine protection attributes\r
- switch(SectionAttributes & TT_DESCRIPTOR_SECTION_AP_MASK) {\r
- case TT_DESCRIPTOR_SECTION_AP_NO_NO: // no read, no write\r
- //*GcdAttributes |= EFI_MEMORY_WP | EFI_MEMORY_RP;\r
- break;\r
-\r
- case TT_DESCRIPTOR_SECTION_AP_RW_NO:\r
- case TT_DESCRIPTOR_SECTION_AP_RW_RW:\r
- // normal read/write access, do not add additional attributes\r
- break;\r
-\r
- // read only cases map to write-protect\r
- case TT_DESCRIPTOR_SECTION_AP_RO_NO:\r
- case TT_DESCRIPTOR_SECTION_AP_RO_RO:\r
- *GcdAttributes |= EFI_MEMORY_WP;\r
- break;\r
-\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- // now process eXectue Never attribute\r
- if ((SectionAttributes & TT_DESCRIPTOR_SECTION_XN_MASK) != 0 ) {\r
- *GcdAttributes |= EFI_MEMORY_XP;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-PageToGcdAttributes (\r
- IN UINT32 PageAttributes,\r
- OUT UINT64 *GcdAttributes\r
- )\r
-{\r
- *GcdAttributes = 0;\r
-\r
- // determine cacheability attributes\r
- switch(PageAttributes & TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK) {\r
- case TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED:\r
- *GcdAttributes |= EFI_MEMORY_UC;\r
- break;\r
- case TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE:\r
- *GcdAttributes |= EFI_MEMORY_UC;\r
- break;\r
- case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:\r
- *GcdAttributes |= EFI_MEMORY_WT;\r
- break;\r
- case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_NO_ALLOC:\r
- *GcdAttributes |= EFI_MEMORY_WB;\r
- break;\r
- case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE:\r
- *GcdAttributes |= EFI_MEMORY_WC;\r
- break;\r
- case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC:\r
- *GcdAttributes |= EFI_MEMORY_WB;\r
- break;\r
- case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_SHAREABLE_DEVICE:\r
- *GcdAttributes |= EFI_MEMORY_UC;\r
- break;\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- // determine protection attributes\r
- switch(PageAttributes & TT_DESCRIPTOR_PAGE_AP_MASK) {\r
- case TT_DESCRIPTOR_PAGE_AP_NO_NO: // no read, no write\r
- //*GcdAttributes |= EFI_MEMORY_WP | EFI_MEMORY_RP;\r
- break;\r
-\r
- case TT_DESCRIPTOR_PAGE_AP_RW_NO:\r
- case TT_DESCRIPTOR_PAGE_AP_RW_RW:\r
- // normal read/write access, do not add additional attributes\r
- break;\r
-\r
- // read only cases map to write-protect\r
- case TT_DESCRIPTOR_PAGE_AP_RO_NO:\r
- case TT_DESCRIPTOR_PAGE_AP_RO_RO:\r
- *GcdAttributes |= EFI_MEMORY_WP;\r
- break;\r
-\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- // now process eXectue Never attribute\r
- if ((PageAttributes & TT_DESCRIPTOR_PAGE_XN_MASK) != 0 ) {\r
- *GcdAttributes |= EFI_MEMORY_XP;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Searches memory descriptors covered by given memory range.\r
-\r
- This function searches into the Gcd Memory Space for descriptors\r
- (from StartIndex to EndIndex) that contains the memory range\r
- specified by BaseAddress and Length.\r
-\r
- @param MemorySpaceMap Gcd Memory Space Map as array.\r
- @param NumberOfDescriptors Number of descriptors in map.\r
- @param BaseAddress BaseAddress for the requested range.\r
- @param Length Length for the requested range.\r
- @param StartIndex Start index into the Gcd Memory Space Map.\r
- @param EndIndex End index into the Gcd Memory Space Map.\r
-\r
- @retval EFI_SUCCESS Search successfully.\r
- @retval EFI_NOT_FOUND The requested descriptors does not exist.\r
-\r
-**/\r
-EFI_STATUS\r
-SearchGcdMemorySpaces (\r
- IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
- IN UINTN NumberOfDescriptors,\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- OUT UINTN *StartIndex,\r
- OUT UINTN *EndIndex\r
- )\r
-{\r
- UINTN Index;\r
-\r
- *StartIndex = 0;\r
- *EndIndex = 0;\r
- for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
- if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&\r
- BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
- *StartIndex = Index;\r
- }\r
- if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&\r
- BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
- *EndIndex = Index;\r
- return EFI_SUCCESS;\r
- }\r
- }\r
- return EFI_NOT_FOUND;\r
-}\r
-\r
-\r
-/**\r
- Sets the attributes for a specified range in Gcd Memory Space Map.\r
-\r
- This function sets the attributes for a specified range in\r
- Gcd Memory Space Map.\r
-\r
- @param MemorySpaceMap Gcd Memory Space Map as array\r
- @param NumberOfDescriptors Number of descriptors in map\r
- @param BaseAddress BaseAddress for the range\r
- @param Length Length for the range\r
- @param Attributes Attributes to set\r
-\r
- @retval EFI_SUCCESS Memory attributes set successfully\r
- @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space\r
-\r
-**/\r
-EFI_STATUS\r
-SetGcdMemorySpaceAttributes (\r
- IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
- IN UINTN NumberOfDescriptors,\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- IN UINT64 Attributes\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN Index;\r
- UINTN StartIndex;\r
- UINTN EndIndex;\r
- EFI_PHYSICAL_ADDRESS RegionStart;\r
- UINT64 RegionLength;\r
-\r
- //\r
- // Get all memory descriptors covered by the memory range\r
- //\r
- Status = SearchGcdMemorySpaces (\r
- MemorySpaceMap,\r
- NumberOfDescriptors,\r
- BaseAddress,\r
- Length,\r
- &StartIndex,\r
- &EndIndex\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Go through all related descriptors and set attributes accordingly\r
- //\r
- for (Index = StartIndex; Index <= EndIndex; Index++) {\r
- if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r
- continue;\r
- }\r
- //\r
- // Calculate the start and end address of the overlapping range\r
- //\r
- if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {\r
- RegionStart = BaseAddress;\r
- } else {\r
- RegionStart = MemorySpaceMap[Index].BaseAddress;\r
- }\r
- if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {\r
- RegionLength = BaseAddress + Length - RegionStart;\r
- } else {\r
- RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;\r
- }\r
- //\r
- // Set memory attributes according to MTRR attribute and the original attribute of descriptor\r
- //\r
- gDS->SetMemorySpaceAttributes (\r
- RegionStart,\r
- RegionLength,\r
- (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)\r
- );\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-SyncCacheConfigPage (\r
- IN UINT32 SectionIndex,\r
- IN UINT32 FirstLevelDescriptor,\r
- IN UINTN NumberOfDescriptors,\r
- IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,\r
- IN OUT EFI_PHYSICAL_ADDRESS *NextRegionBase,\r
- IN OUT UINT64 *NextRegionLength,\r
- IN OUT UINT32 *NextSectionAttributes\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 i;\r
- volatile ARM_PAGE_TABLE_ENTRY *SecondLevelTable;\r
- UINT32 NextPageAttributes = 0;\r
- UINT32 PageAttributes = 0;\r
- UINT32 BaseAddress;\r
- UINT64 GcdAttributes;\r
-\r
- // Get the Base Address from FirstLevelDescriptor;\r
- BaseAddress = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(SectionIndex << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
-\r
- // Convert SectionAttributes into PageAttributes\r
- NextPageAttributes =\r
- TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY(*NextSectionAttributes,0) |\r
- TT_DESCRIPTOR_CONVERT_TO_PAGE_AP(*NextSectionAttributes);\r
-\r
- // obtain page table base\r
- SecondLevelTable = (ARM_PAGE_TABLE_ENTRY *)(FirstLevelDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);\r
-\r
- for (i=0; i < TRANSLATION_TABLE_PAGE_COUNT; i++) {\r
- if ((SecondLevelTable[i] & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) {\r
- // extract attributes (cacheability and permissions)\r
- PageAttributes = SecondLevelTable[i] & (TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK | TT_DESCRIPTOR_PAGE_AP_MASK);\r
-\r
- if (NextPageAttributes == 0) {\r
- // start on a new region\r
- *NextRegionLength = 0;\r
- *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);\r
- NextPageAttributes = PageAttributes;\r
- } else if (PageAttributes != NextPageAttributes) {\r
- // Convert Section Attributes into GCD Attributes\r
- Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
- SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes);\r
-\r
- // start on a new region\r
- *NextRegionLength = 0;\r
- *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);\r
- NextPageAttributes = PageAttributes;\r
- }\r
- } else if (NextPageAttributes != 0) {\r
- // Convert Page Attributes into GCD Attributes\r
- Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
- SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes);\r
-\r
- *NextRegionLength = 0;\r
- *NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);\r
- NextPageAttributes = 0;\r
- }\r
- *NextRegionLength += TT_DESCRIPTOR_PAGE_SIZE;\r
- }\r
-\r
- // Convert back PageAttributes into SectionAttributes\r
- *NextSectionAttributes =\r
- TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY(NextPageAttributes,0) |\r
- TT_DESCRIPTOR_CONVERT_TO_SECTION_AP(NextPageAttributes);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-SyncCacheConfig (\r
- IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 i;\r
- EFI_PHYSICAL_ADDRESS NextRegionBase;\r
- UINT64 NextRegionLength;\r
- UINT32 NextSectionAttributes = 0;\r
- UINT32 SectionAttributes = 0;\r
- UINT64 GcdAttributes;\r
- volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r
- UINTN NumberOfDescriptors;\r
- EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
-\r
-\r
- DEBUG ((EFI_D_PAGE, "SyncCacheConfig()\n"));\r
-\r
- // This code assumes MMU is enabled and filed with section translations\r
- ASSERT (ArmMmuEnabled ());\r
-\r
- //\r
- // Get the memory space map from GCD\r
- //\r
- MemorySpaceMap = NULL;\r
- Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
-\r
- // The GCD implementation maintains its own copy of the state of memory space attributes. GCD needs\r
- // to know what the initial memory space attributes are. The CPU Arch. Protocol does not provide a\r
- // GetMemoryAttributes function for GCD to get this so we must resort to calling GCD (as if we were\r
- // a client) to update its copy of the attributes. This is bad architecture and should be replaced\r
- // with a way for GCD to query the CPU Arch. driver of the existing memory space attributes instead.\r
-\r
- // obtain page table base\r
- FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)(ArmGetTTBR0BaseAddress ());\r
-\r
- // Get the first region\r
- NextSectionAttributes = FirstLevelTable[0] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK);\r
-\r
- // iterate through each 1MB descriptor\r
- NextRegionBase = NextRegionLength = 0;\r
- for (i=0; i < TRANSLATION_TABLE_SECTION_COUNT; i++) {\r
- if ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) {\r
- // extract attributes (cacheability and permissions)\r
- SectionAttributes = FirstLevelTable[i] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK);\r
-\r
- if (NextSectionAttributes == 0) {\r
- // start on a new region\r
- NextRegionLength = 0;\r
- NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
- NextSectionAttributes = SectionAttributes;\r
- } else if (SectionAttributes != NextSectionAttributes) {\r
- // Convert Section Attributes into GCD Attributes\r
- Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
- SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);\r
-\r
- // start on a new region\r
- NextRegionLength = 0;\r
- NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
- NextSectionAttributes = SectionAttributes;\r
- }\r
- NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;\r
- } else if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(FirstLevelTable[i])) {\r
- Status = SyncCacheConfigPage (\r
- i,FirstLevelTable[i],\r
- NumberOfDescriptors, MemorySpaceMap,\r
- &NextRegionBase,&NextRegionLength,&NextSectionAttributes);\r
- ASSERT_EFI_ERROR (Status);\r
- } else {\r
- // We do not support yet 16MB sections\r
- ASSERT ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) != TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION);\r
-\r
- // start on a new region\r
- if (NextSectionAttributes != 0) {\r
- // Convert Section Attributes into GCD Attributes\r
- Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
- SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);\r
-\r
- NextRegionLength = 0;\r
- NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
- NextSectionAttributes = 0;\r
- }\r
- NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;\r
- }\r
- } // section entry loop\r
-\r
- if (NextSectionAttributes != 0) {\r
- // Convert Section Attributes into GCD Attributes\r
- Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- // update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)\r
- SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-\r
-EFI_STATUS\r
-UpdatePageEntries (\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- IN UINT64 Attributes,\r
- IN EFI_PHYSICAL_ADDRESS VirtualMask\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 EntryValue;\r
- UINT32 EntryMask;\r
- UINT32 FirstLevelIdx;\r
- UINT32 Offset;\r
- UINT32 NumPageEntries;\r
- UINT32 Descriptor;\r
- UINT32 p;\r
- UINT32 PageTableIndex;\r
- UINT32 PageTableEntry;\r
- UINT32 CurrentPageTableEntry;\r
- VOID *Mva;\r
-\r
- volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r
- volatile ARM_PAGE_TABLE_ENTRY *PageTable;\r
-\r
- Status = EFI_SUCCESS;\r
-\r
- // EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)\r
- // EntryValue: values at bit positions specified by EntryMask\r
- EntryMask = TT_DESCRIPTOR_PAGE_TYPE_MASK;\r
- EntryValue = TT_DESCRIPTOR_PAGE_TYPE_PAGE;\r
- // Although the PI spec is unclear on this the GCD guarantees that only\r
- // one Attribute bit is set at a time, so we can safely use a switch statement\r
- switch (Attributes) {\r
- case EFI_MEMORY_UC:\r
- // modify cacheability attributes\r
- EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r
- // map to strongly ordered\r
- EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0\r
- break;\r
-\r
- case EFI_MEMORY_WC:\r
- // modify cacheability attributes\r
- EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r
- // map to normal non-cachable\r
- EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0\r
- break;\r
-\r
- case EFI_MEMORY_WT:\r
- // modify cacheability attributes\r
- EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r
- // write through with no-allocate\r
- EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0\r
- break;\r
-\r
- case EFI_MEMORY_WB:\r
- // modify cacheability attributes\r
- EntryMask |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK;\r
- // write back (with allocate)\r
- EntryValue |= TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1\r
- break;\r
-\r
- case EFI_MEMORY_WP:\r
- case EFI_MEMORY_XP:\r
- case EFI_MEMORY_UCE:\r
- // cannot be implemented UEFI definition unclear for ARM\r
- // Cause a page fault if these ranges are accessed.\r
- EntryValue = TT_DESCRIPTOR_PAGE_TYPE_FAULT;\r
- DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): setting page %lx with unsupported attribute %x will page fault on access\n", BaseAddress, Attributes));\r
- break;\r
-\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- // Obtain page table base\r
- FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r
-\r
- // Calculate number of 4KB page table entries to change\r
- NumPageEntries = Length / TT_DESCRIPTOR_PAGE_SIZE;\r
- \r
- // Iterate for the number of 4KB pages to change\r
- Offset = 0;\r
- for(p = 0; p < NumPageEntries; p++) {\r
- // Calculate index into first level translation table for page table value\r
- \r
- FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress + Offset) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r
- ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);\r
-\r
- // Read the descriptor from the first level page table\r
- Descriptor = FirstLevelTable[FirstLevelIdx];\r
-\r
- // Does this descriptor need to be converted from section entry to 4K pages?\r
- if (!TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(Descriptor)) {\r
- Status = ConvertSectionToPages (FirstLevelIdx << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
- if (EFI_ERROR(Status)) {\r
- // Exit for loop\r
- break; \r
- } \r
- \r
- // Re-read descriptor\r
- Descriptor = FirstLevelTable[FirstLevelIdx];\r
- }\r
-\r
- // Obtain page table base address\r
- PageTable = (ARM_PAGE_TABLE_ENTRY *)TT_DESCRIPTOR_PAGE_BASE_ADDRESS(Descriptor);\r
-\r
- // Calculate index into the page table\r
- PageTableIndex = ((BaseAddress + Offset) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;\r
- ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);\r
-\r
- // Get the entry\r
- CurrentPageTableEntry = PageTable[PageTableIndex];\r
-\r
- // Mask off appropriate fields\r
- PageTableEntry = CurrentPageTableEntry & ~EntryMask;\r
-\r
- // Mask in new attributes and/or permissions\r
- PageTableEntry |= EntryValue;\r
-\r
- if (VirtualMask != 0) {\r
- // Make this virtual address point at a physical page\r
- PageTableEntry &= ~VirtualMask;\r
- }\r
- \r
- if (CurrentPageTableEntry != PageTableEntry) {\r
- Mva = (VOID *)(UINTN)((((UINTN)FirstLevelIdx) << TT_DESCRIPTOR_SECTION_BASE_SHIFT) + (PageTableIndex << TT_DESCRIPTOR_PAGE_BASE_SHIFT));\r
- if ((CurrentPageTableEntry & TT_DESCRIPTOR_PAGE_CACHEABLE_MASK) == TT_DESCRIPTOR_PAGE_CACHEABLE_MASK) {\r
- // The current section mapping is cacheable so Clean/Invalidate the MVA of the page\r
- // Note assumes switch(Attributes), not ARMv7 possibilities\r
- WriteBackInvalidateDataCacheRange (Mva, TT_DESCRIPTOR_PAGE_SIZE);\r
- }\r
-\r
- // Only need to update if we are changing the entry \r
- PageTable[PageTableIndex] = PageTableEntry; \r
- ArmUpdateTranslationTableEntry ((VOID *)&PageTable[PageTableIndex], Mva);\r
- }\r
-\r
- Status = EFI_SUCCESS;\r
- Offset += TT_DESCRIPTOR_PAGE_SIZE;\r
- \r
- } // End first level translation table loop\r
-\r
- return Status;\r
-}\r
-\r
-\r
-\r
-EFI_STATUS\r
-UpdateSectionEntries (\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- IN UINT64 Attributes,\r
- IN EFI_PHYSICAL_ADDRESS VirtualMask\r
- )\r
-{\r
- EFI_STATUS Status = EFI_SUCCESS;\r
- UINT32 EntryMask;\r
- UINT32 EntryValue;\r
- UINT32 FirstLevelIdx;\r
- UINT32 NumSections;\r
- UINT32 i;\r
- UINT32 CurrentDescriptor;\r
- UINT32 Descriptor;\r
- VOID *Mva;\r
- volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r
-\r
- // EntryMask: bitmask of values to change (1 = change this value, 0 = leave alone)\r
- // EntryValue: values at bit positions specified by EntryMask\r
-\r
- // Make sure we handle a section range that is unmapped \r
- EntryMask = TT_DESCRIPTOR_SECTION_TYPE_MASK;\r
- EntryValue = TT_DESCRIPTOR_SECTION_TYPE_SECTION;\r
-\r
- // Although the PI spec is unclear on this the GCD guarantees that only\r
- // one Attribute bit is set at a time, so we can safely use a switch statement\r
- switch(Attributes) {\r
- case EFI_MEMORY_UC:\r
- // modify cacheability attributes\r
- EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r
- // map to strongly ordered\r
- EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0\r
- break;\r
-\r
- case EFI_MEMORY_WC:\r
- // modify cacheability attributes\r
- EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r
- // map to normal non-cachable\r
- EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0\r
- break;\r
-\r
- case EFI_MEMORY_WT:\r
- // modify cacheability attributes\r
- EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r
- // write through with no-allocate\r
- EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0\r
- break;\r
-\r
- case EFI_MEMORY_WB:\r
- // modify cacheability attributes\r
- EntryMask |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK;\r
- // write back (with allocate)\r
- EntryValue |= TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1\r
- break;\r
-\r
- case EFI_MEMORY_WP:\r
- case EFI_MEMORY_XP:\r
- case EFI_MEMORY_RP:\r
- case EFI_MEMORY_UCE:\r
- // cannot be implemented UEFI definition unclear for ARM\r
- // Cause a page fault if these ranges are accessed.\r
- EntryValue = TT_DESCRIPTOR_SECTION_TYPE_FAULT;\r
- DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): setting section %lx with unsupported attribute %x will page fault on access\n", BaseAddress, Attributes));\r
- break;\r
-\r
-\r
- default:\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- // obtain page table base\r
- FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r
-\r
- // calculate index into first level translation table for start of modification\r
- FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r
- ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);\r
-\r
- // calculate number of 1MB first level entries this applies to\r
- NumSections = Length / TT_DESCRIPTOR_SECTION_SIZE;\r
- \r
- // iterate through each descriptor\r
- for(i=0; i<NumSections; i++) {\r
- CurrentDescriptor = FirstLevelTable[FirstLevelIdx + i];\r
-\r
- // has this descriptor already been coverted to pages?\r
- if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(CurrentDescriptor)) {\r
- // forward this 1MB range to page table function instead\r
- Status = UpdatePageEntries ((FirstLevelIdx + i) << TT_DESCRIPTOR_SECTION_BASE_SHIFT, TT_DESCRIPTOR_SECTION_SIZE, Attributes, VirtualMask);\r
- } else {\r
- // still a section entry\r
- \r
- // mask off appropriate fields\r
- Descriptor = CurrentDescriptor & ~EntryMask;\r
-\r
- // mask in new attributes and/or permissions\r
- Descriptor |= EntryValue;\r
- if (VirtualMask != 0) {\r
- Descriptor &= ~VirtualMask;\r
- }\r
-\r
- if (CurrentDescriptor != Descriptor) {\r
- Mva = (VOID *)(UINTN)(((UINTN)FirstLevelTable) << TT_DESCRIPTOR_SECTION_BASE_SHIFT);\r
- if ((CurrentDescriptor & TT_DESCRIPTOR_SECTION_CACHEABLE_MASK) == TT_DESCRIPTOR_SECTION_CACHEABLE_MASK) {\r
- // The current section mapping is cacheable so Clean/Invalidate the MVA of the section\r
- // Note assumes switch(Attributes), not ARMv7 possabilities\r
- WriteBackInvalidateDataCacheRange (Mva, SIZE_1MB);\r
- }\r
-\r
- // Only need to update if we are changing the descriptor \r
- FirstLevelTable[FirstLevelIdx + i] = Descriptor;\r
- ArmUpdateTranslationTableEntry ((VOID *)&FirstLevelTable[FirstLevelIdx + i], Mva);\r
- }\r
-\r
- Status = EFI_SUCCESS;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS \r
-ConvertSectionToPages (\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PHYSICAL_ADDRESS PageTableAddr;\r
- UINT32 FirstLevelIdx;\r
- UINT32 SectionDescriptor;\r
- UINT32 PageTableDescriptor;\r
- UINT32 PageDescriptor;\r
- UINT32 Index;\r
-\r
- volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;\r
- volatile ARM_PAGE_TABLE_ENTRY *PageTable;\r
-\r
- DEBUG ((EFI_D_PAGE, "Converting section at 0x%x to pages\n", (UINTN)BaseAddress));\r
-\r
- // Obtain page table base\r
- FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();\r
-\r
- // Calculate index into first level translation table for start of modification\r
- FirstLevelIdx = TT_DESCRIPTOR_SECTION_BASE_ADDRESS(BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;\r
- ASSERT (FirstLevelIdx < TRANSLATION_TABLE_SECTION_COUNT);\r
-\r
- // Get section attributes and convert to page attributes\r
- SectionDescriptor = FirstLevelTable[FirstLevelIdx];\r
- PageDescriptor = TT_DESCRIPTOR_PAGE_TYPE_PAGE;\r
- PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY(SectionDescriptor,0);\r
- PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_AP(SectionDescriptor);\r
- PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_XN(SectionDescriptor,0);\r
- PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_NG(SectionDescriptor);\r
- PageDescriptor |= TT_DESCRIPTOR_CONVERT_TO_PAGE_S(SectionDescriptor);\r
-\r
- // Allocate a page table for the 4KB entries (we use up a full page even though we only need 1KB)\r
- Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, 1, &PageTableAddr);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- PageTable = (volatile ARM_PAGE_TABLE_ENTRY *)(UINTN)PageTableAddr;\r
-\r
- // Write the page table entries out\r
- for (Index = 0; Index < TRANSLATION_TABLE_PAGE_COUNT; Index++) {\r
- PageTable[Index] = TT_DESCRIPTOR_PAGE_BASE_ADDRESS(BaseAddress + (Index << 12)) | PageDescriptor;\r
- }\r
-\r
- // Flush d-cache so descriptors make it back to uncached memory for subsequent table walks\r
- WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)PageTableAddr, TT_DESCRIPTOR_PAGE_SIZE);\r
-\r
- // Formulate page table entry, Domain=0, NS=0\r
- PageTableDescriptor = (((UINTN)PageTableAddr) & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK) | TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE;\r
-\r
- // Write the page table entry out, replacing section entry\r
- FirstLevelTable[FirstLevelIdx] = PageTableDescriptor;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-\r
-EFI_STATUS\r
-SetMemoryAttributes (\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- IN UINT64 Attributes,\r
- IN EFI_PHYSICAL_ADDRESS VirtualMask\r
- )\r
-{\r
- EFI_STATUS Status;\r
- \r
- if(((BaseAddress & 0xFFFFF) == 0) && ((Length & 0xFFFFF) == 0)) {\r
- // Is the base and length a multiple of 1 MB?\r
- DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): MMU section 0x%x length 0x%x to %lx\n", (UINTN)BaseAddress, (UINTN)Length, Attributes));\r
- Status = UpdateSectionEntries (BaseAddress, Length, Attributes, VirtualMask);\r
- } else {\r
- // Base and/or length is not a multiple of 1 MB\r
- DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(): MMU page 0x%x length 0x%x to %lx\n", (UINTN)BaseAddress, (UINTN)Length, Attributes));\r
- Status = UpdatePageEntries (BaseAddress, Length, Attributes, VirtualMask);\r
- }\r
-\r
- // Flush d-cache so descriptors make it back to uncached memory for subsequent table walks\r
- // flush and invalidate pages\r
- //TODO: Do we really need to invalidate the caches everytime we change the memory attributes ?\r
- ArmCleanInvalidateDataCache ();\r
-\r
- ArmInvalidateInstructionCache ();\r
-\r
- // Invalidate all TLB entries so changes are synced\r
- ArmInvalidateTlb ();\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- This function modifies the attributes for the memory region specified by BaseAddress and\r
- Length from their current attributes to the attributes specified by Attributes.\r
-\r
- @param This The EFI_CPU_ARCH_PROTOCOL instance.\r
- @param BaseAddress The physical address that is the start address of a memory region.\r
- @param Length The size in bytes of the memory region.\r
- @param Attributes The bit mask of attributes to set for the memory region.\r
-\r
- @retval EFI_SUCCESS The attributes were set for the memory region.\r
- @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
- BaseAddress and Length cannot be modified.\r
- @retval EFI_INVALID_PARAMETER Length is zero.\r
- @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
- the memory resource range.\r
- @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
- resource range specified by BaseAddress and Length.\r
- The bit mask of attributes is not support for the memory resource\r
- range specified by BaseAddress and Length.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-CpuSetMemoryAttributes (\r
- IN EFI_CPU_ARCH_PROTOCOL *This,\r
- IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
- IN UINT64 Length,\r
- IN UINT64 Attributes\r
- )\r
-{\r
- DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(%lx, %lx, %lx)\n", BaseAddress, Length, Attributes));\r
- if ( ((BaseAddress & ~TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK) != 0) || ((Length & ~TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK) != 0)){\r
- // minimum granularity is SIZE_4KB (4KB on ARM)\r
- DEBUG ((EFI_D_PAGE, "SetMemoryAttributes(%lx, %lx, %lx): minimum ganularity is SIZE_4KB\n", BaseAddress, Length, Attributes));\r
- return EFI_UNSUPPORTED;\r
- }\r
- \r
- return SetMemoryAttributes (BaseAddress, Length, Attributes, 0);\r
-}\r
-\r
-\r
-\r
-//\r
-// Add a new protocol to support \r
-//\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-CpuConvertPagesToUncachedVirtualAddress (\r
- IN VIRTUAL_UNCACHED_PAGES_PROTOCOL *This,\r
- IN EFI_PHYSICAL_ADDRESS Address,\r
- IN UINTN Length,\r
- IN EFI_PHYSICAL_ADDRESS VirtualMask,\r
- OUT UINT64 *Attributes OPTIONAL\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
- \r
- \r
- if (Attributes != NULL) {\r
- Status = gDS->GetMemorySpaceDescriptor (Address, &GcdDescriptor);\r
- if (!EFI_ERROR (Status)) {\r
- *Attributes = GcdDescriptor.Attributes;\r
- }\r
- }\r
-\r
- //\r
- // Make this address range page fault if accessed. If it is a DMA buffer than this would \r
- // be the PCI address. Code should always use the CPU address, and we will or in VirtualMask\r
- // to that address. \r
- //\r
- Status = SetMemoryAttributes (Address, Length, EFI_MEMORY_WP, 0);\r
- if (!EFI_ERROR (Status)) {\r
- Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_UC, VirtualMask);\r
- }\r
-\r
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "ConvertPagesToUncachedVirtualAddress()\n Unmapped 0x%08lx Mapped 0x%08lx 0x%x bytes\n", Address, Address | VirtualMask, Length));\r
-\r
- return Status;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-CpuReconvertPages (\r
- IN VIRTUAL_UNCACHED_PAGES_PROTOCOL *This,\r
- IN EFI_PHYSICAL_ADDRESS Address,\r
- IN UINTN Length,\r
- IN EFI_PHYSICAL_ADDRESS VirtualMask,\r
- IN UINT64 Attributes\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- DEBUG ((DEBUG_INFO | DEBUG_LOAD, "CpuReconvertPages(%lx, %x, %lx, %lx)\n", Address, Length, VirtualMask, Attributes));\r
- \r
- //\r
- // Unmap the alaised Address\r
- //\r
- Status = SetMemoryAttributes (Address | VirtualMask, Length, EFI_MEMORY_WP, 0);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Restore atttributes\r
- //\r
- Status = SetMemoryAttributes (Address, Length, Attributes, 0);\r
- }\r
- \r
- return Status;\r
-}\r
-\r
-\r
-VIRTUAL_UNCACHED_PAGES_PROTOCOL gVirtualUncachedPages = {\r
- CpuConvertPagesToUncachedVirtualAddress,\r
- CpuReconvertPages\r
-};\r
LIBRARY_CLASS = ArmLib\r
\r
[Sources.common]\r
- ../Common/ArmLibSupport.S | GCC\r
- ../Common/ArmLibSupport.asm | RVCT\r
+ ../Common/Arm/ArmLibSupport.S | GCC\r
+ ../Common/Arm/ArmLibSupport.asm | RVCT\r
../Common/ArmLib.c\r
\r
Arm11Support.S | GCC\r
LIBRARY_CLASS = ArmLib\r
\r
[Sources.common]\r
- ../Common/ArmLibSupport.S | GCC\r
- ../Common/ArmLibSupport.asm | RVCT\r
+ ../Common/Arm/ArmLibSupport.S | GCC\r
+ ../Common/Arm/ArmLibSupport.asm | RVCT\r
../Common/ArmLib.c\r
\r
Arm11Support.S | GCC\r
LIBRARY_CLASS = ArmLib\r
\r
[Sources.common]\r
- ../Common/ArmLibSupport.S | GCC\r
- ../Common/ArmLibSupport.asm | RVCT\r
+ ../Common/Arm/ArmLibSupport.S | GCC\r
+ ../Common/Arm/ArmLibSupport.asm | RVCT\r
../Common/ArmLib.c\r
\r
Arm11Support.S | GCC\r
LIBRARY_CLASS = ArmLib\r
\r
[Sources.common]\r
- ../Common/ArmLibSupport.S | GCC\r
- ../Common/ArmLibSupport.asm | RVCT\r
+ ../Common/Arm/ArmLibSupport.S | GCC\r
+ ../Common/Arm/ArmLibSupport.asm | RVCT\r
../Common/ArmLib.c\r
\r
Arm9Support.S | GCC\r
LIBRARY_CLASS = ArmLib\r
\r
[Sources.common]\r
- ../Common/ArmLibSupport.S | GCC\r
- ../Common/ArmLibSupport.asm | RVCT\r
+ ../Common/Arm/ArmLibSupport.S | GCC\r
+ ../Common/Arm/ArmLibSupport.asm | RVCT\r
../Common/ArmLib.c\r
\r
Arm9Support.S | GCC\r
ArmLibSupportV7.S | GCC\r
ArmLibSupportV7.asm | RVCT\r
\r
- ../Common/ArmLibSupport.S | GCC\r
- ../Common/ArmLibSupport.asm | RVCT\r
+ ../Common/Arm/ArmLibSupport.S | GCC\r
+ ../Common/Arm/ArmLibSupport.asm | RVCT\r
../Common/ArmLib.c\r
\r
ArmV7Support.S | GCC\r
ArmLibSupportV7.S | GCC\r
ArmLibSupportV7.asm | RVCT\r
\r
- ../Common/ArmLibSupport.S | GCC\r
- ../Common/ArmLibSupport.asm | RVCT\r
+ ../Common/Arm/ArmLibSupport.S | GCC\r
+ ../Common/Arm/ArmLibSupport.asm | RVCT\r
../Common/ArmLib.c\r
\r
ArmV7Support.S | GCC\r
ArmLibSupportV7.S | GCC\r
ArmLibSupportV7.asm | RVCT\r
\r
- ../Common/ArmLibSupport.S | GCC\r
- ../Common/ArmLibSupport.asm | RVCT\r
+ ../Common/Arm/ArmLibSupport.S | GCC\r
+ ../Common/Arm/ArmLibSupport.asm | RVCT\r
../Common/ArmLib.c\r
\r
ArmV7Support.S | GCC\r
--- /dev/null
+#------------------------------------------------------------------------------ \r
+#\r
+# Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+# Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#------------------------------------------------------------------------------\r
+\r
+#include <AsmMacroIoLib.h>\r
+\r
+#ifdef ARM_CPU_ARMv6\r
+// No memory barriers for ARMv6\r
+#define isb\r
+#define dsb\r
+#endif\r
+\r
+.text\r
+.align 2\r
+GCC_ASM_EXPORT(Cp15IdCode)\r
+GCC_ASM_EXPORT(Cp15CacheInfo)\r
+GCC_ASM_EXPORT(ArmGetInterruptState)\r
+GCC_ASM_EXPORT(ArmGetFiqState)\r
+GCC_ASM_EXPORT(ArmGetTTBR0BaseAddress)\r
+GCC_ASM_EXPORT(ArmSetTTBR0)\r
+GCC_ASM_EXPORT(ArmSetDomainAccessControl)\r
+GCC_ASM_EXPORT(CPSRMaskInsert)\r
+GCC_ASM_EXPORT(CPSRRead)\r
+GCC_ASM_EXPORT(ArmReadCpacr)\r
+GCC_ASM_EXPORT(ArmWriteCpacr)\r
+GCC_ASM_EXPORT(ArmWriteAuxCr)\r
+GCC_ASM_EXPORT(ArmReadAuxCr)\r
+GCC_ASM_EXPORT(ArmInvalidateTlb)\r
+GCC_ASM_EXPORT(ArmUpdateTranslationTableEntry)\r
+GCC_ASM_EXPORT(ArmReadNsacr)\r
+GCC_ASM_EXPORT(ArmWriteNsacr)\r
+GCC_ASM_EXPORT(ArmReadScr)\r
+GCC_ASM_EXPORT(ArmWriteScr)\r
+GCC_ASM_EXPORT(ArmReadMVBar)\r
+GCC_ASM_EXPORT(ArmWriteMVBar)\r
+GCC_ASM_EXPORT(ArmCallWFE)\r
+GCC_ASM_EXPORT(ArmCallSEV)\r
+GCC_ASM_EXPORT(ArmReadSctlr)\r
+\r
+#------------------------------------------------------------------------------\r
+\r
+ASM_PFX(Cp15IdCode):\r
+ mrc p15,0,R0,c0,c0,0\r
+ bx LR\r
+\r
+ASM_PFX(Cp15CacheInfo):\r
+ mrc p15,0,R0,c0,c0,1\r
+ bx LR\r
+\r
+ASM_PFX(ArmGetInterruptState):\r
+ mrs R0,CPSR\r
+ tst R0,#0x80 @Check if IRQ is enabled.\r
+ moveq R0,#1\r
+ movne R0,#0\r
+ bx LR\r
+\r
+ASM_PFX(ArmGetFiqState):\r
+ mrs R0,CPSR\r
+ tst R0,#0x40 @Check if FIQ is enabled.\r
+ moveq R0,#1\r
+ movne R0,#0\r
+ bx LR\r
+\r
+ASM_PFX(ArmSetDomainAccessControl):\r
+ mcr p15,0,r0,c3,c0,0\r
+ bx lr\r
+\r
+ASM_PFX(CPSRMaskInsert): @ on entry, r0 is the mask and r1 is the field to insert\r
+ stmfd sp!, {r4-r12, lr} @ save all the banked registers\r
+ mov r3, sp @ copy the stack pointer into a non-banked register\r
+ mrs r2, cpsr @ read the cpsr\r
+ bic r2, r2, r0 @ clear mask in the cpsr\r
+ and r1, r1, r0 @ clear bits outside the mask in the input\r
+ orr r2, r2, r1 @ set field\r
+ msr cpsr_cxsf, r2 @ write back cpsr (may have caused a mode switch)\r
+ isb\r
+ mov sp, r3 @ restore stack pointer\r
+ ldmfd sp!, {r4-r12, lr} @ restore registers\r
+ bx lr @ return (hopefully thumb-safe!) @ return (hopefully thumb-safe!)\r
+\r
+ASM_PFX(CPSRRead):\r
+ mrs r0, cpsr\r
+ bx lr\r
+\r
+ASM_PFX(ArmReadCpacr):\r
+ mrc p15, 0, r0, c1, c0, 2\r
+ bx lr\r
+\r
+ASM_PFX(ArmWriteCpacr):\r
+ mcr p15, 0, r0, c1, c0, 2\r
+ isb\r
+ bx lr\r
+\r
+ASM_PFX(ArmWriteAuxCr):\r
+ mcr p15, 0, r0, c1, c0, 1\r
+ bx lr\r
+\r
+ASM_PFX(ArmReadAuxCr):\r
+ mrc p15, 0, r0, c1, c0, 1\r
+ bx lr \r
+\r
+ASM_PFX(ArmSetTTBR0):\r
+ mcr p15,0,r0,c2,c0,0\r
+ isb\r
+ bx lr\r
+\r
+ASM_PFX(ArmGetTTBR0BaseAddress):\r
+ mrc p15,0,r0,c2,c0,0\r
+ LoadConstantToReg(0xFFFFC000, r1)\r
+ and r0, r0, r1\r
+ isb\r
+ bx lr\r
+\r
+//\r
+//VOID\r
+//ArmUpdateTranslationTableEntry (\r
+// IN VOID *TranslationTableEntry // R0\r
+// IN VOID *MVA // R1\r
+// );\r
+ASM_PFX(ArmUpdateTranslationTableEntry):\r
+ mcr p15,0,R0,c7,c14,1 @ DCCIMVAC Clean data cache by MVA\r
+ dsb\r
+ mcr p15,0,R1,c8,c7,1 @ TLBIMVA TLB Invalidate MVA \r
+ mcr p15,0,R9,c7,c5,6 @ BPIALL Invalidate Branch predictor array. R9 == NoOp\r
+ dsb\r
+ isb\r
+ bx lr\r
+\r
+ASM_PFX(ArmInvalidateTlb):\r
+ mov r0,#0\r
+ mcr p15,0,r0,c8,c7,0\r
+ mcr p15,0,R9,c7,c5,6 @ BPIALL Invalidate Branch predictor array. R9 == NoOp\r
+ dsb\r
+ isb\r
+ bx lr\r
+\r
+ASM_PFX(ArmReadNsacr):\r
+ mrc p15, 0, r0, c1, c1, 2\r
+ bx lr\r
+\r
+ASM_PFX(ArmWriteNsacr):\r
+ mcr p15, 0, r0, c1, c1, 2\r
+ bx lr\r
+\r
+ASM_PFX(ArmReadScr):\r
+ mrc p15, 0, r0, c1, c1, 0\r
+ bx lr\r
+\r
+ASM_PFX(ArmWriteScr):\r
+ mcr p15, 0, r0, c1, c1, 0\r
+ bx lr\r
+\r
+ASM_PFX(ArmReadMVBar):\r
+ mrc p15, 0, r0, c12, c0, 1\r
+ bx lr\r
+\r
+ASM_PFX(ArmWriteMVBar):\r
+ mcr p15, 0, r0, c12, c0, 1\r
+ bx lr\r
+\r
+ASM_PFX(ArmCallWFE):\r
+ wfe\r
+ bx lr\r
+\r
+ASM_PFX(ArmCallSEV):\r
+ sev\r
+ bx lr\r
+\r
+ASM_PFX(ArmReadSctlr):\r
+ mrc p15, 0, R0, c1, c0, 0 @ Read SCTLR into R0 (Read control register configuration data)\r
+ bx lr\r
+\r
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED\r
--- /dev/null
+//------------------------------------------------------------------------------ \r
+//\r
+// Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+// Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
+//\r
+// This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+//------------------------------------------------------------------------------\r
+\r
+#include <AsmMacroIoLib.h>\r
+ \r
+ INCLUDE AsmMacroIoLib.inc\r
+\r
+#ifdef ARM_CPU_ARMv6\r
+// No memory barriers for ARMv6\r
+#define isb\r
+#define dsb\r
+#endif\r
+\r
+ EXPORT Cp15IdCode\r
+ EXPORT Cp15CacheInfo\r
+ EXPORT ArmGetInterruptState\r
+ EXPORT ArmGetFiqState\r
+ EXPORT ArmGetTTBR0BaseAddress\r
+ EXPORT ArmSetTTBR0\r
+ EXPORT ArmSetDomainAccessControl\r
+ EXPORT CPSRMaskInsert\r
+ EXPORT CPSRRead\r
+ EXPORT ArmReadCpacr\r
+ EXPORT ArmWriteCpacr\r
+ EXPORT ArmWriteAuxCr\r
+ EXPORT ArmReadAuxCr\r
+ EXPORT ArmInvalidateTlb\r
+ EXPORT ArmUpdateTranslationTableEntry\r
+ EXPORT ArmReadNsacr\r
+ EXPORT ArmWriteNsacr\r
+ EXPORT ArmReadScr\r
+ EXPORT ArmWriteScr\r
+ EXPORT ArmReadMVBar\r
+ EXPORT ArmWriteMVBar\r
+ EXPORT ArmCallWFE\r
+ EXPORT ArmCallSEV\r
+ EXPORT ArmReadSctlr\r
+\r
+ AREA ArmLibSupport, CODE, READONLY\r
+\r
+Cp15IdCode\r
+ mrc p15,0,R0,c0,c0,0\r
+ bx LR\r
+\r
+Cp15CacheInfo\r
+ mrc p15,0,R0,c0,c0,1\r
+ bx LR\r
+\r
+ArmGetInterruptState\r
+ mrs R0,CPSR\r
+ tst R0,#0x80 // Check if IRQ is enabled.\r
+ moveq R0,#1\r
+ movne R0,#0\r
+ bx LR\r
+\r
+ArmGetFiqState\r
+ mrs R0,CPSR\r
+ tst R0,#0x40 // Check if FIQ is enabled.\r
+ moveq R0,#1\r
+ movne R0,#0\r
+ bx LR\r
+\r
+ArmSetDomainAccessControl\r
+ mcr p15,0,r0,c3,c0,0\r
+ bx lr\r
+\r
+CPSRMaskInsert // on entry, r0 is the mask and r1 is the field to insert\r
+ stmfd sp!, {r4-r12, lr} // save all the banked registers\r
+ mov r3, sp // copy the stack pointer into a non-banked register\r
+ mrs r2, cpsr // read the cpsr\r
+ bic r2, r2, r0 // clear mask in the cpsr\r
+ and r1, r1, r0 // clear bits outside the mask in the input\r
+ orr r2, r2, r1 // set field\r
+ msr cpsr_cxsf, r2 // write back cpsr (may have caused a mode switch)\r
+ isb\r
+ mov sp, r3 // restore stack pointer\r
+ ldmfd sp!, {r4-r12, lr} // restore registers\r
+ bx lr // return (hopefully thumb-safe!) // return (hopefully thumb-safe!)\r
+\r
+CPSRRead\r
+ mrs r0, cpsr\r
+ bx lr\r
+\r
+ArmReadCpacr\r
+ mrc p15, 0, r0, c1, c0, 2\r
+ bx lr\r
+\r
+ArmWriteCpacr\r
+ mcr p15, 0, r0, c1, c0, 2\r
+ isb\r
+ bx lr\r
+\r
+ArmWriteAuxCr\r
+ mcr p15, 0, r0, c1, c0, 1\r
+ bx lr\r
+\r
+ArmReadAuxCr\r
+ mrc p15, 0, r0, c1, c0, 1\r
+ bx lr \r
+\r
+ArmSetTTBR0\r
+ mcr p15,0,r0,c2,c0,0\r
+ isb\r
+ bx lr\r
+\r
+ArmGetTTBR0BaseAddress\r
+ mrc p15,0,r0,c2,c0,0\r
+ LoadConstantToReg(0xFFFFC000, r1)\r
+ and r0, r0, r1\r
+ isb\r
+ bx lr\r
+\r
+//\r
+//VOID\r
+//ArmUpdateTranslationTableEntry (\r
+// IN VOID *TranslationTableEntry // R0\r
+// IN VOID *MVA // R1\r
+// );\r
+ArmUpdateTranslationTableEntry\r
+ mcr p15,0,R0,c7,c14,1 // DCCIMVAC Clean data cache by MVA\r
+ dsb\r
+ mcr p15,0,R1,c8,c7,1 // TLBIMVA TLB Invalidate MVA\r
+ mcr p15,0,R9,c7,c5,6 // BPIALL Invalidate Branch predictor array. R9 == NoOp\r
+ dsb\r
+ isb\r
+ bx lr\r
+\r
+ArmInvalidateTlb\r
+ mov r0,#0\r
+ mcr p15,0,r0,c8,c7,0\r
+ mcr p15,0,R9,c7,c5,6 // BPIALL Invalidate Branch predictor array. R9 == NoOp\r
+ dsb\r
+ isb\r
+ bx lr\r
+\r
+ArmReadNsacr\r
+ mrc p15, 0, r0, c1, c1, 2\r
+ bx lr\r
+\r
+ArmWriteNsacr\r
+ mcr p15, 0, r0, c1, c1, 2\r
+ bx lr\r
+\r
+ArmReadScr\r
+ mrc p15, 0, r0, c1, c1, 0\r
+ bx lr\r
+\r
+ArmWriteScr\r
+ mcr p15, 0, r0, c1, c1, 0\r
+ bx lr\r
+\r
+ArmReadMVBar\r
+ mrc p15, 0, r0, c12, c0, 1\r
+ bx lr\r
+\r
+ArmWriteMVBar\r
+ mcr p15, 0, r0, c12, c0, 1\r
+ bx lr\r
+ \r
+ArmCallWFE\r
+ wfe\r
+ blx lr\r
+\r
+ArmCallSEV\r
+ sev\r
+ blx lr\r
+\r
+ArmReadSctlr\r
+ mrc p15, 0, R0, c1, c0, 0 // Read SCTLR into R0 (Read control register configuration data)\r
+ bx lr\r
+\r
+ END\r
+++ /dev/null
-#------------------------------------------------------------------------------ \r
-#\r
-# Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
-# Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
-#\r
-# This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this distribution. The full text of the license may be found at\r
-# http://opensource.org/licenses/bsd-license.php\r
-#\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#\r
-#------------------------------------------------------------------------------\r
-\r
-#include <AsmMacroIoLib.h>\r
-\r
-#ifdef ARM_CPU_ARMv6\r
-// No memory barriers for ARMv6\r
-#define isb\r
-#define dsb\r
-#endif\r
-\r
-.text\r
-.align 2\r
-GCC_ASM_EXPORT(Cp15IdCode)\r
-GCC_ASM_EXPORT(Cp15CacheInfo)\r
-GCC_ASM_EXPORT(ArmGetInterruptState)\r
-GCC_ASM_EXPORT(ArmGetFiqState)\r
-GCC_ASM_EXPORT(ArmGetTTBR0BaseAddress)\r
-GCC_ASM_EXPORT(ArmSetTTBR0)\r
-GCC_ASM_EXPORT(ArmSetDomainAccessControl)\r
-GCC_ASM_EXPORT(CPSRMaskInsert)\r
-GCC_ASM_EXPORT(CPSRRead)\r
-GCC_ASM_EXPORT(ArmReadCpacr)\r
-GCC_ASM_EXPORT(ArmWriteCpacr)\r
-GCC_ASM_EXPORT(ArmWriteAuxCr)\r
-GCC_ASM_EXPORT(ArmReadAuxCr)\r
-GCC_ASM_EXPORT(ArmInvalidateTlb)\r
-GCC_ASM_EXPORT(ArmUpdateTranslationTableEntry)\r
-GCC_ASM_EXPORT(ArmReadNsacr)\r
-GCC_ASM_EXPORT(ArmWriteNsacr)\r
-GCC_ASM_EXPORT(ArmReadScr)\r
-GCC_ASM_EXPORT(ArmWriteScr)\r
-GCC_ASM_EXPORT(ArmReadMVBar)\r
-GCC_ASM_EXPORT(ArmWriteMVBar)\r
-GCC_ASM_EXPORT(ArmCallWFE)\r
-GCC_ASM_EXPORT(ArmCallSEV)\r
-GCC_ASM_EXPORT(ArmReadSctlr)\r
-\r
-#------------------------------------------------------------------------------\r
-\r
-ASM_PFX(Cp15IdCode):\r
- mrc p15,0,R0,c0,c0,0\r
- bx LR\r
-\r
-ASM_PFX(Cp15CacheInfo):\r
- mrc p15,0,R0,c0,c0,1\r
- bx LR\r
-\r
-ASM_PFX(ArmGetInterruptState):\r
- mrs R0,CPSR\r
- tst R0,#0x80 @Check if IRQ is enabled.\r
- moveq R0,#1\r
- movne R0,#0\r
- bx LR\r
-\r
-ASM_PFX(ArmGetFiqState):\r
- mrs R0,CPSR\r
- tst R0,#0x40 @Check if FIQ is enabled.\r
- moveq R0,#1\r
- movne R0,#0\r
- bx LR\r
-\r
-ASM_PFX(ArmSetDomainAccessControl):\r
- mcr p15,0,r0,c3,c0,0\r
- bx lr\r
-\r
-ASM_PFX(CPSRMaskInsert): @ on entry, r0 is the mask and r1 is the field to insert\r
- stmfd sp!, {r4-r12, lr} @ save all the banked registers\r
- mov r3, sp @ copy the stack pointer into a non-banked register\r
- mrs r2, cpsr @ read the cpsr\r
- bic r2, r2, r0 @ clear mask in the cpsr\r
- and r1, r1, r0 @ clear bits outside the mask in the input\r
- orr r2, r2, r1 @ set field\r
- msr cpsr_cxsf, r2 @ write back cpsr (may have caused a mode switch)\r
- isb\r
- mov sp, r3 @ restore stack pointer\r
- ldmfd sp!, {r4-r12, lr} @ restore registers\r
- bx lr @ return (hopefully thumb-safe!) @ return (hopefully thumb-safe!)\r
-\r
-ASM_PFX(CPSRRead):\r
- mrs r0, cpsr\r
- bx lr\r
-\r
-ASM_PFX(ArmReadCpacr):\r
- mrc p15, 0, r0, c1, c0, 2\r
- bx lr\r
-\r
-ASM_PFX(ArmWriteCpacr):\r
- mcr p15, 0, r0, c1, c0, 2\r
- isb\r
- bx lr\r
-\r
-ASM_PFX(ArmWriteAuxCr):\r
- mcr p15, 0, r0, c1, c0, 1\r
- bx lr\r
-\r
-ASM_PFX(ArmReadAuxCr):\r
- mrc p15, 0, r0, c1, c0, 1\r
- bx lr \r
-\r
-ASM_PFX(ArmSetTTBR0):\r
- mcr p15,0,r0,c2,c0,0\r
- isb\r
- bx lr\r
-\r
-ASM_PFX(ArmGetTTBR0BaseAddress):\r
- mrc p15,0,r0,c2,c0,0\r
- LoadConstantToReg(0xFFFFC000, r1)\r
- and r0, r0, r1\r
- isb\r
- bx lr\r
-\r
-//\r
-//VOID\r
-//ArmUpdateTranslationTableEntry (\r
-// IN VOID *TranslationTableEntry // R0\r
-// IN VOID *MVA // R1\r
-// );\r
-ASM_PFX(ArmUpdateTranslationTableEntry):\r
- mcr p15,0,R0,c7,c14,1 @ DCCIMVAC Clean data cache by MVA\r
- dsb\r
- mcr p15,0,R1,c8,c7,1 @ TLBIMVA TLB Invalidate MVA \r
- mcr p15,0,R9,c7,c5,6 @ BPIALL Invalidate Branch predictor array. R9 == NoOp\r
- dsb\r
- isb\r
- bx lr\r
-\r
-ASM_PFX(ArmInvalidateTlb):\r
- mov r0,#0\r
- mcr p15,0,r0,c8,c7,0\r
- mcr p15,0,R9,c7,c5,6 @ BPIALL Invalidate Branch predictor array. R9 == NoOp\r
- dsb\r
- isb\r
- bx lr\r
-\r
-ASM_PFX(ArmReadNsacr):\r
- mrc p15, 0, r0, c1, c1, 2\r
- bx lr\r
-\r
-ASM_PFX(ArmWriteNsacr):\r
- mcr p15, 0, r0, c1, c1, 2\r
- bx lr\r
-\r
-ASM_PFX(ArmReadScr):\r
- mrc p15, 0, r0, c1, c1, 0\r
- bx lr\r
-\r
-ASM_PFX(ArmWriteScr):\r
- mcr p15, 0, r0, c1, c1, 0\r
- bx lr\r
-\r
-ASM_PFX(ArmReadMVBar):\r
- mrc p15, 0, r0, c12, c0, 1\r
- bx lr\r
-\r
-ASM_PFX(ArmWriteMVBar):\r
- mcr p15, 0, r0, c12, c0, 1\r
- bx lr\r
-\r
-ASM_PFX(ArmCallWFE):\r
- wfe\r
- bx lr\r
-\r
-ASM_PFX(ArmCallSEV):\r
- sev\r
- bx lr\r
-\r
-ASM_PFX(ArmReadSctlr):\r
- mrc p15, 0, R0, c1, c0, 0 @ Read SCTLR into R0 (Read control register configuration data)\r
- bx lr\r
-\r
-ASM_FUNCTION_REMOVE_IF_UNREFERENCED\r
+++ /dev/null
-//------------------------------------------------------------------------------ \r
-//\r
-// Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
-// Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
-//\r
-// This program and the accompanying materials\r
-// are licensed and made available under the terms and conditions of the BSD License\r
-// which accompanies this distribution. The full text of the license may be found at\r
-// http://opensource.org/licenses/bsd-license.php\r
-//\r
-// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-//\r
-//------------------------------------------------------------------------------\r
-\r
-#include <AsmMacroIoLib.h>\r
- \r
- INCLUDE AsmMacroIoLib.inc\r
-\r
-#ifdef ARM_CPU_ARMv6\r
-// No memory barriers for ARMv6\r
-#define isb\r
-#define dsb\r
-#endif\r
-\r
- EXPORT Cp15IdCode\r
- EXPORT Cp15CacheInfo\r
- EXPORT ArmGetInterruptState\r
- EXPORT ArmGetFiqState\r
- EXPORT ArmGetTTBR0BaseAddress\r
- EXPORT ArmSetTTBR0\r
- EXPORT ArmSetDomainAccessControl\r
- EXPORT CPSRMaskInsert\r
- EXPORT CPSRRead\r
- EXPORT ArmReadCpacr\r
- EXPORT ArmWriteCpacr\r
- EXPORT ArmWriteAuxCr\r
- EXPORT ArmReadAuxCr\r
- EXPORT ArmInvalidateTlb\r
- EXPORT ArmUpdateTranslationTableEntry\r
- EXPORT ArmReadNsacr\r
- EXPORT ArmWriteNsacr\r
- EXPORT ArmReadScr\r
- EXPORT ArmWriteScr\r
- EXPORT ArmReadMVBar\r
- EXPORT ArmWriteMVBar\r
- EXPORT ArmCallWFE\r
- EXPORT ArmCallSEV\r
- EXPORT ArmReadSctlr\r
-\r
- AREA ArmLibSupport, CODE, READONLY\r
-\r
-Cp15IdCode\r
- mrc p15,0,R0,c0,c0,0\r
- bx LR\r
-\r
-Cp15CacheInfo\r
- mrc p15,0,R0,c0,c0,1\r
- bx LR\r
-\r
-ArmGetInterruptState\r
- mrs R0,CPSR\r
- tst R0,#0x80 // Check if IRQ is enabled.\r
- moveq R0,#1\r
- movne R0,#0\r
- bx LR\r
-\r
-ArmGetFiqState\r
- mrs R0,CPSR\r
- tst R0,#0x40 // Check if FIQ is enabled.\r
- moveq R0,#1\r
- movne R0,#0\r
- bx LR\r
-\r
-ArmSetDomainAccessControl\r
- mcr p15,0,r0,c3,c0,0\r
- bx lr\r
-\r
-CPSRMaskInsert // on entry, r0 is the mask and r1 is the field to insert\r
- stmfd sp!, {r4-r12, lr} // save all the banked registers\r
- mov r3, sp // copy the stack pointer into a non-banked register\r
- mrs r2, cpsr // read the cpsr\r
- bic r2, r2, r0 // clear mask in the cpsr\r
- and r1, r1, r0 // clear bits outside the mask in the input\r
- orr r2, r2, r1 // set field\r
- msr cpsr_cxsf, r2 // write back cpsr (may have caused a mode switch)\r
- isb\r
- mov sp, r3 // restore stack pointer\r
- ldmfd sp!, {r4-r12, lr} // restore registers\r
- bx lr // return (hopefully thumb-safe!) // return (hopefully thumb-safe!)\r
-\r
-CPSRRead\r
- mrs r0, cpsr\r
- bx lr\r
-\r
-ArmReadCpacr\r
- mrc p15, 0, r0, c1, c0, 2\r
- bx lr\r
-\r
-ArmWriteCpacr\r
- mcr p15, 0, r0, c1, c0, 2\r
- isb\r
- bx lr\r
-\r
-ArmWriteAuxCr\r
- mcr p15, 0, r0, c1, c0, 1\r
- bx lr\r
-\r
-ArmReadAuxCr\r
- mrc p15, 0, r0, c1, c0, 1\r
- bx lr \r
-\r
-ArmSetTTBR0\r
- mcr p15,0,r0,c2,c0,0\r
- isb\r
- bx lr\r
-\r
-ArmGetTTBR0BaseAddress\r
- mrc p15,0,r0,c2,c0,0\r
- LoadConstantToReg(0xFFFFC000, r1)\r
- and r0, r0, r1\r
- isb\r
- bx lr\r
-\r
-//\r
-//VOID\r
-//ArmUpdateTranslationTableEntry (\r
-// IN VOID *TranslationTableEntry // R0\r
-// IN VOID *MVA // R1\r
-// );\r
-ArmUpdateTranslationTableEntry\r
- mcr p15,0,R0,c7,c14,1 // DCCIMVAC Clean data cache by MVA\r
- dsb\r
- mcr p15,0,R1,c8,c7,1 // TLBIMVA TLB Invalidate MVA\r
- mcr p15,0,R9,c7,c5,6 // BPIALL Invalidate Branch predictor array. R9 == NoOp\r
- dsb\r
- isb\r
- bx lr\r
-\r
-ArmInvalidateTlb\r
- mov r0,#0\r
- mcr p15,0,r0,c8,c7,0\r
- mcr p15,0,R9,c7,c5,6 // BPIALL Invalidate Branch predictor array. R9 == NoOp\r
- dsb\r
- isb\r
- bx lr\r
-\r
-ArmReadNsacr\r
- mrc p15, 0, r0, c1, c1, 2\r
- bx lr\r
-\r
-ArmWriteNsacr\r
- mcr p15, 0, r0, c1, c1, 2\r
- bx lr\r
-\r
-ArmReadScr\r
- mrc p15, 0, r0, c1, c1, 0\r
- bx lr\r
-\r
-ArmWriteScr\r
- mcr p15, 0, r0, c1, c1, 0\r
- bx lr\r
-\r
-ArmReadMVBar\r
- mrc p15, 0, r0, c12, c0, 1\r
- bx lr\r
-\r
-ArmWriteMVBar\r
- mcr p15, 0, r0, c12, c0, 1\r
- bx lr\r
- \r
-ArmCallWFE\r
- wfe\r
- blx lr\r
-\r
-ArmCallSEV\r
- sev\r
- blx lr\r
-\r
-ArmReadSctlr\r
- mrc p15, 0, R0, c1, c0, 0 // Read SCTLR into R0 (Read control register configuration data)\r
- bx lr\r
-\r
- END\r
LIBRARY_CLASS = ArmLib\r
\r
[Sources.common]\r
- ../Common/ArmLibSupport.S | GCC\r
- ../Common/ArmLibSupport.asm | RVCT\r
../Common/ArmLib.c\r
\r
NullArmLib.c\r
NullArmCacheInformation.c\r
\r
+[Sources.ARM]\r
+ ../Common/Arm/ArmLibSupport.S | GCC\r
+ ../Common/Arm/ArmLibSupport.asm | RVCT\r
+\r
[Packages]\r
ArmPkg/ArmPkg.dec\r
MdePkg/MdePkg.dec\r
--- /dev/null
+/** @file\r
+*\r
+* Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
+* \r
+* This program and the accompanying materials \r
+* are licensed and made available under the terms and conditions of the BSD License \r
+* which accompanies this distribution. The full text of the license may be found at \r
+* http://opensource.org/licenses/bsd-license.php \r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+*\r
+**/\r
+\r
+#include "BdsInternal.h"\r
+#include "BdsLinuxLoader.h"\r
+\r
+// Point to the current ATAG\r
+STATIC LINUX_ATAG *mLinuxKernelCurrentAtag;\r
+\r
+STATIC\r
+VOID\r
+SetupCoreTag (\r
+ IN UINT32 PageSize\r
+ )\r
+{\r
+ mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_CORE);\r
+ mLinuxKernelCurrentAtag->header.type = ATAG_CORE;\r
+\r
+ mLinuxKernelCurrentAtag->body.core_tag.flags = 1; /* ensure read-only */\r
+ mLinuxKernelCurrentAtag->body.core_tag.pagesize = PageSize; /* systems PageSize (4k) */\r
+ mLinuxKernelCurrentAtag->body.core_tag.rootdev = 0; /* zero root device (typically overridden from kernel command line )*/\r
+\r
+ // move pointer to next tag\r
+ mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);\r
+}\r
+\r
+STATIC\r
+VOID\r
+SetupMemTag (\r
+ IN UINTN StartAddress,\r
+ IN UINT32 Size\r
+ )\r
+{\r
+ mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_MEM);\r
+ mLinuxKernelCurrentAtag->header.type = ATAG_MEM;\r
+\r
+ mLinuxKernelCurrentAtag->body.mem_tag.start = StartAddress; /* Start of memory chunk for AtagMem */\r
+ mLinuxKernelCurrentAtag->body.mem_tag.size = Size; /* Size of memory chunk for AtagMem */\r
+\r
+ // move pointer to next tag\r
+ mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);\r
+}\r
+\r
+STATIC\r
+VOID\r
+SetupCmdlineTag (\r
+ IN CONST CHAR8 *CmdLine\r
+ )\r
+{\r
+ UINT32 LineLength;\r
+\r
+ // Increment the line length by 1 to account for the null string terminator character\r
+ LineLength = AsciiStrLen(CmdLine) + 1;\r
+\r
+ /* Check for NULL strings.\r
+ * Do not insert a tag for an empty CommandLine, don't even modify the tag address pointer.\r
+ * Remember, you have at least one null string terminator character.\r
+ */\r
+ if(LineLength > 1) {\r
+ mLinuxKernelCurrentAtag->header.size = ((UINT32)sizeof(LINUX_ATAG_HEADER) + LineLength + (UINT32)3) >> 2;\r
+ mLinuxKernelCurrentAtag->header.type = ATAG_CMDLINE;\r
+\r
+ /* place CommandLine into tag */\r
+ AsciiStrCpy(mLinuxKernelCurrentAtag->body.cmdline_tag.cmdline, CmdLine);\r
+\r
+ // move pointer to next tag\r
+ mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);\r
+ }\r
+}\r
+\r
+STATIC\r
+VOID\r
+SetupInitrdTag (\r
+ IN UINT32 InitrdImage,\r
+ IN UINT32 InitrdImageSize\r
+ )\r
+{\r
+ mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_INITRD2);\r
+ mLinuxKernelCurrentAtag->header.type = ATAG_INITRD2;\r
+\r
+ mLinuxKernelCurrentAtag->body.initrd2_tag.start = InitrdImage;\r
+ mLinuxKernelCurrentAtag->body.initrd2_tag.size = InitrdImageSize;\r
+\r
+ // Move pointer to next tag\r
+ mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);\r
+}\r
+STATIC\r
+VOID\r
+SetupEndTag (\r
+ VOID\r
+ )\r
+{\r
+ // Empty tag ends list; this has zero length and no body\r
+ mLinuxKernelCurrentAtag->header.type = ATAG_NONE;\r
+ mLinuxKernelCurrentAtag->header.size = 0;\r
+\r
+ /* We can not calculate the next address by using the standard macro:\r
+ * Params = next_tag_address(Params);\r
+ * because it relies on the header.size, which here it is 0 (zero).\r
+ * The easiest way is to add the sizeof(mLinuxKernelCurrentAtag->header).\r
+ */\r
+ mLinuxKernelCurrentAtag = (LINUX_ATAG*)((UINT32)mLinuxKernelCurrentAtag + sizeof(mLinuxKernelCurrentAtag->header));\r
+}\r
+\r
+EFI_STATUS\r
+PrepareAtagList (\r
+ IN CONST CHAR8* CommandLineString,\r
+ IN EFI_PHYSICAL_ADDRESS InitrdImage,\r
+ IN UINTN InitrdImageSize,\r
+ OUT EFI_PHYSICAL_ADDRESS *AtagBase,\r
+ OUT UINT32 *AtagSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *ResourceLink;\r
+ LIST_ENTRY ResourceList;\r
+ EFI_PHYSICAL_ADDRESS AtagStartAddress;\r
+ BDS_SYSTEM_MEMORY_RESOURCE *Resource;\r
+\r
+ AtagStartAddress = LINUX_ATAG_MAX_OFFSET;\r
+ Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((EFI_D_WARN, "Warning: Failed to allocate Atag at 0x%lX (%r). The Atag will be allocated somewhere else in System Memory.\n", AtagStartAddress, Status));\r
+ Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress);\r
+ ASSERT_EFI_ERROR(Status);\r
+ }\r
+\r
+ // Ready to setup the atag list\r
+ mLinuxKernelCurrentAtag = (LINUX_ATAG*)(UINTN)AtagStartAddress;\r
+\r
+ // Standard core tag 4k PageSize\r
+ SetupCoreTag( (UINT32)SIZE_4KB );\r
+\r
+ // Physical memory setup\r
+ GetSystemMemoryResources (&ResourceList);\r
+ ResourceLink = ResourceList.ForwardLink;\r
+ while (ResourceLink != NULL && ResourceLink != &ResourceList) {\r
+ Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)ResourceLink;\r
+ DEBUG((EFI_D_INFO,"- [0x%08X,0x%08X]\n",(UINT32)Resource->PhysicalStart,(UINT32)Resource->PhysicalStart+(UINT32)Resource->ResourceLength));\r
+ SetupMemTag( (UINT32)Resource->PhysicalStart, (UINT32)Resource->ResourceLength );\r
+ ResourceLink = ResourceLink->ForwardLink;\r
+ }\r
+\r
+ // CommandLine setting root device\r
+ if (CommandLineString) {\r
+ SetupCmdlineTag (CommandLineString);\r
+ }\r
+\r
+ if (InitrdImageSize > 0 && InitrdImage != 0) {\r
+ SetupInitrdTag ((UINT32)InitrdImage, (UINT32)InitrdImageSize);\r
+ }\r
+\r
+ // End of tags\r
+ SetupEndTag();\r
+\r
+ // Calculate atag list size\r
+ *AtagBase = AtagStartAddress;\r
+ *AtagSize = (UINT32)mLinuxKernelCurrentAtag - (UINT32)AtagStartAddress + 1;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+*\r
+* Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
+* \r
+* This program and the accompanying materials \r
+* are licensed and made available under the terms and conditions of the BSD License \r
+* which accompanies this distribution. The full text of the license may be found at \r
+* http://opensource.org/licenses/bsd-license.php \r
+*\r
+* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+*\r
+**/\r
+\r
+#include "BdsInternal.h"\r
+#include "BdsLinuxLoader.h"\r
+\r
+#define ALIGN32_BELOW(addr) ALIGN_POINTER(addr - 32,32)\r
+\r
+STATIC\r
+EFI_STATUS\r
+PreparePlatformHardware (\r
+ VOID\r
+ )\r
+{\r
+ //Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called.\r
+\r
+ // Clean, invalidate, disable data cache\r
+ ArmDisableDataCache();\r
+ ArmCleanInvalidateDataCache();\r
+\r
+ // Invalidate and disable the Instruction cache\r
+ ArmDisableInstructionCache ();\r
+ ArmInvalidateInstructionCache ();\r
+\r
+ // Turn off MMU\r
+ ArmDisableMmu();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+StartLinux (\r
+ IN EFI_PHYSICAL_ADDRESS LinuxImage,\r
+ IN UINTN LinuxImageSize,\r
+ IN EFI_PHYSICAL_ADDRESS KernelParamsAddress,\r
+ IN UINTN KernelParamsSize,\r
+ IN UINT32 MachineType\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ LINUX_KERNEL LinuxKernel;\r
+\r
+ // Shut down UEFI boot services. ExitBootServices() will notify every driver that created an event on\r
+ // ExitBootServices event. Example the Interrupt DXE driver will disable the interrupts on this event.\r
+ Status = ShutdownUefiBootServices ();\r
+ if(EFI_ERROR(Status)) {\r
+ DEBUG((EFI_D_ERROR,"ERROR: Can not shutdown UEFI boot services. Status=0x%X\n", Status));\r
+ goto Exit;\r
+ }\r
+\r
+ // Move the kernel parameters to any address inside the first 1MB.\r
+ // This is necessary because the ARM Linux kernel requires\r
+ // the FTD / ATAG List to reside entirely inside the first 1MB of\r
+ // physical memory.\r
+ //Note: There is no requirement on the alignment\r
+ if (MachineType != ARM_FDT_MACHINE_TYPE) {\r
+ if (((UINTN)KernelParamsAddress > LINUX_ATAG_MAX_OFFSET) && (KernelParamsSize < PcdGet32(PcdArmLinuxAtagMaxOffset))) {\r
+ KernelParamsAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CopyMem (ALIGN32_BELOW(LINUX_ATAG_MAX_OFFSET - KernelParamsSize), (VOID*)(UINTN)KernelParamsAddress, KernelParamsSize);\r
+ }\r
+ } else {\r
+ if (((UINTN)KernelParamsAddress > LINUX_FDT_MAX_OFFSET) && (KernelParamsSize < PcdGet32(PcdArmLinuxFdtMaxOffset))) {\r
+ KernelParamsAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CopyMem (ALIGN32_BELOW(LINUX_FDT_MAX_OFFSET - KernelParamsSize), (VOID*)(UINTN)KernelParamsAddress, KernelParamsSize);\r
+ }\r
+ }\r
+\r
+ if ((UINTN)LinuxImage > LINUX_KERNEL_MAX_OFFSET) {\r
+ //Note: There is no requirement on the alignment\r
+ LinuxKernel = (LINUX_KERNEL)CopyMem (ALIGN32_BELOW(LINUX_KERNEL_MAX_OFFSET - LinuxImageSize), (VOID*)(UINTN)LinuxImage, LinuxImageSize);\r
+ } else {\r
+ LinuxKernel = (LINUX_KERNEL)(UINTN)LinuxImage;\r
+ }\r
+\r
+ // Check if the Linux Image is a uImage\r
+ if (*(UINT32*)LinuxKernel == LINUX_UIMAGE_SIGNATURE) {\r
+ // Assume the Image Entry Point is just after the uImage header (64-byte size)\r
+ LinuxKernel = (LINUX_KERNEL)((UINTN)LinuxKernel + 64);\r
+ LinuxImageSize -= 64;\r
+ }\r
+\r
+ //TODO: Check there is no overlapping between kernel and Atag\r
+\r
+ //\r
+ // Switch off interrupts, caches, mmu, etc\r
+ //\r
+ Status = PreparePlatformHardware ();\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ // Register and print out performance information\r
+ PERF_END (NULL, "BDS", NULL, 0);\r
+ if (PerformanceMeasurementEnabled ()) {\r
+ PrintPerformance ();\r
+ }\r
+\r
+ //\r
+ // Start the Linux Kernel\r
+ //\r
+\r
+ // Outside BootServices, so can't use Print();\r
+ DEBUG((EFI_D_ERROR, "\nStarting the kernel:\n\n"));\r
+\r
+ // Jump to kernel with register set\r
+ LinuxKernel ((UINTN)0, MachineType, (UINTN)KernelParamsAddress);\r
+\r
+ // Kernel should never exit\r
+ // After Life services are not provided\r
+ ASSERT(FALSE);\r
+\r
+Exit:\r
+ // Only be here if we fail to start Linux\r
+ Print (L"ERROR : Can not start the kernel. Status=0x%X\n", Status);\r
+\r
+ // Free Runtimee Memory (kernel and FDT)\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Start a Linux kernel from a Device Path\r
+\r
+ @param LinuxKernel Device Path to the Linux Kernel\r
+ @param Parameters Linux kernel arguments\r
+ @param Fdt Device Path to the Flat Device Tree\r
+\r
+ @retval EFI_SUCCESS All drivers have been connected\r
+ @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsBootLinuxAtag (\r
+ IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
+ IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
+ IN CONST CHAR8* CommandLineArguments\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 LinuxImageSize;\r
+ UINT32 InitrdImageSize = 0;\r
+ UINT32 AtagSize;\r
+ EFI_PHYSICAL_ADDRESS AtagBase;\r
+ EFI_PHYSICAL_ADDRESS LinuxImage;\r
+ EFI_PHYSICAL_ADDRESS InitrdImage;\r
+\r
+ PERF_START (NULL, "BDS", NULL, 0);\r
+\r
+ // Load the Linux kernel from a device path\r
+ LinuxImage = LINUX_KERNEL_MAX_OFFSET;\r
+ Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);\r
+ if (EFI_ERROR(Status)) {\r
+ Print (L"ERROR: Did not find Linux kernel.\n");\r
+ return Status;\r
+ }\r
+\r
+ if (InitrdDevicePath) {\r
+ // Load the initrd near to the Linux kernel\r
+ InitrdImage = LINUX_KERNEL_MAX_OFFSET;\r
+ Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, &InitrdImageSize);\r
+ if (Status == EFI_OUT_OF_RESOURCES) {\r
+ Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize);\r
+ }\r
+ if (EFI_ERROR(Status)) {\r
+ Print (L"ERROR: Did not find initrd image.\n");\r
+ return Status;\r
+ }\r
+ \r
+ // Check if the initrd is a uInitrd\r
+ if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {\r
+ // Skip the 64-byte image header\r
+ InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);\r
+ InitrdImageSize -= 64;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Setup the Linux Kernel Parameters\r
+ //\r
+ \r
+ // By setting address=0 we leave the memory allocation to the function\r
+ Status = PrepareAtagList (CommandLineArguments, InitrdImage, InitrdImageSize, &AtagBase, &AtagSize);\r
+ if (EFI_ERROR(Status)) {\r
+ Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", Status);\r
+ return Status;\r
+ }\r
+\r
+ return StartLinux (LinuxImage, LinuxImageSize, AtagBase, AtagSize, PcdGet32(PcdArmMachineType));\r
+}\r
+\r
+/**\r
+ Start a Linux kernel from a Device Path\r
+\r
+ @param LinuxKernel Device Path to the Linux Kernel\r
+ @param Parameters Linux kernel arguments\r
+ @param Fdt Device Path to the Flat Device Tree\r
+\r
+ @retval EFI_SUCCESS All drivers have been connected\r
+ @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.\r
+\r
+**/\r
+EFI_STATUS\r
+BdsBootLinuxFdt (\r
+ IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
+ IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
+ IN CONST CHAR8* CommandLineArguments,\r
+ IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 LinuxImageSize;\r
+ UINT32 InitrdImageSize = 0;\r
+ UINT32 FdtBlobSize;\r
+ EFI_PHYSICAL_ADDRESS FdtBlobBase;\r
+ EFI_PHYSICAL_ADDRESS LinuxImage;\r
+ EFI_PHYSICAL_ADDRESS InitrdImage;\r
+\r
+ PERF_START (NULL, "BDS", NULL, 0);\r
+\r
+ // Load the Linux kernel from a device path\r
+ LinuxImage = LINUX_KERNEL_MAX_OFFSET;\r
+ Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);\r
+ if (EFI_ERROR(Status)) {\r
+ Print (L"ERROR: Did not find Linux kernel.\n");\r
+ return Status;\r
+ }\r
+\r
+ if (InitrdDevicePath) {\r
+ InitrdImage = LINUX_KERNEL_MAX_OFFSET;\r
+ Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, &InitrdImageSize);\r
+ if (Status == EFI_OUT_OF_RESOURCES) {\r
+ Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize);\r
+ }\r
+ if (EFI_ERROR(Status)) {\r
+ Print (L"ERROR: Did not find initrd image.\n");\r
+ return Status;\r
+ }\r
+\r
+ // Check if the initrd is a uInitrd\r
+ if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {\r
+ // Skip the 64-byte image header\r
+ InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);\r
+ InitrdImageSize -= 64;\r
+ }\r
+ }\r
+\r
+ // Load the FDT binary from a device path. The FDT will be reloaded later to a more appropriate location for the Linux kernel.\r
+ FdtBlobBase = 0;\r
+ Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);\r
+ if (EFI_ERROR(Status)) {\r
+ Print (L"ERROR: Did not find Device Tree blob.\n");\r
+ return Status;\r
+ }\r
+\r
+ // Update the Fdt with the Initrd information. The FDT will increase in size.\r
+ // By setting address=0 we leave the memory allocation to the function\r
+ Status = PrepareFdt (CommandLineArguments, InitrdImage, InitrdImageSize, &FdtBlobBase, &FdtBlobSize);\r
+ if (EFI_ERROR(Status)) {\r
+ Print(L"ERROR: Can not load kernel with FDT. Status=%r\n", Status);\r
+ return Status;\r
+ }\r
+\r
+ return StartLinux (LinuxImage, LinuxImageSize, FdtBlobBase, FdtBlobSize, ARM_FDT_MACHINE_TYPE);\r
+}\r
+\r
BdsAppLoader.c\r
BdsHelper.c\r
BdsLoadOption.c\r
-\r
- BdsLinuxLoader.c\r
- BdsLinuxAtag.c\r
BdsLinuxFdt.c\r
\r
+[Sources.ARM]\r
+ Arm/BdsLinuxLoader.c\r
+ Arm/BdsLinuxAtag.c\r
+\r
[Packages]\r
MdePkg/MdePkg.dec\r
EmbeddedPkg/EmbeddedPkg.dec\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
-* \r
-* This program and the accompanying materials \r
-* are licensed and made available under the terms and conditions of the BSD License \r
-* which accompanies this distribution. The full text of the license may be found at \r
-* http://opensource.org/licenses/bsd-license.php \r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-*\r
-**/\r
-\r
-#include "BdsInternal.h"\r
-#include "BdsLinuxLoader.h"\r
-\r
-// Point to the current ATAG\r
-STATIC LINUX_ATAG *mLinuxKernelCurrentAtag;\r
-\r
-STATIC\r
-VOID\r
-SetupCoreTag (\r
- IN UINT32 PageSize\r
- )\r
-{\r
- mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_CORE);\r
- mLinuxKernelCurrentAtag->header.type = ATAG_CORE;\r
-\r
- mLinuxKernelCurrentAtag->body.core_tag.flags = 1; /* ensure read-only */\r
- mLinuxKernelCurrentAtag->body.core_tag.pagesize = PageSize; /* systems PageSize (4k) */\r
- mLinuxKernelCurrentAtag->body.core_tag.rootdev = 0; /* zero root device (typically overridden from kernel command line )*/\r
-\r
- // move pointer to next tag\r
- mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);\r
-}\r
-\r
-STATIC\r
-VOID\r
-SetupMemTag (\r
- IN UINTN StartAddress,\r
- IN UINT32 Size\r
- )\r
-{\r
- mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_MEM);\r
- mLinuxKernelCurrentAtag->header.type = ATAG_MEM;\r
-\r
- mLinuxKernelCurrentAtag->body.mem_tag.start = StartAddress; /* Start of memory chunk for AtagMem */\r
- mLinuxKernelCurrentAtag->body.mem_tag.size = Size; /* Size of memory chunk for AtagMem */\r
-\r
- // move pointer to next tag\r
- mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);\r
-}\r
-\r
-STATIC\r
-VOID\r
-SetupCmdlineTag (\r
- IN CONST CHAR8 *CmdLine\r
- )\r
-{\r
- UINT32 LineLength;\r
-\r
- // Increment the line length by 1 to account for the null string terminator character\r
- LineLength = AsciiStrLen(CmdLine) + 1;\r
-\r
- /* Check for NULL strings.\r
- * Do not insert a tag for an empty CommandLine, don't even modify the tag address pointer.\r
- * Remember, you have at least one null string terminator character.\r
- */\r
- if(LineLength > 1) {\r
- mLinuxKernelCurrentAtag->header.size = ((UINT32)sizeof(LINUX_ATAG_HEADER) + LineLength + (UINT32)3) >> 2;\r
- mLinuxKernelCurrentAtag->header.type = ATAG_CMDLINE;\r
-\r
- /* place CommandLine into tag */\r
- AsciiStrCpy(mLinuxKernelCurrentAtag->body.cmdline_tag.cmdline, CmdLine);\r
-\r
- // move pointer to next tag\r
- mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);\r
- }\r
-}\r
-\r
-STATIC\r
-VOID\r
-SetupInitrdTag (\r
- IN UINT32 InitrdImage,\r
- IN UINT32 InitrdImageSize\r
- )\r
-{\r
- mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_INITRD2);\r
- mLinuxKernelCurrentAtag->header.type = ATAG_INITRD2;\r
-\r
- mLinuxKernelCurrentAtag->body.initrd2_tag.start = InitrdImage;\r
- mLinuxKernelCurrentAtag->body.initrd2_tag.size = InitrdImageSize;\r
-\r
- // Move pointer to next tag\r
- mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);\r
-}\r
-STATIC\r
-VOID\r
-SetupEndTag (\r
- VOID\r
- )\r
-{\r
- // Empty tag ends list; this has zero length and no body\r
- mLinuxKernelCurrentAtag->header.type = ATAG_NONE;\r
- mLinuxKernelCurrentAtag->header.size = 0;\r
-\r
- /* We can not calculate the next address by using the standard macro:\r
- * Params = next_tag_address(Params);\r
- * because it relies on the header.size, which here it is 0 (zero).\r
- * The easiest way is to add the sizeof(mLinuxKernelCurrentAtag->header).\r
- */\r
- mLinuxKernelCurrentAtag = (LINUX_ATAG*)((UINT32)mLinuxKernelCurrentAtag + sizeof(mLinuxKernelCurrentAtag->header));\r
-}\r
-\r
-EFI_STATUS\r
-PrepareAtagList (\r
- IN CONST CHAR8* CommandLineString,\r
- IN EFI_PHYSICAL_ADDRESS InitrdImage,\r
- IN UINTN InitrdImageSize,\r
- OUT EFI_PHYSICAL_ADDRESS *AtagBase,\r
- OUT UINT32 *AtagSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
- LIST_ENTRY *ResourceLink;\r
- LIST_ENTRY ResourceList;\r
- EFI_PHYSICAL_ADDRESS AtagStartAddress;\r
- BDS_SYSTEM_MEMORY_RESOURCE *Resource;\r
-\r
- AtagStartAddress = LINUX_ATAG_MAX_OFFSET;\r
- Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress);\r
- if (EFI_ERROR(Status)) {\r
- DEBUG ((EFI_D_WARN, "Warning: Failed to allocate Atag at 0x%lX (%r). The Atag will be allocated somewhere else in System Memory.\n", AtagStartAddress, Status));\r
- Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress);\r
- ASSERT_EFI_ERROR(Status);\r
- }\r
-\r
- // Ready to setup the atag list\r
- mLinuxKernelCurrentAtag = (LINUX_ATAG*)(UINTN)AtagStartAddress;\r
-\r
- // Standard core tag 4k PageSize\r
- SetupCoreTag( (UINT32)SIZE_4KB );\r
-\r
- // Physical memory setup\r
- GetSystemMemoryResources (&ResourceList);\r
- ResourceLink = ResourceList.ForwardLink;\r
- while (ResourceLink != NULL && ResourceLink != &ResourceList) {\r
- Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)ResourceLink;\r
- DEBUG((EFI_D_INFO,"- [0x%08X,0x%08X]\n",(UINT32)Resource->PhysicalStart,(UINT32)Resource->PhysicalStart+(UINT32)Resource->ResourceLength));\r
- SetupMemTag( (UINT32)Resource->PhysicalStart, (UINT32)Resource->ResourceLength );\r
- ResourceLink = ResourceLink->ForwardLink;\r
- }\r
-\r
- // CommandLine setting root device\r
- if (CommandLineString) {\r
- SetupCmdlineTag (CommandLineString);\r
- }\r
-\r
- if (InitrdImageSize > 0 && InitrdImage != 0) {\r
- SetupInitrdTag ((UINT32)InitrdImage, (UINT32)InitrdImageSize);\r
- }\r
-\r
- // End of tags\r
- SetupEndTag();\r
-\r
- // Calculate atag list size\r
- *AtagBase = AtagStartAddress;\r
- *AtagSize = (UINT32)mLinuxKernelCurrentAtag - (UINT32)AtagStartAddress + 1;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
+++ /dev/null
-/** @file\r
-*\r
-* Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
-* \r
-* This program and the accompanying materials \r
-* are licensed and made available under the terms and conditions of the BSD License \r
-* which accompanies this distribution. The full text of the license may be found at \r
-* http://opensource.org/licenses/bsd-license.php \r
-*\r
-* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-*\r
-**/\r
-\r
-#include "BdsInternal.h"\r
-#include "BdsLinuxLoader.h"\r
-\r
-#define ALIGN32_BELOW(addr) ALIGN_POINTER(addr - 32,32)\r
-\r
-STATIC\r
-EFI_STATUS\r
-PreparePlatformHardware (\r
- VOID\r
- )\r
-{\r
- //Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called.\r
-\r
- // Clean, invalidate, disable data cache\r
- ArmDisableDataCache();\r
- ArmCleanInvalidateDataCache();\r
-\r
- // Invalidate and disable the Instruction cache\r
- ArmDisableInstructionCache ();\r
- ArmInvalidateInstructionCache ();\r
-\r
- // Turn off MMU\r
- ArmDisableMmu();\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-StartLinux (\r
- IN EFI_PHYSICAL_ADDRESS LinuxImage,\r
- IN UINTN LinuxImageSize,\r
- IN EFI_PHYSICAL_ADDRESS KernelParamsAddress,\r
- IN UINTN KernelParamsSize,\r
- IN UINT32 MachineType\r
- )\r
-{\r
- EFI_STATUS Status;\r
- LINUX_KERNEL LinuxKernel;\r
-\r
- // Shut down UEFI boot services. ExitBootServices() will notify every driver that created an event on\r
- // ExitBootServices event. Example the Interrupt DXE driver will disable the interrupts on this event.\r
- Status = ShutdownUefiBootServices ();\r
- if(EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR,"ERROR: Can not shutdown UEFI boot services. Status=0x%X\n", Status));\r
- goto Exit;\r
- }\r
-\r
- // Move the kernel parameters to any address inside the first 1MB.\r
- // This is necessary because the ARM Linux kernel requires\r
- // the FTD / ATAG List to reside entirely inside the first 1MB of\r
- // physical memory.\r
- //Note: There is no requirement on the alignment\r
- if (MachineType != ARM_FDT_MACHINE_TYPE) {\r
- if (((UINTN)KernelParamsAddress > LINUX_ATAG_MAX_OFFSET) && (KernelParamsSize < PcdGet32(PcdArmLinuxAtagMaxOffset))) {\r
- KernelParamsAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CopyMem (ALIGN32_BELOW(LINUX_ATAG_MAX_OFFSET - KernelParamsSize), (VOID*)(UINTN)KernelParamsAddress, KernelParamsSize);\r
- }\r
- } else {\r
- if (((UINTN)KernelParamsAddress > LINUX_FDT_MAX_OFFSET) && (KernelParamsSize < PcdGet32(PcdArmLinuxFdtMaxOffset))) {\r
- KernelParamsAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CopyMem (ALIGN32_BELOW(LINUX_FDT_MAX_OFFSET - KernelParamsSize), (VOID*)(UINTN)KernelParamsAddress, KernelParamsSize);\r
- }\r
- }\r
-\r
- if ((UINTN)LinuxImage > LINUX_KERNEL_MAX_OFFSET) {\r
- //Note: There is no requirement on the alignment\r
- LinuxKernel = (LINUX_KERNEL)CopyMem (ALIGN32_BELOW(LINUX_KERNEL_MAX_OFFSET - LinuxImageSize), (VOID*)(UINTN)LinuxImage, LinuxImageSize);\r
- } else {\r
- LinuxKernel = (LINUX_KERNEL)(UINTN)LinuxImage;\r
- }\r
-\r
- // Check if the Linux Image is a uImage\r
- if (*(UINT32*)LinuxKernel == LINUX_UIMAGE_SIGNATURE) {\r
- // Assume the Image Entry Point is just after the uImage header (64-byte size)\r
- LinuxKernel = (LINUX_KERNEL)((UINTN)LinuxKernel + 64);\r
- LinuxImageSize -= 64;\r
- }\r
-\r
- //TODO: Check there is no overlapping between kernel and Atag\r
-\r
- //\r
- // Switch off interrupts, caches, mmu, etc\r
- //\r
- Status = PreparePlatformHardware ();\r
- ASSERT_EFI_ERROR(Status);\r
-\r
- // Register and print out performance information\r
- PERF_END (NULL, "BDS", NULL, 0);\r
- if (PerformanceMeasurementEnabled ()) {\r
- PrintPerformance ();\r
- }\r
-\r
- //\r
- // Start the Linux Kernel\r
- //\r
-\r
- // Outside BootServices, so can't use Print();\r
- DEBUG((EFI_D_ERROR, "\nStarting the kernel:\n\n"));\r
-\r
- // Jump to kernel with register set\r
- LinuxKernel ((UINTN)0, MachineType, (UINTN)KernelParamsAddress);\r
-\r
- // Kernel should never exit\r
- // After Life services are not provided\r
- ASSERT(FALSE);\r
-\r
-Exit:\r
- // Only be here if we fail to start Linux\r
- Print (L"ERROR : Can not start the kernel. Status=0x%X\n", Status);\r
-\r
- // Free Runtimee Memory (kernel and FDT)\r
- return Status;\r
-}\r
-\r
-/**\r
- Start a Linux kernel from a Device Path\r
-\r
- @param LinuxKernel Device Path to the Linux Kernel\r
- @param Parameters Linux kernel arguments\r
- @param Fdt Device Path to the Flat Device Tree\r
-\r
- @retval EFI_SUCCESS All drivers have been connected\r
- @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.\r
-\r
-**/\r
-EFI_STATUS\r
-BdsBootLinuxAtag (\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN CONST CHAR8* CommandLineArguments\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 LinuxImageSize;\r
- UINT32 InitrdImageSize = 0;\r
- UINT32 AtagSize;\r
- EFI_PHYSICAL_ADDRESS AtagBase;\r
- EFI_PHYSICAL_ADDRESS LinuxImage;\r
- EFI_PHYSICAL_ADDRESS InitrdImage;\r
-\r
- PERF_START (NULL, "BDS", NULL, 0);\r
-\r
- // Load the Linux kernel from a device path\r
- LinuxImage = LINUX_KERNEL_MAX_OFFSET;\r
- Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);\r
- if (EFI_ERROR(Status)) {\r
- Print (L"ERROR: Did not find Linux kernel.\n");\r
- return Status;\r
- }\r
-\r
- if (InitrdDevicePath) {\r
- // Load the initrd near to the Linux kernel\r
- InitrdImage = LINUX_KERNEL_MAX_OFFSET;\r
- Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, &InitrdImageSize);\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize);\r
- }\r
- if (EFI_ERROR(Status)) {\r
- Print (L"ERROR: Did not find initrd image.\n");\r
- return Status;\r
- }\r
- \r
- // Check if the initrd is a uInitrd\r
- if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {\r
- // Skip the 64-byte image header\r
- InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);\r
- InitrdImageSize -= 64;\r
- }\r
- }\r
-\r
- //\r
- // Setup the Linux Kernel Parameters\r
- //\r
- \r
- // By setting address=0 we leave the memory allocation to the function\r
- Status = PrepareAtagList (CommandLineArguments, InitrdImage, InitrdImageSize, &AtagBase, &AtagSize);\r
- if (EFI_ERROR(Status)) {\r
- Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", Status);\r
- return Status;\r
- }\r
-\r
- return StartLinux (LinuxImage, LinuxImageSize, AtagBase, AtagSize, PcdGet32(PcdArmMachineType));\r
-}\r
-\r
-/**\r
- Start a Linux kernel from a Device Path\r
-\r
- @param LinuxKernel Device Path to the Linux Kernel\r
- @param Parameters Linux kernel arguments\r
- @param Fdt Device Path to the Flat Device Tree\r
-\r
- @retval EFI_SUCCESS All drivers have been connected\r
- @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found\r
- @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.\r
-\r
-**/\r
-EFI_STATUS\r
-BdsBootLinuxFdt (\r
- IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,\r
- IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,\r
- IN CONST CHAR8* CommandLineArguments,\r
- IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 LinuxImageSize;\r
- UINT32 InitrdImageSize = 0;\r
- UINT32 FdtBlobSize;\r
- EFI_PHYSICAL_ADDRESS FdtBlobBase;\r
- EFI_PHYSICAL_ADDRESS LinuxImage;\r
- EFI_PHYSICAL_ADDRESS InitrdImage;\r
-\r
- PERF_START (NULL, "BDS", NULL, 0);\r
-\r
- // Load the Linux kernel from a device path\r
- LinuxImage = LINUX_KERNEL_MAX_OFFSET;\r
- Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);\r
- if (EFI_ERROR(Status)) {\r
- Print (L"ERROR: Did not find Linux kernel.\n");\r
- return Status;\r
- }\r
-\r
- if (InitrdDevicePath) {\r
- InitrdImage = LINUX_KERNEL_MAX_OFFSET;\r
- Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, &InitrdImageSize);\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize);\r
- }\r
- if (EFI_ERROR(Status)) {\r
- Print (L"ERROR: Did not find initrd image.\n");\r
- return Status;\r
- }\r
-\r
- // Check if the initrd is a uInitrd\r
- if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {\r
- // Skip the 64-byte image header\r
- InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);\r
- InitrdImageSize -= 64;\r
- }\r
- }\r
-\r
- // Load the FDT binary from a device path. The FDT will be reloaded later to a more appropriate location for the Linux kernel.\r
- FdtBlobBase = 0;\r
- Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);\r
- if (EFI_ERROR(Status)) {\r
- Print (L"ERROR: Did not find Device Tree blob.\n");\r
- return Status;\r
- }\r
-\r
- // Update the Fdt with the Initrd information. The FDT will increase in size.\r
- // By setting address=0 we leave the memory allocation to the function\r
- Status = PrepareFdt (CommandLineArguments, InitrdImage, InitrdImageSize, &FdtBlobBase, &FdtBlobSize);\r
- if (EFI_ERROR(Status)) {\r
- Print(L"ERROR: Can not load kernel with FDT. Status=%r\n", Status);\r
- return Status;\r
- }\r
-\r
- return StartLinux (LinuxImage, LinuxImageSize, FdtBlobBase, FdtBlobSize, ARM_FDT_MACHINE_TYPE);\r
-}\r
-\r
--- /dev/null
+#------------------------------------------------------------------------------\r
+#\r
+# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
+# Copyright (c) 2011 - 2012, ARM Ltd. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#------------------------------------------------------------------------------\r
+\r
+#include <Library/PcdLib.h>\r
+\r
+/*\r
+\r
+This is the stack constructed by the exception handler (low address to high address)\r
+ # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM\r
+ Reg Offset\r
+ === ======\r
+ R0 0x00 # stmfd SP!,{R0-R12}\r
+ R1 0x04\r
+ R2 0x08\r
+ R3 0x0c\r
+ R4 0x10\r
+ R5 0x14\r
+ R6 0x18\r
+ R7 0x1c\r
+ R8 0x20\r
+ R9 0x24\r
+ R10 0x28\r
+ R11 0x2c\r
+ R12 0x30\r
+ SP 0x34 # reserved via adding 0x20 (32) to the SP\r
+ LR 0x38\r
+ PC 0x3c\r
+ CPSR 0x40\r
+ DFSR 0x44\r
+ DFAR 0x48\r
+ IFSR 0x4c\r
+ IFAR 0x50\r
+\r
+ LR 0x54 # SVC Link register (we need to restore it)\r
+\r
+ LR 0x58 # pushed by srsfd\r
+ CPSR 0x5c\r
+\r
+ */\r
+\r
+GCC_ASM_EXPORT(DebugAgentVectorTable)\r
+GCC_ASM_IMPORT(DefaultExceptionHandler)\r
+\r
+.text\r
+#if !defined(__APPLE__)\r
+.fpu neon @ makes vpush/vpop assemble\r
+#endif\r
+.align 5\r
+\r
+\r
+//\r
+// This code gets copied to the ARM vector table\r
+// ExceptionHandlersStart - ExceptionHandlersEnd gets copied\r
+//\r
+ASM_PFX(DebugAgentVectorTable):\r
+ b ASM_PFX(ResetEntry)\r
+ b ASM_PFX(UndefinedInstructionEntry)\r
+ b ASM_PFX(SoftwareInterruptEntry)\r
+ b ASM_PFX(PrefetchAbortEntry)\r
+ b ASM_PFX(DataAbortEntry)\r
+ b ASM_PFX(ReservedExceptionEntry)\r
+ b ASM_PFX(IrqEntry)\r
+ b ASM_PFX(FiqEntry)\r
+\r
+ASM_PFX(ResetEntry):\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ @ We are already in SVC mode\r
+\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+ \r
+ mov R0,#0 @ ExceptionType\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(UndefinedInstructionEntry):\r
+ sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ cps #0x13 @ Switch to SVC for common stack\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#1 @ ExceptionType\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(SoftwareInterruptEntry):\r
+ sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ @ We are already in SVC mode\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#2 @ ExceptionType\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(PrefetchAbortEntry):\r
+ sub LR,LR,#4\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ cps #0x13 @ Switch to SVC for common stack\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#3 @ ExceptionType\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(DataAbortEntry):\r
+ sub LR,LR,#8\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ cps #0x13 @ Switch to SVC for common stack\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#4\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(ReservedExceptionEntry):\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ cps #0x13 @ Switch to SVC for common stack\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#5\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(IrqEntry):\r
+ sub LR,LR,#4\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ cps #0x13 @ Switch to SVC for common stack\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+\r
+ mov R0,#6 @ ExceptionType\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+ASM_PFX(FiqEntry):\r
+ sub LR,LR,#4\r
+ srsdb #0x13! @ Store return state on SVC stack\r
+ cps #0x13 @ Switch to SVC for common stack\r
+ stmfd SP!,{LR} @ Store the link register for the current mode\r
+ sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} @ Store the register state\r
+ @ Since we have already switch to SVC R8_fiq - R12_fiq\r
+ @ never get used or saved\r
+ mov R0,#7 @ ExceptionType\r
+ ldr R1,ASM_PFX(CommonExceptionEntry)\r
+ bx R1\r
+\r
+//\r
+// This gets patched by the C code that patches in the vector table\r
+//\r
+ASM_PFX(CommonExceptionEntry):\r
+ .word ASM_PFX(AsmCommonExceptionEntry)\r
+\r
+ASM_PFX(ExceptionHandlersEnd):\r
+\r
+//\r
+// This code runs from CpuDxe driver loaded address. It is patched into\r
+// CommonExceptionEntry.\r
+//\r
+ASM_PFX(AsmCommonExceptionEntry):\r
+ mrc p15, 0, R1, c6, c0, 2 @ Read IFAR\r
+ str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR\r
+\r
+ mrc p15, 0, R1, c5, c0, 1 @ Read IFSR\r
+ str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR\r
+\r
+ mrc p15, 0, R1, c6, c0, 0 @ Read DFAR\r
+ str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR\r
+\r
+ mrc p15, 0, R1, c5, c0, 0 @ Read DFSR\r
+ str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR\r
+\r
+ ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack\r
+ str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR\r
+\r
+ add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
+ and R3, R1, #0x1f @ Check CPSR to see if User or System Mode\r
+ cmp R3, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1df))\r
+ cmpne R3, #0x10 @\r
+ stmeqed R2, {lr}^ @ save unbanked lr\r
+ @ else\r
+ stmneed R2, {lr} @ save SVC lr\r
+\r
+\r
+ ldr R5, [SP, #0x58] @ PC is the LR pushed by srsfd\r
+ @ Check to see if we have to adjust for Thumb entry\r
+ sub r4, r0, #1 @ if (ExceptionType == 1 || ExceptionType ==2)) {\r
+ cmp r4, #1 @ // UND & SVC have differnt LR adjust for Thumb\r
+ bhi NoAdjustNeeded\r
+\r
+ tst r1, #0x20 @ if ((CPSR & T)) == T) { // Thumb Mode on entry\r
+ addne R5, R5, #2 @ PC += 2@\r
+ str R5,[SP,#0x58] @ Update LR value pused by srsfd\r
+\r
+NoAdjustNeeded:\r
+\r
+ str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC\r
+\r
+ sub R1, SP, #0x60 @ We pused 0x60 bytes on the stack\r
+ str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP\r
+\r
+ @ R0 is ExceptionType\r
+ mov R1,SP @ R1 is SystemContext\r
+\r
+#if (FixedPcdGet32(PcdVFPEnabled))\r
+ vpush {d0-d15} @ save vstm registers in case they are used in optimizations\r
+#endif\r
+\r
+/*\r
+VOID\r
+EFIAPI\r
+DefaultExceptionHandler (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType, R0\r
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext R1\r
+ )\r
+\r
+*/\r
+ blx ASM_PFX(DefaultExceptionHandler) @ Call exception handler\r
+\r
+#if (FixedPcdGet32(PcdVFPEnabled))\r
+ vpop {d0-d15}\r
+#endif\r
+\r
+ ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR\r
+ mcr p15, 0, R1, c5, c0, 1 @ Write IFSR\r
+\r
+ ldr R1, [SP, #0x44] @ sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR\r
+ mcr p15, 0, R1, c5, c0, 0 @ Write DFSR\r
+\r
+ ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC\r
+ str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored\r
+\r
+ ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR\r
+ str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored\r
+\r
+ add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry\r
+ add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
+ and R1, R1, #0x1f @ Check to see if User or System Mode\r
+ cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))\r
+ cmpne R1, #0x10 @\r
+ ldmeqed R2, {lr}^ @ restore unbanked lr\r
+ @ else\r
+ ldmneed R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}\r
+\r
+ ldmfd SP!,{R0-R12} @ Restore general purpose registers\r
+ @ Exception handler can not change SP\r
+\r
+ add SP,SP,#0x20 @ Clear out the remaining stack space\r
+ ldmfd SP!,{LR} @ restore the link register for this context\r
+ rfefd SP! @ return from exception via srsfd stack slot\r
+\r
--- /dev/null
+//------------------------------------------------------------------------------\r
+//\r
+// Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
+// Copyright (c) 2011 - 2012, ARM Ltd. All rights reserved.<BR>\r
+//\r
+// This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions of the BSD License\r
+// which accompanies this distribution. The full text of the license may be found at\r
+// http://opensource.org/licenses/bsd-license.php\r
+//\r
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+//\r
+//------------------------------------------------------------------------------\r
+\r
+#include <Library/PcdLib.h>\r
+\r
+/*\r
+\r
+This is the stack constructed by the exception handler (low address to high address)\r
+ # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM\r
+ Reg Offset\r
+ === ======\r
+ R0 0x00 # stmfd SP!,{R0-R12}\r
+ R1 0x04\r
+ R2 0x08\r
+ R3 0x0c\r
+ R4 0x10\r
+ R5 0x14\r
+ R6 0x18\r
+ R7 0x1c\r
+ R8 0x20\r
+ R9 0x24\r
+ R10 0x28\r
+ R11 0x2c\r
+ R12 0x30\r
+ SP 0x34 # reserved via adding 0x20 (32) to the SP\r
+ LR 0x38\r
+ PC 0x3c\r
+ CPSR 0x40\r
+ DFSR 0x44\r
+ DFAR 0x48\r
+ IFSR 0x4c\r
+ IFAR 0x50\r
+\r
+ LR 0x54 # SVC Link register (we need to restore it)\r
+ \r
+ LR 0x58 # pushed by srsfd\r
+ CPSR 0x5c\r
+\r
+ */\r
+\r
+ EXPORT DebugAgentVectorTable\r
+ IMPORT DefaultExceptionHandler\r
+\r
+ PRESERVE8\r
+ AREA DebugAgentException, CODE, READONLY, CODEALIGN, ALIGN=5\r
+\r
+//\r
+// This code gets copied to the ARM vector table\r
+// ExceptionHandlersStart - ExceptionHandlersEnd gets copied\r
+//\r
+DebugAgentVectorTable FUNCTION\r
+ b ResetEntry\r
+ b UndefinedInstructionEntry\r
+ b SoftwareInterruptEntry\r
+ b PrefetchAbortEntry\r
+ b DataAbortEntry\r
+ b ReservedExceptionEntry\r
+ b IrqEntry\r
+ b FiqEntry\r
+ ENDFUNC\r
+\r
+ResetEntry\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ ; We are already in SVC mode\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+ \r
+ mov R0,#0 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+UndefinedInstructionEntry\r
+ sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ cps #0x13 ; Switch to SVC for common stack\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#1 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry;\r
+ bx R1\r
+\r
+SoftwareInterruptEntry\r
+ sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ ; We are already in SVC mode\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#2 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+PrefetchAbortEntry\r
+ sub LR,LR,#4\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ cps #0x13 ; Switch to SVC for common stack\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#3 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+DataAbortEntry\r
+ sub LR,LR,#8\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ cps #0x13 ; Switch to SVC for common stack\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#4 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+ReservedExceptionEntry\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ cps #0x13 ; Switch to SVC for common stack\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#5 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+IrqEntry\r
+ sub LR,LR,#4\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ cps #0x13 ; Switch to SVC for common stack\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+\r
+ mov R0,#6 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+FiqEntry\r
+ sub LR,LR,#4\r
+ srsfd #0x13! ; Store return state on SVC stack\r
+ cps #0x13 ; Switch to SVC for common stack\r
+ stmfd SP!,{LR} ; Store the link register for the current mode\r
+ sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
+ stmfd SP!,{R0-R12} ; Store the register state\r
+ ; Since we have already switch to SVC R8_fiq - R12_fiq\r
+ ; never get used or saved\r
+ mov R0,#7 ; ExceptionType\r
+ ldr R1,CommonExceptionEntry\r
+ bx R1\r
+\r
+//\r
+// This gets patched by the C code that patches in the vector table\r
+//\r
+CommonExceptionEntry\r
+ dcd AsmCommonExceptionEntry\r
+\r
+ExceptionHandlersEnd\r
+\r
+//\r
+// This code runs from CpuDxe driver loaded address. It is patched into\r
+// CommonExceptionEntry.\r
+//\r
+AsmCommonExceptionEntry\r
+ mrc p15, 0, R1, c6, c0, 2 ; Read IFAR\r
+ str R1, [SP, #0x50] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR\r
+\r
+ mrc p15, 0, R1, c5, c0, 1 ; Read IFSR\r
+ str R1, [SP, #0x4c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR\r
+\r
+ mrc p15, 0, R1, c6, c0, 0 ; Read DFAR\r
+ str R1, [SP, #0x48] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR\r
+\r
+ mrc p15, 0, R1, c5, c0, 0 ; Read DFSR\r
+ str R1, [SP, #0x44] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR\r
+\r
+ ldr R1, [SP, #0x5c] ; srsfd saved pre-exception CPSR on the stack\r
+ str R1, [SP, #0x40] ; Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR\r
+\r
+ add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
+ and R3, R1, #0x1f ; Check CPSR to see if User or System Mode\r
+ cmp R3, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1df))\r
+ cmpne R3, #0x10 ;\r
+ stmeqed R2, {lr}^ ; save unbanked lr\r
+ ; else\r
+ stmneed R2, {lr} ; save SVC lr\r
+\r
+\r
+ ldr R5, [SP, #0x58] ; PC is the LR pushed by srsfd\r
+ ; Check to see if we have to adjust for Thumb entry\r
+ sub r4, r0, #1 ; if (ExceptionType == 1 || ExceptionType ==2)) {\r
+ cmp r4, #1 ; // UND & SVC have differnt LR adjust for Thumb\r
+ bhi NoAdjustNeeded\r
+\r
+ tst r1, #0x20 ; if ((CPSR & T)) == T) { // Thumb Mode on entry\r
+ addne R5, R5, #2 ; PC += 2;\r
+ str R5,[SP,#0x58] ; Update LR value pused by srsfd\r
+\r
+NoAdjustNeeded\r
+\r
+ str R5, [SP, #0x3c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.PC\r
+\r
+ sub R1, SP, #0x60 ; We pused 0x60 bytes on the stack\r
+ str R1, [SP, #0x34] ; Store it in EFI_SYSTEM_CONTEXT_ARM.SP\r
+\r
+ ; R0 is ExceptionType\r
+ mov R1,SP ; R1 is SystemContext\r
+\r
+#if (FixedPcdGet32(PcdVFPEnabled))\r
+ vpush {d0-d15} ; save vstm registers in case they are used in optimizations\r
+#endif\r
+\r
+/*\r
+VOID\r
+EFIAPI\r
+DefaultExceptionHandler (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType, R0\r
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext R1\r
+ )\r
+\r
+*/\r
+ blx DefaultExceptionHandler ; Call exception handler\r
+\r
+#if (FixedPcdGet32(PcdVFPEnabled))\r
+ vpop {d0-d15}\r
+#endif\r
+\r
+ ldr R1, [SP, #0x4c] ; Restore EFI_SYSTEM_CONTEXT_ARM.IFSR\r
+ mcr p15, 0, R1, c5, c0, 1 ; Write IFSR\r
+\r
+ ldr R1, [SP, #0x44] ; sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR\r
+ mcr p15, 0, R1, c5, c0, 0 ; Write DFSR\r
+\r
+ ldr R1,[SP,#0x3c] ; EFI_SYSTEM_CONTEXT_ARM.PC\r
+ str R1,[SP,#0x58] ; Store it back to srsfd stack slot so it can be restored\r
+\r
+ ldr R1,[SP,#0x40] ; EFI_SYSTEM_CONTEXT_ARM.CPSR\r
+ str R1,[SP,#0x5c] ; Store it back to srsfd stack slot so it can be restored\r
+\r
+ add R3, SP, #0x54 ; Make R3 point to SVC LR saved on entry\r
+ add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
+ and R1, R1, #0x1f ; Check to see if User or System Mode\r
+ cmp R1, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1f))\r
+ cmpne R1, #0x10 ;\r
+ ldmeqed R2, {lr}^ ; restore unbanked lr\r
+ ; else\r
+ ldmneed R3, {lr} ; restore SVC lr, via ldmfd SP!, {LR}\r
+\r
+ ldmfd SP!,{R0-R12} ; Restore general purpose registers\r
+ ; Exception handler can not change SP\r
+\r
+ add SP,SP,#0x20 ; Clear out the remaining stack space\r
+ ldmfd SP!,{LR} ; restore the link register for this context\r
+ rfefd SP! ; return from exception via srsfd stack slot\r
+\r
+ END\r
+++ /dev/null
-#------------------------------------------------------------------------------\r
-#\r
-# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
-# Copyright (c) 2011 - 2012, ARM Ltd. All rights reserved.<BR>\r
-#\r
-# This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this distribution. The full text of the license may be found at\r
-# http://opensource.org/licenses/bsd-license.php\r
-#\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#\r
-#------------------------------------------------------------------------------\r
-\r
-#include <Library/PcdLib.h>\r
-\r
-/*\r
-\r
-This is the stack constructed by the exception handler (low address to high address)\r
- # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM\r
- Reg Offset\r
- === ======\r
- R0 0x00 # stmfd SP!,{R0-R12}\r
- R1 0x04\r
- R2 0x08\r
- R3 0x0c\r
- R4 0x10\r
- R5 0x14\r
- R6 0x18\r
- R7 0x1c\r
- R8 0x20\r
- R9 0x24\r
- R10 0x28\r
- R11 0x2c\r
- R12 0x30\r
- SP 0x34 # reserved via adding 0x20 (32) to the SP\r
- LR 0x38\r
- PC 0x3c\r
- CPSR 0x40\r
- DFSR 0x44\r
- DFAR 0x48\r
- IFSR 0x4c\r
- IFAR 0x50\r
-\r
- LR 0x54 # SVC Link register (we need to restore it)\r
-\r
- LR 0x58 # pushed by srsfd\r
- CPSR 0x5c\r
-\r
- */\r
-\r
-GCC_ASM_EXPORT(DebugAgentVectorTable)\r
-GCC_ASM_IMPORT(DefaultExceptionHandler)\r
-\r
-.text\r
-#if !defined(__APPLE__)\r
-.fpu neon @ makes vpush/vpop assemble\r
-#endif\r
-.align 5\r
-\r
-\r
-//\r
-// This code gets copied to the ARM vector table\r
-// ExceptionHandlersStart - ExceptionHandlersEnd gets copied\r
-//\r
-ASM_PFX(DebugAgentVectorTable):\r
- b ASM_PFX(ResetEntry)\r
- b ASM_PFX(UndefinedInstructionEntry)\r
- b ASM_PFX(SoftwareInterruptEntry)\r
- b ASM_PFX(PrefetchAbortEntry)\r
- b ASM_PFX(DataAbortEntry)\r
- b ASM_PFX(ReservedExceptionEntry)\r
- b ASM_PFX(IrqEntry)\r
- b ASM_PFX(FiqEntry)\r
-\r
-ASM_PFX(ResetEntry):\r
- srsdb #0x13! @ Store return state on SVC stack\r
- @ We are already in SVC mode\r
-\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
- \r
- mov R0,#0 @ ExceptionType\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-ASM_PFX(UndefinedInstructionEntry):\r
- sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry\r
- srsdb #0x13! @ Store return state on SVC stack\r
- cps #0x13 @ Switch to SVC for common stack\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
-\r
- mov R0,#1 @ ExceptionType\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-ASM_PFX(SoftwareInterruptEntry):\r
- sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry\r
- srsdb #0x13! @ Store return state on SVC stack\r
- @ We are already in SVC mode\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
-\r
- mov R0,#2 @ ExceptionType\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-ASM_PFX(PrefetchAbortEntry):\r
- sub LR,LR,#4\r
- srsdb #0x13! @ Store return state on SVC stack\r
- cps #0x13 @ Switch to SVC for common stack\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
-\r
- mov R0,#3 @ ExceptionType\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-ASM_PFX(DataAbortEntry):\r
- sub LR,LR,#8\r
- srsdb #0x13! @ Store return state on SVC stack\r
- cps #0x13 @ Switch to SVC for common stack\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
-\r
- mov R0,#4\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-ASM_PFX(ReservedExceptionEntry):\r
- srsdb #0x13! @ Store return state on SVC stack\r
- cps #0x13 @ Switch to SVC for common stack\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
-\r
- mov R0,#5\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-ASM_PFX(IrqEntry):\r
- sub LR,LR,#4\r
- srsdb #0x13! @ Store return state on SVC stack\r
- cps #0x13 @ Switch to SVC for common stack\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
-\r
- mov R0,#6 @ ExceptionType\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-ASM_PFX(FiqEntry):\r
- sub LR,LR,#4\r
- srsdb #0x13! @ Store return state on SVC stack\r
- cps #0x13 @ Switch to SVC for common stack\r
- stmfd SP!,{LR} @ Store the link register for the current mode\r
- sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} @ Store the register state\r
- @ Since we have already switch to SVC R8_fiq - R12_fiq\r
- @ never get used or saved\r
- mov R0,#7 @ ExceptionType\r
- ldr R1,ASM_PFX(CommonExceptionEntry)\r
- bx R1\r
-\r
-//\r
-// This gets patched by the C code that patches in the vector table\r
-//\r
-ASM_PFX(CommonExceptionEntry):\r
- .word ASM_PFX(AsmCommonExceptionEntry)\r
-\r
-ASM_PFX(ExceptionHandlersEnd):\r
-\r
-//\r
-// This code runs from CpuDxe driver loaded address. It is patched into\r
-// CommonExceptionEntry.\r
-//\r
-ASM_PFX(AsmCommonExceptionEntry):\r
- mrc p15, 0, R1, c6, c0, 2 @ Read IFAR\r
- str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR\r
-\r
- mrc p15, 0, R1, c5, c0, 1 @ Read IFSR\r
- str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR\r
-\r
- mrc p15, 0, R1, c6, c0, 0 @ Read DFAR\r
- str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR\r
-\r
- mrc p15, 0, R1, c5, c0, 0 @ Read DFSR\r
- str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR\r
-\r
- ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack\r
- str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR\r
-\r
- add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
- and R3, R1, #0x1f @ Check CPSR to see if User or System Mode\r
- cmp R3, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1df))\r
- cmpne R3, #0x10 @\r
- stmeqed R2, {lr}^ @ save unbanked lr\r
- @ else\r
- stmneed R2, {lr} @ save SVC lr\r
-\r
-\r
- ldr R5, [SP, #0x58] @ PC is the LR pushed by srsfd\r
- @ Check to see if we have to adjust for Thumb entry\r
- sub r4, r0, #1 @ if (ExceptionType == 1 || ExceptionType ==2)) {\r
- cmp r4, #1 @ // UND & SVC have differnt LR adjust for Thumb\r
- bhi NoAdjustNeeded\r
-\r
- tst r1, #0x20 @ if ((CPSR & T)) == T) { // Thumb Mode on entry\r
- addne R5, R5, #2 @ PC += 2@\r
- str R5,[SP,#0x58] @ Update LR value pused by srsfd\r
-\r
-NoAdjustNeeded:\r
-\r
- str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC\r
-\r
- sub R1, SP, #0x60 @ We pused 0x60 bytes on the stack\r
- str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP\r
-\r
- @ R0 is ExceptionType\r
- mov R1,SP @ R1 is SystemContext\r
-\r
-#if (FixedPcdGet32(PcdVFPEnabled))\r
- vpush {d0-d15} @ save vstm registers in case they are used in optimizations\r
-#endif\r
-\r
-/*\r
-VOID\r
-EFIAPI\r
-DefaultExceptionHandler (\r
- IN EFI_EXCEPTION_TYPE ExceptionType, R0\r
- IN OUT EFI_SYSTEM_CONTEXT SystemContext R1\r
- )\r
-\r
-*/\r
- blx ASM_PFX(DefaultExceptionHandler) @ Call exception handler\r
-\r
-#if (FixedPcdGet32(PcdVFPEnabled))\r
- vpop {d0-d15}\r
-#endif\r
-\r
- ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR\r
- mcr p15, 0, R1, c5, c0, 1 @ Write IFSR\r
-\r
- ldr R1, [SP, #0x44] @ sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR\r
- mcr p15, 0, R1, c5, c0, 0 @ Write DFSR\r
-\r
- ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC\r
- str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored\r
-\r
- ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR\r
- str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored\r
-\r
- add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry\r
- add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
- and R1, R1, #0x1f @ Check to see if User or System Mode\r
- cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))\r
- cmpne R1, #0x10 @\r
- ldmeqed R2, {lr}^ @ restore unbanked lr\r
- @ else\r
- ldmneed R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}\r
-\r
- ldmfd SP!,{R0-R12} @ Restore general purpose registers\r
- @ Exception handler can not change SP\r
-\r
- add SP,SP,#0x20 @ Clear out the remaining stack space\r
- ldmfd SP!,{LR} @ restore the link register for this context\r
- rfefd SP! @ return from exception via srsfd stack slot\r
-\r
+++ /dev/null
-//------------------------------------------------------------------------------\r
-//\r
-// Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
-// Copyright (c) 2011 - 2012, ARM Ltd. All rights reserved.<BR>\r
-//\r
-// This program and the accompanying materials\r
-// are licensed and made available under the terms and conditions of the BSD License\r
-// which accompanies this distribution. The full text of the license may be found at\r
-// http://opensource.org/licenses/bsd-license.php\r
-//\r
-// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-//\r
-//------------------------------------------------------------------------------\r
-\r
-#include <Library/PcdLib.h>\r
-\r
-/*\r
-\r
-This is the stack constructed by the exception handler (low address to high address)\r
- # R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM\r
- Reg Offset\r
- === ======\r
- R0 0x00 # stmfd SP!,{R0-R12}\r
- R1 0x04\r
- R2 0x08\r
- R3 0x0c\r
- R4 0x10\r
- R5 0x14\r
- R6 0x18\r
- R7 0x1c\r
- R8 0x20\r
- R9 0x24\r
- R10 0x28\r
- R11 0x2c\r
- R12 0x30\r
- SP 0x34 # reserved via adding 0x20 (32) to the SP\r
- LR 0x38\r
- PC 0x3c\r
- CPSR 0x40\r
- DFSR 0x44\r
- DFAR 0x48\r
- IFSR 0x4c\r
- IFAR 0x50\r
-\r
- LR 0x54 # SVC Link register (we need to restore it)\r
- \r
- LR 0x58 # pushed by srsfd\r
- CPSR 0x5c\r
-\r
- */\r
-\r
- EXPORT DebugAgentVectorTable\r
- IMPORT DefaultExceptionHandler\r
-\r
- PRESERVE8\r
- AREA DebugAgentException, CODE, READONLY, CODEALIGN, ALIGN=5\r
-\r
-//\r
-// This code gets copied to the ARM vector table\r
-// ExceptionHandlersStart - ExceptionHandlersEnd gets copied\r
-//\r
-DebugAgentVectorTable FUNCTION\r
- b ResetEntry\r
- b UndefinedInstructionEntry\r
- b SoftwareInterruptEntry\r
- b PrefetchAbortEntry\r
- b DataAbortEntry\r
- b ReservedExceptionEntry\r
- b IrqEntry\r
- b FiqEntry\r
- ENDFUNC\r
-\r
-ResetEntry\r
- srsfd #0x13! ; Store return state on SVC stack\r
- ; We are already in SVC mode\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
- \r
- mov R0,#0 ; ExceptionType\r
- ldr R1,CommonExceptionEntry\r
- bx R1\r
-\r
-UndefinedInstructionEntry\r
- sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry\r
- srsfd #0x13! ; Store return state on SVC stack\r
- cps #0x13 ; Switch to SVC for common stack\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
-\r
- mov R0,#1 ; ExceptionType\r
- ldr R1,CommonExceptionEntry;\r
- bx R1\r
-\r
-SoftwareInterruptEntry\r
- sub LR, LR, #4 ; Only -2 for Thumb, adjust in CommonExceptionEntry\r
- srsfd #0x13! ; Store return state on SVC stack\r
- ; We are already in SVC mode\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
-\r
- mov R0,#2 ; ExceptionType\r
- ldr R1,CommonExceptionEntry\r
- bx R1\r
-\r
-PrefetchAbortEntry\r
- sub LR,LR,#4\r
- srsfd #0x13! ; Store return state on SVC stack\r
- cps #0x13 ; Switch to SVC for common stack\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
-\r
- mov R0,#3 ; ExceptionType\r
- ldr R1,CommonExceptionEntry\r
- bx R1\r
-\r
-DataAbortEntry\r
- sub LR,LR,#8\r
- srsfd #0x13! ; Store return state on SVC stack\r
- cps #0x13 ; Switch to SVC for common stack\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
-\r
- mov R0,#4 ; ExceptionType\r
- ldr R1,CommonExceptionEntry\r
- bx R1\r
-\r
-ReservedExceptionEntry\r
- srsfd #0x13! ; Store return state on SVC stack\r
- cps #0x13 ; Switch to SVC for common stack\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
-\r
- mov R0,#5 ; ExceptionType\r
- ldr R1,CommonExceptionEntry\r
- bx R1\r
-\r
-IrqEntry\r
- sub LR,LR,#4\r
- srsfd #0x13! ; Store return state on SVC stack\r
- cps #0x13 ; Switch to SVC for common stack\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
-\r
- mov R0,#6 ; ExceptionType\r
- ldr R1,CommonExceptionEntry\r
- bx R1\r
-\r
-FiqEntry\r
- sub LR,LR,#4\r
- srsfd #0x13! ; Store return state on SVC stack\r
- cps #0x13 ; Switch to SVC for common stack\r
- stmfd SP!,{LR} ; Store the link register for the current mode\r
- sub SP,SP,#0x20 ; Save space for SP, LR, PC, IFAR - CPSR\r
- stmfd SP!,{R0-R12} ; Store the register state\r
- ; Since we have already switch to SVC R8_fiq - R12_fiq\r
- ; never get used or saved\r
- mov R0,#7 ; ExceptionType\r
- ldr R1,CommonExceptionEntry\r
- bx R1\r
-\r
-//\r
-// This gets patched by the C code that patches in the vector table\r
-//\r
-CommonExceptionEntry\r
- dcd AsmCommonExceptionEntry\r
-\r
-ExceptionHandlersEnd\r
-\r
-//\r
-// This code runs from CpuDxe driver loaded address. It is patched into\r
-// CommonExceptionEntry.\r
-//\r
-AsmCommonExceptionEntry\r
- mrc p15, 0, R1, c6, c0, 2 ; Read IFAR\r
- str R1, [SP, #0x50] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR\r
-\r
- mrc p15, 0, R1, c5, c0, 1 ; Read IFSR\r
- str R1, [SP, #0x4c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR\r
-\r
- mrc p15, 0, R1, c6, c0, 0 ; Read DFAR\r
- str R1, [SP, #0x48] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR\r
-\r
- mrc p15, 0, R1, c5, c0, 0 ; Read DFSR\r
- str R1, [SP, #0x44] ; Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR\r
-\r
- ldr R1, [SP, #0x5c] ; srsfd saved pre-exception CPSR on the stack\r
- str R1, [SP, #0x40] ; Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR\r
-\r
- add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
- and R3, R1, #0x1f ; Check CPSR to see if User or System Mode\r
- cmp R3, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1df))\r
- cmpne R3, #0x10 ;\r
- stmeqed R2, {lr}^ ; save unbanked lr\r
- ; else\r
- stmneed R2, {lr} ; save SVC lr\r
-\r
-\r
- ldr R5, [SP, #0x58] ; PC is the LR pushed by srsfd\r
- ; Check to see if we have to adjust for Thumb entry\r
- sub r4, r0, #1 ; if (ExceptionType == 1 || ExceptionType ==2)) {\r
- cmp r4, #1 ; // UND & SVC have differnt LR adjust for Thumb\r
- bhi NoAdjustNeeded\r
-\r
- tst r1, #0x20 ; if ((CPSR & T)) == T) { // Thumb Mode on entry\r
- addne R5, R5, #2 ; PC += 2;\r
- str R5,[SP,#0x58] ; Update LR value pused by srsfd\r
-\r
-NoAdjustNeeded\r
-\r
- str R5, [SP, #0x3c] ; Store it in EFI_SYSTEM_CONTEXT_ARM.PC\r
-\r
- sub R1, SP, #0x60 ; We pused 0x60 bytes on the stack\r
- str R1, [SP, #0x34] ; Store it in EFI_SYSTEM_CONTEXT_ARM.SP\r
-\r
- ; R0 is ExceptionType\r
- mov R1,SP ; R1 is SystemContext\r
-\r
-#if (FixedPcdGet32(PcdVFPEnabled))\r
- vpush {d0-d15} ; save vstm registers in case they are used in optimizations\r
-#endif\r
-\r
-/*\r
-VOID\r
-EFIAPI\r
-DefaultExceptionHandler (\r
- IN EFI_EXCEPTION_TYPE ExceptionType, R0\r
- IN OUT EFI_SYSTEM_CONTEXT SystemContext R1\r
- )\r
-\r
-*/\r
- blx DefaultExceptionHandler ; Call exception handler\r
-\r
-#if (FixedPcdGet32(PcdVFPEnabled))\r
- vpop {d0-d15}\r
-#endif\r
-\r
- ldr R1, [SP, #0x4c] ; Restore EFI_SYSTEM_CONTEXT_ARM.IFSR\r
- mcr p15, 0, R1, c5, c0, 1 ; Write IFSR\r
-\r
- ldr R1, [SP, #0x44] ; sRestore EFI_SYSTEM_CONTEXT_ARM.DFSR\r
- mcr p15, 0, R1, c5, c0, 0 ; Write DFSR\r
-\r
- ldr R1,[SP,#0x3c] ; EFI_SYSTEM_CONTEXT_ARM.PC\r
- str R1,[SP,#0x58] ; Store it back to srsfd stack slot so it can be restored\r
-\r
- ldr R1,[SP,#0x40] ; EFI_SYSTEM_CONTEXT_ARM.CPSR\r
- str R1,[SP,#0x5c] ; Store it back to srsfd stack slot so it can be restored\r
-\r
- add R3, SP, #0x54 ; Make R3 point to SVC LR saved on entry\r
- add R2, SP, #0x38 ; Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR\r
- and R1, R1, #0x1f ; Check to see if User or System Mode\r
- cmp R1, #0x1f ; if ((CPSR == 0x10) || (CPSR == 0x1f))\r
- cmpne R1, #0x10 ;\r
- ldmeqed R2, {lr}^ ; restore unbanked lr\r
- ; else\r
- ldmneed R3, {lr} ; restore SVC lr, via ldmfd SP!, {LR}\r
-\r
- ldmfd SP!,{R0-R12} ; Restore general purpose registers\r
- ; Exception handler can not change SP\r
-\r
- add SP,SP,#0x20 ; Clear out the remaining stack space\r
- ldmfd SP!,{LR} ; restore the link register for this context\r
- rfefd SP! ; return from exception via srsfd stack slot\r
-\r
- END\r
\r
[Sources.common]\r
DebugAgentSymbolsBaseLib.c\r
- DebugAgentException.asm | RVCT\r
- DebugAgentException.S | GCC\r
- \r
+\r
+[Sources.ARM]\r
+ Arm/DebugAgentException.asm | RVCT\r
+ Arm/DebugAgentException.S | GCC\r
+\r
[Packages]\r
MdePkg/MdePkg.dec\r
MdeModulePkg/MdeModulePkg.dec\r
--- /dev/null
+/** @file\r
+ Default exception handler\r
+\r
+ Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
+ Copyright (c) 2012, ARM Ltd. All rights reserved.<BR>\r
+ \r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/PrintLib.h>\r
+#include <Library/ArmDisassemblerLib.h>\r
+#include <Library/SerialPortLib.h>\r
+\r
+#include <Guid/DebugImageInfoTable.h>\r
+\r
+#include <Protocol/DebugSupport.h>\r
+#include <Library/DefaultExceptionHandlerLib.h>\r
+\r
+EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *gDebugImageTableHeader = NULL;\r
+\r
+typedef struct {\r
+ UINT32 BIT;\r
+ CHAR8 Char;\r
+} CPSR_CHAR;\r
+\r
+CHAR8 *\r
+GetImageName (\r
+ IN UINT32 FaultAddress,\r
+ OUT UINT32 *ImageBase,\r
+ OUT UINT32 *PeCoffSizeOfHeaders\r
+ );\r
+\r
+/**\r
+ Convert the Current Program Status Register (CPSR) to a string. The string is \r
+ a defacto standard in the ARM world. \r
+ \r
+ It is possible to add extra bits by adding them to CpsrChar array.\r
+\r
+ @param Cpsr ARM CPSR register value\r
+ @param ReturnStr 32 byte string that contains string version of CPSR\r
+\r
+**/\r
+VOID\r
+CpsrString (\r
+ IN UINT32 Cpsr,\r
+ OUT CHAR8 *ReturnStr\r
+ )\r
+{\r
+ UINTN Index;\r
+ CHAR8* Str;\r
+ CHAR8* ModeStr;\r
+ CPSR_CHAR CpsrChar[] = {\r
+ { 31, 'n' },\r
+ { 30, 'z' },\r
+ { 29, 'c' },\r
+ { 28, 'v' },\r
+\r
+ { 9, 'e' },\r
+ { 8, 'a' },\r
+ { 7, 'i' },\r
+ { 6, 'f' },\r
+ { 5, 't' },\r
+ { 0, '?' }\r
+ };\r
+ \r
+ Str = ReturnStr;\r
+\r
+ for (Index = 0; CpsrChar[Index].BIT != 0; Index++, Str++) {\r
+ *Str = CpsrChar[Index].Char;\r
+ if ((Cpsr & (1 << CpsrChar[Index].BIT)) != 0) {\r
+ // Concert to upper case if bit is set\r
+ *Str &= ~0x20;\r
+ }\r
+ }\r
+ \r
+ *Str++ = '_';\r
+ *Str = '\0';\r
+ \r
+ switch (Cpsr & 0x1f) {\r
+ case 0x10:\r
+ ModeStr = "usr";\r
+ break;\r
+ case 0x011:\r
+ ModeStr = "fiq";\r
+ break;\r
+ case 0x12:\r
+ ModeStr = "irq";\r
+ break;\r
+ case 0x13:\r
+ ModeStr = "svc";\r
+ break;\r
+ case 0x16:\r
+ ModeStr = "mon";\r
+ break;\r
+ case 0x17:\r
+ ModeStr = "abt";\r
+ break;\r
+ case 0x1b:\r
+ ModeStr = "und";\r
+ break;\r
+ case 0x1f:\r
+ ModeStr = "sys";\r
+ break;\r
+ \r
+ default:\r
+ ModeStr = "???";\r
+ break;\r
+ }\r
+ \r
+ AsciiStrCat (Str, ModeStr);\r
+ return;\r
+} \r
+\r
+CHAR8 *\r
+FaultStatusToString (\r
+ IN UINT32 Status\r
+ )\r
+{\r
+ CHAR8 *FaultSource;\r
+\r
+ switch (Status) {\r
+ case 0x01: FaultSource = "Alignment fault"; break;\r
+ case 0x02: FaultSource = "Debug event fault"; break;\r
+ case 0x03: FaultSource = "Access Flag fault on Section"; break;\r
+ case 0x04: FaultSource = "Cache maintenance operation fault[2]"; break;\r
+ case 0x05: FaultSource = "Translation fault on Section"; break;\r
+ case 0x06: FaultSource = "Access Flag fault on Page"; break;\r
+ case 0x07: FaultSource = "Translation fault on Page"; break;\r
+ case 0x08: FaultSource = "Precise External Abort"; break;\r
+ case 0x09: FaultSource = "Domain fault on Section"; break;\r
+ case 0x0b: FaultSource = "Domain fault on Page"; break;\r
+ case 0x0c: FaultSource = "External abort on translation, first level"; break;\r
+ case 0x0d: FaultSource = "Permission fault on Section"; break;\r
+ case 0x0e: FaultSource = "External abort on translation, second level"; break;\r
+ case 0x0f: FaultSource = "Permission fault on Page"; break;\r
+ case 0x16: FaultSource = "Imprecise External Abort"; break;\r
+ default: FaultSource = "No function"; break;\r
+ }\r
+\r
+ return FaultSource;\r
+}\r
+\r
+STATIC CHAR8 *gExceptionTypeString[] = {\r
+ "Reset",\r
+ "Undefined OpCode",\r
+ "SVC",\r
+ "Prefetch Abort",\r
+ "Data Abort",\r
+ "Undefined",\r
+ "IRQ",\r
+ "FIQ"\r
+};\r
+\r
+/**\r
+ This is the default action to take on an unexpected exception\r
+ \r
+ Since this is exception context don't do anything crazy like try to allcoate memory.\r
+\r
+ @param ExceptionType Type of the exception\r
+ @param SystemContext Register state at the time of the Exception\r
+\r
+\r
+**/\r
+VOID\r
+DefaultExceptionHandler (\r
+ IN EFI_EXCEPTION_TYPE ExceptionType,\r
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
+ )\r
+{\r
+ CHAR8 Buffer[100];\r
+ UINTN CharCount;\r
+ UINT32 DfsrStatus;\r
+ UINT32 IfsrStatus;\r
+ BOOLEAN DfsrWrite;\r
+ UINT32 PcAdjust = 0;\r
+\r
+ CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"\n%a Exception PC at 0x%08x CPSR 0x%08x ",\r
+ gExceptionTypeString[ExceptionType], SystemContext.SystemContextArm->PC, SystemContext.SystemContextArm->CPSR);\r
+ SerialPortWrite ((UINT8 *) Buffer, CharCount);\r
+\r
+ DEBUG_CODE_BEGIN ();\r
+ CHAR8 *Pdb;\r
+ UINT32 ImageBase;\r
+ UINT32 PeCoffSizeOfHeader;\r
+ UINT32 Offset;\r
+ CHAR8 CpsrStr[32]; // char per bit. Lower 5-bits are mode that is a 3 char string\r
+ CHAR8 Buffer[80];\r
+ UINT8 *DisAsm;\r
+ UINT32 ItBlock;\r
+ \r
+ CpsrString (SystemContext.SystemContextArm->CPSR, CpsrStr);\r
+ DEBUG ((EFI_D_ERROR, "%a\n", CpsrStr));\r
+ \r
+ Pdb = GetImageName (SystemContext.SystemContextArm->PC, &ImageBase, &PeCoffSizeOfHeader);\r
+ Offset = SystemContext.SystemContextArm->PC - ImageBase;\r
+ if (Pdb != NULL) {\r
+ DEBUG ((EFI_D_ERROR, "%a\n", Pdb));\r
+\r
+ //\r
+ // A PE/COFF image loads its headers into memory so the headers are \r
+ // included in the linked addresses. ELF and Mach-O images do not\r
+ // include the headers so the first byte of the image is usually\r
+ // text (code). If you look at link maps from ELF or Mach-O images\r
+ // you need to subtract out the size of the PE/COFF header to get\r
+ // get the offset that matches the link map. \r
+ //\r
+ DEBUG ((EFI_D_ERROR, "loaded at 0x%08x (PE/COFF offset) 0x%x (ELF or Mach-O offset) 0x%x", ImageBase, Offset, Offset - PeCoffSizeOfHeader));\r
+ \r
+ // If we come from an image it is safe to show the instruction. We know it should not fault\r
+ DisAsm = (UINT8 *)(UINTN)SystemContext.SystemContextArm->PC;\r
+ ItBlock = 0;\r
+ DisassembleInstruction (&DisAsm, (SystemContext.SystemContextArm->CPSR & BIT5) == BIT5, TRUE, &ItBlock, Buffer, sizeof (Buffer));\r
+ DEBUG ((EFI_D_ERROR, "\n%a", Buffer));\r
+ \r
+ switch (ExceptionType) {\r
+ case EXCEPT_ARM_UNDEFINED_INSTRUCTION:\r
+ case EXCEPT_ARM_SOFTWARE_INTERRUPT:\r
+ case EXCEPT_ARM_PREFETCH_ABORT:\r
+ case EXCEPT_ARM_DATA_ABORT:\r
+ // advance PC past the faulting instruction\r
+ PcAdjust = (UINTN)DisAsm - SystemContext.SystemContextArm->PC;\r
+ break;\r
+ \r
+ default:\r
+ break;\r
+ }\r
+\r
+ }\r
+ DEBUG_CODE_END ();\r
+ DEBUG ((EFI_D_ERROR, "\n R0 0x%08x R1 0x%08x R2 0x%08x R3 0x%08x\n", SystemContext.SystemContextArm->R0, SystemContext.SystemContextArm->R1, SystemContext.SystemContextArm->R2, SystemContext.SystemContextArm->R3));\r
+ DEBUG ((EFI_D_ERROR, " R4 0x%08x R5 0x%08x R6 0x%08x R7 0x%08x\n", SystemContext.SystemContextArm->R4, SystemContext.SystemContextArm->R5, SystemContext.SystemContextArm->R6, SystemContext.SystemContextArm->R7));\r
+ DEBUG ((EFI_D_ERROR, " R8 0x%08x R9 0x%08x R10 0x%08x R11 0x%08x\n", SystemContext.SystemContextArm->R8, SystemContext.SystemContextArm->R9, SystemContext.SystemContextArm->R10, SystemContext.SystemContextArm->R11));\r
+ DEBUG ((EFI_D_ERROR, " R12 0x%08x SP 0x%08x LR 0x%08x PC 0x%08x\n", SystemContext.SystemContextArm->R12, SystemContext.SystemContextArm->SP, SystemContext.SystemContextArm->LR, SystemContext.SystemContextArm->PC));\r
+ DEBUG ((EFI_D_ERROR, "DFSR 0x%08x DFAR 0x%08x IFSR 0x%08x IFAR 0x%08x\n", SystemContext.SystemContextArm->DFSR, SystemContext.SystemContextArm->DFAR, SystemContext.SystemContextArm->IFSR, SystemContext.SystemContextArm->IFAR));\r
+\r
+ // Bit10 is Status[4] Bit3:0 is Status[3:0]\r
+ DfsrStatus = (SystemContext.SystemContextArm->DFSR & 0xf) | ((SystemContext.SystemContextArm->DFSR >> 6) & 0x10);\r
+ DfsrWrite = (SystemContext.SystemContextArm->DFSR & BIT11) != 0;\r
+ if (DfsrStatus != 0x00) {\r
+ DEBUG ((EFI_D_ERROR, " %a: %a 0x%08x\n", FaultStatusToString (DfsrStatus), DfsrWrite ? "write to" : "read from", SystemContext.SystemContextArm->DFAR));\r
+ }\r
+\r
+ IfsrStatus = (SystemContext.SystemContextArm->IFSR & 0xf) | ((SystemContext.SystemContextArm->IFSR >> 6) & 0x10);\r
+ if (IfsrStatus != 0) {\r
+ DEBUG ((EFI_D_ERROR, " Instruction %a at 0x%08x\n", FaultStatusToString (SystemContext.SystemContextArm->IFSR & 0xf), SystemContext.SystemContextArm->IFAR));\r
+ }\r
+\r
+ DEBUG ((EFI_D_ERROR, "\n"));\r
+ ASSERT (FALSE);\r
+ \r
+ // Clear the error registers that we have already displayed incase some one wants to keep going\r
+ SystemContext.SystemContextArm->DFSR = 0;\r
+ SystemContext.SystemContextArm->IFSR = 0;\r
+\r
+ // If some one is stepping past the exception handler adjust the PC to point to the next instruction \r
+ SystemContext.SystemContextArm->PC += PcAdjust;\r
+}\r
+++ /dev/null
-/** @file\r
- Default exception handler\r
-\r
- Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>\r
- Copyright (c) 2012, ARM Ltd. All rights reserved.<BR>\r
- \r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include <Uefi.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/PeCoffGetEntryPointLib.h>\r
-#include <Library/PrintLib.h>\r
-#include <Library/ArmDisassemblerLib.h>\r
-#include <Library/SerialPortLib.h>\r
-\r
-#include <Guid/DebugImageInfoTable.h>\r
-\r
-#include <Protocol/DebugSupport.h>\r
-#include <Library/DefaultExceptionHandlerLib.h>\r
-\r
-EFI_DEBUG_IMAGE_INFO_TABLE_HEADER *gDebugImageTableHeader = NULL;\r
-\r
-typedef struct {\r
- UINT32 BIT;\r
- CHAR8 Char;\r
-} CPSR_CHAR;\r
-\r
-CHAR8 *\r
-GetImageName (\r
- IN UINT32 FaultAddress,\r
- OUT UINT32 *ImageBase,\r
- OUT UINT32 *PeCoffSizeOfHeaders\r
- );\r
-\r
-/**\r
- Convert the Current Program Status Register (CPSR) to a string. The string is \r
- a defacto standard in the ARM world. \r
- \r
- It is possible to add extra bits by adding them to CpsrChar array.\r
-\r
- @param Cpsr ARM CPSR register value\r
- @param ReturnStr 32 byte string that contains string version of CPSR\r
-\r
-**/\r
-VOID\r
-CpsrString (\r
- IN UINT32 Cpsr,\r
- OUT CHAR8 *ReturnStr\r
- )\r
-{\r
- UINTN Index;\r
- CHAR8* Str;\r
- CHAR8* ModeStr;\r
- CPSR_CHAR CpsrChar[] = {\r
- { 31, 'n' },\r
- { 30, 'z' },\r
- { 29, 'c' },\r
- { 28, 'v' },\r
-\r
- { 9, 'e' },\r
- { 8, 'a' },\r
- { 7, 'i' },\r
- { 6, 'f' },\r
- { 5, 't' },\r
- { 0, '?' }\r
- };\r
- \r
- Str = ReturnStr;\r
-\r
- for (Index = 0; CpsrChar[Index].BIT != 0; Index++, Str++) {\r
- *Str = CpsrChar[Index].Char;\r
- if ((Cpsr & (1 << CpsrChar[Index].BIT)) != 0) {\r
- // Concert to upper case if bit is set\r
- *Str &= ~0x20;\r
- }\r
- }\r
- \r
- *Str++ = '_';\r
- *Str = '\0';\r
- \r
- switch (Cpsr & 0x1f) {\r
- case 0x10:\r
- ModeStr = "usr";\r
- break;\r
- case 0x011:\r
- ModeStr = "fiq";\r
- break;\r
- case 0x12:\r
- ModeStr = "irq";\r
- break;\r
- case 0x13:\r
- ModeStr = "svc";\r
- break;\r
- case 0x16:\r
- ModeStr = "mon";\r
- break;\r
- case 0x17:\r
- ModeStr = "abt";\r
- break;\r
- case 0x1b:\r
- ModeStr = "und";\r
- break;\r
- case 0x1f:\r
- ModeStr = "sys";\r
- break;\r
- \r
- default:\r
- ModeStr = "???";\r
- break;\r
- }\r
- \r
- AsciiStrCat (Str, ModeStr);\r
- return;\r
-} \r
-\r
-CHAR8 *\r
-FaultStatusToString (\r
- IN UINT32 Status\r
- )\r
-{\r
- CHAR8 *FaultSource;\r
-\r
- switch (Status) {\r
- case 0x01: FaultSource = "Alignment fault"; break;\r
- case 0x02: FaultSource = "Debug event fault"; break;\r
- case 0x03: FaultSource = "Access Flag fault on Section"; break;\r
- case 0x04: FaultSource = "Cache maintenance operation fault[2]"; break;\r
- case 0x05: FaultSource = "Translation fault on Section"; break;\r
- case 0x06: FaultSource = "Access Flag fault on Page"; break;\r
- case 0x07: FaultSource = "Translation fault on Page"; break;\r
- case 0x08: FaultSource = "Precise External Abort"; break;\r
- case 0x09: FaultSource = "Domain fault on Section"; break;\r
- case 0x0b: FaultSource = "Domain fault on Page"; break;\r
- case 0x0c: FaultSource = "External abort on translation, first level"; break;\r
- case 0x0d: FaultSource = "Permission fault on Section"; break;\r
- case 0x0e: FaultSource = "External abort on translation, second level"; break;\r
- case 0x0f: FaultSource = "Permission fault on Page"; break;\r
- case 0x16: FaultSource = "Imprecise External Abort"; break;\r
- default: FaultSource = "No function"; break;\r
- }\r
-\r
- return FaultSource;\r
-}\r
-\r
-STATIC CHAR8 *gExceptionTypeString[] = {\r
- "Reset",\r
- "Undefined OpCode",\r
- "SVC",\r
- "Prefetch Abort",\r
- "Data Abort",\r
- "Undefined",\r
- "IRQ",\r
- "FIQ"\r
-};\r
-\r
-/**\r
- This is the default action to take on an unexpected exception\r
- \r
- Since this is exception context don't do anything crazy like try to allcoate memory.\r
-\r
- @param ExceptionType Type of the exception\r
- @param SystemContext Register state at the time of the Exception\r
-\r
-\r
-**/\r
-VOID\r
-DefaultExceptionHandler (\r
- IN EFI_EXCEPTION_TYPE ExceptionType,\r
- IN OUT EFI_SYSTEM_CONTEXT SystemContext\r
- )\r
-{\r
- CHAR8 Buffer[100];\r
- UINTN CharCount;\r
- UINT32 DfsrStatus;\r
- UINT32 IfsrStatus;\r
- BOOLEAN DfsrWrite;\r
- UINT32 PcAdjust = 0;\r
-\r
- CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"\n%a Exception PC at 0x%08x CPSR 0x%08x ",\r
- gExceptionTypeString[ExceptionType], SystemContext.SystemContextArm->PC, SystemContext.SystemContextArm->CPSR);\r
- SerialPortWrite ((UINT8 *) Buffer, CharCount);\r
-\r
- DEBUG_CODE_BEGIN ();\r
- CHAR8 *Pdb;\r
- UINT32 ImageBase;\r
- UINT32 PeCoffSizeOfHeader;\r
- UINT32 Offset;\r
- CHAR8 CpsrStr[32]; // char per bit. Lower 5-bits are mode that is a 3 char string\r
- CHAR8 Buffer[80];\r
- UINT8 *DisAsm;\r
- UINT32 ItBlock;\r
- \r
- CpsrString (SystemContext.SystemContextArm->CPSR, CpsrStr);\r
- DEBUG ((EFI_D_ERROR, "%a\n", CpsrStr));\r
- \r
- Pdb = GetImageName (SystemContext.SystemContextArm->PC, &ImageBase, &PeCoffSizeOfHeader);\r
- Offset = SystemContext.SystemContextArm->PC - ImageBase;\r
- if (Pdb != NULL) {\r
- DEBUG ((EFI_D_ERROR, "%a\n", Pdb));\r
-\r
- //\r
- // A PE/COFF image loads its headers into memory so the headers are \r
- // included in the linked addresses. ELF and Mach-O images do not\r
- // include the headers so the first byte of the image is usually\r
- // text (code). If you look at link maps from ELF or Mach-O images\r
- // you need to subtract out the size of the PE/COFF header to get\r
- // get the offset that matches the link map. \r
- //\r
- DEBUG ((EFI_D_ERROR, "loaded at 0x%08x (PE/COFF offset) 0x%x (ELF or Mach-O offset) 0x%x", ImageBase, Offset, Offset - PeCoffSizeOfHeader));\r
- \r
- // If we come from an image it is safe to show the instruction. We know it should not fault\r
- DisAsm = (UINT8 *)(UINTN)SystemContext.SystemContextArm->PC;\r
- ItBlock = 0;\r
- DisassembleInstruction (&DisAsm, (SystemContext.SystemContextArm->CPSR & BIT5) == BIT5, TRUE, &ItBlock, Buffer, sizeof (Buffer));\r
- DEBUG ((EFI_D_ERROR, "\n%a", Buffer));\r
- \r
- switch (ExceptionType) {\r
- case EXCEPT_ARM_UNDEFINED_INSTRUCTION:\r
- case EXCEPT_ARM_SOFTWARE_INTERRUPT:\r
- case EXCEPT_ARM_PREFETCH_ABORT:\r
- case EXCEPT_ARM_DATA_ABORT:\r
- // advance PC past the faulting instruction\r
- PcAdjust = (UINTN)DisAsm - SystemContext.SystemContextArm->PC;\r
- break;\r
- \r
- default:\r
- break;\r
- }\r
-\r
- }\r
- DEBUG_CODE_END ();\r
- DEBUG ((EFI_D_ERROR, "\n R0 0x%08x R1 0x%08x R2 0x%08x R3 0x%08x\n", SystemContext.SystemContextArm->R0, SystemContext.SystemContextArm->R1, SystemContext.SystemContextArm->R2, SystemContext.SystemContextArm->R3));\r
- DEBUG ((EFI_D_ERROR, " R4 0x%08x R5 0x%08x R6 0x%08x R7 0x%08x\n", SystemContext.SystemContextArm->R4, SystemContext.SystemContextArm->R5, SystemContext.SystemContextArm->R6, SystemContext.SystemContextArm->R7));\r
- DEBUG ((EFI_D_ERROR, " R8 0x%08x R9 0x%08x R10 0x%08x R11 0x%08x\n", SystemContext.SystemContextArm->R8, SystemContext.SystemContextArm->R9, SystemContext.SystemContextArm->R10, SystemContext.SystemContextArm->R11));\r
- DEBUG ((EFI_D_ERROR, " R12 0x%08x SP 0x%08x LR 0x%08x PC 0x%08x\n", SystemContext.SystemContextArm->R12, SystemContext.SystemContextArm->SP, SystemContext.SystemContextArm->LR, SystemContext.SystemContextArm->PC));\r
- DEBUG ((EFI_D_ERROR, "DFSR 0x%08x DFAR 0x%08x IFSR 0x%08x IFAR 0x%08x\n", SystemContext.SystemContextArm->DFSR, SystemContext.SystemContextArm->DFAR, SystemContext.SystemContextArm->IFSR, SystemContext.SystemContextArm->IFAR));\r
-\r
- // Bit10 is Status[4] Bit3:0 is Status[3:0]\r
- DfsrStatus = (SystemContext.SystemContextArm->DFSR & 0xf) | ((SystemContext.SystemContextArm->DFSR >> 6) & 0x10);\r
- DfsrWrite = (SystemContext.SystemContextArm->DFSR & BIT11) != 0;\r
- if (DfsrStatus != 0x00) {\r
- DEBUG ((EFI_D_ERROR, " %a: %a 0x%08x\n", FaultStatusToString (DfsrStatus), DfsrWrite ? "write to" : "read from", SystemContext.SystemContextArm->DFAR));\r
- }\r
-\r
- IfsrStatus = (SystemContext.SystemContextArm->IFSR & 0xf) | ((SystemContext.SystemContextArm->IFSR >> 6) & 0x10);\r
- if (IfsrStatus != 0) {\r
- DEBUG ((EFI_D_ERROR, " Instruction %a at 0x%08x\n", FaultStatusToString (SystemContext.SystemContextArm->IFSR & 0xf), SystemContext.SystemContextArm->IFAR));\r
- }\r
-\r
- DEBUG ((EFI_D_ERROR, "\n"));\r
- ASSERT (FALSE);\r
- \r
- // Clear the error registers that we have already displayed incase some one wants to keep going\r
- SystemContext.SystemContextArm->DFSR = 0;\r
- SystemContext.SystemContextArm->IFSR = 0;\r
-\r
- // If some one is stepping past the exception handler adjust the PC to point to the next instruction \r
- SystemContext.SystemContextArm->PC += PcAdjust;\r
-}\r
LIBRARY_CLASS = DefaultExceptionHandlerLib\r
CONSTRUCTOR = DefaultExceptionHandlerConstructor\r
\r
-\r
[Sources.common]\r
- DefaultExceptionHandler.c\r
DefaultExceptionHandlerUefi.c\r
\r
+[Sources.ARM]\r
+ Arm/DefaultExceptionHandler.c\r
+\r
[Packages]\r
MdePkg/MdePkg.dec\r
ArmPkg/ArmPkg.dec\r
LIBRARY_CLASS = DefaultExceptionHandlerLib\r
\r
[Sources.common]\r
- DefaultExceptionHandler.c\r
DefaultExceptionHandlerBase.c\r
\r
+[Sources.ARM]\r
+ Arm/DefaultExceptionHandler.c\r
+\r
[Packages]\r
MdePkg/MdePkg.dec\r
ArmPkg/ArmPkg.dec\r
+++ /dev/null
-/** @file\r
-\r
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
- \r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-#include <Base.h>\r
-\r
-#include <Library/BaseLib.h>\r
-#include <Library/SemihostLib.h>\r
-\r
-#include "SemihostPrivate.h"\r
-\r
-BOOLEAN\r
-SemihostConnectionSupported (\r
- VOID\r
- )\r
-{\r
- return SEMIHOST_SUPPORTED;\r
-}\r
-\r
-RETURN_STATUS\r
-SemihostFileOpen (\r
- IN CHAR8 *FileName,\r
- IN UINT32 Mode,\r
- OUT UINT32 *FileHandle\r
- )\r
-{\r
- SEMIHOST_FILE_OPEN_BLOCK OpenBlock;\r
- INT32 Result;\r
-\r
- if (FileHandle == NULL) {\r
- return RETURN_INVALID_PARAMETER;\r
- }\r
-\r
- OpenBlock.FileName = FileName;\r
- OpenBlock.Mode = Mode;\r
- OpenBlock.NameLength = AsciiStrLen(FileName);\r
-\r
- Result = Semihost_SYS_OPEN(&OpenBlock);\r
-\r
- if (Result == -1) {\r
- return RETURN_NOT_FOUND;\r
- } else {\r
- *FileHandle = Result;\r
- return RETURN_SUCCESS;\r
- }\r
-}\r
-\r
-RETURN_STATUS\r
-SemihostFileSeek (\r
- IN UINT32 FileHandle,\r
- IN UINT32 Offset\r
- )\r
-{\r
- SEMIHOST_FILE_SEEK_BLOCK SeekBlock;\r
- INT32 Result;\r
-\r
- SeekBlock.Handle = FileHandle;\r
- SeekBlock.Location = Offset;\r
-\r
- Result = Semihost_SYS_SEEK(&SeekBlock);\r
-\r
- if (Result == 0) {\r
- return RETURN_SUCCESS;\r
- } else {\r
- return RETURN_ABORTED;\r
- }\r
-}\r
-\r
-RETURN_STATUS\r
-SemihostFileRead (\r
- IN UINT32 FileHandle,\r
- IN OUT UINT32 *Length,\r
- OUT VOID *Buffer\r
- )\r
-{\r
- SEMIHOST_FILE_READ_WRITE_BLOCK ReadBlock;\r
- UINT32 Result;\r
-\r
- if ((Length == NULL) || (Buffer == NULL)) {\r
- return RETURN_INVALID_PARAMETER;\r
- }\r
-\r
- ReadBlock.Handle = FileHandle;\r
- ReadBlock.Buffer = Buffer;\r
- ReadBlock.Length = *Length;\r
-\r
- Result = Semihost_SYS_READ(&ReadBlock);\r
-\r
- if (Result == *Length) {\r
- return RETURN_ABORTED;\r
- } else {\r
- *Length -= Result;\r
- return RETURN_SUCCESS;\r
- }\r
-}\r
-\r
-RETURN_STATUS\r
-SemihostFileWrite (\r
- IN UINT32 FileHandle,\r
- IN OUT UINT32 *Length,\r
- IN VOID *Buffer\r
- )\r
-{\r
- SEMIHOST_FILE_READ_WRITE_BLOCK WriteBlock;\r
-\r
- if ((Length == NULL) || (Buffer == NULL)) {\r
- return RETURN_INVALID_PARAMETER;\r
- }\r
-\r
- WriteBlock.Handle = FileHandle;\r
- WriteBlock.Buffer = Buffer;\r
- WriteBlock.Length = *Length;\r
-\r
- *Length = Semihost_SYS_WRITE(&WriteBlock);\r
- \r
- return RETURN_SUCCESS;\r
-}\r
-\r
-RETURN_STATUS\r
-SemihostFileClose (\r
- IN UINT32 FileHandle\r
- )\r
-{\r
- INT32 Result = Semihost_SYS_CLOSE(&FileHandle);\r
-\r
- if (Result == -1) {\r
- return RETURN_INVALID_PARAMETER;\r
- } else {\r
- return RETURN_SUCCESS;\r
- }\r
-}\r
-\r
-RETURN_STATUS\r
-SemihostFileLength (\r
- IN UINT32 FileHandle,\r
- OUT UINT32 *Length\r
- )\r
-{\r
- INT32 Result;\r
-\r
- if (Length == NULL) {\r
- return RETURN_INVALID_PARAMETER;\r
- }\r
-\r
- Result = Semihost_SYS_FLEN(&FileHandle);\r
-\r
- if (Result == -1) {\r
- return RETURN_ABORTED;\r
- } else {\r
- *Length = Result;\r
- return RETURN_SUCCESS;\r
- }\r
-}\r
-\r
-RETURN_STATUS\r
-SemihostFileRemove (\r
- IN CHAR8 *FileName\r
- )\r
-{\r
- SEMIHOST_FILE_REMOVE_BLOCK RemoveBlock;\r
- UINT32 Result;\r
-\r
- RemoveBlock.FileName = FileName;\r
- RemoveBlock.NameLength = AsciiStrLen(FileName);\r
-\r
- Result = Semihost_SYS_REMOVE(&RemoveBlock);\r
-\r
- if (Result == 0) {\r
- return RETURN_SUCCESS;\r
- } else {\r
- return RETURN_ABORTED;\r
- }\r
-}\r
-\r
-CHAR8\r
-SemihostReadCharacter (\r
- VOID\r
- )\r
-{\r
- return Semihost_SYS_READC();\r
-}\r
-\r
-VOID\r
-SemihostWriteCharacter (\r
- IN CHAR8 Character\r
- )\r
-{\r
- Semihost_SYS_WRITEC(&Character);\r
-}\r
-\r
-VOID\r
-SemihostWriteString (\r
- IN CHAR8 *String\r
- )\r
-{\r
- Semihost_SYS_WRITE0(String);\r
-}\r
- \r
-UINT32\r
-SemihostSystem (\r
- IN CHAR8 *CommandLine\r
- )\r
-{\r
- SEMIHOST_SYSTEM_BLOCK SystemBlock;\r
-\r
- SystemBlock.CommandLine = CommandLine;\r
- SystemBlock.CommandLength = AsciiStrLen(CommandLine);\r
-\r
- return Semihost_SYS_SYSTEM(&SystemBlock);\r
-}\r
+++ /dev/null
-/** @file\r
-\r
- Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
-\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#ifndef __SEMIHOST_PRIVATE_H__\r
-#define __SEMIHOST_PRIVATE_H__\r
-\r
-typedef struct {\r
- CHAR8 *FileName;\r
- UINT32 Mode;\r
- UINT32 NameLength;\r
-} SEMIHOST_FILE_OPEN_BLOCK;\r
-\r
-typedef struct {\r
- UINT32 Handle;\r
- VOID *Buffer;\r
- UINT32 Length;\r
-} SEMIHOST_FILE_READ_WRITE_BLOCK;\r
-\r
-typedef struct {\r
- UINT32 Handle;\r
- UINT32 Location;\r
-} SEMIHOST_FILE_SEEK_BLOCK;\r
-\r
-typedef struct {\r
- CHAR8 *FileName;\r
- UINT32 NameLength;\r
-} SEMIHOST_FILE_REMOVE_BLOCK;\r
-\r
-typedef struct {\r
- CHAR8 *CommandLine;\r
- UINT32 CommandLength;\r
-} SEMIHOST_SYSTEM_BLOCK;\r
-\r
-#if defined(__CC_ARM) \r
-\r
-#if defined(__thumb__)\r
-#define SWI 0xAB\r
-#else\r
-#define SWI 0x123456\r
-#endif\r
-\r
-#define SEMIHOST_SUPPORTED TRUE\r
-\r
-__swi(SWI)\r
-INT32\r
-_Semihost_SYS_OPEN(\r
- IN UINTN SWI_0x01,\r
- IN SEMIHOST_FILE_OPEN_BLOCK *OpenBlock\r
- );\r
-\r
-__swi(SWI)\r
-INT32\r
-_Semihost_SYS_CLOSE(\r
- IN UINTN SWI_0x02,\r
- IN UINT32 *Handle\r
- );\r
-\r
-__swi(SWI)\r
-VOID\r
-_Semihost_SYS_WRITEC(\r
- IN UINTN SWI_0x03,\r
- IN CHAR8 *Character\r
- );\r
-\r
-__swi(SWI)\r
-VOID\r
-_Semihost_SYS_WRITE0(\r
- IN UINTN SWI_0x04,\r
- IN CHAR8 *String\r
- );\r
-\r
-__swi(SWI)\r
-UINT32\r
-_Semihost_SYS_WRITE(\r
- IN UINTN SWI_0x05,\r
- IN OUT SEMIHOST_FILE_READ_WRITE_BLOCK *WriteBlock\r
- );\r
-\r
-__swi(SWI)\r
-UINT32\r
-_Semihost_SYS_READ(\r
- IN UINTN SWI_0x06,\r
- IN OUT SEMIHOST_FILE_READ_WRITE_BLOCK *ReadBlock\r
- );\r
-\r
-__swi(SWI)\r
-CHAR8\r
-_Semihost_SYS_READC(\r
- IN UINTN SWI_0x07,\r
- IN UINTN Zero\r
- );\r
-\r
-__swi(SWI)\r
-INT32\r
-_Semihost_SYS_SEEK(\r
- IN UINTN SWI_0x0A,\r
- IN SEMIHOST_FILE_SEEK_BLOCK *SeekBlock\r
- );\r
-\r
-__swi(SWI)\r
-INT32\r
-_Semihost_SYS_FLEN(\r
- IN UINTN SWI_0x0C,\r
- IN UINT32 *Handle\r
- );\r
-\r
-__swi(SWI)\r
-UINT32\r
-_Semihost_SYS_REMOVE(\r
- IN UINTN SWI_0x0E,\r
- IN SEMIHOST_FILE_REMOVE_BLOCK *RemoveBlock\r
- );\r
-\r
-__swi(SWI)\r
-UINT32\r
-_Semihost_SYS_SYSTEM(\r
- IN UINTN SWI_0x12,\r
- IN SEMIHOST_SYSTEM_BLOCK *SystemBlock\r
- );\r
-\r
-#define Semihost_SYS_OPEN(OpenBlock) _Semihost_SYS_OPEN(0x01, OpenBlock)\r
-#define Semihost_SYS_CLOSE(Handle) _Semihost_SYS_CLOSE(0x02, Handle)\r
-#define Semihost_SYS_WRITE0(String) _Semihost_SYS_WRITE0(0x04, String)\r
-#define Semihost_SYS_WRITEC(Character) _Semihost_SYS_WRITEC(0x03, Character)\r
-#define Semihost_SYS_WRITE(WriteBlock) _Semihost_SYS_WRITE(0x05, WriteBlock)\r
-#define Semihost_SYS_READ(ReadBlock) _Semihost_SYS_READ(0x06, ReadBlock)\r
-#define Semihost_SYS_READC() _Semihost_SYS_READC(0x07, 0)\r
-#define Semihost_SYS_SEEK(SeekBlock) _Semihost_SYS_SEEK(0x0A, SeekBlock)\r
-#define Semihost_SYS_FLEN(Handle) _Semihost_SYS_FLEN(0x0C, Handle)\r
-#define Semihost_SYS_REMOVE(RemoveBlock) _Semihost_SYS_REMOVE(0x0E, RemoveBlock)\r
-#define Semihost_SYS_SYSTEM(SystemBlock) _Semihost_SYS_SYSTEM(0x12, SystemBlock)\r
-\r
-#elif defined(__GNUC__) // __CC_ARM\r
-\r
-#define SEMIHOST_SUPPORTED TRUE\r
-\r
-UINT32\r
-GccSemihostCall (\r
- IN UINT32 Operation,\r
- IN UINTN SystemBlockAddress\r
- ); // __attribute__ ((interrupt ("SVC")));\r
-\r
-#define Semihost_SYS_OPEN(OpenBlock) GccSemihostCall(0x01, (UINTN)(OpenBlock))\r
-#define Semihost_SYS_CLOSE(Handle) GccSemihostCall(0x02, (UINTN)(Handle))\r
-#define Semihost_SYS_WRITE0(String) GccSemihostCall(0x04, (UINTN)(String))\r
-#define Semihost_SYS_WRITEC(Character) GccSemihostCall(0x03, (UINTN)(Character))\r
-#define Semihost_SYS_WRITE(WriteBlock) GccSemihostCall(0x05, (UINTN)(WriteBlock))\r
-#define Semihost_SYS_READ(ReadBlock) GccSemihostCall(0x06, (UINTN)(ReadBlock))\r
-#define Semihost_SYS_READC() GccSemihostCall(0x07, (UINTN)(0))\r
-#define Semihost_SYS_SEEK(SeekBlock) GccSemihostCall(0x0A, (UINTN)(SeekBlock))\r
-#define Semihost_SYS_FLEN(Handle) GccSemihostCall(0x0C, (UINTN)(Handle))\r
-#define Semihost_SYS_REMOVE(RemoveBlock) GccSemihostCall(0x0E, (UINTN)(RemoveBlock))\r
-#define Semihost_SYS_SYSTEM(SystemBlock) GccSemihostCall(0x12, (UINTN)(SystemBlock))\r
-\r
-#else // __CC_ARM\r
-\r
-#define SEMIHOST_SUPPORTED FALSE\r
-\r
-#define Semihost_SYS_OPEN(OpenBlock) (-1)\r
-#define Semihost_SYS_CLOSE(Handle) (-1)\r
-#define Semihost_SYS_WRITE0(String)\r
-#define Semihost_SYS_WRITEC(Character)\r
-#define Semihost_SYS_WRITE(WriteBlock) (0)\r
-#define Semihost_SYS_READ(ReadBlock) ((ReadBlock)->Length)\r
-#define Semihost_SYS_READC() ('x')\r
-#define Semihost_SYS_SEEK(SeekBlock) (-1)\r
-#define Semihost_SYS_FLEN(Handle) (-1)\r
-#define Semihost_SYS_REMOVE(RemoveBlock) (-1)\r
-#define Semihost_SYS_SYSTEM(SystemBlock) (-1)\r
-\r
-#endif // __CC_ARM\r
-\r
-#endif //__SEMIHOST_PRIVATE_H__\r
--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+ \r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include <Base.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/SemihostLib.h>\r
+\r
+#include "SemihostPrivate.h"\r
+\r
+BOOLEAN\r
+SemihostConnectionSupported (\r
+ VOID\r
+ )\r
+{\r
+ return SEMIHOST_SUPPORTED;\r
+}\r
+\r
+RETURN_STATUS\r
+SemihostFileOpen (\r
+ IN CHAR8 *FileName,\r
+ IN UINT32 Mode,\r
+ OUT UINT32 *FileHandle\r
+ )\r
+{\r
+ SEMIHOST_FILE_OPEN_BLOCK OpenBlock;\r
+ INT32 Result;\r
+\r
+ if (FileHandle == NULL) {\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+\r
+ OpenBlock.FileName = FileName;\r
+ OpenBlock.Mode = Mode;\r
+ OpenBlock.NameLength = AsciiStrLen(FileName);\r
+\r
+ Result = Semihost_SYS_OPEN(&OpenBlock);\r
+\r
+ if (Result == -1) {\r
+ return RETURN_NOT_FOUND;\r
+ } else {\r
+ *FileHandle = Result;\r
+ return RETURN_SUCCESS;\r
+ }\r
+}\r
+\r
+RETURN_STATUS\r
+SemihostFileSeek (\r
+ IN UINT32 FileHandle,\r
+ IN UINT32 Offset\r
+ )\r
+{\r
+ SEMIHOST_FILE_SEEK_BLOCK SeekBlock;\r
+ INT32 Result;\r
+\r
+ SeekBlock.Handle = FileHandle;\r
+ SeekBlock.Location = Offset;\r
+\r
+ Result = Semihost_SYS_SEEK(&SeekBlock);\r
+\r
+ if (Result == 0) {\r
+ return RETURN_SUCCESS;\r
+ } else {\r
+ return RETURN_ABORTED;\r
+ }\r
+}\r
+\r
+RETURN_STATUS\r
+SemihostFileRead (\r
+ IN UINT32 FileHandle,\r
+ IN OUT UINT32 *Length,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ SEMIHOST_FILE_READ_WRITE_BLOCK ReadBlock;\r
+ UINT32 Result;\r
+\r
+ if ((Length == NULL) || (Buffer == NULL)) {\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+\r
+ ReadBlock.Handle = FileHandle;\r
+ ReadBlock.Buffer = Buffer;\r
+ ReadBlock.Length = *Length;\r
+\r
+ Result = Semihost_SYS_READ(&ReadBlock);\r
+\r
+ if (Result == *Length) {\r
+ return RETURN_ABORTED;\r
+ } else {\r
+ *Length -= Result;\r
+ return RETURN_SUCCESS;\r
+ }\r
+}\r
+\r
+RETURN_STATUS\r
+SemihostFileWrite (\r
+ IN UINT32 FileHandle,\r
+ IN OUT UINT32 *Length,\r
+ IN VOID *Buffer\r
+ )\r
+{\r
+ SEMIHOST_FILE_READ_WRITE_BLOCK WriteBlock;\r
+\r
+ if ((Length == NULL) || (Buffer == NULL)) {\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+\r
+ WriteBlock.Handle = FileHandle;\r
+ WriteBlock.Buffer = Buffer;\r
+ WriteBlock.Length = *Length;\r
+\r
+ *Length = Semihost_SYS_WRITE(&WriteBlock);\r
+ \r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+RETURN_STATUS\r
+SemihostFileClose (\r
+ IN UINT32 FileHandle\r
+ )\r
+{\r
+ INT32 Result = Semihost_SYS_CLOSE(&FileHandle);\r
+\r
+ if (Result == -1) {\r
+ return RETURN_INVALID_PARAMETER;\r
+ } else {\r
+ return RETURN_SUCCESS;\r
+ }\r
+}\r
+\r
+RETURN_STATUS\r
+SemihostFileLength (\r
+ IN UINT32 FileHandle,\r
+ OUT UINT32 *Length\r
+ )\r
+{\r
+ INT32 Result;\r
+\r
+ if (Length == NULL) {\r
+ return RETURN_INVALID_PARAMETER;\r
+ }\r
+\r
+ Result = Semihost_SYS_FLEN(&FileHandle);\r
+\r
+ if (Result == -1) {\r
+ return RETURN_ABORTED;\r
+ } else {\r
+ *Length = Result;\r
+ return RETURN_SUCCESS;\r
+ }\r
+}\r
+\r
+RETURN_STATUS\r
+SemihostFileRemove (\r
+ IN CHAR8 *FileName\r
+ )\r
+{\r
+ SEMIHOST_FILE_REMOVE_BLOCK RemoveBlock;\r
+ UINT32 Result;\r
+\r
+ RemoveBlock.FileName = FileName;\r
+ RemoveBlock.NameLength = AsciiStrLen(FileName);\r
+\r
+ Result = Semihost_SYS_REMOVE(&RemoveBlock);\r
+\r
+ if (Result == 0) {\r
+ return RETURN_SUCCESS;\r
+ } else {\r
+ return RETURN_ABORTED;\r
+ }\r
+}\r
+\r
+CHAR8\r
+SemihostReadCharacter (\r
+ VOID\r
+ )\r
+{\r
+ return Semihost_SYS_READC();\r
+}\r
+\r
+VOID\r
+SemihostWriteCharacter (\r
+ IN CHAR8 Character\r
+ )\r
+{\r
+ Semihost_SYS_WRITEC(&Character);\r
+}\r
+\r
+VOID\r
+SemihostWriteString (\r
+ IN CHAR8 *String\r
+ )\r
+{\r
+ Semihost_SYS_WRITE0(String);\r
+}\r
+ \r
+UINT32\r
+SemihostSystem (\r
+ IN CHAR8 *CommandLine\r
+ )\r
+{\r
+ SEMIHOST_SYSTEM_BLOCK SystemBlock;\r
+\r
+ SystemBlock.CommandLine = CommandLine;\r
+ SystemBlock.CommandLength = AsciiStrLen(CommandLine);\r
+\r
+ return Semihost_SYS_SYSTEM(&SystemBlock);\r
+}\r
#\r
# VALID_ARCHITECTURES = ARM\r
#\r
+[Sources.common]\r
+ SemihostLib.c\r
+\r
[Sources.ARM]\r
Arm/GccSemihost.S | GCC\r
- Arm/SemihostLib.c\r
-\r
\r
[Packages]\r
MdePkg/MdePkg.dec\r
\r
[LibraryClasses]\r
BaseLib\r
- \r
-[Protocols]\r
- \r
-[Guids]\r
- \r
-[Pcd]\r
- \r
\ No newline at end of file
+ \r\r
--- /dev/null
+/** @file\r
+\r
+ Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __SEMIHOST_PRIVATE_H__\r
+#define __SEMIHOST_PRIVATE_H__\r
+\r
+typedef struct {\r
+ CHAR8 *FileName;\r
+ UINT32 Mode;\r
+ UINT32 NameLength;\r
+} SEMIHOST_FILE_OPEN_BLOCK;\r
+\r
+typedef struct {\r
+ UINT32 Handle;\r
+ VOID *Buffer;\r
+ UINT32 Length;\r
+} SEMIHOST_FILE_READ_WRITE_BLOCK;\r
+\r
+typedef struct {\r
+ UINT32 Handle;\r
+ UINT32 Location;\r
+} SEMIHOST_FILE_SEEK_BLOCK;\r
+\r
+typedef struct {\r
+ CHAR8 *FileName;\r
+ UINT32 NameLength;\r
+} SEMIHOST_FILE_REMOVE_BLOCK;\r
+\r
+typedef struct {\r
+ CHAR8 *CommandLine;\r
+ UINT32 CommandLength;\r
+} SEMIHOST_SYSTEM_BLOCK;\r
+\r
+#if defined(__CC_ARM) \r
+\r
+#if defined(__thumb__)\r
+#define SWI 0xAB\r
+#else\r
+#define SWI 0x123456\r
+#endif\r
+\r
+#define SEMIHOST_SUPPORTED TRUE\r
+\r
+__swi(SWI)\r
+INT32\r
+_Semihost_SYS_OPEN(\r
+ IN UINTN SWI_0x01,\r
+ IN SEMIHOST_FILE_OPEN_BLOCK *OpenBlock\r
+ );\r
+\r
+__swi(SWI)\r
+INT32\r
+_Semihost_SYS_CLOSE(\r
+ IN UINTN SWI_0x02,\r
+ IN UINT32 *Handle\r
+ );\r
+\r
+__swi(SWI)\r
+VOID\r
+_Semihost_SYS_WRITEC(\r
+ IN UINTN SWI_0x03,\r
+ IN CHAR8 *Character\r
+ );\r
+\r
+__swi(SWI)\r
+VOID\r
+_Semihost_SYS_WRITE0(\r
+ IN UINTN SWI_0x04,\r
+ IN CHAR8 *String\r
+ );\r
+\r
+__swi(SWI)\r
+UINT32\r
+_Semihost_SYS_WRITE(\r
+ IN UINTN SWI_0x05,\r
+ IN OUT SEMIHOST_FILE_READ_WRITE_BLOCK *WriteBlock\r
+ );\r
+\r
+__swi(SWI)\r
+UINT32\r
+_Semihost_SYS_READ(\r
+ IN UINTN SWI_0x06,\r
+ IN OUT SEMIHOST_FILE_READ_WRITE_BLOCK *ReadBlock\r
+ );\r
+\r
+__swi(SWI)\r
+CHAR8\r
+_Semihost_SYS_READC(\r
+ IN UINTN SWI_0x07,\r
+ IN UINTN Zero\r
+ );\r
+\r
+__swi(SWI)\r
+INT32\r
+_Semihost_SYS_SEEK(\r
+ IN UINTN SWI_0x0A,\r
+ IN SEMIHOST_FILE_SEEK_BLOCK *SeekBlock\r
+ );\r
+\r
+__swi(SWI)\r
+INT32\r
+_Semihost_SYS_FLEN(\r
+ IN UINTN SWI_0x0C,\r
+ IN UINT32 *Handle\r
+ );\r
+\r
+__swi(SWI)\r
+UINT32\r
+_Semihost_SYS_REMOVE(\r
+ IN UINTN SWI_0x0E,\r
+ IN SEMIHOST_FILE_REMOVE_BLOCK *RemoveBlock\r
+ );\r
+\r
+__swi(SWI)\r
+UINT32\r
+_Semihost_SYS_SYSTEM(\r
+ IN UINTN SWI_0x12,\r
+ IN SEMIHOST_SYSTEM_BLOCK *SystemBlock\r
+ );\r
+\r
+#define Semihost_SYS_OPEN(OpenBlock) _Semihost_SYS_OPEN(0x01, OpenBlock)\r
+#define Semihost_SYS_CLOSE(Handle) _Semihost_SYS_CLOSE(0x02, Handle)\r
+#define Semihost_SYS_WRITE0(String) _Semihost_SYS_WRITE0(0x04, String)\r
+#define Semihost_SYS_WRITEC(Character) _Semihost_SYS_WRITEC(0x03, Character)\r
+#define Semihost_SYS_WRITE(WriteBlock) _Semihost_SYS_WRITE(0x05, WriteBlock)\r
+#define Semihost_SYS_READ(ReadBlock) _Semihost_SYS_READ(0x06, ReadBlock)\r
+#define Semihost_SYS_READC() _Semihost_SYS_READC(0x07, 0)\r
+#define Semihost_SYS_SEEK(SeekBlock) _Semihost_SYS_SEEK(0x0A, SeekBlock)\r
+#define Semihost_SYS_FLEN(Handle) _Semihost_SYS_FLEN(0x0C, Handle)\r
+#define Semihost_SYS_REMOVE(RemoveBlock) _Semihost_SYS_REMOVE(0x0E, RemoveBlock)\r
+#define Semihost_SYS_SYSTEM(SystemBlock) _Semihost_SYS_SYSTEM(0x12, SystemBlock)\r
+\r
+#elif defined(__GNUC__) // __CC_ARM\r
+\r
+#define SEMIHOST_SUPPORTED TRUE\r
+\r
+UINT32\r
+GccSemihostCall (\r
+ IN UINT32 Operation,\r
+ IN UINTN SystemBlockAddress\r
+ ); // __attribute__ ((interrupt ("SVC")));\r
+\r
+#define Semihost_SYS_OPEN(OpenBlock) GccSemihostCall(0x01, (UINTN)(OpenBlock))\r
+#define Semihost_SYS_CLOSE(Handle) GccSemihostCall(0x02, (UINTN)(Handle))\r
+#define Semihost_SYS_WRITE0(String) GccSemihostCall(0x04, (UINTN)(String))\r
+#define Semihost_SYS_WRITEC(Character) GccSemihostCall(0x03, (UINTN)(Character))\r
+#define Semihost_SYS_WRITE(WriteBlock) GccSemihostCall(0x05, (UINTN)(WriteBlock))\r
+#define Semihost_SYS_READ(ReadBlock) GccSemihostCall(0x06, (UINTN)(ReadBlock))\r
+#define Semihost_SYS_READC() GccSemihostCall(0x07, (UINTN)(0))\r
+#define Semihost_SYS_SEEK(SeekBlock) GccSemihostCall(0x0A, (UINTN)(SeekBlock))\r
+#define Semihost_SYS_FLEN(Handle) GccSemihostCall(0x0C, (UINTN)(Handle))\r
+#define Semihost_SYS_REMOVE(RemoveBlock) GccSemihostCall(0x0E, (UINTN)(RemoveBlock))\r
+#define Semihost_SYS_SYSTEM(SystemBlock) GccSemihostCall(0x12, (UINTN)(SystemBlock))\r
+\r
+#else // __CC_ARM\r
+\r
+#define SEMIHOST_SUPPORTED FALSE\r
+\r
+#define Semihost_SYS_OPEN(OpenBlock) (-1)\r
+#define Semihost_SYS_CLOSE(Handle) (-1)\r
+#define Semihost_SYS_WRITE0(String)\r
+#define Semihost_SYS_WRITEC(Character)\r
+#define Semihost_SYS_WRITE(WriteBlock) (0)\r
+#define Semihost_SYS_READ(ReadBlock) ((ReadBlock)->Length)\r
+#define Semihost_SYS_READC() ('x')\r
+#define Semihost_SYS_SEEK(SeekBlock) (-1)\r
+#define Semihost_SYS_FLEN(Handle) (-1)\r
+#define Semihost_SYS_REMOVE(RemoveBlock) (-1)\r
+#define Semihost_SYS_SYSTEM(SystemBlock) (-1)\r
+\r
+#endif // __CC_ARM\r
+\r
+#endif //__SEMIHOST_PRIVATE_H__\r