Hello all,
This series is part of the Xen stuff I am working on, and due to some circumstances particular to my situation (i.e., no easy access to hardware) I have decided to prototype as much as I can on QEMU, which like Xen, uses the kernel boot protocol, as documented in linux/Documentation/arm64/booting.txt
This is a RFC series to probe whether the approach taken here is acceptable. If not, there should be an update to Xen/arm to implement a specific bootloader boot protocol in addition to the kernel boot protocol it supports currently. But if it is, there may be other interesting uses, e.g., as a chainloader so that any platform can easily support UEFI booting if it already supports arm64. This would require a NOR flash in the device tree, and some standard bus type (SATA, PCI) to hold the block device containing the OS, but other than that, it seems that most of what is required is already in place.
Note the hacky use of fixed PCDs: these are supposed to be read-only, obviously, but I am updating them in code regardless. It would probably be more consistent to use PatchableInModule PCDs instead, and I will make the required changes if the overall direction is deemed appropriate.
I have included the QemuKernel.dsc: this is just a proof of concept, it works under 'qemu-system-aarch64 -kernel' whose RAM is at 0x4000_0000 whereas the .DSC puts the RAM at 0x0. The relocatable PrePi and the new lib flavours work together to relocate the PrePi and set the environment according to the device tree before launching the DXE core. From that point, everything operates as before.
Ard Biesheuvel (8): ArmVirtualizationPkg: move early UART discovery to PlatformPeim ArmVirtualizationPkg: use a HOB to store device tree blob ArmPlatformPkg: replace some instances of FixedPcdGetXX() with PcdGetXX() ArmPlatformPkg/PrePi: allow unicore build to execute on mpcore system ArmPlatformPkg/PrePi: add a relocatable version of PrePi ArmVirtualizationPkg: implement a relocatable platformlib instance ArmVirtualizationPkg: implement custom MemoryInitPeiLib ArmVirtualizationPkg: add Qemu -kernel platform description
.../ArmVirtualizationPkg/ArmVirtualizationPkg.dec | 3 +- .../ArmVirtualizationPkg/ArmVirtualizationQemu.dsc | 3 - .../ArmVirtualizationQemuKernel.dsc | 263 ++++++++++++++++ .../ArmVirtualizationQemuKernel.fdf | 334 +++++++++++++++++++++ .../ArmVirtualizationPkg/Include/Guid/FdtHob.h | 26 ++ .../ArmVirtualizationMemoryInitPeiLib.c | 91 ++++++ .../ArmVirtualizationMemoryInitPeiLib.inf | 64 ++++ .../AARCH64/MemnodeParser.S | 224 ++++++++++++++ .../AARCH64/RelocatableVirtHelper.S | 177 +++++++++++ .../ArmVirtRelocatablePlatformLib.inf | 66 ++++ .../ArmVirtualizationPlatformLib.inf | 1 + .../ArmVirtualizationPlatformLib/RelocatableVirt.c | 78 +++++ .../Library/ArmVirtualizationPlatformLib/Virt.c | 46 +-- .../EarlyFdtPL011SerialPortLib.c | 2 +- .../Library/PlatformPeiLib/PlatformPeiLib.c | 60 +++- .../Library/PlatformPeiLib/PlatformPeiLib.inf | 3 - .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c | 10 +- .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf | 2 +- ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S | 49 ++- ArmPlatformPkg/PrePi/MainMPCore.c | 2 +- ArmPlatformPkg/PrePi/MainUniCore.c | 2 +- ArmPlatformPkg/PrePi/MainUniCoreRelocatable.c | 38 +++ ArmPlatformPkg/PrePi/PeiUniCoreRelocatable.inf | 108 +++++++ ArmPlatformPkg/PrePi/PrePi.c | 25 +- ArmPlatformPkg/PrePi/PrePi.h | 3 +- ArmPlatformPkg/PrePi/Scripts/PrePi-PIE.lds | 28 ++ 26 files changed, 1619 insertions(+), 89 deletions(-) create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.dsc create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.fdf create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/AARCH64/MemnodeParser.S create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/AARCH64/RelocatableVirtHelper.S create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtRelocatablePlatformLib.inf create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/RelocatableVirt.c create mode 100644 ArmPlatformPkg/PrePi/MainUniCoreRelocatable.c create mode 100755 ArmPlatformPkg/PrePi/PeiUniCoreRelocatable.inf create mode 100644 ArmPlatformPkg/PrePi/Scripts/PrePi-PIE.lds
This is partially motivated by the desire to use PrePi in a virt environment, and in that configuration, ArmPlatformInitializeMemory() is never called. But actually, this is a more suitable place anyway.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- .../Library/ArmVirtualizationPlatformLib/Virt.c | 46 +-------------------- .../Library/PlatformPeiLib/PlatformPeiLib.c | 48 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 44 deletions(-)
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c index aa4ced4582e8..463a6d6d3b9b 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c @@ -24,9 +24,6 @@ #include <Pi/PiBootMode.h> #include <Uefi/UefiBaseType.h> #include <Uefi/UefiMultiPhase.h> -#include <Pi/PiHob.h> -#include <Library/HobLib.h> -#include <Guid/EarlyPL011BaseAddress.h>
/** Return the current Boot Mode @@ -77,25 +74,13 @@ ArmPlatformInitializeSystemMemory ( INT32 Node, Prev; UINT64 NewBase; UINT64 NewSize; - BOOLEAN HaveMemory, HaveUART; - UINT64 *HobData; CONST CHAR8 *Type; - CONST CHAR8 *Compatible; - CONST CHAR8 *CompItem; INT32 Len; CONST UINT64 *RegProp; - UINT64 UartBase;
NewBase = 0; NewSize = 0;
- HaveMemory = FALSE; - HaveUART = FALSE; - - HobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *HobData); - ASSERT (HobData != NULL); - *HobData = 0; - DeviceTreeBase = (VOID *)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (DeviceTreeBase != NULL);
@@ -107,7 +92,7 @@ ArmPlatformInitializeSystemMemory ( // // Look for a memory node // - for (Prev = 0; !(HaveMemory && HaveUART); Prev = Node) { + for (Prev = 0;; Prev = Node) { Node = fdt_next_node (DeviceTreeBase, Prev, NULL); if (Node < 0) { break; @@ -140,34 +125,7 @@ ArmPlatformInitializeSystemMemory ( DEBUG ((EFI_D_ERROR, "%a: Failed to parse FDT memory node\n", __FUNCTION__)); } - HaveMemory = TRUE; - continue; - } - - // - // Check for UART node - // - Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len); - - // - // Iterate over the NULL-separated items in the compatible string - // - for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len; - CompItem += 1 + AsciiStrLen (CompItem)) { - - if (AsciiStrCmp (CompItem, "arm,pl011") == 0) { - RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); - ASSERT (Len == 16); - - UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp)); - - DEBUG ((EFI_D_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase)); - - *HobData = UartBase; - - HaveUART = TRUE; - continue; - } + break; } }
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c index af0d6e87da9f..58bc2b828dcd 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c @@ -21,6 +21,8 @@ #include <Library/PcdLib.h> #include <libfdt.h>
+#include <Guid/EarlyPL011BaseAddress.h> + EFI_STATUS EFIAPI PlatformPeim ( @@ -30,6 +32,14 @@ PlatformPeim ( VOID *Base; VOID *NewBase; UINTN FdtSize; + UINT64 *UartHobData; + INT32 Node, Prev; + CONST CHAR8 *Compatible; + CONST CHAR8 *CompItem; + INT32 Len; + CONST UINT64 *RegProp; + UINT64 UartBase; +
Base = (VOID*)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (fdt_check_header (Base) == 0); @@ -41,6 +51,44 @@ PlatformPeim ( CopyMem (NewBase, Base, FdtSize); PcdSet64 (PcdDeviceTreeBaseAddress, (UINT64)(UINTN)NewBase);
+ UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData); + ASSERT (UartHobData != NULL); + *UartHobData = 0; + + // + // Look for a UART node + // + for (Prev = 0;; Prev = Node) { + Node = fdt_next_node (Base, Prev, NULL); + if (Node < 0) { + break; + } + + // + // Check for UART node + // + Compatible = fdt_getprop (Base, Node, "compatible", &Len); + + // + // Iterate over the NULL-separated items in the compatible string + // + for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len; + CompItem += 1 + AsciiStrLen (CompItem)) { + + if (AsciiStrCmp (CompItem, "arm,pl011") == 0) { + RegProp = fdt_getprop (Base, Node, "reg", &Len); + ASSERT (Len == 16); + + UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp)); + + DEBUG ((EFI_D_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase)); + + *UartHobData = UartBase; + break; + } + } + } + BuildFvHob (PcdGet64 (PcdFvBaseAddress), PcdGet32 (PcdFvSize));
return EFI_SUCCESS;
On 12/08/14 19:22, Ard Biesheuvel wrote:
This is partially motivated by the desire to use PrePi in a virt environment, and in that configuration, ArmPlatformInitializeMemory()
Typo in commit message, should say ArmPlatformInitializeSystemMemory().
is never called. But actually, this is a more suitable place anyway.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org
.../Library/ArmVirtualizationPlatformLib/Virt.c | 46 +-------------------- .../Library/PlatformPeiLib/PlatformPeiLib.c | 48 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 44 deletions(-)
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c index aa4ced4582e8..463a6d6d3b9b 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c @@ -24,9 +24,6 @@ #include <Pi/PiBootMode.h> #include <Uefi/UefiBaseType.h> #include <Uefi/UefiMultiPhase.h> -#include <Pi/PiHob.h> -#include <Library/HobLib.h> -#include <Guid/EarlyPL011BaseAddress.h> /** Return the current Boot Mode @@ -77,25 +74,13 @@ ArmPlatformInitializeSystemMemory ( INT32 Node, Prev; UINT64 NewBase; UINT64 NewSize;
- BOOLEAN HaveMemory, HaveUART;
- UINT64 *HobData; CONST CHAR8 *Type;
- CONST CHAR8 *Compatible;
- CONST CHAR8 *CompItem; INT32 Len; CONST UINT64 *RegProp;
- UINT64 UartBase;
NewBase = 0; NewSize = 0;
- HaveMemory = FALSE;
- HaveUART = FALSE;
- HobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *HobData);
- ASSERT (HobData != NULL);
- *HobData = 0;
- DeviceTreeBase = (VOID *)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (DeviceTreeBase != NULL);
@@ -107,7 +92,7 @@ ArmPlatformInitializeSystemMemory ( // // Look for a memory node //
- for (Prev = 0; !(HaveMemory && HaveUART); Prev = Node) {
- for (Prev = 0;; Prev = Node) { Node = fdt_next_node (DeviceTreeBase, Prev, NULL); if (Node < 0) { break;
@@ -140,34 +125,7 @@ ArmPlatformInitializeSystemMemory ( DEBUG ((EFI_D_ERROR, "%a: Failed to parse FDT memory node\n", __FUNCTION__)); }
HaveMemory = TRUE;
continue;
- }
- //
- // Check for UART node
- //
- Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
- //
- // Iterate over the NULL-separated items in the compatible string
- //
- for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len;
CompItem += 1 + AsciiStrLen (CompItem)) {
if (AsciiStrCmp (CompItem, "arm,pl011") == 0) {
RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
ASSERT (Len == 16);
UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
DEBUG ((EFI_D_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase));
*HobData = UartBase;
HaveUART = TRUE;
continue;
}
} }break;
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c index af0d6e87da9f..58bc2b828dcd 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c @@ -21,6 +21,8 @@ #include <Library/PcdLib.h> #include <libfdt.h> +#include <Guid/EarlyPL011BaseAddress.h>
EFI_STATUS EFIAPI PlatformPeim ( @@ -30,6 +32,14 @@ PlatformPeim ( VOID *Base; VOID *NewBase; UINTN FdtSize;
- UINT64 *UartHobData;
- INT32 Node, Prev;
- CONST CHAR8 *Compatible;
- CONST CHAR8 *CompItem;
- INT32 Len;
- CONST UINT64 *RegProp;
- UINT64 UartBase;
Base = (VOID*)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (fdt_check_header (Base) == 0); @@ -41,6 +51,44 @@ PlatformPeim ( CopyMem (NewBase, Base, FdtSize); PcdSet64 (PcdDeviceTreeBaseAddress, (UINT64)(UINTN)NewBase);
- UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData);
- ASSERT (UartHobData != NULL);
- *UartHobData = 0;
- //
- // Look for a UART node
- //
- for (Prev = 0;; Prev = Node) {
- Node = fdt_next_node (Base, Prev, NULL);
- if (Node < 0) {
break;
- }
- //
- // Check for UART node
- //
- Compatible = fdt_getprop (Base, Node, "compatible", &Len);
- //
- // Iterate over the NULL-separated items in the compatible string
- //
- for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len;
CompItem += 1 + AsciiStrLen (CompItem)) {
if (AsciiStrCmp (CompItem, "arm,pl011") == 0) {
RegProp = fdt_getprop (Base, Node, "reg", &Len);
ASSERT (Len == 16);
UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
DEBUG ((EFI_D_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase));
*UartHobData = UartBase;
break;
}
- }
- }
- BuildFvHob (PcdGet64 (PcdFvBaseAddress), PcdGet32 (PcdFvSize));
return EFI_SUCCESS;
The discovery code that is being moved is kept intact.
The source module (ie. the module that the original code is embedded into during build) is "ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf", which has module type PEIM.
The target module is "ArmPlatformPkg/PlatformPei/PlatformPeim.inf", which is also of type PEIM.
These modules are both part of [FV.FVMAIN_COMPACT] in "ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.fdf", and their dispatch order is unspecified (neither is listed in APRIORI PEI). So neither can depend on anything the other does, which means we're allowed to move code between them.
Reviewed-by: Laszlo Ersek lersek@redhat.com
On 12/10/14 11:59, Laszlo Ersek wrote:
On 12/08/14 19:22, Ard Biesheuvel wrote:
This is partially motivated by the desire to use PrePi in a virt environment, and in that configuration, ArmPlatformInitializeMemory()
Typo in commit message, should say ArmPlatformInitializeSystemMemory().
is never called. But actually, this is a more suitable place anyway.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org
.../Library/ArmVirtualizationPlatformLib/Virt.c | 46 +-------------------- .../Library/PlatformPeiLib/PlatformPeiLib.c | 48 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 44 deletions(-)
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c index aa4ced4582e8..463a6d6d3b9b 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/Virt.c @@ -24,9 +24,6 @@ #include <Pi/PiBootMode.h> #include <Uefi/UefiBaseType.h> #include <Uefi/UefiMultiPhase.h> -#include <Pi/PiHob.h> -#include <Library/HobLib.h> -#include <Guid/EarlyPL011BaseAddress.h> /** Return the current Boot Mode @@ -77,25 +74,13 @@ ArmPlatformInitializeSystemMemory ( INT32 Node, Prev; UINT64 NewBase; UINT64 NewSize;
- BOOLEAN HaveMemory, HaveUART;
- UINT64 *HobData; CONST CHAR8 *Type;
- CONST CHAR8 *Compatible;
- CONST CHAR8 *CompItem; INT32 Len; CONST UINT64 *RegProp;
- UINT64 UartBase;
NewBase = 0; NewSize = 0;
- HaveMemory = FALSE;
- HaveUART = FALSE;
- HobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *HobData);
- ASSERT (HobData != NULL);
- *HobData = 0;
- DeviceTreeBase = (VOID *)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (DeviceTreeBase != NULL);
@@ -107,7 +92,7 @@ ArmPlatformInitializeSystemMemory ( // // Look for a memory node //
- for (Prev = 0; !(HaveMemory && HaveUART); Prev = Node) {
- for (Prev = 0;; Prev = Node) { Node = fdt_next_node (DeviceTreeBase, Prev, NULL); if (Node < 0) { break;
@@ -140,34 +125,7 @@ ArmPlatformInitializeSystemMemory ( DEBUG ((EFI_D_ERROR, "%a: Failed to parse FDT memory node\n", __FUNCTION__)); }
HaveMemory = TRUE;
continue;
- }
- //
- // Check for UART node
- //
- Compatible = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
- //
- // Iterate over the NULL-separated items in the compatible string
- //
- for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len;
CompItem += 1 + AsciiStrLen (CompItem)) {
if (AsciiStrCmp (CompItem, "arm,pl011") == 0) {
RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
ASSERT (Len == 16);
UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
DEBUG ((EFI_D_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase));
*HobData = UartBase;
HaveUART = TRUE;
continue;
}
} }break;
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c index af0d6e87da9f..58bc2b828dcd 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c @@ -21,6 +21,8 @@ #include <Library/PcdLib.h> #include <libfdt.h> +#include <Guid/EarlyPL011BaseAddress.h>
EFI_STATUS EFIAPI PlatformPeim ( @@ -30,6 +32,14 @@ PlatformPeim ( VOID *Base; VOID *NewBase; UINTN FdtSize;
- UINT64 *UartHobData;
- INT32 Node, Prev;
- CONST CHAR8 *Compatible;
- CONST CHAR8 *CompItem;
- INT32 Len;
- CONST UINT64 *RegProp;
- UINT64 UartBase;
Base = (VOID*)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (fdt_check_header (Base) == 0); @@ -41,6 +51,44 @@ PlatformPeim ( CopyMem (NewBase, Base, FdtSize); PcdSet64 (PcdDeviceTreeBaseAddress, (UINT64)(UINTN)NewBase);
- UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData);
- ASSERT (UartHobData != NULL);
- *UartHobData = 0;
- //
- // Look for a UART node
- //
- for (Prev = 0;; Prev = Node) {
- Node = fdt_next_node (Base, Prev, NULL);
- if (Node < 0) {
break;
- }
- //
- // Check for UART node
- //
- Compatible = fdt_getprop (Base, Node, "compatible", &Len);
- //
- // Iterate over the NULL-separated items in the compatible string
- //
- for (CompItem = Compatible; CompItem != NULL && CompItem < Compatible + Len;
CompItem += 1 + AsciiStrLen (CompItem)) {
if (AsciiStrCmp (CompItem, "arm,pl011") == 0) {
RegProp = fdt_getprop (Base, Node, "reg", &Len);
ASSERT (Len == 16);
UartBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
DEBUG ((EFI_D_INFO, "%a: PL011 UART @ 0x%lx\n", __FUNCTION__, UartBase));
*UartHobData = UartBase;
break;
}
- }
- }
- BuildFvHob (PcdGet64 (PcdFvBaseAddress), PcdGet32 (PcdFvSize));
return EFI_SUCCESS;
The discovery code that is being moved is kept intact.
The source module (ie. the module that the original code is embedded into during build) is "ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf", which has module type PEIM.
The target module is "ArmPlatformPkg/PlatformPei/PlatformPeim.inf", which is also of type PEIM.
These modules are both part of [FV.FVMAIN_COMPACT] in "ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.fdf", and their dispatch order is unspecified (neither is listed in APRIORI PEI).
I was wrong about the dispatch order; these two modules are serialized by the gEfiPeiMemoryDiscoveredPpiGuid [Depex] of "ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf".
That PPI GUID is installed by the PEI core sometime after the PeiServicesInstallPeiMemory() call in "ArmPlatformPkg/MemoryInitPei/MemoryInitPeim.inf". (temporary ram migration etc.)
This patch is nonetheless correct; the HOB with gEarlyPL011BaseAddressGuid is needed in the DXE_CORE at the earliest (via "ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/FdtPL011SerialPortLib.inf').
So neither can depend on anything the other does, which means we're allowed to move code between them.
Reviewed-by: Laszlo Ersek lersek@redhat.com
So the R-b stands.
Laszlo
Instead of using AllocatePages() and a dynamic PCD, store the device tree data in a HOB so that we can also run under a configuration that does not support dynamic PCDs.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- .../ArmVirtualizationPkg/ArmVirtualizationPkg.dec | 3 +-- .../ArmVirtualizationPkg/ArmVirtualizationQemu.dsc | 3 --- .../ArmVirtualizationPkg/Include/Guid/FdtHob.h | 26 ++++++++++++++++++++++ .../ArmVirtualizationPlatformLib.inf | 1 + .../Library/PlatformPeiLib/PlatformPeiLib.c | 12 +++++----- .../Library/PlatformPeiLib/PlatformPeiLib.inf | 3 --- .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c | 10 +++++++-- .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf | 2 +- 8 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec index b581add024aa..55a9b8ce7562 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec +++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec @@ -33,6 +33,7 @@ [Guids.common] gArmVirtualizationTokenSpaceGuid = { 0x0B6F5CA7, 0x4F53, 0x445A, { 0xB7, 0x6E, 0x2E, 0x36, 0x5B, 0x80, 0x63, 0x66 } } gEarlyPL011BaseAddressGuid = { 0xB199DEA9, 0xFD5C, 0x4A84, { 0x80, 0x82, 0x2F, 0x41, 0x70, 0x78, 0x03, 0x05 } } + gFdtHobGuid = { 0x16958446, 0x19B7, 0x480B, { 0xB0, 0x47, 0x74, 0x85, 0xAD, 0x3F, 0x71, 0x6D } }
[PcdsFixedAtBuild] # @@ -44,8 +45,6 @@ gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress|0x0|UINT64|0x00000001
[PcdsDynamic, PcdsFixedAtBuild] - gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x0|UINT64|0x00000002 - # # ARM PSCI function invocations can be done either through hypervisor # calls (HVC) or secure monitor calls (SMC). diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc index c7066b091cb8..395bf217e149 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc +++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc @@ -154,9 +154,6 @@ # System Memory Size -- 1 MB initially, actual size will be fetched from DT gArmTokenSpaceGuid.PcdSystemMemorySize|0x00100000
- # location of the device tree blob passed by QEMU - gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x0 - gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum|0x0 gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x0 gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x0 diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h b/ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h new file mode 100644 index 000000000000..79b06e935700 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h @@ -0,0 +1,26 @@ +/** @file + GUID for the HOB that contains the copy of the flattened device tree blob + + Copyright (C) 2014, Linaro Ltd. + + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License that accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __FDT_HOB_H__ +#define __FDT_HOB_H__ + +#define FDT_HOB_H_GUID { \ + 0x16958446, 0x19B7, 0x480B, \ + { 0xB0, 0x47, 0x74, 0x85, 0xAD, 0x3F, 0x71, 0x6D } \ + } + +extern EFI_GUID gFdtHobGuid; + +#endif diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf index 57bebff13ef8..679192bb0485 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf @@ -65,3 +65,4 @@
[Guids] gEarlyPL011BaseAddressGuid + gFdtHobGuid diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c index 58bc2b828dcd..d180a01415b0 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c @@ -22,6 +22,7 @@ #include <libfdt.h>
#include <Guid/EarlyPL011BaseAddress.h> +#include <Guid/FdtHob.h>
EFI_STATUS EFIAPI @@ -30,8 +31,8 @@ PlatformPeim ( ) { VOID *Base; - VOID *NewBase; UINTN FdtSize; + UINT64 *FdtHobData; UINT64 *UartHobData; INT32 Node, Prev; CONST CHAR8 *Compatible; @@ -44,12 +45,11 @@ PlatformPeim ( Base = (VOID*)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (fdt_check_header (Base) == 0);
+ fdt_pack (Base); FdtSize = fdt_totalsize (Base); - NewBase = AllocatePages (EFI_SIZE_TO_PAGES (FdtSize)); - ASSERT (NewBase != NULL); - - CopyMem (NewBase, Base, FdtSize); - PcdSet64 (PcdDeviceTreeBaseAddress, (UINT64)(UINTN)NewBase); + FdtHobData = BuildGuidHob (&gFdtHobGuid, FdtSize); + ASSERT (FdtHobData != NULL); + CopyMem (FdtHobData, Base, FdtSize);
UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData); ASSERT (UartHobData != NULL); diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf index e544b528d261..12b24db63313 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf @@ -41,8 +41,5 @@ gArmTokenSpaceGuid.PcdFvSize gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
-[Pcd] - gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress - [Depex] gEfiPeiMemoryDiscoveredPpiGuid diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c index d002e668aa48..14879387864c 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c @@ -24,9 +24,11 @@ #include <Library/DevicePathLib.h> #include <Library/PcdLib.h> #include <Library/DxeServicesLib.h> +#include <Library/HobLib.h> #include <libfdt.h>
#include <Guid/Fdt.h> +#include <Guid/FdtHob.h>
#pragma pack (1) typedef struct { @@ -100,6 +102,7 @@ InitializeVirtFdtDxe ( IN EFI_SYSTEM_TABLE *SystemTable ) { + VOID *Hob; VOID *DeviceTreeBase; INT32 Node, Prev; INT32 RtcNode; @@ -116,8 +119,11 @@ InitializeVirtFdtDxe ( INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum; CONST CHAR8 *PsciMethod;
- DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeBaseAddress); - ASSERT (DeviceTreeBase != NULL); + Hob = GetFirstGuidHob(&gFdtHobGuid); + if (Hob == NULL) { + return EFI_NOT_FOUND; + } + DeviceTreeBase = GET_GUID_HOB_DATA (Hob);
if (fdt_check_header (DeviceTreeBase) != 0) { DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%p\n", __FUNCTION__, DeviceTreeBase)); diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf index 1c9dd20580c4..2ea6b6f8156d 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf +++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf @@ -43,9 +43,9 @@
[Guids] gFdtTableGuid + gFdtHobGuid
[Pcd] - gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress gArmVirtualizationTokenSpaceGuid.PcdArmPsciMethod gArmTokenSpaceGuid.PcdGicDistributorBase gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
comments below
On 12/08/14 19:22, Ard Biesheuvel wrote:
Instead of using AllocatePages() and a dynamic PCD, store the device tree data in a HOB so that we can also run under a configuration that does not support dynamic PCDs.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org
.../ArmVirtualizationPkg/ArmVirtualizationPkg.dec | 3 +-- .../ArmVirtualizationPkg/ArmVirtualizationQemu.dsc | 3 --- .../ArmVirtualizationPkg/Include/Guid/FdtHob.h | 26 ++++++++++++++++++++++ .../ArmVirtualizationPlatformLib.inf | 1 + .../Library/PlatformPeiLib/PlatformPeiLib.c | 12 +++++----- .../Library/PlatformPeiLib/PlatformPeiLib.inf | 3 --- .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c | 10 +++++++-- .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf | 2 +- 8 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h
suggestion (that I should keep in mind myself as well): when formatting edk2 patchsets, please pass --stat=150 or something similar to git-format-patch. The project uses unreasonably long filenames and deep directory nesting, so without --stat=150 the diffstat is not really useful.
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec index b581add024aa..55a9b8ce7562 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec +++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec @@ -33,6 +33,7 @@ [Guids.common] gArmVirtualizationTokenSpaceGuid = { 0x0B6F5CA7, 0x4F53, 0x445A, { 0xB7, 0x6E, 0x2E, 0x36, 0x5B, 0x80, 0x63, 0x66 } } gEarlyPL011BaseAddressGuid = { 0xB199DEA9, 0xFD5C, 0x4A84, { 0x80, 0x82, 0x2F, 0x41, 0x70, 0x78, 0x03, 0x05 } }
- gFdtHobGuid = { 0x16958446, 0x19B7, 0x480B, { 0xB0, 0x47, 0x74, 0x85, 0xAD, 0x3F, 0x71, 0x6D } }
[PcdsFixedAtBuild] # @@ -44,8 +45,6 @@ gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress|0x0|UINT64|0x00000001 [PcdsDynamic, PcdsFixedAtBuild]
- gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x0|UINT64|0x00000002
- # # ARM PSCI function invocations can be done either through hypervisor # calls (HVC) or secure monitor calls (SMC).
If I'm counting right, all 6 uses of PcdDeviceTreeBaseAddress are removed, good.
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc index c7066b091cb8..395bf217e149 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc +++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc @@ -154,9 +154,6 @@ # System Memory Size -- 1 MB initially, actual size will be fetched from DT gArmTokenSpaceGuid.PcdSystemMemorySize|0x00100000
- # location of the device tree blob passed by QEMU
- gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x0
- gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum|0x0 gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x0 gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x0
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h b/ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h new file mode 100644 index 000000000000..79b06e935700 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h @@ -0,0 +1,26 @@ +/** @file
- GUID for the HOB that contains the copy of the flattened device tree blob
- Copyright (C) 2014, Linaro Ltd.
- This program and the accompanying materials are licensed and made available
- under the terms and conditions of the BSD License that accompanies this
- distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php.
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
- WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef __FDT_HOB_H__ +#define __FDT_HOB_H__
+#define FDT_HOB_H_GUID { \
0x16958446, 0x19B7, 0x480B, \
{ 0xB0, 0x47, 0x74, 0x85, 0xAD, 0x3F, 0x71, 0x6D } \
}
+extern EFI_GUID gFdtHobGuid;
+#endif
Looks good, except the structure initializer's name should not contain the "_H" substring. FDT_HOB_H_GUID --> FDT_HOB_GUID
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf index 57bebff13ef8..679192bb0485 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf @@ -65,3 +65,4 @@ [Guids] gEarlyPL011BaseAddressGuid
- gFdtHobGuid
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c index 58bc2b828dcd..d180a01415b0 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c @@ -22,6 +22,7 @@ #include <libfdt.h> #include <Guid/EarlyPL011BaseAddress.h> +#include <Guid/FdtHob.h> EFI_STATUS EFIAPI @@ -30,8 +31,8 @@ PlatformPeim ( ) { VOID *Base;
- VOID *NewBase; UINTN FdtSize;
- UINT64 *FdtHobData;
I would prefer if you changed the type of this variable to (VOID *).
UINT64 *UartHobData; INT32 Node, Prev; CONST CHAR8 *Compatible; @@ -44,12 +45,11 @@ PlatformPeim ( Base = (VOID*)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (fdt_check_header (Base) == 0);
- fdt_pack (Base);
This is okay, but please consider adding a *loud* comment here.
The dtb that QEMU exports at the moment is 64KB in size (FDT_MAX_SIZE in "device_tree.c"). See
qemu-system-aarch64 -M virt -machine dumpdtb=virt.dtb
I'm sure you've noticed that; I'll assume that your first new BuildGuidHob() call failed. That's because the BuildGuidHob() function in "MdePkg/Library/PeiHobLib/HobLib.c" limits the size to
(0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)))
Which is why you probably added fdt_pack().
The 64KB DTB that qemu currently exports for the virt machtype carries actually less than 5KB of payload, the rest is padding (for in-place updates I guess), which fdt_pack() trims in-place.
First question: can you guarantee that fdt_pack() trims the DTB in-place? CC'ing David Gibson.
This is the initial DTB we're talking about, the one that QEMU places at the base of DRAM in advance (and at reset).
Assuming the above packing (trimming) occurs in-place, we do have a nice margin here (58+ KB) for *normal* FDT nodes (ie. nodes that describe devices), but this change definitely shuts the door on any future ideas to place anything "blob-like" in the DTB. That's okay, and it does match our qemu plans, but you should still explain it in a loud comment at the top. (Also, CC'ing Peter.)
FdtSize = fdt_totalsize (Base);
- NewBase = AllocatePages (EFI_SIZE_TO_PAGES (FdtSize));
- ASSERT (NewBase != NULL);
- CopyMem (NewBase, Base, FdtSize);
- PcdSet64 (PcdDeviceTreeBaseAddress, (UINT64)(UINTN)NewBase);
- FdtHobData = BuildGuidHob (&gFdtHobGuid, FdtSize);
- ASSERT (FdtHobData != NULL);
- CopyMem (FdtHobData, Base, FdtSize);
UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData); ASSERT (UartHobData != NULL); diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf index e544b528d261..12b24db63313 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf @@ -41,8 +41,5 @@ gArmTokenSpaceGuid.PcdFvSize gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress -[Pcd]
- gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress
[Depex] gEfiPeiMemoryDiscoveredPpiGuid diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c index d002e668aa48..14879387864c 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c @@ -24,9 +24,11 @@ #include <Library/DevicePathLib.h> #include <Library/PcdLib.h> #include <Library/DxeServicesLib.h> +#include <Library/HobLib.h> #include <libfdt.h> #include <Guid/Fdt.h> +#include <Guid/FdtHob.h> #pragma pack (1) typedef struct { @@ -100,6 +102,7 @@ InitializeVirtFdtDxe ( IN EFI_SYSTEM_TABLE *SystemTable ) {
- VOID *Hob; VOID *DeviceTreeBase; INT32 Node, Prev; INT32 RtcNode;
@@ -116,8 +119,11 @@ InitializeVirtFdtDxe ( INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum; CONST CHAR8 *PsciMethod;
- DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeBaseAddress);
- ASSERT (DeviceTreeBase != NULL);
- Hob = GetFirstGuidHob(&gFdtHobGuid);
- if (Hob == NULL) {
- return EFI_NOT_FOUND;
- }
- DeviceTreeBase = GET_GUID_HOB_DATA (Hob);
Hm, I disagree.
You are going to do at least two things to the memory pointed-to by DeviceTreeBase: - link it into the UEFI system config table, with gBS->InstallConfigurationTable(), - you set the status of the RTC node to disabled, with fdt_setprop_string()
I'm probably just too paranoid, but I don't feel safe linking the guts of a HOB directly into the UEFI system table. Previously what we linked was an independently allocated memory area.
In addition, what you're modifying now with fdt_setprop_string is (a) the guts of a HOB, (b) that has even been packed.
Please *at least* do something like
DeviceTreeBase = AllocateCopyPool ( fdt_totalsize (GET_GUID_HOB_DATA (Hob)), GET_GUID_HOB_DATA (Hob) );
(and check the retval / return EFI_OUT_OF_RESOURCES).
But, preferably, allocate something bigger than the packed size (64KB could be a good choice), and "inflate" the packed FDT from the HOB contents into the newly allocated, bigger block, giving it again some "reserve" room, so that the later fdt_setprop_string() has a good chance to succeed.
(I might be wrong about how libfdt works.)
if (fdt_check_header (DeviceTreeBase) != 0) { DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%p\n", __FUNCTION__, DeviceTreeBase)); diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf index 1c9dd20580c4..2ea6b6f8156d 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf +++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf @@ -43,9 +43,9 @@ [Guids] gFdtTableGuid
- gFdtHobGuid
[Pcd]
- gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress gArmVirtualizationTokenSpaceGuid.PcdArmPsciMethod gArmTokenSpaceGuid.PcdGicDistributorBase gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
Looks okay other than that.
Thanks, Laszlo
On 10 December 2014 at 12:40, Laszlo Ersek lersek@redhat.com wrote:
comments below
On 12/08/14 19:22, Ard Biesheuvel wrote:
Instead of using AllocatePages() and a dynamic PCD, store the device tree data in a HOB so that we can also run under a configuration that does not support dynamic PCDs.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org
.../ArmVirtualizationPkg/ArmVirtualizationPkg.dec | 3 +-- .../ArmVirtualizationPkg/ArmVirtualizationQemu.dsc | 3 --- .../ArmVirtualizationPkg/Include/Guid/FdtHob.h | 26 ++++++++++++++++++++++ .../ArmVirtualizationPlatformLib.inf | 1 + .../Library/PlatformPeiLib/PlatformPeiLib.c | 12 +++++----- .../Library/PlatformPeiLib/PlatformPeiLib.inf | 3 --- .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c | 10 +++++++-- .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf | 2 +- 8 files changed, 43 insertions(+), 17 deletions(-) create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h
suggestion (that I should keep in mind myself as well): when formatting edk2 patchsets, please pass --stat=150 or something similar to git-format-patch. The project uses unreasonably long filenames and deep directory nesting, so without --stat=150 the diffstat is not really useful.
ok
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec index b581add024aa..55a9b8ce7562 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec +++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec @@ -33,6 +33,7 @@ [Guids.common] gArmVirtualizationTokenSpaceGuid = { 0x0B6F5CA7, 0x4F53, 0x445A, { 0xB7, 0x6E, 0x2E, 0x36, 0x5B, 0x80, 0x63, 0x66 } } gEarlyPL011BaseAddressGuid = { 0xB199DEA9, 0xFD5C, 0x4A84, { 0x80, 0x82, 0x2F, 0x41, 0x70, 0x78, 0x03, 0x05 } }
- gFdtHobGuid = { 0x16958446, 0x19B7, 0x480B, { 0xB0, 0x47, 0x74, 0x85, 0xAD, 0x3F, 0x71, 0x6D } }
[PcdsFixedAtBuild] # @@ -44,8 +45,6 @@ gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress|0x0|UINT64|0x00000001
[PcdsDynamic, PcdsFixedAtBuild]
- gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x0|UINT64|0x00000002
- # # ARM PSCI function invocations can be done either through hypervisor # calls (HVC) or secure monitor calls (SMC).
If I'm counting right, all 6 uses of PcdDeviceTreeBaseAddress are removed, good.
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc index c7066b091cb8..395bf217e149 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc +++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemu.dsc @@ -154,9 +154,6 @@ # System Memory Size -- 1 MB initially, actual size will be fetched from DT gArmTokenSpaceGuid.PcdSystemMemorySize|0x00100000
- # location of the device tree blob passed by QEMU
- gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress|0x0
- gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum|0x0 gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x0 gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x0
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h b/ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h new file mode 100644 index 000000000000..79b06e935700 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h @@ -0,0 +1,26 @@ +/** @file
- GUID for the HOB that contains the copy of the flattened device tree blob
- Copyright (C) 2014, Linaro Ltd.
- This program and the accompanying materials are licensed and made available
- under the terms and conditions of the BSD License that accompanies this
- distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php.
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
- WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef __FDT_HOB_H__ +#define __FDT_HOB_H__
+#define FDT_HOB_H_GUID { \
0x16958446, 0x19B7, 0x480B, \
{ 0xB0, 0x47, 0x74, 0x85, 0xAD, 0x3F, 0x71, 0x6D } \
}
+extern EFI_GUID gFdtHobGuid;
+#endif
Looks good, except the structure initializer's name should not contain the "_H" substring. FDT_HOB_H_GUID --> FDT_HOB_GUID
ok
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf index 57bebff13ef8..679192bb0485 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtualizationPlatformLib.inf @@ -65,3 +65,4 @@
[Guids] gEarlyPL011BaseAddressGuid
- gFdtHobGuid
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c index 58bc2b828dcd..d180a01415b0 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c @@ -22,6 +22,7 @@ #include <libfdt.h>
#include <Guid/EarlyPL011BaseAddress.h> +#include <Guid/FdtHob.h>
EFI_STATUS EFIAPI @@ -30,8 +31,8 @@ PlatformPeim ( ) { VOID *Base;
- VOID *NewBase; UINTN FdtSize;
- UINT64 *FdtHobData;
I would prefer if you changed the type of this variable to (VOID *).
ok
UINT64 *UartHobData; INT32 Node, Prev; CONST CHAR8 *Compatible; @@ -44,12 +45,11 @@ PlatformPeim ( Base = (VOID*)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (fdt_check_header (Base) == 0);
- fdt_pack (Base);
This is okay, but please consider adding a *loud* comment here.
The dtb that QEMU exports at the moment is 64KB in size (FDT_MAX_SIZE in "device_tree.c"). See
qemu-system-aarch64 -M virt -machine dumpdtb=virt.dtb
I'm sure you've noticed that; I'll assume that your first new BuildGuidHob() call failed. That's because the BuildGuidHob() function in "MdePkg/Library/PeiHobLib/HobLib.c" limits the size to
(0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)))
Which is why you probably added fdt_pack().
spot on :-)
The 64KB DTB that qemu currently exports for the virt machtype carries actually less than 5KB of payload, the rest is padding (for in-place updates I guess), which fdt_pack() trims in-place.
First question: can you guarantee that fdt_pack() trims the DTB in-place? CC'ing David Gibson.
This is the initial DTB we're talking about, the one that QEMU places at the base of DRAM in advance (and at reset).
Assuming the above packing (trimming) occurs in-place, we do have a nice margin here (58+ KB) for *normal* FDT nodes (ie. nodes that describe devices), but this change definitely shuts the door on any future ideas to place anything "blob-like" in the DTB. That's okay, and it does match our qemu plans, but you should still explain it in a loud comment at the top. (Also, CC'ing Peter.)
Well, considering all the concerns you raise (including the ones below), it is perhaps better to retain the old allocation, and pass the address via the HOB, instead of the payload itself. This was what I set out to do but then I realized it would be much easier to pass the entire DTB ...
FdtSize = fdt_totalsize (Base);
- NewBase = AllocatePages (EFI_SIZE_TO_PAGES (FdtSize));
- ASSERT (NewBase != NULL);
- CopyMem (NewBase, Base, FdtSize);
- PcdSet64 (PcdDeviceTreeBaseAddress, (UINT64)(UINTN)NewBase);
FdtHobData = BuildGuidHob (&gFdtHobGuid, FdtSize);
ASSERT (FdtHobData != NULL);
CopyMem (FdtHobData, Base, FdtSize);
UartHobData = BuildGuidHob (&gEarlyPL011BaseAddressGuid, sizeof *UartHobData); ASSERT (UartHobData != NULL);
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf index e544b528d261..12b24db63313 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.inf @@ -41,8 +41,5 @@ gArmTokenSpaceGuid.PcdFvSize gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
-[Pcd]
- gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress
[Depex] gEfiPeiMemoryDiscoveredPpiGuid diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c index d002e668aa48..14879387864c 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c @@ -24,9 +24,11 @@ #include <Library/DevicePathLib.h> #include <Library/PcdLib.h> #include <Library/DxeServicesLib.h> +#include <Library/HobLib.h> #include <libfdt.h>
#include <Guid/Fdt.h> +#include <Guid/FdtHob.h>
#pragma pack (1) typedef struct { @@ -100,6 +102,7 @@ InitializeVirtFdtDxe ( IN EFI_SYSTEM_TABLE *SystemTable ) {
- VOID *Hob; VOID *DeviceTreeBase; INT32 Node, Prev; INT32 RtcNode;
@@ -116,8 +119,11 @@ InitializeVirtFdtDxe ( INT32 SecIntrNum, IntrNum, VirtIntrNum, HypIntrNum; CONST CHAR8 *PsciMethod;
- DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeBaseAddress);
- ASSERT (DeviceTreeBase != NULL);
- Hob = GetFirstGuidHob(&gFdtHobGuid);
- if (Hob == NULL) {
- return EFI_NOT_FOUND;
- }
- DeviceTreeBase = GET_GUID_HOB_DATA (Hob);
Hm, I disagree.
You are going to do at least two things to the memory pointed-to by DeviceTreeBase:
- link it into the UEFI system config table, with gBS->InstallConfigurationTable(),
- you set the status of the RTC node to disabled, with fdt_setprop_string()
I'm probably just too paranoid, but I don't feel safe linking the guts of a HOB directly into the UEFI system table. Previously what we linked was an independently allocated memory area.
In addition, what you're modifying now with fdt_setprop_string is (a) the guts of a HOB, (b) that has even been packed.
yes, (b) is bad, thanks for pointing that out. It is highly unlikely that that call would succeed after shrinking the FDT to its minimum size.
Please *at least* do something like
DeviceTreeBase = AllocateCopyPool ( fdt_totalsize (GET_GUID_HOB_DATA (Hob)), GET_GUID_HOB_DATA (Hob) );
(and check the retval / return EFI_OUT_OF_RESOURCES).
But, preferably, allocate something bigger than the packed size (64KB could be a good choice), and "inflate" the packed FDT from the HOB contents into the newly allocated, bigger block, giving it again some "reserve" room, so that the later fdt_setprop_string() has a good chance to succeed.
(I might be wrong about how libfdt works.)
No you're right. The fdt_pack() by itself is OK, but it strips all the spare room to add new properties.
if (fdt_check_header (DeviceTreeBase) != 0) { DEBUG ((EFI_D_ERROR, "%a: No DTB found @ 0x%p\n", __FUNCTION__, DeviceTreeBase)); diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf index 1c9dd20580c4..2ea6b6f8156d 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf +++ b/ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf @@ -43,9 +43,9 @@
[Guids] gFdtTableGuid
- gFdtHobGuid
[Pcd]
- gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeBaseAddress gArmVirtualizationTokenSpaceGuid.PcdArmPsciMethod gArmTokenSpaceGuid.PcdGicDistributorBase gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
Looks okay other than that.
Thanks, Ard.
On 12/10/14 13:12, Ard Biesheuvel wrote:
Well, considering all the concerns you raise (including the ones below), it is perhaps better to retain the old allocation, and pass the address via the HOB, instead of the payload itself.
Good point, let's do that. :)
This was what I set out to do but then I realized it would be much easier to pass the entire DTB ...
So that's why the "FdtHobData" local variable has type (UINT64 *) in the patch, rather than (VOID *). Because originally you only wanted to store an address in the HOB. :)
Laszlo
On 10 December 2014 at 11:40, Laszlo Ersek lersek@redhat.com wrote:
The dtb that QEMU exports at the moment is 64KB in size (FDT_MAX_SIZE in "device_tree.c"). See
qemu-system-aarch64 -M virt -machine dumpdtb=virt.dtb
I'm sure you've noticed that; I'll assume that your first new BuildGuidHob() call failed. That's because the BuildGuidHob() function in "MdePkg/Library/PeiHobLib/HobLib.c" limits the size to
(0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)))
Which is why you probably added fdt_pack().
The 64KB DTB that qemu currently exports for the virt machtype carries actually less than 5KB of payload, the rest is padding (for in-place updates I guess), which fdt_pack() trims in-place.
Hmm. That seems like a bug in QEMU to me -- we should probably be trimming down the dtb we create ourselves. In any case I wouldn't recommend making an guest assumptions about the presence or absence of that padding or whether it might end up more than 64K in future.
-- PMM
On 12/10/14 13:25, Peter Maydell wrote:
On 10 December 2014 at 11:40, Laszlo Ersek lersek@redhat.com wrote:
The dtb that QEMU exports at the moment is 64KB in size (FDT_MAX_SIZE in "device_tree.c"). See
qemu-system-aarch64 -M virt -machine dumpdtb=virt.dtb
I'm sure you've noticed that; I'll assume that your first new BuildGuidHob() call failed. That's because the BuildGuidHob() function in "MdePkg/Library/PeiHobLib/HobLib.c" limits the size to
(0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)))
Which is why you probably added fdt_pack().
The 64KB DTB that qemu currently exports for the virt machtype carries actually less than 5KB of payload, the rest is padding (for in-place updates I guess), which fdt_pack() trims in-place.
Hmm. That seems like a bug in QEMU to me -- we should probably be trimming down the dtb we create ourselves. In any case I wouldn't recommend making an guest assumptions about the presence or absence of that padding or whether it might end up more than 64K in future.
Ard, if you want to prepare for the case that the current padding disappears and want to add some reserve to the DTB, I think it would be best done in PEI, where you copy from the initial place to the dynamically allocated place anyway.
(ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c, PlatformPeim().)
Because, elsewhere, you could only do it in VirtFdtDxe, which would introduce an extra allocation there. Let's avoid that. Also, you can't FreePages() in DXE what you have AllocatePages()'d in PEI; the MemoryAllocationLib instances implementing those interfaces in PEI vs. DXE are not compatible. Which means that beyond having to do the extra allocation in VirtFdtDxe, you'd also have to leak the first copy (made in PEI).
So I propose - to use the new HOB to carry only the address of the copy of the DTB that's made in PEI - the current AllocatePages() in PEI should account for a larger (expanded) size DTB, and after copying the initial DTB over there, the copy should be at once extended in-place to the new size (I think this is doable in libfdt). This is arguably a small separate patch though.
Thanks Laszlo
On 10 December 2014 at 13:48, Laszlo Ersek lersek@redhat.com wrote:
On 12/10/14 13:25, Peter Maydell wrote:
On 10 December 2014 at 11:40, Laszlo Ersek lersek@redhat.com wrote:
The dtb that QEMU exports at the moment is 64KB in size (FDT_MAX_SIZE in "device_tree.c"). See
qemu-system-aarch64 -M virt -machine dumpdtb=virt.dtb
I'm sure you've noticed that; I'll assume that your first new BuildGuidHob() call failed. That's because the BuildGuidHob() function in "MdePkg/Library/PeiHobLib/HobLib.c" limits the size to
(0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)))
Which is why you probably added fdt_pack().
The 64KB DTB that qemu currently exports for the virt machtype carries actually less than 5KB of payload, the rest is padding (for in-place updates I guess), which fdt_pack() trims in-place.
Hmm. That seems like a bug in QEMU to me -- we should probably be trimming down the dtb we create ourselves. In any case I wouldn't recommend making an guest assumptions about the presence or absence of that padding or whether it might end up more than 64K in future.
Ard, if you want to prepare for the case that the current padding disappears and want to add some reserve to the DTB, I think it would be best done in PEI, where you copy from the initial place to the dynamically allocated place anyway.
(ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c, PlatformPeim().)
Because, elsewhere, you could only do it in VirtFdtDxe, which would introduce an extra allocation there. Let's avoid that. Also, you can't FreePages() in DXE what you have AllocatePages()'d in PEI; the MemoryAllocationLib instances implementing those interfaces in PEI vs. DXE are not compatible. Which means that beyond having to do the extra allocation in VirtFdtDxe, you'd also have to leak the first copy (made in PEI).
So I propose
- to use the new HOB to carry only the address of the copy of the DTB
that's made in PEI
- the current AllocatePages() in PEI should account for a larger
(expanded) size DTB, and after copying the initial DTB over there, the copy should be at once extended in-place to the new size (I think this is doable in libfdt). This is arguably a small separate patch though.
Yes, I was just implementing that, along the lines of:
// // Add some padding to FdtSize, so that we can add properties later if needed. // FdtSize = fdt_totalsize (Base) + PADDING; *FdtHobData = (UINT64)AllocatePages (EFI_SIZE_TO_PAGES (FdtSize)); ASSERT (*FdtHobData != 0); fdt_open_into (Base, (VOID *)*FdtHobData, EFI_SIZE_TO_PAGES (FdtSize) * EFI_PAGE_SIZE);
On 12/10/14 13:53, Ard Biesheuvel wrote:
On 10 December 2014 at 13:48, Laszlo Ersek lersek@redhat.com wrote:
On 12/10/14 13:25, Peter Maydell wrote:
On 10 December 2014 at 11:40, Laszlo Ersek lersek@redhat.com wrote:
The dtb that QEMU exports at the moment is 64KB in size (FDT_MAX_SIZE in "device_tree.c"). See
qemu-system-aarch64 -M virt -machine dumpdtb=virt.dtb
I'm sure you've noticed that; I'll assume that your first new BuildGuidHob() call failed. That's because the BuildGuidHob() function in "MdePkg/Library/PeiHobLib/HobLib.c" limits the size to
(0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)))
Which is why you probably added fdt_pack().
The 64KB DTB that qemu currently exports for the virt machtype carries actually less than 5KB of payload, the rest is padding (for in-place updates I guess), which fdt_pack() trims in-place.
Hmm. That seems like a bug in QEMU to me -- we should probably be trimming down the dtb we create ourselves. In any case I wouldn't recommend making an guest assumptions about the presence or absence of that padding or whether it might end up more than 64K in future.
Ard, if you want to prepare for the case that the current padding disappears and want to add some reserve to the DTB, I think it would be best done in PEI, where you copy from the initial place to the dynamically allocated place anyway.
(ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c, PlatformPeim().)
Because, elsewhere, you could only do it in VirtFdtDxe, which would introduce an extra allocation there. Let's avoid that. Also, you can't FreePages() in DXE what you have AllocatePages()'d in PEI; the MemoryAllocationLib instances implementing those interfaces in PEI vs. DXE are not compatible. Which means that beyond having to do the extra allocation in VirtFdtDxe, you'd also have to leak the first copy (made in PEI).
So I propose
- to use the new HOB to carry only the address of the copy of the DTB
that's made in PEI
- the current AllocatePages() in PEI should account for a larger
(expanded) size DTB, and after copying the initial DTB over there, the copy should be at once extended in-place to the new size (I think this is doable in libfdt). This is arguably a small separate patch though.
Yes, I was just implementing that, along the lines of:
// // Add some padding to FdtSize, so that we can add properties later if needed. // FdtSize = fdt_totalsize (Base) + PADDING; *FdtHobData = (UINT64)AllocatePages (EFI_SIZE_TO_PAGES (FdtSize)); ASSERT (*FdtHobData != 0); fdt_open_into (Base, (VOID *)*FdtHobData, EFI_SIZE_TO_PAGES (FdtSize) * EFI_PAGE_SIZE);
Two comments: - say (VOID *)(UINTN)*FdtHobData, otherwise 32-bit builds will throw a fit with gcc warnings, *FdtHobData being UINT64 - instead of multiplying with EFI_PAGE_SIZE, employ the aptly named EFI_PAGES_TO_SIZE() macro:
EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (FdtSize))
Thanks Laszlo
On Wed, 10 Dec 2014 13:53:13 +0100 Ard Biesheuvel ard.biesheuvel@linaro.org wrote:
On 10 December 2014 at 13:48, Laszlo Ersek lersek@redhat.com wrote:
On 12/10/14 13:25, Peter Maydell wrote:
On 10 December 2014 at 11:40, Laszlo Ersek lersek@redhat.com wrote:
The dtb that QEMU exports at the moment is 64KB in size (FDT_MAX_SIZE in "device_tree.c"). See
qemu-system-aarch64 -M virt -machine dumpdtb=virt.dtb
I'm sure you've noticed that; I'll assume that your first new BuildGuidHob() call failed. That's because the BuildGuidHob() function in "MdePkg/Library/PeiHobLib/HobLib.c" limits the size to
(0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)))
Which is why you probably added fdt_pack().
The 64KB DTB that qemu currently exports for the virt machtype carries actually less than 5KB of payload, the rest is padding (for in-place updates I guess), which fdt_pack() trims in-place.
Hmm. That seems like a bug in QEMU to me -- we should probably be trimming down the dtb we create ourselves. In any case I wouldn't recommend making an guest assumptions about the presence or absence of that padding or whether it might end up more than 64K in future.
Ard, if you want to prepare for the case that the current padding disappears and want to add some reserve to the DTB, I think it would be best done in PEI, where you copy from the initial place to the dynamically allocated place anyway.
(ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c, PlatformPeim().)
Because, elsewhere, you could only do it in VirtFdtDxe, which would introduce an extra allocation there. Let's avoid that. Also, you can't FreePages() in DXE what you have AllocatePages()'d in PEI; the MemoryAllocationLib instances implementing those interfaces in PEI vs. DXE are not compatible. Which means that beyond having to do the extra allocation in VirtFdtDxe, you'd also have to leak the first copy (made in PEI).
So I propose
- to use the new HOB to carry only the address of the copy of the DTB
that's made in PEI
- the current AllocatePages() in PEI should account for a larger
(expanded) size DTB, and after copying the initial DTB over there, the copy should be at once extended in-place to the new size (I think this is doable in libfdt). This is arguably a small separate patch though.
Yes, I was just implementing that, along the lines of:
// // Add some padding to FdtSize, so that we can add properties later if needed. // FdtSize = fdt_totalsize (Base) + PADDING; *FdtHobData = (UINT64)AllocatePages (EFI_SIZE_TO_PAGES (FdtSize)); ASSERT (*FdtHobData != 0); fdt_open_into (Base, (VOID *)*FdtHobData, EFI_SIZE_TO_PAGES (FdtSize) * EFI_PAGE_SIZE);
Looks sensible from my p.o.v. As I guess you've realised, the fdt_open_into() function does both a copy and expand. It's basically designed for exactly this use case.
On Wed, 10 Dec 2014 12:40:57 +0100 Laszlo Ersek lersek@redhat.com wrote:
[snip]
This is okay, but please consider adding a *loud* comment here.
The dtb that QEMU exports at the moment is 64KB in size (FDT_MAX_SIZE in "device_tree.c"). See
qemu-system-aarch64 -M virt -machine dumpdtb=virt.dtb
I'm sure you've noticed that; I'll assume that your first new BuildGuidHob() call failed. That's because the BuildGuidHob() function in "MdePkg/Library/PeiHobLib/HobLib.c" limits the size to
(0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)))
Which is why you probably added fdt_pack().
The 64KB DTB that qemu currently exports for the virt machtype carries actually less than 5KB of payload, the rest is padding (for in-place updates I guess), which fdt_pack() trims in-place.
First question: can you guarantee that fdt_pack() trims the DTB in-place? CC'ing David Gibson.
Yes, fdt_pack() will always modify the dtb in place. If there's nothing to pack it will just be a no-op, it will never expand the dtb or move it elsewhere.
This is the initial DTB we're talking about, the one that QEMU places at the base of DRAM in advance (and at reset).
Assuming the above packing (trimming) occurs in-place, we do have a nice margin here (58+ KB) for *normal* FDT nodes (ie. nodes that describe devices), but this change definitely shuts the door on any future ideas to place anything "blob-like" in the DTB. That's okay, and it does match our qemu plans, but you should still explain it in a loud comment at the top. (Also, CC'ing Peter.)
As noted later in the thread it's probably not a good idea to rely on the passed in dtb containing expansion roon - you should use fdt_open_into() to allocate extra space for yourself. You have two options: 1) (easy) Estimate some amount of padding space you think will be sufficient and fdt_open_into before you begin any dtb processing.
2) (harder but more robust with extensive dtb modifications) Write wrappers around the libfdt functions which alter the dtb which will catch -FDT_ERR_NOSPACE errors and re-allocate the dtb at that point.
Note that fdt_open_into() (and fdt_move()) are safe to use with a destination buffer that overlaps the source buffer - and in particular can be used in-place.
This replaces a number of instances of FixedPcdGetXX() with the respective PcdGetXX() invocation. This will prevent the PCDs from being evaluated to immediate constants, and instead refer to the global variables containing the constants.
This allows PrePi implementations that execute from RAM to override those values, for instance when self relocating to arbitrary RAM offsets.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- .../EarlyFdtPL011SerialPortLib.c | 2 +- .../Library/PlatformPeiLib/PlatformPeiLib.c | 2 +- ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S | 22 +++++++++++----------- ArmPlatformPkg/PrePi/PrePi.c | 16 ++++++++-------- 4 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c index ba6d277d4571..2f5222efeac8 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c @@ -71,7 +71,7 @@ SerialPortGetBaseAddress ( UINTN UartBase; RETURN_STATUS Status;
- DeviceTreeBase = (VOID *)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress); + DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
if ((DeviceTreeBase == NULL) || (fdt_check_header (DeviceTreeBase) != 0)) { return 0; diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c index d180a01415b0..aa6a419bf1b5 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c @@ -42,7 +42,7 @@ PlatformPeim ( UINT64 UartBase;
- Base = (VOID*)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress); + Base = (VOID*)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (fdt_check_header (Base) == 0);
fdt_pack (Base); diff --git a/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S b/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S index fcea9496cbd5..9e1477107d30 100644 --- a/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S +++ b/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S @@ -42,19 +42,19 @@ _SetSVCMode: // at the top of the DRAM) _SetupStackPosition: // Compute Top of System Memory - LoadConstantToReg (FixedPcdGet64 (PcdSystemMemoryBase), x1) - LoadConstantToReg (FixedPcdGet64 (PcdSystemMemorySize), x2) + ldr x1, PcdGet64 (PcdSystemMemoryBase) + ldr x2, PcdGet64 (PcdSystemMemorySize) sub x2, x2, #1 add x1, x1, x2 // x1 = SystemMemoryTop = PcdSystemMemoryBase + PcdSystemMemorySize
// Calculate Top of the Firmware Device - LoadConstantToReg (FixedPcdGet32(PcdFdBaseAddress), x2) - LoadConstantToReg (FixedPcdGet32(PcdFdSize), x3) + ldr x2, PcdGet64 (PcdFdBaseAddress) + ldr w3, PcdGet32 (PcdFdSize) sub x3, x3, #1 add x3, x3, x2 // x3 = FdTop = PcdFdBaseAddress + PcdFdSize
// UEFI Memory Size (stacks are allocated in this region) - LoadConstantToReg (FixedPcdGet32(PcdSystemMemoryUefiRegionSize), x4) + ldr w4, PcdGet32 (PcdSystemMemoryUefiRegionSize)
// // Reserve the memory for the UEFI region (contain stacks on its top) @@ -96,13 +96,13 @@ _GetBaseUefiMemory: _GetStackBase: // r1 = The top of the Mpcore Stacks // Stack for the primary core = PrimaryCoreStack - LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), x2) + ldr w2, PcdGet32 (PcdCPUCorePrimaryStackSize) sub x12, x1, x2
// Stack for the secondary core = Number of Cores - 1 - LoadConstantToReg (FixedPcdGet32(PcdCoreCount), x0) + ldr w0, PcdGet32 (PcdCoreCount) sub x0, x0, #1 - LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), x1) + ldr w1, PcdGet32 (PcdCPUCoreSecondaryStackSize) mul x1, x1, x0 sub x12, x12, x1
@@ -110,8 +110,8 @@ _GetStackBase: mov x0, x12 mov x1, x10 //ArmPlatformStackSet(StackBase, MpId, PrimaryStackSize, SecondaryStackSize) - LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), x2) - LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), x3) + ldr w2, PcdGet32 (PcdCPUCorePrimaryStackSize) + ldr w3, PcdGet32 (PcdCPUCoreSecondaryStackSize) bl ASM_PFX(ArmPlatformStackSet)
// Is it the Primary Core ? @@ -121,7 +121,7 @@ _GetStackBase: bne _PrepareArguments
_ReserveGlobalVariable: - LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), x0) + ldr w0, PcdGet32(PcdPeiGlobalVariableSize) // InitializePrimaryStack($GlobalVariableSize, $Tmp1, $Tmp2) InitializePrimaryStack(x0, x1, x2)
diff --git a/ArmPlatformPkg/PrePi/PrePi.c b/ArmPlatformPkg/PrePi/PrePi.c index 9a5e067ef537..2091017a0996 100755 --- a/ArmPlatformPkg/PrePi/PrePi.c +++ b/ArmPlatformPkg/PrePi/PrePi.c @@ -30,8 +30,8 @@ #include "PrePi.h" #include "LzmaDecompress.h"
-#define IS_XIP() (((UINT32)FixedPcdGet32 (PcdFdBaseAddress) > (UINT32)(FixedPcdGet64 (PcdSystemMemoryBase) + FixedPcdGet32 (PcdSystemMemorySize))) || \ - ((FixedPcdGet32 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) < FixedPcdGet64 (PcdSystemMemoryBase))) +#define IS_XIP() (((UINT32)PcdGet64 (PcdFdBaseAddress) > (UINT32)(PcdGet64 (PcdSystemMemoryBase) + PcdGet64 (PcdSystemMemorySize))) || \ + ((PcdGet64 (PcdFdBaseAddress) + PcdGet32 (PcdFdSize)) < PcdGet64 (PcdSystemMemoryBase)))
// Not used when PrePi in run in XIP mode UINTN mGlobalVariableBase = 0; @@ -108,8 +108,8 @@ PrePiMain (
// If ensure the FD is either part of the System Memory or totally outside of the System Memory (XIP) ASSERT (IS_XIP() || - ((FixedPcdGet32 (PcdFdBaseAddress) >= FixedPcdGet64 (PcdSystemMemoryBase)) && - ((UINT32)(FixedPcdGet32 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= (UINT32)(FixedPcdGet64 (PcdSystemMemoryBase) + FixedPcdGet64 (PcdSystemMemorySize))))); + ((PcdGet64 (PcdFdBaseAddress) >= PcdGet64 (PcdSystemMemoryBase)) && + ((UINT32)(PcdGet64 (PcdFdBaseAddress) + PcdGet32 (PcdFdSize)) <= (UINT32)(PcdGet64 (PcdSystemMemoryBase) + PcdGet64 (PcdSystemMemorySize)))));
// Initialize the architecture specific bits ArchInitialize (); @@ -127,27 +127,27 @@ PrePiMain ( // Declare the PI/UEFI memory region HobList = HobConstructor ( (VOID*)UefiMemoryBase, - FixedPcdGet32 (PcdSystemMemoryUefiRegionSize), + PcdGet32 (PcdSystemMemoryUefiRegionSize), (VOID*)UefiMemoryBase, (VOID*)StacksBase // The top of the UEFI Memory is reserved for the stacks ); PrePeiSetHobList (HobList);
// Initialize MMU and Memory HOBs (Resource Descriptor HOBs) - Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize)); + Status = MemoryPeim (UefiMemoryBase, PcdGet32 (PcdSystemMemoryUefiRegionSize)); ASSERT_EFI_ERROR (Status);
// Create the Stacks HOB (reserve the memory for all stacks) if (ArmIsMpCore ()) { StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize) + - ((FixedPcdGet32 (PcdCoreCount) - 1) * FixedPcdGet32 (PcdCPUCoreSecondaryStackSize)); + ((PcdGet32 (PcdCoreCount) - 1) * PcdGet32 (PcdCPUCoreSecondaryStackSize)); } else { StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize); } BuildStackHob (StacksBase, StacksSize);
// Declare the Global Variable HOB - BuildGlobalVariableHob (GlobalVariableBase, FixedPcdGet32 (PcdPeiGlobalVariableSize)); + BuildGlobalVariableHob (GlobalVariableBase, PcdGet32 (PcdPeiGlobalVariableSize));
//TODO: Call CpuPei as a library BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize));
On 12/08/14 19:22, Ard Biesheuvel wrote:
This replaces a number of instances of FixedPcdGetXX() with the respective PcdGetXX() invocation. This will prevent the PCDs from being evaluated to immediate constants, and instead refer to the global variables containing the constants.
This allows PrePi implementations that execute from RAM to override those values, for instance when self relocating to arbitrary RAM offsets.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org
.../EarlyFdtPL011SerialPortLib.c | 2 +- .../Library/PlatformPeiLib/PlatformPeiLib.c | 2 +- ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S | 22 +++++++++++----------- ArmPlatformPkg/PrePi/PrePi.c | 16 ++++++++-------- 4 files changed, 21 insertions(+), 21 deletions(-)
I can't offer an opinion wrt. to the PrePi sources.
With regard to the other two files, the one PCD whose getter you're replacing is PcdDeviceTreeInitialBaseAddress. This should indeed replace the
_PCD_VALUE_PcdDeviceTreeInitialBaseAddress
macro expansion of FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress) with
_gPcd_FixedAtBuild_PcdDeviceTreeInitialBaseAddress
whose definition (incl. initialization, with the same value) is auto-generated; using type "const UINT64".
"PcdDeviceTreeInitialBaseAddress" remains listed under [PcdsFixedAtBuild.common] in "ArmVirtualizationQemu.dsc".
So that should be fine for the current code too (which executes from flash), because we'll never try to change the globals.
So I'm okay with this part of the patch (and have no opinion about the other part).
Acked-by: Laszlo Ersek lersek@redhat.com
Thanks Laszlo
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c index ba6d277d4571..2f5222efeac8 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/FdtPL011SerialPortLib/EarlyFdtPL011SerialPortLib.c @@ -71,7 +71,7 @@ SerialPortGetBaseAddress ( UINTN UartBase; RETURN_STATUS Status;
- DeviceTreeBase = (VOID *)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress);
- DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
if ((DeviceTreeBase == NULL) || (fdt_check_header (DeviceTreeBase) != 0)) { return 0; diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c index d180a01415b0..aa6a419bf1b5 100644 --- a/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/PlatformPeiLib/PlatformPeiLib.c @@ -42,7 +42,7 @@ PlatformPeim ( UINT64 UartBase;
- Base = (VOID*)(UINTN)FixedPcdGet64 (PcdDeviceTreeInitialBaseAddress);
- Base = (VOID*)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); ASSERT (fdt_check_header (Base) == 0);
fdt_pack (Base); diff --git a/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S b/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S index fcea9496cbd5..9e1477107d30 100644 --- a/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S +++ b/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S @@ -42,19 +42,19 @@ _SetSVCMode: // at the top of the DRAM) _SetupStackPosition: // Compute Top of System Memory
- LoadConstantToReg (FixedPcdGet64 (PcdSystemMemoryBase), x1)
- LoadConstantToReg (FixedPcdGet64 (PcdSystemMemorySize), x2)
- ldr x1, PcdGet64 (PcdSystemMemoryBase)
- ldr x2, PcdGet64 (PcdSystemMemorySize) sub x2, x2, #1 add x1, x1, x2 // x1 = SystemMemoryTop = PcdSystemMemoryBase + PcdSystemMemorySize
// Calculate Top of the Firmware Device
- LoadConstantToReg (FixedPcdGet32(PcdFdBaseAddress), x2)
- LoadConstantToReg (FixedPcdGet32(PcdFdSize), x3)
- ldr x2, PcdGet64 (PcdFdBaseAddress)
- ldr w3, PcdGet32 (PcdFdSize) sub x3, x3, #1 add x3, x3, x2 // x3 = FdTop = PcdFdBaseAddress + PcdFdSize
// UEFI Memory Size (stacks are allocated in this region)
- LoadConstantToReg (FixedPcdGet32(PcdSystemMemoryUefiRegionSize), x4)
- ldr w4, PcdGet32 (PcdSystemMemoryUefiRegionSize)
// // Reserve the memory for the UEFI region (contain stacks on its top) @@ -96,13 +96,13 @@ _GetBaseUefiMemory: _GetStackBase: // r1 = The top of the Mpcore Stacks // Stack for the primary core = PrimaryCoreStack
- LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), x2)
- ldr w2, PcdGet32 (PcdCPUCorePrimaryStackSize) sub x12, x1, x2
// Stack for the secondary core = Number of Cores - 1
- LoadConstantToReg (FixedPcdGet32(PcdCoreCount), x0)
- ldr w0, PcdGet32 (PcdCoreCount) sub x0, x0, #1
- LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), x1)
- ldr w1, PcdGet32 (PcdCPUCoreSecondaryStackSize) mul x1, x1, x0 sub x12, x12, x1
@@ -110,8 +110,8 @@ _GetStackBase: mov x0, x12 mov x1, x10 //ArmPlatformStackSet(StackBase, MpId, PrimaryStackSize, SecondaryStackSize)
- LoadConstantToReg (FixedPcdGet32(PcdCPUCorePrimaryStackSize), x2)
- LoadConstantToReg (FixedPcdGet32(PcdCPUCoreSecondaryStackSize), x3)
- ldr w2, PcdGet32 (PcdCPUCorePrimaryStackSize)
- ldr w3, PcdGet32 (PcdCPUCoreSecondaryStackSize) bl ASM_PFX(ArmPlatformStackSet)
// Is it the Primary Core ? @@ -121,7 +121,7 @@ _GetStackBase: bne _PrepareArguments _ReserveGlobalVariable:
- LoadConstantToReg (FixedPcdGet32(PcdPeiGlobalVariableSize), x0)
- ldr w0, PcdGet32(PcdPeiGlobalVariableSize) // InitializePrimaryStack($GlobalVariableSize, $Tmp1, $Tmp2) InitializePrimaryStack(x0, x1, x2)
diff --git a/ArmPlatformPkg/PrePi/PrePi.c b/ArmPlatformPkg/PrePi/PrePi.c index 9a5e067ef537..2091017a0996 100755 --- a/ArmPlatformPkg/PrePi/PrePi.c +++ b/ArmPlatformPkg/PrePi/PrePi.c @@ -30,8 +30,8 @@ #include "PrePi.h" #include "LzmaDecompress.h" -#define IS_XIP() (((UINT32)FixedPcdGet32 (PcdFdBaseAddress) > (UINT32)(FixedPcdGet64 (PcdSystemMemoryBase) + FixedPcdGet32 (PcdSystemMemorySize))) || \
((FixedPcdGet32 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) < FixedPcdGet64 (PcdSystemMemoryBase)))
+#define IS_XIP() (((UINT32)PcdGet64 (PcdFdBaseAddress) > (UINT32)(PcdGet64 (PcdSystemMemoryBase) + PcdGet64 (PcdSystemMemorySize))) || \
((PcdGet64 (PcdFdBaseAddress) + PcdGet32 (PcdFdSize)) < PcdGet64 (PcdSystemMemoryBase)))
// Not used when PrePi in run in XIP mode UINTN mGlobalVariableBase = 0; @@ -108,8 +108,8 @@ PrePiMain ( // If ensure the FD is either part of the System Memory or totally outside of the System Memory (XIP) ASSERT (IS_XIP() ||
((FixedPcdGet32 (PcdFdBaseAddress) >= FixedPcdGet64 (PcdSystemMemoryBase)) &&
((UINT32)(FixedPcdGet32 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= (UINT32)(FixedPcdGet64 (PcdSystemMemoryBase) + FixedPcdGet64 (PcdSystemMemorySize)))));
((PcdGet64 (PcdFdBaseAddress) >= PcdGet64 (PcdSystemMemoryBase)) &&
((UINT32)(PcdGet64 (PcdFdBaseAddress) + PcdGet32 (PcdFdSize)) <= (UINT32)(PcdGet64 (PcdSystemMemoryBase) + PcdGet64 (PcdSystemMemorySize)))));
// Initialize the architecture specific bits ArchInitialize (); @@ -127,27 +127,27 @@ PrePiMain ( // Declare the PI/UEFI memory region HobList = HobConstructor ( (VOID*)UefiMemoryBase,
- FixedPcdGet32 (PcdSystemMemoryUefiRegionSize),
- PcdGet32 (PcdSystemMemoryUefiRegionSize), (VOID*)UefiMemoryBase, (VOID*)StacksBase // The top of the UEFI Memory is reserved for the stacks ); PrePeiSetHobList (HobList);
// Initialize MMU and Memory HOBs (Resource Descriptor HOBs)
- Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
- Status = MemoryPeim (UefiMemoryBase, PcdGet32 (PcdSystemMemoryUefiRegionSize)); ASSERT_EFI_ERROR (Status);
// Create the Stacks HOB (reserve the memory for all stacks) if (ArmIsMpCore ()) { StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize) +
((FixedPcdGet32 (PcdCoreCount) - 1) * FixedPcdGet32 (PcdCPUCoreSecondaryStackSize));
} else { StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize); } BuildStackHob (StacksBase, StacksSize);((PcdGet32 (PcdCoreCount) - 1) * PcdGet32 (PcdCPUCoreSecondaryStackSize));
// Declare the Global Variable HOB
- BuildGlobalVariableHob (GlobalVariableBase, FixedPcdGet32 (PcdPeiGlobalVariableSize));
- BuildGlobalVariableHob (GlobalVariableBase, PcdGet32 (PcdPeiGlobalVariableSize));
//TODO: Call CpuPei as a library BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize));
When we execute under the Linux kernel boot protocol, secondary cores must be parked or powered down. This means that we may want to allow the unicore build to execute on a CPU which identifies itself as part of an MPcore set.
This patch refactors the calls to ArmIsMpCore () so that the PrePi flavor introduced in a subsequent patch can override them.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- ArmPlatformPkg/PrePi/MainMPCore.c | 2 +- ArmPlatformPkg/PrePi/MainUniCore.c | 2 +- ArmPlatformPkg/PrePi/PrePi.c | 9 ++++----- ArmPlatformPkg/PrePi/PrePi.h | 3 ++- 4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/ArmPlatformPkg/PrePi/MainMPCore.c b/ArmPlatformPkg/PrePi/MainMPCore.c index bf813730d341..8e5f9947d499 100644 --- a/ArmPlatformPkg/PrePi/MainMPCore.c +++ b/ArmPlatformPkg/PrePi/MainMPCore.c @@ -35,7 +35,7 @@ PrimaryMain ( ArmGicSendSgiTo (PcdGet32(PcdGicDistributorBase), ARM_GIC_ICDSGIR_FILTER_EVERYONEELSE, 0x0E, PcdGet32 (PcdGicSgiIntId)); }
- PrePiMain (UefiMemoryBase, StacksBase, GlobalVariableBase, StartTimeStamp); + PrePiMain (UefiMemoryBase, StacksBase, GlobalVariableBase, StartTimeStamp, ArmIsMpCore());
// We must never return ASSERT(FALSE); diff --git a/ArmPlatformPkg/PrePi/MainUniCore.c b/ArmPlatformPkg/PrePi/MainUniCore.c index 43588a50ddb5..918ea4dcdf7b 100644 --- a/ArmPlatformPkg/PrePi/MainUniCore.c +++ b/ArmPlatformPkg/PrePi/MainUniCore.c @@ -27,7 +27,7 @@ PrimaryMain ( ASSERT(ArmIsMpCore() == 0); DEBUG_CODE_END();
- PrePiMain (UefiMemoryBase, StacksBase, GlobalVariableBase, StartTimeStamp); + PrePiMain (UefiMemoryBase, StacksBase, GlobalVariableBase, StartTimeStamp, ArmIsMpCore());
// We must never return ASSERT(FALSE); diff --git a/ArmPlatformPkg/PrePi/PrePi.c b/ArmPlatformPkg/PrePi/PrePi.c index 2091017a0996..9c669280be01 100755 --- a/ArmPlatformPkg/PrePi/PrePi.c +++ b/ArmPlatformPkg/PrePi/PrePi.c @@ -94,7 +94,8 @@ PrePiMain ( IN UINTN UefiMemoryBase, IN UINTN StacksBase, IN UINTN GlobalVariableBase, - IN UINT64 StartTimeStamp + IN UINT64 StartTimeStamp, + IN BOOLEAN IsMpCore ) { EFI_HOB_HANDOFF_INFO_TABLE* HobList; @@ -138,7 +139,7 @@ PrePiMain ( ASSERT_EFI_ERROR (Status);
// Create the Stacks HOB (reserve the memory for all stacks) - if (ArmIsMpCore ()) { + if (IsMpCore) { StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize) + ((PcdGet32 (PcdCoreCount) - 1) * PcdGet32 (PcdCPUCoreSecondaryStackSize)); } else { @@ -152,7 +153,7 @@ PrePiMain ( //TODO: Call CpuPei as a library BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize));
- if (ArmIsMpCore ()) { + if (IsMpCore) { // Only MP Core platform need to produce gArmMpCoreInfoPpiGuid Status = GetPlatformPpi (&gArmMpCoreInfoPpiGuid, (VOID**)&ArmMpCoreInfoPpi);
@@ -209,8 +210,6 @@ CEntryPoint ( { UINT64 StartTimeStamp;
- ASSERT(!ArmIsMpCore() || (PcdGet32 (PcdCoreCount) > 1)); - // Initialize the platform specific controllers ArmPlatformInitialize (MpId);
diff --git a/ArmPlatformPkg/PrePi/PrePi.h b/ArmPlatformPkg/PrePi/PrePi.h index e67795f4490a..468569b3a28b 100644 --- a/ArmPlatformPkg/PrePi/PrePi.h +++ b/ArmPlatformPkg/PrePi/PrePi.h @@ -40,7 +40,8 @@ PrePiMain ( IN UINTN UefiMemoryBase, IN UINTN StacksBase, IN UINTN GlobalVariableBase, - IN UINT64 StartTimeStamp + IN UINT64 StartTimeStamp, + IN BOOLEAN IsMpCore );
EFI_STATUS
This patch introduces a relocatable PrePi, which can execute from arbitrary offsets in RAM. This is intendend to be run from a boot loader which passes a description of the actual platform in a device tree, for instance.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S | 27 ++++++ ArmPlatformPkg/PrePi/MainUniCoreRelocatable.c | 38 +++++++++ ArmPlatformPkg/PrePi/PeiUniCoreRelocatable.inf | 108 ++++++++++++++++++++++++ ArmPlatformPkg/PrePi/Scripts/PrePi-PIE.lds | 28 ++++++ 4 files changed, 201 insertions(+) create mode 100644 ArmPlatformPkg/PrePi/MainUniCoreRelocatable.c create mode 100755 ArmPlatformPkg/PrePi/PeiUniCoreRelocatable.inf create mode 100644 ArmPlatformPkg/PrePi/Scripts/PrePi-PIE.lds
diff --git a/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S b/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S index 9e1477107d30..816d1298fc82 100644 --- a/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S +++ b/ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S @@ -28,6 +28,33 @@ GCC_ASM_EXPORT(_ModuleEntryPoint) StartupAddr: .8byte ASM_PFX(CEntryPoint)
ASM_PFX(_ModuleEntryPoint): + +#if defined (SELF_RELOCATE) + // + // If we are built as a ET_DYN PIE executable, we need to process all + // relative relocations regardless of whether or not we are executing from + // the same offset we were linked at. This is only possible if we are + // running from RAM. + // + adr x8, __reloc_base + adr x9, __reloc_start + adr x10, __reloc_end + +.Lreloc_loop: + cmp x9, x10 + bhs .Lreloc_done + + ldp x11, x12, [x9], #24 + cmp x12, #0x403 // R_AARCH64_RELATIVE + bne .Lreloc_loop + + ldr x12, [x9, #-8] + add x12, x12, x8 + str x12, [x11, x8] + b .Lreloc_loop +.Lreloc_done: +#endif + // Do early platform specific actions bl ASM_PFX(ArmPlatformPeiBootAction)
diff --git a/ArmPlatformPkg/PrePi/MainUniCoreRelocatable.c b/ArmPlatformPkg/PrePi/MainUniCoreRelocatable.c new file mode 100644 index 000000000000..594579971a2d --- /dev/null +++ b/ArmPlatformPkg/PrePi/MainUniCoreRelocatable.c @@ -0,0 +1,38 @@ +/** @file +* +* Copyright (c) 2011, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include "PrePi.h" + +VOID +PrimaryMain ( + IN UINTN UefiMemoryBase, + IN UINTN StacksBase, + IN UINTN GlobalVariableBase, + IN UINT64 StartTimeStamp + ) +{ + PrePiMain (UefiMemoryBase, StacksBase, GlobalVariableBase, StartTimeStamp, FALSE); + + // We must never return + ASSERT(FALSE); +} + +VOID +SecondaryMain ( + IN UINTN MpId + ) +{ + // We must never get into this function on UniCore system + ASSERT(FALSE); +} diff --git a/ArmPlatformPkg/PrePi/PeiUniCoreRelocatable.inf b/ArmPlatformPkg/PrePi/PeiUniCoreRelocatable.inf new file mode 100755 index 000000000000..33b2052f7ab4 --- /dev/null +++ b/ArmPlatformPkg/PrePi/PeiUniCoreRelocatable.inf @@ -0,0 +1,108 @@ +#/** @file +# +# Copyright (c) 2011-2014, ARM Ltd. All rights reserved.<BR> +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmPlatformPrePiUniCoreRelocatable + FILE_GUID = f7d9fd14-9335-4389-80c5-334d6abfcced + MODULE_TYPE = SEC + VALID_ARCHITECTURES = AARCH64 + VERSION_STRING = 1.0 + +[Sources] + PrePi.c + MainUniCoreRelocatable.c + +[Sources.AArch64] + AArch64/ArchPrePi.c + AArch64/ModuleEntryPoint.S + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + DebugAgentLib + ArmLib + IoLib + TimerLib + SerialPortLib + ExtractGuidedSectionLib + LzmaDecompressLib + PeCoffGetEntryPointLib + DebugAgentLib + PrePiLib + ArmPlatformLib + ArmPlatformStackLib + MemoryAllocationLib + HobLib + PrePiHobListPointerLib + PlatformPeiLib + MemoryInitPeiLib + +[Ppis] + gArmMpCoreInfoPpiGuid + +[Guids] + gArmGlobalVariableGuid + gArmMpCoreInfoGuid + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob + gArmPlatformTokenSpaceGuid.PcdSendSgiToBringUpSecondaryCores + +[FixedPcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString + + gArmTokenSpaceGuid.PcdVFPEnabled + + gArmTokenSpaceGuid.PcdFdBaseAddress + gArmTokenSpaceGuid.PcdFdSize + + gArmTokenSpaceGuid.PcdFvBaseAddress + gArmTokenSpaceGuid.PcdFvSize + + gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize + gArmPlatformTokenSpaceGuid.PcdCPUCoreSecondaryStackSize + + gArmPlatformTokenSpaceGuid.PcdPeiGlobalVariableSize + + gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize + + gArmPlatformTokenSpaceGuid.PcdCoreCount + + gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize + gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize + + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData + gArmTokenSpaceGuid.PcdSystemMemoryBase + gArmTokenSpaceGuid.PcdSystemMemorySize + +[BuildOptions] + GCC:*_*_AARCH64_PP_FLAGS = -DSELF_RELOCATE + GCC:*_*_AARCH64_DLINK_FLAGS = -pie -T $(MODULE_DIR)/Scripts/PrePi-PIE.lds diff --git a/ArmPlatformPkg/PrePi/Scripts/PrePi-PIE.lds b/ArmPlatformPkg/PrePi/Scripts/PrePi-PIE.lds new file mode 100644 index 000000000000..880f9b114ddd --- /dev/null +++ b/ArmPlatformPkg/PrePi/Scripts/PrePi-PIE.lds @@ -0,0 +1,28 @@ +SECTIONS +{ + .text 0x0 : { + PROVIDE(__reloc_base = .); + + *(.text .text*) + *(.got .got*) + *(.rodata .rodata*) + *(.data .data*) + + . = ALIGN(0x20); + PROVIDE(__reloc_start = .); + *(.rela .rela*) + PROVIDE(__reloc_end = .); + } + .bss ALIGN(0x20) : { *(.bss .bss*) } + + /DISCARD/ : { + *(.note.GNU-stack) + *(.gnu_debuglink) + *(.interp) + *(.dynamic) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.comment) + } +}
This patch introduces a variant of the ArmVirtualizationPkg PlatformLib instance that can be combined with the relocatable PrePi to produce a build that is able to fully configure itself based on the memory layout described in a flattened device tree (FDT) image).
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- .../AARCH64/MemnodeParser.S | 224 +++++++++++++++++++++ .../AARCH64/RelocatableVirtHelper.S | 177 ++++++++++++++++ .../ArmVirtRelocatablePlatformLib.inf | 66 ++++++ .../ArmVirtualizationPlatformLib/RelocatableVirt.c | 78 +++++++ 4 files changed, 545 insertions(+) create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/AARCH64/MemnodeParser.S create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/AARCH64/RelocatableVirtHelper.S create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtRelocatablePlatformLib.inf create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/RelocatableVirt.c
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/AARCH64/MemnodeParser.S b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/AARCH64/MemnodeParser.S new file mode 100644 index 000000000000..cbd40c611543 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/AARCH64/MemnodeParser.S @@ -0,0 +1,224 @@ +// +// Copyright (c) 2014, Linaro Ltd. All rights reserved. +// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// + +// +// Theory of operation +// ------------------- +// +// This code parses a Flattened Device Tree binary (DTB) to find the base of +// system RAM. It is written in assembly so that it can be executed before a +// stack has been set up. +// +// To find the base of system RAM, we have to traverse the FDT to find a memory +// node. The first node that has a device_type property with the value 'memory' +// and a 'reg' property is selected, and the name of the node (memory[@xxx]) is +// ignored, as are any other nodes that match the above constraints. +// +// In pseudo code, this implementation does the following: +// +// for each node { +// have_device_type = false +// have_reg = false +// +// for each property { +// if property value == 'memory' { +// if property name == 'device_type' { +// have_device_type = true +// } +// } else { +// if property name == 'reg' { +// have_reg = true +// membase = property value[0] +// memsize = property value[1] +// } +// } +// } +// if have_device_type and have_reg { +// return membase and memsize +// } +// } +// return NOT_FOUND +// + +#define FDT_BEGIN_NODE 0x1 +#define FDT_END_NODE 0x2 +#define FDT_PROP 0x3 +#define FDT_END 0x9 + + xMEMSIZE .req x0 + xMEMBASE .req x1 + wFDTSIZE .req w2 + + xLR .req x8 + xDTP .req x9 + xSTRTAB .req x10 + xMEMNODE .req x11 + + .text + .align 3 +_fdtmagic: + .byte 0xd0, 0x0d, 0xfe, 0xed +_memory: + .asciz "memory" +_reg: + .asciz "reg" +_device_type: + .asciz "device_type" + + // + // Compare strings in x4 and x5, return in w3 + // + .align 3 +strcmp: + ldrb w6, [x4], #1 + ldrb w7, [x5], #1 + subs w3, w6, w7 + cbz w6, 0f + cbz w7, 0f + beq strcmp +0: ret + + .globl find_memnode +find_memnode: + // + // Preserve link register + // + mov xLR, x30 + mov xDTP, x0 + mov xMEMNODE, #0 + + // + // Check the DTB magic at offset 0 + // + ldr w4, _fdtmagic + ldp w5, wFDTSIZE, [xDTP] + cmp w4, w5 + bne err_invalid_magic + rev wFDTSIZE, wFDTSIZE + + // + // Read the string offset and store it for later use + // Read the struct offset and add it to the DT pointer + // + ldp w4, w5, [xDTP, #8] + rev w4, w4 + rev w5, w5 + add xSTRTAB, xDTP, x5 + add xDTP, xDTP, x4 + + // + // Check current tag for FDT_BEGIN_NODE + // + ldr w5, [xDTP] + rev w5, w5 + cmp w5, #FDT_BEGIN_NODE + bne err_unexpected_begin_tag + +begin_node: + mov xMEMNODE, #0 + add xDTP, xDTP, #4 + + // + // Advance xDTP past NULL terminated string + // +0: ldrb w4, [xDTP], #1 + cbnz w4, 0b + +next_tag: + add xDTP, xDTP, #3 + and xDTP, xDTP, #~3 + + // + // Read the next tag, could be BEGIN_NODE, END_NODE, PROP, END + // + ldr w5, [xDTP] + rev w5, w5 + cmp w5, #FDT_BEGIN_NODE + beq begin_node + cmp w5, #FDT_END_NODE + beq end_node + cmp w5, #FDT_PROP + beq prop_node + cmp w5, #FDT_END + beq err_end_of_fdt + b err_unexpected_tag + +prop_node: + // + // If propname == 'reg', record as membase and memsize + // If propname == 'device_type' and value == 'memory', + // set the 'is_memnode' flag for this node + // + ldr w12, [xDTP, #4] + add xDTP, xDTP, #12 + rev w12, w12 + mov x5, xDTP + adr x4, _memory + bl strcmp + + // + // Get handle to property name + // + ldr w5, [xDTP, #-4] + rev w5, w5 + add x5, xSTRTAB, x5 + + cbz w3, check_device_type + + // + // Check for 'reg' property + // + adr x4, _reg + bl strcmp + cbnz w3, inc_and_next_tag + + // + // Extract two 64-bit quantities from the 'reg' property. These values + // will only be used if the node also turns out to have a device_type + // property with a value of 'memory'. + // + ldp xMEMBASE, xMEMSIZE, [xDTP] + rev xMEMBASE, xMEMBASE + rev xMEMSIZE, xMEMSIZE + orr xMEMNODE, xMEMNODE, #2 + b inc_and_next_tag + +check_device_type: + // + // Check whether the current property's name is 'device_type' + // + adr x4, _device_type + bl strcmp + cbnz w3, inc_and_next_tag + orr xMEMNODE, xMEMNODE, #1 + +inc_and_next_tag: + add xDTP, xDTP, x12 + b next_tag + +end_node: + // + // Check for device_type = memory and reg = xxxx + // If we have both, we are done + // + add xDTP, xDTP, #4 + cmp xMEMNODE, #3 + bne next_tag + + ret xLR + +err_invalid_magic: +err_unexpected_begin_tag: +err_unexpected_tag: +err_end_of_fdt: + mov xMEMSIZE, #0 + ret xLR diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/AARCH64/RelocatableVirtHelper.S b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/AARCH64/RelocatableVirtHelper.S new file mode 100644 index 000000000000..a9b808f7494d --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/AARCH64/RelocatableVirtHelper.S @@ -0,0 +1,177 @@ +# +# Copyright (c) 2011-2013, ARM Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# + +#include <AsmMacroIoLibV8.h> +#include <Base.h> +#include <Library/ArmLib.h> +#include <Library/PcdLib.h> +#include <AutoGen.h> + +.text +.align 2 + +GCC_ASM_EXPORT(ArmPlatformPeiBootAction) +GCC_ASM_EXPORT(ArmPlatformIsPrimaryCore) +GCC_ASM_EXPORT(ArmPlatformGetPrimaryCoreMpId) +GCC_ASM_EXPORT(ArmPlatformGetCorePosition) +GCC_ASM_EXPORT(ArmGetPhysAddrTop) + +GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCore) +GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCoreMask) +GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdCoreCount) + +.LFdtMagic: + .byte 0xd0, 0x0d, 0xfe, 0xed + +.LArm64LinuxMagic: + .byte 0x41, 0x52, 0x4d, 0x64 + +ASM_PFX(ArmPlatformPeiBootAction): + // preserve LR + mov x29, x30 + + // + // If we are booting from RAM using the Linux kernel boot protocol, x0 will + // point to the DTB image in memory. Otherwise, we are just coming out of + // reset, and x0 will be 0. Check also the FDT magic. + // + cbz x0, .Lout + ldr w8, .LFdtMagic + ldr w9, [x0] + cmp w8, w9 + bne .Lout + + // + // The base of the runtime image has been preserved in x1. Check whether + // the expected magic number can be found in the header. + // + ldr w8, .LArm64LinuxMagic + ldr w9, [x1, #0x38] + cmp w8, w9 + bne .Lout + + // + // OK, so far so good. We have confirmed that we likely have a DTB and are + // booting via the arm64 Linux boot protocol. Record the base of the image as + // PcdFdbaseAddress + // + adr x8, PcdGet64 (PcdFdBaseAddress) + ldr x2, [x8] + str x1, [x8] + + // + // Add the shift of PcdFdBaseAddress to PcdFvBaseAddress as well + // + adr x8, PcdGet64 (PcdFvBaseAddress) + ldr x3, [x8] + sub x3, x3, x2 + add x3, x3, x1 + str x3, [x8] + + // + // Parse the memory info from the DTB. + // + mov x27, x0 + mov x28, x1 + bl find_memnode // returns (memsize,membase,fdtsize) size in (x0,x1,x2) + cbz x0, .Lout + + // + // Store the system base and size + // + adr x8, PcdGet64 (PcdSystemMemorySize) + str x0, [x8] + + adr x8, PcdGet64 (PcdSystemMemoryBase) + str x1, [x8] + + // + // To prevent the FDT from being clobbered before we have a chance of + // preserving it, copy it right above the FD image and add its size to + // the FD size so the core code will treat it as part of the flash image. + // + adr x8, PcdGet32 (PcdFdSize) + ldr w9, [x8] + add x0, x28, x9 + add w9, w9, w2 + str w9, [x8] + + // + // Store the new FDT pointer + // + adr x8, PcdGet64 (PcdDeviceTreeInitialBaseAddress) + str x0, [x8] + + // + // Now copy the dtb: + // source: x27 + // dest: x0 + // length: w2 + // + mov x1, x27 + bl memcpy + +.Lout: + ret x29 + +//UINTN +//ArmPlatformGetPrimaryCoreMpId ( +// VOID +// ); +ASM_PFX(ArmPlatformGetPrimaryCoreMpId): + LoadConstantToReg (_gPcd_FixedAtBuild_PcdArmPrimaryCore, x0) + ldrh w0, [x0] + ret + +//UINTN +//ArmPlatformIsPrimaryCore ( +// IN UINTN MpId +// ); +ASM_PFX(ArmPlatformIsPrimaryCore): + mov x0, #1 + ret + +//UINTN +//ArmPlatformGetCorePosition ( +// IN UINTN MpId +// ); +// With this function: CorePos = (ClusterId * 4) + CoreId +ASM_PFX(ArmPlatformGetCorePosition): + and x1, x0, #ARM_CORE_MASK + and x0, x0, #ARM_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret + +//EFI_PHYSICAL_ADDRESS +//GetPhysAddrTop ( +// VOID +// ); +ASM_PFX(ArmGetPhysAddrTop): + mrs x0, id_aa64mmfr0_el1 + adr x1, .LPARanges + and x0, x0, #7 + ldrb w1, [x1, x0] + mov x0, #1 + lsl x0, x0, x1 + ret + +// +// Bits 0..2 of the AA64MFR0_EL1 system register encode the size of the +// physical address space support on this CPU: +// 0 == 32 bits, 1 == 36 bits, etc etc +// 6 and 7 are reserved +// +.LPARanges: + .byte 32, 36, 40, 42, 44, 48, -1, -1 + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtRelocatablePlatformLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtRelocatablePlatformLib.inf new file mode 100644 index 000000000000..a18975038003 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtRelocatablePlatformLib.inf @@ -0,0 +1,66 @@ +#/* @file +# Copyright (c) 2011-2014, ARM Limited. All rights reserved. +# Copyright (c) 2014, Linaro Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#*/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmVirtRelocatablePlatformLib + FILE_GUID = c8602718-4faa-4119-90ca-cae72509ac4c + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmPlatformLib|SEC PEIM + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec + +[LibraryClasses] + IoLib + ArmLib + PrintLib + FdtLib + SerialPortLib + HobLib + +[Sources.common] + RelocatableVirt.c + VirtMem.c + +[Sources.AARCH64] + AARCH64/RelocatableVirtHelper.S | GCC + AARCH64/MemnodeParser.S | GCC + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdCacheEnable + gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec + +[Pcd] + gArmTokenSpaceGuid.PcdSystemMemorySize + +[FixedPcd] + gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress + gArmPlatformTokenSpaceGuid.PcdCoreCount + gArmTokenSpaceGuid.PcdSystemMemoryBase + gArmTokenSpaceGuid.PcdArmPrimaryCoreMask + gArmTokenSpaceGuid.PcdArmPrimaryCore + gArmTokenSpaceGuid.PcdFdBaseAddress + gArmTokenSpaceGuid.PcdFdSize + gArmTokenSpaceGuid.PcdFvBaseAddress + +[Guids] + gEarlyPL011BaseAddressGuid + gFdtHobGuid diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/RelocatableVirt.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/RelocatableVirt.c new file mode 100644 index 000000000000..e9fe114383a5 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/RelocatableVirt.c @@ -0,0 +1,78 @@ +/** @file +* +* Copyright (c) 2011-2013, ARM Limited. All rights reserved. +* Copyright (c) 2014, Linaro Limited. All rights reserved. +* Copyright (c) 2014, Red Hat, Inc. +* +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include <Library/IoLib.h> +#include <Library/ArmPlatformLib.h> +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <ArmPlatform.h> +#include <libfdt.h> +#include <Pi/PiBootMode.h> +#include <Uefi/UefiBaseType.h> +#include <Uefi/UefiMultiPhase.h> +#include <Pi/PiHob.h> +#include <Library/HobLib.h> +#include <Guid/EarlyPL011BaseAddress.h> + +/** + Return the current Boot Mode + + This function returns the boot reason on the platform + + @return Return the current Boot Mode of the platform + +**/ +EFI_BOOT_MODE +ArmPlatformGetBootMode ( + VOID + ) +{ + return BOOT_WITH_FULL_CONFIGURATION; +} + +/** + This function is called by PrePeiCore, in the SEC phase. +**/ +RETURN_STATUS +ArmPlatformInitialize ( + IN UINTN MpId + ) +{ + // + // We are relying on ArmPlatformInitializeSystemMemory () being called from + // InitializeMemory (), which only occurs if the following feature is disabled + // + ASSERT (!FeaturePcdGet (PcdSystemMemoryInitializeInSec)); + return RETURN_SUCCESS; +} + +VOID +ArmPlatformInitializeSystemMemory ( + VOID + ) +{ +} + +VOID +ArmPlatformGetPlatformPpiList ( + OUT UINTN *PpiListSize, + OUT EFI_PEI_PPI_DESCRIPTOR **PpiList + ) +{ + *PpiListSize = 0; + *PpiList = NULL; +}
This implements a MemoryInitPeiLib instance that differs from the stock ArmPlatformPkg version only in the fact that it does not remove the memory used by the flash device (FD). The reason is that, when using PrePi, the DXE core is started immediately and never returns so there is no reason to preserve any of the memory that the flash device occupied originally, and it is preferable to release is so that the OS loader can reuse it. This is especially important for the relocatable PrePi configuration, which is aimed at being launched from a boot loader that itself adheres to the Linux arm64 boot protocol.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel ard.biesheuvel@linaro.org --- .../ArmVirtualizationMemoryInitPeiLib.c | 91 ++++++++++++++++++++++ .../ArmVirtualizationMemoryInitPeiLib.inf | 64 +++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c new file mode 100644 index 000000000000..5f6cd059c47f --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c @@ -0,0 +1,91 @@ +/** @file +* +* Copyright (c) 2011-2014, ARM Limited. All rights reserved. +* Copyright (c) 2014, Linaro Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include <PiPei.h> + +#include <Library/ArmPlatformLib.h> +#include <Library/DebugLib.h> +#include <Library/HobLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PcdLib.h> + +VOID +BuildMemoryTypeInformationHob ( + VOID + ); + +VOID +InitMmu ( + VOID + ) +{ + ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable; + VOID *TranslationTableBase; + UINTN TranslationTableSize; + RETURN_STATUS Status; + + // Get Virtual Memory Map from the Platform Library + ArmPlatformGetVirtualMemoryMap (&MemoryTable); + + //Note: Because we called PeiServicesInstallPeiMemory() before to call InitMmu() the MMU Page Table resides in + // DRAM (even at the top of DRAM as it is the first permanent memory allocation) + Status = ArmConfigureMmu (MemoryTable, &TranslationTableBase, &TranslationTableSize); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Error: Failed to enable MMU\n")); + } +} + +EFI_STATUS +EFIAPI +MemoryPeim ( + IN EFI_PHYSICAL_ADDRESS UefiMemoryBase, + IN UINT64 UefiMemorySize + ) +{ + EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes; + + // Ensure PcdSystemMemorySize has been set + ASSERT (PcdGet64 (PcdSystemMemorySize) != 0); + + // + // Now, the permanent memory has been installed, we can call AllocatePages() + // + ResourceAttributes = ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED + ); + + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ResourceAttributes, + PcdGet64 (PcdSystemMemoryBase), + PcdGet64 (PcdSystemMemorySize) + ); + + // Build Memory Allocation Hob + InitMmu (); + + if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) { + // Optional feature that helps prevent EFI memory map fragmentation. + BuildMemoryTypeInformationHob (); + } + + return EFI_SUCCESS; +} diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf new file mode 100644 index 000000000000..1031f64fb8de --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf @@ -0,0 +1,64 @@ +#/** @file +# +# Copyright (c) 2011-2014, ARM Ltd. All rights reserved.<BR> +# Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR> +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmVirtMemoryInitPeiLib + FILE_GUID = 021b6156-3cc8-4e99-85ee-13d8a871edf2 + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformPeiLib + +[Sources] + ArmVirtualizationMemoryInitPeiLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + +[LibraryClasses] + DebugLib + HobLib + ArmLib + ArmPlatformLib + +[Guids] + gEfiMemoryTypeInformationGuid + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob + +[FixedPcd] + gArmTokenSpaceGuid.PcdFdBaseAddress + gArmTokenSpaceGuid.PcdFdSize + + gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize + + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData + gArmTokenSpaceGuid.PcdSystemMemoryBase + gArmTokenSpaceGuid.PcdSystemMemorySize + +[Depex] + TRUE
This is a platform description that can be booted on QEMU via the -kernel option rather than -bios option, causing it to be booted via the Linux/arm64 boot protocol rather than (emulated) bare metal.
This patch is just a proof-of-concept, i.e., if you are going to target QEMU/mach-virt, you're probably better off using the tailored solution in ArmVirtualizationQemu.dsc. It is included in this series to illustrate the intention of the previous patches, and not intended to be merged. --- .../ArmVirtualizationQemuKernel.dsc | 263 ++++++++++++++++ .../ArmVirtualizationQemuKernel.fdf | 334 +++++++++++++++++++++ 2 files changed, 597 insertions(+) create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.dsc create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.fdf
diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.dsc b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.dsc new file mode 100644 index 000000000000..e5ca8b85f90c --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.dsc @@ -0,0 +1,263 @@ +# +# Copyright (c) 2011-2013, ARM Limited. All rights reserved. +# Copyright (c) 2014, Linaro Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = ArmVirtualizationQemuKernel + PLATFORM_GUID = 37d7e986-f7e9-45c2-8067-e371421a626c + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/ArmVirtualizationQemuKernel-$(ARCH) + SUPPORTED_ARCHITECTURES = AARCH64 + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.fdf + +!include ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualization.dsc.inc + +[LibraryClasses.AARCH64] + ArmLib|ArmPkg/Library/ArmLib/AArch64/AArch64Lib.inf + ArmCpuLib|ArmPkg/Drivers/ArmCpuLib/ArmCortexAEMv8Lib/ArmCortexAEMv8Lib.inf + +[LibraryClasses.ARM] + ArmLib|ArmPkg/Library/ArmLib/ArmV7/ArmV7Lib.inf + ArmCpuLib|ArmPkg/Drivers/ArmCpuLib/ArmCortexA15Lib/ArmCortexA15Lib.inf + +[LibraryClasses.common] + # Virtio Support + VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf + VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf + + ArmPlatformLib|ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtRelocatablePlatformLib.inf + ArmPlatformSysConfigLib|ArmPlatformPkg/Library/ArmPlatformSysConfigLibNull/ArmPlatformSysConfigLibNull.inf + + TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf + +!ifdef INTEL_BDS + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.inf + PlatformBdsLib|ArmPlatformPkg/Library/PlatformIntelBdsLib/PlatformIntelBdsLib.inf + CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf +!endif + +[LibraryClasses.common.UEFI_DRIVER] + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf + +[LibraryClasses.AARCH64.SEC] + ArmLib|ArmPkg/Library/ArmLib/AArch64/AArch64LibSec.inf + +[LibraryClasses.ARM.SEC] + ArmLib|ArmPkg/Library/ArmLib/ArmV7/ArmV7LibSec.inf + +[BuildOptions] + RVCT:*_*_ARM_PLATFORM_FLAGS == --cpu Cortex-A15 -I$(WORKSPACE)/ArmPlatformPkg/ArmVirtualizationPkg/Include + GCC:*_*_ARM_PLATFORM_FLAGS == -mcpu=cortex-a15 -I$(WORKSPACE)/ArmPlatformPkg/ArmVirtualizationPkg/Include + GCC:*_*_AARCH64_PLATFORM_FLAGS == -I$(WORKSPACE)/ArmPlatformPkg/ArmVirtualizationPkg/Include + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ + +[PcdsFeatureFlag.common] + ## If TRUE, Graphics Output Protocol will be installed on virtual handle created by ConsplitterDxe. + # It could be set FALSE to save size. + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|FALSE + +[PcdsFixedAtBuild.common] + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F + + gArmPlatformTokenSpaceGuid.PcdFirmwareVendor|"QEMU" + + gArmPlatformTokenSpaceGuid.PcdCoreCount|1 +!if $(ARCH) == AARCH64 + gArmTokenSpaceGuid.PcdVFPEnabled|1 +!endif + + gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase|0x4007c000 + gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize|0x4000 + + # Size of the region used by UEFI in permanent memory (Reserved 64MB) + gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize|0x04000000 + + # + # ARM Pcds + # + gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000040000000 + + ## Trustzone enable (to make the transition from EL3 to EL2 in ArmPlatformPkg/Sec) + gArmTokenSpaceGuid.PcdTrustzoneSupport|FALSE + + # + # ARM PrimeCell + # + + ## PL011 - Serial Terminal + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|38400 + + # + # ARM OS Loader + # + gArmPlatformTokenSpaceGuid.PcdDefaultBootDescription|L"Linux (EFI stub) on virtio31:hd0:part0" + gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath|L"VenHw(837DCA9E-E874-4D82-B29A-23FE0E23D1E2,003E000A00000000)/HD(1,MBR,0x00000000,0x3F,0x19FC0)/Image" + gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument|"root=/dev/vda2 console=ttyAMA0 earlycon uefi_debug" + gArmPlatformTokenSpaceGuid.PcdDefaultBootType|0 + + # Use the serial console (ConIn & ConOut) and the Graphic driver (ConOut) + gArmPlatformTokenSpaceGuid.PcdDefaultConOutPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(38400,8,N,1)/VenVt100()" + gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths|L"VenHw(D3987D4B-971A-435F-8CAF-4967EB627241)/Uart(38400,8,N,1)/VenVt100()" + gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|3 + + # + # ARM Virtual Architectural Timer + # + gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz|100000000 + + # + # NV Storage PCDs. Use base of 0x04000000 for NOR1 + # + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0x04000000 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize|0x00040000 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0x04040000 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x00040000 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0x04080000 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x00040000 + +!ifdef INTEL_BDS + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE +!endif + + # + # This will be overridden in the code + # + gArmTokenSpaceGuid.PcdSystemMemoryBase|0x0 + gArmTokenSpaceGuid.PcdSystemMemorySize|0x0 + gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress|0x0 + +[PcdsDynamicDefault.common] + + gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum|0x0 + gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x0 + gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x0 + gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum|0x0 + + # + # ARM General Interrupt Controller + # + gArmTokenSpaceGuid.PcdGicDistributorBase|0x0 + gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0x0 + + ## PL031 RealTimeClock + gArmPlatformTokenSpaceGuid.PcdPL031RtcBase|0x0 + + gArmVirtualizationTokenSpaceGuid.PcdArmPsciMethod|0 + +################################################################################ +# +# Components Section - list of all EDK II Modules needed by this Platform +# +################################################################################ +[Components.common] + # + # PEI Phase modules + # + ArmPlatformPkg/PrePi/PeiUniCoreRelocatable.inf { + <LibraryClasses> + ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf + LzmaDecompressLib|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf + HobLib|EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf + PrePiHobListPointerLib|ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf + MemoryInitPeiLib|ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf + ArmLib|ArmPkg/Library/ArmLib/AArch64/AArch64LibPrePi.inf + MemoryAllocationLib|EmbeddedPkg/Library/PrePiMemoryAllocationLib/PrePiMemoryAllocationLib.inf + ArmPlatformGlobalVariableLib|ArmPlatformPkg/Library/ArmPlatformGlobalVariableLib/PrePi/PrePiArmPlatformGlobalVariableLib.inf + } + + # + # DXE + # + MdeModulePkg/Core/Dxe/DxeMain.inf { + <LibraryClasses> + NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf + } + MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + + # + # Architectural Protocols + # + ArmPkg/Drivers/CpuDxe/CpuDxe.inf + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf + + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + EmbeddedPkg/SerialDxe/SerialDxe.inf + + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + + ArmPkg/Drivers/ArmGic/ArmGicDxe.inf + ArmPkg/Drivers/TimerDxe/TimerDxe.inf + ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf { + <LibraryClasses> + NorFlashPlatformLib|ArmPlatformPkg/ArmVirtualizationPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf + } + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + + # + # Platform Driver + # + ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf + OvmfPkg/VirtioBlkDxe/VirtioBlk.inf + OvmfPkg/VirtioScsiDxe/VirtioScsi.inf + OvmfPkg/VirtioNetDxe/VirtioNet.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # Bds + # + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf +!ifdef INTEL_BDS + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf +!else + ArmPlatformPkg/Bds/Bds.inf +!endif + + # + # SCSI Bus and Disk Driver + # + MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.fdf b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.fdf new file mode 100644 index 000000000000..11fba59139b6 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.fdf @@ -0,0 +1,334 @@ +# +# Copyright (c) 2011, 2013, ARM Limited. All rights reserved. +# Copyright (c) 2014, Linaro Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +################################################################################ +# +# FD Section +# The [FD] Section is made up of the definition statements and a +# description of what goes into the Flash Device Image. Each FD section +# defines one flash "device" image. A flash device image may be one of +# the following: Removable media bootable image (like a boot floppy +# image,) an Option ROM image (that would be "flashed" into an add-in +# card,) a System "Flash" image (that would be burned into a system's +# flash) or an Update ("Capsule") image that will be used to update and +# existing system flash. +# +################################################################################ + +[FD.QEMU_EFI] +BaseAddress = 0x00000000|gArmTokenSpaceGuid.PcdFdBaseAddress +Size = 0x00200000|gArmTokenSpaceGuid.PcdFdSize +ErasePolarity = 1 + +# This one is tricky, it must be: BlockSize * NumBlocks = Size +BlockSize = 0x00001000 +NumBlocks = 0x200 + +################################################################################ +# +# Following are lists of FD Region layout which correspond to the locations of different +# images within the flash device. +# +# Regions must be defined in ascending order and may not overlap. +# +# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by +# the pipe "|" character, followed by the size of the region, also in hex with the leading +# "0x" characters. Like: +# Offset|Size +# PcdOffsetCName|PcdSizeCName +# RegionType <FV, DATA, or FILE> +# +################################################################################ + +# +# Implement the Linux kernel header layout so that the Xen loader will identify +# it as something bootable, and execute it with a FDT pointer in x0. Make some +# room for an initial stack by setting TEXT_OFFSET to 512 KB. +# +0x00000000|0x00001000 +DATA = { + 0x01, 0x00, 0x00, 0x10, # code0: adr x1, . + 0xff, 0x03, 0x00, 0x14, # code1: b 0x1000 + 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, # text_offset: 512 KB + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, # image_size: 2 MB + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # flags + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # res2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # res3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # res4 + 0x41, 0x52, 0x4d, 0x64, # magic: "ARM\x64" + 0x00, 0x00, 0x00, 0x00 # res5 +} + +0x00001000|0x001ff000 +gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize +FV = FVMAIN_COMPACT + + +################################################################################ +# +# FV Section +# +# [FV] section is used to define what components or modules are placed within a flash +# device file. This section also defines order the components and modules are positioned +# within the image. The [FV] section consists of define statements, set statements and +# module statements. +# +################################################################################ + +[FV.FvMain] +BlockSize = 0x40 +NumBlocks = 0 # This FV gets compressed so make it just big enough +FvAlignment = 16 # FV alignment and FV attributes setting. +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + APRIORI DXE { + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + INF ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf + } + INF MdeModulePkg/Core/Dxe/DxeMain.inf + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + INF ArmPlatformPkg/ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf + + # + # PI DXE Drivers producing Architectural Protocols (EFI Services) + # + INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf + INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf + INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf + INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + INF EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf + INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + + # + # Multiple Console IO support + # + INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + INF EmbeddedPkg/SerialDxe/SerialDxe.inf + + INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf + INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf + INF ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf + INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + INF FatBinPkg/EnhancedFatDxe/Fat.inf + INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # Platform Driver + # + INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf + INF OvmfPkg/VirtioNetDxe/VirtioNet.inf + INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf + + # + # UEFI application (Shell Embedded Boot Loader) + # + INF ShellBinPkg/UefiShell/UefiShell.inf + + # + # Bds + # + INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf +!ifdef INTEL_BDS + INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + INF IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf +!else + INF ArmPlatformPkg/Bds/Bds.inf +!endif + + # + # Networking stack + # + INF MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf + INF MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf + INF MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf + INF MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf + INF MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf + INF MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf + INF MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf + INF MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf + INF MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf + INF MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf + INF MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf + INF MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf + + # + # SCSI Bus and Disk Driver + # + INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + +[FV.FVMAIN_COMPACT] +FvAlignment = 16 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + INF ArmPlatformPkg/PrePi/PeiUniCoreRelocatable.inf + + FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { + SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + SECTION FV_IMAGE = FVMAIN + } + } + + +################################################################################ +# +# Rules are use with the [FV] section's module INF type to define +# how an FFS file is created for a given INF file. The following Rule are the default +# rules for the different module type. User can add the customized rules to define the +# content of the FFS file. +# +################################################################################ + + +############################################################################ +# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section # +############################################################################ +# +#[Rule.Common.DXE_DRIVER] +# FILE DRIVER = $(NAMED_GUID) { +# DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex +# COMPRESS PI_STD { +# GUIDED { +# PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi +# UI STRING="$(MODULE_NAME)" Optional +# VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) +# } +# } +# } +# +############################################################################ + +[Rule.Common.SEC] + FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED { + TE TE Align = 4K $(INF_OUTPUT)/$(MODULE_NAME).efi + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + TE TE Align = 8 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING ="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + TE TE Align = 8 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM.TIANOCOMPRESSED] + FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 { + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + } + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(NAMED_GUID) { + UI STRING ="$(MODULE_NAME)" Optional + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + } + +[Rule.Common.UEFI_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_APPLICATION.BINARY] + FILE APPLICATION = $(NAMED_GUID) { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.USER_DEFINED.ACPITABLE] + FILE FREEFORM = $(NAMED_GUID) { + RAW ACPI |.acpi + RAW ASL |.aml + UI STRING="$(MODULE_NAME)" Optional + }
On 12/08/14 19:21, Ard Biesheuvel wrote:
Hello all,
This series is part of the Xen stuff I am working on, and due to some circumstances particular to my situation (i.e., no easy access to hardware) I have decided to prototype as much as I can on QEMU, which like Xen, uses the kernel boot protocol, as documented in linux/Documentation/arm64/booting.txt
This is a RFC series to probe whether the approach taken here is acceptable. If not, there should be an update to Xen/arm to implement a specific bootloader boot protocol in addition to the kernel boot protocol it supports currently. But if it is, there may be other interesting uses, e.g., as a chainloader so that any platform can easily support UEFI booting if it already supports arm64. This would require a NOR flash in the device tree, and some standard bus type (SATA, PCI) to hold the block device containing the OS, but other than that, it seems that most of what is required is already in place.
Note the hacky use of fixed PCDs: these are supposed to be read-only, obviously, but I am updating them in code regardless. It would probably be more consistent to use PatchableInModule PCDs instead, and I will make the required changes if the overall direction is deemed appropriate.
I have included the QemuKernel.dsc: this is just a proof of concept, it works under 'qemu-system-aarch64 -kernel' whose RAM is at 0x4000_0000 whereas the .DSC puts the RAM at 0x0. The relocatable PrePi and the new lib flavours work together to relocate the PrePi and set the environment according to the device tree before launching the DXE core. From that point, everything operates as before.
Ard Biesheuvel (8): ArmVirtualizationPkg: move early UART discovery to PlatformPeim ArmVirtualizationPkg: use a HOB to store device tree blob ArmPlatformPkg: replace some instances of FixedPcdGetXX() with PcdGetXX() ArmPlatformPkg/PrePi: allow unicore build to execute on mpcore system ArmPlatformPkg/PrePi: add a relocatable version of PrePi ArmVirtualizationPkg: implement a relocatable platformlib instance ArmVirtualizationPkg: implement custom MemoryInitPeiLib ArmVirtualizationPkg: add Qemu -kernel platform description
.../ArmVirtualizationPkg/ArmVirtualizationPkg.dec | 3 +- .../ArmVirtualizationPkg/ArmVirtualizationQemu.dsc | 3 - .../ArmVirtualizationQemuKernel.dsc | 263 ++++++++++++++++ .../ArmVirtualizationQemuKernel.fdf | 334 +++++++++++++++++++++ .../ArmVirtualizationPkg/Include/Guid/FdtHob.h | 26 ++ .../ArmVirtualizationMemoryInitPeiLib.c | 91 ++++++ .../ArmVirtualizationMemoryInitPeiLib.inf | 64 ++++ .../AARCH64/MemnodeParser.S | 224 ++++++++++++++ .../AARCH64/RelocatableVirtHelper.S | 177 +++++++++++ .../ArmVirtRelocatablePlatformLib.inf | 66 ++++ .../ArmVirtualizationPlatformLib.inf | 1 + .../ArmVirtualizationPlatformLib/RelocatableVirt.c | 78 +++++ .../Library/ArmVirtualizationPlatformLib/Virt.c | 46 +-- .../EarlyFdtPL011SerialPortLib.c | 2 +- .../Library/PlatformPeiLib/PlatformPeiLib.c | 60 +++- .../Library/PlatformPeiLib/PlatformPeiLib.inf | 3 - .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.c | 10 +- .../ArmVirtualizationPkg/VirtFdtDxe/VirtFdtDxe.inf | 2 +- ArmPlatformPkg/PrePi/AArch64/ModuleEntryPoint.S | 49 ++- ArmPlatformPkg/PrePi/MainMPCore.c | 2 +- ArmPlatformPkg/PrePi/MainUniCore.c | 2 +- ArmPlatformPkg/PrePi/MainUniCoreRelocatable.c | 38 +++ ArmPlatformPkg/PrePi/PeiUniCoreRelocatable.inf | 108 +++++++ ArmPlatformPkg/PrePi/PrePi.c | 25 +- ArmPlatformPkg/PrePi/PrePi.h | 3 +- ArmPlatformPkg/PrePi/Scripts/PrePi-PIE.lds | 28 ++ 26 files changed, 1619 insertions(+), 89 deletions(-) create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.dsc create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationQemuKernel.fdf create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Include/Guid/FdtHob.h create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.c create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationMemoryInitPeiLib/ArmVirtualizationMemoryInitPeiLib.inf create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/AARCH64/MemnodeParser.S create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/AARCH64/RelocatableVirtHelper.S create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/ArmVirtRelocatablePlatformLib.inf create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmVirtualizationPlatformLib/RelocatableVirt.c create mode 100644 ArmPlatformPkg/PrePi/MainUniCoreRelocatable.c create mode 100755 ArmPlatformPkg/PrePi/PeiUniCoreRelocatable.inf create mode 100644 ArmPlatformPkg/PrePi/Scripts/PrePi-PIE.lds
All I can offer as "review" is checking against regressions in current code. See the individual emails.
Thanks Laszlo