From patchwork Fri Jun 21 08:05:22 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Harkin X-Patchwork-Id: 18045 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ve0-f197.google.com (mail-ve0-f197.google.com [209.85.128.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 47C2225E54 for ; Fri, 21 Jun 2013 08:05:52 +0000 (UTC) Received: by mail-ve0-f197.google.com with SMTP id d10sf10631354vea.8 for ; Fri, 21 Jun 2013 01:05:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-beenthere:x-forwarded-to:x-forwarded-for :delivered-to:from:to:subject:date:message-id:x-mailer:in-reply-to :references:x-gm-message-state:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-google-group-id:list-post:list-help:list-archive:list-unsubscribe; bh=wgQR0xEuL8fGt+WGdp5Z2R9Ckm7qtxVx/G/kPAfP9zs=; b=RBbXDdS98J+lZMDLiHIzVZLofF98yJcLcl6pZPaxrmxFBqZRD/2uzfrOnTSfAa1twg OO7tM4XVw9fqoF+p8UK0MPgXugcC/EnDbnfvVbBAkWkzhgyShy9PA6ZShBR+Z5Jq5kLs Dkk7WPdvucjtt9RoZ4aKYkUlcc2QNCpdSEfE+gvQv66ZiMF+a+fU7bfmO++NEAsziFou +QYNQQKgnAkdHv/Bzveo5Zw1Mk3E7rPRpsopUSerAF7/8phYVW62kuWYaItYVWOea7I1 69QMpxw5qHqdxc76JCRH7pZ7u5wxsNBwaFDE8zFWeGfFGBWxQnDB0ugst4uUvtvkFLTT h8Vw== X-Received: by 10.236.14.233 with SMTP id d69mr6375736yhd.51.1371801952027; Fri, 21 Jun 2013 01:05:52 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.86.232 with SMTP id s8ls1043358qez.94.gmail; Fri, 21 Jun 2013 01:05:51 -0700 (PDT) X-Received: by 10.220.66.203 with SMTP id o11mr4825103vci.67.1371801951871; Fri, 21 Jun 2013 01:05:51 -0700 (PDT) Received: from mail-ve0-x22f.google.com (mail-ve0-x22f.google.com [2607:f8b0:400c:c01::22f]) by mx.google.com with ESMTPS id tq4si1216150vdc.144.2013.06.21.01.05.51 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 21 Jun 2013 01:05:51 -0700 (PDT) Received-SPF: neutral (google.com: 2607:f8b0:400c:c01::22f is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=2607:f8b0:400c:c01::22f; Received: by mail-ve0-f175.google.com with SMTP id da11so5937654veb.20 for ; Fri, 21 Jun 2013 01:05:51 -0700 (PDT) X-Received: by 10.58.187.232 with SMTP id fv8mr5143824vec.50.1371801951746; Fri, 21 Jun 2013 01:05:51 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.58.165.8 with SMTP id yu8csp51562veb; Fri, 21 Jun 2013 01:05:51 -0700 (PDT) X-Received: by 10.195.12.133 with SMTP id eq5mr8255626wjd.27.1371801950140; Fri, 21 Jun 2013 01:05:50 -0700 (PDT) Received: from mail-we0-x22d.google.com (mail-we0-x22d.google.com [2a00:1450:400c:c03::22d]) by mx.google.com with ESMTPS id l8si1552364wjx.8.2013.06.21.01.05.49 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 21 Jun 2013 01:05:50 -0700 (PDT) Received-SPF: neutral (google.com: 2a00:1450:400c:c03::22d is neither permitted nor denied by best guess record for domain of ryan.harkin@linaro.org) client-ip=2a00:1450:400c:c03::22d; Received: by mail-we0-f173.google.com with SMTP id x54so6131819wes.18 for ; Fri, 21 Jun 2013 01:05:49 -0700 (PDT) X-Received: by 10.180.206.180 with SMTP id lp20mr1943218wic.41.1371801949687; Fri, 21 Jun 2013 01:05:49 -0700 (PDT) Received: from qpc.lan (82-69-54-187.dsl.in-addr.zen.co.uk. [82.69.54.187]) by mx.google.com with ESMTPSA id ay7sm21069904wib.9.2013.06.21.01.05.48 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 21 Jun 2013 01:05:49 -0700 (PDT) From: Ryan Harkin To: ryan.harkin@linaro.org, edk2-devel@lists.sourceforge.net, patches@linaro.org, boot-architecture@lists.linaro.org, olivier.martin@arm.com Subject: [PATCH 9/9] ArmPlatformPkg/Bds: add local FDT config Date: Fri, 21 Jun 2013 09:05:22 +0100 Message-Id: <1371801922-15142-10-git-send-email-ryan.harkin@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1371801922-15142-1-git-send-email-ryan.harkin@linaro.org> References: <1371801922-15142-1-git-send-email-ryan.harkin@linaro.org> X-Gm-Message-State: ALoCoQmvdXxmVb/CnZoZJawRCurIbtXopsxeUXg0svavByMkvwr7VZJLyytAEQVwM+bWw75nPzzn X-Original-Sender: ryan.harkin@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 2607:f8b0:400c:c01::22f is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , This patch adds a local FDT config option to each boot device. Bds was using a global FDT config for all boot devices of Loader Type = 2. I've added a new Loader Type = 3 that stores an device path to an FDT file this is only used for this boot device. This change will invalidate any existing configs stored on the board due to the change in structure sizes to store the boot device configurations. Signed-off-by: Ryan Harkin --- ArmPlatformPkg/ArmPlatformPkg.dec | 2 + ArmPlatformPkg/Bds/Bds.c | 30 +++- ArmPlatformPkg/Bds/Bds.inf | 1 + ArmPlatformPkg/Bds/BdsInternal.h | 11 +- ArmPlatformPkg/Bds/BootMenu.c | 246 +++++++++++++++++++++++--------- ArmPlatformPkg/Bds/BootOption.c | 46 ++++-- ArmPlatformPkg/Bds/BootOptionSupport.c | 17 ++- 7 files changed, 254 insertions(+), 99 deletions(-) diff --git a/ArmPlatformPkg/ArmPlatformPkg.dec b/ArmPlatformPkg/ArmPlatformPkg.dec index 3e2900b..e672ce2 100644 --- a/ArmPlatformPkg/ArmPlatformPkg.dec +++ b/ArmPlatformPkg/ArmPlatformPkg.dec @@ -136,6 +136,8 @@ gArmPlatformTokenSpaceGuid.PcdDefaultBootType|0|UINT32|0x00000010 gArmPlatformTokenSpaceGuid.PcdFdtDevicePath|L""|VOID*|0x00000011 + gArmPlatformTokenSpaceGuid.PcdDefaultFdtLocalDevicePath|L""|VOID*|0x0000002E + ## Timeout value for displaying progressing bar in before boot OS. # According to UEFI 2.0 spec, the default TimeOut should be 0xffff. gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut|0xffff|UINT16|0x0000001A diff --git a/ArmPlatformPkg/Bds/Bds.c b/ArmPlatformPkg/Bds/Bds.c index 2801fac..d0fc6a3 100644 --- a/ArmPlatformPkg/Bds/Bds.c +++ b/ArmPlatformPkg/Bds/Bds.c @@ -223,8 +223,10 @@ DefineDefaultBootEntries ( ARM_BDS_LOADER_ARGUMENTS* BootArguments; ARM_BDS_LOADER_TYPE BootType; EFI_DEVICE_PATH* InitrdPath; + EFI_DEVICE_PATH* FdtLocalPath; UINTN CmdLineSize; UINTN InitrdSize; + UINTN FdtLocalSize; // // If Boot Order does not exist then create a default entry @@ -262,17 +264,30 @@ DefineDefaultBootEntries ( if (BootDevicePath != NULL) { BootType = (ARM_BDS_LOADER_TYPE)PcdGet32 (PcdDefaultBootType); - if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { + if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) { CmdLineSize = AsciiStrSize ((CHAR8*)PcdGetPtr(PcdDefaultBootArgument)); InitrdPath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootInitrdPath)); InitrdSize = GetDevicePathSize (InitrdPath); + if (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) { + FdtLocalPath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultFdtLocalDevicePath)); + FdtLocalSize = GetDevicePathSize (FdtLocalPath); + } else { + FdtLocalPath = NULL; + FdtLocalSize = 0; + } - BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize); - BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; - BootArguments->LinuxArguments.InitrdSize = InitrdSize; - - CopyMem ((VOID*)(BootArguments + 1), (CHAR8*)PcdGetPtr(PcdDefaultBootArgument), CmdLineSize); - CopyMem ((VOID*)((UINTN)(BootArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); + BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize + FdtLocalSize); + if ( BootArguments != NULL ) { + BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; + BootArguments->LinuxArguments.InitrdSize = InitrdSize; + BootArguments->LinuxArguments.FdtLocalSize = FdtLocalSize; + + CopyMem ((VOID*)(BootArguments + 1), (CHAR8*)PcdGetPtr(PcdDefaultBootArgument), CmdLineSize); + CopyMem ((VOID*)((UINTN)(BootArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); + CopyMem ((VOID*)((UINTN)(BootArguments + 1) + CmdLineSize + InitrdSize), FdtLocalPath, FdtLocalSize); + } + FreePool (FdtLocalPath); + FreePool (InitrdPath); } else { BootArguments = NULL; } @@ -285,6 +300,7 @@ DefineDefaultBootEntries ( &BdsLoadOption ); FreePool (BdsLoadOption); + FreePool (BootDevicePath); } else { Status = EFI_UNSUPPORTED; } diff --git a/ArmPlatformPkg/Bds/Bds.inf b/ArmPlatformPkg/Bds/Bds.inf index 5faa4b2..8b3f1d2 100644 --- a/ArmPlatformPkg/Bds/Bds.inf +++ b/ArmPlatformPkg/Bds/Bds.inf @@ -68,6 +68,7 @@ gArmPlatformTokenSpaceGuid.PcdDefaultBootArgument gArmPlatformTokenSpaceGuid.PcdDefaultBootType gArmPlatformTokenSpaceGuid.PcdFdtDevicePath + gArmPlatformTokenSpaceGuid.PcdDefaultFdtLocalDevicePath gArmPlatformTokenSpaceGuid.PcdPlatformBootTimeOut gArmPlatformTokenSpaceGuid.PcdDefaultConInPaths gArmPlatformTokenSpaceGuid.PcdDefaultConOutPaths diff --git a/ArmPlatformPkg/Bds/BdsInternal.h b/ArmPlatformPkg/Bds/BdsInternal.h index a8d836d..7830066 100644 --- a/ArmPlatformPkg/Bds/BdsInternal.h +++ b/ArmPlatformPkg/Bds/BdsInternal.h @@ -38,6 +38,11 @@ #define BOOT_DEVICE_OPTION_MAX 300 #define BOOT_DEVICE_ADDRESS_MAX (sizeof(L"0x0000000000000000")) +// Length of the buffer used to hold the user input for the main menu +// This includes the NULL terminator +// 1 chars + newline + NULL gives room for up to 9 boot device configs +#define BOOT_OPTION_LEN 3 + #define ARM_BDS_OPTIONAL_DATA_SIGNATURE SIGNATURE_32('a', 'b', 'o', 'd') #define IS_ARM_BDS_BOOTENTRY(ptr) (ReadUnaligned32 ((CONST UINT32*)&((ARM_BDS_LOADER_OPTIONAL_DATA*)((ptr)->OptionalData))->Header.Signature) == ARM_BDS_OPTIONAL_DATA_SIGNATURE) @@ -48,16 +53,20 @@ typedef enum { BDS_LOADER_EFI_APPLICATION = 0, BDS_LOADER_KERNEL_LINUX_ATAG, - BDS_LOADER_KERNEL_LINUX_FDT, + BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT, + BDS_LOADER_KERNEL_LINUX_LOCAL_FDT, } ARM_BDS_LOADER_TYPE; typedef struct { UINT16 CmdLineSize; UINT16 InitrdSize; + UINT16 FdtLocalSize; + // These following fields have variable length and are packed: //CHAR8 *CmdLine; //EFI_DEVICE_PATH_PROTOCOL *InitrdPathList; + //EFI_DEVICE_PATH_PROTOCOL *FdtLocalPathList; } ARM_BDS_LINUX_ARGUMENTS; typedef union { diff --git a/ArmPlatformPkg/Bds/BootMenu.c b/ArmPlatformPkg/Bds/BootMenu.c index 2b32e83..de2117b 100644 --- a/ArmPlatformPkg/Bds/BootMenu.c +++ b/ArmPlatformPkg/Bds/BootMenu.c @@ -128,9 +128,12 @@ BootMenuAddBootOption ( EFI_DEVICE_PATH_PROTOCOL *DevicePathNodes; EFI_DEVICE_PATH_PROTOCOL *InitrdPathNodes; EFI_DEVICE_PATH_PROTOCOL *InitrdPath; + EFI_DEVICE_PATH_PROTOCOL *FdtLocalPathNode; + EFI_DEVICE_PATH_PROTOCOL *FdtLocalPath; UINTN CmdLineSize; BOOLEAN InitrdSupport; UINTN InitrdSize; + UINTN FdtLocalSize; Attributes = 0; SupportedBootDevice = NULL; @@ -155,12 +158,12 @@ BootMenuAddBootOption ( goto EXIT; } - if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { + if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) { Print(L"Add an initrd: "); Status = GetHIInputBoolean (&InitrdSupport); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; - goto EXIT; + goto FREE_DEVICE_PATH; } if (InitrdSupport) { @@ -168,7 +171,7 @@ BootMenuAddBootOption ( Status = SupportedBootDevice->Support->CreateDevicePathNode (L"initrd", &InitrdPathNodes, NULL, NULL); if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd Status = EFI_ABORTED; - goto EXIT; + goto FREE_DEVICE_PATH; } if (InitrdPathNodes != NULL) { @@ -176,7 +179,7 @@ BootMenuAddBootOption ( InitrdPath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes); if (InitrdPath == NULL) { Status = EFI_OUT_OF_RESOURCES; - goto EXIT; + goto FREE_DEVICE_PATH; } } else { InitrdPath = NULL; @@ -192,15 +195,37 @@ BootMenuAddBootOption ( goto FREE_DEVICE_PATH; } - CmdLineSize = AsciiStrSize (CmdLine); - InitrdSize = GetDevicePathSize (InitrdPath); + if (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) { + // Create the specific device path node + Status = SupportedBootDevice->Support->CreateDevicePathNode (L"local FDT", &FdtLocalPathNode, NULL, NULL); + if (EFI_ERROR(Status) || (FdtLocalPathNode == NULL)) { + Status = EFI_ABORTED; + goto FREE_DEVICE_PATH; + } - BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize); + if (FdtLocalPathNode != NULL) { + // Append the Device Path node to the select device path + FdtLocalPath = AppendDevicePathNode (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)FdtLocalPathNode); + } else { + FdtLocalPath = NULL; + } + } else { + FdtLocalPath = NULL; + } - BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; - BootArguments->LinuxArguments.InitrdSize = InitrdSize; - CopyMem ((VOID*)(&BootArguments->LinuxArguments + 1), CmdLine, CmdLineSize); - CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); + CmdLineSize = AsciiStrSize (CmdLine); + InitrdSize = GetDevicePathSize (InitrdPath); + FdtLocalSize = GetDevicePathSize (FdtLocalPath); + + BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize + FdtLocalSize); + if ( BootArguments != NULL ) { + BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; + BootArguments->LinuxArguments.InitrdSize = InitrdSize; + BootArguments->LinuxArguments.FdtLocalSize = FdtLocalSize; + CopyMem ((VOID*)(&BootArguments->LinuxArguments + 1), CmdLine, CmdLineSize); + CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); + CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize + InitrdSize), FdtLocalPath, FdtLocalSize); + } } else { BootArguments = NULL; } @@ -214,6 +239,10 @@ BootMenuAddBootOption ( // Create new entry BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof(BDS_LOAD_OPTION_ENTRY)); + if ( BdsLoadOptionEntry == NULL ) { + Status = EFI_ABORTED; + goto FREE_DEVICE_PATH; + } Status = BootOptionCreate (Attributes, BootDescription, DevicePath, BootType, BootArguments, &BdsLoadOptionEntry->BdsLoadOption); if (!EFI_ERROR(Status)) { InsertTailList (BootOptionsList, &BdsLoadOptionEntry->Link); @@ -274,7 +303,7 @@ BootMenuSelectBootOption ( Print(L"\t- %s\n",DevicePathTxt); OptionalData = BdsLoadOption->OptionalData; LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType); - if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT)) { + if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (LoaderType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) { Print (L"\t- Arguments: %a\n",&OptionalData->Arguments.LinuxArguments + 1); } @@ -366,14 +395,19 @@ BootMenuUpdateBootOption ( CHAR8 CmdLine[BOOT_DEVICE_OPTION_MAX]; EFI_DEVICE_PATH *DevicePath; EFI_DEVICE_PATH *TempInitrdPath; + EFI_DEVICE_PATH *TempFdtLocalPath; ARM_BDS_LOADER_TYPE BootType; ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData; ARM_BDS_LINUX_ARGUMENTS* LinuxArguments; EFI_DEVICE_PATH *InitrdPathNodes; EFI_DEVICE_PATH *InitrdPath; UINTN InitrdSize; + EFI_DEVICE_PATH *FdtLocalPathNode; + EFI_DEVICE_PATH *FdtLocalPath; + UINTN FdtLocalSize; UINTN CmdLineSize; BOOLEAN InitrdSupport; + BOOLEAN FdtLocalSupport; Status = BootMenuSelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, TRUE, &BootOptionEntry); if (EFI_ERROR(Status)) { @@ -397,12 +431,65 @@ BootMenuUpdateBootOption ( OptionalData = BootOption->OptionalData; BootType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((UINT32 *)(&OptionalData->Header.LoaderType)); - if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { + if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) { LinuxArguments = &OptionalData->Arguments.LinuxArguments; CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize); InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize); + FdtLocalSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->FdtLocalSize); + + if (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) { + if (FdtLocalSize > 0) { + Print(L"Keep the local FDT: "); + } else { + Print(L"Add a local FDT: "); + } + Status = GetHIInputBoolean (&FdtLocalSupport); + if (EFI_ERROR(Status)) { + Status = EFI_ABORTED; + goto EXIT; + } + if (FdtLocalSupport && BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) { + if (FdtLocalSize > 0) { + // Case we update the FDT local device path + Status = DeviceSupport->UpdateDevicePathNode ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize + InitrdSize), L"local FDT", &FdtLocalPath, NULL, NULL); + if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) {// EFI_NOT_FOUND is returned on empty input string + Status = EFI_ABORTED; + goto EXIT; + } + FdtLocalSize = GetDevicePathSize (FdtLocalPath); + } else { + // Case we create the FdtLocal device path + + Status = DeviceSupport->CreateDevicePathNode (L"local FDT", &FdtLocalPathNode, NULL, NULL); + if (EFI_ERROR(Status) || (FdtLocalPathNode == NULL)) { + Status = EFI_ABORTED; + goto EXIT; + } + + if (FdtLocalPathNode != NULL) { + // Duplicate Linux kernel Device Path + TempFdtLocalPath = DuplicateDevicePath (BootOption->FilePathList); + if ( TempFdtLocalPath != NULL ) { + // Replace Linux kernel Node by EndNode + SetDevicePathEndNode (GetLastDevicePathNode (TempFdtLocalPath)); + // Append the Device Path node to the select device path + FdtLocalPath = AppendDevicePathNode (TempFdtLocalPath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FdtLocalPathNode); + FreePool (TempFdtLocalPath); + FdtLocalSize = GetDevicePathSize (FdtLocalPath); + } + } else { + FdtLocalPath = NULL; + } + } + } else { + FdtLocalSize = 0; + } + } else { + FdtLocalSupport = FALSE; + } + if (InitrdSize > 0) { Print(L"Keep the initrd: "); } else { @@ -467,11 +554,15 @@ BootMenuUpdateBootOption ( CmdLineSize = AsciiStrSize (CmdLine); - BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool(sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize); - BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; - BootArguments->LinuxArguments.InitrdSize = InitrdSize; - CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize); - CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); + BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool(sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize + FdtLocalSize); + if ( BootArguments != NULL ) { + BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; + BootArguments->LinuxArguments.InitrdSize = InitrdSize; + BootArguments->LinuxArguments.FdtLocalSize = FdtLocalSize; + CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize); + CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); + CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize + InitrdSize), FdtLocalPath, FdtLocalSize); + } } else { BootArguments = NULL; } @@ -648,19 +739,20 @@ BootMenuMain ( VOID ) { - LIST_ENTRY BootOptionsList; - UINTN OptionCount; - UINTN HardCodedOptionCount; - UINTN BootOptionCount; - EFI_STATUS Status; - LIST_ENTRY* Entry; - BDS_LOAD_OPTION* BootOption; - UINTN BootOptionSelected; - UINTN Index; - UINTN BootMainEntryCount; - CHAR8 BootOptionSelectedStr[32]; - EFI_DEVICE_PATH_PROTOCOL* DefaultFdtDevicePath; - UINTN FdtDevicePathSize; + LIST_ENTRY BootOptionsList; + UINTN OptionCount; + UINTN BootOptionCount; + EFI_STATUS Status; + LIST_ENTRY* Entry; + BDS_LOAD_OPTION* BootOption; + UINTN BootOptionSelected; + UINTN Index; + UINTN BootMainEntryCount; + CHAR8 BootOptionSelectedStr[BOOT_OPTION_LEN]; + EFI_DEVICE_PATH_PROTOCOL* DefaultFdtDevicePath; + UINTN FdtDevicePathSize; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; + CHAR16* DevicePathTxt; BootOption = NULL; @@ -682,11 +774,10 @@ BootMenuMain ( Print(L"[%d] %s\n", OptionCount, BootOption->Description); - DEBUG_CODE_BEGIN(); - CHAR16* DevicePathTxt; - EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; + //DEBUG_CODE_BEGIN(); ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData; UINTN CmdLineSize; + UINTN InitrdSize; ARM_BDS_LOADER_TYPE LoaderType; Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); @@ -703,7 +794,7 @@ BootMenuMain ( if (IS_ARM_BDS_BOOTENTRY (BootOption)) { OptionalData = BootOption->OptionalData; LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType); - if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT)) { + if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (LoaderType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) { if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.InitrdSize) > 0) { CmdLineSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize); DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ( @@ -722,16 +813,28 @@ BootMenuMain ( Print(L"\t- LoaderType: Linux kernel with ATAG support\n"); break; - case BDS_LOADER_KERNEL_LINUX_FDT: - Print(L"\t- LoaderType: Linux kernel with FDT support\n"); + case BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT: + Print(L"\t- LoaderType: Linux kernel with global FDT support\n"); + break; + case BDS_LOADER_KERNEL_LINUX_LOCAL_FDT: + if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.FdtLocalSize) > 0) { + CmdLineSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize); + InitrdSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.InitrdSize); + DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ( + GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(&OptionalData->Arguments.LinuxArguments + 1) + CmdLineSize + InitrdSize)), TRUE, TRUE); + Print(L"\t- FDT: %s\n", DevicePathTxt); + } else { + Print(L"\t- FDT: error, local FDT not specified, using global FDT\n"); + } + Print(L"\t- LoaderType: Linux kernel with Local FDT\n"); break; - default: Print(L"\t- LoaderType: Not recognized (%d)\n", LoaderType); + break; } } FreePool(DevicePathTxt); - DEBUG_CODE_END(); + //DEBUG_CODE_END(); OptionCount++; } @@ -739,55 +842,56 @@ BootMenuMain ( // Display the global FDT config Print(L"-----------------------\n"); - { - EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol; - EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath; - EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; - CHAR16* DevicePathTxt; + { + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol; + EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath; - // Get the default FDT device path - Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); - ASSERT_EFI_ERROR(Status); - DefaultFdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath)); + // Get the default FDT device path + Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); + ASSERT_EFI_ERROR(Status); + DefaultFdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath)); - // Get the FDT device path - FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath); - Status = GetEnvironmentVariable ((CHAR16 *)L"Fdt", &gArmGlobalVariableGuid, DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath); + // Get the FDT device path + FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath); + Status = GetEnvironmentVariable ((CHAR16 *)L"Fdt", &gArmGlobalVariableGuid, DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath); - // Convert FdtDevicePath to text - if (EFI_ERROR(Status)) { - DevicePathTxt = L"not configured"; - } else { - Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); - DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ( FdtDevicePath, TRUE, TRUE ); - } - Print(L"Global FDT Config\n\t- %s\n", DevicePathTxt); + // Convert FdtDevicePath to text + if (EFI_ERROR(Status)) { + DevicePathTxt = L"not configured"; + } else { + Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); + DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ( FdtDevicePath, TRUE, TRUE ); } + Print(L"Global FDT Config\n\t- %s\n", DevicePathTxt); + FreePool(DevicePathTxt); + FreePool(DefaultFdtDevicePath); + } // Display the hardcoded Boot entries Print(L"-----------------------\n"); for (Index = 0; Index < BootMainEntryCount; Index++) { - Print(L"[%c] %s\n", ('a'+Index), BootMainEntries[Index]); + Print(L"[%c] %s\n", ('a' + Index), BootMainEntries[Index]); OptionCount++; } - HardCodedOptionCount=Index; // Request the boot entry from the user BootOptionSelected = 0; while (BootOptionSelected == 0) { Print(L"Start: "); - Status = GetHIInputAscii (BootOptionSelectedStr,8); + Status = GetHIInputAscii (BootOptionSelectedStr, BOOT_OPTION_LEN); - if (BootOptionSelectedStr[0]-'0' <= OptionCount) { - BootOptionSelected = BootOptionSelectedStr[0] - '0'; - } else if (BootOptionSelectedStr[0]-'a' <= HardCodedOptionCount) { - BootOptionSelected = BootOptionCount + 1 + BootOptionSelectedStr[0] - 'a'; - } + if (!EFI_ERROR(Status)) { + if ((BootOptionSelectedStr[0] - '0') < OptionCount) { + BootOptionSelected = BootOptionSelectedStr[0] - '0'; + } else if ((BootOptionSelectedStr[0] - 'a') < BootMainEntryCount) { + BootOptionSelected = BootOptionCount + 1 + BootOptionSelectedStr[0] - 'a'; + } - if (EFI_ERROR(Status) || (BootOptionSelected == 0) || (BootOptionSelected > OptionCount)) { - Print(L"Invalid input (max %d)\n",(OptionCount-1)); - BootOptionSelected = 0; - } + if ((BootOptionSelected == 0) || (BootOptionSelected > OptionCount)) { + Print(L"Invalid input, please choose a menu option from the list above\n"); + BootOptionSelected = 0; + } + } } // Start the selected entry diff --git a/ArmPlatformPkg/Bds/BootOption.c b/ArmPlatformPkg/Bds/BootOption.c index ee0301e..6b756a3 100644 --- a/ArmPlatformPkg/Bds/BootOption.c +++ b/ArmPlatformPkg/Bds/BootOption.c @@ -33,6 +33,7 @@ BootOptionStart ( UINTN CmdLineSize; UINTN InitrdSize; EFI_DEVICE_PATH* Initrd; + UINTN FdtLocalSize; UINT16 LoadOptionIndexSize; if (IS_ARM_BDS_BOOTENTRY (BootOption)) { @@ -59,7 +60,7 @@ BootOptionStart ( Status = BdsBootLinuxAtag (BootOption->FilePathList, Initrd, // Initrd (CHAR8*)(LinuxArguments + 1)); // CmdLine - } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT) { + } else if ((LoaderType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (LoaderType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) { LinuxArguments = &(OptionalData->Arguments.LinuxArguments); CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize); InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize); @@ -70,17 +71,27 @@ BootOptionStart ( Initrd = NULL; } - // Get the default FDT device path - Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); - ASSERT_EFI_ERROR(Status); - DefaultFdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath)); - - // Get the FDT device path - FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath); - Status = GetEnvironmentVariable ((CHAR16 *)L"Fdt", &gArmGlobalVariableGuid, - DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath); - ASSERT_EFI_ERROR(Status); + if (LoaderType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT) { + FdtLocalSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->FdtLocalSize); + if (FdtLocalSize > 0) { + FdtDevicePath = GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize + InitrdSize)); + } else { + FdtDevicePath = NULL; + } + } else { + // Get the default FDT device path + Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); + ASSERT_EFI_ERROR(Status); + DefaultFdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath)); + + // Get the FDT device path + FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath); + Status = GetEnvironmentVariable ((CHAR16 *)L"Fdt", &gArmGlobalVariableGuid, + DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath); + ASSERT_EFI_ERROR(Status); + FreePool (DefaultFdtDevicePath); + } Status = BdsBootLinuxFdt (BootOption->FilePathList, Initrd, // Initrd (CHAR8*)(LinuxArguments + 1), @@ -159,6 +170,7 @@ BootOptionSetFields ( UINT16 FilePathListLength; UINT8* EfiLoadOptionPtr; UINT8* InitrdPathListPtr; + UINT8* FdtLocalPathListPtr; UINTN OptionalDataSize; ARM_BDS_LINUX_ARGUMENTS* DestLinuxArguments; ARM_BDS_LINUX_ARGUMENTS* SrcLinuxArguments; @@ -170,8 +182,8 @@ BootOptionSetFields ( BootDescriptionSize = StrSize (BootDescription); BootOptionalDataSize = sizeof(ARM_BDS_LOADER_OPTIONAL_DATA_HEADER); - if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { - BootOptionalDataSize += sizeof(ARM_BDS_LINUX_ARGUMENTS) + BootArguments->LinuxArguments.CmdLineSize + BootArguments->LinuxArguments.InitrdSize; + if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) { + BootOptionalDataSize += sizeof(ARM_BDS_LINUX_ARGUMENTS) + BootArguments->LinuxArguments.CmdLineSize + BootArguments->LinuxArguments.InitrdSize + BootArguments->LinuxArguments.FdtLocalSize; } // Compute the size of the FilePath list @@ -213,12 +225,13 @@ BootOptionSetFields ( OptionalDataSize = sizeof(ARM_BDS_LOADER_OPTIONAL_DATA_HEADER); - if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { + if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT) || (BootType == BDS_LOADER_KERNEL_LINUX_LOCAL_FDT)) { SrcLinuxArguments = &(BootArguments->LinuxArguments); DestLinuxArguments = &((ARM_BDS_LOADER_OPTIONAL_DATA*)EfiLoadOptionPtr)->Arguments.LinuxArguments; WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->CmdLineSize), SrcLinuxArguments->CmdLineSize); WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->InitrdSize), SrcLinuxArguments->InitrdSize); + WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->FdtLocalSize), SrcLinuxArguments->FdtLocalSize); OptionalDataSize += sizeof (ARM_BDS_LINUX_ARGUMENTS); if (SrcLinuxArguments->CmdLineSize > 0) { @@ -230,6 +243,11 @@ BootOptionSetFields ( InitrdPathListPtr = (UINT8*)((UINTN)(DestLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize); CopyMem (InitrdPathListPtr, (VOID*)((UINTN)(SrcLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize), SrcLinuxArguments->InitrdSize); } + + if (SrcLinuxArguments->FdtLocalSize > 0) { + FdtLocalPathListPtr = (UINT8*)((UINTN)(DestLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize + SrcLinuxArguments->InitrdSize); + CopyMem (FdtLocalPathListPtr, (VOID*)((UINTN)(SrcLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize + SrcLinuxArguments->InitrdSize), SrcLinuxArguments->FdtLocalSize); + } } BootOption->OptionalDataSize = OptionalDataSize; diff --git a/ArmPlatformPkg/Bds/BootOptionSupport.c b/ArmPlatformPkg/Bds/BootOptionSupport.c index 190169a..c2df7f9 100644 --- a/ArmPlatformPkg/Bds/BootOptionSupport.c +++ b/ArmPlatformPkg/Bds/BootOptionSupport.c @@ -25,6 +25,7 @@ #include #define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype))) +#define LOCAL_FDT_RESPONSE_LEN 2 // 1 character, plus carriage return EFI_STATUS BdsLoadOptionFileSystemList ( @@ -233,7 +234,7 @@ BootDeviceGetType ( EFI_STATUS Status; BOOLEAN IsEfiApp; BOOLEAN IsBootLoader; - BOOLEAN HasFDTSupport; + CHAR16 FDTType[ LOCAL_FDT_RESPONSE_LEN ]; if (FileName == NULL) { Print(L"Is an EFI Application? "); @@ -258,15 +259,19 @@ BootDeviceGetType ( } *BootType = BDS_LOADER_EFI_APPLICATION; } else { - Print(L"Has FDT support? "); - Status = GetHIInputBoolean (&HasFDTSupport); + Print(L"Boot Type: [a] ATAGS, [g] Global FDT or [l] Local FDT? [a/g/l] "); + Status = GetHIInputStr (FDTType, LOCAL_FDT_RESPONSE_LEN ); if (EFI_ERROR(Status)) { return EFI_ABORTED; } - if (HasFDTSupport) { - *BootType = BDS_LOADER_KERNEL_LINUX_FDT; - } else { + if (StrCmp(FDTType, L"g") == 0) { + *BootType = BDS_LOADER_KERNEL_LINUX_GLOBAL_FDT; + } else if (StrCmp(FDTType, L"l") == 0) { + *BootType = BDS_LOADER_KERNEL_LINUX_LOCAL_FDT; + } else if (StrCmp(FDTType, L"a") == 0) { *BootType = BDS_LOADER_KERNEL_LINUX_ATAG; + } else { + return EFI_ABORTED; } }