--- /dev/null
+/*\r
+ * Copyright (c) 2014, Linaro Ltd. 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
+ * Theory of operation\r
+ * -------------------\r
+ *\r
+ * This code parses a Flattened Device Tree binary (DTB) to find the base of\r
+ * system RAM. It is written in assembly so that it can be executed before a\r
+ * stack has been set up.\r
+ *\r
+ * To find the base of system RAM, we have to traverse the FDT to find a memory\r
+ * node. In the context of this implementation, the first node that has a\r
+ * device_type property with the value 'memory' and a 'reg' property is\r
+ * acceptable, and the name of the node (memory[@xxx]) is ignored, as are any\r
+ * other nodes that match the above constraints.\r
+ *\r
+ * In pseudo code, this implementation does the following:\r
+ *\r
+ * for each node {\r
+ * have_device_type = false\r
+ * have_reg = false\r
+ *\r
+ * for each property {\r
+ * if property value == 'memory' {\r
+ * if property name == 'device_type' {\r
+ * have_device_type = true\r
+ * }\r
+ * } else {\r
+ * if property name == 'reg' {\r
+ * have_reg = true\r
+ * membase = property value[0]\r
+ * memsize = property value[1]\r
+ * }\r
+ * }\r
+ * }\r
+ * if have_device_type and have_reg {\r
+ * return membase and memsize\r
+ * }\r
+ * }\r
+ * return NOT_FOUND\r
+ */\r
+\r
+#define FDT_MAGIC 0xedfe0dd0\r
+\r
+#define FDT_BEGIN_NODE 0x1\r
+#define FDT_END_NODE 0x2\r
+#define FDT_PROP 0x3\r
+#define FDT_END 0x9\r
+\r
+ xMEMSIZE .req x0 // recorded system RAM size\r
+ xMEMBASE .req x1 // recorded system RAM base\r
+\r
+ xLR .req x8 // our preserved link register\r
+ xDTP .req x9 // pointer to traverse the DT structure\r
+ xSTRTAB .req x10 // pointer to the DTB string table\r
+ xMEMNODE .req x11 // bit field to record found properties\r
+\r
+#define HAVE_REG 0x1\r
+#define HAVE_DEVICE_TYPE 0x2\r
+\r
+ .text\r
+ .align 3\r
+_memory:\r
+ .asciz "memory"\r
+_reg:\r
+ .asciz "reg"\r
+_device_type:\r
+ .asciz "device_type"\r
+\r
+ /*\r
+ * Compare strings in x4 and x5, return in w7\r
+ */\r
+ .align 3\r
+strcmp:\r
+ ldrb w2, [x4], #1\r
+ ldrb w3, [x5], #1\r
+ subs w7, w2, w3\r
+ cbz w2, 0f\r
+ cbz w3, 0f\r
+ beq strcmp\r
+0: ret\r
+\r
+ .globl find_memnode\r
+find_memnode:\r
+ // preserve link register\r
+ mov xLR, x30\r
+ mov xDTP, x0\r
+\r
+ /*\r
+ * Check the DTB magic at offset 0\r
+ */\r
+ movz w4, #:abs_g0_nc:FDT_MAGIC\r
+ movk w4, #:abs_g1:FDT_MAGIC\r
+ ldr w5, [xDTP]\r
+ cmp w4, w5\r
+ bne err_invalid_magic\r
+\r
+ /*\r
+ * Read the string offset and store it for later use\r
+ */\r
+ ldr w4, [xDTP, #12]\r
+ rev w4, w4\r
+ add xSTRTAB, xDTP, x4\r
+\r
+ /*\r
+ * Read the struct offset and add it to the DT pointer\r
+ */\r
+ ldr w5, [xDTP, #8]\r
+ rev w5, w5\r
+ add xDTP, xDTP, x5\r
+\r
+ /*\r
+ * Check current tag for FDT_BEGIN_NODE\r
+ */\r
+ ldr w5, [xDTP]\r
+ rev w5, w5\r
+ cmp w5, #FDT_BEGIN_NODE\r
+ bne err_unexpected_begin_tag\r
+\r
+begin_node:\r
+ mov xMEMNODE, #0\r
+ add xDTP, xDTP, #4\r
+\r
+ /*\r
+ * Advance xDTP past NULL terminated string\r
+ */\r
+0: ldrb w4, [xDTP], #1\r
+ cbnz w4, 0b\r
+\r
+next_tag:\r
+ /*\r
+ * Align the DT pointer xDTP to the next 32-bit boundary\r
+ */\r
+ add xDTP, xDTP, #3\r
+ and xDTP, xDTP, #~3\r
+\r
+ /*\r
+ * Read the next tag, could be BEGIN_NODE, END_NODE, PROP, END\r
+ */\r
+ ldr w5, [xDTP]\r
+ rev w5, w5\r
+ cmp w5, #FDT_BEGIN_NODE\r
+ beq begin_node\r
+ cmp w5, #FDT_END_NODE\r
+ beq end_node\r
+ cmp w5, #FDT_PROP\r
+ beq prop_node\r
+ cmp w5, #FDT_END\r
+ beq err_end_of_fdt\r
+ b err_unexpected_tag\r
+\r
+prop_node:\r
+ /*\r
+ * If propname == 'reg', record as membase and memsize\r
+ * If propname == 'device_type' and value == 'memory',\r
+ * set the 'is_memnode' flag for this node\r
+ */\r
+ ldr w6, [xDTP, #4]\r
+ add xDTP, xDTP, #12\r
+ rev w6, w6\r
+ mov x5, xDTP\r
+ adr x4, _memory\r
+ bl strcmp\r
+\r
+ /*\r
+ * Get handle to property name\r
+ */\r
+ ldr w5, [xDTP, #-4]\r
+ rev w5, w5\r
+ add x5, xSTRTAB, x5\r
+\r
+ cbz w7, check_device_type\r
+\r
+ /*\r
+ * Check for 'reg' property\r
+ */\r
+ adr x4, _reg\r
+ bl strcmp\r
+ cbnz w7, inc_and_next_tag\r
+\r
+ /*\r
+ * Extract two 64-bit quantities from the 'reg' property. These values\r
+ * will only be used if the node also turns out to have a device_type\r
+ * property with a value of 'memory'.\r
+ *\r
+ * NOTE: xDTP is only guaranteed to be 32 bit aligned, and we are most\r
+ * likely executing with the MMU off, so we cannot use 64 bit\r
+ * wide accesses here.\r
+ */\r
+ ldp w4, w5, [xDTP]\r
+ orr xMEMBASE, x4, x5, lsl #32\r
+ ldp w4, w5, [xDTP, #8]\r
+ orr xMEMSIZE, x4, x5, lsl #32\r
+ rev xMEMBASE, xMEMBASE\r
+ rev xMEMSIZE, xMEMSIZE\r
+ orr xMEMNODE, xMEMNODE, #HAVE_REG\r
+ b inc_and_next_tag\r
+\r
+check_device_type:\r
+ /*\r
+ * Check whether the current property's name is 'device_type'\r
+ */\r
+ adr x4, _device_type\r
+ bl strcmp\r
+ cbnz w7, inc_and_next_tag\r
+ orr xMEMNODE, xMEMNODE, #HAVE_DEVICE_TYPE\r
+\r
+inc_and_next_tag:\r
+ add xDTP, xDTP, x6\r
+ b next_tag\r
+\r
+end_node:\r
+ /*\r
+ * Check for device_type = memory and reg = xxxx\r
+ * If we have both, we are done\r
+ */\r
+ add xDTP, xDTP, #4\r
+ cmp xMEMNODE, #(HAVE_REG | HAVE_DEVICE_TYPE)\r
+ bne next_tag\r
+\r
+ ret xLR\r
+\r
+err_invalid_magic:\r
+err_unexpected_begin_tag:\r
+err_unexpected_tag:\r
+err_end_of_fdt:\r
+ wfi\r
--- /dev/null
+#\r
+# Copyright (c) 2011-2013, 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 <AsmMacroIoLibV8.h>\r
+#include <Base.h>\r
+#include <Library/ArmLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <AutoGen.h>\r
+\r
+.text\r
+.align 2\r
+\r
+GCC_ASM_EXPORT(ArmPlatformPeiBootAction)\r
+GCC_ASM_EXPORT(ArmPlatformIsPrimaryCore)\r
+GCC_ASM_EXPORT(ArmPlatformGetPrimaryCoreMpId)\r
+GCC_ASM_EXPORT(ArmPlatformGetCorePosition)\r
+GCC_ASM_EXPORT(ArmGetPhysAddrTop)\r
+\r
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCore)\r
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCoreMask)\r
+GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdCoreCount)\r
+\r
+.LFdtMagic:\r
+ .byte 0xd0, 0x0d, 0xfe, 0xed\r
+\r
+.LArm64LinuxMagic:\r
+ .byte 0x41, 0x52, 0x4d, 0x64\r
+\r
+// VOID\r
+// ArmPlatformPeiBootAction (\r
+// VOID *DeviceTreeBaseAddress, // passed by loader in x0\r
+// VOID *ImageBase // passed by FDF trampoline in x1\r
+// );\r
+ASM_PFX(ArmPlatformPeiBootAction):\r
+ mov x29, x30 // preserve LR\r
+\r
+ //\r
+ // If we are booting from RAM using the Linux kernel boot protocol, x0 will\r
+ // point to the DTB image in memory. Otherwise, we are just coming out of\r
+ // reset, and x0 will be 0. Check also the FDT magic.\r
+ //\r
+ cbz x0, .Lout\r
+ ldr w8, .LFdtMagic\r
+ ldr w9, [x0]\r
+ cmp w8, w9\r
+ bne .Lout\r
+\r
+ //\r
+ // The base of the runtime image has been preserved in x1. Check whether\r
+ // the expected magic number can be found in the header.\r
+ //\r
+ ldr w8, .LArm64LinuxMagic\r
+ ldr w9, [x1, #0x38]\r
+ cmp w8, w9\r
+ bne .Lout\r
+\r
+ //\r
+ //\r
+ // OK, so far so good. We have confirmed that we likely have a DTB and are\r
+ // booting via the arm64 Linux boot protocol. Update the base-of-image PCD\r
+ // to the actual relocated value, and add the shift of PcdFdBaseAddress to\r
+ // PcdFvBaseAddress as well\r
+ //\r
+ adr x8, PcdGet64 (PcdFdBaseAddress)\r
+ adr x9, PcdGet64 (PcdFvBaseAddress)\r
+ ldr x6, [x8]\r
+ ldr x7, [x9]\r
+ sub x7, x7, x6\r
+ add x7, x7, x1\r
+ str x1, [x8]\r
+ str x7, [x9]\r
+\r
+ //\r
+ // Copy the DTB to the slack space right after the 64 byte arm64/Linux style\r
+ // image header at the base of this image (defined in the FDF), and record the\r
+ // pointer in PcdDeviceTreeInitialBaseAddress.\r
+ //\r
+ adr x8, PcdGet64 (PcdDeviceTreeInitialBaseAddress)\r
+ add x1, x1, #0x40\r
+ str x1, [x8]\r
+\r
+ ldr w8, [x0, #4] // get DTB size (BE)\r
+ mov x9, x1\r
+ rev w8, w8\r
+ add x8, x8, x0\r
+0:ldp x6, x7, [x0], #16\r
+ stp x6, x7, [x9], #16\r
+ cmp x0, x8\r
+ blt 0b\r
+\r
+ //\r
+ // Discover the memory size and offset from the DTB, and record in the\r
+ // respective PCDs\r
+ //\r
+ mov x0, x1\r
+ bl find_memnode // returns (size, base) size in (x0, x1)\r
+ cbz x0, .Lout\r
+\r
+ adr x8, PcdGet64 (PcdSystemMemorySize)\r
+ adr x9, PcdGet64 (PcdSystemMemoryBase)\r
+ str x0, [x8]\r
+ str x1, [x9]\r
+\r
+.Lout:\r
+ ret x29\r
+\r
+//UINTN\r
+//ArmPlatformGetPrimaryCoreMpId (\r
+// VOID\r
+// );\r
+ASM_PFX(ArmPlatformGetPrimaryCoreMpId):\r
+ LoadConstantToReg (_gPcd_FixedAtBuild_PcdArmPrimaryCore, x0)\r
+ ldrh w0, [x0]\r
+ ret\r
+\r
+//UINTN\r
+//ArmPlatformIsPrimaryCore (\r
+// IN UINTN MpId\r
+// );\r
+ASM_PFX(ArmPlatformIsPrimaryCore):\r
+ mov x0, #1\r
+ ret\r
+\r
+//UINTN\r
+//ArmPlatformGetCorePosition (\r
+// IN UINTN MpId\r
+// );\r
+// With this function: CorePos = (ClusterId * 4) + CoreId\r
+ASM_PFX(ArmPlatformGetCorePosition):\r
+ and x1, x0, #ARM_CORE_MASK\r
+ and x0, x0, #ARM_CLUSTER_MASK\r
+ add x0, x1, x0, LSR #6\r
+ ret\r
+\r
+//EFI_PHYSICAL_ADDRESS\r
+//GetPhysAddrTop (\r
+// VOID\r
+// );\r
+ASM_PFX(ArmGetPhysAddrTop):\r
+ mrs x0, id_aa64mmfr0_el1\r
+ adr x1, .LPARanges\r
+ and x0, x0, #7\r
+ ldrb w1, [x1, x0]\r
+ mov x0, #1\r
+ lsl x0, x0, x1\r
+ ret\r
+\r
+//\r
+// Bits 0..2 of the AA64MFR0_EL1 system register encode the size of the\r
+// physical address space support on this CPU:\r
+// 0 == 32 bits, 1 == 36 bits, etc etc\r
+// 6 and 7 are reserved\r
+//\r
+.LPARanges:\r
+ .byte 32, 36, 40, 42, 44, 48, -1, -1\r
+\r
+ASM_FUNCTION_REMOVE_IF_UNREFERENCED\r
--- /dev/null
+#/* @file\r
+# Copyright (c) 2011-2014, ARM Limited. All rights reserved.\r
+# Copyright (c) 2014, Linaro 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
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = ArmXenRelocatablePlatformLib\r
+ FILE_GUID = c8602718-4faa-4119-90ca-cae72509ac4c\r
+ MODULE_TYPE = BASE\r
+ VERSION_STRING = 1.0\r
+ LIBRARY_CLASS = ArmPlatformLib|SEC PEIM\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+ EmbeddedPkg/EmbeddedPkg.dec\r
+ ArmPkg/ArmPkg.dec\r
+ ArmPlatformPkg/ArmPlatformPkg.dec\r
+ ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec\r
+\r
+[LibraryClasses]\r
+ IoLib\r
+ ArmLib\r
+ PrintLib\r
+\r
+[Sources.common]\r
+ RelocatableVirt.c\r
+ XenVirtMem.c\r
+\r
+[Sources.AARCH64]\r
+ AARCH64/RelocatableVirtHelper.S\r
+ AARCH64/MemnodeParser.S\r
+\r
+[FeaturePcd]\r
+ gEmbeddedTokenSpaceGuid.PcdCacheEnable\r
+ gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec\r
+\r
+[PatchPcd]\r
+ gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress\r
+ gArmTokenSpaceGuid.PcdFdBaseAddress\r
+ gArmTokenSpaceGuid.PcdFvBaseAddress\r
+ gArmTokenSpaceGuid.PcdSystemMemoryBase\r
+ gArmTokenSpaceGuid.PcdSystemMemorySize\r
+\r
+[FixedPcd]\r
+ gArmPlatformTokenSpaceGuid.PcdCoreCount\r
+ gArmTokenSpaceGuid.PcdArmPrimaryCoreMask\r
+ gArmTokenSpaceGuid.PcdArmPrimaryCore\r
+ gArmTokenSpaceGuid.PcdFdSize\r
--- /dev/null
+/** @file\r
+*\r
+* Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
+* Copyright (c) 2014, Linaro Limited. All rights reserved.\r
+* Copyright (c) 2014, Red Hat, Inc.\r
+*\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/IoLib.h>\r
+#include <Library/ArmPlatformLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <ArmPlatform.h>\r
+#include <Pi/PiBootMode.h>\r
+\r
+/**\r
+ Return the current Boot Mode\r
+\r
+ This function returns the boot reason on the platform\r
+\r
+ @return Return the current Boot Mode of the platform\r
+\r
+**/\r
+EFI_BOOT_MODE\r
+ArmPlatformGetBootMode (\r
+ VOID\r
+ )\r
+{\r
+ return BOOT_WITH_FULL_CONFIGURATION;\r
+}\r
+\r
+/**\r
+ This function is called by PrePeiCore, in the SEC phase.\r
+**/\r
+RETURN_STATUS\r
+ArmPlatformInitialize (\r
+ IN UINTN MpId\r
+ )\r
+{\r
+ //\r
+ // We are relying on ArmPlatformInitializeSystemMemory () being called from\r
+ // InitializeMemory (), which only occurs if the following feature is disabled\r
+ //\r
+ ASSERT (!FeaturePcdGet (PcdSystemMemoryInitializeInSec));\r
+ return RETURN_SUCCESS;\r
+}\r
+\r
+VOID\r
+ArmPlatformInitializeSystemMemory (\r
+ VOID\r
+ )\r
+{\r
+}\r
+\r
+VOID\r
+ArmPlatformGetPlatformPpiList (\r
+ OUT UINTN *PpiListSize,\r
+ OUT EFI_PEI_PPI_DESCRIPTOR **PpiList\r
+ )\r
+{\r
+ *PpiListSize = 0;\r
+ *PpiList = NULL;\r
+}\r
--- /dev/null
+/** @file\r
+*\r
+* Copyright (c) 2014, Linaro 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 <Library/ArmPlatformLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <ArmPlatform.h>\r
+\r
+// Number of Virtual Memory Map Descriptors\r
+#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 2\r
+\r
+// DDR attributes\r
+#define DDR_ATTRIBUTES_CACHED ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK\r
+#define DDR_ATTRIBUTES_UNCACHED ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED\r
+\r
+EFI_PHYSICAL_ADDRESS\r
+ArmGetPhysAddrTop (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Return the Virtual Memory Map of your platform\r
+\r
+ This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU\r
+ on your platform.\r
+\r
+ @param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_DESCRIPTOR\r
+ describing a Physical-to-Virtual Memory\r
+ mapping. This array must be ended by a\r
+ zero-filled entry\r
+\r
+**/\r
+VOID\r
+ArmPlatformGetVirtualMemoryMap (\r
+ IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap\r
+ )\r
+{\r
+ ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable;\r
+\r
+ ASSERT (VirtualMemoryMap != NULL);\r
+\r
+ VirtualMemoryTable = AllocatePages (\r
+ EFI_SIZE_TO_PAGES (\r
+ sizeof (ARM_MEMORY_REGION_DESCRIPTOR)\r
+ * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS\r
+ )\r
+ );\r
+\r
+ if (VirtualMemoryTable == NULL) {\r
+ DEBUG ((EFI_D_ERROR, "%a: Error: Failed AllocatePages()\n", __FUNCTION__));\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Map the entire physical memory space as cached. The only device\r
+ // we care about is the GIC, which will be stage 2 mapped as a device\r
+ // by the hypervisor, which will override the cached mapping we install\r
+ // here.\r
+ //\r
+ VirtualMemoryTable[0].PhysicalBase = 0x0;\r
+ VirtualMemoryTable[0].VirtualBase = 0x0;\r
+ VirtualMemoryTable[0].Length = ArmGetPhysAddrTop ();\r
+ VirtualMemoryTable[0].Attributes = DDR_ATTRIBUTES_CACHED;\r
+\r
+ // End of Table\r
+ ZeroMem (&VirtualMemoryTable[1], sizeof (ARM_MEMORY_REGION_DESCRIPTOR));\r
+\r
+ *VirtualMemoryMap = VirtualMemoryTable;\r
+}\r