From patchwork Thu Nov 16 18:00:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 119075 Delivered-To: patch@linaro.org Received: by 10.80.225.132 with SMTP id k4csp5013991edl; Thu, 16 Nov 2017 10:00:46 -0800 (PST) X-Google-Smtp-Source: AGs4zMbJIA8kKQz4iaARacArj+V/PbiyJ0kLkmYhj9YWk5LJjTNbY75WP3lRNKRwVj9w/oNXWRV6 X-Received: by 10.99.109.73 with SMTP id i70mr2509014pgc.134.1510855245870; Thu, 16 Nov 2017 10:00:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1510855245; cv=none; d=google.com; s=arc-20160816; b=NVD37MSQmyLZt9tHLuiWCYU8F7pFEGo6GcF0Jt45xKHxxEHL0no37E+mObr229he0w M7oB1nndI+Umop3fKUDtkTtDjQjbV/+sgrAajR8LDCZd2Sp2ayPD0ZRAXtLvezEOSRK+ gYNtFkfqqQFUcd9k9Eo0doPs+sKxbTdoG6VamkIVwjXQFbhdXyskdjSFKdjRcJNaT8nI dyVsF7zfolKeDLi//q1m/pGVaHZMT1iq4mVPZfhZ/V6f37Hnw7s3YP3uPg6p0IVg0Fjc suq0NZ44dqXfwoNtagyfSta+D7mcstIr1wsbCuqw3sy7/rz1NY6QoylaNzJi9jNvero5 0Ubw== 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=f61qhlYVgqnb03Ga48EkSfuPuP1xekDCVah1GIUdLJQ=; b=tFfE5+ND28p52sOCUo017xj8F/mYIEc+Q4QHQhkwm7p7ftUGf6vx13flUYHRcaf94h a71FB6qUSfXNwzGV1CQ5bqV5U99NHav4Dbay8H803sMGtWl4+DbP6+WlS8l85O8wUZkv tZ1GyqMxliAeRKxPD0F2lM5BOX0Lon7LGGgAWejtdXiHv0qFgrVM8Jr16+XOSM4YImZz qUaOUvWfgBJTqB4envp7AjOZLxH8B3kwh9h/D6/pN9uCtSe8ZNrN1c4wg+u7DnS0JGL+ /48kaKLuVDCd8LEXbTtYmADL2B8yaJjmvq+TodKaD4GOZjSgadfYVQgYpMZxCiNA6tfp 9wmg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=D/iggGVD; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 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. [2001:19d0:306:5::1]) by mx.google.com with ESMTPS id r3si1239716pgf.32.2017.11.16.10.00.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 Nov 2017 10:00:45 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 as permitted sender) client-ip=2001:19d0:306:5::1; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b=D/iggGVD; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 2001:19d0:306:5::1 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 720372035BB16; Thu, 16 Nov 2017 09:56:35 -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::230; helo=mail-wr0-x230.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-wr0-x230.google.com (mail-wr0-x230.google.com [IPv6:2a00:1450:400c:c0c::230]) (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 60B972035BB05 for ; Thu, 16 Nov 2017 09:56:31 -0800 (PST) Received: by mail-wr0-x230.google.com with SMTP id y42so23637873wrd.3 for ; Thu, 16 Nov 2017 10:00:41 -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=Dlc6De2a59NrBsmZ9DhP6ggnPC1A/GWDckyvTuh5YHY=; b=D/iggGVD4VGxG1jtZwFbcPoHduk4Fv6rZB6GNTIXes5+bMPakNrqXu/0JLHDb9oC89 LFzYRrqr1uq/08T5GBjOuNnGJx9bL8s6jEp0hHFgJiJJ7+xPOrTD1egQ+cgLYWadKxnf Kw+rfzIACynqvIPyR+f2gRD9MnG4kizdMF9QY= 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=Dlc6De2a59NrBsmZ9DhP6ggnPC1A/GWDckyvTuh5YHY=; b=e39kNptEpL9J/5d/mJPdy5QbjX02+rCQCB/VMOqkFo1AXayf1zMO7mtV4oNRpQyyEK yXlbnFmuAi1owve9wNHu9YLNIWmBGUDrCPGAnBYAcvxw3ONbe4bju1BBUEqvmHW5zsJV G564SWVMUdK8zOSfJLwSsWxWOiHQFx56ZcQiZDVD1WRbCTPphQXB2WEsTQa9HRbuZ+WX yVzuBQAk21jYXUmn9NBfSpVmbCtBccMziG+Xyi6SHSrW6bCR8PR9v6lYjsVXi20E+60k 5gqPG0/iSw5IJ1k3VueZuK+eYFWql9XbQBNpdQ8NrwMDESfCrMRZUAeOt4NGel0e4jyM LaUQ== X-Gm-Message-State: AJaThX6t7tTW0Wmwu204ZlmAseZeVvZBLtzQ+xgvxAqm9OBb27umX48F qDg0zwOzuZhzatW7vLDnBmesCXWTNfk= X-Received: by 10.223.141.180 with SMTP id o49mr2053033wrb.35.1510855236788; Thu, 16 Nov 2017 10:00:36 -0800 (PST) Received: from localhost.localdomain ([160.167.170.128]) by smtp.gmail.com with ESMTPSA id s67sm1917372wmd.23.2017.11.16.10.00.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 16 Nov 2017 10:00:35 -0800 (PST) From: Ard Biesheuvel To: edk2-devel@lists.01.org, leif.lindholm@linaro.org Date: Thu, 16 Nov 2017 18:00:19 +0000 Message-Id: <20171116180021.30139-2-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20171116180021.30139-1-ard.biesheuvel@linaro.org> References: <20171116175839.30012-1-ard.biesheuvel@linaro.org> <20171116180021.30139-1-ard.biesheuvel@linaro.org> Subject: [edk2] [PATCH edk2-platforms v2 11/13] Platform/ARM: import BootMonFs and ArmShellCmdRunAxf 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: Ard Biesheuvel MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" BootMonFs and ArmShellCmdRunAxf are only used on development boards manufactured by ARM itself, so let's keep it under Platform/ARM where it belongs. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ard Biesheuvel --- Platform/ARM/ARM.dec | 25 + Platform/ARM/Drivers/BootMonFs/BootMonFs.dec | 26 + Platform/ARM/Drivers/BootMonFs/BootMonFs.inf | 63 ++ Platform/ARM/Drivers/BootMonFs/BootMonFsApi.h | 388 +++++++ Platform/ARM/Drivers/BootMonFs/BootMonFsDir.c | 766 ++++++++++++++ Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c | 529 ++++++++++ Platform/ARM/Drivers/BootMonFs/BootMonFsHw.h | 57 ++ Platform/ARM/Drivers/BootMonFs/BootMonFsImages.c | 222 ++++ Platform/ARM/Drivers/BootMonFs/BootMonFsInternal.h | 101 ++ Platform/ARM/Drivers/BootMonFs/BootMonFsOpenClose.c | 795 +++++++++++++++ Platform/ARM/Drivers/BootMonFs/BootMonFsReadWrite.c | 259 +++++ Platform/ARM/Drivers/BootMonFs/BootMonFsUnsupported.c | 37 + Platform/ARM/Include/Guid/BootMonFsFileInfo.h | 47 + Platform/ARM/Include/Library/ArmShellCmdLib.h | 57 ++ Platform/ARM/JunoPkg/ArmJuno.dsc | 2 +- Platform/ARM/JunoPkg/ArmJuno.fdf | 2 +- Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf | 1 + Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.c | 95 ++ Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.h | 83 ++ Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf | 54 + Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.uni | 68 ++ Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.c | 154 +++ Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.h | 66 ++ Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.c | 340 +++++++ Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.h | 64 ++ Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c | 395 ++++++++ Platform/ARM/Library/ArmShellCmdRunAxf/elf32.h | 258 +++++ Platform/ARM/Library/ArmShellCmdRunAxf/elf64.h | 260 +++++ Platform/ARM/Library/ArmShellCmdRunAxf/elf_common.h | 1059 ++++++++++++++++++++ Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf | 2 +- Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc | 6 +- Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf | 1 + 32 files changed, 6276 insertions(+), 6 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/ARM.dec b/Platform/ARM/ARM.dec new file mode 100644 index 000000000000..f9bf3294a0ca --- /dev/null +++ b/Platform/ARM/ARM.dec @@ -0,0 +1,25 @@ +#/** @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 = ARM + PACKAGE_GUID = 2a905d2b-30c9-4408-86a2-c0b328876aee + PACKAGE_VERSION = 0.1 + +[Includes] + Include # Root include for the package + +[Guids] + gArmBootMonFsFileInfoGuid = { 0x41e26b9c, 0xada6, 0x45b3, { 0x80, 0x8e, 0x23, 0x57, 0xa3, 0x5b, 0x60, 0xd6 } } diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFs.dec b/Platform/ARM/Drivers/BootMonFs/BootMonFs.dec new file mode 100644 index 000000000000..533dee3b616c --- /dev/null +++ b/Platform/ARM/Drivers/BootMonFs/BootMonFs.dec @@ -0,0 +1,26 @@ +#/** @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 = BootMonFs + PACKAGE_GUID = 41f14aba-452f-4204-a435-25242973c5b1 + PACKAGE_VERSION = 0.1 + +[Guids.common] + gArmBootMonFsTokenSpaceGuid = { 0xeb76a201, 0x69b4, 0x491f, { 0x9b, 0xde, 0xbf, 0x30, 0xbd, 0x03, 0x82, 0xb4 } } + +[PcdsFixedAtBuild.common] + # Boot Monitor FileSystem + gArmBootMonFsTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths|L""|VOID*|0x0000003A diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFs.inf b/Platform/ARM/Drivers/BootMonFs/BootMonFs.inf new file mode 100644 index 000000000000..5b9353f0ee21 --- /dev/null +++ b/Platform/ARM/Drivers/BootMonFs/BootMonFs.inf @@ -0,0 +1,63 @@ +#/** @file +# Support for ARM Boot Monitor File System +# +# Copyright (c) 2012-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 = 0x00010005 + BASE_NAME = BootMonFs + FILE_GUID = 7abbc454-f737-4322-931c-b1bb62a01d6f + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = BootMonFsEntryPoint + +[Sources] + BootMonFsEntryPoint.c + BootMonFsOpenClose.c + BootMonFsDir.c + BootMonFsImages.c + BootMonFsReadWrite.c + BootMonFsUnsupported.c + +[Packages] + ArmPlatformPkg/ArmPlatformPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Platform/ARM/ARM.dec + Platform/ARM/Drivers/BootMonFs/BootMonFs.dec + +[LibraryClasses] + BaseLib + DevicePathLib + MemoryAllocationLib + PrintLib + UefiDriverEntryPoint + UefiLib + +[Guids] + gArmBootMonFsFileInfoGuid + gEfiFileSystemInfoGuid + gEfiFileInfoGuid + gEfiFileSystemVolumeLabelInfoIdGuid + +[Pcd] + gArmBootMonFsTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths + +[Protocols] + gEfiDiskIoProtocolGuid + gEfiBlockIoProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEfiDevicePathProtocolGuid + gEfiDevicePathFromTextProtocolGuid + diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsApi.h b/Platform/ARM/Drivers/BootMonFs/BootMonFsApi.h new file mode 100644 index 000000000000..d690520a0f67 --- /dev/null +++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsApi.h @@ -0,0 +1,388 @@ +/** @file +* +* Copyright (c) 2012-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. +* +**/ + +#ifndef __BOOTMON_FS_API_H +#define __BOOTMON_FS_API_H + +#include + +EFI_STATUS +BootMonFsInitialize ( + IN BOOTMON_FS_INSTANCE *Instance + ); + +UINT32 +BootMonFsChecksum ( + IN VOID *Data, + IN UINT32 Size + ); + +EFI_STATUS +BootMonFsComputeFooterChecksum ( + IN OUT HW_IMAGE_DESCRIPTION *Footer + ); + +EFIAPI +EFI_STATUS +OpenBootMonFsOpenVolume ( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **Root + ); + +UINT32 +BootMonFsGetImageLength ( + IN BOOTMON_FS_FILE *File + ); + +UINTN +BootMonFsGetPhysicalSize ( + IN BOOTMON_FS_FILE* File + ); + +EFI_STATUS +BootMonFsCreateFile ( + IN BOOTMON_FS_INSTANCE *Instance, + OUT BOOTMON_FS_FILE **File + ); + +EFIAPI +EFI_STATUS +BootMonFsGetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +EFIAPI +EFI_STATUS +BootMonFsReadDirectory ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +EFIAPI +EFI_STATUS +BootMonFsFlushDirectory ( + IN EFI_FILE_PROTOCOL *This + ); + +/** + Flush all modified data associated with a file to a device. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the + file handle to flush. + + @retval EFI_SUCCESS The data was flushed. + @retval EFI_ACCESS_DENIED The file was opened read-only. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_FULL The volume is full. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to flush the data. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsFlushFile ( + IN EFI_FILE_PROTOCOL *This + ); + +/** + Close a specified file handle. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to close. + + @retval EFI_SUCCESS The file was closed. + @retval EFI_INVALID_PARAMETER The parameter "This" is NULL or is not an open + file handle. + +**/ +EFIAPI +EFI_STATUS +BootMonFsCloseFile ( + IN EFI_FILE_PROTOCOL *This + ); + +/** + Open a file on the boot monitor file system. + + The boot monitor file system does not allow for sub-directories. There is only + one directory, the root one. On any attempt to create a directory, the function + returns in error with the EFI_WRITE_PROTECTED error code. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is + the file handle to source location. + @param[out] NewHandle A pointer to the location to return the opened + handle for the new file. + @param[in] FileName The Null-terminated string of the name of the file + to be opened. + @param[in] OpenMode The mode to open the file : Read or Read/Write or + Read/Write/Create + @param[in] Attributes Attributes of the file in case of a file creation + + @retval EFI_SUCCESS The file was open. + @retval EFI_NOT_FOUND The specified file could not be found or the specified + directory in which to create a file could not be found. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_WRITE_PROTECTED Attempt to create a directory. This is not possible + with the Boot Monitor file system. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsOpenFile ( + IN EFI_FILE_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ); + +/** + Read data from an open file. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that + is the file handle to read data from. + @param[in out] BufferSize On input, the size of the Buffer. On output, the + amount of data returned in Buffer. In both cases, + the size is measured in bytes. + @param[out] Buffer The buffer into which the data is read. + + @retval EFI_SUCCESS The data was read. + @retval EFI_DEVICE_ERROR On entry, the current file position is + beyond the end of the file, or the device + reported an error while performing the read + operation. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsReadFile ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +EFIAPI +EFI_STATUS +BootMonFsSetDirPosition ( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ); + +EFIAPI +EFI_STATUS +BootMonFsGetPosition ( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ); + +/** + Write data to an open file. + + The data is not written to the flash yet. It will be written when the file + will be either read, closed or flushed. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that + is the file handle to write data to. + @param[in out] BufferSize On input, the size of the Buffer. On output, the + size of the data actually written. In both cases, + the size is measured in bytes. + @param[in] Buffer The buffer of data to write. + + @retval EFI_SUCCESS The data was written. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_OUT_OF_RESOURCES Unable to allocate the buffer to store the + data to write. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsWriteFile ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +EFIAPI +EFI_STATUS +BootMonFsDeleteFail ( + IN EFI_FILE_PROTOCOL *This + ); + +/** + Close and delete a file from the boot monitor file system. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to delete. + + @retval EFI_SUCCESS The file was closed and deleted. + @retval EFI_INVALID_PARAMETER The parameter "This" is NULL or is not an open + file handle. + @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted. + +**/ +EFIAPI +EFI_STATUS +BootMonFsDelete ( + IN EFI_FILE_PROTOCOL *This + ); + +/** + Set a file's current position. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is + the file handle to set the requested position on. + @param[in] Position The byte position from the start of the file to set. + + @retval EFI_SUCCESS The position was set. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsSetPosition ( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ); + +/** + Return a file's current position. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is + the file handle to get the current position on. + @param[out] Position The address to return the file's current position value. + + @retval EFI_SUCCESS The position was returned. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsGetPosition( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ); + +// +// UNSUPPORTED OPERATIONS +// + +EFIAPI +EFI_STATUS +BootMonFsGetPositionUnsupported ( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ); + +/** + Set information about a file or a volume. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that + is the file handle the information is for. + @param[in] InformationType The type identifier for the information being set : + EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or + EFI_FILE_SYSTEM_VOLUME_LABEL_ID + @param[in] BufferSize The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the data buffer to write. The type of the + data inside the buffer is indicated by InformationType. + + @retval EFI_SUCCESS The information was set. + @retval EFI_UNSUPPORTED The InformationType is not known. + @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed. + @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file + to a file that is already present. + @retval EFI_ACCESS_DENIED An attempt is being made to change the + EFI_FILE_DIRECTORY Attribute. + @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and + the file was opened in read-only mode and an + attempt is being made to modify a field other + than Attribute. + @retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only + attribute. + @retval EFI_BAD_BUFFER_SIZE The size of the buffer is lower than that indicated by + the data inside the buffer. + @retval EFI_OUT_OF_RESOURCES A allocation needed to process the request failed. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsSetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +// +// Directory API +// + +EFI_STATUS +BootMonFsOpenDirectory ( + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN BOOTMON_FS_INSTANCE *Volume + ); + +// +// Internal API +// + +/** + Search for a file given its name coded in Ascii. + + When searching through the files of the volume, if a file is currently not + open, its name was written on the media and is kept in RAM in the + "HwDescription.Footer.Filename[]" field of the file's description. + + If a file is currently open, its name might not have been written on the + media yet, and as the "HwDescription" is a mirror in RAM of what is on the + media the "HwDescription.Footer.Filename[]" might be outdated. In that case, + the up to date name of the file is stored in the "Info" field of the file's + description. + + @param[in] Instance Pointer to the description of the volume in which + the file has to be search for. + @param[in] AsciiFileName Name of the file. + + @param[out] File Pointer to the description of the file if the + file was found. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. + +**/ +EFI_STATUS +BootMonGetFileFromAsciiFileName ( + IN BOOTMON_FS_INSTANCE *Instance, + IN CHAR8* AsciiFileName, + OUT BOOTMON_FS_FILE **File + ); + +EFI_STATUS +BootMonGetFileFromPosition ( + IN BOOTMON_FS_INSTANCE *Instance, + IN UINTN Position, + OUT BOOTMON_FS_FILE **File + ); + +#endif diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsDir.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsDir.c new file mode 100644 index 000000000000..64ea0ec68048 --- /dev/null +++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsDir.c @@ -0,0 +1,766 @@ +/** @file +* +* Copyright (c) 2012-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 "BootMonFsInternal.h" + +EFIAPI +EFI_STATUS +OpenBootMonFsOpenVolume ( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **Root + ) +{ + BOOTMON_FS_INSTANCE *Instance; + + Instance = BOOTMON_FS_FROM_FS_THIS (This); + if (Instance == NULL) { + return EFI_DEVICE_ERROR; + } + + Instance->RootFile->Info->Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY; + + *Root = &Instance->RootFile->File; + + return EFI_SUCCESS; +} + +UINT32 +BootMonFsGetImageLength ( + IN BOOTMON_FS_FILE *File + ) +{ + UINT32 Index; + UINT32 FileSize; + LIST_ENTRY *RegionToFlushLink; + BOOTMON_FS_FILE_REGION *Region; + + FileSize = 0; + + // Look at all Flash areas to determine file size + for (Index = 0; Index < HW_IMAGE_DESCRIPTION_REGION_MAX; Index++) { + FileSize += File->HwDescription.Region[Index].Size; + } + + // Add the regions that have not been flushed yet + for (RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink); + !IsNull (&File->RegionToFlushLink, RegionToFlushLink); + RegionToFlushLink = GetNextNode (&File->RegionToFlushLink, RegionToFlushLink) + ) + { + Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink; + if (Region->Offset + Region->Size > FileSize) { + FileSize += Region->Offset + Region->Size; + } + } + + return FileSize; +} + +UINTN +BootMonFsGetPhysicalSize ( + IN BOOTMON_FS_FILE* File + ) +{ + // Return 0 for files that haven't yet been flushed to media + if (File->HwDescription.RegionCount == 0) { + return 0; + } + + return ((File->HwDescription.BlockEnd - File->HwDescription.BlockStart) + 1 ) + * File->Instance->Media->BlockSize; +} + +EFIAPI +EFI_STATUS +BootMonFsSetDirPosition ( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ) +{ + BOOTMON_FS_FILE *File; + + File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (File == NULL) { + return EFI_INVALID_PARAMETER; + } + + // UEFI Spec section 12.5: + // "The seek request for nonzero is not valid on open directories." + if (Position != 0) { + return EFI_UNSUPPORTED; + } + File->Position = Position; + + return EFI_SUCCESS; +} + +EFI_STATUS +BootMonFsOpenDirectory ( + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN BOOTMON_FS_INSTANCE *Volume + ) +{ + ASSERT(0); + + return EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +GetFileSystemVolumeLabelInfo ( + IN BOOTMON_FS_INSTANCE *Instance, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + UINTN Size; + EFI_FILE_SYSTEM_VOLUME_LABEL *Label; + EFI_STATUS Status; + + Label = Buffer; + + // Value returned by StrSize includes null terminator. + Size = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + + StrSize (Instance->FsInfo.VolumeLabel); + + if (*BufferSize >= Size) { + CopyMem (&Label->VolumeLabel, &Instance->FsInfo.VolumeLabel, Size); + Status = EFI_SUCCESS; + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + *BufferSize = Size; + return Status; +} + +// Helper function that calculates a rough "free space" by: +// - Taking the media size +// - Subtracting the sum of all file sizes +// - Subtracting the block size times the number of files +// (To account for the blocks containing the HW_IMAGE_INFO +STATIC +UINT64 +ComputeFreeSpace ( + IN BOOTMON_FS_INSTANCE *Instance + ) +{ + LIST_ENTRY *FileLink; + UINT64 FileSizeSum; + UINT64 MediaSize; + UINTN NumFiles; + EFI_BLOCK_IO_MEDIA *Media; + BOOTMON_FS_FILE *File; + + Media = Instance->BlockIo->Media; + MediaSize = Media->BlockSize * (Media->LastBlock + 1); + + NumFiles = 0; + FileSizeSum = 0; + for (FileLink = GetFirstNode (&Instance->RootFile->Link); + !IsNull (&Instance->RootFile->Link, FileLink); + FileLink = GetNextNode (&Instance->RootFile->Link, FileLink) + ) + { + File = BOOTMON_FS_FILE_FROM_LINK_THIS (FileLink); + FileSizeSum += BootMonFsGetImageLength (File); + + NumFiles++; + } + + return MediaSize - (FileSizeSum + (Media->BlockSize + NumFiles)); +} + +STATIC +EFI_STATUS +GetFilesystemInfo ( + IN BOOTMON_FS_INSTANCE *Instance, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + + if (*BufferSize >= Instance->FsInfo.Size) { + Instance->FsInfo.FreeSpace = ComputeFreeSpace (Instance); + CopyMem (Buffer, &Instance->FsInfo, Instance->FsInfo.Size); + Status = EFI_SUCCESS; + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + + *BufferSize = Instance->FsInfo.Size; + return Status; +} + +STATIC +EFI_STATUS +GetFileInfo ( + IN BOOTMON_FS_INSTANCE *Instance, + IN BOOTMON_FS_FILE *File, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_FILE_INFO *Info; + UINTN ResultSize; + + ResultSize = SIZE_OF_EFI_FILE_INFO + StrSize (File->Info->FileName); + + if (*BufferSize < ResultSize) { + *BufferSize = ResultSize; + return EFI_BUFFER_TOO_SMALL; + } + + Info = Buffer; + + CopyMem (Info, File->Info, ResultSize); + // Size of the information + Info->Size = ResultSize; + + *BufferSize = ResultSize; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GetBootMonFsFileInfo ( + IN BOOTMON_FS_INSTANCE *Instance, + IN BOOTMON_FS_FILE *File, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + BOOTMON_FS_FILE_INFO *Info; + UINTN ResultSize; + UINTN Index; + + if (File == Instance->RootFile) { + Status = EFI_UNSUPPORTED; + } else { + ResultSize = SIZE_OF_BOOTMON_FS_FILE_INFO; + + if (*BufferSize < ResultSize) { + *BufferSize = ResultSize; + Status = EFI_BUFFER_TOO_SMALL; + } else { + Info = Buffer; + + // Zero out the structure + ZeroMem (Info, ResultSize); + + // Fill in the structure + Info->Size = ResultSize; + + Info->EntryPoint = File->HwDescription.EntryPoint; + Info->RegionCount = File->HwDescription.RegionCount; + for (Index = 0; Index < File->HwDescription.RegionCount; Index++) { + Info->Region[Index].LoadAddress = File->HwDescription.Region[Index].LoadAddress; + Info->Region[Index].Size = File->HwDescription.Region[Index].Size; + Info->Region[Index].Offset = File->HwDescription.Region[Index].Offset; + Info->Region[Index].Checksum = File->HwDescription.Region[Index].Checksum; + } + *BufferSize = ResultSize; + Status = EFI_SUCCESS; + } + } + + return Status; +} + +/** + Set the name of a file. + + This is a helper function for SetFileInfo(). + + @param[in] Instance A pointer to the description of the volume + the file belongs to. + @param[in] File A pointer to the description of the file. + @param[in] FileName A pointer to the new name of the file. + + @retval EFI_SUCCESS The name was set. + @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file + to a file that is already present. + +**/ +STATIC +EFI_STATUS +SetFileName ( + IN BOOTMON_FS_INSTANCE *Instance, + IN BOOTMON_FS_FILE *File, + IN CONST CHAR16 *FileName + ) +{ + CHAR8 AsciiFileName[MAX_NAME_LENGTH]; + BOOTMON_FS_FILE *SameFile; + + // If the file path start with a \ strip it. The EFI Shell may + // insert a \ in front of the file name. + if (FileName[0] == L'\\') { + FileName++; + } + + UnicodeStrToAsciiStrS (FileName, AsciiFileName, MAX_NAME_LENGTH); + + if (BootMonGetFileFromAsciiFileName ( + File->Instance, + AsciiFileName, + &SameFile + ) != EFI_NOT_FOUND) { + // A file with that name already exists. + return EFI_ACCESS_DENIED; + } else { + // OK, change the filename. + AsciiStrToUnicodeStrS (AsciiFileName, File->Info->FileName, + (File->Info->Size - SIZE_OF_EFI_FILE_INFO) / sizeof (CHAR16)); + return EFI_SUCCESS; + } +} + +/** + Set the size of a file. + + This is a helper function for SetFileInfo(). + + @param[in] Instance A pointer to the description of the volume + the file belongs to. + @param[in] File A pointer to the description of the file. + @param[in] NewSize The requested new size for the file. + + @retval EFI_SUCCESS The size was set. + @retval EFI_OUT_OF_RESOURCES An allocation needed to process the request failed. + +**/ +STATIC +EFI_STATUS +SetFileSize ( + IN BOOTMON_FS_INSTANCE *Instance, + IN BOOTMON_FS_FILE *BootMonFsFile, + IN UINTN NewSize + ) +{ + EFI_STATUS Status; + UINT32 OldSize; + LIST_ENTRY *RegionToFlushLink; + LIST_ENTRY *NextRegionToFlushLink; + BOOTMON_FS_FILE_REGION *Region; + EFI_FILE_PROTOCOL *File; + CHAR8 *Buffer; + UINTN BufferSize; + UINT64 StoredPosition; + + OldSize = BootMonFsFile->Info->FileSize; + + // + // In case of file truncation, force the regions waiting for writing to + // not overflow the new size of the file. + // + if (NewSize < OldSize) { + for (RegionToFlushLink = GetFirstNode (&BootMonFsFile->RegionToFlushLink); + !IsNull (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink); + ) + { + NextRegionToFlushLink = GetNextNode (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink); + Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink; + if (Region->Offset > NewSize) { + RemoveEntryList (RegionToFlushLink); + FreePool (Region->Buffer); + FreePool (Region); + } else { + Region->Size = MIN (Region->Size, NewSize - Region->Offset); + } + RegionToFlushLink = NextRegionToFlushLink; + } + + } else if (NewSize > OldSize) { + // Increasing a file's size is potentially complicated as it may require + // moving the image description on media. The simplest way to do it is to + // seek past the end of the file (which is valid in UEFI) and perform a + // Write. + File = &BootMonFsFile->File; + + // Save position + Status = File->GetPosition (File, &StoredPosition); + if (EFI_ERROR (Status)) { + return Status; + } + // Set position at the end of the file + Status = File->SetPosition (File, OldSize); + if (EFI_ERROR (Status)) { + return Status; + } + + BufferSize = NewSize - OldSize; + Buffer = AllocateZeroPool (BufferSize); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = File->Write (File, &BufferSize, Buffer); + FreePool (Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // Restore saved position + Status = File->SetPosition (File, StoredPosition); + if (EFI_ERROR (Status)) { + return Status; + } + } + + BootMonFsFile->Info->FileSize = NewSize; + + return EFI_SUCCESS; +} + +/** + Set information about a file. + + @param[in] Instance A pointer to the description of the volume + the file belongs to. + @param[in] File A pointer to the description of the file. + @param[in] Info A pointer to the file information to write. + + @retval EFI_SUCCESS The information was set. + @retval EFI_ACCESS_DENIED An attempt is being made to change the + EFI_FILE_DIRECTORY Attribute. + @retval EFI_ACCESS_DENIED The file was opened in read-only mode and an + attempt is being made to modify a field other + than Attribute. + @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file + to a file that is already present. + @retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only + attribute. + @retval EFI_OUT_OF_RESOURCES An allocation needed to process the request + failed. + +**/ +STATIC +EFI_STATUS +SetFileInfo ( + IN BOOTMON_FS_INSTANCE *Instance, + IN BOOTMON_FS_FILE *File, + IN EFI_FILE_INFO *Info + ) +{ + EFI_STATUS Status; + BOOLEAN FileSizeIsDifferent; + BOOLEAN FileNameIsDifferent; + BOOLEAN TimeIsDifferent; + + // + // A directory can not be changed to a file and a file can + // not be changed to a directory. + // + if ((Info->Attribute & EFI_FILE_DIRECTORY) != + (File->Info->Attribute & EFI_FILE_DIRECTORY) ) { + return EFI_ACCESS_DENIED; + } + + FileSizeIsDifferent = (Info->FileSize != File->Info->FileSize); + FileNameIsDifferent = (StrnCmp ( + Info->FileName, + File->Info->FileName, + MAX_NAME_LENGTH - 1 + ) != 0); + // + // Check if the CreateTime, LastAccess or ModificationTime + // have been changed. The file system does not support file + // timestamps thus the three times in "File->Info" are + // always equal to zero. The following comparison actually + // checks if all three times are still equal to 0 or not. + // + TimeIsDifferent = CompareMem ( + &Info->CreateTime, + &File->Info->CreateTime, + 3 * sizeof (EFI_TIME) + ) != 0; + + // + // For a file opened in read-only mode, only the Attribute field can be + // modified. The root directory open mode is forced to read-only at opening + // thus the following test protects the root directory to be somehow modified. + // + if (File->OpenMode == EFI_FILE_MODE_READ) { + if (FileSizeIsDifferent || FileNameIsDifferent || TimeIsDifferent) { + return EFI_ACCESS_DENIED; + } + } + + if (TimeIsDifferent) { + return EFI_WRITE_PROTECTED; + } + + if (FileSizeIsDifferent) { + Status = SetFileSize (Instance, File, Info->FileSize); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Note down in RAM the Attribute field but we can not + // ask to store it in flash for the time being. + // + File->Info->Attribute = Info->Attribute; + + if (FileNameIsDifferent) { + Status = SetFileName (Instance, File, Info->FileName); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} + +EFIAPI +EFI_STATUS +BootMonFsGetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + BOOTMON_FS_FILE *File; + BOOTMON_FS_INSTANCE *Instance; + + if ((This == NULL) || + (InformationType == NULL) || + (BufferSize == NULL) || + ((Buffer == NULL) && (*BufferSize > 0)) ) { + return EFI_INVALID_PARAMETER; + } + + File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (File->Info == NULL) { + return EFI_INVALID_PARAMETER; + } + Instance = File->Instance; + + // If the instance has not been initialized yet then do it ... + if (!Instance->Initialized) { + Status = BootMonFsInitialize (Instance); + } else { + Status = EFI_SUCCESS; + } + + if (!EFI_ERROR (Status)) { + if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid) + != 0) { + Status = GetFileSystemVolumeLabelInfo (Instance, BufferSize, Buffer); + } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) != 0) { + Status = GetFilesystemInfo (Instance, BufferSize, Buffer); + } else if (CompareGuid (InformationType, &gEfiFileInfoGuid) != 0) { + Status = GetFileInfo (Instance, File, BufferSize, Buffer); + } else if (CompareGuid (InformationType, &gArmBootMonFsFileInfoGuid) != 0) { + Status = GetBootMonFsFileInfo (Instance, File, BufferSize, Buffer); + } else { + Status = EFI_UNSUPPORTED; + } + } + + return Status; +} + +/** + Set information about a file or a volume. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that + is the file handle the information is for. + @param[in] InformationType The type identifier for the information being set : + EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or + EFI_FILE_SYSTEM_VOLUME_LABEL_ID + @param[in] BufferSize The size, in bytes, of Buffer. + @param[in] Buffer A pointer to the data buffer to write. The type of the + data inside the buffer is indicated by InformationType. + + @retval EFI_SUCCESS The information was set. + @retval EFI_UNSUPPORTED The InformationType is not known. + @retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed. + @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file + to a file that is already present. + @retval EFI_ACCESS_DENIED An attempt is being made to change the + EFI_FILE_DIRECTORY Attribute. + @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and + the file was opened in read-only mode and an + attempt is being made to modify a field other + than Attribute. + @retval EFI_WRITE_PROTECTED An attempt is being made to modify a read-only + attribute. + @retval EFI_BAD_BUFFER_SIZE The size of the buffer is lower than that indicated by + the data inside the buffer. + @retval EFI_OUT_OF_RESOURCES A allocation needed to process the request failed. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsSetInfo ( + IN EFI_FILE_PROTOCOL *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + BOOTMON_FS_FILE *File; + EFI_FILE_INFO *Info; + EFI_FILE_SYSTEM_INFO *SystemInfo; + + if ((This == NULL) || + (InformationType == NULL) || + (Buffer == NULL) ) { + return EFI_INVALID_PARAMETER; + } + + File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (File->Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { + Info = Buffer; + if (Info->Size < (SIZE_OF_EFI_FILE_INFO + StrSize (Info->FileName))) { + return EFI_INVALID_PARAMETER; + } + if (BufferSize < Info->Size) { + return EFI_BAD_BUFFER_SIZE; + } + return (SetFileInfo (File->Instance, File, Info)); + } + + // + // The only writable field in the other two information types + // (i.e. EFI_FILE_SYSTEM_INFO and EFI_FILE_SYSTEM_VOLUME_LABEL) is the + // filesystem volume label. This can be retrieved with GetInfo, but it is + // hard-coded into this driver, not stored on media. + // + + if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { + SystemInfo = Buffer; + if (SystemInfo->Size < + (SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (SystemInfo->VolumeLabel))) { + return EFI_INVALID_PARAMETER; + } + if (BufferSize < SystemInfo->Size) { + return EFI_BAD_BUFFER_SIZE; + } + return EFI_WRITE_PROTECTED; + } + + if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) { + return EFI_WRITE_PROTECTED; + } + + return EFI_UNSUPPORTED; +} + +EFIAPI +EFI_STATUS +BootMonFsReadDirectory ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + BOOTMON_FS_INSTANCE *Instance; + BOOTMON_FS_FILE *RootFile; + BOOTMON_FS_FILE *File; + EFI_FILE_INFO *Info; + UINTN NameSize; + UINTN ResultSize; + EFI_STATUS Status; + UINTN Index; + + RootFile = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (RootFile == NULL) { + return EFI_INVALID_PARAMETER; + } + + Instance = RootFile->Instance; + Status = BootMonGetFileFromPosition (Instance, RootFile->Position, &File); + if (EFI_ERROR (Status)) { + // No more file + *BufferSize = 0; + return EFI_SUCCESS; + } + + NameSize = AsciiStrLen (File->HwDescription.Footer.Filename) + 1; + ResultSize = SIZE_OF_EFI_FILE_INFO + (NameSize * sizeof (CHAR16)); + if (*BufferSize < ResultSize) { + *BufferSize = ResultSize; + return EFI_BUFFER_TOO_SMALL; + } + + // Zero out the structure + Info = Buffer; + ZeroMem (Info, ResultSize); + + // Fill in the structure + Info->Size = ResultSize; + Info->FileSize = BootMonFsGetImageLength (File); + Info->PhysicalSize = BootMonFsGetPhysicalSize (File); + for (Index = 0; Index < NameSize; Index++) { + Info->FileName[Index] = File->HwDescription.Footer.Filename[Index]; + } + + *BufferSize = ResultSize; + RootFile->Position++; + + return EFI_SUCCESS; +} + +EFIAPI +EFI_STATUS +BootMonFsFlushDirectory ( + IN EFI_FILE_PROTOCOL *This + ) +{ + BOOTMON_FS_FILE *RootFile; + LIST_ENTRY *ListFiles; + LIST_ENTRY *Link; + BOOTMON_FS_FILE *File; + + RootFile = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (RootFile == NULL) { + return EFI_INVALID_PARAMETER; + } + + ListFiles = &RootFile->Link; + + if (IsListEmpty (ListFiles)) { + return EFI_SUCCESS; + } + + // + // Flush all the files that need to be flushed + // + + // Go through all the list of files to flush them + for (Link = GetFirstNode (ListFiles); + !IsNull (ListFiles, Link); + Link = GetNextNode (ListFiles, Link) + ) + { + File = BOOTMON_FS_FILE_FROM_LINK_THIS (Link); + File->File.Flush (&File->File); + } + + return EFI_SUCCESS; +} diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c new file mode 100644 index 000000000000..a1150856f6ba --- /dev/null +++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c @@ -0,0 +1,529 @@ +/** @file +* +* Copyright (c) 2012-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 +#include +#include +#include +#include + +#include +#include + +#include "BootMonFsInternal.h" + +EFI_DEVICE_PATH* mBootMonFsSupportedDevicePaths; +LIST_ENTRY mInstances; + +EFI_FILE_PROTOCOL mBootMonFsRootTemplate = { + EFI_FILE_PROTOCOL_REVISION, + BootMonFsOpenFile, + BootMonFsCloseFile, + BootMonFsDeleteFail, + BootMonFsReadDirectory, + BootMonFsWriteFile, + BootMonFsGetPositionUnsupported, // UEFI Spec: GetPosition not valid on dirs + BootMonFsSetDirPosition, + BootMonFsGetInfo, + BootMonFsSetInfo, + BootMonFsFlushDirectory +}; + +EFI_FILE_PROTOCOL mBootMonFsFileTemplate = { + EFI_FILE_PROTOCOL_REVISION, + BootMonFsOpenFile, + BootMonFsCloseFile, + BootMonFsDelete, + BootMonFsReadFile, + BootMonFsWriteFile, + BootMonFsGetPosition, + BootMonFsSetPosition, + BootMonFsGetInfo, + BootMonFsSetInfo, + BootMonFsFlushFile +}; + +/** + Search for a file given its name coded in Ascii. + + When searching through the files of the volume, if a file is currently not + open, its name was written on the media and is kept in RAM in the + "HwDescription.Footer.Filename[]" field of the file's description. + + If a file is currently open, its name might not have been written on the + media yet, and as the "HwDescription" is a mirror in RAM of what is on the + media the "HwDescription.Footer.Filename[]" might be outdated. In that case, + the up to date name of the file is stored in the "Info" field of the file's + description. + + @param[in] Instance Pointer to the description of the volume in which + the file has to be search for. + @param[in] AsciiFileName Name of the file. + + @param[out] File Pointer to the description of the file if the + file was found. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. + +**/ +EFI_STATUS +BootMonGetFileFromAsciiFileName ( + IN BOOTMON_FS_INSTANCE *Instance, + IN CHAR8* AsciiFileName, + OUT BOOTMON_FS_FILE **File + ) +{ + LIST_ENTRY *Entry; + BOOTMON_FS_FILE *FileEntry; + CHAR8 OpenFileAsciiFileName[MAX_NAME_LENGTH]; + CHAR8 *AsciiFileNameToCompare; + + // Go through all the files in the list and return the file handle + for (Entry = GetFirstNode (&Instance->RootFile->Link); + !IsNull (&Instance->RootFile->Link, Entry); + Entry = GetNextNode (&Instance->RootFile->Link, Entry) + ) + { + FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (Entry); + if (FileEntry->Info != NULL) { + UnicodeStrToAsciiStrS (FileEntry->Info->FileName, OpenFileAsciiFileName, + MAX_NAME_LENGTH); + AsciiFileNameToCompare = OpenFileAsciiFileName; + } else { + AsciiFileNameToCompare = FileEntry->HwDescription.Footer.Filename; + } + + if (AsciiStrCmp (AsciiFileNameToCompare, AsciiFileName) == 0) { + *File = FileEntry; + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +BootMonGetFileFromPosition ( + IN BOOTMON_FS_INSTANCE *Instance, + IN UINTN Position, + OUT BOOTMON_FS_FILE **File + ) +{ + LIST_ENTRY *Entry; + BOOTMON_FS_FILE *FileEntry; + + // Go through all the files in the list and return the file handle + for (Entry = GetFirstNode (&Instance->RootFile->Link); + !IsNull (&Instance->RootFile->Link, Entry) && (&Instance->RootFile->Link != Entry); + Entry = GetNextNode (&Instance->RootFile->Link, Entry) + ) + { + if (Position == 0) { + FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (Entry); + *File = FileEntry; + return EFI_SUCCESS; + } + Position--; + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +BootMonFsCreateFile ( + IN BOOTMON_FS_INSTANCE *Instance, + OUT BOOTMON_FS_FILE **File + ) +{ + BOOTMON_FS_FILE *NewFile; + + NewFile = (BOOTMON_FS_FILE*)AllocateZeroPool (sizeof (BOOTMON_FS_FILE)); + if (NewFile == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + NewFile->Signature = BOOTMON_FS_FILE_SIGNATURE; + InitializeListHead (&NewFile->Link); + InitializeListHead (&NewFile->RegionToFlushLink); + NewFile->Instance = Instance; + + // If the created file is the root file then create a directory EFI_FILE_PROTOCOL + if (Instance->RootFile == *File) { + CopyMem (&NewFile->File, &mBootMonFsRootTemplate, sizeof (mBootMonFsRootTemplate)); + } else { + CopyMem (&NewFile->File, &mBootMonFsFileTemplate, sizeof (mBootMonFsFileTemplate)); + } + *File = NewFile; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SupportedDevicePathsInit ( + VOID + ) +{ + EFI_STATUS Status; + CHAR16* DevicePathListStr; + CHAR16* DevicePathStr; + CHAR16* NextDevicePathStr; + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; + EFI_DEVICE_PATH_PROTOCOL *Instance; + + Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); + ASSERT_EFI_ERROR (Status); + + // Initialize Variable + DevicePathListStr = (CHAR16*)PcdGetPtr (PcdBootMonFsSupportedDevicePaths); + mBootMonFsSupportedDevicePaths = NULL; + + // Extract the Device Path instances from the multi-device path string + while ((DevicePathListStr != NULL) && (DevicePathListStr[0] != L'\0')) { + NextDevicePathStr = StrStr (DevicePathListStr, L";"); + if (NextDevicePathStr == NULL) { + DevicePathStr = DevicePathListStr; + DevicePathListStr = NULL; + } else { + DevicePathStr = (CHAR16*)AllocateCopyPool ((NextDevicePathStr - DevicePathListStr + 1) * sizeof (CHAR16), DevicePathListStr); + if (DevicePathStr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + *(DevicePathStr + (NextDevicePathStr - DevicePathListStr)) = L'\0'; + DevicePathListStr = NextDevicePathStr; + if (DevicePathListStr[0] == L';') { + DevicePathListStr++; + } + } + + Instance = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (DevicePathStr); + ASSERT (Instance != NULL); + mBootMonFsSupportedDevicePaths = AppendDevicePathInstance (mBootMonFsSupportedDevicePaths, Instance); + + if (NextDevicePathStr != NULL) { + FreePool (DevicePathStr); + } + FreePool (Instance); + } + + if (mBootMonFsSupportedDevicePaths == NULL) { + return EFI_UNSUPPORTED; + } else { + return EFI_SUCCESS; + } +} + +EFI_STATUS +EFIAPI +BootMonFsDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL + ) +{ + EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePathProtocol; + EFI_DEVICE_PATH_PROTOCOL *SupportedDevicePath; + EFI_DEVICE_PATH_PROTOCOL *SupportedDevicePaths; + EFI_STATUS Status; + UINTN Size1; + UINTN Size2; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &DiskIo, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + gImageHandle, + ControllerHandle + ); + + // Check that BlockIo protocol instance exists + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + NULL, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Check if a DevicePath is attached to the handle + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **)&DevicePathProtocol, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Check if the Device Path is the one which contains the Boot Monitor File System + Size1 = GetDevicePathSize (DevicePathProtocol); + + // Go through the list of Device Path Instances + Status = EFI_UNSUPPORTED; + SupportedDevicePaths = mBootMonFsSupportedDevicePaths; + while (SupportedDevicePaths != NULL) { + SupportedDevicePath = GetNextDevicePathInstance (&SupportedDevicePaths, &Size2); + + if ((Size1 == Size2) && (CompareMem (DevicePathProtocol, SupportedDevicePath, Size1) == 0)) { + // The Device Path is supported + Status = EFI_SUCCESS; + break; + } + } + + gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid, gImageHandle, ControllerHandle); + return Status; +} + +EFI_STATUS +EFIAPI +BootMonFsDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL + ) +{ + BOOTMON_FS_INSTANCE *Instance; + EFI_STATUS Status; + UINTN VolumeNameSize; + EFI_FILE_INFO *Info; + + Instance = AllocateZeroPool (sizeof (BOOTMON_FS_INSTANCE)); + if (Instance == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // Initialize the BlockIo of the Instance + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **)&(Instance->BlockIo), + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + (VOID **)&(Instance->DiskIo), + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // Initialize the attributes of the Instance + // + Instance->Signature = BOOTMON_FS_SIGNATURE; + Instance->ControllerHandle = ControllerHandle; + Instance->Media = Instance->BlockIo->Media; + Instance->Binding = DriverBinding; + + // Initialize the Simple File System Protocol + Instance->Fs.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION; + Instance->Fs.OpenVolume = OpenBootMonFsOpenVolume; + + // Volume name + L' ' + '2' digit number + VolumeNameSize = StrSize (BOOTMON_FS_VOLUME_LABEL) + (3 * sizeof (CHAR16)); + + // Initialize FileSystem Information + Instance->FsInfo.Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + VolumeNameSize; + Instance->FsInfo.BlockSize = Instance->Media->BlockSize; + Instance->FsInfo.ReadOnly = FALSE; + Instance->FsInfo.VolumeSize = + Instance->Media->BlockSize * (Instance->Media->LastBlock - Instance->Media->LowestAlignedLba); + CopyMem (Instance->FsInfo.VolumeLabel, BOOTMON_FS_VOLUME_LABEL, StrSize (BOOTMON_FS_VOLUME_LABEL)); + + // Initialize the root file + Status = BootMonFsCreateFile (Instance, &Instance->RootFile); + if (EFI_ERROR (Status)) { + goto Error; + } + + Info = AllocateZeroPool (sizeof (EFI_FILE_INFO)); + if (Info == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + Instance->RootFile->Info = Info; + + // Initialize the DevicePath of the Instance + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **)&(Instance->DevicePath), + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // Install the Simple File System Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, &Instance->Fs, + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + InsertTailList (&mInstances, &Instance->Link); + + return EFI_SUCCESS; + +Error: + + if (Instance->RootFile != NULL) { + if (Instance->RootFile->Info != NULL) { + FreePool (Instance->RootFile->Info); + } + FreePool (Instance->RootFile); + } + FreePool (Instance); + + return Status; +} + + +EFI_STATUS +EFIAPI +BootMonFsDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +{ + BOOTMON_FS_INSTANCE *Instance; + LIST_ENTRY *Link; + EFI_STATUS Status; + BOOLEAN InstanceFound; + + // Find instance from ControllerHandle. + Instance = NULL; + InstanceFound = FALSE; + // For each instance in mInstances: + for (Link = GetFirstNode (&mInstances); !IsNull (&mInstances, Link); Link = GetNextNode (&mInstances, Link)) { + Instance = BOOTMON_FS_FROM_LINK (Link); + + if (Instance->ControllerHandle == ControllerHandle) { + InstanceFound = TRUE; + break; + } + } + ASSERT (InstanceFound == TRUE); + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + DriverBinding->ImageHandle, + ControllerHandle); + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + DriverBinding->ImageHandle, + ControllerHandle); + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + DriverBinding->ImageHandle, + ControllerHandle); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, &Instance->Fs, + NULL); + + FreePool (Instance->RootFile->Info); + FreePool (Instance->RootFile); + FreePool (Instance); + + return Status; +} + +// +// Simple Network Protocol Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL mBootMonFsDriverBinding = { + BootMonFsDriverSupported, + BootMonFsDriverStart, + BootMonFsDriverStop, + 0xa, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +BootMonFsEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + InitializeListHead (&mInstances); + + // Initialize the list of Device Paths that could support BootMonFs + Status = SupportedDevicePathsInit (); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiDriverBindingProtocolGuid, &mBootMonFsDriverBinding, + NULL + ); + ASSERT_EFI_ERROR (Status); + } else { + DEBUG((EFI_D_ERROR,"Warning: No Device Paths supporting BootMonFs have been defined in the PCD.\n")); + } + + return Status; +} diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsHw.h b/Platform/ARM/Drivers/BootMonFs/BootMonFsHw.h new file mode 100644 index 000000000000..c1bef755aea0 --- /dev/null +++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsHw.h @@ -0,0 +1,57 @@ +/** @file +* +* Copyright (c) 2012-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. +* +**/ + +#ifndef __BOOTMON_FS_HW_H__ +#define __BOOTMON_FS_HW_H__ + +#define MAX_NAME_LENGTH 32 + +#define HW_IMAGE_FOOTER_SIGNATURE_1 0x464C5348 +#define HW_IMAGE_FOOTER_SIGNATURE_2 0x464F4F54 + +#define HW_IMAGE_FOOTER_VERSION 1 +#define HW_IMAGE_FOOTER_OFFSET 92 + +#define HW_IMAGE_FOOTER_VERSION2 2 +#define HW_IMAGE_FOOTER_OFFSET2 96 + +typedef struct { + CHAR8 Filename[MAX_NAME_LENGTH]; + UINT32 Offset; + UINT32 Version; + UINT32 FooterSignature1; + UINT32 FooterSignature2; +} HW_IMAGE_FOOTER; + +#define HW_IMAGE_DESCRIPTION_REGION_MAX 4 + +// This structure is located at the end of a block when a file is present +typedef struct { + UINT32 EntryPoint; + UINT32 Attributes; + UINT32 RegionCount; + struct { + UINT32 LoadAddress; + UINT32 Size; + UINT32 Offset; + UINT32 Checksum; + } Region[HW_IMAGE_DESCRIPTION_REGION_MAX]; + UINT32 BlockStart; + UINT32 BlockEnd; + UINT32 FooterChecksum; + + HW_IMAGE_FOOTER Footer; +} HW_IMAGE_DESCRIPTION; + +#endif diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsImages.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsImages.c new file mode 100644 index 000000000000..346c360292eb --- /dev/null +++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsImages.c @@ -0,0 +1,222 @@ +/** @file +* +* Copyright (c) 2012-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 +#include +#include +#include + +#include + +#include "BootMonFsInternal.h" + +UINT32 +BootMonFsChecksum ( + IN VOID *Data, + IN UINT32 Size + ) +{ + UINT32 *Ptr; + UINT32 Word; + UINT32 Checksum; + + ASSERT (Size % 4 == 0); + + Checksum = 0; + Ptr = (UINT32*)Data; + + while (Size > 0) { + Word = *Ptr++; + Size -= 4; + + if (Word > ~Checksum) { + Checksum++; + } + + Checksum += Word; + } + + return ~Checksum; +} + +EFI_STATUS +BootMonFsComputeFooterChecksum ( + IN OUT HW_IMAGE_DESCRIPTION *Footer + ) +{ + HW_IMAGE_DESCRIPTION *Description; + UINT32 Index; + + Footer->Attributes = 1; + + Description = AllocateZeroPool (sizeof (HW_IMAGE_DESCRIPTION)); + if (Description == NULL) { + DEBUG ((DEBUG_ERROR, "BootMonFsComputeFooterChecksum: Unable to allocate memory.\n")); + return EFI_OUT_OF_RESOURCES; + } + + // Copy over to temporary shim + CopyMem (Description, Footer, sizeof (HW_IMAGE_DESCRIPTION)); + + // BootMon doesn't checksum the previous checksum + Description->FooterChecksum = 0; + + // Blank out regions which aren't being used. + for (Index = Footer->RegionCount; Index < HW_IMAGE_DESCRIPTION_REGION_MAX; Index++) { + Description->Region[Index].Checksum = 0; + Description->Region[Index].LoadAddress = 0; + Description->Region[Index].Offset = 0; + Description->Region[Index].Size = 0; + } + + // Compute the checksum + Footer->FooterChecksum = BootMonFsChecksum (Description, sizeof (HW_IMAGE_DESCRIPTION)); + + FreePool (Description); + + return EFI_SUCCESS; +} + +BOOLEAN +BootMonFsIsImageValid ( + IN HW_IMAGE_DESCRIPTION *Desc, + IN EFI_LBA Lba + ) +{ + EFI_STATUS Status; + HW_IMAGE_FOOTER *Footer; + UINT32 Checksum; + + Footer = &Desc->Footer; + + // Check that the verification bytes are present + if ((Footer->FooterSignature1 != HW_IMAGE_FOOTER_SIGNATURE_1) || + (Footer->FooterSignature2 != HW_IMAGE_FOOTER_SIGNATURE_2)) { + return FALSE; + } + + if (Footer->Version == HW_IMAGE_FOOTER_VERSION) { + if (Footer->Offset != HW_IMAGE_FOOTER_OFFSET) { + return FALSE; + } + } else if (Footer->Version == HW_IMAGE_FOOTER_VERSION2) { + if (Footer->Offset != HW_IMAGE_FOOTER_OFFSET2) { + return FALSE; + } + } else { + return FALSE; + } + + Checksum = Desc->FooterChecksum; + Status = BootMonFsComputeFooterChecksum (Desc); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Warning: failed to compute checksum for image '%a'\n", Desc->Footer.Filename)); + } + + if (Desc->FooterChecksum != Checksum) { + DEBUG ((DEBUG_ERROR, "Warning: image '%a' checksum mismatch.\n", Desc->Footer.Filename)); + } + + if ((Desc->BlockEnd != Lba) || (Desc->BlockStart > Desc->BlockEnd)) { + return FALSE; + } + + return TRUE; +} + +STATIC +EFI_STATUS +BootMonFsDiscoverNextImage ( + IN BOOTMON_FS_INSTANCE *Instance, + IN OUT EFI_LBA *LbaStart, + IN OUT BOOTMON_FS_FILE *File + ) +{ + EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_LBA CurrentLba; + UINT64 DescOffset; + EFI_STATUS Status; + + DiskIo = Instance->DiskIo; + + CurrentLba = *LbaStart; + + // Look for images in the rest of this block + while (CurrentLba <= Instance->Media->LastBlock) { + // Work out the byte offset into media of the image description in this block + // If present, the image description is at the very end of the block. + DescOffset = ((CurrentLba + 1) * Instance->Media->BlockSize) - sizeof (HW_IMAGE_DESCRIPTION); + + // Read the image description from media + Status = DiskIo->ReadDisk (DiskIo, + Instance->Media->MediaId, + DescOffset, + sizeof (HW_IMAGE_DESCRIPTION), + &File->HwDescription + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // If we found a valid image description... + if (BootMonFsIsImageValid (&File->HwDescription, (CurrentLba - Instance->Media->LowestAlignedLba))) { + DEBUG ((EFI_D_ERROR, "Found image: %a in block %d.\n", + &(File->HwDescription.Footer.Filename), + (UINTN)(CurrentLba - Instance->Media->LowestAlignedLba) + )); + File->HwDescAddress = DescOffset; + + *LbaStart = CurrentLba + 1; + return EFI_SUCCESS; + } else { + CurrentLba++; + } + } + + *LbaStart = CurrentLba; + return EFI_NOT_FOUND; +} + +EFI_STATUS +BootMonFsInitialize ( + IN BOOTMON_FS_INSTANCE *Instance + ) +{ + EFI_STATUS Status; + EFI_LBA Lba; + UINT32 ImageCount; + BOOTMON_FS_FILE *NewFile; + + ImageCount = 0; + Lba = 0; + + while (1) { + Status = BootMonFsCreateFile (Instance, &NewFile); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = BootMonFsDiscoverNextImage (Instance, &Lba, NewFile); + if (EFI_ERROR (Status)) { + // Free NewFile allocated by BootMonFsCreateFile () + FreePool (NewFile); + break; + } + InsertTailList (&Instance->RootFile->Link, &NewFile->Link); + ImageCount++; + } + + Instance->Initialized = TRUE; + return EFI_SUCCESS; +} diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsInternal.h b/Platform/ARM/Drivers/BootMonFs/BootMonFsInternal.h new file mode 100644 index 000000000000..c0c6599cb707 --- /dev/null +++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsInternal.h @@ -0,0 +1,101 @@ +/** @file +* +* Copyright (c) 2012-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. +* +**/ + +#ifndef __BOOTMONFS_INTERNAL_H__ +#define __BOOTMONFS_INTERNAL_H__ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "BootMonFsHw.h" + +#define BOOTMON_FS_VOLUME_LABEL L"NOR Flash" + +typedef struct _BOOTMON_FS_INSTANCE BOOTMON_FS_INSTANCE; + +typedef struct { + LIST_ENTRY Link; + VOID* Buffer; + UINTN Size; + UINT64 Offset; // Offset from the start of the file +} BOOTMON_FS_FILE_REGION; + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + BOOTMON_FS_INSTANCE *Instance; + + UINTN HwDescAddress; + HW_IMAGE_DESCRIPTION HwDescription; + + EFI_FILE_PROTOCOL File; + + // + // The following fields are relevant only if the file is open. + // + + EFI_FILE_INFO *Info; + UINT64 Position; + // If the file needs to be flushed then this list contain the memory + // buffer that creates this file + LIST_ENTRY RegionToFlushLink; + UINT64 OpenMode; +} BOOTMON_FS_FILE; + +#define BOOTMON_FS_FILE_SIGNATURE SIGNATURE_32('b', 'o', 't', 'f') +#define BOOTMON_FS_FILE_FROM_FILE_THIS(a) CR (a, BOOTMON_FS_FILE, File, BOOTMON_FS_FILE_SIGNATURE) +#define BOOTMON_FS_FILE_FROM_LINK_THIS(a) CR (a, BOOTMON_FS_FILE, Link, BOOTMON_FS_FILE_SIGNATURE) + +struct _BOOTMON_FS_INSTANCE { + UINT32 Signature; + EFI_HANDLE ControllerHandle; + + LIST_ENTRY Link; + + EFI_DRIVER_BINDING_PROTOCOL *Binding; + EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_IO_MEDIA *Media; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL Fs; + + EFI_FILE_SYSTEM_INFO FsInfo; + CHAR16 Label[20]; + + BOOTMON_FS_FILE *RootFile; // All the other files are linked to this root + BOOLEAN Initialized; +}; + +#define BOOTMON_FS_SIGNATURE SIGNATURE_32('b', 'o', 't', 'm') +#define BOOTMON_FS_FROM_FS_THIS(a) CR (a, BOOTMON_FS_INSTANCE, Fs, BOOTMON_FS_SIGNATURE) +#define BOOTMON_FS_FROM_LINK(a) CR (a, BOOTMON_FS_INSTANCE, Link, BOOTMON_FS_SIGNATURE) + +#include "BootMonFsApi.h" + +#endif + diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsOpenClose.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsOpenClose.c new file mode 100644 index 000000000000..ae10055255ff --- /dev/null +++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsOpenClose.c @@ -0,0 +1,795 @@ +/** @file +* +* Copyright (c) 2012-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 "BootMonFsInternal.h" + +// Clear a file's image description on storage media: +// UEFI allows you to seek past the end of a file, a subsequent write will grow +// the file. It does not specify how space between the former end of the file +// and the beginning of the write should be filled. It's therefore possible that +// BootMonFs metadata, that comes after the end of a file, could be left there +// and wrongly detected by BootMonFsImageInBlock. +STATIC +EFI_STATUS +InvalidateImageDescription ( + IN BOOTMON_FS_FILE *File + ) +{ + EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + UINT32 MediaId; + VOID *Buffer; + EFI_STATUS Status; + + DiskIo = File->Instance->DiskIo; + BlockIo = File->Instance->BlockIo; + MediaId = BlockIo->Media->MediaId; + + Buffer = AllocateZeroPool (sizeof (HW_IMAGE_DESCRIPTION)); + + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = DiskIo->WriteDisk (DiskIo, + MediaId, + File->HwDescAddress, + sizeof (HW_IMAGE_DESCRIPTION), + Buffer + ); + + FreePool(Buffer); + + return Status; +} + +/** + Write the description of a file to storage media. + + This function uses DiskIo to write to the media, so call BlockIo->FlushBlocks() + after calling it to ensure the data are written on the media. + + @param[in] File Description of the file whose description on the + storage media has to be updated. + @param[in] FileName Name of the file. Its length is assumed to be + lower than MAX_NAME_LENGTH. + @param[in] DataSize Number of data bytes of the file. + @param[in] FileStart File's starting position on media. FileStart must + be aligned to the media's block size. + + @retval EFI_WRITE_PROTECTED The device cannot be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing + the write operation. + +**/ +STATIC +EFI_STATUS +WriteFileDescription ( + IN BOOTMON_FS_FILE *File, + IN CHAR8 *FileName, + IN UINT32 DataSize, + IN UINT64 FileStart + ) +{ + EFI_STATUS Status; + EFI_DISK_IO_PROTOCOL *DiskIo; + UINTN BlockSize; + UINT32 FileSize; + HW_IMAGE_DESCRIPTION *Description; + + DiskIo = File->Instance->DiskIo; + BlockSize = File->Instance->BlockIo->Media->BlockSize; + ASSERT (FileStart % BlockSize == 0); + + // + // Construct the file description + // + + FileSize = DataSize + sizeof (HW_IMAGE_DESCRIPTION); + Description = &File->HwDescription; + Description->Attributes = 1; + Description->BlockStart = FileStart / BlockSize; + Description->BlockEnd = Description->BlockStart + (FileSize / BlockSize); + AsciiStrCpyS (Description->Footer.Filename, + sizeof Description->Footer.Filename, FileName); + +#ifdef MDE_CPU_ARM + Description->Footer.Offset = HW_IMAGE_FOOTER_OFFSET; + Description->Footer.Version = HW_IMAGE_FOOTER_VERSION; +#else + Description->Footer.Offset = HW_IMAGE_FOOTER_OFFSET2; + Description->Footer.Version = HW_IMAGE_FOOTER_VERSION2; +#endif + Description->Footer.FooterSignature1 = HW_IMAGE_FOOTER_SIGNATURE_1; + Description->Footer.FooterSignature2 = HW_IMAGE_FOOTER_SIGNATURE_2; + Description->RegionCount = 1; + Description->Region[0].Checksum = 0; + Description->Region[0].Offset = Description->BlockStart * BlockSize; + Description->Region[0].Size = DataSize; + + Status = BootMonFsComputeFooterChecksum (Description); + if (EFI_ERROR (Status)) { + return Status; + } + + File->HwDescAddress = ((Description->BlockEnd + 1) * BlockSize) - sizeof (HW_IMAGE_DESCRIPTION); + + // Update the file description on the media + Status = DiskIo->WriteDisk ( + DiskIo, + File->Instance->Media->MediaId, + File->HwDescAddress, + sizeof (HW_IMAGE_DESCRIPTION), + Description + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +// Find a space on media for a file that has not yet been flushed to disk. +// Just returns the first space that's big enough. +// This function could easily be adapted to: +// - Find space for moving an existing file that has outgrown its space +// (We do not currently move files, just return EFI_VOLUME_FULL) +// - Find space for a fragment of a file that has outgrown its space +// (We do not currently fragment files - it's not clear whether fragmentation +// is actually part of BootMonFs as there is no spec) +// - Be more clever about finding space (choosing the largest or smallest +// suitable space) +// Parameters: +// File - the new (not yet flushed) file for which we need to find space. +// FileStart - the position on media of the file (in bytes). +STATIC +EFI_STATUS +BootMonFsFindSpaceForNewFile ( + IN BOOTMON_FS_FILE *File, + IN UINT64 FileSize, + OUT UINT64 *FileStart + ) +{ + LIST_ENTRY *FileLink; + BOOTMON_FS_FILE *RootFile; + BOOTMON_FS_FILE *FileEntry; + UINTN BlockSize; + EFI_BLOCK_IO_MEDIA *Media; + + Media = File->Instance->BlockIo->Media; + BlockSize = Media->BlockSize; + RootFile = File->Instance->RootFile; + + // This function must only be called for file which has not been flushed into + // Flash yet + ASSERT (File->HwDescription.RegionCount == 0); + + *FileStart = 0; + // Go through all the files in the list + for (FileLink = GetFirstNode (&RootFile->Link); + !IsNull (&RootFile->Link, FileLink); + FileLink = GetNextNode (&RootFile->Link, FileLink) + ) + { + FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (FileLink); + // Skip files that aren't on disk yet + if (FileEntry->HwDescription.RegionCount == 0) { + continue; + } + + // If the free space preceding the file is big enough to contain the new + // file then use it! + if (((FileEntry->HwDescription.BlockStart * BlockSize) - *FileStart) + >= FileSize) { + // The file list must be in disk-order + RemoveEntryList (&File->Link); + File->Link.BackLink = FileLink->BackLink; + File->Link.ForwardLink = FileLink; + FileLink->BackLink->ForwardLink = &File->Link; + FileLink->BackLink = &File->Link; + + return EFI_SUCCESS; + } else { + *FileStart = (FileEntry->HwDescription.BlockEnd + 1) * BlockSize; + } + } + // See if there's space after the last file + if ((((Media->LastBlock + 1) * BlockSize) - *FileStart) >= FileSize) { + return EFI_SUCCESS; + } else { + return EFI_VOLUME_FULL; + } +} + +// Free the resources in the file's Region list. +STATIC +VOID +FreeFileRegions ( + IN BOOTMON_FS_FILE *File + ) +{ + LIST_ENTRY *RegionToFlushLink; + BOOTMON_FS_FILE_REGION *Region; + + RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink); + while (!IsNull (&File->RegionToFlushLink, RegionToFlushLink)) { + // Repeatedly remove the first node from the list and free its resources. + Region = (BOOTMON_FS_FILE_REGION *) RegionToFlushLink; + RemoveEntryList (RegionToFlushLink); + FreePool (Region->Buffer); + FreePool (Region); + + RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink); + } +} + +/** + Flush all modified data associated with a file to a device. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the + file handle to flush. + + @retval EFI_SUCCESS The data was flushed. + @retval EFI_ACCESS_DENIED The file was opened read-only. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_FULL The volume is full. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to flush the data. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsFlushFile ( + IN EFI_FILE_PROTOCOL *This + ) +{ + EFI_STATUS Status; + BOOTMON_FS_INSTANCE *Instance; + EFI_FILE_INFO *Info; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_IO_MEDIA *Media; + EFI_DISK_IO_PROTOCOL *DiskIo; + UINTN BlockSize; + CHAR8 AsciiFileName[MAX_NAME_LENGTH]; + LIST_ENTRY *RegionToFlushLink; + BOOTMON_FS_FILE *File; + BOOTMON_FS_FILE *NextFile; + BOOTMON_FS_FILE_REGION *Region; + LIST_ENTRY *FileLink; + UINTN CurrentPhysicalSize; + UINT64 FileStart; + UINT64 FileEnd; + UINT64 RegionStart; + UINT64 RegionEnd; + UINT64 NewDataSize; + UINT64 NewFileSize; + UINT64 EndOfAppendSpace; + BOOLEAN HasSpace; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (File->Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (File->OpenMode == EFI_FILE_MODE_READ) { + return EFI_ACCESS_DENIED; + } + + Instance = File->Instance; + Info = File->Info; + BlockIo = Instance->BlockIo; + Media = BlockIo->Media; + DiskIo = Instance->DiskIo; + BlockSize = Media->BlockSize; + + UnicodeStrToAsciiStrS (Info->FileName, AsciiFileName, MAX_NAME_LENGTH); + + // If the file doesn't exist then find a space for it + if (File->HwDescription.RegionCount == 0) { + Status = BootMonFsFindSpaceForNewFile ( + File, + Info->FileSize + sizeof (HW_IMAGE_DESCRIPTION), + &FileStart + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + FileStart = File->HwDescription.BlockStart * BlockSize; + } + // FileEnd is the current NOR address of the end of the file's data + FileEnd = FileStart + File->HwDescription.Region[0].Size; + + for (RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink); + !IsNull (&File->RegionToFlushLink, RegionToFlushLink); + RegionToFlushLink = GetNextNode (&File->RegionToFlushLink, RegionToFlushLink) + ) + { + Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink; + if (Region->Size == 0) { + continue; + } + + // RegionStart and RegionEnd are the the intended NOR address of the + // start and end of the region + RegionStart = FileStart + Region->Offset; + RegionEnd = RegionStart + Region->Size; + + if (RegionEnd < FileEnd) { + // Handle regions representing edits to existing portions of the file + // Write the region data straight into the file + Status = DiskIo->WriteDisk (DiskIo, + Media->MediaId, + RegionStart, + Region->Size, + Region->Buffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + // Handle regions representing appends to the file + // + // Note: Since seeking past the end of the file with SetPosition() is + // valid, it's possible there will be a gap between the current end of + // the file and the beginning of the new region. Since the UEFI spec + // says nothing about this case (except "a subsequent write would grow + // the file"), we just leave garbage in the gap. + + // Check if there is space to append the new region + HasSpace = FALSE; + NewDataSize = RegionEnd - FileStart; + NewFileSize = NewDataSize + sizeof (HW_IMAGE_DESCRIPTION); + CurrentPhysicalSize = BootMonFsGetPhysicalSize (File); + if (NewFileSize <= CurrentPhysicalSize) { + HasSpace = TRUE; + } else { + // Get the File Description for the next file + FileLink = GetNextNode (&Instance->RootFile->Link, &File->Link); + if (!IsNull (&Instance->RootFile->Link, FileLink)) { + NextFile = BOOTMON_FS_FILE_FROM_LINK_THIS (FileLink); + + // If there is space between the beginning of the current file and the + // beginning of the next file then use it + EndOfAppendSpace = NextFile->HwDescription.BlockStart * BlockSize; + } else { + // We are flushing the last file. + EndOfAppendSpace = (Media->LastBlock + 1) * BlockSize; + } + if (EndOfAppendSpace - FileStart >= NewFileSize) { + HasSpace = TRUE; + } + } + + if (HasSpace == TRUE) { + // Invalidate the current image description of the file if any. + if (File->HwDescAddress != 0) { + Status = InvalidateImageDescription (File); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // Write the new file data + Status = DiskIo->WriteDisk ( + DiskIo, + Media->MediaId, + RegionStart, + Region->Size, + Region->Buffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WriteFileDescription (File, AsciiFileName, NewDataSize, FileStart); + if (EFI_ERROR (Status)) { + return Status; + } + + } else { + // There isn't a space for the file. + // Options here are to move the file or fragment it. However as files + // may represent boot images at fixed positions, these options will + // break booting if the bootloader doesn't use BootMonFs to find the + // image. + + return EFI_VOLUME_FULL; + } + } + } + + FreeFileRegions (File); + Info->PhysicalSize = BootMonFsGetPhysicalSize (File); + + if ((AsciiStrCmp (AsciiFileName, File->HwDescription.Footer.Filename) != 0) || + (Info->FileSize != File->HwDescription.Region[0].Size) ) { + Status = WriteFileDescription (File, AsciiFileName, Info->FileSize, FileStart); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // Flush DiskIo Buffers (see UEFI Spec 12.7 - DiskIo buffers are flushed by + // calling FlushBlocks on the same device's BlockIo). + BlockIo->FlushBlocks (BlockIo); + + return EFI_SUCCESS; +} + +/** + Close a specified file handle. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to close. + + @retval EFI_SUCCESS The file was closed. + @retval EFI_INVALID_PARAMETER The parameter "This" is NULL or is not an open + file handle. + +**/ +EFIAPI +EFI_STATUS +BootMonFsCloseFile ( + IN EFI_FILE_PROTOCOL *This + ) +{ + BOOTMON_FS_FILE *File; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (File->Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + // In the case of a file and not the root directory + if (This != &File->Instance->RootFile->File) { + This->Flush (This); + FreePool (File->Info); + File->Info = NULL; + } + + return EFI_SUCCESS; +} + +/** + Open a file on the boot monitor file system. + + The boot monitor file system does not allow for sub-directories. There is only + one directory, the root one. On any attempt to create a directory, the function + returns in error with the EFI_WRITE_PROTECTED error code. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is + the file handle to source location. + @param[out] NewHandle A pointer to the location to return the opened + handle for the new file. + @param[in] FileName The Null-terminated string of the name of the file + to be opened. + @param[in] OpenMode The mode to open the file : Read or Read/Write or + Read/Write/Create + @param[in] Attributes Attributes of the file in case of a file creation + + @retval EFI_SUCCESS The file was open. + @retval EFI_NOT_FOUND The specified file could not be found or the specified + directory in which to create a file could not be found. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_WRITE_PROTECTED Attempt to create a directory. This is not possible + with the Boot Monitor file system. + @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsOpenFile ( + IN EFI_FILE_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + BOOTMON_FS_FILE *Directory; + BOOTMON_FS_FILE *File; + BOOTMON_FS_INSTANCE *Instance; + CHAR8 *Buf; + CHAR16 *Path; + CHAR16 *Separator; + CHAR8 *AsciiFileName; + EFI_FILE_INFO *Info; + UINTN AsciiFileNameSize; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Directory = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (Directory->Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((FileName == NULL) || (NewHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // The only valid modes are read, read/write, and read/write/create + // + if ( (OpenMode != EFI_FILE_MODE_READ) && + (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE)) && + (OpenMode != (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE)) ) { + return EFI_INVALID_PARAMETER; + } + + Instance = Directory->Instance; + + // + // If the instance has not been initialized yet then do it ... + // + if (!Instance->Initialized) { + Status = BootMonFsInitialize (Instance); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Copy the file path to be able to work on it. We do not want to + // modify the input file name string "FileName". + // + Buf = AllocateCopyPool (StrSize (FileName), FileName); + if (Buf == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Path = (CHAR16*)Buf; + AsciiFileName = NULL; + Info = NULL; + + // + // Handle single periods, double periods and convert forward slashes '/' + // to backward '\' ones. Does not handle a '.' at the beginning of the + // path for the time being. + // + if (PathCleanUpDirectories (Path) == NULL) { + Status = EFI_INVALID_PARAMETER; + goto Error; + } + + // + // Detect if the first component of the path refers to a directory. + // This is done to return the correct error code when trying to + // access or create a directory other than the root directory. + // + + // + // Search for the '\\' sequence and if found return in error + // with the EFI_INVALID_PARAMETER error code. ere in the path. + // + if (StrStr (Path, L"\\\\") != NULL) { + Status = EFI_INVALID_PARAMETER; + goto Error; + } + // + // Get rid of the leading '\' if any. + // + Path += (Path[0] == L'\\'); + + // + // Look for a '\' in the file path. If one is found then + // the first component of the path refers to a directory + // that is not the root directory. + // + Separator = StrStr (Path, L"\\"); + if (Separator != NULL) { + // + // In the case '\' and a creation, return + // EFI_WRITE_PROTECTED if this is for a directory + // creation, EFI_INVALID_PARAMETER otherwise. + // + if ((*(Separator + 1) == '\0') && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)) { + if (Attributes & EFI_FILE_DIRECTORY) { + Status = EFI_WRITE_PROTECTED; + } else { + Status = EFI_INVALID_PARAMETER; + } + } else { + // + // Attempt to open a file or a directory that is not in the + // root directory or to open without creation a directory + // located in the root directory, returns EFI_NOT_FOUND. + // + Status = EFI_NOT_FOUND; + } + goto Error; + } + + // + // BootMonFs interface requires ASCII filenames + // + AsciiFileNameSize = StrLen (Path) + 1; + if (AsciiFileNameSize > MAX_NAME_LENGTH) { + AsciiFileNameSize = MAX_NAME_LENGTH; + } + AsciiFileName = AllocatePool (AsciiFileNameSize); + if (AsciiFileName == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + UnicodeStrToAsciiStrS (Path, AsciiFileName, AsciiFileNameSize); + + if ((AsciiFileName[0] == '\0') || + (AsciiFileName[0] == '.' ) ) { + // + // Opening the root directory + // + + *NewHandle = &Instance->RootFile->File; + Instance->RootFile->Position = 0; + Status = EFI_SUCCESS; + } else { + + if ((OpenMode & EFI_FILE_MODE_CREATE) && + (Attributes & EFI_FILE_DIRECTORY) ) { + Status = EFI_WRITE_PROTECTED; + goto Error; + } + + // + // Allocate a buffer to store the characteristics of the file while the + // file is open. We allocate the maximum size to not have to reallocate + // if the file name is changed. + // + Info = AllocateZeroPool ( + SIZE_OF_EFI_FILE_INFO + (sizeof (CHAR16) * MAX_NAME_LENGTH)); + if (Info == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + + // + // Open or create a file in the root directory. + // + + Status = BootMonGetFileFromAsciiFileName (Instance, AsciiFileName, &File); + if (Status == EFI_NOT_FOUND) { + if ((OpenMode & EFI_FILE_MODE_CREATE) == 0) { + goto Error; + } + + Status = BootMonFsCreateFile (Instance, &File); + if (EFI_ERROR (Status)) { + goto Error; + } + InsertHeadList (&Instance->RootFile->Link, &File->Link); + Info->Attribute = Attributes; + } else { + // + // File already open, not supported yet. + // + if (File->Info != NULL) { + Status = EFI_UNSUPPORTED; + goto Error; + } + } + + Info->FileSize = BootMonFsGetImageLength (File); + Info->PhysicalSize = BootMonFsGetPhysicalSize (File); + AsciiStrToUnicodeStrS (AsciiFileName, Info->FileName, MAX_NAME_LENGTH); + + File->Info = Info; + Info = NULL; + File->Position = 0; + File->OpenMode = OpenMode; + + *NewHandle = &File->File; + } + +Error: + + FreePool (Buf); + if (AsciiFileName != NULL) { + FreePool (AsciiFileName); + } + if (Info != NULL) { + FreePool (Info); + } + + return Status; +} + +// Delete() for the root directory's EFI_FILE_PROTOCOL instance +EFIAPI +EFI_STATUS +BootMonFsDeleteFail ( + IN EFI_FILE_PROTOCOL *This + ) +{ + This->Close(This); + // You can't delete the root directory + return EFI_WARN_DELETE_FAILURE; +} + +/** + Close and delete a file from the boot monitor file system. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file + handle to delete. + + @retval EFI_SUCCESS The file was closed and deleted. + @retval EFI_INVALID_PARAMETER The parameter "This" is NULL or is not an open + file handle. + @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted. + +**/ +EFIAPI +EFI_STATUS +BootMonFsDelete ( + IN EFI_FILE_PROTOCOL *This + ) +{ + EFI_STATUS Status; + BOOTMON_FS_FILE *File; + LIST_ENTRY *RegionToFlushLink; + BOOTMON_FS_FILE_REGION *Region; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (File->Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!IsListEmpty (&File->RegionToFlushLink)) { + // Free the entries from the Buffer List + RegionToFlushLink = GetFirstNode (&File->RegionToFlushLink); + do { + Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink; + + // + // Get next element of the list before deleting the region description + // that contain the LIST_ENTRY structure. + // + RegionToFlushLink = RemoveEntryList (RegionToFlushLink); + + // Free the buffers + FreePool (Region->Buffer); + FreePool (Region); + } while (!IsListEmpty (&File->RegionToFlushLink)); + } + + // If (RegionCount is greater than 0) then the file already exists + if (File->HwDescription.RegionCount > 0) { + // Invalidate the last Block + Status = InvalidateImageDescription (File); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return EFI_WARN_DELETE_FAILURE; + } + } + + // Remove the entry from the list + RemoveEntryList (&File->Link); + FreePool (File->Info); + FreePool (File); + + return EFI_SUCCESS; +} diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsReadWrite.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsReadWrite.c new file mode 100644 index 000000000000..f8124e95ac0c --- /dev/null +++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsReadWrite.c @@ -0,0 +1,259 @@ +/** @file +* +* Copyright (c) 2012-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 +#include +#include +#include +#include + +#include "BootMonFsInternal.h" + +/** + Read data from an open file. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that + is the file handle to read data from. + @param[in out] BufferSize On input, the size of the Buffer. On output, the + amount of data returned in Buffer. In both cases, + the size is measured in bytes. + @param[out] Buffer The buffer into which the data is read. + + @retval EFI_SUCCESS The data was read. + @retval EFI_DEVICE_ERROR On entry, the current file position is + beyond the end of the file, or the device + reported an error while performing the read + operation. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsReadFile ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + BOOTMON_FS_INSTANCE *Instance; + BOOTMON_FS_FILE *File; + EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_BLOCK_IO_MEDIA *Media; + UINT64 FileStart; + EFI_STATUS Status; + UINTN RemainingFileSize; + + if ((This == NULL) || + (BufferSize == NULL) || + (Buffer == NULL) ) { + return EFI_INVALID_PARAMETER; + } + File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (File->Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + // Ensure the file has been written in Flash before reading it. + // This keeps the code simple and avoids having to manage a non-flushed file. + BootMonFsFlushFile (This); + + Instance = File->Instance; + DiskIo = Instance->DiskIo; + Media = Instance->Media; + FileStart = (Media->LowestAlignedLba + File->HwDescription.BlockStart) * Media->BlockSize; + + if (File->Position >= File->Info->FileSize) { + // The entire file has been read or the position has been + // set past the end of the file. + *BufferSize = 0; + if (File->Position > File->Info->FileSize) { + return EFI_DEVICE_ERROR; + } else { + return EFI_SUCCESS; + } + } + + // This driver assumes that the entire file is in region 0. + RemainingFileSize = File->Info->FileSize - File->Position; + + // If read would go past end of file, truncate the read + if (*BufferSize > RemainingFileSize) { + *BufferSize = RemainingFileSize; + } + + Status = DiskIo->ReadDisk ( + DiskIo, + Media->MediaId, + FileStart + File->Position, + *BufferSize, + Buffer + ); + if (EFI_ERROR (Status)) { + *BufferSize = 0; + } + + File->Position += *BufferSize; + + return Status; +} + +/** + Write data to an open file. + + The data is not written to the flash yet. It will be written when the file + will be either read, closed or flushed. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that + is the file handle to write data to. + @param[in out] BufferSize On input, the size of the Buffer. On output, the + size of the data actually written. In both cases, + the size is measured in bytes. + @param[in] Buffer The buffer of data to write. + + @retval EFI_SUCCESS The data was written. + @retval EFI_ACCESS_DENIED The file was opened read only. + @retval EFI_OUT_OF_RESOURCES Unable to allocate the buffer to store the + data to write. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsWriteFile ( + IN EFI_FILE_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + BOOTMON_FS_FILE *File; + BOOTMON_FS_FILE_REGION *Region; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (File->Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (File->OpenMode == EFI_FILE_MODE_READ) { + return EFI_ACCESS_DENIED; + } + + // Allocate and initialize the memory region + Region = (BOOTMON_FS_FILE_REGION*)AllocateZeroPool (sizeof (BOOTMON_FS_FILE_REGION)); + if (Region == NULL) { + *BufferSize = 0; + return EFI_OUT_OF_RESOURCES; + } + + Region->Buffer = AllocateCopyPool (*BufferSize, Buffer); + if (Region->Buffer == NULL) { + *BufferSize = 0; + FreePool (Region); + return EFI_OUT_OF_RESOURCES; + } + + Region->Size = *BufferSize; + Region->Offset = File->Position; + + InsertTailList (&File->RegionToFlushLink, &Region->Link); + + File->Position += *BufferSize; + + if (File->Position > File->Info->FileSize) { + File->Info->FileSize = File->Position; + } + + return EFI_SUCCESS; +} + +/** + Set a file's current position. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is + the file handle to set the requested position on. + @param[in] Position The byte position from the start of the file to set. + + @retval EFI_SUCCESS The position was set. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsSetPosition ( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ) +{ + BOOTMON_FS_FILE *File; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (File->Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // UEFI Spec section 12.5: + // "Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to + // be set to the end of the file." + // + if (Position == 0xFFFFFFFFFFFFFFFF) { + Position = File->Info->FileSize; + } + + File->Position = Position; + + return EFI_SUCCESS; +} + +/** + Return a file's current position. + + @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is + the file handle to get the current position on. + @param[out] Position The address to return the file's current position value. + + @retval EFI_SUCCESS The position was returned. + @retval EFI_INVALID_PARAMETER At least one of the parameters is invalid. + +**/ +EFIAPI +EFI_STATUS +BootMonFsGetPosition ( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ) +{ + BOOTMON_FS_FILE *File; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + File = BOOTMON_FS_FILE_FROM_FILE_THIS (This); + if (File->Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Position == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Position = File->Position; + + return EFI_SUCCESS; +} diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsUnsupported.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsUnsupported.c new file mode 100644 index 000000000000..4ecc4ea008ea --- /dev/null +++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsUnsupported.c @@ -0,0 +1,37 @@ +/** @file +* +* Copyright (c) 2012-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 "BootMonFsInternal.h" + +EFIAPI +EFI_STATUS +BootMonFsSetPositionUnsupported ( + IN EFI_FILE_PROTOCOL *This, + IN UINT64 Position + ) +{ + ASSERT(0); + return EFI_UNSUPPORTED; +} + +EFIAPI +EFI_STATUS +BootMonFsGetPositionUnsupported ( + IN EFI_FILE_PROTOCOL *This, + OUT UINT64 *Position + ) +{ + ASSERT(0); + return EFI_UNSUPPORTED; +} diff --git a/Platform/ARM/Include/Guid/BootMonFsFileInfo.h b/Platform/ARM/Include/Guid/BootMonFsFileInfo.h new file mode 100644 index 000000000000..c4d805c14f0e --- /dev/null +++ b/Platform/ARM/Include/Guid/BootMonFsFileInfo.h @@ -0,0 +1,47 @@ +/** @file +* +* 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. +* +**/ + +#ifndef __BOOTMON_FS_FILE_INFO_H__ +#define __BOOTMON_FS_FILE_INFO_H__ + +#define BOOTMON_FS_FILE_INFO_ID \ + { \ + 0x41e26b9c, 0xada6, 0x45b3, {0x80, 0x8e, 0x23, 0x57, 0xa3, 0x5b, 0x60, 0xd6 } \ + } + +// From BootMonFS header file +#define BOOTMONFS_IMAGE_DESCRIPTION_REGION_MAX 4 + +typedef struct { + // The size of the structure. + UINT64 Size; + + // Subset of properties stored in the file meta-data. + UINT32 EntryPoint; + UINT32 RegionCount; + struct { + UINT32 LoadAddress; + UINT32 Size; + UINT32 Offset; + UINT32 Checksum; + } Region[BOOTMONFS_IMAGE_DESCRIPTION_REGION_MAX]; + +} BOOTMON_FS_FILE_INFO; + +#define SIZE_OF_BOOTMON_FS_FILE_INFO \ + OFFSET_OF (BOOTMON_FS_FILE_INFO, Region[BOOTMONFS_IMAGE_DESCRIPTION_REGION_MAX - 1].Checksum) + +extern EFI_GUID gArmBootMonFsFileInfoGuid; + +#endif // __BOOTMON_FS_FILE_INFO_H__ diff --git a/Platform/ARM/Include/Library/ArmShellCmdLib.h b/Platform/ARM/Include/Library/ArmShellCmdLib.h new file mode 100644 index 000000000000..eb31cd405338 --- /dev/null +++ b/Platform/ARM/Include/Library/ArmShellCmdLib.h @@ -0,0 +1,57 @@ +/** @file +* +* Definitions for the Dynamic Shell command library +* +* Copyright (C) 2014, ARM Ltd +* +* 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 _ARM_SHELL_CMD_LIB_H_ +#define _ARM_SHELL_CMD_LIB_H_ + +/** + + Initialize and Install EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL for RunAxf command. + + @param[in] ImageHandle Handle the protocol should be attached to. + + @retval EFI_SUCCESS The command has been installed successfully. + + @retval EFI_UNSUPPORTED Help for the command failed to initialise. + + @return Status code returned by InstallProtocolInterface + Boot Service function. + +**/ +EFI_STATUS +ShellDynCmdRunAxfInstall ( + IN EFI_HANDLE ImageHandle + ); + +/** + + Uninstall the RunAxf Command + + @param[in] ImageHandle Handle of the device where the protocol should have + been installed. + + @retval EFI_SUCCESS The device has been un-initialized successfully. + + @return Status code returned by UninstallProtocolInterface + Boot Service function. + +**/ +EFI_STATUS +ShellDynCmdRunAxfUninstall ( + IN EFI_HANDLE ImageHandle + ); + +#endif // _ARM_SHELL_CMD_LIB_H_ diff --git a/Platform/ARM/JunoPkg/ArmJuno.dsc b/Platform/ARM/JunoPkg/ArmJuno.dsc index 80a5ef631ce9..3cbacb35dae3 100644 --- a/Platform/ARM/JunoPkg/ArmJuno.dsc +++ b/Platform/ARM/JunoPkg/ArmJuno.dsc @@ -160,7 +160,7 @@ [PcdsFixedAtBuild.common] gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|24 # List of Device Paths that support BootMonFs - gArmPlatformTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)" + gArmBootMonFsTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)" # # ARM OS Loader diff --git a/Platform/ARM/JunoPkg/ArmJuno.fdf b/Platform/ARM/JunoPkg/ArmJuno.fdf index bb78e1fa8589..04d58323d130 100644 --- a/Platform/ARM/JunoPkg/ArmJuno.fdf +++ b/Platform/ARM/JunoPkg/ArmJuno.fdf @@ -135,7 +135,7 @@ [FV.FvMain] INF ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf # Versatile Express FileSystem - INF ArmPlatformPkg/FileSystem/BootMonFs/BootMonFs.inf + INF Platform/ARM/Drivers/BootMonFs/BootMonFs.inf # # FAT filesystem + GPT/MBR partitioning diff --git a/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf index b215a3bc882d..70175c2d2405 100644 --- a/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf +++ b/Platform/ARM/JunoPkg/Drivers/ArmJunoDxe/ArmJunoDxe.inf @@ -28,6 +28,7 @@ [Packages] EmbeddedPkg/EmbeddedPkg.dec MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec + Platform/ARM/ARM.dec Platform/ARM/JunoPkg/ArmJuno.dec [LibraryClasses] diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.c b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.c new file mode 100644 index 000000000000..67bbb9e86334 --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.c @@ -0,0 +1,95 @@ +/** @file +* +* 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. +* +**/ + +#include + +#include +#include +#include +#include + +#include "ArmShellCmdRunAxf.h" + +EFI_HANDLE gRunAxfHiiHandle = NULL; + +#define RUNAXF_HII_GUID \ + { \ + 0xf5a6413b, 0x78d5, 0x448e, { 0xa2, 0x15, 0x22, 0x82, 0x8e, 0xbc, 0x61, 0x61 } \ + } + +EFI_GUID gRunAxfHiiGuid = RUNAXF_HII_GUID; + +static EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mShellDynCmdProtocolRunAxf = { + L"runaxf", // *CommandName + ShellDynCmdRunAxfHandler, // Handler + ShellDynCmdRunAxfGetHelp // GetHelp +}; + +EFI_STATUS +ShellDynCmdRunAxfInstall ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + // Register our shell command + Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle, + &gEfiShellDynamicCommandProtocolGuid, + &mShellDynCmdProtocolRunAxf, + NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // Load the manual page for our command + // + // 3rd parameter 'HII strings array' must be name of .uni strings file + // followed by 'Strings', e.g. mycommands.uni must be specified as + // 'mycommandsStrings' because the build Autogen process defines this as a + // string array for the strings in your .uni file. Examine your Build folder + // under your package's DEBUG folder and you will find it defined in a + // xxxStrDefs.h file. + // + gRunAxfHiiHandle = HiiAddPackages (&gRunAxfHiiGuid, ImageHandle, + ArmShellCmdRunAxfStrings, NULL); + if (gRunAxfHiiHandle == NULL) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +ShellDynCmdRunAxfUninstall ( + IN EFI_HANDLE ImageHandle + ) +{ + + EFI_STATUS Status; + + if (gRunAxfHiiHandle != NULL) { + HiiRemovePackages (gRunAxfHiiHandle); + } + + Status = gBS->UninstallMultipleProtocolInterfaces (ImageHandle, + &gEfiShellDynamicCommandProtocolGuid, + &mShellDynCmdProtocolRunAxf, + NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.h b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.h new file mode 100644 index 000000000000..2708b53cc172 --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.h @@ -0,0 +1,83 @@ +/** @file +* +* 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. +* +**/ + +#ifndef __ARM_SHELL_CMD_RUNAXF__ +#define __ARM_SHELL_CMD_RUNAXF__ + +#include +#include + +#include +#include +#include + +extern EFI_GUID gRunAxfHiiGuid; +extern EFI_HANDLE gRunAxfHiiHandle; +extern EFI_HANDLE gRunAxfImageHandle; + +// List of data segments to load to memory from AXF/ELF file. +typedef struct { + LIST_ENTRY Link; // This attribute must be the first entry of this + // structure (to avoid pointer computation) + UINTN MemOffset; // Where the data should go, Dest + UINTN FileOffset; // Where the data is from, Src + BOOLEAN Zeroes; // A section of Zeroes. Like .bss in ELF + UINTN Length; // Number of bytes. +} RUNAXF_LOAD_LIST; + + +/** + This is the shell command handler function pointer callback type. 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 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 EFI_SUCCESS The operation was successful. + @return other The operation failed. +**/ +SHELL_STATUS +EFIAPI +ShellDynCmdRunAxfHandler ( + 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 command help handler function pointer callback type. This + function is responsible for displaying help information for the associated + command. + + @param[in] This The instance of the + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] Language The pointer to the language string to use. + + @return string Pool allocated help string, must be freed by + caller. +**/ +CHAR16* +EFIAPI +ShellDynCmdRunAxfGetHelp ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN CONST CHAR8 *Language + ); + +#endif //__ARM_SHELL_CMD_RUNAXF__ diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf new file mode 100644 index 000000000000..8473b0fa90d2 --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf @@ -0,0 +1,54 @@ +## @file +# +# 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. +# +## + +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = ArmShellCmdRunAxf + FILE_GUID = 676a0e7c-2e16-43e8-b49c-d82a1f9e24df + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmShellCmdRunAxfLib + +[Sources.common] + ArmShellCmdRunAxf.c + ArmShellCmdRunAxf.uni + RunAxf.c + BootMonFsLoader.h + BootMonFsLoader.c + ElfLoader.h + ElfLoader.c + # ELF definitions taken from BaseTools + elf32.h + elf64.h + elf_common.h + +[Packages] + ArmPkg/ArmPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Platform/ARM/ARM.dec + ShellPkg/ShellPkg.dec + +[LibraryClasses] + ArmLib + BaseLib + DebugLib + HiiLib + ShellLib + +[Protocols] + gEfiShellDynamicCommandProtocolGuid + +[Guids] + gArmBootMonFsFileInfoGuid diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.uni b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.uni new file mode 100644 index 000000000000..6b7296079175 --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.uni @@ -0,0 +1,68 @@ +// *++ +// +// 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: +// +// RunAxfStrings.uni +// +// Abstract: +// +// String definitions for the Shell 'runaxf' command +// +// Revision History: +// +// --*/ + +/=# + +#langdef en-US "English" + +#string STR_RUNAXF_BAD_FILE #language en-US "File type not supported\n" +#string STR_RUNAXF_BAD_ARCH #language en-US "Architecture not supported\n" +#string STR_RUNAXF_INVALID_ARG #language en-US "Invalid argument(s)\n" +#string STR_RUNAXF_FILE_NOT_FOUND #language en-US "File not found : %s\n" +#string STR_RUNAXF_NO_MEM #language en-US "Out of Memory\n" +#string STR_RUNAXF_READ_FAIL #language en-US "Failed to read file\n" + +#string STR_RUNAXF_ELFMAGIC #language en-US "Wrong magic number. The file is either not an ELF binary or it is corrupted.\n" +#string STR_RUNAXF_ELFNOTEXEC #language en-US "Wrong ELF file type, expected an executable file.\n" +#string STR_RUNAXF_ELFNOPROG #language en-US "No program header table found in ELF file.\n" +#string STR_RUNAXF_ELFWRONGCLASS #language en-US "Invalid ELF Class type.\n" +#string STR_RUNAXF_ELFBADFORMAT #language en-US "ELF file format is incorrect (filesize > memorysize).\n" +#string STR_RUNAXF_ELFBADHEADER #language en-US "Invalid ELF header.\n" +#string STR_RUNAXF_ELFFAILSEG #language en-US "Failed to load segment from ELF file.\n +#string STR_RUNAXF_ELFNOSEG #language en-US "The ELF file must have at least 1 loadable segment.\n" + +#string STR_RUNAXF_ELFWRONGCLASS_32 #language en-US "Wrong file class, expected 32-bit ELF file.\n" +#string STR_RUNAXF_ELFWRONGCLASS_64 #language en-US "Wrong file class, expected 64-bit ELF file.\n" +#string STR_RUNAXF_ELFWRONGMACH_32 #language en-US "Wrong machine type, expected ARM.\n" +#string STR_RUNAXF_ELFWRONGMACH_64 #language en-US "Wrong machine type, expected AARCH64.\n" + +#string STR_GET_HELP_RUNAXF #language en-US "" +".TH runaxf 0 "load and execute AXF binary"\r\n" +".SH NAME\r\n" +"Loads and executes ARM Executable File (AXF).\r\n" +".SH SYNOPSIS\r\n" +"runaxf file\r\n" +".SH OPTIONS\r\n" +"file AXF binary to load and execute.\r\n" +".SH DESCRIPTION\r\n" +"Loads and executes ARM Executable File (AXF). This function is not expected to return.\r\n" + +".SH RETURNVALUES\r\n" +"SHELL_DEVICE_ERROR The operation failed to complete.\r\n" +"SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly formatted or its value was out of bounds.\r\n" +"SHELL_UNSUPPORTED The action as requested was unsupported.\r\n" +"SHELL_OUT_OF_RESOURCES There was insufficient free space for the request to be completed.\r\n" +".SH EXAMPLES\r\n" +" fs0:\> runaxf file.axf\r\n" diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.c b/Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.c new file mode 100644 index 000000000000..0bce037dcb08 --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.c @@ -0,0 +1,154 @@ +/** @file +* +* 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. +* +**/ + +#include +#include +#include +#include +#include + +#include +#include // EFI_FILE_HANDLE + +#include "ArmShellCmdRunAxf.h" +#include "BootMonFsLoader.h" + +/** + Check that loading the file is supported. + + Not all information is checked, only the properties that matters to us in + our simplified loader. + + BootMonFS file properties is not in a file header but in the file-system + metadata, so we need to pass a handle to the file to allow access to the + information. + + @param[in] FileHandle Handle of the file to check. + + @retval EFI_SUCCESS on success. + @retval EFI_INVALID_PARAMETER if the header is invalid. + @retval EFI_UNSUPPORTED if the file type/platform is not supported. +**/ +EFI_STATUS +BootMonFsCheckFile ( + IN CONST EFI_FILE_HANDLE FileHandle + ) +{ + EFI_STATUS Status; + BOOTMON_FS_FILE_INFO Info; + UINTN InfoSize; + UINTN Index; + + ASSERT (FileHandle != NULL); + + // Try to load the file information as BootMonFS executable. + InfoSize = sizeof (Info); + // Get BootMon File info and see if it gives us what we need to load the file. + Status = FileHandle->GetInfo (FileHandle, &gArmBootMonFsFileInfoGuid, + &InfoSize, &Info); + + if (!EFI_ERROR (Status)) { + // Check the values return to see if they look reasonable. + // Do we have a good entrypoint and at least one good load region? + // We assume here that we cannot load to address 0x0. + if ((Info.Size == 0) || (Info.EntryPoint == 0) || (Info.RegionCount == 0) || + (Info.RegionCount > BOOTMONFS_IMAGE_DESCRIPTION_REGION_MAX)) { + // The file does not seem to be of the right type. + Status = EFI_UNSUPPORTED; + } else { + // Check load regions. We just check for valid numbers, we dont do the + // checksums. Info.Offset can be zero if it loads from the start of the + // file. + for (Index = 0; Index < Info.RegionCount; Index++) { + if ((Info.Region[Index].LoadAddress == 0) || (Info.Region[Index].Size == 0)) { + Status = EFI_UNSUPPORTED; + break; + } + } + } + } + + return Status; +} + +/** + Load a binary file from BootMonFS. + + @param[in] FileHandle Handle of the file to load. + + @param[in] FileData Address of the file data in memory. + + @param[out] EntryPoint Will be filled with the ELF entry point address. + + @param[out] ImageSize Will be filled with the file size in memory. This + will effectively be equal to the sum of the load + region sizes. + + This function assumes the file is valid and supported as checked with + BootMonFsCheckFile(). + + @retval EFI_SUCCESS on success. + @retval EFI_INVALID_PARAMETER if the file is invalid. +**/ +EFI_STATUS +BootMonFsLoadFile ( + IN CONST EFI_FILE_HANDLE FileHandle, + IN CONST VOID *FileData, + OUT VOID **EntryPoint, + OUT LIST_ENTRY *LoadList + ) +{ + EFI_STATUS Status; + BOOTMON_FS_FILE_INFO Info; + UINTN InfoSize; + UINTN Index; + UINTN ImageSize; + RUNAXF_LOAD_LIST *LoadNode; + + ASSERT (FileHandle != NULL); + ASSERT (FileData != NULL); + ASSERT (EntryPoint != NULL); + ASSERT (LoadList != NULL); + + ImageSize = 0; + + InfoSize = sizeof (Info); + Status = FileHandle->GetInfo (FileHandle, &gArmBootMonFsFileInfoGuid, + &InfoSize, &Info); + + if (!EFI_ERROR (Status)) { + *EntryPoint = (VOID*)((UINTN)Info.EntryPoint); + // Load all the regions to run-time memory + for (Index = 0; Index < Info.RegionCount; Index++) { + LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST)); + if (LoadNode == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + + LoadNode->MemOffset = (UINTN)Info.Region[Index].LoadAddress; + LoadNode->FileOffset = (UINTN)FileData + Info.Region[Index].Offset; + LoadNode->Length = (UINTN)Info.Region[Index].Size; + InsertTailList (LoadList, &LoadNode->Link); + + ImageSize += LoadNode->Length; + } + } + + if ((!EFI_ERROR (Status)) && (ImageSize == 0)) { + Status = EFI_INVALID_PARAMETER; + } + + return Status; +} diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.h b/Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.h new file mode 100644 index 000000000000..de3c0adcd11f --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/BootMonFsLoader.h @@ -0,0 +1,66 @@ +/** @file +* +* 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. +* +**/ + +#ifndef __BOOTMONFS_LOADER_H__ +#define __BOOTMONFS_LOADER_H__ + +/** + Check that loading the file is supported. + + Not all information is checked, only the properties that matters to us in + our simplified loader. + + BootMonFS file properties is not in a file header but in the file-system + metadata, so we need to pass a handle to the file to allow access to the + information. + + @param[in] FileHandle Handle of the file to check. + + @retval EFI_SUCCESS on success. + @retval EFI_INVALID_PARAMETER if the header is invalid. + @retval EFI_UNSUPPORTED if the file type/platform is not supported. +**/ +EFI_STATUS +BootMonFsCheckFile ( + IN CONST EFI_FILE_HANDLE FileHandle + ); + +/** + Load a binary file from BootMonFS. + + @param[in] FileHandle Handle of the file to load. + + @param[in] FileData Address of the file data in memory. + + @param[out] EntryPoint Will be filled with the ELF entry point address. + + @param[out] ImageSize Will be filled with the file size in memory. This + will effectively be equal to the sum of the load + region sizes. + + This function assumes the file is valid and supported as checked with + BootMonFsCheckFile(). + + @retval EFI_SUCCESS on success. + @retval EFI_INVALID_PARAMETER if the file is invalid. +**/ +EFI_STATUS +BootMonFsLoadFile ( + IN CONST EFI_FILE_HANDLE FileHandle, + IN CONST VOID *FileData, + OUT VOID **EntryPoint, + OUT LIST_ENTRY *LoadList + ); + +#endif // __BOOTMONFS_LOADER_H__ diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.c b/Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.c new file mode 100644 index 000000000000..6bb0d22de2fd --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.c @@ -0,0 +1,340 @@ +/** @file +* +* Copyright (c) 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 +#include +#include +#include +#include + +#include "ArmShellCmdRunAxf.h" +#include "ElfLoader.h" +#include "elf_common.h" +#include "elf32.h" +#include "elf64.h" + + +// Put the functions the #ifdef. We only use the appropriate one for the platform. +// This prevents 'defined but not used' compiler warning. +#ifdef MDE_CPU_ARM +STATIC +BOOLEAN +IsArmElf ( + IN CONST VOID *Buf + ) +{ + Elf32_Ehdr *Hdr = (Elf32_Ehdr*)Buf; + + if (Hdr->e_ident[EI_CLASS] != ELFCLASS32) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGCLASS_32), gRunAxfHiiHandle); + return FALSE; + } + + if (Hdr->e_machine != EM_ARM) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGMACH_32), gRunAxfHiiHandle); + return FALSE; + } + + // We don't currently check endianness of ELF data (hdr->e_ident[EI_DATA]) + + return TRUE; +} +#elif defined(MDE_CPU_AARCH64) +STATIC +BOOLEAN +IsAarch64Elf ( + IN CONST VOID *Buf + ) +{ + Elf64_Ehdr *Hdr = (Elf64_Ehdr*)Buf; + + if (Hdr->e_ident[EI_CLASS] != ELFCLASS64) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGCLASS_64), gRunAxfHiiHandle); + return FALSE; + } + + if (Hdr->e_machine != EM_AARCH64) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGMACH_64), gRunAxfHiiHandle); + return FALSE; + } + + // We don't currently check endianness of ELF data (hdr->e_ident[EI_DATA]) + + return TRUE; +} +#endif // MDE_CPU_ARM , MDE_CPU_AARCH64 + + +/** + Support checking 32 and 64bit as the header could be valid, we might just + not support loading it. +**/ +STATIC +EFI_STATUS +ElfCheckHeader ( + IN CONST VOID *Buf + ) +{ + Elf32_Ehdr *Hdr32 = (Elf32_Ehdr*)Buf; + + if (!IS_ELF (*Hdr32)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFMAGIC), gRunAxfHiiHandle); + return EFI_INVALID_PARAMETER; + } + + if (Hdr32->e_type != ET_EXEC) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFNOTEXEC), gRunAxfHiiHandle); + return EFI_INVALID_PARAMETER; + } + + if (Hdr32->e_ident[EI_CLASS] == ELFCLASS32) { + if ((Hdr32->e_phoff == 0) || (Hdr32->e_phentsize == 0) || (Hdr32->e_phnum == 0)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFNOPROG), gRunAxfHiiHandle); + return EFI_INVALID_PARAMETER; + } + + if (Hdr32->e_flags != 0) { + DEBUG ((EFI_D_INFO, "Warning: Wrong processor-specific flags, expected 0.\n")); + } + + DEBUG ((EFI_D_INFO, "Entry point addr: 0x%lx\n", Hdr32->e_entry)); + DEBUG ((EFI_D_INFO, "Start of program headers: 0x%lx\n", Hdr32->e_phoff)); + DEBUG ((EFI_D_INFO, "Size of 1 program header: %d\n", Hdr32->e_phentsize)); + DEBUG ((EFI_D_INFO, "Number of program headers: %d\n", Hdr32->e_phnum)); + } else if (Hdr32->e_ident[EI_CLASS] == ELFCLASS64) { + Elf64_Ehdr *Hdr64 = (Elf64_Ehdr*)Buf; + + if ((Hdr64->e_phoff == 0) || (Hdr64->e_phentsize == 0) || (Hdr64->e_phnum == 0)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFNOPROG), gRunAxfHiiHandle); + return EFI_INVALID_PARAMETER; + } + + if (Hdr64->e_flags != 0) { + DEBUG ((EFI_D_INFO, "Warning: Wrong processor-specific flags, expected 0.\n")); + } + + DEBUG ((EFI_D_INFO, "Entry point addr: 0x%lx\n", Hdr64->e_entry)); + DEBUG ((EFI_D_INFO, "Start of program headers: 0x%lx\n", Hdr64->e_phoff)); + DEBUG ((EFI_D_INFO, "Size of 1 program header: %d\n", Hdr64->e_phentsize)); + DEBUG ((EFI_D_INFO, "Number of program headers: %d\n", Hdr64->e_phnum)); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFWRONGCLASS), gRunAxfHiiHandle); + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + + +/** + Load an ELF segment into memory. + + This function assumes the ELF file is valid. + This function is meant to be called for PT_LOAD type segments only. +**/ +STATIC +EFI_STATUS +ElfLoadSegment ( + IN CONST VOID *ElfImage, + IN CONST VOID *PHdr, + IN LIST_ENTRY *LoadList + ) +{ + VOID *FileSegment; + VOID *MemSegment; + UINTN ExtraZeroes; + UINTN ExtraZeroesCount; + RUNAXF_LOAD_LIST *LoadNode; + +#ifdef MDE_CPU_ARM + Elf32_Phdr *ProgramHdr; + ProgramHdr = (Elf32_Phdr *)PHdr; +#elif defined(MDE_CPU_AARCH64) + Elf64_Phdr *ProgramHdr; + ProgramHdr = (Elf64_Phdr *)PHdr; +#endif + + ASSERT (ElfImage != NULL); + ASSERT (ProgramHdr != NULL); + + FileSegment = (VOID *)((UINTN)ElfImage + ProgramHdr->p_offset); + MemSegment = (VOID *)ProgramHdr->p_vaddr; + + // If the segment's memory size p_memsz is larger than the file size p_filesz, + // the "extra" bytes are defined to hold the value 0 and to follow the + // segment's initialised area. + // This is typically the case for the .bss segment. + // The file size may not be larger than the memory size. + if (ProgramHdr->p_filesz > ProgramHdr->p_memsz) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFBADFORMAT), gRunAxfHiiHandle); + return EFI_INVALID_PARAMETER; + } + + // Load the segment in memory. + if (ProgramHdr->p_filesz != 0) { + DEBUG ((EFI_D_INFO, "Loading segment from 0x%lx to 0x%lx (size = %ld)\n", + FileSegment, MemSegment, ProgramHdr->p_filesz)); + + LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST)); + if (LoadNode == NULL) { + return EFI_OUT_OF_RESOURCES; + } + LoadNode->MemOffset = (UINTN)MemSegment; + LoadNode->FileOffset = (UINTN)FileSegment; + LoadNode->Length = (UINTN)ProgramHdr->p_filesz; + InsertTailList (LoadList, &LoadNode->Link); + } + + ExtraZeroes = ((UINTN)MemSegment + ProgramHdr->p_filesz); + ExtraZeroesCount = ProgramHdr->p_memsz - ProgramHdr->p_filesz; + DEBUG ((EFI_D_INFO, "Completing segment with %d zero bytes.\n", ExtraZeroesCount)); + if (ExtraZeroesCount > 0) { + // Extra Node to add the Zeroes. + LoadNode = AllocateRuntimeZeroPool (sizeof (RUNAXF_LOAD_LIST)); + if (LoadNode == NULL) { + return EFI_OUT_OF_RESOURCES; + } + LoadNode->MemOffset = (UINTN)ExtraZeroes; + LoadNode->Zeroes = TRUE; + LoadNode->Length = ExtraZeroesCount; + InsertTailList (LoadList, &LoadNode->Link); + } + + return EFI_SUCCESS; +} + + +/** + Check that the ELF File Header is valid and Machine type supported. + + Not all information is checked in the ELF header, only the stuff that + matters to us in our simplified ELF loader. + + @param[in] ElfImage Address of the ELF file to check. + + @retval EFI_SUCCESS on success. + @retval EFI_INVALID_PARAMETER if the header is invalid. + @retval EFI_UNSUPPORTED if the file type/platform is not supported. +**/ +EFI_STATUS +ElfCheckFile ( + IN CONST VOID *ElfImage + ) +{ + EFI_STATUS Status; + + ASSERT (ElfImage != NULL); + + // Check that the ELF header is valid. + Status = ElfCheckHeader (ElfImage); + if (EFI_ERROR(Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFBADHEADER), gRunAxfHiiHandle); + return EFI_INVALID_PARAMETER; + } + +#ifdef MDE_CPU_ARM + if (IsArmElf (ElfImage)) { + return EFI_SUCCESS; + } +#elif defined(MDE_CPU_AARCH64) + if (IsAarch64Elf (ElfImage)) { + return EFI_SUCCESS; + } +#endif + + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_BAD_ARCH), gRunAxfHiiHandle); + return EFI_UNSUPPORTED; +} + + +/** + Load a ELF file. + + @param[in] ElfImage Address of the ELF file in memory. + + @param[out] EntryPoint Will be filled with the ELF entry point address. + + @param[out] ImageSize Will be filled with the ELF size in memory. This will + effectively be equal to the sum of the segments sizes. + + This functon assumes the header is valid and supported as checked with + ElfCheckFile(). + + @retval EFI_SUCCESS on success. + @retval EFI_INVALID_PARAMETER if the ELF file is invalid. +**/ +EFI_STATUS +ElfLoadFile ( + IN CONST VOID *ElfImage, + OUT VOID **EntryPoint, + OUT LIST_ENTRY *LoadList + ) +{ + EFI_STATUS Status; + UINT8 *ProgramHdr; + UINTN Index; + UINTN ImageSize; + +#ifdef MDE_CPU_ARM + Elf32_Ehdr *ElfHdr; + Elf32_Phdr *ProgramHdrPtr; + + ElfHdr = (Elf32_Ehdr*)ElfImage; +#elif defined(MDE_CPU_AARCH64) + Elf64_Ehdr *ElfHdr; + Elf64_Phdr *ProgramHdrPtr; + + ElfHdr = (Elf64_Ehdr*)ElfImage; +#endif + + ASSERT (ElfImage != NULL); + ASSERT (EntryPoint != NULL); + ASSERT (LoadList != NULL); + + ProgramHdr = (UINT8*)ElfImage + ElfHdr->e_phoff; + DEBUG ((EFI_D_INFO, "ELF program header entry : 0x%lx\n", ProgramHdr)); + + ImageSize = 0; + + // Load every loadable ELF segment into memory. + for (Index = 0; Index < ElfHdr->e_phnum; ++Index) { + +#ifdef MDE_CPU_ARM + ProgramHdrPtr = (Elf32_Phdr*)ProgramHdr; +#elif defined(MDE_CPU_AARCH64) + ProgramHdrPtr = (Elf64_Phdr*)ProgramHdr; +#endif + + // Only consider PT_LOAD type segments, ignore others. + if (ProgramHdrPtr->p_type == PT_LOAD) { + Status = ElfLoadSegment (ElfImage, (VOID *)ProgramHdrPtr, LoadList); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFFAILSEG), gRunAxfHiiHandle); + return EFI_INVALID_PARAMETER; + } + ImageSize += ProgramHdrPtr->p_memsz; + } + ProgramHdr += ElfHdr->e_phentsize; + } + + if (ImageSize == 0) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_ELFNOSEG), gRunAxfHiiHandle); + return EFI_INVALID_PARAMETER; + } + + // Return the entry point specified in the ELF header. + *EntryPoint = (void*)ElfHdr->e_entry; + + return EFI_SUCCESS; +} diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.h b/Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.h new file mode 100644 index 000000000000..7020a6c4e726 --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/ElfLoader.h @@ -0,0 +1,64 @@ +/** @file +* +* Copyright (c) 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. +* +**/ + +#ifndef ELF_LOADER_H +#define ELF_LOADER_H + +/** + Check that the ELF File Header is valid and Machine type supported. + + Not all information is checked in the ELF header, only the stuff that + matters to us in our simplified ELF loader. + + @param[in] ElfImage Address of the ELF file to check. + + @retval EFI_SUCCESS on success. + @retval EFI_INVALID_PARAMETER if the header is invalid. + @retval EFI_UNSUPPORTED if the file type/platform is not supported. +**/ +EFI_STATUS +ElfCheckFile ( + IN CONST VOID *ElfImage + ); + + +/** + Load a ELF file. + + @param[in] ElfImage Address of the ELF file in memory. + + @param[out] EntryPoint Will be filled with the ELF entry point address. + + @param[out] ImageSize Will be filled with the ELF size in memory. This will + effectively be equal to the sum of the segments sizes. + + This function assumes the header is valid and supported as checked with + ElfCheckFile(). + + NOTE: + - We don't currently take the segment permissions into account (indicated by + the program headers). It can be used to allocate pages with the right + read/write/exec permissions. + + @retval EFI_SUCCESS on success. + @retval EFI_INVALID_PARAMETER if the ELF file is invalid. +**/ +EFI_STATUS +ElfLoadFile ( + IN CONST VOID *ElfImage, + OUT VOID **EntryPoint, + OUT LIST_ENTRY *LoadList + ); + +#endif // ELF_LOADER_H diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c b/Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c new file mode 100644 index 000000000000..9f4fc780307d --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/RunAxf.c @@ -0,0 +1,395 @@ +/** @file +* +* Shell command for launching AXF files. +* +* Copyright (c) 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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ArmShellCmdRunAxf.h" +#include "ElfLoader.h" +#include "BootMonFsLoader.h" + +// Provide arguments to AXF? +typedef VOID (*ELF_ENTRYPOINT)(UINTN arg0, UINTN arg1, + UINTN arg2, UINTN arg3); + +STATIC +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; +} + + +STATIC +EFI_STATUS +PreparePlatformHardware ( + VOID + ) +{ + //Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called. + + // Clean before Disable else the Stack gets corrupted with old data. + ArmCleanDataCache (); + ArmDisableDataCache (); + // Invalidate all the entries that might have snuck in. + ArmInvalidateDataCache (); + + // Disable and invalidate the instruction cache + ArmDisableInstructionCache (); + ArmInvalidateInstructionCache (); + + // Turn off MMU + ArmDisableMmu(); + + return EFI_SUCCESS; +} + +// Process arguments to pass to AXF? +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {NULL, TypeMax} +}; + + +/** + This is the shell command handler function pointer callback type. 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 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 EFI_SUCCESS The operation was successful. + @return other The operation failed. +**/ +SHELL_STATUS +EFIAPI +ShellDynCmdRunAxfHandler ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN EFI_SYSTEM_TABLE *SystemTable, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, + IN EFI_SHELL_PROTOCOL *Shell + ) +{ + LIST_ENTRY *ParamPackage; + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + SHELL_FILE_HANDLE FileHandle; + ELF_ENTRYPOINT StartElf; + CONST CHAR16 *FileName; + EFI_FILE_INFO *Info; + UINTN FileSize; + VOID *FileData; + VOID *Entrypoint; + LIST_ENTRY LoadList; + LIST_ENTRY *Node; + LIST_ENTRY *NextNode; + RUNAXF_LOAD_LIST *LoadNode; + CHAR16 *TmpFileName; + CHAR16 *TmpChar16; + + + ShellStatus = SHELL_SUCCESS; + FileHandle = NULL; + FileData = NULL; + InitializeListHead (&LoadList); + + // Only install if they are not there yet? First time or every time? + // These can change if the shell exits and start again. + Status = gBS->InstallMultipleProtocolInterfaces (&gImageHandle, + &gEfiShellProtocolGuid, Shell, + &gEfiShellParametersProtocolGuid, ShellParameters, + NULL); + + if (EFI_ERROR (Status)) { + return SHELL_DEVICE_ERROR; + } + + // Update the protocols for the application library + Status = ShellInitialize (); + ASSERT_EFI_ERROR (Status); + // Add support to load AXF with optipnal args? + + // + // Process Command Line arguments + // + Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_INVALID_ARG), gRunAxfHiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // + // Check for "-?" + // + if ((ShellCommandLineGetFlag (ParamPackage, L"-?")) || + (ShellCommandLineGetRawValue (ParamPackage, 1) == NULL)) { + // + // We didn't get a file to load + // + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_INVALID_ARG), gRunAxfHiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + // For the moment we assume we only ever get one file to load with no arguments. + FileName = ShellCommandLineGetRawValue (ParamPackage, 1); + Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + // BootMonFS supports file extensions, but they are stripped by default + // when the NOR is programmed. + // Remove the file extension and try to open again. + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_FILE_NOT_FOUND), + gRunAxfHiiHandle, FileName); + // Go through the filename and remove file extension. Preserve the + // original name. + TmpFileName = AllocateCopyPool (StrSize (FileName), (VOID *)FileName); + if (TmpFileName != NULL) { + TmpChar16 = StrStr (TmpFileName, L"."); + if (TmpChar16 != NULL) { + *TmpChar16 = '\0'; + DEBUG((EFI_D_ERROR, "Trying to open file: %s\n", TmpFileName)); + Status = ShellOpenFileByName (TmpFileName, &FileHandle, + EFI_FILE_MODE_READ, 0); + } + FreePool (TmpFileName); + } + // Do we now have an open file after trying again? + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_INVALID_PARAMETER; + FileHandle = NULL; + } + } + + if (FileHandle != NULL) { + Info = ShellGetFileInfo (FileHandle); + FileSize = (UINTN) Info->FileSize; + FreePool (Info); + + // + // Allocate buffer to read file. 'Runtime' so we can access it after + // ExitBootServices(). + // + FileData = AllocateRuntimeZeroPool (FileSize); + if (FileData == NULL) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_NO_MEM), gRunAxfHiiHandle); + ShellStatus = SHELL_OUT_OF_RESOURCES; + } else { + // + // Read file into Buffer + // + Status = ShellReadFile (FileHandle, &FileSize, FileData); + if (EFI_ERROR (Status)) { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_READ_FAIL), gRunAxfHiiHandle); + SHELL_FREE_NON_NULL (FileData); + FileData = NULL; + ShellStatus = SHELL_DEVICE_ERROR; + } + } + } + } + + // + // Free the command line package + // + ShellCommandLineFreeVarList (ParamPackage); + } + + // We have a file in memory. Try to work out if we can use it. + // It can either be in ELF format or BootMonFS format. + if (FileData != NULL) { + // Do some validation on the file before we try to load it. The file can + // either be an proper ELF file or one processed by the FlashLoader. + // Since the data might need to go to various locations in memory we cannot + // load the data directly while UEFI is running. We use the file loaders to + // populate a linked list of data and load addresses. This is processed and + // data copied to where it needs to go after calling ExitBootServices. At + // that stage we've reached the point of no return, so overwriting UEFI code + // does not make a difference. + Status = ElfCheckFile (FileData); + if (!EFI_ERROR (Status)) { + // Load program into memory + Status = ElfLoadFile ((VOID*)FileData, &Entrypoint, &LoadList); + } else { + // Try to see if it is a BootMonFs executable + Status = BootMonFsCheckFile ((EFI_FILE_HANDLE)FileHandle); + if (!EFI_ERROR (Status)) { + // Load program into memory + Status = BootMonFsLoadFile ((EFI_FILE_HANDLE)FileHandle, + (VOID*)FileData, &Entrypoint, &LoadList); + } else { + ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_RUNAXF_BAD_FILE), + gRunAxfHiiHandle); + SHELL_FREE_NON_NULL (FileData); + ShellStatus = SHELL_UNSUPPORTED; + } + } + } + + // Program load list created. + // Shutdown UEFI, copy and jump to code. + if (!IsListEmpty (&LoadList) && !EFI_ERROR (Status)) { + // Exit boot services here. This means we cannot return and cannot assume to + // have access to UEFI functions. + Status = ShutdownUefiBootServices (); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR,"Can not shutdown UEFI boot services. Status=0x%X\n", + Status)); + } else { + // Process linked list. Copy data to Memory. + Node = GetFirstNode (&LoadList); + while (!IsNull (&LoadList, Node)) { + LoadNode = (RUNAXF_LOAD_LIST *)Node; + // Do we have data to copy or do we need to set Zeroes (.bss)? + if (LoadNode->Zeroes) { + ZeroMem ((VOID*)LoadNode->MemOffset, LoadNode->Length); + } else { + CopyMem ((VOID *)LoadNode->MemOffset, (VOID *)LoadNode->FileOffset, + LoadNode->Length); + } + Node = GetNextNode (&LoadList, Node); + } + + // + // Switch off interrupts, caches, mmu, etc + // + Status = PreparePlatformHardware (); + ASSERT_EFI_ERROR (Status); + + StartElf = (ELF_ENTRYPOINT)Entrypoint; + StartElf (0,0,0,0); + + // We should never get here.. But if we do, spin.. + ASSERT (FALSE); + while (1); + } + } + + // Free file related information as we are returning to UEFI. + Node = GetFirstNode (&LoadList); + while (!IsNull (&LoadList, Node)) { + NextNode = RemoveEntryList (Node); + FreePool (Node); + Node = NextNode; + } + SHELL_FREE_NON_NULL (FileData); + if (FileHandle != NULL) { + ShellCloseFile (&FileHandle); + } + + // Uninstall protocols as we don't know if they will change. + // If the shell exits and come in again these mappings may be different + // and cause a crash. + Status = gBS->UninstallMultipleProtocolInterfaces (gImageHandle, + &gEfiShellProtocolGuid, Shell, + &gEfiShellParametersProtocolGuid, ShellParameters, + NULL); + + if (EFI_ERROR (Status) && ShellStatus == SHELL_SUCCESS) { + ShellStatus = SHELL_DEVICE_ERROR; + } + + return ShellStatus; +} + + +/** + This is the command help handler function pointer callback type. This + function is responsible for displaying help information for the associated + command. + + @param[in] This The instance of the + EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL. + @param[in] Language The pointer to the language string to use. + + @return string Pool allocated help string, must be freed by + caller. +**/ +CHAR16* +EFIAPI +ShellDynCmdRunAxfGetHelp ( + IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This, + IN CONST CHAR8 *Language + ) +{ + CHAR16 *HelpText; + + ASSERT (gRunAxfHiiHandle != NULL); + + // This allocates memory. The caller is responsoible to free. + HelpText = HiiGetString (gRunAxfHiiHandle, STRING_TOKEN (STR_GET_HELP_RUNAXF), + Language); + + return HelpText; +} diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/elf32.h b/Platform/ARM/Library/ArmShellCmdRunAxf/elf32.h new file mode 100644 index 000000000000..3951444a3085 --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/elf32.h @@ -0,0 +1,258 @@ +/** @file +Ported ELF include files from FreeBSD + +Copyright (c) 2009 - 2010, Apple Inc. 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. + + +**/ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.2 2007/12/03 21:30:36 marius Exp $ + */ + +#ifndef _SYS_ELF32_H_ +#define _SYS_ELF32_H_ 1 + + +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef UINT32 Elf32_Addr; +typedef UINT16 Elf32_Half; +typedef UINT32 Elf32_Off; +typedef INT32 Elf32_Sword; +typedef UINT32 Elf32_Word; +typedef UINT64 Elf32_Lword; + +typedef Elf32_Word Elf32_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf32_Word Elf32_Size; +typedef Elf32_Sword Elf32_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf32_Half e_type; /* File type. */ + Elf32_Half e_machine; /* Machine architecture. */ + Elf32_Word e_version; /* ELF format version. */ + Elf32_Addr e_entry; /* Entry point. */ + Elf32_Off e_phoff; /* Program header file offset. */ + Elf32_Off e_shoff; /* Section header file offset. */ + Elf32_Word e_flags; /* Architecture-specific flags. */ + Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf32_Half e_phentsize; /* Size of program header entry. */ + Elf32_Half e_phnum; /* Number of program header entries. */ + Elf32_Half e_shentsize; /* Size of section header entry. */ + Elf32_Half e_shnum; /* Number of section header entries. */ + Elf32_Half e_shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf32_Word sh_name; /* Section name (index into the + section header string table). */ + Elf32_Word sh_type; /* Section type. */ + Elf32_Word sh_flags; /* Section flags. */ + Elf32_Addr sh_addr; /* Address in memory image. */ + Elf32_Off sh_offset; /* Offset in file. */ + Elf32_Word sh_size; /* Size in bytes. */ + Elf32_Word sh_link; /* Index of a related section. */ + Elf32_Word sh_info; /* Depends on section type. */ + Elf32_Word sh_addralign; /* Alignment in bytes. */ + Elf32_Word sh_entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf32_Word p_type; /* Entry type. */ + Elf32_Off p_offset; /* File offset of contents. */ + Elf32_Addr p_vaddr; /* Virtual address in memory image. */ + Elf32_Addr p_paddr; /* Physical address (not used). */ + Elf32_Word p_filesz; /* Size of contents in file. */ + Elf32_Word p_memsz; /* Size of contents in memory. */ + Elf32_Word p_flags; /* Access permission flags. */ + Elf32_Word p_align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf32_Sword d_tag; /* Entry type. */ + union { + Elf32_Word d_val; /* Integer value. */ + Elf32_Addr d_ptr; /* Address value. */ + } d_un; +} Elf32_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ +} Elf32_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ + Elf32_Sword r_addend; /* Addend. */ +} Elf32_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf32_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf32_Lword m_value; /* symbol value */ + Elf32_Word m_info; /* size + index */ + Elf32_Word m_poffset; /* symbol offset */ + Elf32_Half m_repeat; /* repeat count */ + Elf32_Half m_stride; /* stride info */ +} Elf32_Move; + +/* + * The macros compose and decompose values for Move.r_info + * + * sym = ELF32_M_SYM(M.m_info) + * size = ELF32_M_SIZE(M.m_info) + * M.m_info = ELF32_M_INFO(sym, size) + */ +#define ELF32_M_SYM(info) ((info)>>8) +#define ELF32_M_SIZE(info) ((unsigned char)(info)) +#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf32_Word c_tag; /* how to interpret value */ + union { + Elf32_Word c_val; + Elf32_Addr c_ptr; + } c_un; +} Elf32_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf32_Word st_name; /* String table index of name. */ + Elf32_Addr st_value; /* Symbol value. */ + Elf32_Word st_size; /* Size of associated object. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf32_Half st_shndx; /* Section index of symbol. */ +} Elf32_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU symbol versioning. */ +typedef struct +{ + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct +{ + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct +{ + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + Elf32_Word vn_aux; + Elf32_Word vn_next; +} Elf32_Verneed; + +typedef struct +{ + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; +} Elf32_Vernaux; + +typedef Elf32_Half Elf32_Versym; + +typedef struct { + Elf32_Half si_boundto; /* direct bindings - symbol bound to */ + Elf32_Half si_flags; /* per symbol flags */ +} Elf32_Syminfo; + +#endif /* !_SYS_ELF32_H_ */ diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/elf64.h b/Platform/ARM/Library/ArmShellCmdRunAxf/elf64.h new file mode 100644 index 000000000000..1cfe0c9539aa --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/elf64.h @@ -0,0 +1,260 @@ +/** @file +Ported ELF include files from FreeBSD + +Copyright (c) 2009 - 2010, Apple Inc. 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. + +**/ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.2 2007/12/03 21:30:36 marius Exp $ + */ + +#ifndef _SYS_ELF64_H_ +#define _SYS_ELF64_H_ 1 + + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef UINT64 Elf64_Addr; +typedef UINT16 Elf64_Half; +typedef UINT64 Elf64_Off; +typedef INT32 Elf64_Sword; +typedef INT64 Elf64_Sxword; +typedef UINT32 Elf64_Word; +typedef UINT64 Elf64_Lword; +typedef UINT64 Elf64_Xword; + +/* + * Types of dynamic symbol hash table bucket and chain elements. + * + * This is inconsistent among 64 bit architectures, so a machine dependent + * typedef is required. + */ + +typedef Elf64_Word Elf64_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf64_Xword Elf64_Size; +typedef Elf64_Sxword Elf64_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf64_Word sh_name; /* Section name (index into the + section header string table). */ + Elf64_Word sh_type; /* Section type. */ + Elf64_Xword sh_flags; /* Section flags. */ + Elf64_Addr sh_addr; /* Address in memory image. */ + Elf64_Off sh_offset; /* Offset in file. */ + Elf64_Xword sh_size; /* Size in bytes. */ + Elf64_Word sh_link; /* Index of a related section. */ + Elf64_Word sh_info; /* Depends on section type. */ + Elf64_Xword sh_addralign; /* Alignment in bytes. */ + Elf64_Xword sh_entsize; /* Size of each entry in section. */ +} Elf64_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address in memory image. */ + Elf64_Addr p_paddr; /* Physical address (not used). */ + Elf64_Xword p_filesz; /* Size of contents in file. */ + Elf64_Xword p_memsz; /* Size of contents in memory. */ + Elf64_Xword p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Sxword d_tag; /* Entry type. */ + union { + Elf64_Xword d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ + Elf64_Sxword r_addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL)) + +#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) +#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) +#define ELF64_R_TYPE_INFO(data, type) \ + (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf64_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf64_Lword m_value; /* symbol value */ + Elf64_Xword m_info; /* size + index */ + Elf64_Xword m_poffset; /* symbol offset */ + Elf64_Half m_repeat; /* repeat count */ + Elf64_Half m_stride; /* stride info */ +} Elf64_Move; + +#define ELF64_M_SYM(info) ((info)>>8) +#define ELF64_M_SIZE(info) ((unsigned char)(info)) +#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf64_Xword c_tag; /* how to interpret value */ + union { + Elf64_Xword c_val; + Elf64_Addr c_ptr; + } c_un; +} Elf64_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word st_name; /* String table index of name. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf64_Half st_shndx; /* Section index of symbol. */ + Elf64_Addr st_value; /* Symbol value. */ + Elf64_Xword st_size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU-style symbol versioning. */ +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + +typedef Elf64_Half Elf64_Versym; + +typedef struct { + Elf64_Half si_boundto; /* direct bindings - symbol bound to */ + Elf64_Half si_flags; /* per symbol flags */ +} Elf64_Syminfo; + +#endif /* !_SYS_ELF64_H_ */ diff --git a/Platform/ARM/Library/ArmShellCmdRunAxf/elf_common.h b/Platform/ARM/Library/ArmShellCmdRunAxf/elf_common.h new file mode 100644 index 000000000000..ed3cedc1b076 --- /dev/null +++ b/Platform/ARM/Library/ArmShellCmdRunAxf/elf_common.h @@ -0,0 +1,1059 @@ +/** @file +Ported ELF include files from FreeBSD + +Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.
+Portions Copyright (c) 2011 - 2013, 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. + + +**/ +/*- + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.2 2007/12/03 21:30:36 marius Exp $ + */ + +#ifndef _SYS_ELF_COMMON_H_ +#define _SYS_ELF_COMMON_H_ 1 + +/* + * ELF definitions that are independent of architecture or word size. + */ + +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +typedef struct { + UINT32 n_namesz; /* Length of name. */ + UINT32 n_descsz; /* Length of descriptor. */ + UINT32 n_type; /* Type of this note. */ +} Elf_Note; + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_IA_64 50 /* Intel IA-64 Processor. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ +#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ +#define EM_AARCH64 183 /* ARM 64bit Architecture */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ +#define SHT_SUNW_versym 0x6fffffff +#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ +#define PT_SUNWDTRACE 0x6ffffffc /* private */ +#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object + name. */ +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in + non-writable segments. [sup] */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +#define DT_INIT_ARRAY 25 /* Address of the array of pointers to + initialization functions */ +#define DT_FINI_ARRAY 26 /* Address of the array of pointers to + termination functions */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of + initialization functions. */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of + terminationfunctions. */ +#define DT_RUNPATH 29 /* String table offset of a null-terminated + library search path string. */ +#define DT_FLAGS 30 /* Object specific flag values. */ +#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING + and less than DT_LOOS follow the rules for + the interpretation of the d_un union + as follows: even == 'd_ptr', even == 'd_val' + or none */ +#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to + pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of + pre-initialization functions. */ +#define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ +#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ +#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ +#define DT_SUNW_CAP 0x60000010 /* hardware/software */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ + +/* + * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + * Dyn.d_un.d_val field of the Elf*_Dyn structure. + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ +#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ +#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ +#define DT_MOVESZ 0x6ffffdfb /* move table size */ +#define DT_FEATURE_1 0x6ffffdfc /* feature holder */ +#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ + /* the following DT_* entry. */ + /* See DF_P1_* definitions */ +#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ +#define DT_VALRNGHI 0x6ffffdff + +/* + * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + * + * If any adjustment is made to the ELF object after it has been + * built, these entries will need to be adjusted. + */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_CONFIG 0x6ffffefa /* configuration information */ +#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ +#define DT_AUDIT 0x6ffffefc /* object auditing */ +#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ +#define DT_MOVETAB 0x6ffffefe /* move table */ +#define DT_SYMINFO 0x6ffffeff /* syminfo table */ +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ +#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ +#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ +#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ +#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ + +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 +#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ +#define DT_USED 0x7ffffffe /* ignored - same as needed */ +#define DT_FILTER 0x7fffffff /* shared library filter name */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for DT_FLAGS */ +#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may + make reference to the $ORIGIN substitution + string */ +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in + non-writable segments. */ +#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should + process all relocations for the object + containing this entry before transferring + control to the program. */ +#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or + executable contains code using a static + thread-local storage scheme. */ + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_NUM 7 +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* Symbol versioning flags. */ +#define VER_DEF_CURRENT 1 +#define VER_DEF_IDX(x) VER_NDX(x) + +#define VER_FLG_BASE 0x01 +#define VER_FLG_WEAK 0x02 + +#define VER_NEED_CURRENT 1 +#define VER_NEED_WEAK (1u << 15) +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 + +#define VER_NDX_HIDDEN (1u << 15) +#define VER_NDX(x) ((x) & ~(1u << 15)) + +#define CA_SUNW_NULL 0 +#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ +#define CA_SUNW_SF_1 2 /* first software capabilities entry */ + +/* + * Syminfo flag values + */ +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ + /* to object containing defn. */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ + /* lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ + /* object containing defn. */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ + /* directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +/* + * Syminfo.si_boundto values. + */ +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +/* + * Syminfo version values. + */ +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * Relocation types. + * + * All machine architectures are defined here to allow tools on one to + * handle others. + */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ + +/* Null relocation */ +#define R_AARCH64_NONE 256 /* No relocation */ +/* Static AArch64 relocations */ + /* Static data relocations */ +#define R_AARCH64_ABS64 257 /* S + A */ +#define R_AARCH64_ABS32 258 /* S + A */ +#define R_AARCH64_ABS16 259 /* S + A */ +#define R_AARCH64_PREL64 260 /* S + A - P */ +#define R_AARCH64_PREL32 261 /* S + A - P */ +#define R_AARCH64_PREL16 262 /* S + A - P */ + /* Group relocations to create a 16, 32, 48, or 64 bit unsigned data value or address inline */ +#define R_AARCH64_MOVW_UABS_G0 263 /* S + A */ +#define R_AARCH64_MOVW_UABS_G0_NC 264 /* S + A */ +#define R_AARCH64_MOVW_UABS_G1 265 /* S + A */ +#define R_AARCH64_MOVW_UABS_G1_NC 266 /* S + A */ +#define R_AARCH64_MOVW_UABS_G2 267 /* S + A */ +#define R_AARCH64_MOVW_UABS_G2_NC 268 /* S + A */ +#define R_AARCH64_MOVW_UABS_G3 269 /* S + A */ + /* Group relocations to create a 16, 32, 48, or 64 bit signed data or offset value inline */ +#define R_AARCH64_MOVW_SABS_G0 270 /* S + A */ +#define R_AARCH64_MOVW_SABS_G1 271 /* S + A */ +#define R_AARCH64_MOVW_SABS_G2 272 /* S + A */ + /* Relocations to generate 19, 21 and 33 bit PC-relative addresses */ +#define R_AARCH64_LD_PREL_LO19 273 /* S + A - P */ +#define R_AARCH64_ADR_PREL_LO21 274 /* S + A - P */ +#define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page(S+A) - Page(P) */ +#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Page(S+A) - Page(P) */ +#define R_AARCH64_ADD_ABS_LO12_NC 277 /* S + A */ +#define R_AARCH64_LDST8_ABS_LO12_NC 278 /* S + A */ +#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* S + A */ +#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* S + A */ +#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* S + A */ +#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* S + A */ + /* Relocations for control-flow instructions - all offsets are a multiple of 4 */ +#define R_AARCH64_TSTBR14 279 /* S+A-P */ +#define R_AARCH64_CONDBR19 280 /* S+A-P */ +#define R_AARCH64_JUMP26 282 /* S+A-P */ +#define R_AARCH64_CALL26 283 /* S+A-P */ + /* Group relocations to create a 16, 32, 48, or 64 bit PC-relative offset inline */ +#define R_AARCH64_MOVW_PREL_G0 287 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G0_NC 288 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G1 289 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G1_NC 290 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G2 291 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G2_NC 292 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G3 293 /* S+A-P */ + /* Group relocations to create a 16, 32, 48, or 64 bit GOT-relative offsets inline */ +#define R_AARCH64_MOVW_GOTOFF_G0 300 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G1 302 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G2 304 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G3 306 /* G(S)-GOT */ + /* GOT-relative data relocations */ +#define R_AARCH64_GOTREL64 307 /* S+A-GOT */ +#define R_AARCH64_GOTREL32 308 /* S+A-GOT */ + /* GOT-relative instruction relocations */ +#define R_AARCH64_GOT_LD_PREL19 309 /* G(S)-P */ +#define R_AARCH64_LD64_GOTOFF_LO15 310 /* G(S)-GOT */ +#define R_AARCH64_ADR_GOT_PAGE 311 /* Page(G(S))-Page(P) */ +#define R_AARCH64_LD64_GOT_LO12_NC 312 /* G(S) */ +#define R_AARCH64_LD64_GOTPAGE_LO15 313 /* G(S)-Page(GOT) */ +/* Relocations for thread-local storage */ + /* General Dynamic TLS relocations */ +#define R_AARCH64_TLSGD_ADR_PREL21 512 /* G(TLSIDX(S+A)) - P */ +#define R_AARCH64_TLSGD_ADR_PAGE21 513 /* Page(G(TLSIDX(S+A))) - Page(P) */ +#define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* G(TLSIDX(S+A)) */ +#define R_AARCH64_TLSGD_MOVW_G1 515 /* G(TLSIDX(S+A)) - GOT */ +#define R_AARCH64_TLSGD_MOVW_G0_NC 516 /* G(TLSIDX(S+A)) - GOT */ + /* Local Dynamic TLS relocations */ +#define R_AARCH64_TLSLD_ADR_PREL21 517 /* G(LDM(S))) - P */ +#define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Page(G(LDM(S)))-Page(P) */ +#define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* G(LDM(S)) */ +#define R_AARCH64_TLSLD_MOVW_G1 520 /* G(LDM(S)) - GOT */ +#define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* G(LDM(S)) - GOT */ +#define R_AARCH64_TLSLD_LD_PREL19 522 /* G(LDM(S)) - P */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* DTPREL(S+A) */ + /* Initial Exec TLS relocations */ +#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* G(TPREL(S+A)) - GOT */ +#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* G(TPREL(S+A)) - GOT */ +#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page(G(TPREL(S+A))) - Page(P) */ +#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* G(TPREL(S+A)) */ +#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* G(TPREL(S+A)) - P */ + /* Local Exec TLS relocations */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* TPREL(S+A) */ +/* Dynamic relocations */ + /* Dynamic relocations */ +#define R_AARCH64_COPY 1024 +#define R_AARCH64_GLOB_DAT 1025 /* S + A */ +#define R_AARCH64_JUMP_SLOT 1026 /* S + A */ +#define R_AARCH64_RELATIVE 1027 /* Delta(S) + A , Delta(P) + A */ +#define R_AARCH64_TLS_DTPREL64 1028 /* DTPREL(S+A) */ +#define R_AARCH64_TLS_DTPMOD64 1029 /* LDM(S) */ +#define R_AARCH64_TLS_TPREL64 1030 /* TPREL(S+A) */ +#define R_AARCH64_TLS_DTPREL32 1031 /* DTPREL(S+A) */ +#define R_AARCH64_TLS_DTPMOD32 1032 /* LDM(S) */ +#define R_AARCH64_TLS_TPREL32 1033 /* DTPREL(S+A) */ + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_OP_PUSH 12 /* OP stack push */ +#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */ +#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */ +#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */ +#define R_ALPHA_GPVALUE 16 +#define R_ALPHA_GPRELHIGH 17 +#define R_ALPHA_GPRELLOW 18 +#define R_ALPHA_IMMED_GP_16 19 +#define R_ALPHA_IMMED_GP_HI32 20 +#define R_ALPHA_IMMED_SCN_HI32 21 +#define R_ALPHA_IMMED_BR_HI32 22 +#define R_ALPHA_IMMED_LO32 23 +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_CALL 28 +#define R_ARM_JMP24 29 +#define R_ARM_MOVW_ABS_NC 43 +#define R_ARM_MOVT_ABS 44 +#define R_ARM_THM_MOVW_ABS_NC 47 +#define R_ARM_THM_MOVT_ABS 48 + +// Block of PC-relative relocations added to work around gcc putting +// object relocations in static executables. +#define R_ARM_THM_JUMP24 30 +#define R_ARM_PREL31 42 +#define R_ARM_MOVW_PREL_NC 45 +#define R_ARM_MOVT_PREL 46 +#define R_ARM_THM_MOVW_PREL_NC 49 +#define R_ARM_THM_MOVT_PREL 50 +#define R_ARM_THM_JMP6 52 +#define R_ARM_THM_ALU_PREL_11_0 53 +#define R_ARM_THM_PC12 54 +#define R_ARM_REL32_NOI 56 +#define R_ARM_ALU_PC_G0_NC 57 +#define R_ARM_ALU_PC_G0 58 +#define R_ARM_ALU_PC_G1_NC 59 +#define R_ARM_ALU_PC_G1 60 +#define R_ARM_ALU_PC_G2 61 +#define R_ARM_LDR_PC_G1 62 +#define R_ARM_LDR_PC_G2 63 +#define R_ARM_LDRS_PC_G0 64 +#define R_ARM_LDRS_PC_G1 65 +#define R_ARM_LDRS_PC_G2 66 +#define R_ARM_LDC_PC_G0 67 +#define R_ARM_LDC_PC_G1 68 +#define R_ARM_LDC_PC_G2 69 +#define R_ARM_GOT_PREL 96 +#define R_ARM_THM_JUMP11 102 +#define R_ARM_THM_JUMP8 103 +#define R_ARM_TLS_GD32 104 +#define R_ARM_TLS_LDM32 105 +#define R_ARM_TLS_IE32 107 + +#define R_ARM_THM_JUMP19 51 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + + + +/* Name Value Field Calculation */ +#define R_IA_64_NONE 0 /* None */ +#define R_IA_64_IMM14 0x21 /* immediate14 S + A */ +#define R_IA_64_IMM22 0x22 /* immediate22 S + A */ +#define R_IA_64_IMM64 0x23 /* immediate64 S + A */ +#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ +#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ +#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ +#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ +#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ +#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ +#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ +#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ +#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ +#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ +#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ +#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ +#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ +#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ +#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ +#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ +#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ +#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ +#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ +#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ +#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ +#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ +#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ +#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ +#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ +#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ +#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ +#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ +#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ +#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ +#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ +#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ +#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ +#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ +#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ +#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ +#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ +#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ +#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ +#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ +#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ +#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ +#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ +#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA_64_SUB 0x85 /* immediate64 A - S */ +#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ +#define R_IA_64_LDXMOV 0x87 /* immediate22 special */ +#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ +#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ +#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ +#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ +#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ +#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ +#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ +#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ +#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ +#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ +#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ +#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ +#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ +#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* + * The remaining relocs are from the Embedded ELF ABI, and are not in the + * SVR4 ELF ABI. + */ + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ + + +#endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf index d33c3b79f84c..ed901f9f1f86 100644 --- a/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf +++ b/Platform/ARM/VExpressPkg/ArmVExpress-CTA15-A7.fdf @@ -128,7 +128,7 @@ [FV.FvMain] INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf # Versatile Express FileSystem - INF ArmPlatformPkg/FileSystem/BootMonFs/BootMonFs.inf + INF Platform/ARM/Drivers/BootMonFs/BootMonFs.inf # # USB support diff --git a/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc b/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc index 0fbef7e378cd..c9bb236168cf 100644 --- a/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc +++ b/Platform/ARM/VExpressPkg/ArmVExpress.dsc.inc @@ -118,7 +118,7 @@ [LibraryClasses.common] # RunAxf support via Dynamic Shell Command protocol # It uses the Shell libraries. - ArmShellCmdRunAxfLib|ArmPlatformPkg/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf + ArmShellCmdRunAxfLib|Platform/ARM/Library/ArmShellCmdRunAxf/ArmShellCmdRunAxf.inf ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf @@ -370,7 +370,7 @@ [PcdsFixedAtBuild.common] # # List of Device Paths that support BootMonFs - gArmPlatformTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59);VenHw(1F15DA3C-37FF-4070-B471-BB4AF12A724A)" + gArmBootMonFsTokenSpaceGuid.PcdBootMonFsSupportedDevicePaths|L"VenHw(E7223039-5836-41E1-B542-D7EC736C5E59);VenHw(1F15DA3C-37FF-4070-B471-BB4AF12A724A)" # # ARM OS Loader @@ -434,7 +434,7 @@ [Components.common] } # Versatile Express FileSystem - ArmPlatformPkg/FileSystem/BootMonFs/BootMonFs.inf + Platform/ARM/Drivers/BootMonFs/BootMonFs.inf # # Networking stack diff --git a/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf index 1ecdbb0b231e..8bf289f8da83 100644 --- a/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf +++ b/Platform/ARM/VExpressPkg/Drivers/ArmVExpressDxe/ArmHwDxe.inf @@ -26,6 +26,7 @@ [Sources.common] [Packages] ArmPlatformPkg/ArmPlatformPkg.dec MdePkg/MdePkg.dec + Platform/ARM/ARM.dec [LibraryClasses] ArmShellCmdRunAxfLib