From patchwork Mon Nov 20 11:37:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 119269 Delivered-To: patch@linaro.org Received: by 10.140.22.164 with SMTP id 33csp3733766qgn; Mon, 20 Nov 2017 03:37:27 -0800 (PST) X-Google-Smtp-Source: AGs4zMbof59vSEcT6Kj+WKI7Ko07Hy/QMcDC2dT0x9ie2R2ctpy9qlFL4RNa4uBSnmKJ8ukA1y9v X-Received: by 10.159.194.197 with SMTP id u5mr13599735plz.448.1511177847495; Mon, 20 Nov 2017 03:37:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1511177847; cv=none; d=google.com; s=arc-20160816; b=eZ86uk2Vcmj/es5OIEZUuLqbKhi4F4/azK6GFkg3ArTNDkyG8bMonwXr/ivbfJuj34 KjsfspQEAUVFaBu9kvjvAeRnXXCgY8GessmHD2k6MZZcA/GNuHAXL3zztO9u7itRR7jG M+/f4NdfFIbozin9oq+GkmefiaUTmt25MASI+kUcAD7BvkakA3KgFAwvsJfZNQttlJqr qZr3qiiPLVl23dQ1nxeZ5znNgt5ARHQfvGQ7aU5z5RochUi7VwKI3HLKV9icvWCPdYnQ yv77SnGgxAWstNCwyoHCpGCtRLief95+1KBK/se5bTY110UwdMPXdv/UsM5Qd1LIsM9k aUqA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:delivered-to:arc-authentication-results; bh=LbfKH95APOupHzyw1wsc3m5sf7sp9fqIy/7noPBF/H8=; b=H1BWmoWh3ahtPZuuMwQdJse+Jn3GUj/ip3gEL8jQ2Z4IEBOCf+NkxiH34SYykEcE94 QzkdCqrSNyq2TmDG2jPUhdSI8I/aLpsqMMTh2KofCNp/NbRFxOTuBE08t2+wbGh6+aDy pORyQMObkgc12tq0DOISB2DWCg1yvyhHDGCMGcvSbC+TrnFIxTWO1zJAcOy9wfiP8CaD ++TzArzh5+lVUPPxkZQgAXlT59WKhmZf9qWtEd6w4bhUh4eO1m2TWOIxt/KQQ75tGZxj 6jiVyp/WUy4JbOZczErboXeNfU6rRHPapHJmkC2NBMiQMCx4Fs8+fXfOk9SoyuqpXHsX BSRQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=WpxMMc/3; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from ml01.01.org (ml01.01.org. [198.145.21.10]) by mx.google.com with ESMTPS id z5si7634752plh.282.2017.11.20.03.37.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Nov 2017 03:37:27 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) client-ip=198.145.21.10; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=WpxMMc/3; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id DE40220347139; Mon, 20 Nov 2017 03:33:12 -0800 (PST) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2a00:1450:400c:c09::22a; helo=mail-wm0-x22a.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-wm0-x22a.google.com (mail-wm0-x22a.google.com [IPv6:2a00:1450:400c:c09::22a]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id C773E21959707 for ; Mon, 20 Nov 2017 03:33:10 -0800 (PST) Received: by mail-wm0-x22a.google.com with SMTP id y80so17985228wmd.0 for ; Mon, 20 Nov 2017 03:37:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=wfsGkexouKYY46p3nvq/+6DLvAyrLEqlxCbbPpDN0rI=; b=WpxMMc/3UDdHUeoV3LVrTZ7tx5isYyHdrK5rAxDEgHnTGVaE+a1FNmEwjuP6NZJWMZ gIkpD+CBsHXyBMwKOZeH98TO/j1NCBK4Br/s5T4MeRoTaSNkgcPbFfe41CZSjYWBLc8C iHCCzCaQ5TFJvusaoDXR9bJOvC6LPyuiebhkQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=wfsGkexouKYY46p3nvq/+6DLvAyrLEqlxCbbPpDN0rI=; b=UDmzCIVBthYF7zXsV7NYN3K1eFoJLm83lQ91aKqkDwH3MVkPVVVdc0104ILoXms5+n w4L3f5vFL4BpVOUHfm8Bkp1p/PE2WzEBdFBYvzRzfk91nIWvD0vnq8Vmuu0SaMfYv3UN MwaDYrdBTlGM4kLjWERH7ec4bgQvknZQ5ALVWe5GG6tW1BBOaROkc8UxfJOiGppLxWsN 9giVxrSAl2rq+xjdSHeb1YXXiT+iSu2w10+sWhIl5FNIhhXFPVUn33bL1az4DHQzoeCp +z7XxmAwuyzAER2Nvk3KyOF1j+1ghP3p8ujqOGV8ajawLjezfI9m1aSeUvFvhVraDKTZ sOCA== X-Gm-Message-State: AJaThX7laeb/epfYu3vib+TOWil8H5ERpwWoyyFerp6ixYfgWFA+vJTQ xYuAfTk7vLuLMlpgU7kdGZmCPAkz0GA= X-Received: by 10.28.194.139 with SMTP id s133mr9216282wmf.14.1511177842096; Mon, 20 Nov 2017 03:37:22 -0800 (PST) Received: from localhost.localdomain ([154.145.25.106]) by smtp.gmail.com with ESMTPSA id d4sm14760181wmh.35.2017.11.20.03.37.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Nov 2017 03:37:21 -0800 (PST) From: Ard Biesheuvel To: edk2-devel@lists.01.org Date: Mon, 20 Nov 2017 11:37:11 +0000 Message-Id: <20171120113714.21856-2-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171120113714.21856-1-ard.biesheuvel@linaro.org> References: <20171120113714.21856-1-ard.biesheuvel@linaro.org> Subject: [edk2] [PATCH edk2-platforms 1/4] Platform/ARM: import BdsLib from ArmPkg X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: leif.lindholm@linaro.org, Ard Biesheuvel MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" We are about to migrate the only remaining user of the deprecated ARM BdsLib, i.e., FdtPlatformDxe, into Platform/ARM. So create our own copy of BdsLib, allowing us to finally remove it from upstream EDK2. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ard Biesheuvel --- Platform/ARM/Library/BdsLib/BdsAppLoader.c | 253 ++++ Platform/ARM/Library/BdsLib/BdsFilePath.c | 1413 ++++++++++++++++++++ Platform/ARM/Library/BdsLib/BdsHelper.c | 183 +++ Platform/ARM/Library/BdsLib/BdsInternal.h | 111 ++ Platform/ARM/Library/BdsLib/BdsLib.inf | 62 + Platform/ARM/Library/BdsLib/BdsLoadOption.c | 272 ++++ 6 files changed, 2294 insertions(+) -- 2.11.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel diff --git a/Platform/ARM/Library/BdsLib/BdsAppLoader.c b/Platform/ARM/Library/BdsLib/BdsAppLoader.c new file mode 100644 index 000000000000..1f208f8dd796 --- /dev/null +++ b/Platform/ARM/Library/BdsLib/BdsAppLoader.c @@ -0,0 +1,253 @@ +/** @file +* +* Copyright (c) 2011-2015, 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 "BdsInternal.h" + +/** + Locate an EFI application in a the Firmware Volumes by its Name + + @param EfiAppGuid Guid of the EFI Application into the Firmware Volume + @param DevicePath EFI Device Path of the EFI application + + @return EFI_SUCCESS The function completed successfully. + @return EFI_NOT_FOUND The protocol could not be located. + @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. + +**/ +EFI_STATUS +LocateEfiApplicationInFvByName ( + IN CONST CHAR16* EfiAppName, + OUT EFI_DEVICE_PATH **DevicePath + ) +{ + VOID *Key; + EFI_STATUS Status, FileStatus; + EFI_GUID NameGuid; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINTN Size; + UINTN UiStringLen; + CHAR16 *UiSection; + UINT32 Authentication; + EFI_DEVICE_PATH *FvDevicePath; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileDevicePath; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + UINTN Index; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; + + ASSERT (DevicePath != NULL); + + // Length of FilePath + UiStringLen = StrLen (EfiAppName); + + // Locate all the Firmware Volume protocols. + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *DevicePath = NULL; + + // Looking for FV with ACPI storage file + for (Index = 0; Index < NumberOfHandles; Index++) { + // + // Get the protocol on this handle + // This should not fail because of LocateHandleBuffer + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID**) &FvInstance + ); + if (EFI_ERROR (Status)) { + goto FREE_HANDLE_BUFFER; + } + + // Allocate Key + Key = AllocatePool (FvInstance->KeySize); + ASSERT (Key != NULL); + ZeroMem (Key, FvInstance->KeySize); + + do { + // Search in all files + FileType = EFI_FV_FILETYPE_ALL; + + Status = FvInstance->GetNextFile (FvInstance, Key, &FileType, &NameGuid, &Attributes, &Size); + if (!EFI_ERROR (Status)) { + UiSection = NULL; + FileStatus = FvInstance->ReadSection ( + FvInstance, + &NameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + (VOID **)&UiSection, + &Size, + &Authentication + ); + if (!EFI_ERROR (FileStatus)) { + if (StrnCmp (EfiAppName, UiSection, UiStringLen) == 0) { + // + // We found a UiString match. + // + Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath); + + // Generate the Device Path for the file + EfiInitializeFwVolDevicepathNode (&FileDevicePath, &NameGuid); + *DevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FileDevicePath); + ASSERT (*DevicePath != NULL); + + FreePool (Key); + FreePool (UiSection); + FreePool (HandleBuffer); + return FileStatus; + } + FreePool (UiSection); + } + } + } while (!EFI_ERROR (Status)); + + FreePool (Key); + } + +FREE_HANDLE_BUFFER: + FreePool (HandleBuffer); + return EFI_NOT_FOUND; +} + +/** + Locate an EFI application in a the Firmware Volumes by its GUID + + @param EfiAppGuid Guid of the EFI Application into the Firmware Volume + @param DevicePath EFI Device Path of the EFI application + + @return EFI_SUCCESS The function completed successfully. + @return EFI_NOT_FOUND The protocol could not be located. + @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. + +**/ +EFI_STATUS +LocateEfiApplicationInFvByGuid ( + IN CONST EFI_GUID *EfiAppGuid, + OUT EFI_DEVICE_PATH **DevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH *FvDevicePath; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + UINTN Index; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 AuthenticationStatus; + EFI_FV_FILETYPE Type; + UINTN Size; + CHAR16 *UiSection; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileDevicePath; + + ASSERT (DevicePath != NULL); + + // Locate all the Firmware Volume protocols. + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + *DevicePath = NULL; + + // Looking for FV with ACPI storage file + for (Index = 0; Index < NumberOfHandles; Index++) { + // + // Get the protocol on this handle + // This should not fail because of LocateHandleBuffer + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID**) &FvInstance + ); + if (EFI_ERROR (Status)) { + goto FREE_HANDLE_BUFFER; + } + + Status = FvInstance->ReadFile ( + FvInstance, + EfiAppGuid, + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + // + // Skip if no EFI application file in the FV + // + continue; + } else { + UiSection = NULL; + Status = FvInstance->ReadSection ( + FvInstance, + EfiAppGuid, + EFI_SECTION_USER_INTERFACE, + 0, + (VOID **)&UiSection, + &Size, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + // + // Create the EFI Device Path for the application using the Filename of the application + // + *DevicePath = FileDevicePath (HandleBuffer[Index], UiSection); + } else { + Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID**)&FvDevicePath); + ASSERT_EFI_ERROR (Status); + + // + // Create the EFI Device Path for the application using the EFI GUID of the application + // + EfiInitializeFwVolDevicepathNode (&FvFileDevicePath, EfiAppGuid); + + *DevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FvFileDevicePath); + ASSERT (*DevicePath != NULL); + } + break; + } + } + +FREE_HANDLE_BUFFER: + // + // Free any allocated buffers + // + FreePool (HandleBuffer); + + if (*DevicePath == NULL) { + return EFI_NOT_FOUND; + } else { + return EFI_SUCCESS; + } +} diff --git a/Platform/ARM/Library/BdsLib/BdsFilePath.c b/Platform/ARM/Library/BdsLib/BdsFilePath.c new file mode 100644 index 000000000000..7a4a5052a786 --- /dev/null +++ b/Platform/ARM/Library/BdsLib/BdsFilePath.c @@ -0,0 +1,1413 @@ +/** @file +* +* Copyright (c) 2011-2014, 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 "BdsInternal.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_TFTP_FILE_SIZE 0x01000000 + +/* Type and defines to set up the DHCP4 options */ + +typedef struct { + EFI_DHCP4_PACKET_OPTION Head; + UINT8 Route; +} DHCP4_OPTION; + +#define DHCP_TAG_PARA_LIST 55 +#define DHCP_TAG_NETMASK 1 +#define DHCP_TAG_ROUTER 3 + +/* + Constant strings and define related to the message indicating the amount of + progress in the dowloading of a TFTP file. +*/ + +// Frame for the progression slider +STATIC CONST CHAR16 mTftpProgressFrame[] = L"[ ]"; + +// Number of steps in the progression slider +#define TFTP_PROGRESS_SLIDER_STEPS ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 3) + +// Size in number of characters plus one (final zero) of the message to +// indicate the progress of a tftp download. The format is "[(progress slider: +// 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". There +// are thus the number of characters in mTftpProgressFrame[] plus 11 characters +// (2 // spaces, "Kb" and seven characters for the number of KBytes). +#define TFTP_PROGRESS_MESSAGE_SIZE ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) + 12) + +// String to delete the tftp progress message to be able to update it : +// (TFTP_PROGRESS_MESSAGE_SIZE-1) '\b' +STATIC CONST CHAR16 mTftpProgressDelete[] = L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"; + + +// Extract the FilePath from the Device Path +CHAR16* +BdsExtractFilePathFromDevicePath ( + IN CONST CHAR16 *StrDevicePath, + IN UINTN NumberDevicePathNode + ) +{ + UINTN Node; + CHAR16 *Str; + + Str = (CHAR16*)StrDevicePath; + Node = 0; + while ((Str != NULL) && (*Str != L'\0') && (Node < NumberDevicePathNode)) { + if ((*Str == L'/') || (*Str == L'\\')) { + Node++; + } + Str++; + } + + if (*Str == L'\0') { + return NULL; + } else { + return Str; + } +} + +BOOLEAN +BdsIsRemovableUsb ( + IN EFI_DEVICE_PATH* DevicePath + ) +{ + return ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) && + ((DevicePathSubType (DevicePath) == MSG_USB_CLASS_DP) || + (DevicePathSubType (DevicePath) == MSG_USB_WWID_DP))); +} + +EFI_STATUS +BdsGetDeviceUsb ( + IN EFI_DEVICE_PATH* RemovableDevicePath, + OUT EFI_HANDLE* DeviceHandle, + OUT EFI_DEVICE_PATH** NewDevicePath + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN UsbIoHandleCount; + EFI_HANDLE *UsbIoBuffer; + EFI_DEVICE_PATH* UsbIoDevicePath; + EFI_DEVICE_PATH* TmpDevicePath; + USB_WWID_DEVICE_PATH* WwidDevicePath1; + USB_WWID_DEVICE_PATH* WwidDevicePath2; + USB_CLASS_DEVICE_PATH* UsbClassDevicePath1; + USB_CLASS_DEVICE_PATH* UsbClassDevicePath2; + + // Get all the UsbIo handles + UsbIoHandleCount = 0; + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiUsbIoProtocolGuid, NULL, &UsbIoHandleCount, &UsbIoBuffer); + if (EFI_ERROR (Status) || (UsbIoHandleCount == 0)) { + return Status; + } + + // Check if one of the handles matches the USB description + for (Index = 0; Index < UsbIoHandleCount; Index++) { + Status = gBS->HandleProtocol (UsbIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **) &UsbIoDevicePath); + if (!EFI_ERROR (Status)) { + TmpDevicePath = UsbIoDevicePath; + while (!IsDevicePathEnd (TmpDevicePath)) { + // Check if the Device Path node is a USB Removable device Path node + if (BdsIsRemovableUsb (TmpDevicePath)) { + if (TmpDevicePath->SubType == MSG_USB_WWID_DP) { + WwidDevicePath1 = (USB_WWID_DEVICE_PATH*)RemovableDevicePath; + WwidDevicePath2 = (USB_WWID_DEVICE_PATH*)TmpDevicePath; + if ((WwidDevicePath1->VendorId == WwidDevicePath2->VendorId) && + (WwidDevicePath1->ProductId == WwidDevicePath2->ProductId) && + (CompareMem (WwidDevicePath1+1, WwidDevicePath2+1, DevicePathNodeLength(WwidDevicePath1)-sizeof (USB_WWID_DEVICE_PATH)) == 0)) + { + *DeviceHandle = UsbIoBuffer[Index]; + // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path + *NewDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePathNode (RemovableDevicePath)); + return EFI_SUCCESS; + } + } else { + UsbClassDevicePath1 = (USB_CLASS_DEVICE_PATH*)RemovableDevicePath; + UsbClassDevicePath2 = (USB_CLASS_DEVICE_PATH*)TmpDevicePath; + if ((UsbClassDevicePath1->VendorId != 0xFFFF) && (UsbClassDevicePath1->VendorId == UsbClassDevicePath2->VendorId) && + (UsbClassDevicePath1->ProductId != 0xFFFF) && (UsbClassDevicePath1->ProductId == UsbClassDevicePath2->ProductId) && + (UsbClassDevicePath1->DeviceClass != 0xFF) && (UsbClassDevicePath1->DeviceClass == UsbClassDevicePath2->DeviceClass) && + (UsbClassDevicePath1->DeviceSubClass != 0xFF) && (UsbClassDevicePath1->DeviceSubClass == UsbClassDevicePath2->DeviceSubClass) && + (UsbClassDevicePath1->DeviceProtocol != 0xFF) && (UsbClassDevicePath1->DeviceProtocol == UsbClassDevicePath2->DeviceProtocol)) + { + *DeviceHandle = UsbIoBuffer[Index]; + // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path + *NewDevicePath = AppendDevicePath (UsbIoDevicePath, NextDevicePathNode (RemovableDevicePath)); + return EFI_SUCCESS; + } + } + } + TmpDevicePath = NextDevicePathNode (TmpDevicePath); + } + + } + } + + return EFI_NOT_FOUND; +} + +BOOLEAN +BdsIsRemovableHd ( + IN EFI_DEVICE_PATH* DevicePath + ) +{ + return IS_DEVICE_PATH_NODE (DevicePath, MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP); +} + +EFI_STATUS +BdsGetDeviceHd ( + IN EFI_DEVICE_PATH* RemovableDevicePath, + OUT EFI_HANDLE* DeviceHandle, + OUT EFI_DEVICE_PATH** NewDevicePath + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN PartitionHandleCount; + EFI_HANDLE *PartitionBuffer; + EFI_DEVICE_PATH* PartitionDevicePath; + EFI_DEVICE_PATH* TmpDevicePath; + HARDDRIVE_DEVICE_PATH* HardDriveDevicePath1; + HARDDRIVE_DEVICE_PATH* HardDriveDevicePath2; + + // Get all the DiskIo handles + PartitionHandleCount = 0; + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDiskIoProtocolGuid, NULL, &PartitionHandleCount, &PartitionBuffer); + if (EFI_ERROR (Status) || (PartitionHandleCount == 0)) { + return Status; + } + + // Check if one of the handles matches the Hard Disk Description + for (Index = 0; Index < PartitionHandleCount; Index++) { + Status = gBS->HandleProtocol (PartitionBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **) &PartitionDevicePath); + if (!EFI_ERROR (Status)) { + TmpDevicePath = PartitionDevicePath; + while (!IsDevicePathEnd (TmpDevicePath)) { + // Check if the Device Path node is a HD Removable device Path node + if (BdsIsRemovableHd (TmpDevicePath)) { + HardDriveDevicePath1 = (HARDDRIVE_DEVICE_PATH*)RemovableDevicePath; + HardDriveDevicePath2 = (HARDDRIVE_DEVICE_PATH*)TmpDevicePath; + if ((HardDriveDevicePath1->SignatureType == HardDriveDevicePath2->SignatureType) && + (CompareGuid ((EFI_GUID *)HardDriveDevicePath1->Signature, (EFI_GUID *)HardDriveDevicePath2->Signature) == TRUE) && + (HardDriveDevicePath1->PartitionNumber == HardDriveDevicePath2->PartitionNumber)) + { + *DeviceHandle = PartitionBuffer[Index]; + // Add the additional original Device Path Nodes (eg: FilePath Device Path Node) to the new Device Path + *NewDevicePath = AppendDevicePath (PartitionDevicePath, NextDevicePathNode (RemovableDevicePath)); + return EFI_SUCCESS; + } + } + TmpDevicePath = NextDevicePathNode (TmpDevicePath); + } + + } + } + + return EFI_NOT_FOUND; +} + +/*BOOLEAN +BdsIsRemovableCdrom ( + IN EFI_DEVICE_PATH* DevicePath + ) +{ + return IS_DEVICE_PATH_NODE (DevicePath, MEDIA_DEVICE_PATH, MEDIA_CDROM_DP); +} + +EFI_STATUS +BdsGetDeviceCdrom ( + IN EFI_DEVICE_PATH* RemovableDevicePath, + OUT EFI_HANDLE* DeviceHandle, + OUT EFI_DEVICE_PATH** DevicePath + ) +{ + ASSERT(0); + return EFI_UNSUPPORTED; +}*/ + +typedef BOOLEAN +(*BDS_IS_REMOVABLE) ( + IN EFI_DEVICE_PATH* DevicePath + ); + +typedef EFI_STATUS +(*BDS_GET_DEVICE) ( + IN EFI_DEVICE_PATH* RemovableDevicePath, + OUT EFI_HANDLE* DeviceHandle, + OUT EFI_DEVICE_PATH** DevicePath + ); + +typedef struct { + BDS_IS_REMOVABLE IsRemovable; + BDS_GET_DEVICE GetDevice; +} BDS_REMOVABLE_DEVICE_SUPPORT; + +BDS_REMOVABLE_DEVICE_SUPPORT RemovableDeviceSupport[] = { + { BdsIsRemovableUsb, BdsGetDeviceUsb }, + { BdsIsRemovableHd, BdsGetDeviceHd }, + //{ BdsIsRemovableCdrom, BdsGetDeviceCdrom } +}; + +STATIC +BOOLEAN +IsRemovableDevice ( + IN EFI_DEVICE_PATH* DevicePath + ) +{ + UINTN Index; + EFI_DEVICE_PATH* TmpDevicePath; + + TmpDevicePath = DevicePath; + while (!IsDevicePathEnd (TmpDevicePath)) { + for (Index = 0; Index < sizeof (RemovableDeviceSupport) / sizeof (BDS_REMOVABLE_DEVICE_SUPPORT); Index++) { + if (RemovableDeviceSupport[Index].IsRemovable (TmpDevicePath)) { + return TRUE; + } + } + TmpDevicePath = NextDevicePathNode (TmpDevicePath); + } + + return FALSE; +} + +STATIC +EFI_STATUS +TryRemovableDevice ( + IN EFI_DEVICE_PATH* DevicePath, + OUT EFI_HANDLE* DeviceHandle, + OUT EFI_DEVICE_PATH** NewDevicePath + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_DEVICE_PATH* TmpDevicePath; + BDS_REMOVABLE_DEVICE_SUPPORT* RemovableDevice; + EFI_DEVICE_PATH* RemovableDevicePath; + BOOLEAN RemovableFound; + + RemovableDevice = NULL; + RemovableDevicePath = NULL; + RemovableFound = FALSE; + TmpDevicePath = DevicePath; + + while (!IsDevicePathEnd (TmpDevicePath) && !RemovableFound) { + for (Index = 0; Index < sizeof (RemovableDeviceSupport) / sizeof (BDS_REMOVABLE_DEVICE_SUPPORT); Index++) { + RemovableDevice = &RemovableDeviceSupport[Index]; + if (RemovableDevice->IsRemovable (TmpDevicePath)) { + RemovableDevicePath = TmpDevicePath; + RemovableFound = TRUE; + break; + } + } + TmpDevicePath = NextDevicePathNode (TmpDevicePath); + } + + if (!RemovableFound) { + return EFI_NOT_FOUND; + } + + // Search into the current started drivers + Status = RemovableDevice->GetDevice (RemovableDevicePath, DeviceHandle, NewDevicePath); + if (Status == EFI_NOT_FOUND) { + // Connect all the drivers + BdsConnectAllDrivers (); + + // Search again into all the drivers + Status = RemovableDevice->GetDevice (RemovableDevicePath, DeviceHandle, NewDevicePath); + } + + return Status; +} + +STATIC +EFI_STATUS +BdsConnectAndUpdateDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT EFI_HANDLE *Handle, + OUT EFI_DEVICE_PATH_PROTOCOL **RemainingDevicePath + ) +{ + EFI_DEVICE_PATH* Remaining; + EFI_DEVICE_PATH* NewDevicePath; + EFI_STATUS Status; + EFI_HANDLE PreviousHandle; + + if ((DevicePath == NULL) || (*DevicePath == NULL) || (Handle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + PreviousHandle = NULL; + do { + Remaining = *DevicePath; + + // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns + // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified + // to point to the remaining part of the device path + Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Remaining, Handle); + + if (!EFI_ERROR (Status)) { + if (*Handle == PreviousHandle) { + // + // If no forward progress is made try invoking the Dispatcher. + // A new FV may have been added to the system and new drivers + // may now be found. + // Status == EFI_SUCCESS means a driver was dispatched + // Status == EFI_NOT_FOUND means no new drivers were dispatched + // + Status = gDS->Dispatch (); + } + + if (!EFI_ERROR (Status)) { + PreviousHandle = *Handle; + + // Recursive = FALSE: We do not want to start the whole device tree + Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE); + } + } + } while (!EFI_ERROR (Status) && !IsDevicePathEnd (Remaining)); + + if (!EFI_ERROR (Status)) { + // Now, we have got the whole Device Path connected, call again ConnectController to ensure all the supported Driver + // Binding Protocol are connected (such as DiskIo and SimpleFileSystem) + Remaining = *DevicePath; + Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Remaining, Handle); + if (!EFI_ERROR (Status)) { + Status = gBS->ConnectController (*Handle, NULL, Remaining, FALSE); + if (EFI_ERROR (Status)) { + // If the last node is a Memory Map Device Path just return EFI_SUCCESS. + if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) { + Status = EFI_SUCCESS; + } + } + } + } else if (!IsDevicePathEnd (Remaining) && !IsRemovableDevice (Remaining)) { + + /*// If the remaining Device Path is a FilePath or MemoryMap then we consider the Device Path has been loaded correctly + if ((Remaining->Type == MEDIA_DEVICE_PATH) && (Remaining->SubType == MEDIA_FILEPATH_DP)) { + Status = EFI_SUCCESS; + } else if ((Remaining->Type == HARDWARE_DEVICE_PATH) && (Remaining->SubType == HW_MEMMAP_DP)) { + Status = EFI_SUCCESS; + }*/ + + //TODO: Should we just return success and leave the caller decide if it is the expected RemainingPath + Status = EFI_SUCCESS; + } else { + Status = TryRemovableDevice (*DevicePath, Handle, &NewDevicePath); + if (!EFI_ERROR (Status)) { + Status = BdsConnectAndUpdateDevicePath (&NewDevicePath, Handle, RemainingDevicePath); + *DevicePath = NewDevicePath; + return Status; + } + } + + if (RemainingDevicePath) { + *RemainingDevicePath = Remaining; + } + + return Status; +} + +/** + Connect a Device Path and return the handle of the driver that support this DevicePath + + @param DevicePath Device Path of the File to connect + @param Handle Handle of the driver that support this DevicePath + @param RemainingDevicePath Remaining DevicePath nodes that do not match the driver DevicePath + + @retval EFI_SUCCESS A driver that matches the Device Path has been found + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_INVALID_PARAMETER DevicePath or Handle is NULL + +**/ +EFI_STATUS +BdsConnectDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, + OUT EFI_HANDLE *Handle, + OUT EFI_DEVICE_PATH_PROTOCOL **RemainingDevicePath + ) +{ + return BdsConnectAndUpdateDevicePath (&DevicePath, Handle, RemainingDevicePath); +} + +BOOLEAN +BdsFileSystemSupport ( + IN EFI_DEVICE_PATH *DevicePath, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FsProtocol; + + Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FsProtocol); + + return (!EFI_ERROR (Status) && IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP)); +} + +EFI_STATUS +BdsFileSystemLoadImage ( + IN OUT EFI_DEVICE_PATH **DevicePath, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH *RemainingDevicePath, + IN EFI_ALLOCATE_TYPE Type, + IN OUT EFI_PHYSICAL_ADDRESS *Image, + OUT UINTN *ImageSize + ) +{ + EFI_STATUS Status; + FILEPATH_DEVICE_PATH *FilePathDevicePath; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FsProtocol; + EFI_FILE_PROTOCOL *Fs; + EFI_FILE_INFO *FileInfo; + EFI_FILE_PROTOCOL *File; + UINTN Size; + + ASSERT (IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP)); + + FilePathDevicePath = (FILEPATH_DEVICE_PATH*)RemainingDevicePath; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID**)&FsProtocol, + gImageHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Try to Open the volume and get root directory + Status = FsProtocol->OpenVolume (FsProtocol, &Fs); + if (EFI_ERROR (Status)) { + goto CLOSE_PROTOCOL; + } + + Status = Fs->Open (Fs, &File, FilePathDevicePath->PathName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + goto CLOSE_PROTOCOL; + } + + Size = 0; + File->GetInfo (File, &gEfiFileInfoGuid, &Size, NULL); + FileInfo = AllocatePool (Size); + Status = File->GetInfo (File, &gEfiFileInfoGuid, &Size, FileInfo); + if (EFI_ERROR (Status)) { + goto CLOSE_FILE; + } + + // Get the file size + Size = FileInfo->FileSize; + if (ImageSize) { + *ImageSize = Size; + } + FreePool (FileInfo); + + Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image); + // Try to allocate in any pages if failed to allocate memory at the defined location + if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) { + Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image); + } + if (!EFI_ERROR (Status)) { + Status = File->Read (File, &Size, (VOID*)(UINTN)(*Image)); + } + +CLOSE_FILE: + File->Close (File); + +CLOSE_PROTOCOL: + gBS->CloseProtocol ( + Handle, + &gEfiSimpleFileSystemProtocolGuid, + gImageHandle, + Handle); + + return Status; +} + +BOOLEAN +BdsMemoryMapSupport ( + IN EFI_DEVICE_PATH *DevicePath, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH *RemainingDevicePath + ) +{ + return IS_DEVICE_PATH_NODE (DevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP) || + IS_DEVICE_PATH_NODE (RemainingDevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP); +} + +EFI_STATUS +BdsMemoryMapLoadImage ( + IN OUT EFI_DEVICE_PATH **DevicePath, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH *RemainingDevicePath, + IN EFI_ALLOCATE_TYPE Type, + IN OUT EFI_PHYSICAL_ADDRESS* Image, + OUT UINTN *ImageSize + ) +{ + EFI_STATUS Status; + MEMMAP_DEVICE_PATH* MemMapPathDevicePath; + UINTN Size; + + if (IS_DEVICE_PATH_NODE (RemainingDevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP)) { + MemMapPathDevicePath = (MEMMAP_DEVICE_PATH*)RemainingDevicePath; + } else { + ASSERT (IS_DEVICE_PATH_NODE (*DevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP)); + MemMapPathDevicePath = (MEMMAP_DEVICE_PATH*)*DevicePath; + } + + Size = MemMapPathDevicePath->EndingAddress - MemMapPathDevicePath->StartingAddress; + if (Size == 0) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image); + // Try to allocate in any pages if failed to allocate memory at the defined location + if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) { + Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image); + } + if (!EFI_ERROR (Status)) { + CopyMem ((VOID*)(UINTN)(*Image), (CONST VOID*)(UINTN)MemMapPathDevicePath->StartingAddress, Size); + + if (ImageSize != NULL) { + *ImageSize = Size; + } + } + + return Status; +} + +BOOLEAN +BdsFirmwareVolumeSupport ( + IN EFI_DEVICE_PATH *DevicePath, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH *RemainingDevicePath + ) +{ + return IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP); +} + +EFI_STATUS +BdsFirmwareVolumeLoadImage ( + IN OUT EFI_DEVICE_PATH **DevicePath, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH *RemainingDevicePath, + IN EFI_ALLOCATE_TYPE Type, + IN OUT EFI_PHYSICAL_ADDRESS* Image, + OUT UINTN *ImageSize + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; + EFI_GUID *FvNameGuid; + EFI_SECTION_TYPE SectionType; + EFI_FV_FILETYPE FvType; + EFI_FV_FILE_ATTRIBUTES Attrib; + UINT32 AuthenticationStatus; + VOID* ImageBuffer; + + ASSERT (IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_PIWG_FW_FILE_DP)); + + Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FwVol); + if (EFI_ERROR (Status)) { + return Status; + } + + FvNameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)RemainingDevicePath); + if (FvNameGuid == NULL) { + Status = EFI_INVALID_PARAMETER; + } + + SectionType = EFI_SECTION_PE32; + AuthenticationStatus = 0; + //Note: ReadSection at the opposite of ReadFile does not allow to pass ImageBuffer == NULL to get the size of the file. + ImageBuffer = NULL; + Status = FwVol->ReadSection ( + FwVol, + FvNameGuid, + SectionType, + 0, + &ImageBuffer, + ImageSize, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { +#if 0 + // In case the buffer has some address requirements, we must copy the buffer to a buffer following the requirements + if (Type != AllocateAnyPages) { + Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize),Image); + if (!EFI_ERROR (Status)) { + CopyMem ((VOID*)(UINTN)(*Image), ImageBuffer, *ImageSize); + FreePool (ImageBuffer); + } + } +#else + // We must copy the buffer into a page allocations. Otherwise, the caller could call gBS->FreePages() on the pool allocation + Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image); + // Try to allocate in any pages if failed to allocate memory at the defined location + if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) { + Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image); + } + if (!EFI_ERROR (Status)) { + CopyMem ((VOID*)(UINTN)(*Image), ImageBuffer, *ImageSize); + FreePool (ImageBuffer); + } +#endif + } else { + // Try a raw file, since a PE32 SECTION does not exist + Status = FwVol->ReadFile ( + FwVol, + FvNameGuid, + NULL, + ImageSize, + &FvType, + &Attrib, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image); + // Try to allocate in any pages if failed to allocate memory at the defined location + if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) { + Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(*ImageSize), Image); + } + if (!EFI_ERROR (Status)) { + Status = FwVol->ReadFile ( + FwVol, + FvNameGuid, + (VOID**)Image, + ImageSize, + &FvType, + &Attrib, + &AuthenticationStatus + ); + } + } + } + return Status; +} + +BOOLEAN +BdsPxeSupport ( + IN EFI_DEVICE_PATH* DevicePath, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH* RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PXE_BASE_CODE_PROTOCOL* PxeBcProtocol; + + if (!IsDevicePathEnd (RemainingDevicePath)) { + return FALSE; + } + + Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol); + if (EFI_ERROR (Status)) { + return FALSE; + } else { + return TRUE; + } +} + +EFI_STATUS +BdsPxeLoadImage ( + IN OUT EFI_DEVICE_PATH **DevicePath, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH *RemainingDevicePath, + IN EFI_ALLOCATE_TYPE Type, + IN OUT EFI_PHYSICAL_ADDRESS* Image, + OUT UINTN *ImageSize + ) +{ + EFI_STATUS Status; + EFI_LOAD_FILE_PROTOCOL *LoadFileProtocol; + UINTN BufferSize; + EFI_PXE_BASE_CODE_PROTOCOL *Pxe; + + // Get Load File Protocol attached to the PXE protocol + Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **)&LoadFileProtocol); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = LoadFileProtocol->LoadFile (LoadFileProtocol, RemainingDevicePath, TRUE, &BufferSize, NULL); + if (Status == EFI_BUFFER_TOO_SMALL) { + Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(BufferSize), Image); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = LoadFileProtocol->LoadFile (LoadFileProtocol, RemainingDevicePath, TRUE, &BufferSize, (VOID*)(UINTN)(*Image)); + if (!EFI_ERROR (Status) && (ImageSize != NULL)) { + *ImageSize = BufferSize; + } + } + + if (Status == EFI_ALREADY_STARTED) { + Status = gBS->LocateProtocol (&gEfiPxeBaseCodeProtocolGuid, NULL, (VOID **)&Pxe); + if (!EFI_ERROR(Status)) { + // If PXE is already started, we stop it + Pxe->Stop (Pxe); + // And we try again + return BdsPxeLoadImage (DevicePath, Handle, RemainingDevicePath, Type, Image, ImageSize); + } + } + return Status; +} + +BOOLEAN +BdsTftpSupport ( + IN EFI_DEVICE_PATH *DevicePath, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH *NextDevicePath; + VOID *Interface; + + // Validate the Remaining Device Path + if (IsDevicePathEnd (RemainingDevicePath)) { + return FALSE; + } + if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP) && + !IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv6_DP)) { + return FALSE; + } + NextDevicePath = NextDevicePathNode (RemainingDevicePath); + if (IsDevicePathEnd (NextDevicePath)) { + return FALSE; + } + if (!IS_DEVICE_PATH_NODE (NextDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP)) { + return FALSE; + } + + Status = gBS->HandleProtocol ( + Handle, &gEfiDevicePathProtocolGuid, + &Interface + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Check that the controller (identified by its handle "Handle") supports the + // MTFTPv4 Service Binding Protocol. If it does, it means that it supports the + // EFI MTFTPv4 Protocol needed to download the image through TFTP. + // + Status = gBS->HandleProtocol ( + Handle, &gEfiMtftp4ServiceBindingProtocolGuid, + &Interface + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + return TRUE; +} + +/** + Worker function that get the size in numbers of bytes of a file from a TFTP + server before to download the file. + + @param[in] Mtftp4 MTFTP4 protocol interface + @param[in] FilePath Path of the file, Ascii encoded + @param[out] FileSize Address where to store the file size in number of + bytes. + + @retval EFI_SUCCESS The size of the file was returned. + @retval !EFI_SUCCESS The size of the file was not returned. + +**/ +STATIC +EFI_STATUS +Mtftp4GetFileSize ( + IN EFI_MTFTP4_PROTOCOL *Mtftp4, + IN CHAR8 *FilePath, + OUT UINT64 *FileSize + ) +{ + EFI_STATUS Status; + EFI_MTFTP4_OPTION ReqOpt[1]; + EFI_MTFTP4_PACKET *Packet; + UINT32 PktLen; + EFI_MTFTP4_OPTION *TableOfOptions; + EFI_MTFTP4_OPTION *Option; + UINT32 OptCnt; + UINT8 OptBuf[128]; + + ReqOpt[0].OptionStr = (UINT8*)"tsize"; + OptBuf[0] = '0'; + OptBuf[1] = 0; + ReqOpt[0].ValueStr = OptBuf; + + Status = Mtftp4->GetInfo ( + Mtftp4, + NULL, + (UINT8*)FilePath, + NULL, + 1, + ReqOpt, + &PktLen, + &Packet + ); + + if (EFI_ERROR (Status)) { + goto Error; + } + + Status = Mtftp4->ParseOptions ( + Mtftp4, + PktLen, + Packet, + (UINT32 *) &OptCnt, + &TableOfOptions + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Option = TableOfOptions; + while (OptCnt != 0) { + if (AsciiStrnCmp ((CHAR8 *)Option->OptionStr, "tsize", 5) == 0) { + *FileSize = AsciiStrDecimalToUint64 ((CHAR8 *)Option->ValueStr); + break; + } + OptCnt--; + Option++; + } + FreePool (TableOfOptions); + + if (OptCnt == 0) { + Status = EFI_UNSUPPORTED; + } + +Error : + + return Status; +} + +/** + Update the progress of a file download + This procedure is called each time a new TFTP packet is received. + + @param[in] This MTFTP4 protocol interface + @param[in] Token Parameters for the download of the file + @param[in] PacketLen Length of the packet + @param[in] Packet Address of the packet + + @retval EFI_SUCCESS All packets are accepted. + +**/ +STATIC +EFI_STATUS +Mtftp4CheckPacket ( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token, + IN UINT16 PacketLen, + IN EFI_MTFTP4_PACKET *Packet + ) +{ + BDS_TFTP_CONTEXT *Context; + CHAR16 Progress[TFTP_PROGRESS_MESSAGE_SIZE]; + UINT64 NbOfKb; + UINTN Index; + UINTN LastStep; + UINTN Step; + UINT64 LastNbOf50Kb; + UINT64 NbOf50Kb; + + if ((NTOHS (Packet->OpCode)) == EFI_MTFTP4_OPCODE_DATA) { + Context = (BDS_TFTP_CONTEXT*)Token->Context; + + if (Context->DownloadedNbOfBytes == 0) { + if (Context->FileSize > 0) { + Print (L"%s 0 Kb", mTftpProgressFrame); + } else { + Print (L" 0 Kb"); + } + } + + // + // The data is the packet are prepended with two UINT16 : + // . OpCode = EFI_MTFTP4_OPCODE_DATA + // . Block = the number of this block of data + // + Context->DownloadedNbOfBytes += PacketLen - sizeof (Packet->OpCode) - sizeof (Packet->Data.Block); + NbOfKb = Context->DownloadedNbOfBytes / 1024; + + Progress[0] = L'\0'; + if (Context->FileSize > 0) { + LastStep = (Context->LastReportedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize; + Step = (Context->DownloadedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize; + if (Step > LastStep) { + Print (mTftpProgressDelete); + CopyMem (Progress, mTftpProgressFrame, sizeof mTftpProgressFrame); + for (Index = 1; Index < Step; Index++) { + Progress[Index] = L'='; + } + Progress[Step] = L'>'; + + UnicodeSPrint ( + Progress + (sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 1, + sizeof (Progress) - sizeof (mTftpProgressFrame), + L" %7d Kb", + NbOfKb + ); + Context->LastReportedNbOfBytes = Context->DownloadedNbOfBytes; + } + } else { + // + // Case when we do not know the size of the final file. + // We print the updated size every 50KB of downloaded data + // + LastNbOf50Kb = Context->LastReportedNbOfBytes / (50*1024); + NbOf50Kb = Context->DownloadedNbOfBytes / (50*1024); + if (NbOf50Kb > LastNbOf50Kb) { + Print (L"\b\b\b\b\b\b\b\b\b\b"); + UnicodeSPrint (Progress, sizeof (Progress), L"%7d Kb", NbOfKb); + Context->LastReportedNbOfBytes = Context->DownloadedNbOfBytes; + } + } + if (Progress[0] != L'\0') { + Print (L"%s", Progress); + } + } + + return EFI_SUCCESS; +} + +/** + Download an image from a TFTP server + + @param[in] DevicePath Device path of the TFTP boot option + @param[in] ControllerHandle Handle of the network controller + @param[in] RemainingDevicePath Device path of the TFTP boot option but + the first node that identifies the network controller + @param[in] Type Type to allocate memory pages + @param[out] Image Address of the bufer where the image is stored in + case of success + @param[out] ImageSize Size in number of bytes of the i;age in case of + success + + @retval EFI_SUCCESS The image was returned. + @retval !EFI_SUCCESS Something went wrong. + +**/ +EFI_STATUS +BdsTftpLoadImage ( + IN OUT EFI_DEVICE_PATH **DevicePath, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH *RemainingDevicePath, + IN EFI_ALLOCATE_TYPE Type, + IN OUT EFI_PHYSICAL_ADDRESS *Image, + OUT UINTN *ImageSize + ) +{ + EFI_STATUS Status; + EFI_HANDLE Dhcp4ChildHandle; + EFI_DHCP4_PROTOCOL *Dhcp4; + BOOLEAN Dhcp4ToStop; + EFI_HANDLE Mtftp4ChildHandle; + EFI_MTFTP4_PROTOCOL *Mtftp4; + DHCP4_OPTION ParaList; + EFI_DHCP4_PACKET_OPTION *OptionList[2]; + EFI_DHCP4_CONFIG_DATA Dhcp4CfgData; + EFI_DHCP4_MODE_DATA Dhcp4Mode; + EFI_MTFTP4_CONFIG_DATA Mtftp4CfgData; + IPv4_DEVICE_PATH *IPv4DevicePathNode; + CHAR16 *PathName; + CHAR8 *AsciiFilePath; + EFI_MTFTP4_TOKEN Mtftp4Token; + UINT64 FileSize; + UINT64 TftpBufferSize; + BDS_TFTP_CONTEXT *TftpContext; + UINTN PathNameLen; + + ASSERT(IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP)); + IPv4DevicePathNode = (IPv4_DEVICE_PATH*)RemainingDevicePath; + + Dhcp4ChildHandle = NULL; + Dhcp4 = NULL; + Dhcp4ToStop = FALSE; + Mtftp4ChildHandle = NULL; + Mtftp4 = NULL; + AsciiFilePath = NULL; + TftpContext = NULL; + + if (!IPv4DevicePathNode->StaticIpAddress) { + // + // Using the DHCP4 Service Binding Protocol, create a child handle of the DHCP4 service and + // install the DHCP4 protocol on it. Then, open the DHCP protocol. + // + Status = NetLibCreateServiceChild ( + ControllerHandle, + gImageHandle, + &gEfiDhcp4ServiceBindingProtocolGuid, + &Dhcp4ChildHandle + ); + if (!EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Dhcp4ChildHandle, + &gEfiDhcp4ProtocolGuid, + (VOID **) &Dhcp4, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + } + if (EFI_ERROR (Status)) { + Print (L"Unable to open DHCP4 protocol\n"); + goto Error; + } + } + + // + // Using the MTFTP4 Service Binding Protocol, create a child handle of the MTFTP4 service and + // install the MTFTP4 protocol on it. Then, open the MTFTP4 protocol. + // + Status = NetLibCreateServiceChild ( + ControllerHandle, + gImageHandle, + &gEfiMtftp4ServiceBindingProtocolGuid, + &Mtftp4ChildHandle + ); + if (!EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Mtftp4ChildHandle, + &gEfiMtftp4ProtocolGuid, + (VOID **) &Mtftp4, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + } + if (EFI_ERROR (Status)) { + Print (L"Unable to open MTFTP4 protocol\n"); + goto Error; + } + + if (!IPv4DevicePathNode->StaticIpAddress) { + // + // Configure the DHCP4, all default settings. It is acceptable for the configuration to + // fail if the return code is equal to EFI_ACCESS_DENIED which means that the configuration + // has been done by another instance of the DHCP4 protocol or that the DHCP configuration + // process has been started but is not completed yet. + // + ZeroMem (&Dhcp4CfgData, sizeof (EFI_DHCP4_CONFIG_DATA)); + ParaList.Head.OpCode = DHCP_TAG_PARA_LIST; + ParaList.Head.Length = 2; + ParaList.Head.Data[0] = DHCP_TAG_NETMASK; + ParaList.Route = DHCP_TAG_ROUTER; + OptionList[0] = &ParaList.Head; + Dhcp4CfgData.OptionCount = 1; + Dhcp4CfgData.OptionList = OptionList; + + Status = Dhcp4->Configure (Dhcp4, &Dhcp4CfgData); + if (EFI_ERROR (Status)) { + if (Status != EFI_ACCESS_DENIED) { + Print (L"Error while configuring the DHCP4 protocol\n"); + goto Error; + } + } + + // + // Start the DHCP configuration. This may have already been done thus do not leave in error + // if the return code is EFI_ALREADY_STARTED. + // + Status = Dhcp4->Start (Dhcp4, NULL); + if (EFI_ERROR (Status)) { + if (Status != EFI_ALREADY_STARTED) { + Print (L"DHCP configuration failed\n"); + goto Error; + } + } else { + Dhcp4ToStop = TRUE; + } + + Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode); + if (EFI_ERROR (Status)) { + goto Error; + } + + if (Dhcp4Mode.State != Dhcp4Bound) { + Status = EFI_TIMEOUT; + Print (L"DHCP configuration failed\n"); + goto Error; + } + } + + // + // Configure the TFTP4 protocol + // + + ZeroMem (&Mtftp4CfgData, sizeof (EFI_MTFTP4_CONFIG_DATA)); + Mtftp4CfgData.UseDefaultSetting = FALSE; + Mtftp4CfgData.TimeoutValue = 4; + Mtftp4CfgData.TryCount = 6; + + if (IPv4DevicePathNode->StaticIpAddress) { + CopyMem (&Mtftp4CfgData.StationIp , &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Mtftp4CfgData.SubnetMask, &IPv4DevicePathNode->SubnetMask, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Mtftp4CfgData.GatewayIp , &IPv4DevicePathNode->GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS)); + } else { + CopyMem (&Mtftp4CfgData.StationIp , &Dhcp4Mode.ClientAddress, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Mtftp4CfgData.SubnetMask, &Dhcp4Mode.SubnetMask , sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Mtftp4CfgData.GatewayIp , &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS)); + } + + CopyMem (&Mtftp4CfgData.ServerIp , &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS)); + + Status = Mtftp4->Configure (Mtftp4, &Mtftp4CfgData); + if (EFI_ERROR (Status)) { + Print (L"Error while configuring the MTFTP4 protocol\n"); + goto Error; + } + + // The Device Path might contain multiple FilePath nodes + PathName = ConvertDevicePathToText ((EFI_DEVICE_PATH_PROTOCOL*)(IPv4DevicePathNode + 1), FALSE, FALSE); + PathNameLen = StrLen (PathName) + 1; + AsciiFilePath = AllocatePool (PathNameLen); + UnicodeStrToAsciiStrS (PathName, AsciiFilePath, PathNameLen); + + // + // Try to get the size of the file in bytes from the server. If it fails, + // start with a 8MB buffer to download the file. + // + FileSize = 0; + if (Mtftp4GetFileSize (Mtftp4, AsciiFilePath, &FileSize) == EFI_SUCCESS) { + TftpBufferSize = FileSize; + } else { + TftpBufferSize = SIZE_16MB; + } + + TftpContext = AllocatePool (sizeof (BDS_TFTP_CONTEXT)); + if (TftpContext == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + TftpContext->FileSize = FileSize; + + for (; TftpBufferSize <= MAX_TFTP_FILE_SIZE; + TftpBufferSize = (TftpBufferSize + SIZE_16MB) & (~(SIZE_16MB-1))) { + // + // Allocate a buffer to hold the whole file. + // + Status = gBS->AllocatePages ( + Type, + EfiBootServicesCode, + EFI_SIZE_TO_PAGES (TftpBufferSize), + Image + ); + if (EFI_ERROR (Status)) { + Print (L"Failed to allocate space for image\n"); + goto Error; + } + + TftpContext->DownloadedNbOfBytes = 0; + TftpContext->LastReportedNbOfBytes = 0; + + ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN)); + Mtftp4Token.Filename = (UINT8*)AsciiFilePath; + Mtftp4Token.BufferSize = TftpBufferSize; + Mtftp4Token.Buffer = (VOID *)(UINTN)*Image; + Mtftp4Token.CheckPacket = Mtftp4CheckPacket; + Mtftp4Token.Context = (VOID*)TftpContext; + + Print (L"Downloading the file <%a> from the TFTP server\n", AsciiFilePath); + Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token); + Print (L"\n"); + if (EFI_ERROR (Status)) { + gBS->FreePages (*Image, EFI_SIZE_TO_PAGES (TftpBufferSize)); + if (Status == EFI_BUFFER_TOO_SMALL) { + Print (L"Downloading failed, file larger than expected.\n"); + continue; + } else { + goto Error; + } + } + + *ImageSize = Mtftp4Token.BufferSize; + break; + } + +Error: + if (Dhcp4ChildHandle != NULL) { + if (Dhcp4 != NULL) { + if (Dhcp4ToStop) { + Dhcp4->Stop (Dhcp4); + } + gBS->CloseProtocol ( + Dhcp4ChildHandle, + &gEfiDhcp4ProtocolGuid, + gImageHandle, + ControllerHandle + ); + } + NetLibDestroyServiceChild ( + ControllerHandle, + gImageHandle, + &gEfiDhcp4ServiceBindingProtocolGuid, + Dhcp4ChildHandle + ); + } + + if (Mtftp4ChildHandle != NULL) { + if (Mtftp4 != NULL) { + if (AsciiFilePath != NULL) { + FreePool (AsciiFilePath); + } + if (TftpContext != NULL) { + FreePool (TftpContext); + } + gBS->CloseProtocol ( + Mtftp4ChildHandle, + &gEfiMtftp4ProtocolGuid, + gImageHandle, + ControllerHandle + ); + } + NetLibDestroyServiceChild ( + ControllerHandle, + gImageHandle, + &gEfiMtftp4ServiceBindingProtocolGuid, + Mtftp4ChildHandle + ); + } + + if (EFI_ERROR (Status)) { + *Image = 0; + Print (L"Failed to download the file - Error=%r\n", Status); + } + + return Status; +} + +BDS_FILE_LOADER FileLoaders[] = { + { BdsFileSystemSupport, BdsFileSystemLoadImage }, + { BdsFirmwareVolumeSupport, BdsFirmwareVolumeLoadImage }, + //{ BdsLoadFileSupport, BdsLoadFileLoadImage }, + { BdsMemoryMapSupport, BdsMemoryMapLoadImage }, + { BdsPxeSupport, BdsPxeLoadImage }, + { BdsTftpSupport, BdsTftpLoadImage }, + { NULL, NULL } +}; + +EFI_STATUS +BdsLoadImageAndUpdateDevicePath ( + IN OUT EFI_DEVICE_PATH **DevicePath, + IN EFI_ALLOCATE_TYPE Type, + IN OUT EFI_PHYSICAL_ADDRESS* Image, + OUT UINTN *FileSize + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_DEVICE_PATH *RemainingDevicePath; + BDS_FILE_LOADER* FileLoader; + + Status = BdsConnectAndUpdateDevicePath (DevicePath, &Handle, &RemainingDevicePath); + if (EFI_ERROR (Status)) { + return Status; + } + + FileLoader = FileLoaders; + while (FileLoader->Support != NULL) { + if (FileLoader->Support (*DevicePath, Handle, RemainingDevicePath)) { + return FileLoader->LoadImage (DevicePath, Handle, RemainingDevicePath, Type, Image, FileSize); + } + FileLoader++; + } + + return EFI_UNSUPPORTED; +} + +EFI_STATUS +BdsLoadImage ( + IN EFI_DEVICE_PATH *DevicePath, + IN EFI_ALLOCATE_TYPE Type, + IN OUT EFI_PHYSICAL_ADDRESS* Image, + OUT UINTN *FileSize + ) +{ + return BdsLoadImageAndUpdateDevicePath (&DevicePath, Type, Image, FileSize); +} + +/** + Start an EFI Application from a Device Path + + @param ParentImageHandle Handle of the calling image + @param DevicePath Location of the EFI Application + + @retval EFI_SUCCESS All drivers have been connected + @retval EFI_NOT_FOUND The Linux kernel Device Path has not been found + @retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results. + +**/ +EFI_STATUS +BdsStartEfiApplication ( + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN UINTN LoadOptionsSize, + IN VOID* LoadOptions + ) +{ + EFI_STATUS Status; + EFI_HANDLE ImageHandle; + EFI_PHYSICAL_ADDRESS BinaryBuffer; + UINTN BinarySize; + EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; + + // Find the nearest supported file loader + Status = BdsLoadImageAndUpdateDevicePath (&DevicePath, AllocateAnyPages, &BinaryBuffer, &BinarySize); + if (EFI_ERROR (Status)) { + return Status; + } + + // Load the image from the Buffer with Boot Services function + Status = gBS->LoadImage (TRUE, ParentImageHandle, DevicePath, (VOID*)(UINTN)BinaryBuffer, BinarySize, &ImageHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // Passed LoadOptions to the EFI Application + if (LoadOptionsSize != 0) { + Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage); + if (EFI_ERROR (Status)) { + return Status; + } + + LoadedImage->LoadOptionsSize = LoadOptionsSize; + LoadedImage->LoadOptions = LoadOptions; + } + + // Before calling the image, enable the Watchdog Timer for the 5 Minute period + gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL); + // Start the image + Status = gBS->StartImage (ImageHandle, NULL, NULL); + // Clear the Watchdog Timer after the image returns + gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL); + + return Status; +} diff --git a/Platform/ARM/Library/BdsLib/BdsHelper.c b/Platform/ARM/Library/BdsLib/BdsHelper.c new file mode 100644 index 000000000000..b10fe2074d53 --- /dev/null +++ b/Platform/ARM/Library/BdsLib/BdsHelper.c @@ -0,0 +1,183 @@ +/** @file +* +* Copyright (c) 2011-2015, 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 "BdsInternal.h" + +EFI_STATUS +ShutdownUefiBootServices ( + VOID + ) +{ + EFI_STATUS Status; + UINTN MemoryMapSize; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + UINTN MapKey; + UINTN DescriptorSize; + UINT32 DescriptorVersion; + UINTN Pages; + + MemoryMap = NULL; + MemoryMapSize = 0; + Pages = 0; + + do { + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + + Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1; + MemoryMap = AllocatePages (Pages); + + // + // Get System MemoryMap + // + Status = gBS->GetMemoryMap ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + } + + // Don't do anything between the GetMemoryMap() and ExitBootServices() + if (!EFI_ERROR(Status)) { + Status = gBS->ExitBootServices (gImageHandle, MapKey); + if (EFI_ERROR(Status)) { + FreePages (MemoryMap, Pages); + MemoryMap = NULL; + MemoryMapSize = 0; + } + } + } while (EFI_ERROR(Status)); + + return Status; +} + +/** + Connect all DXE drivers + + @retval EFI_SUCCESS All drivers have been connected + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_OUT_OF_RESOURCES There is not resource pool memory to store the matching results. + +**/ +EFI_STATUS +BdsConnectAllDrivers ( + VOID + ) +{ + UINTN HandleCount, Index; + EFI_HANDLE *HandleBuffer; + EFI_STATUS Status; + + do { + // Locate all the driver handles + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + break; + } + + // Connect every handles + for (Index = 0; Index < HandleCount; Index++) { + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + // Check if new handles have been created after the start of the previous handles + Status = gDS->Dispatch (); + } while (!EFI_ERROR(Status)); + + return EFI_SUCCESS; +} + +EFI_STATUS +GetGlobalEnvironmentVariable ( + IN CONST CHAR16* VariableName, + IN VOID* DefaultValue, + IN OUT UINTN* Size, + OUT VOID** Value + ) +{ + return GetEnvironmentVariable (VariableName, &gEfiGlobalVariableGuid, + DefaultValue, Size, Value); +} + +EFI_STATUS +GetEnvironmentVariable ( + IN CONST CHAR16* VariableName, + IN EFI_GUID* VendorGuid, + IN VOID* DefaultValue, + IN OUT UINTN* Size, + OUT VOID** Value + ) +{ + EFI_STATUS Status; + UINTN VariableSize; + + // Try to get the variable size. + *Value = NULL; + VariableSize = 0; + Status = gRT->GetVariable ((CHAR16 *) VariableName, VendorGuid, NULL, &VariableSize, *Value); + if (Status == EFI_NOT_FOUND) { + if ((DefaultValue != NULL) && (Size != NULL) && (*Size != 0)) { + // If the environment variable does not exist yet then set it with the default value + Status = gRT->SetVariable ( + (CHAR16*)VariableName, + VendorGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + *Size, + DefaultValue + ); + *Value = AllocateCopyPool (*Size, DefaultValue); + } else { + return EFI_NOT_FOUND; + } + } else if (Status == EFI_BUFFER_TOO_SMALL) { + // Get the environment variable value + *Value = AllocatePool (VariableSize); + if (*Value == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = gRT->GetVariable ((CHAR16 *)VariableName, VendorGuid, NULL, &VariableSize, *Value); + if (EFI_ERROR (Status)) { + FreePool(*Value); + return EFI_INVALID_PARAMETER; + } + + if (Size) { + *Size = VariableSize; + } + } else { + *Value = AllocateCopyPool (*Size, DefaultValue); + return Status; + } + + return EFI_SUCCESS; +} diff --git a/Platform/ARM/Library/BdsLib/BdsInternal.h b/Platform/ARM/Library/BdsLib/BdsInternal.h new file mode 100644 index 000000000000..f70aae603d69 --- /dev/null +++ b/Platform/ARM/Library/BdsLib/BdsInternal.h @@ -0,0 +1,111 @@ +/** @file +* +* Copyright (c) 2011-2015, 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. +* +**/ + +#ifndef __BDS_INTERNAL_H__ +#define __BDS_INTERNAL_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/** + * Check if the file loader can support this device path. + * + * @param DevicePath EFI Device Path of the image to load. + * This device path generally comes from the boot entry (ie: Boot####). + * @param Handle Handle of the driver supporting the device path + * @param RemainingDevicePath Part of the EFI Device Path that has not been resolved during + * the Device Path discovery + */ +typedef BOOLEAN (*BDS_FILE_LOADER_SUPPORT) ( + IN EFI_DEVICE_PATH *DevicePath, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH *RemainingDevicePath + ); + +/** + * Function to load an image from a given Device Path for a + * specific support (FileSystem, TFTP, PXE, ...) + * + * @param DevicePath EFI Device Path of the image to load. + * This device path generally comes from the boot entry (ie: Boot####). + * This path is also defined as 'OUT' as there are some device paths that + * might not be completed such as EFI path for removable device. In these + * cases, it is expected the loader to add \EFI\BOOT\BOOT(ARM|AA64).EFI + * @param Handle Handle of the driver supporting the device path + * @param RemainingDevicePath Part of the EFI Device Path that has not been resolved during + * the Device Path discovery + * @param Type Define where the image should be loaded (see EFI_ALLOCATE_TYPE definition) + * @param Image Base Address of the image has been loaded + * @param ImageSize Size of the image that has been loaded + */ +typedef EFI_STATUS (*BDS_FILE_LOADER_LOAD_IMAGE) ( + IN OUT EFI_DEVICE_PATH **DevicePath, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH *RemainingDevicePath, + IN EFI_ALLOCATE_TYPE Type, + IN OUT EFI_PHYSICAL_ADDRESS* Image, + OUT UINTN *ImageSize + ); + +typedef struct { + BDS_FILE_LOADER_SUPPORT Support; + BDS_FILE_LOADER_LOAD_IMAGE LoadImage; +} BDS_FILE_LOADER; + +typedef struct _BDS_SYSTEM_MEMORY_RESOURCE { + LIST_ENTRY Link; // This attribute must be the first entry of this structure (to avoid pointer computation) + EFI_PHYSICAL_ADDRESS PhysicalStart; + UINT64 ResourceLength; +} BDS_SYSTEM_MEMORY_RESOURCE; + +typedef struct { + UINT64 FileSize; + UINT64 DownloadedNbOfBytes; + UINT64 LastReportedNbOfBytes; +} BDS_TFTP_CONTEXT; + +EFI_STATUS +BdsLoadImage ( + IN EFI_DEVICE_PATH *DevicePath, + IN EFI_ALLOCATE_TYPE Type, + IN OUT EFI_PHYSICAL_ADDRESS* Image, + OUT UINTN *FileSize + ); + +#endif diff --git a/Platform/ARM/Library/BdsLib/BdsLib.inf b/Platform/ARM/Library/BdsLib/BdsLib.inf new file mode 100644 index 000000000000..96c1d6e7e200 --- /dev/null +++ b/Platform/ARM/Library/BdsLib/BdsLib.inf @@ -0,0 +1,62 @@ +#/* @file +# +# Copyright (c) 2011-2014, 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. +# +#*/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BdsLib + FILE_GUID = ddbf73a0-bb25-11df-8e4e-0002a5d5c51b + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = BdsLib + +[Sources.common] + BdsFilePath.c + BdsAppLoader.c + BdsHelper.c + BdsLoadOption.c + +[Packages] + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + ArmLib + BaseLib + DebugLib + DevicePathLib + HobLib + PcdLib + NetLib + +[Guids] + gEfiFileInfoGuid + +[Protocols] + gEfiBdsArchProtocolGuid + gEfiDevicePathProtocolGuid + gEfiDevicePathFromTextProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEfiFirmwareVolume2ProtocolGuid + gEfiLoadFileProtocolGuid + gEfiPxeBaseCodeProtocolGuid + gEfiDiskIoProtocolGuid + gEfiUsbIoProtocolGuid + gEfiLoadedImageProtocolGuid + gEfiSimpleNetworkProtocolGuid + gEfiDhcp4ServiceBindingProtocolGuid + gEfiDhcp4ProtocolGuid + gEfiMtftp4ServiceBindingProtocolGuid + gEfiMtftp4ProtocolGuid diff --git a/Platform/ARM/Library/BdsLib/BdsLoadOption.c b/Platform/ARM/Library/BdsLib/BdsLoadOption.c new file mode 100644 index 000000000000..766a9890fc09 --- /dev/null +++ b/Platform/ARM/Library/BdsLib/BdsLoadOption.c @@ -0,0 +1,272 @@ +/** @file +* +* 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 "BdsInternal.h" + +EFI_STATUS +BootOptionParseLoadOption ( + IN EFI_LOAD_OPTION *EfiLoadOption, + IN UINTN EfiLoadOptionSize, + IN OUT BDS_LOAD_OPTION **BdsLoadOption + ) +{ + BDS_LOAD_OPTION *LoadOption; + UINTN DescriptionLength; + UINTN EfiLoadOptionPtr; + + if (EfiLoadOption == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (EfiLoadOptionSize < sizeof(UINT32) + sizeof(UINT16) + sizeof(CHAR16) + sizeof(EFI_DEVICE_PATH_PROTOCOL)) { + return EFI_BAD_BUFFER_SIZE; + } + + if (*BdsLoadOption == NULL) { + LoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION)); + if (LoadOption == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } else { + LoadOption = *BdsLoadOption; + } + + EfiLoadOptionPtr = (UINTN)EfiLoadOption; + LoadOption->LoadOption = EfiLoadOption; + LoadOption->LoadOptionSize = EfiLoadOptionSize; + + LoadOption->Attributes = *(UINT32*)EfiLoadOptionPtr; + LoadOption->FilePathListLength = *(UINT16*)(EfiLoadOptionPtr + sizeof(UINT32)); + LoadOption->Description = (CHAR16*)(EfiLoadOptionPtr + sizeof(UINT32) + sizeof(UINT16)); + DescriptionLength = StrSize (LoadOption->Description); + LoadOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)(EfiLoadOptionPtr + sizeof(UINT32) + sizeof(UINT16) + DescriptionLength); + + // If ((End of EfiLoadOptiony - Start of EfiLoadOption) == EfiLoadOptionSize) then No Optional Data + if ((UINTN)((UINTN)LoadOption->FilePathList + LoadOption->FilePathListLength - EfiLoadOptionPtr) == EfiLoadOptionSize) { + LoadOption->OptionalData = NULL; + LoadOption->OptionalDataSize = 0; + } else { + LoadOption->OptionalData = (VOID*)((UINTN)(LoadOption->FilePathList) + LoadOption->FilePathListLength); + LoadOption->OptionalDataSize = EfiLoadOptionSize - ((UINTN)LoadOption->OptionalData - EfiLoadOptionPtr); + } + + if (*BdsLoadOption == NULL) { + *BdsLoadOption = LoadOption; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +BootOptionFromLoadOptionVariable ( + IN CHAR16* BootVariableName, + OUT BDS_LOAD_OPTION** BdsLoadOption + ) +{ + EFI_STATUS Status; + EFI_LOAD_OPTION *EfiLoadOption; + UINTN EfiLoadOptionSize; + + Status = GetGlobalEnvironmentVariable (BootVariableName, NULL, &EfiLoadOptionSize, (VOID**)&EfiLoadOption); + if (!EFI_ERROR(Status)) { + *BdsLoadOption = NULL; + Status = BootOptionParseLoadOption (EfiLoadOption, EfiLoadOptionSize, BdsLoadOption); + } + + return Status; +} + +EFI_STATUS +BootOptionFromLoadOptionIndex ( + IN UINT16 LoadOptionIndex, + OUT BDS_LOAD_OPTION **BdsLoadOption + ) +{ + CHAR16 BootVariableName[9]; + EFI_STATUS Status; + + UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", LoadOptionIndex); + + Status = BootOptionFromLoadOptionVariable (BootVariableName, BdsLoadOption); + if (!EFI_ERROR(Status)) { + (*BdsLoadOption)->LoadOptionIndex = LoadOptionIndex; + } + + return Status; +} + +EFI_STATUS +BootOptionToLoadOptionVariable ( + IN BDS_LOAD_OPTION* BdsLoadOption + ) +{ + EFI_STATUS Status; + UINTN DescriptionSize; + //UINT16 FilePathListLength; + EFI_DEVICE_PATH_PROTOCOL* DevicePathNode; + UINTN NodeLength; + UINT8* EfiLoadOptionPtr; + VOID* OldLoadOption; + CHAR16 BootVariableName[9]; + UINTN BootOrderSize; + UINT16* BootOrder; + + // If we are overwriting an existent Boot Option then we have to free previously allocated memory + if (BdsLoadOption->LoadOptionSize > 0) { + OldLoadOption = BdsLoadOption->LoadOption; + } else { + OldLoadOption = NULL; + + // If this function is called at the creation of the Boot Device entry (not at the update) the + // BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry + BdsLoadOption->LoadOptionIndex = BootOptionAllocateBootIndex (); + + //TODO: Add to the the Boot Entry List + } + + DescriptionSize = StrSize(BdsLoadOption->Description); + + // Ensure the FilePathListLength information is correct + ASSERT (GetDevicePathSize (BdsLoadOption->FilePathList) == BdsLoadOption->FilePathListLength); + + // Allocate the memory for the EFI Load Option + BdsLoadOption->LoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + DescriptionSize + BdsLoadOption->FilePathListLength + BdsLoadOption->OptionalDataSize; + + BdsLoadOption->LoadOption = (EFI_LOAD_OPTION *)AllocateZeroPool (BdsLoadOption->LoadOptionSize); + if (BdsLoadOption->LoadOption == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + EfiLoadOptionPtr = (UINT8 *) BdsLoadOption->LoadOption; + + // + // Populate the EFI Load Option and BDS Boot Option structures + // + + // Attributes fields + *(UINT32*)EfiLoadOptionPtr = BdsLoadOption->Attributes; + EfiLoadOptionPtr += sizeof(UINT32); + + // FilePath List fields + *(UINT16*)EfiLoadOptionPtr = BdsLoadOption->FilePathListLength; + EfiLoadOptionPtr += sizeof(UINT16); + + // Boot description fields + CopyMem (EfiLoadOptionPtr, BdsLoadOption->Description, DescriptionSize); + EfiLoadOptionPtr += DescriptionSize; + + // File path fields + DevicePathNode = BdsLoadOption->FilePathList; + while (!IsDevicePathEndType (DevicePathNode)) { + NodeLength = DevicePathNodeLength(DevicePathNode); + CopyMem (EfiLoadOptionPtr, DevicePathNode, NodeLength); + EfiLoadOptionPtr += NodeLength; + DevicePathNode = NextDevicePathNode (DevicePathNode); + } + + // Set the End Device Path Type + SetDevicePathEndNode (EfiLoadOptionPtr); + EfiLoadOptionPtr += sizeof(EFI_DEVICE_PATH); + + // Fill the Optional Data + if (BdsLoadOption->OptionalDataSize > 0) { + CopyMem (EfiLoadOptionPtr, BdsLoadOption->OptionalData, BdsLoadOption->OptionalDataSize); + } + + // Case where the fields have been updated + if (OldLoadOption) { + // Now, the old data has been copied to the new allocated packed structure, we need to update the pointers of BdsLoadOption + BootOptionParseLoadOption (BdsLoadOption->LoadOption, BdsLoadOption->LoadOptionSize, &BdsLoadOption); + // Free the old packed structure + FreePool (OldLoadOption); + } + + // Create/Update Boot#### environment variable + UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex); + Status = gRT->SetVariable ( + BootVariableName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + BdsLoadOption->LoadOptionSize, + BdsLoadOption->LoadOption + ); + + // When it is a new entry we must add the entry to the BootOrder + if (OldLoadOption == NULL) { + // Add the new Boot Index to the list + Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder); + if (!EFI_ERROR(Status)) { + BootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof(UINT16), BootOrder); + // Add the new index at the end + BootOrder[BootOrderSize / sizeof(UINT16)] = BdsLoadOption->LoadOptionIndex; + BootOrderSize += sizeof(UINT16); + } else { + // BootOrder does not exist. Create it + BootOrderSize = sizeof(UINT16); + BootOrder = &(BdsLoadOption->LoadOptionIndex); + } + + // Update (or Create) the BootOrder environment variable + gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + BootOrderSize, + BootOrder + ); + DEBUG((EFI_D_ERROR,"Create %s\n",BootVariableName)); + + // Free memory allocated by GetGlobalEnvironmentVariable + if (!EFI_ERROR(Status)) { + FreePool (BootOrder); + } + } else { + DEBUG((EFI_D_ERROR,"Update %s\n",BootVariableName)); + } + + return EFI_SUCCESS; +} + +UINT16 +BootOptionAllocateBootIndex ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Index; + UINT32 BootIndex; + UINT16 *BootOrder; + UINTN BootOrderSize; + BOOLEAN Found; + + // Get the Boot Option Order from the environment variable + Status = GetGlobalEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder); + if (!EFI_ERROR(Status)) { + for (BootIndex = 0; BootIndex <= 0xFFFF; BootIndex++) { + Found = FALSE; + for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { + if (BootOrder[Index] == BootIndex) { + Found = TRUE; + break; + } + } + if (!Found) { + return BootIndex; + } + } + FreePool (BootOrder); + } + // Return the first index + return 0; +} From patchwork Mon Nov 20 11:37:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 119271 Delivered-To: patch@linaro.org Received: by 10.140.22.164 with SMTP id 33csp3733853qgn; Mon, 20 Nov 2017 03:37:32 -0800 (PST) X-Google-Smtp-Source: AGs4zMbo4MLkWdNLtVCliPbVWiL3x/IPqH0Ls2pupUO4d0DO2FxqHbNMdNqpi4z9BK+PBS6Qszh8 X-Received: by 10.99.166.18 with SMTP id t18mr13280198pge.252.1511177852452; Mon, 20 Nov 2017 03:37:32 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1511177852; cv=none; d=google.com; s=arc-20160816; b=RyNO/wa6LGO98hesEDFE67kWTsA7KaMjxRq6QCLdxaggMstbe9saxpEssRNF6X7B3Z Y6Q+7OufMRFtfaLayWJNvmRaqIPHvUZ4OkPTsMwbnv5Y4I9n4m2sXqvh7GpXcjNlvQPI heNAS4lQ0ZMe5NIz2e9JpqCVOwRKdlcUJRQV8T1ymlGE538mIL3HeMqWb1SS2KNmuP16 sWpoPpG9UEurZ+hpSujRMWahQqrY+ZWWEbU3u7eGe+YilzaM7ZRzhecmVqvPcceucPW8 Gp7o/oaOk/4+YkjXdaHQjSbTx2K2ydtOhFtX5ylmjduSV6z8YTCerWW9hFm6C14SMNQF N2Sg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:delivered-to:arc-authentication-results; bh=/r8bZhrct191xsKZfGkX1V2frxAofDwNo5YfWmT4EjY=; b=WxCVqpy3v6jiOL2J2dFQkiXrig33TXtMO5ApqLqRnZHjyYxPAzrIDQYGrS28A5eH0A 5tqJhcctQZ/n0wYC06/ZQHdVvKd5EFbfyRyyPVipeChcf0S553+xO4iu6ohkbIlFq9NI kIY0CREUbSltWPNbJ/AsZiiHcgNBliniTKRHMcde6W0u1j8H8EAreZ+y4ca6Zld8WFD/ +SyT0j985jhHDTispFKuq+EJ+m196X9K0LZS6rBNiLCmjH3E18+2GpUAk/27GifDB73Y dOwykHx/QUzwMIwan60oC3ApEkT9DmFxfaW2eW5ZX7MXg/eklUWMWtKze1NURxNrDxNS XaPA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=Fux628us; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from ml01.01.org (ml01.01.org. [198.145.21.10]) by mx.google.com with ESMTPS id 8si3377203pfh.285.2017.11.20.03.37.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Nov 2017 03:37:32 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) client-ip=198.145.21.10; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=Fux628us; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 6BB2320347134; Mon, 20 Nov 2017 03:33:15 -0800 (PST) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2a00:1450:400c:c09::229; helo=mail-wm0-x229.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-wm0-x229.google.com (mail-wm0-x229.google.com [IPv6:2a00:1450:400c:c09::229]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 9D36020347134 for ; Mon, 20 Nov 2017 03:33:13 -0800 (PST) Received: by mail-wm0-x229.google.com with SMTP id v186so17956780wma.2 for ; Mon, 20 Nov 2017 03:37:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=n4Fk1PGKDteCjO04GLJ8ByaaSegow5Zh66ChqlmjwX4=; b=Fux628us6iNG28vyLsJRC7hQzc6p2Vo7s0bVlTCd5TIpls3nSRDz5HXe2LDhvYakDo eFSbLJR575kGH8YR3EH4ceIPUZUWxV4hLuWPLkQbtrdEE4QcC/iRWavTUXhURehTwATi v8Z2Nvm52D8SZuZ7nQxaMDyetsTVyDk+kkmz0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=n4Fk1PGKDteCjO04GLJ8ByaaSegow5Zh66ChqlmjwX4=; b=B2T3YSF2HkXra+O9gQEk3jWbL7JDQL0bqabzHa3HhyuyfzenkegRn/i0CjVgxVgUCT fr+wnezF2xEnPzzjKclbYJ1MTpReLEuqk2cW5LUgWH8LRCz4PNTTvpqvMgaci60Jy4r4 NFHxKp+p63okj9rxgUumWueviGDkyNLJrtYmjxTbjqfIY7CPk695U+TboEpS9bCCZM+n cLeH25xYR/13o5VEdNrJM4BdAPzfBfGTupVoguXpO8Xb+1PDRT4+caTM4uKn21cVHXXZ sk7FhmHzRo9QbAgBEMG5rzesyoZi8w8q5RpUL3uCSAMGKcl6ottEv6XqNeR8Z1M2Y/7x aW/A== X-Gm-Message-State: AJaThX5GOCclq6ADCg4VjrAzxtgj3NUr/hTG1yiO1KF0t8YEe+yC4BnB ZYxvi+1T5HxLHU4SvBqDz+HPrtGSIfQ= X-Received: by 10.28.96.195 with SMTP id u186mr6885986wmb.121.1511177844357; Mon, 20 Nov 2017 03:37:24 -0800 (PST) Received: from localhost.localdomain ([154.145.25.106]) by smtp.gmail.com with ESMTPSA id d4sm14760181wmh.35.2017.11.20.03.37.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Nov 2017 03:37:23 -0800 (PST) From: Ard Biesheuvel To: edk2-devel@lists.01.org Date: Mon, 20 Nov 2017 11:37:12 +0000 Message-Id: <20171120113714.21856-3-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171120113714.21856-1-ard.biesheuvel@linaro.org> References: <20171120113714.21856-1-ard.biesheuvel@linaro.org> Subject: [edk2] [PATCH edk2-platforms 2/4] Platform/ARM: import FdtPlatformDxe driver from EDK2 X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: leif.lindholm@linaro.org, Ard Biesheuvel MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" Import FdtPlatformDxe from EmbeddedPkg into Platform/ARM, given that it is not used anywhere else, nor should it be. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ard Biesheuvel --- Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatform.c | 461 +++++++++++++++++++ Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatform.h | 174 ++++++++ Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.dec | 31 ++ Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf | 65 +++ Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.uni | 109 +++++ Platform/ARM/Drivers/FdtPlatformDxe/README.txt | 72 +++ Platform/ARM/Drivers/FdtPlatformDxe/ShellDumpFdt.c | 279 ++++++++++++ Platform/ARM/Drivers/FdtPlatformDxe/ShellSetFdt.c | 468 ++++++++++++++++++++ 8 files changed, 1659 insertions(+) -- 2.11.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel diff --git a/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatform.c b/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatform.c new file mode 100644 index 000000000000..b4be2a078991 --- /dev/null +++ b/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatform.c @@ -0,0 +1,461 @@ +/** @file + + Copyright (c) 2015, ARM 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 "FdtPlatform.h" + +#include +#include +#include + +#include + +// +// Internal variables +// + +STATIC CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mShellDynCmdProtocolSetFdt = { + L"setfdt", // Name of the command + ShellDynCmdSetFdtHandler, // Handler + ShellDynCmdSetFdtGetHelp // GetHelp +}; + +STATIC CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mShellDynCmdProtocolDumpFdt = { + L"dumpfdt", // Name of the command + ShellDynCmdDumpFdtHandler, // Handler + ShellDynCmdDumpFdtGetHelp // GetHelp +}; + +STATIC CONST EFI_GUID mFdtPlatformDxeHiiGuid = { + 0x8afa7610, 0x62b1, 0x46aa, + {0xb5, 0x34, 0xc3, 0xde, 0xff, 0x39, 0x77, 0x8c} + }; + +EFI_HANDLE mFdtPlatformDxeHiiHandle; + +/** + Install the FDT specified by its device path in text form. + + @param[in] TextDevicePath Device path of the FDT to install in text form + + @retval EFI_SUCCESS The FDT was installed. + @retval EFI_NOT_FOUND Failed to locate a protocol or a file. + @retval EFI_INVALID_PARAMETER Invalid device path. + @retval EFI_UNSUPPORTED Device path not supported. + @retval EFI_OUT_OF_RESOURCES An allocation failed. +**/ +STATIC +EFI_STATUS +InstallFdt ( + IN CONST CHAR16* TextDevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; + EFI_DEVICE_PATH *DevicePath; + EFI_PHYSICAL_ADDRESS FdtBlobBase; + UINTN FdtBlobSize; + UINTN NumPages; + EFI_PHYSICAL_ADDRESS FdtConfigurationTableBase; + + Status = gBS->LocateProtocol ( + &gEfiDevicePathFromTextProtocolGuid, + NULL, + (VOID **)&EfiDevicePathFromTextProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "InstallFdt() - Failed to locate EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL protocol\n")); + return Status; + } + + DevicePath = (EFI_DEVICE_PATH*)EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (TextDevicePath); + if (DevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Load the FDT given its device path. + // This operation may fail if the device path is not supported. + // + FdtBlobBase = 0; + NumPages = 0; + Status = BdsLoadImage (DevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize); + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // Ensure that the FDT header is valid and that the Size of the Device Tree + // is smaller than the size of the read file + // + if (fdt_check_header ((VOID*)(UINTN)FdtBlobBase) != 0 || + (UINTN)fdt_totalsize ((VOID*)(UINTN)FdtBlobBase) > FdtBlobSize) { + DEBUG ((EFI_D_ERROR, "InstallFdt() - loaded FDT binary image seems corrupt\n")); + Status = EFI_LOAD_ERROR; + goto Error; + } + + // + // Store the FDT as Runtime Service Data to prevent the Kernel from + // overwritting its data. + // + NumPages = EFI_SIZE_TO_PAGES (FdtBlobSize); + Status = gBS->AllocatePages ( + AllocateAnyPages, EfiRuntimeServicesData, + NumPages, &FdtConfigurationTableBase + ); + if (EFI_ERROR (Status)) { + goto Error; + } + CopyMem ( + (VOID*)(UINTN)FdtConfigurationTableBase, + (VOID*)(UINTN)FdtBlobBase, + FdtBlobSize + ); + + // + // Install the FDT into the Configuration Table + // + Status = gBS->InstallConfigurationTable ( + &gFdtTableGuid, + (VOID*)(UINTN)FdtConfigurationTableBase + ); + if (EFI_ERROR (Status)) { + gBS->FreePages (FdtConfigurationTableBase, NumPages); + } + +Error: + if (FdtBlobBase != 0) { + gBS->FreePages (FdtBlobBase, NumPages); + } + FreePool (DevicePath); + + return Status; +} + +/** + Main entry point of the FDT platform driver. + + @param[in] ImageHandle The firmware allocated handle for the present driver + UEFI image. + @param[in] *SystemTable A pointer to the EFI System table. + + @retval EFI_SUCCESS The driver was initialized. + @retval EFI_OUT_OF_RESOURCES The "End of DXE" event could not be allocated or + there was not enough memory in pool to install + the Shell Dynamic Command protocol. + @retval EFI_LOAD_ERROR Unable to add the HII package. + +**/ +EFI_STATUS +FdtPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + // + // Install the Device Tree from its expected location + // + Status = RunFdtInstallation (NULL); + + if (FeaturePcdGet (PcdOverridePlatformFdt) || FeaturePcdGet (PcdDumpFdtShellCommand)) { + // + // Register the strings for the user interface in the HII Database. + // This shows the way to the multi-language support, even if + // only the English language is actually supported. The strings to register + // are stored in the "ShellSetFdtStrings[]" array. This array is + // built by the building process from the "*.uni" file associated to + // the present driver (cf. FdtPlatfromDxe.inf). Examine your Build + // folder under your package's DEBUG folder and you will find the array + // defined in a xxxStrDefs.h file. + // + mFdtPlatformDxeHiiHandle = HiiAddPackages ( + &mFdtPlatformDxeHiiGuid, + ImageHandle, + FdtPlatformDxeStrings, + NULL + ); + } + + // + // If the development features are enabled, install the dynamic shell + // command "setfdt" to be able to define a device path for the FDT + // that has precedence over the device paths defined by + // "PcdFdtDevicePaths". + // + + if (FeaturePcdGet (PcdOverridePlatformFdt)) { + if (mFdtPlatformDxeHiiHandle != NULL) { + // We install dynamic EFI command on separate handles as we cannot register + // more than one protocol of the same protocol interface on the same handle. + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiShellDynamicCommandProtocolGuid, + &mShellDynCmdProtocolSetFdt, + NULL + ); + if (EFI_ERROR (Status)) { + HiiRemovePackages (mFdtPlatformDxeHiiHandle); + } + } else { + Status = EFI_LOAD_ERROR; + } + if (EFI_ERROR (Status)) { + DEBUG (( + EFI_D_WARN, + "Unable to install \"setfdt\" EFI Shell command - %r \n", + Status + )); + } + } + + if (FeaturePcdGet (PcdDumpFdtShellCommand)) { + if (mFdtPlatformDxeHiiHandle != NULL) { + // We install dynamic EFI command on separate handles as we cannot register + // more than one protocol of the same protocol interface on the same handle. + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiShellDynamicCommandProtocolGuid, + &mShellDynCmdProtocolDumpFdt, + NULL + ); + if (EFI_ERROR (Status)) { + HiiRemovePackages (mFdtPlatformDxeHiiHandle); + } + } else { + Status = EFI_LOAD_ERROR; + } + if (EFI_ERROR (Status)) { + DEBUG (( + EFI_D_WARN, + "Unable to install \"dumpfdt\" EFI Shell command - %r \n", + Status + )); + } + } + + return Status; +} + +/** + Run the FDT installation process. + + Loop in priority order over the device paths from which the FDT has + been asked to be retrieved for. For each device path, try to install + the FDT. Stop as soon as an installation succeeds. + + @param[in] SuccessfullDevicePath If not NULL, address where to store the + pointer to the text device path from + which the FDT was successfully retrieved. + Not used if the FDT installation failed. + The returned address is the address of + an allocated buffer that has to be + freed by the caller. + + @retval EFI_SUCCESS The FDT was installed. + @retval EFI_NOT_FOUND Failed to locate a protocol or a file. + @retval EFI_INVALID_PARAMETER Invalid device path. + @retval EFI_UNSUPPORTED Device path not supported. + @retval EFI_OUT_OF_RESOURCES An allocation failed. + +**/ +EFI_STATUS +RunFdtInstallation ( + OUT CHAR16 **SuccessfullDevicePath + ) +{ + EFI_STATUS Status; + UINTN DataSize; + CHAR16 *TextDevicePath; + CHAR16 *TextDevicePathStart; + CHAR16 *TextDevicePathSeparator; + UINTN TextDevicePathLen; + + TextDevicePath = NULL; + // + // For development purpose, if enabled through the "PcdOverridePlatformFdt" + // feature PCD, try first to install the FDT specified by the device path in + // text form stored in the "Fdt" UEFI variable. + // + if (FeaturePcdGet (PcdOverridePlatformFdt)) { + DataSize = 0; + Status = gRT->GetVariable ( + L"Fdt", + &gFdtVariableGuid, + NULL, + &DataSize, + NULL + ); + + // + // Keep going only if the "Fdt" variable is defined. + // + + if (Status == EFI_BUFFER_TOO_SMALL) { + TextDevicePath = AllocatePool (DataSize); + if (TextDevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + + Status = gRT->GetVariable ( + L"Fdt", + &gFdtVariableGuid, + NULL, + &DataSize, + TextDevicePath + ); + if (EFI_ERROR (Status)) { + FreePool (TextDevicePath); + goto Error; + } + + Status = InstallFdt (TextDevicePath); + if (!EFI_ERROR (Status)) { + DEBUG (( + EFI_D_WARN, + "Installation of the FDT using the device path <%s> completed.\n", + TextDevicePath + )); + goto Done; + } + DEBUG (( + EFI_D_ERROR, + "Installation of the FDT specified by the \"Fdt\" UEFI variable failed - %r\n", + Status + )); + FreePool (TextDevicePath); + } + } + + // + // Loop over the device path list provided by "PcdFdtDevicePaths". The device + // paths are in text form and separated by a semi-colon. + // + + Status = EFI_NOT_FOUND; + for (TextDevicePathStart = (CHAR16*)PcdGetPtr (PcdFdtDevicePaths); + *TextDevicePathStart != L'\0' ; ) { + TextDevicePathSeparator = StrStr (TextDevicePathStart, L";"); + + // + // Last device path of the list + // + if (TextDevicePathSeparator == NULL) { + TextDevicePathLen = StrLen (TextDevicePathStart); + } else { + TextDevicePathLen = (UINTN)(TextDevicePathSeparator - TextDevicePathStart); + } + + TextDevicePath = AllocateCopyPool ( + (TextDevicePathLen + 1) * sizeof (CHAR16), + TextDevicePathStart + ); + if (TextDevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + TextDevicePath[TextDevicePathLen] = L'\0'; + + Status = InstallFdt (TextDevicePath); + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_WARN, "Installation of the FDT using the device path <%s> completed.\n", + TextDevicePath + )); + goto Done; + } + + DEBUG ((EFI_D_WARN, "Installation of the FDT using the device path <%s> failed - %r.\n", + TextDevicePath, Status + )); + FreePool (TextDevicePath); + + if (TextDevicePathSeparator == NULL) { + goto Error; + } + TextDevicePathStart = TextDevicePathSeparator + 1; + } + +Error: +Done: + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Failed to install the FDT - %r.\n", Status)); + return Status; + } + + if (SuccessfullDevicePath != NULL) { + *SuccessfullDevicePath = TextDevicePath; + } else { + FreePool (TextDevicePath); + } + + return EFI_SUCCESS; +} + +/** + Transcode one of the EFI return code used by the model into an EFI Shell return code. + + @param[in] Status EFI return code. + + @return Transcoded EFI Shell return code. + +**/ +SHELL_STATUS +EfiCodeToShellCode ( + IN EFI_STATUS Status + ) +{ + SHELL_STATUS ShellStatus; + + switch (Status) { + case EFI_SUCCESS : + ShellStatus = SHELL_SUCCESS; + break; + + case EFI_INVALID_PARAMETER : + ShellStatus = SHELL_INVALID_PARAMETER; + break; + + case EFI_UNSUPPORTED : + ShellStatus = SHELL_UNSUPPORTED; + break; + + case EFI_DEVICE_ERROR : + ShellStatus = SHELL_DEVICE_ERROR; + break; + + case EFI_WRITE_PROTECTED : + case EFI_SECURITY_VIOLATION : + ShellStatus = SHELL_ACCESS_DENIED; + break; + + case EFI_OUT_OF_RESOURCES : + ShellStatus = SHELL_OUT_OF_RESOURCES; + break; + + case EFI_NOT_FOUND : + ShellStatus = SHELL_NOT_FOUND; + break; + + default : + ShellStatus = SHELL_ABORTED; + } + + return ShellStatus; +} diff --git a/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatform.h b/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatform.h new file mode 100644 index 000000000000..a631f2847bf5 --- /dev/null +++ b/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatform.h @@ -0,0 +1,174 @@ +/** @file + + Copyright (c) 2015, ARM 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. + +**/ + +#ifndef __FDT_PLATFORM_DXE_H__ +#define __FDT_PLATFORM_DXE_H__ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +extern EFI_HANDLE mFdtPlatformDxeHiiHandle; + +/** + Transcode one of the EFI return code used by the model into an EFI Shell return code. + + @param[in] Status EFI return code. + + @return Transcoded EFI Shell return code. + +**/ +SHELL_STATUS +EfiCodeToShellCode ( + IN EFI_STATUS Status + ); + +/** + Run the FDT installation process. + + Loop in priority order over the device paths from which the FDT has + been asked to be retrieved for. For each device path, try to install + the FDT. Stop as soon as an installation succeeds. + + @param[in] SuccessfullDevicePath If not NULL, address where to store the + pointer to the text device path from + which the FDT was successfully retrieved. + Not used if the FDT installation failed. + The returned address is the address of + an allocated buffer that has to be + freed by the caller. + + @retval EFI_SUCCESS The FDT was installed. + @retval EFI_NOT_FOUND Failed to locate a protocol or a file. + @retval EFI_INVALID_PARAMETER Invalid device path. + @retval EFI_UNSUPPORTED Device path not supported. + @retval EFI_OUT_OF_RESOURCES An allocation failed. + +**/ +EFI_STATUS +RunFdtInstallation ( + OUT CHAR16 **SuccessfullDevicePath + ); + +/** + This is the shell command "setfdt" handler function. This function handles + the command when it is invoked in the shell. + + @param[in] This The instance of the + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] SystemTable The pointer to the UEFI system table. + @param[in] ShellParameters The parameters associated with the command. + @param[in] Shell The instance of the shell protocol used in the + context of processing this command. + + @return SHELL_SUCCESS The operation was successful. + @return SHELL_ABORTED Operation aborted due to internal error. + @return SHELL_INVALID_PARAMETER The parameters of the command are not valid. + @return SHELL_INVALID_PARAMETER The EFI Shell file path is not valid. + @return SHELL_NOT_FOUND Failed to locate a protocol or a file. + @return SHELL_UNSUPPORTED Device path not supported. + @return SHELL_OUT_OF_RESOURCES A memory allocation failed. + @return SHELL_DEVICE_ERROR The "Fdt" variable could not be saved due to a hardware failure. + @return SHELL_ACCESS_DENIED The "Fdt" variable is read-only. + @return SHELL_ACCESS_DENIED The "Fdt" variable cannot be deleted. + @return SHELL_ACCESS_DENIED The "Fdt" variable could not be written due to security violation. + +**/ +SHELL_STATUS +EFIAPI +ShellDynCmdSetFdtHandler ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN EFI_SHELL_PROTOCOL *Shell + ); + +/** + This is the shell command "setfdt" help handler function. This + function returns the formatted help for the "setfdt" command. + The format matchs that in Appendix B of the revision 2.1 of the + UEFI Shell Specification. + + @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] Language The pointer to the language string to use. + + @return CHAR16* Pool allocated help string, must be freed by caller. +**/ +CHAR16* +EFIAPI +ShellDynCmdSetFdtGetHelp ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN CONST CHAR8 *Language + ); + +/** + This is the shell command "dumpfdt" handler function. This function handles + the command when it is invoked in the shell. + + @param[in] This The instance of the + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] SystemTable The pointer to the UEFI system table. + @param[in] ShellParameters The parameters associated with the command. + @param[in] Shell The instance of the shell protocol used in the + context of processing this command. + + @return SHELL_SUCCESS The operation was successful. + @return SHELL_ABORTED Operation aborted due to internal error. + @return SHELL_NOT_FOUND Failed to locate the Device Tree into the EFI Configuration Table + @return SHELL_OUT_OF_RESOURCES A memory allocation failed. + +**/ +SHELL_STATUS +EFIAPI +ShellDynCmdDumpFdtHandler ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN EFI_SHELL_PROTOCOL *Shell + ); + +/** + This is the shell command "dumpfdt" help handler function. This + function returns the formatted help for the "dumpfdt" command. + The format matchs that in Appendix B of the revision 2.1 of the + UEFI Shell Specification. + + @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] Language The pointer to the language string to use. + + @return CHAR16* Pool allocated help string, must be freed by caller. +**/ +CHAR16* +EFIAPI +ShellDynCmdDumpFdtGetHelp ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN CONST CHAR8 *Language + ); + +#endif /* __FDT_PLATFORM_DXE_H__ */ diff --git a/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.dec b/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.dec new file mode 100644 index 000000000000..3faced589504 --- /dev/null +++ b/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.dec @@ -0,0 +1,31 @@ +#/** @file +# +# Copyright (c) 2011-2017, 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. +# +#**/ + +[Defines] + DEC_SPECIFICATION = 0x0001001A + PACKAGE_NAME = FdtPlatformDxe + PACKAGE_GUID = ed22c1e5-71cb-48d6-a9d8-c20f8d6b909f + PACKAGE_VERSION = 0.1 + +[Guids] + gFdtPlatformDxeTokenSpaceGuid = { 0xbfcaa0af, 0xedd4, 0x4ce7, { 0xbd, 0xb3, 0x39, 0x15, 0x07, 0x28, 0x65, 0x77 } } + +[PcdsFeatureFlag.common] + # Enable the development specific features + gFdtPlatformDxeTokenSpaceGuid.PcdOverridePlatformFdt|TRUE|BOOLEAN|0x00000001 + # Add 'dumpfdt' EFI Shell command + gFdtPlatformDxeTokenSpaceGuid.PcdDumpFdtShellCommand|TRUE|BOOLEAN|0x00000002 + +[PcdsFixedAtBuild.common, PcdsDynamic.common] + gFdtPlatformDxeTokenSpaceGuid.PcdFdtDevicePaths|L""|VOID*|0x00000055 diff --git a/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf b/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf new file mode 100644 index 000000000000..f9a5aee3596e --- /dev/null +++ b/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf @@ -0,0 +1,65 @@ +#/** @file +# +# Copyright (c) 2015, ARM 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. +# +#**/ + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = FdtPlatformDxe + MODULE_UNI_FILE = FdtPlatformDxe.uni + FILE_GUID = 4bd726b2-d1c8-4e98-ba08-2bc2ab251daf + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 0.1 + ENTRY_POINT = FdtPlatformEntryPoint + +[Sources.common] + FdtPlatform.c + FdtPlatformDxe.uni + ShellDumpFdt.c + ShellSetFdt.c + +[Packages] + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + BaseMemoryLib + BdsLib + DebugLib + DxeServicesTableLib + FdtLib + HiiLib + ShellLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeServicesTableLib + +[Protocols] + gEfiDevicePathFromTextProtocolGuid + gEfiDevicePathToTextProtocolGuid + gEfiShellDynamicCommandProtocolGuid + +[Guids] + gEfiEndOfDxeEventGroupGuid + gFdtTableGuid + gFdtVariableGuid + +[FeaturePcd] + gFdtPlatformDxeTokenSpaceGuid.PcdDumpFdtShellCommand + gFdtPlatformDxeTokenSpaceGuid.PcdOverridePlatformFdt + +[Pcd] + gFdtPlatformDxeTokenSpaceGuid.PcdFdtDevicePaths diff --git a/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.uni b/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.uni new file mode 100644 index 000000000000..f8bde834841d --- /dev/null +++ b/Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.uni @@ -0,0 +1,109 @@ +// *++ +// +// Copyright (c) 2014, ARM 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. +// +// +// Module Name: +// +// FdtPlatformDxe +// +// Abstract: +// +// String definitions for the EFI Shell 'setfdt' command +// +// Revision History: +// +// --*/ + +/=# + +#langdef en-US "English" + +#string STR_SETFDT_INSTALLING #language en-US "Installing the FDT ...\r\n" +#string STR_SETFDT_INSTALL_SUCCEEDED #language en-US "Installation of\r\n'%s'\r\ncompleted.\r\n" + +#string STR_SETFDT_UPDATING #language en-US "Updating the FDT device path ...\r\n" +#string STR_SETFDT_UPDATE_SUCCEEDED #language en-US "Update of the FDT device path '%s' completed.\r\n" +#string STR_SETFDT_UPDATE_DELETED #language en-US "The UEFI variable "Fdt" was deleted.\r\n" + +#string STR_SETFDT_INVALID_DEVICE_PATH #language en-US "Invalid device path.\r\n" +#string STR_SETFDT_INVALID_PATH #language en-US "The EFI Shell or device file path '%s' is invalid.\r\n" +#string STR_SETFDT_ERROR #language en-US "Error - %r.\r\n" +#string STR_SETFDT_DEVICE_PATH_LIST #language en-US "FDT device paths :\r\n" +#string STR_SETFDT_DEVICE_PATH #language en-US "'%s'\r\n" + +#string STR_GET_HELP_SETFDT #language en-US "" +".TH setfdt 0 "Define and/or install a new Flat Device Tree (FDT) for the platform."\r\n" +".SH NAME\r\n" +"Define and/or re-install a Flat Device Tree (FDT)\r\n" +".SH SYNOPSIS\r\n" +"setfdt [-i] [fdt_path]\r\n" +".SH OPTIONS\r\n" +"-i run the FDT installation process\r\n" +"file_path EFI Shell file path or device path to a FDT\r\n" +"\r\n" +".SH DESCRIPTION\r\n" +"NOTES:\r\n" +"1. If a valid EFI Shell file path is passed to the command, then the\r\n" +" command translates the EFI Shell file path into a device path in the\r\n" +" text form and saves it in the non volatile UEFI variable "Fdt". If\r\n" +" the path to the FDT is a device path in the text form, it is saved as\r\n" +" it is in the non volatile UEFI variable "Fdt". The next time the FDT\r\n" +" installation process is run, it will first try to install the FDT from\r\n" +" the device path specified by the UEFI variable "Fdt".\r\n" +" \r\n +"2. If the option -i is passed to the command, then the FDT installation\r\n" +" process is run. If a path to the FDT is passed to the command as well,\r\n" +" the update of the "Fdt" UEFI variable is done first before to launch\r\n" +" the FDT installation process.\r\n" +" \r\n +".SH RETURNVALUES\r\n" +"SHELL_SUCCESS Operation(s) completed.\r\n" +"SHELL_ABORTED Operation aborted.\r\n" +"SHELL_INVALID_PARAMETER Invalid argument(s).\r\n" +"SHELL_NOT_FOUND Failed to locate a protocol or a file.\r\n" +"SHELL_UNSUPPORTED Device path not supported.\r\n" +"SHELL_OUT_OF_RESOURCES A memory allocation failed.\r\n" +"SHELL_DEVICE ERROR Hardware failure.\r\n" +"SHELL_ACCESS_DENIED Access to the Fdt UEFI variable for modification denied.\r\n" +".SH EXAMPLES\r\n" +"EXAMPLES:\r\n" +"1. Relaunch the FDT installation process :\r\n" +" Shell> setfdt -i\r\n" +" \r\n" +"2. Set the EFI Shell file path 'fs0:\>fdt.dtb' to be the default path\r\n" +" to the FDT :\r\n" +" Shell> setfdt fs0:fdt.dtb\r\n" +" \r\n" +"3. Set a TFTP device path to be the default path to the FDT :\r\n" +" Shell> setfdt MAC(0002f700570b,0x1)/IPv4(192.168.1.1)/fdt.dtb\r\n" +" where . 00:02:f7:00:57:0b is the MAC address of the network\r\n" +" interface card to be used. The 'ifconfig -l' EFI Shell\r\n" +" command allows to get the MAC address of the network\r\n" +" interface cards.\r\n" +" . 192.168.1.1 is the address of the TFTP server.\r\n" +" . fdt.dtb is the file path to the FDT file on the server.\r\n" +"4. Display the FDT device paths from the highest to the lowest\r\n" +" priority :\r\n" +" Shell> setfdt\r\n" +"5. Delete the "Fdt" UEFI variable :\r\n" +" Shell> setfdt ""\r\n" +"\r\n" + +#string STR_GET_HELP_DUMPFDT #language en-US "" +".TH dumpfdt 0 "Dump installed Flat Device Tree (FDT) of the platform."\r\n" +".SH NAME\r\n" +"Dump current Flat Device Tree (FDT)\r\n" +".SH SYNOPSIS\r\n" +"dumpfdt\r\n" +"\r\n" +".SH DESCRIPTION\r\n" +"\r\n" diff --git a/Platform/ARM/Drivers/FdtPlatformDxe/README.txt b/Platform/ARM/Drivers/FdtPlatformDxe/README.txt new file mode 100644 index 000000000000..5f052d9a63aa --- /dev/null +++ b/Platform/ARM/Drivers/FdtPlatformDxe/README.txt @@ -0,0 +1,72 @@ +/** @file + + Copyright (c) 2015, ARM 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. + +**/ + +The purpose of the FdtPlatformDxe UEFI driver is to install the Flat Device +Tree (FDT) of the platform the UEFI frimware is running on into the UEFI +Configuration Table. The FDT is identified within the UEFI Configuration +Table by the "gFdtTableGuid" GUID defined in "EmbeddedPkg.dec". + +Once installed, an UEFI application or OS boot loader can get from the UEFI +Configuration Table the FDT of the platform from the "gFdtTableGuid" GUID. + +The installation is done after each boot at the end of the DXE phase, +just before the BDS phase. It is done at the end of the DXE phase to be sure +that all drivers have been dispatched. That way, all UEFI protocols that may +be needed to retrieve the FDT can be made available. It is done before the BDS +phase to be able to provide the FDT during that phase. + +The present driver tries to retrieve the FDT from the device paths defined in the +"gFdtPlatformDxeTokenSpaceGuid.PcdFdtDevicePaths" PCD. The "PcdFdtDevicePaths" +PCD contains a list a device paths. The device paths are in the text form and +separated by semi-colons. The present driver tries the device paths in the order +it finds them in the "PcdFdtDevicePaths" PCD as long as he did not install +succesfully a FDT. + +The "PcdFdtDevicePaths" PCD is a dynamic PCD that can be modified during the +DXE phase. This allows for exemple to select the right FDT when a binary is +intended to run on several platforms and/or variants of a platform. + +If the driver manages to download a FDT from one of the device paths mentioned +above then it installs it in the UEFI Configuration table and the run over the +device paths is stopped. + +For development purposes only, if the feature PCD "gFdtPlatformDxeTokenSpaceGuid. +PcdOverridePlatformFdt" is equal to TRUE, then before to try to install the +FDT from the device paths listed in the "PcdFdtDevicePaths" PCD, the present +driver tries to install it using the device path defined by the UEFI variable +"Fdt". If the variable does not exist or the installation using the device path +defined by the UEFI variable fails then the installation proceeds as described +above. + +Furthermore and again for development purposes only, if the feature PCD +"PcdOverridePlatformFdt" is equal to TRUE, the current driver provides the EFI +Shell command "setfdt" to define the location of the FDT by the mean of an EFI +Shell file path (like "fs2:\boot\fdt.dtb") or a device path. + +If the path passed in to the command is a valid EFI Shell file path, the +command translates it into the corresponding device path and stores that +device path in the "Fdt" UEFI variable asking for the variable to be non +volatile. + +If the path passed in to the command is not recognised as a valid EFI +Shell device path, the command handles it as device path and stored +in the "Fdt" UEFI variable as it is. + +Finally, the "-i" option of the "setfdt" command allows to trigger the FDT +installation process. The installation process is completed when the command +returns. The command can be invoked with the "-i" option only and in that +case the "Fdt" UEFI variable is not updated and the command just runs the +FDT installation process. If the command is invoked with the "-i" option and +an EFI Shell file path then first the "Fdt" UEFI variable is updated accordingly +and then the FDT installation process is run. diff --git a/Platform/ARM/Drivers/FdtPlatformDxe/ShellDumpFdt.c b/Platform/ARM/Drivers/FdtPlatformDxe/ShellDumpFdt.c new file mode 100644 index 000000000000..c7dc8985685b --- /dev/null +++ b/Platform/ARM/Drivers/FdtPlatformDxe/ShellDumpFdt.c @@ -0,0 +1,279 @@ +/** @file + + Copyright (c) 2015, ARM 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 "FdtPlatform.h" + +#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) +#define PALIGN(p, a) ((void *)(ALIGN ((unsigned long)(p), (a)))) +#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) + +STATIC +UINTN +IsPrintableString ( + IN CONST VOID* data, + IN UINTN len + ) +{ + CONST CHAR8 *s = data; + CONST CHAR8 *ss; + + // Zero length is not + if (len == 0) { + return 0; + } + + // Must terminate with zero + if (s[len - 1] != '\0') { + return 0; + } + + ss = s; + while (*s/* && isprint (*s)*/) { + s++; + } + + // Not zero, or not done yet + if (*s != '\0' || (s + 1 - ss) < len) { + return 0; + } + + return 1; +} + +STATIC +VOID +PrintData ( + IN CONST CHAR8* data, + IN UINTN len + ) +{ + UINTN i; + CONST CHAR8 *p = data; + + // No data, don't print + if (len == 0) + return; + + if (IsPrintableString (data, len)) { + Print (L" = \"%a\"", (const char *)data); + } else if ((len % 4) == 0) { + Print (L" = <"); + for (i = 0; i < len; i += 4) { + Print (L"0x%08x%a", fdt32_to_cpu (GET_CELL (p)), i < (len - 4) ? " " : ""); + } + Print (L">"); + } else { + Print (L" = ["); + for (i = 0; i < len; i++) + Print (L"%02x%a", *p++, i < len - 1 ? " " : ""); + Print (L"]"); + } +} + +STATIC +VOID +DumpFdt ( + IN VOID* FdtBlob + ) +{ + struct fdt_header *bph; + UINT32 off_dt; + UINT32 off_str; + CONST CHAR8* p_struct; + CONST CHAR8* p_strings; + CONST CHAR8* p; + CONST CHAR8* s; + CONST CHAR8* t; + UINT32 tag; + UINTN sz; + UINTN depth; + UINTN shift; + UINT32 version; + + { + // Can 'memreserve' be printed by below code? + INTN num = fdt_num_mem_rsv (FdtBlob); + INTN i, err; + UINT64 addr = 0, size = 0; + + for (i = 0; i < num; i++) { + err = fdt_get_mem_rsv (FdtBlob, i, &addr, &size); + if (err) { + DEBUG ((EFI_D_ERROR, "Error (%d) : Cannot get memreserve section (%d)\n", err, i)); + } + else { + Print (L"/memreserve/ \t0x%lx \t0x%lx;\n", addr, size); + } + } + } + + depth = 0; + shift = 4; + + bph = FdtBlob; + off_dt = fdt32_to_cpu (bph->off_dt_struct); + off_str = fdt32_to_cpu (bph->off_dt_strings); + p_struct = (CONST CHAR8*)FdtBlob + off_dt; + p_strings = (CONST CHAR8*)FdtBlob + off_str; + version = fdt32_to_cpu (bph->version); + + p = p_struct; + while ((tag = fdt32_to_cpu (GET_CELL (p))) != FDT_END) { + if (tag == FDT_BEGIN_NODE) { + s = p; + p = PALIGN (p + AsciiStrLen (s) + 1, 4); + + if (*s == '\0') + s = "/"; + + Print (L"%*s%a {\n", depth * shift, L" ", s); + + depth++; + continue; + } + + if (tag == FDT_END_NODE) { + depth--; + + Print (L"%*s};\n", depth * shift, L" "); + continue; + } + + if (tag == FDT_NOP) { + Print (L"%*s// [NOP]\n", depth * shift, L" "); + continue; + } + + if (tag != FDT_PROP) { + Print (L"%*s ** Unknown tag 0x%08x\n", depth * shift, L" ", tag); + break; + } + sz = fdt32_to_cpu (GET_CELL (p)); + s = p_strings + fdt32_to_cpu (GET_CELL (p)); + if (version < 16 && sz >= 8) + p = PALIGN (p, 8); + t = p; + + p = PALIGN (p + sz, 4); + + Print (L"%*s%a", depth * shift, L" ", s); + PrintData (t, sz); + Print (L";\n"); + } +} + +/** + This is the shell command "dumpfdt" handler function. This function handles + the command when it is invoked in the shell. + + @param[in] This The instance of the + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] SystemTable The pointer to the UEFI system table. + @param[in] ShellParameters The parameters associated with the command. + @param[in] Shell The instance of the shell protocol used in the + context of processing this command. + + @return SHELL_SUCCESS The operation was successful. + @return SHELL_ABORTED Operation aborted due to internal error. + @return SHELL_NOT_FOUND Failed to locate the Device Tree into the EFI Configuration Table + @return SHELL_OUT_OF_RESOURCES A memory allocation failed. + +**/ +SHELL_STATUS +EFIAPI +ShellDynCmdDumpFdtHandler ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN EFI_SHELL_PROTOCOL *Shell + ) +{ + SHELL_STATUS ShellStatus; + EFI_STATUS Status; + VOID *FdtBlob; + + ShellStatus = SHELL_SUCCESS; + + // + // Install the Shell and Shell Parameters Protocols on the driver + // image. This is necessary for the initialisation of the Shell + // Library to succeed in the next step. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &gImageHandle, + &gEfiShellProtocolGuid, Shell, + &gEfiShellParametersProtocolGuid, ShellParameters, + NULL + ); + if (EFI_ERROR (Status)) { + return SHELL_ABORTED; + } + + // + // Initialise the Shell Library as we are going to use it. + // Assert that the return code is EFI_SUCCESS as it should. + // To anticipate any change is the codes returned by + // ShellInitialize(), leave in case of error. + // + Status = ShellInitialize (); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return SHELL_ABORTED; + } + + Status = EfiGetSystemConfigurationTable (&gFdtTableGuid, &FdtBlob); + if (EFI_ERROR (Status)) { + Print (L"ERROR: Did not find the Fdt Blob.\n"); + return EfiCodeToShellCode (Status); + } + + DumpFdt (FdtBlob); + + gBS->UninstallMultipleProtocolInterfaces ( + gImageHandle, + &gEfiShellProtocolGuid, Shell, + &gEfiShellParametersProtocolGuid, ShellParameters, + NULL + ); + + return ShellStatus; +} + +/** + This is the shell command "dumpfdt" help handler function. This + function returns the formatted help for the "dumpfdt" command. + The format matchs that in Appendix B of the revision 2.1 of the + UEFI Shell Specification. + + @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] Language The pointer to the language string to use. + + @return CHAR16* Pool allocated help string, must be freed by caller. +**/ +CHAR16* +EFIAPI +ShellDynCmdDumpFdtGetHelp ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN CONST CHAR8 *Language + ) +{ + // + // This allocates memory. The caller has to free the allocated memory. + // + return HiiGetString ( + mFdtPlatformDxeHiiHandle, + STRING_TOKEN (STR_GET_HELP_DUMPFDT), + Language + ); +} diff --git a/Platform/ARM/Drivers/FdtPlatformDxe/ShellSetFdt.c b/Platform/ARM/Drivers/FdtPlatformDxe/ShellSetFdt.c new file mode 100644 index 000000000000..9be23c845593 --- /dev/null +++ b/Platform/ARM/Drivers/FdtPlatformDxe/ShellSetFdt.c @@ -0,0 +1,468 @@ +/** @file + + Copyright (c) 2015, ARM 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 "FdtPlatform.h" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-i", TypeFlag }, + {NULL , TypeMax } +}; + +/** + Display FDT device paths. + + Display in text form the device paths used to install the FDT from the + highest to the lowest priority. + +**/ +STATIC +VOID +DisplayFdtDevicePaths ( + VOID + ) +{ + EFI_STATUS Status; + UINTN DataSize; + CHAR16 *TextDevicePath; + CHAR16 *TextDevicePaths; + CHAR16 *TextDevicePathSeparator; + + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_DEVICE_PATH_LIST), + mFdtPlatformDxeHiiHandle + ); + + if (FeaturePcdGet (PcdOverridePlatformFdt)) { + DataSize = 0; + Status = gRT->GetVariable ( + L"Fdt", + &gFdtVariableGuid, + NULL, + &DataSize, + NULL + ); + + // + // Keep going only if the "Fdt" variable is defined. + // + + if (Status == EFI_BUFFER_TOO_SMALL) { + TextDevicePath = AllocatePool (DataSize); + if (TextDevicePath == NULL) { + return; + } + + Status = gRT->GetVariable ( + L"Fdt", + &gFdtVariableGuid, + NULL, + &DataSize, + TextDevicePath + ); + if (!EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_DEVICE_PATH), + mFdtPlatformDxeHiiHandle, + TextDevicePath + ); + } + + FreePool (TextDevicePath); + } + } + + // + // Loop over the device path list provided by "PcdFdtDevicePaths". The device + // paths are in text form and separated by a semi-colon. + // + + TextDevicePaths = AllocateCopyPool ( + StrSize ((CHAR16*)PcdGetPtr (PcdFdtDevicePaths)), + (CHAR16*)PcdGetPtr (PcdFdtDevicePaths) + ); + if (TextDevicePaths == NULL) { + return; + } + + for (TextDevicePath = TextDevicePaths; + *TextDevicePath != L'\0' ; ) { + TextDevicePathSeparator = StrStr (TextDevicePath, L";"); + + if (TextDevicePathSeparator != NULL) { + *TextDevicePathSeparator = L'\0'; + } + + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_DEVICE_PATH), + mFdtPlatformDxeHiiHandle, + TextDevicePath + ); + + if (TextDevicePathSeparator == NULL) { + break; + } + TextDevicePath = TextDevicePathSeparator + 1; + } + + FreePool (TextDevicePaths); +} + +/** + Update the text device path stored in the "Fdt" UEFI variable given + an EFI Shell file path or a text device path. + + This function is a subroutine of the ShellDynCmdSetFdtHandler() function + to make its code easier to read. + + @param[in] Shell The instance of the shell protocol used in the + context of processing the "setfdt" command. + @param[in] FilePath EFI Shell path or the device path to the FDT file. + + @return SHELL_SUCCESS The text device path was succesfully updated. + @return SHELL_INVALID_PARAMETER The Shell file path is not valid. + @return SHELL_OUT_OF_RESOURCES A memory allocation failed. + @return SHELL_DEVICE_ERROR The "Fdt" variable could not be saved due to a hardware failure. + @return SHELL_ACCESS_DENIED The "Fdt" variable is read-only. + @return SHELL_ACCESS_DENIED The "Fdt" variable cannot be deleted. + @return SHELL_ACCESS_DENIED The "Fdt" variable could not be written due to security violation. + @return SHELL_NOT_FOUND Device path to text protocol not found. + @return SHELL_ABORTED Operation aborted. + +**/ +STATIC +SHELL_STATUS +UpdateFdtTextDevicePath ( + IN EFI_SHELL_PROTOCOL *Shell, + IN CONST CHAR16 *FilePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH *DevicePath; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *EfiDevicePathToTextProtocol; + CHAR16 *TextDevicePath; + CHAR16 *FdtVariableValue; + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; + SHELL_STATUS ShellStatus; + + ASSERT (FilePath != NULL); + DevicePath = NULL; + TextDevicePath = NULL; + FdtVariableValue = NULL; + + if (*FilePath != L'\0') { + DevicePath = Shell->GetDevicePathFromFilePath (FilePath); + if (DevicePath != NULL) { + Status = gBS->LocateProtocol ( + &gEfiDevicePathToTextProtocolGuid, + NULL, + (VOID **)&EfiDevicePathToTextProtocol + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + TextDevicePath = EfiDevicePathToTextProtocol->ConvertDevicePathToText ( + DevicePath, + FALSE, + FALSE + ); + if (TextDevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + FdtVariableValue = TextDevicePath; + } else { + // + // Try to convert back the EFI Device Path String into a EFI device Path + // to ensure the format is valid + // + Status = gBS->LocateProtocol ( + &gEfiDevicePathFromTextProtocolGuid, + NULL, + (VOID **)&EfiDevicePathFromTextProtocol + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ( + FilePath + ); + if (DevicePath == NULL) { + Status = EFI_INVALID_PARAMETER; + goto Error; + } + FdtVariableValue = (CHAR16*)FilePath; + } + } + + Status = gRT->SetVariable ( + (CHAR16*)L"Fdt", + &gFdtVariableGuid, + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS , + (FdtVariableValue != NULL) ? + StrSize (FdtVariableValue) : 0, + FdtVariableValue + ); + +Error: + ShellStatus = EfiCodeToShellCode (Status); + if (!EFI_ERROR (Status)) { + if (FdtVariableValue != NULL) { + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_UPDATE_SUCCEEDED), + mFdtPlatformDxeHiiHandle, + FdtVariableValue + ); + } else { + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_UPDATE_DELETED), + mFdtPlatformDxeHiiHandle + ); + } + } else { + if (Status == EFI_INVALID_PARAMETER) { + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_INVALID_PATH), + mFdtPlatformDxeHiiHandle, + FilePath + ); + } else { + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_ERROR), + mFdtPlatformDxeHiiHandle, + Status + ); + } + } + + if (DevicePath != NULL) { + FreePool (DevicePath); + } + if (TextDevicePath != NULL) { + FreePool (TextDevicePath); + } + + return ShellStatus; +} + +/** + This is the shell command "setfdt" handler function. This function handles + the command when it is invoked in the shell. + + @param[in] This The instance of the + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] SystemTable The pointer to the UEFI system table. + @param[in] ShellParameters The parameters associated with the command. + @param[in] Shell The instance of the shell protocol used in the + context of processing this command. + + @return SHELL_SUCCESS The operation was successful. + @return SHELL_ABORTED Operation aborted due to internal error. + @return SHELL_INVALID_PARAMETER The parameters of the command are not valid. + @return SHELL_INVALID_PARAMETER The EFI Shell file path is not valid. + @return SHELL_NOT_FOUND Failed to locate a protocol or a file. + @return SHELL_UNSUPPORTED Device path not supported. + @return SHELL_OUT_OF_RESOURCES A memory allocation failed. + @return SHELL_DEVICE_ERROR The "Fdt" variable could not be saved due to a hardware failure. + @return SHELL_ACCESS_DENIED The "Fdt" variable is read-only. + @return SHELL_ACCESS_DENIED The "Fdt" variable cannot be deleted. + @return SHELL_ACCESS_DENIED The "Fdt" variable could not be written due to security violation. + +**/ +SHELL_STATUS +EFIAPI +ShellDynCmdSetFdtHandler ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN EFI_SHELL_PROTOCOL *Shell + ) +{ + SHELL_STATUS ShellStatus; + EFI_STATUS Status; + LIST_ENTRY *ParamPackage; + BOOLEAN FilePath; + CONST CHAR16 *ValueStr; + CHAR16 *TextDevicePath; + + ShellStatus = SHELL_SUCCESS; + ParamPackage = NULL; + FilePath = FALSE; + + // + // Install the Shell and Shell Parameters Protocols on the driver + // image. This is necessary for the initialisation of the Shell + // Library to succeed in the next step. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &gImageHandle, + &gEfiShellProtocolGuid, Shell, + &gEfiShellParametersProtocolGuid, ShellParameters, + NULL + ); + if (EFI_ERROR (Status)) { + return SHELL_ABORTED; + } + + // + // Initialise the Shell Library as we are going to use it. + // Assert that the return code is EFI_SUCCESS as it should. + // To anticipate any change is the codes returned by + // ShellInitialize(), leave in case of error. + // + Status = ShellInitialize (); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return SHELL_ABORTED; + } + + Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE); + if (!EFI_ERROR (Status)) { + switch (ShellCommandLineGetCount (ParamPackage)) { + case 1: + // + // Case "setfdt" or "setfdt -i" + // + if (!ShellCommandLineGetFlag (ParamPackage, L"-i")) { + DisplayFdtDevicePaths (); + } + break; + + case 2: + // + // Case "setfdt file_path" or + // "setfdt -i file_path" or + // "setfdt file_path -i" + // + FilePath = TRUE; + break; + + default: + Status = EFI_INVALID_PARAMETER; + } + } + if (EFI_ERROR (Status)) { + ShellStatus = EfiCodeToShellCode (Status); + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_ERROR), + mFdtPlatformDxeHiiHandle, + Status + ); + goto Error; + } + + // + // Update the preferred device path for the FDT if asked for. + // + if (FilePath) { + ValueStr = ShellCommandLineGetRawValue (ParamPackage, 1); + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_UPDATING), + mFdtPlatformDxeHiiHandle + ); + ShellStatus = UpdateFdtTextDevicePath (Shell, ValueStr); + if (ShellStatus != SHELL_SUCCESS) { + goto Error; + } + } + + // + // Run the FDT installation process if asked for. + // + if (ShellCommandLineGetFlag (ParamPackage, L"-i")) { + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_INSTALLING), + mFdtPlatformDxeHiiHandle + ); + Status = RunFdtInstallation (&TextDevicePath); + ShellStatus = EfiCodeToShellCode (Status); + if (!EFI_ERROR (Status)) { + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_INSTALL_SUCCEEDED), + mFdtPlatformDxeHiiHandle, + TextDevicePath + ); + FreePool (TextDevicePath); + } else { + if (Status == EFI_INVALID_PARAMETER) { + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_INVALID_DEVICE_PATH), + mFdtPlatformDxeHiiHandle + ); + } else { + ShellPrintHiiEx ( + -1, -1, NULL, + STRING_TOKEN (STR_SETFDT_ERROR), + mFdtPlatformDxeHiiHandle, + Status + ); + } + DisplayFdtDevicePaths (); + } + } + +Error: + gBS->UninstallMultipleProtocolInterfaces ( + gImageHandle, + &gEfiShellProtocolGuid, Shell, + &gEfiShellParametersProtocolGuid, ShellParameters, + NULL + ); + ShellCommandLineFreeVarList (ParamPackage); + + return ShellStatus; +} + +/** + This is the shell command "setfdt" help handler function. This + function returns the formatted help for the "setfdt" command. + The format matchs that in Appendix B of the revision 2.1 of the + UEFI Shell Specification. + + @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] Language The pointer to the language string to use. + + @return CHAR16* Pool allocated help string, must be freed by caller. +**/ +CHAR16* +EFIAPI +ShellDynCmdSetFdtGetHelp ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN CONST CHAR8 *Language + ) +{ + // + // This allocates memory. The caller has to free the allocated memory. + // + return HiiGetString ( + mFdtPlatformDxeHiiHandle, + STRING_TOKEN (STR_GET_HELP_SETFDT), + Language + ); +} From patchwork Mon Nov 20 11:37:13 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 119270 Delivered-To: patch@linaro.org Received: by 10.140.22.164 with SMTP id 33csp3733805qgn; Mon, 20 Nov 2017 03:37:29 -0800 (PST) X-Google-Smtp-Source: AGs4zMZuBTvOOKXq0T5ZIpnEUwe/yc/hNjgvla+P564VCQrrwe3S39sAaA2vrBgXbG0TraqSrZMd X-Received: by 10.98.33.8 with SMTP id h8mr10993983pfh.160.1511177849679; Mon, 20 Nov 2017 03:37:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1511177849; cv=none; d=google.com; s=arc-20160816; b=c1TfotyyeEElPgVqZ7rRHUN5jB+3BwDVPNg1g2gCsHjQzIfOGdnwS14TEZmh7ichod u38y+bCSmXqBFCTCcshFufjm1FUPTAj+XM+bt/ynkUje4Tql0K5HX/cuQv5FwAGbNlhd CXCuixA2BojNmCPR8Z4Zr2427MLPkN8H8DcrWspcUh1wEsyFhh/c8K7YbVp6De1X/k/T 1Hpg/x1/Olgc44Ckd418HGMwAM1Ns4rzwSAWYwIVqS+tU4ORC4OSlU6dkes8PcjjRPvT DdXfB9O0O/zWgDujTk44llAtws+lXxfuHRbUhMN7M7gNQM/+aoHKcxcJ0MUa2+bcIeyy 4kxA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:delivered-to:arc-authentication-results; bh=S5tadqRQk/KYtaN1itMJL/p6sVHvGrGOfe9QsloSHFg=; b=Io8jJeBPCqauBTKe0SqiYJZ7DC1xHdoR74rcIGeiaa9mdIsdKd6fsH6N1vdr2MkcQj ekXXv5emPQEko5ZqX8UeKY8x41cFGqGXfTj7hxqJrCesWRmv7L6/rkdmkhbMrkN6yPuV K5VK6qhkdeKInXRREjlaM4USoRSGervjqn+Ta1jQrVTDzTzKwvljfO/tURegra5no9B7 xgFYWmY5dGS7c8d3LBLVOGJaHuBgs35O1KlWjZB4LDxmGXUihzDbhMoioWQQFQnGt//8 +B5p+uY3i6iHJ8rOQgY9nG5IwBIMs2ocVCy7UEa+gymrZhNyEJwRkUxANbeKSWD2tX29 hD1w== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=A226fWhp; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from ml01.01.org (ml01.01.org. [198.145.21.10]) by mx.google.com with ESMTPS id h3si7272243plh.254.2017.11.20.03.37.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Nov 2017 03:37:29 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) client-ip=198.145.21.10; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=A226fWhp; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 2B7FF2034713D; Mon, 20 Nov 2017 03:33:15 -0800 (PST) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2a00:1450:400c:c09::242; helo=mail-wm0-x242.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-wm0-x242.google.com (mail-wm0-x242.google.com [IPv6:2a00:1450:400c:c09::242]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 9B50621959707 for ; Mon, 20 Nov 2017 03:33:13 -0800 (PST) Received: by mail-wm0-x242.google.com with SMTP id b189so17887305wmd.5 for ; Mon, 20 Nov 2017 03:37:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5/a2caRnb4HFNpDpGnJ1Fvt87zB6ym73i3rTa63+7dk=; b=A226fWhpHJx8FN6toTMuv8f4bM377JH+EatwHKCkG/x0WBcC8rTJH60ccm//wRtPi4 /imOnW/BFGuM/vMXOEgbVYnmSOTajMzttD7nJxoxZxKHRWTufbZ68oOkeoEhQ3Cqat5F WH2epH7GqjqleeisMRFiceJy8d+HbvjwMS1+s= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5/a2caRnb4HFNpDpGnJ1Fvt87zB6ym73i3rTa63+7dk=; b=aVAUyeuaNA2Fvjur0VwjC28gYyaB7JBHxNWUuI1RVL+zHQ2LxPMtpQvmo1dm9orBPH LfZ5bTvHKpW6AqmsLZPAkes7onJwfmFTYBF0UDBZIOe/jcJxwLAQd8g23trcVBs2vMyt Mo7HxcagD1HYPvvOc8aJ3o6JcSJnusAf/REfLkv1DEM/P8oCR3SmcHT7mPBmN6ktNRNJ ESXiJXK+bXUWd2aCtRLC8sKMmQcXG1jLQ1PBD+bLAdjBkwBWHvYG2y8/aijeO6P/ZpLO slFQanNEwu0ql0D8IfG0yiG8M3pcWtZ/iK+o1pdRihzFCHcSHgpJUwE1E4W/X48K4fJT EmZA== X-Gm-Message-State: AJaThX6YvgqvXmNKNUg9PV9bnlo5I/CINIqJmY82DN933Mbw3NH5FiZF rGv69Fghm3DRzCrDd7swFXjI36vXTIA= X-Received: by 10.28.22.16 with SMTP id 16mr9137629wmw.138.1511177846101; Mon, 20 Nov 2017 03:37:26 -0800 (PST) Received: from localhost.localdomain ([154.145.25.106]) by smtp.gmail.com with ESMTPSA id d4sm14760181wmh.35.2017.11.20.03.37.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Nov 2017 03:37:25 -0800 (PST) From: Ard Biesheuvel To: edk2-devel@lists.01.org Date: Mon, 20 Nov 2017 11:37:13 +0000 Message-Id: <20171120113714.21856-4-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171120113714.21856-1-ard.biesheuvel@linaro.org> References: <20171120113714.21856-1-ard.biesheuvel@linaro.org> Subject: [edk2] [PATCH edk2-platforms 3/4] Platform/ARM/Juno: move to migrated FdtPlatformDxe X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: leif.lindholm@linaro.org, Ard Biesheuvel MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" Move Juno to the migrated version of FdtPlatformDxe. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ard Biesheuvel --- Platform/ARM/JunoPkg/ArmJuno.dsc | 6 +++--- Platform/ARM/JunoPkg/ArmJuno.fdf | 2 +- Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf | 3 ++- Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc | 5 +---- 4 files changed, 7 insertions(+), 9 deletions(-) -- 2.11.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel diff --git a/Platform/ARM/JunoPkg/ArmJuno.dsc b/Platform/ARM/JunoPkg/ArmJuno.dsc index 4c63309d36f1..e7cb280ff381 100644 --- a/Platform/ARM/JunoPkg/ArmJuno.dsc +++ b/Platform/ARM/JunoPkg/ArmJuno.dsc @@ -200,7 +200,7 @@ [PcdsDynamicDefault.common] # character "empty" string, to allow to be able to set FDT text device paths # up to 128 characters long. # - gEmbeddedTokenSpaceGuid.PcdFdtDevicePaths|L" " + gFdtPlatformDxeTokenSpaceGuid.PcdFdtDevicePaths|L" " # Not all Juno platforms support PCI. This dynamic PCD disables or enable # PCI support. @@ -352,9 +352,9 @@ [Components.common] # # FDT installation # - EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf { + Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf { - BdsLib|ArmPkg/Library/BdsLib/BdsLib.inf + BdsLib|Platform/ARM/Library/BdsLib/BdsLib.inf } [Components.AARCH64] diff --git a/Platform/ARM/JunoPkg/ArmJuno.fdf b/Platform/ARM/JunoPkg/ArmJuno.fdf index 04d58323d130..898c471248d7 100644 --- a/Platform/ARM/JunoPkg/ArmJuno.fdf +++ b/Platform/ARM/JunoPkg/ArmJuno.fdf @@ -230,7 +230,7 @@ [FV.FvMain] # # The UEFI driver is at the end of the list of the driver to be dispatched # after the device drivers (eg: Ethernet) to ensure we have support for them. - INF EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf + INF Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf !if $(ARCH) == AARCH64 # diff --git a/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf index 70175c2d2405..7da336fbd8e7 100644 --- a/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf +++ b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf @@ -29,6 +29,7 @@ [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec Platform/ARM/ARM.dec + Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.dec Platform/ARM/JunoPkg/ArmJuno.dec [LibraryClasses] @@ -81,7 +82,7 @@ [FixedPcd] gArmTokenSpaceGuid.PcdPciBusMax [Pcd] - gEmbeddedTokenSpaceGuid.PcdFdtDevicePaths + gFdtPlatformDxeTokenSpaceGuid.PcdFdtDevicePaths gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration [Depex] diff --git a/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc b/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc index 75f4e924cb9f..3679530decf0 100644 --- a/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc +++ b/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc @@ -457,10 +457,7 @@ [Components.common] # # Android Fastboot # - EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.inf { - - BdsLib|ArmPkg/Library/BdsLib/BdsLib.inf - } + EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.inf EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsbDxe.inf Platform/ARM/VExpressPkg/Drivers/ArmVExpressFastBootDxe/ArmVExpressFastBootDxe.inf From patchwork Mon Nov 20 11:37:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 119272 Delivered-To: patch@linaro.org Received: by 10.140.22.164 with SMTP id 33csp3733911qgn; Mon, 20 Nov 2017 03:37:35 -0800 (PST) X-Google-Smtp-Source: AGs4zMbk9RF1KV/u297pHAAy41LmIpQBLtanFpaFsjez7VY6d5ApZsjLp19rq4n3cAOpzRGGQ0zi X-Received: by 10.98.65.197 with SMTP id g66mr10981080pfd.60.1511177855610; Mon, 20 Nov 2017 03:37:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1511177855; cv=none; d=google.com; s=arc-20160816; b=dngg0xj+bZvpEk5KpNAPK4U6MvmjPx6dQiPwYk0Lc7+4PnsmX30zy15MQgI8Iw8H0g dNE+0JgOO3gXARJLjXO3hDqVV3X7wyMBZXG7/GA+qkZeEZ+z/a4Fwr9J2dw9e80y7Ixp v8k96Q7QQYC1xFsqHq2S+KBs5YvOtow2cuOQNClrKtw2gzYizOm5/GDj8sYieLeOYkiv oGuqUTF/pGHWInd9tHS2/17Cm20ExVADh8JZg0PCD/O6U7UUBOM4U1pfdTDGWKKues64 a4lZLc5o+A10I0YPGmC4arnex2SpIvsnz9imsAXUh8qGyvkMiZNH0uue/4FovGi2rqYb gPmg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:cc :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:delivered-to:arc-authentication-results; bh=4Lkli2JalF65QcnD771oGb7373wSsZ2Xv6w9IUmB0rQ=; b=0F6JQywz1RmqCcN7iVDUR2K82MU6D1CVd4/Hi6baM/V7/c+teSP860QLxBUlJY3s4/ N3YAtLdxp5P1bHGslAi307+NQ9dnbsC72UxZrpztI00M91gsPtAIq3QODuyhdKQqq2v/ KTEicVElzGl3W86Em1e9BW4lkzJYE4BMpTpCJHJG7wrncThsyiEwlDwJ0OaVuA5dO1s6 rHtU1738CSypzRt9EO1hUqoOx/Q8NDunV81vX3SnHoyBQeYG1cdV7T6jHkzo9mJVUphz J+s3SFC3weiNOwWi1mJ0KB6xdA5xjppnRzODy4d6GWHIefjiZIqFHNpnjLS46zcSvLnX 68pw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=U9VKitui; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from ml01.01.org (ml01.01.org. [198.145.21.10]) by mx.google.com with ESMTPS id s28si1072723pgo.597.2017.11.20.03.37.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Nov 2017 03:37:35 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) client-ip=198.145.21.10; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=U9VKitui; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id A59A920349DA3; Mon, 20 Nov 2017 03:33:16 -0800 (PST) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2a00:1450:400c:c0c::241; helo=mail-wr0-x241.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-wr0-x241.google.com (mail-wr0-x241.google.com [IPv6:2a00:1450:400c:c0c::241]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 1ADD121C913AB for ; Mon, 20 Nov 2017 03:33:15 -0800 (PST) Received: by mail-wr0-x241.google.com with SMTP id r2so1331524wra.13 for ; Mon, 20 Nov 2017 03:37:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=MerludL6i19J7W/2+vurQekMMmR88pu1T8Dv8kpABLY=; b=U9VKituiuye6QDo/pAtAs0Me3oP44yOWzvYtC2x68XAvrG4/kaAqOgabx8EGgtUAjD mnje7hASMM9ktKemhCxElPgX5rURzhqq93Q4+/fPrTcLpxOB6z56SV4crrfgznC+HUkc RFvMq3YrQRmDqCEIIaPgEVkymEvLgBqFqGP54= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=MerludL6i19J7W/2+vurQekMMmR88pu1T8Dv8kpABLY=; b=Fo52fcnv4tMAxzOM1fg3/ru/jBXIvIY0B5Bj0UPJdo7n/9/JPz5O3g32BNCO4PcUBz wu3FeNG5lsmlTYz2hnc/w1WmX9jL2nUpY41g1mJEnGzLbKPohoZCcGl6/NIFmtoa+ip2 9Tf87Brkybvw8L09LSi2jiullxkAXDhWMl5pNd0KzK1ZnSqztfyxeRpUkyiDvFf0XaHZ HT8xOdutb+JpA3ofHtqOLTMIwY2eo77YUU4Z1Okydpe8dbILwoHP+Q1y1ck8R5PC/ktM kt2c7WHXu7BWJXyxG2njD3o1IsDoKbuG48bT5v9S2tLNg7eWa3CTqFJZG1+qSAznVUr1 koJg== X-Gm-Message-State: AJaThX7ZDEsB2BZhUkNRJ2NWo9WnnTCB7GY7IivLbNmDemR+0U3a0k/k wAAi/c/GiNUkaAUYIJsuasRhas4WAD4= X-Received: by 10.223.138.138 with SMTP id y10mr11686541wry.167.1511177847846; Mon, 20 Nov 2017 03:37:27 -0800 (PST) Received: from localhost.localdomain ([154.145.25.106]) by smtp.gmail.com with ESMTPSA id d4sm14760181wmh.35.2017.11.20.03.37.26 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Nov 2017 03:37:27 -0800 (PST) From: Ard Biesheuvel To: edk2-devel@lists.01.org Date: Mon, 20 Nov 2017 11:37:14 +0000 Message-Id: <20171120113714.21856-5-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171120113714.21856-1-ard.biesheuvel@linaro.org> References: <20171120113714.21856-1-ard.biesheuvel@linaro.org> Subject: [edk2] [PATCH edk2-platforms 4/4] Platform/TC2: move to private FdtPlatformDxe implementation X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: leif.lindholm@linaro.org, Ard Biesheuvel MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" Move to our own private copy of FdtPlatformDxe and BdsLib so that we can get rid of the upstream version. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ard Biesheuvel --- Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc | 6 +++--- Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) -- 2.11.0 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel diff --git a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc index 1e6884ad5480..995dacd0b473 100644 --- a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc +++ b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.dsc @@ -183,7 +183,7 @@ [PcdsFixedAtBuild.common] # # Define the device path to the FDT for the platform # - gEmbeddedTokenSpaceGuid.PcdFdtDevicePaths|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)/ca15a7" + gFdtPlatformDxeTokenSpaceGuid.PcdFdtDevicePaths|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)/ca15a7" # # ARM Architectural Timer Frequency @@ -296,7 +296,7 @@ [Components.common] # # FDT installation # - EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf { + Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf { - BdsLib|ArmPkg/Library/BdsLib/BdsLib.inf + BdsLib|Platform/ARM/Library/BdsLib/BdsLib.inf } diff --git a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf index ed901f9f1f86..86d6f1415383 100644 --- a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf +++ b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf @@ -183,7 +183,7 @@ [FV.FvMain] # # The UEFI driver is at the end of the list of the driver to be dispatched # after the device drivers (eg: Ethernet) to ensure we have support for them. - INF EmbeddedPkg/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf + INF Platform/ARM/Drivers/FdtPlatformDxe/FdtPlatformDxe.inf # Example to add a Device Tree to the Firmware Volume #FILE FREEFORM = PCD(gArmVExpressTokenSpaceGuid.PcdFdtVExpressHwA15x2A7x3) {