ArmVirtPkg: introduce new ArmQemuRelocatablePlatformLib

This introduces ArmQemuRelocatablePlatformLib, which started out as a
straight copy of ArmXenRelocatablePlatformLib, but has been modified so
that ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf can be used with
QEMU as well as with Xen. It retains the self relocation and FDT parsing
for the system memory, but uses the QEMU MMU layout.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Laszlo Ersek <lersek@redhat.com>
This commit is contained in:
Ard Biesheuvel 2016-02-05 14:54:42 +01:00
parent ff05707ef2
commit 577393c272
6 changed files with 632 additions and 0 deletions

View File

@ -0,0 +1,157 @@
#
# 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)
.LArm64LinuxMagic:
.byte 0x41, 0x52, 0x4d, 0x64
// VOID
// ArmPlatformPeiBootAction (
// VOID *DeviceTreeBaseAddress, // passed by loader in x0
// VOID *ImageBase // passed by FDF trampoline in x1
// );
ASM_PFX(ArmPlatformPeiBootAction):
//
// If we are booting from RAM using the Linux kernel boot protocol, x0 will
// point to the DTB image in memory. Otherwise, use the default value defined
// by the platform.
//
cbnz x0, 0f
ldr x0, PcdGet64 (PcdDeviceTreeInitialBaseAddress)
0:mov x29, x30 // preserve LR
mov x28, x0 // preserve DTB pointer
mov x27, x1 // preserve base of image pointer
//
// 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. Update the base-of-image PCD
// to the actual relocated value, and add the shift of PcdFdBaseAddress to
// PcdFvBaseAddress as well
//
adr x8, PcdGet64 (PcdFdBaseAddress)
adr x9, PcdGet64 (PcdFvBaseAddress)
ldr x6, [x8]
ldr x7, [x9]
sub x7, x7, x6
add x7, x7, x1
str x1, [x8]
str x7, [x9]
//
// Discover the memory size and offset from the DTB, and record in the
// respective PCDs. This will also return false if a corrupt DTB is
// encountered. Since we are calling a C function, use the window at the
// beginning of the FD image as a temp stack.
//
adr x1, PcdGet64 (PcdSystemMemorySize)
adr x2, PcdGet64 (PcdSystemMemoryBase)
mov sp, x7
bl FindMemnode
cbz x0, .Lout
//
// Copy the DTB to the slack space right after the 64 byte arm64/Linux style
// image header at the base of this image (defined in the FDF), and record the
// pointer in PcdDeviceTreeInitialBaseAddress.
//
adr x8, PcdGet64 (PcdDeviceTreeInitialBaseAddress)
add x27, x27, #0x40
str x27, [x8]
mov x0, x27
mov x1, x28
bl CopyFdt
.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

View File

@ -0,0 +1,141 @@
#
# 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.
#
#
#include <AsmMacroIoLib.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)
.LArm32LinuxMagic:
.byte 0x18, 0x28, 0x6f, 0x01
ASM_PFX(ArmPlatformPeiBootAction):
//
// If we are booting from RAM using the Linux kernel boot protocol, r0 will
// point to the DTB image in memory. Otherwise, use the default value defined
// by the platform.
//
teq r0, #0
bne 0f
ldr r0, =PcdGet64 (PcdDeviceTreeInitialBaseAddress)
0:mov r11, r14 // preserve LR
mov r10, r0 // preserve DTB pointer
mov r9, r1 // preserve base of image pointer
//
// The base of the runtime image has been preserved in r1. Check whether
// the expected magic number can be found in the header.
//
ldr r8, .LArm32LinuxMagic
ldr r7, [r1, #0x24]
cmp r7, r8
bne .Lout
//
//
// OK, so far so good. We have confirmed that we likely have a DTB and are
// booting via the ARM Linux boot protocol. Update the base-of-image PCD
// to the actual relocated value, and add the shift of PcdFdBaseAddress to
// PcdFvBaseAddress as well
//
ldr r8, =PcdGet64 (PcdFdBaseAddress)
ldr r7, =PcdGet64 (PcdFvBaseAddress)
ldr r6, [r8]
ldr r5, [r7]
sub r5, r5, r6
add r5, r5, r1
str r1, [r8]
str r5, [r7]
//
// Discover the memory size and offset from the DTB, and record in the
// respective PCDs. This will also return false if a corrupt DTB is
// encountered. Since we are calling a C function, use the window at the
// beginning of the FD image as a temp stack.
//
ldr r1, =PcdGet64 (PcdSystemMemorySize)
ldr r2, =PcdGet64 (PcdSystemMemoryBase)
mov sp, r5
bl FindMemnode
teq r0, #0
beq .Lout
//
// Copy the DTB to the slack space right after the 64 byte arm64/Linux style
// image header at the base of this image (defined in the FDF), and record the
// pointer in PcdDeviceTreeInitialBaseAddress.
//
ldr r8, =PcdGet64 (PcdDeviceTreeInitialBaseAddress)
add r9, r9, #0x40
str r9, [r8]
mov r0, r9
mov r1, r10
bl CopyFdt
.Lout:
bx r11
//UINTN
//ArmPlatformGetPrimaryCoreMpId (
// VOID
// );
ASM_PFX(ArmPlatformGetPrimaryCoreMpId):
LoadConstantToReg (_gPcd_FixedAtBuild_PcdArmPrimaryCore, r0)
ldr r0, [r0]
bx lr
//UINTN
//ArmPlatformIsPrimaryCore (
// IN UINTN MpId
// );
ASM_PFX(ArmPlatformIsPrimaryCore):
mov r0, #1
bx lr
//UINTN
//ArmPlatformGetCorePosition (
// IN UINTN MpId
// );
// With this function: CorePos = (ClusterId * 4) + CoreId
ASM_PFX(ArmPlatformGetCorePosition):
and r1, r0, #ARM_CORE_MASK
and r0, r0, #ARM_CLUSTER_MASK
add r0, r1, r0, LSR #6
bx lr
//EFI_PHYSICAL_ADDRESS
//GetPhysAddrTop (
// VOID
// );
ASM_PFX(ArmGetPhysAddrTop):
mov r0, #0x00000000
mov r1, #0x10000
bx lr

View File

@ -0,0 +1,64 @@
#/* @file
# Copyright (c) 2011-2015, 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 = ArmXenRelocatablePlatformLib
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
ArmVirtPkg/ArmVirtPkg.dec
[LibraryClasses]
IoLib
ArmLib
PrintLib
FdtLib
[Sources.common]
RelocatableVirt.c
QemuVirtMem.c
FdtParser.c
[Sources.AARCH64]
AARCH64/RelocatableVirtHelper.S
[Sources.ARM]
ARM/RelocatableVirtHelper.S
[FeaturePcd]
gEmbeddedTokenSpaceGuid.PcdCacheEnable
gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec
[PatchPcd]
gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
gArmTokenSpaceGuid.PcdFdBaseAddress
gArmTokenSpaceGuid.PcdFvBaseAddress
gArmTokenSpaceGuid.PcdSystemMemoryBase
gArmTokenSpaceGuid.PcdSystemMemorySize
[FixedPcd]
gArmPlatformTokenSpaceGuid.PcdCoreCount
gArmTokenSpaceGuid.PcdArmPrimaryCoreMask
gArmTokenSpaceGuid.PcdArmPrimaryCore
gArmTokenSpaceGuid.PcdFdSize
gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2015, 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.
*/
#include <Uefi.h>
#include <Include/libfdt.h>
BOOLEAN
FindMemnode (
IN VOID *DeviceTreeBlob,
OUT UINT64 *SystemMemoryBase,
OUT UINT64 *SystemMemorySize
)
{
INT32 MemoryNode;
INT32 AddressCells;
INT32 SizeCells;
INT32 Length;
CONST INT32 *Prop;
if (fdt_check_header (DeviceTreeBlob) != 0) {
return FALSE;
}
//
// Look for a node called "memory" at the lowest level of the tree
//
MemoryNode = fdt_path_offset (DeviceTreeBlob, "/memory");
if (MemoryNode <= 0) {
return FALSE;
}
//
// Retrieve the #address-cells and #size-cells properties
// from the root node, or use the default if not provided.
//
AddressCells = 1;
SizeCells = 1;
Prop = fdt_getprop (DeviceTreeBlob, 0, "#address-cells", &Length);
if (Length == 4) {
AddressCells = fdt32_to_cpu (*Prop);
}
Prop = fdt_getprop (DeviceTreeBlob, 0, "#size-cells", &Length);
if (Length == 4) {
SizeCells = fdt32_to_cpu (*Prop);
}
//
// Now find the 'reg' property of the /memory node, and read the first
// range listed.
//
Prop = fdt_getprop (DeviceTreeBlob, MemoryNode, "reg", &Length);
if (Length < (AddressCells + SizeCells) * sizeof (INT32)) {
return FALSE;
}
if (AddressCells == 1) {
*SystemMemoryBase = fdt32_to_cpu (*Prop);
} else {
*SystemMemoryBase = fdt64_to_cpu (*(UINT64 *)Prop);
}
Prop += AddressCells;
if (SizeCells == 1) {
*SystemMemorySize = fdt32_to_cpu (*Prop);
} else {
*SystemMemorySize = fdt64_to_cpu (*(UINT64 *)Prop);
}
return TRUE;
}
VOID
CopyFdt (
IN VOID *FdtDest,
IN VOID *FdtSource
)
{
fdt_pack(FdtSource);
CopyMem (FdtDest, FdtSource, fdt_totalsize (FdtSource));
}

View File

@ -0,0 +1,107 @@
/** @file
*
* 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 <Library/ArmPlatformLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/PcdLib.h>
#include <Library/IoLib.h>
#include <Library/MemoryAllocationLib.h>
#include <ArmPlatform.h>
// Number of Virtual Memory Map Descriptors
#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 5
// DDR attributes
#define DDR_ATTRIBUTES_CACHED ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK
#define DDR_ATTRIBUTES_UNCACHED ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED
EFI_PHYSICAL_ADDRESS
ArmGetPhysAddrTop (
VOID
);
/**
Return the Virtual Memory Map of your platform
This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU
on your platform.
@param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_DESCRIPTOR
describing a Physical-to-Virtual Memory
mapping. This array must be ended by a
zero-filled entry
**/
VOID
ArmPlatformGetVirtualMemoryMap (
IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap
)
{
ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable;
ASSERT (VirtualMemoryMap != NULL);
VirtualMemoryTable = AllocatePages (
EFI_SIZE_TO_PAGES (
sizeof (ARM_MEMORY_REGION_DESCRIPTOR)
* MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS
)
);
if (VirtualMemoryTable == NULL) {
DEBUG ((EFI_D_ERROR, "%a: Error: Failed AllocatePages()\n", __FUNCTION__));
return;
}
// System DRAM
VirtualMemoryTable[0].PhysicalBase = PcdGet64 (PcdSystemMemoryBase);
VirtualMemoryTable[0].VirtualBase = VirtualMemoryTable[0].PhysicalBase;
VirtualMemoryTable[0].Length = PcdGet64 (PcdSystemMemorySize);
VirtualMemoryTable[0].Attributes = DDR_ATTRIBUTES_CACHED;
DEBUG ((EFI_D_INFO, "%a: Dumping System DRAM Memory Map:\n"
"\tPhysicalBase: 0x%lX\n"
"\tVirtualBase: 0x%lX\n"
"\tLength: 0x%lX\n",
__FUNCTION__,
VirtualMemoryTable[0].PhysicalBase,
VirtualMemoryTable[0].VirtualBase,
VirtualMemoryTable[0].Length));
// Peripheral space before DRAM
VirtualMemoryTable[1].PhysicalBase = 0x0;
VirtualMemoryTable[1].VirtualBase = 0x0;
VirtualMemoryTable[1].Length = VirtualMemoryTable[0].PhysicalBase;
VirtualMemoryTable[1].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
// Peripheral space after DRAM
VirtualMemoryTable[2].PhysicalBase = VirtualMemoryTable[0].Length + VirtualMemoryTable[1].Length;
VirtualMemoryTable[2].VirtualBase = VirtualMemoryTable[2].PhysicalBase;
VirtualMemoryTable[2].Length = MIN (1ULL << FixedPcdGet8 (PcdPrePiCpuMemorySize),
ArmGetPhysAddrTop ()) -
VirtualMemoryTable[2].PhysicalBase;
VirtualMemoryTable[2].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;
// Remap the FD region as normal executable memory
VirtualMemoryTable[3].PhysicalBase = PcdGet64 (PcdFdBaseAddress);
VirtualMemoryTable[3].VirtualBase = VirtualMemoryTable[3].PhysicalBase;
VirtualMemoryTable[3].Length = FixedPcdGet32 (PcdFdSize);
VirtualMemoryTable[3].Attributes = DDR_ATTRIBUTES_CACHED;
// End of Table
ZeroMem (&VirtualMemoryTable[4], sizeof (ARM_MEMORY_REGION_DESCRIPTOR));
*VirtualMemoryMap = VirtualMemoryTable;
}

View File

@ -0,0 +1,71 @@
/** @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 <ArmPlatform.h>
#include <Pi/PiBootMode.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;
}