From 6d60dfea870182cfed9bfe612316619786afb848 Mon Sep 17 00:00:00 2001 From: Olivier Martin Date: Thu, 26 Feb 2015 11:04:52 +0000 Subject: [PATCH] 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 git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16942 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Drivers/ArmJunoDxe/ArmJunoDxe.c | 161 +++++++++++++++++- .../Drivers/ArmJunoDxe/ArmJunoDxe.inf | 6 +- 2 files changed, 163 insertions(+), 4 deletions(-) diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c index 4b91f1ee06..e94047ab8b 100644 --- a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c +++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.c @@ -13,12 +13,90 @@ **/ #include "ArmJunoDxeInternal.h" + +#include + +#include + #include #include +#include +#include +#include +#include // 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; } diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf index 370edcb7c8..ea1738ba75 100644 --- a/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf +++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf @@ -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 -- 2.39.2