mirror of https://github.com/acidanthera/audk.git
ArmPlatformPkg/ArmJunoPkg: Create two default boot entries on first boot on Juno R1
Juno R1 can run in two configurations: - A57x2 - A57x2-A53x4 The Device Tree tell Linux which configuration has been selected. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin <olivier.martin@arm.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16942 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
1ccc0fd73f
commit
6d60dfea87
|
@ -13,12 +13,90 @@
|
|||
**/
|
||||
|
||||
#include "ArmJunoDxeInternal.h"
|
||||
|
||||
#include <Protocol/DevicePathFromText.h>
|
||||
|
||||
#include <Guid/GlobalVariable.h>
|
||||
|
||||
#include <Library/ArmShellCmdLib.h>
|
||||
#include <Library/AcpiLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
|
||||
// This GUID must match the FILE_GUID in ArmPlatformPkg/ArmJunoPkg/AcpiTables/AcpiTables.inf
|
||||
STATIC CONST EFI_GUID mJunoAcpiTableFile = { 0xa1dd808e, 0x1e95, 0x4399, { 0xab, 0xc0, 0x65, 0x3c, 0x82, 0xe8, 0x53, 0x0c } };
|
||||
|
||||
/**
|
||||
* Build and Set UEFI Variable Boot####
|
||||
*
|
||||
* @param BootVariableName Name of the UEFI Variable
|
||||
* @param Attributes 'Attributes' for the Boot#### variable as per UEFI spec
|
||||
* @param BootDescription Description of the Boot#### variable
|
||||
* @param DevicePath EFI Device Path of the EFI Application to boot
|
||||
* @param OptionalData Parameters to pass to the EFI application
|
||||
* @param OptionalDataSize Size of the parameters to pass to the EFI application
|
||||
*
|
||||
* @return EFI_OUT_OF_RESOURCES A memory allocation failed
|
||||
* @return Return value of RT.SetVariable
|
||||
*/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
BootOptionCreate (
|
||||
IN CHAR16 BootVariableName[9],
|
||||
IN UINT32 Attributes,
|
||||
IN CHAR16* BootDescription,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,
|
||||
IN UINT8* OptionalData,
|
||||
IN UINTN OptionalDataSize
|
||||
)
|
||||
{
|
||||
UINTN VariableSize;
|
||||
UINT8 *Variable;
|
||||
UINT8 *VariablePtr;
|
||||
UINTN FilePathListLength;
|
||||
UINTN BootDescriptionSize;
|
||||
|
||||
FilePathListLength = GetDevicePathSize (DevicePath);
|
||||
BootDescriptionSize = StrSize (BootDescription);
|
||||
|
||||
// Each Boot#### variable is built as follow:
|
||||
// UINT32 Attributes
|
||||
// UINT16 FilePathListLength
|
||||
// CHAR16* Description
|
||||
// EFI_DEVICE_PATH_PROTOCOL FilePathList[]
|
||||
// UINT8 OptionalData[]
|
||||
VariableSize = sizeof (UINT32) + sizeof (UINT16) +
|
||||
BootDescriptionSize + FilePathListLength + OptionalDataSize;
|
||||
Variable = AllocateZeroPool (VariableSize);
|
||||
if (Variable == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
// 'Attributes' field
|
||||
*(UINT32*)Variable = Attributes;
|
||||
// 'FilePathListLength' field
|
||||
VariablePtr = Variable + sizeof (UINT32);
|
||||
*(UINT16*)VariablePtr = FilePathListLength;
|
||||
// 'Description' field
|
||||
VariablePtr += sizeof (UINT16);
|
||||
CopyMem (VariablePtr, BootDescription, BootDescriptionSize);
|
||||
// 'FilePathList' field
|
||||
VariablePtr += BootDescriptionSize;
|
||||
CopyMem (VariablePtr, DevicePath, FilePathListLength);
|
||||
// 'OptionalData' field
|
||||
VariablePtr += FilePathListLength;
|
||||
CopyMem (VariablePtr, OptionalData, OptionalDataSize);
|
||||
|
||||
return gRT->SetVariable (
|
||||
BootVariableName,
|
||||
&gEfiGlobalVariableGuid,
|
||||
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
VariableSize, Variable
|
||||
);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArmJunoEntryPoint (
|
||||
|
@ -34,6 +112,7 @@ ArmJunoEntryPoint (
|
|||
UINT32 Midr;
|
||||
UINT32 CpuType;
|
||||
UINT32 CpuRev;
|
||||
BOOLEAN IsJunoR1;
|
||||
|
||||
Status = PciEmulationEntryPoint ();
|
||||
if (EFI_ERROR (Status)) {
|
||||
|
@ -89,10 +168,11 @@ ArmJunoEntryPoint (
|
|||
// runtime by checking the value of the MIDR register.
|
||||
//
|
||||
|
||||
Midr = ArmReadMidr ();
|
||||
CpuType = (Midr >> ARM_CPU_TYPE_SHIFT) & ARM_CPU_TYPE_MASK;
|
||||
CpuRev = Midr & ARM_CPU_REV_MASK;
|
||||
Midr = ArmReadMidr ();
|
||||
CpuType = (Midr >> ARM_CPU_TYPE_SHIFT) & ARM_CPU_TYPE_MASK;
|
||||
CpuRev = Midr & ARM_CPU_REV_MASK;
|
||||
TextDevicePath = NULL;
|
||||
IsJunoR1 = FALSE;
|
||||
|
||||
switch (CpuType) {
|
||||
case ARM_CPU_TYPE_A53:
|
||||
|
@ -100,6 +180,7 @@ ArmJunoEntryPoint (
|
|||
TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoR0FdtDevicePath);
|
||||
} else if (CpuRev == ARM_CPU_REV (0, 3)) {
|
||||
TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoR1A57x2FdtDevicePath);
|
||||
IsJunoR1 = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -108,6 +189,7 @@ ArmJunoEntryPoint (
|
|||
TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoR0FdtDevicePath);
|
||||
} else if (CpuRev == ARM_CPU_REV (1, 1)) {
|
||||
TextDevicePath = (CHAR16*)FixedPcdGetPtr (PcdJunoR1A57x2FdtDevicePath);
|
||||
IsJunoR1 = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,5 +212,78 @@ ArmJunoEntryPoint (
|
|||
// Try to install the ACPI Tables
|
||||
Status = LocateAndInstallAcpiFromFv (&mJunoAcpiTableFile);
|
||||
|
||||
//
|
||||
// If Juno R1 and it is the first boot then default boot entries will be created
|
||||
//
|
||||
if (IsJunoR1) {
|
||||
CONST CHAR16* ExtraBootArgument = L" dtb=juno-r1-ca57x2_ca53x4.dtb";
|
||||
UINTN Size;
|
||||
EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol;
|
||||
EFI_DEVICE_PATH* BootDevicePath;
|
||||
CHAR16* DefaultBootArgument;
|
||||
UINTN DefaultBootArgumentSize;
|
||||
CHAR16* DefaultBootArgument2;
|
||||
UINTN DefaultBootArgument2Size;
|
||||
UINT16 BootOrder[2];
|
||||
|
||||
// Because the driver has a dependency on gEfiVariable(Write)ArchProtocolGuid (see [Depex]
|
||||
// section of the INF file), we know we can safely access the UEFI Variable at that stage.
|
||||
Size = 0;
|
||||
Status = gRT->GetVariable (L"BootOrder", &gEfiGlobalVariableGuid, NULL, &Size, NULL);
|
||||
if (Status == EFI_NOT_FOUND) {
|
||||
Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol);
|
||||
if (EFI_ERROR (Status)) {
|
||||
// You must provide an implementation of DevicePathFromTextProtocol in your firmware (eg: DevicePathDxe)
|
||||
DEBUG ((EFI_D_ERROR, "Error: Require DevicePathFromTextProtocol\n"));
|
||||
return Status;
|
||||
}
|
||||
// We use the same default kernel
|
||||
BootDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath));
|
||||
|
||||
// Create the entry if the Default values are correct
|
||||
if (BootDevicePath != NULL) {
|
||||
DefaultBootArgument = (CHAR16*)PcdGetPtr (PcdDefaultBootArgument);
|
||||
DefaultBootArgumentSize = StrSize (DefaultBootArgument);
|
||||
DefaultBootArgument2Size = DefaultBootArgumentSize + StrSize (ExtraBootArgument);
|
||||
|
||||
DefaultBootArgument2 = AllocatePool (DefaultBootArgument2Size);
|
||||
if (DefaultBootArgument2 == NULL) {
|
||||
FreePool (BootDevicePath);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
CopyMem (DefaultBootArgument2, DefaultBootArgument, DefaultBootArgumentSize);
|
||||
CopyMem ((UINT8*)DefaultBootArgument2 + (StrLen (DefaultBootArgument2) * sizeof (CHAR16)), ExtraBootArgument, StrSize (ExtraBootArgument));
|
||||
|
||||
// Create Boot0001 environment variable
|
||||
Status = BootOptionCreate (L"Boot0001", LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT,
|
||||
L"Linux with A57x2", BootDevicePath,
|
||||
(UINT8*)DefaultBootArgument, DefaultBootArgumentSize);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// Create Boot0002 environment variable
|
||||
Status = BootOptionCreate (L"Boot0002", LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT,
|
||||
L"Linux with A57x2_A53x4", BootDevicePath,
|
||||
(UINT8*)DefaultBootArgument2, DefaultBootArgument2Size);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// Add the new Boot Index to the list
|
||||
BootOrder[0] = 1; // Boot0001
|
||||
BootOrder[1] = 2; // Boot0002
|
||||
Status = gRT->SetVariable (
|
||||
L"BootOrder",
|
||||
&gEfiGlobalVariableGuid,
|
||||
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
||||
sizeof (BootOrder),
|
||||
BootOrder
|
||||
);
|
||||
|
||||
FreePool (BootDevicePath);
|
||||
FreePool (DefaultBootArgument2);
|
||||
} else {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -73,8 +73,12 @@
|
|||
gArmJunoTokenSpaceGuid.PcdJunoR1A57x2FdtDevicePath
|
||||
gArmJunoTokenSpaceGuid.PcdJunoR1A57x2A53x4FdtDevicePath
|
||||
|
||||
gArmPlatformTokenSpaceGuid.PcdDefaultBootDevicePath
|
||||
gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument
|
||||
|
||||
[Pcd]
|
||||
gEmbeddedTokenSpaceGuid.PcdFdtDevicePaths
|
||||
|
||||
[Depex]
|
||||
TRUE
|
||||
# We depend on these protocols to create the default boot entries
|
||||
gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
|
||||
|
|
Loading…
Reference in New Issue