From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: None (no SPF record) identity=mailfrom; client-ip=2a00:1450:4864:20::542; helo=mail-ed1-x542.google.com; envelope-from=pete@akeo.ie; receiver=edk2-devel@lists.01.org Received: from mail-ed1-x542.google.com (mail-ed1-x542.google.com [IPv6:2a00:1450:4864:20::542]) (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 2469A21A02937 for ; Fri, 7 Dec 2018 04:06:07 -0800 (PST) Received: by mail-ed1-x542.google.com with SMTP id h15so3521181edb.4 for ; Fri, 07 Dec 2018 04:06:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=akeo-ie.20150623.gappssmtp.com; s=20150623; h=from:to:subject:date:message-id:in-reply-to:references; bh=RQFoiJmJ1HqATPJQ/nG+04M10DCvVf8Y9zM3Z7TZwhU=; b=f5xGD2NYDpJpg+JZzZKt4RBi/KiabVaJ3UZPvImG1O0Z8t6ahWP+puDBQRm/GW2ze5 DnJ6TPcVWxu/DzXhD3nc7mVhmNna/6F0FNQiUmKL6DTPHwYlv8XxyeAkv6gq//Bdc6eT Ij2CUQJE6g9R4qUJYbFOqd7aloQz6Ovi/ZomJyFeOMI1eJM+H8ocxadlV51ZmU4P32Bo RH2hD30D2O4EmWThkU3Shk4BGVi8iD7d9+EZNWa89sK2ClZ0TapMX4p4ZxMfwWOt9R+X kbL4shQy32RW9FAxJt4gJf3jHw8ZqSBQr+Tm2NvMwLNta26BSSRacd7H/eJEsB3YsdBo C0RQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=RQFoiJmJ1HqATPJQ/nG+04M10DCvVf8Y9zM3Z7TZwhU=; b=i5s7L+ISlRwx+BDibkLTpEPZWGztM3F8JmYpGpoQIXdlrn/nGUKfvOOA9K5LtFJWZe vuU9oT6/cPdycgCG6RCUrM0aUXLyPBCmKpxyyIfq297R/FgLgw9ys4muiRPXnFKyd8wU 8l8RCTsQTvzjyV3olaa69AILwCPE2ssPf7nzWUJZRX/dh3+R2vfLL1M+lbHE62OJ6YA9 SwmbifWvVN5MCwVYb9sfxevRVyW0mcdF1NnFolYP5tlpcGiMEwCsmL7Ougaw+CdiZhw/ f87cLL4/cWDshaZ8BVS0It4YDoTlMB+jPmx0cMw/RiwCGf/2Bksvk3h6FcseLG6EbUX1 x/aA== X-Gm-Message-State: AA+aEWYOBtMI0EmS+MQzYeqnZk18xQOchjoNKMz+HmmieJUx530886WY Ari5FhQiwA2CtU3t5q02hStcROyHMRc= X-Google-Smtp-Source: AFSGD/V7DXQoAA+mctCayQqD4yb0I/fq23CbC+JLFHOHB5vhJ2w9VKJApgY0S0WQd6ON9Nt9PR6vWg== X-Received: by 2002:a50:8bc9:: with SMTP id n9mr2025817edn.41.1544184362796; Fri, 07 Dec 2018 04:06:02 -0800 (PST) Received: from localhost.localdomain ([84.203.68.105]) by smtp.gmail.com with ESMTPSA id b9sm394099ede.12.2018.12.07.04.05.22 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 07 Dec 2018 04:06:00 -0800 (PST) From: Pete Batard To: edk2-devel@lists.01.org Date: Fri, 7 Dec 2018 12:05:10 +0000 Message-Id: <20181207120511.8724-2-pete@akeo.ie> X-Mailer: git-send-email 2.17.0.windows.1 In-Reply-To: <20181207120511.8724-1-pete@akeo.ie> References: <20181207120511.8724-1-pete@akeo.ie> Subject: [PATCH v1 edk2-platfoms 1/2] Platform/Broadcom: Add Raspberry Pi 3 support X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 X-List-Received-Date: Fri, 07 Dec 2018 12:06:08 -0000 This commit contains the edk2-platform components that introduce support for the Raspberry Pi 3 as a platform, based on the original work by Ard Biesheuvel and Andrei Warkentin. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Pete Batard --- Platform/Broadcom/Bcm283x/AcpiTables/AcpiTables.inf | 51 + Platform/Broadcom/Bcm283x/AcpiTables/Csrt.aslc | 337 ++++ Platform/Broadcom/Bcm283x/AcpiTables/Dbg2.aslc | 32 + Platform/Broadcom/Bcm283x/AcpiTables/Dsdt.asl | 523 ++++++ Platform/Broadcom/Bcm283x/AcpiTables/Fadt.aslc | 50 + Platform/Broadcom/Bcm283x/AcpiTables/Gtdt.aslc | 31 + Platform/Broadcom/Bcm283x/AcpiTables/Madt.aslc | 60 + Platform/Broadcom/Bcm283x/AcpiTables/Pep.asl | 92 + Platform/Broadcom/Bcm283x/AcpiTables/Pep.c | 84 + Platform/Broadcom/Bcm283x/AcpiTables/Pep.h | 126 ++ Platform/Broadcom/Bcm283x/AcpiTables/Platform.h | 82 + Platform/Broadcom/Bcm283x/AcpiTables/Rhpx.asl | 201 +++ Platform/Broadcom/Bcm283x/AcpiTables/Sdhc.asl | 105 ++ Platform/Broadcom/Bcm283x/AcpiTables/Spcr.asl | 53 + Platform/Broadcom/Bcm283x/AcpiTables/Uart.asl | 155 ++ Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.c | 730 ++++++++ Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.h | 50 + Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.inf | 53 + Platform/Broadcom/Bcm283x/Drivers/Bcm2836InterruptDxe/Bcm2836InterruptDxe.c | 367 ++++ Platform/Broadcom/Bcm283x/Drivers/Bcm2836InterruptDxe/Bcm2836InterruptDxe.inf | 48 + Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxe.c | 356 ++++ Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxe.inf | 81 + Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxeFormSetGuid.h | 23 + Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxeHii.uni | 100 ++ Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxeHii.vfr | 306 ++++ Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/ComponentName.c | 222 +++ Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.c | 606 +++++++ Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.h | 43 + Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.inf | 71 + Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/Screenshot.c | 379 ++++ Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/ComponentName.c | 183 ++ Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsole.c | 1836 ++++++++++++++++++++ Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsole.h | 591 +++++++ Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxe.inf | 74 + Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxe.uni | 19 + Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxeExtra.uni | 20 + Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/NewFont.c | 288 +++ Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/ComponentName.c | 163 ++ Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/Diagnostics.c | 256 +++ Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/Mmc.c | 458 +++++ Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/Mmc.h | 533 ++++++ Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcBlockIo.c | 473 +++++ Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcDebug.c | 169 ++ Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcDxe.inf | 58 + Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcIdentification.c | 993 +++++++++++ Platform/Broadcom/Bcm283x/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c | 915 ++++++++++ Platform/Broadcom/Bcm283x/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf | 56 + Platform/Broadcom/Bcm283x/Drivers/RpiFdtDxe/RpiFdtDxe.c | 370 ++++ Platform/Broadcom/Bcm283x/Drivers/RpiFdtDxe/RpiFdtDxe.inf | 53 + Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c | 1085 ++++++++++++ Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf | 49 + Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.c | 830 +++++++++ Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.inf | 54 + Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/FileIo.c | 196 +++ Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/FvbInfo.c | 118 ++ Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockService.c | 984 +++++++++++ Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockService.h | 217 +++ Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockServiceDxe.c | 334 ++++ Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockServiceDxe.inf | 93 + Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836.h | 70 + Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836MmcHs.h | 199 +++ Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836SdHost.h | 92 + Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2837Gpio.h | 50 + Platform/Broadcom/Bcm283x/Include/IndustryStandard/RpiFirmware.h | 93 + Platform/Broadcom/Bcm283x/Include/Library/GpioLib.h | 33 + Platform/Broadcom/Bcm283x/Include/Protocol/DwUsb.h | 53 + Platform/Broadcom/Bcm283x/Include/Protocol/ExtendedTextOut.h | 36 + Platform/Broadcom/Bcm283x/Include/Protocol/PiMmcHost.h | 187 ++ Platform/Broadcom/Bcm283x/Include/Protocol/RaspberryPiFirmware.h | 131 ++ Platform/Broadcom/Bcm283x/Include/Utils.h | 33 + Platform/Broadcom/Bcm283x/Library/GpioLib/GpioLib.c | 79 + Platform/Broadcom/Bcm283x/Library/GpioLib/GpioLib.inf | 39 + Platform/Broadcom/Bcm283x/Library/MemoryInitPeiLib/MemoryInitPeiLib.c | 183 ++ Platform/Broadcom/Bcm283x/Library/MemoryInitPeiLib/MemoryInitPeiLib.inf | 51 + Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBm.c | 831 +++++++++ Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBm.h | 60 + Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf | 90 + Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/AArch64/RaspberryPiHelper.S | 107 ++ Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPi.c | 99 ++ Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPiMem.c | 160 ++ Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPiPlatformLib.inf | 64 + Platform/Broadcom/Bcm283x/Library/ResetLib/ResetLib.c | 104 ++ Platform/Broadcom/Bcm283x/Library/ResetLib/ResetLib.inf | 46 + Platform/Broadcom/Bcm283x/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c | 222 +++ Platform/Broadcom/Bcm283x/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf | 43 + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec | 63 + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dsc | 636 +++++++ Platform/Broadcom/Bcm283x/RaspberryPiPkg.fdf | 450 +++++ Platform/Broadcom/Bcm283x/Readme.md | 263 +++ 89 files changed, 21452 insertions(+) diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/AcpiTables.inf b/Platform/Broadcom/Bcm283x/AcpiTables/AcpiTables.inf new file mode 100644 index 000000000000..db0270270cf9 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/AcpiTables.inf @@ -0,0 +1,51 @@ +#/** @file +# +# ACPI table data and ASL sources required to boot the platform. +# +# Copyright (c) 2017, Andrey Warkentin +# Copyright (c) Microsoft Corporation. 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 = AcpiTables + FILE_GUID = 7E374E25-8E01-4FEE-87F2-390C23C606CD + MODULE_TYPE = USER_DEFINED + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = AARCH64 +# + +[Sources] + Platform.h + Madt.aslc + Fadt.aslc + Dbg2.aslc + Gtdt.aslc + Dsdt.asl + Csrt.aslc + Spcr.asl + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[FixedPcd] + gEmbeddedTokenSpaceGuid.PcdInterruptBaseAddress + +[BuildOptions] + # The default '-mcmodel=small' used with DEBUG produces a GenFw error when compiling CSRT.acpi: + # "AARCH64 small code model requires identical ELF and PE/COFF section offsets modulo 4 KB." + GCC:DEBUG_*_AARCH64_CC_FLAGS = -mcmodel=tiny diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Csrt.aslc b/Platform/Broadcom/Bcm283x/AcpiTables/Csrt.aslc new file mode 100644 index 000000000000..926942ec8da3 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Csrt.aslc @@ -0,0 +1,337 @@ +/** @file + * + * Core System Resource Table (CSRT) + * + * Copyright (c) Microsoft Corporation. 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 "Platform.h" + +#define DMA_MAX_REQ_LINES 32 + +#pragma pack(push, 1) + +//------------------------------------------------------------------------ +// DMA Controller Vendor Data for RPi3 +//------------------------------------------------------------------------ +typedef struct +{ + UINT32 Length; + UINT32 Type; + UINT64 ChannelsBaseAddress; + UINT32 ChannelsBaseSize; + UINT64 ControllerBaseAddress; + UINT32 ControllerBaseSize; + UINT32 ChannelCount; + UINT32 ControllerInterrupt; + UINT32 MinimumRequestLine; + UINT32 MaximumRequestLine; + BOOLEAN CacheCoherent; +} DMA_CONTROLLER_VENDOR_DATA; + +//------------------------------------------------------------------------ +// DMA Controller on RPi3 +//------------------------------------------------------------------------ +typedef struct +{ + EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER DmaControllerHeader; + DMA_CONTROLLER_VENDOR_DATA ControllerVendorData; +} RD_DMA_CONTROLLER; + +//------------------------------------------------------------------------ +// DMA Channel Vendor Data for RPi3 +//------------------------------------------------------------------------ +typedef struct +{ + UINT32 ChannelNumber; + UINT32 ChannelInterrupt; + UINT16 IsReservedChannel; + UINT16 NoSrcNoDestAddrIncr; +} DMA_CHANNEL_VENDOR_DATA; + +//------------------------------------------------------------------------ +// DMA Channel on RPi3 +//------------------------------------------------------------------------ +typedef struct +{ + EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER DmaChannelHeader; + DMA_CHANNEL_VENDOR_DATA ChannelVendorData; +} RD_DMA_CHANNEL; + +//------------------------------------------------------------------------ +// DMA Resource Group on RPi3 +//------------------------------------------------------------------------ + +typedef struct +{ + EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER ResGroupHeader; + RD_DMA_CONTROLLER DmaController; + RD_DMA_CHANNEL DmaChannels[RPI3_DMA_CHANNEL_COUNT]; +} RG_DMA; + +//---------------------------------------------------------------------------- +// CSRT table structure for RPi3 platform - current revision only includes DMA +//---------------------------------------------------------------------------- +typedef struct +{ +// Standard ACPI Header + EFI_ACPI_DESCRIPTION_HEADER CsrtHeader; + +// DMA Resource Group + RG_DMA DmaResourceGroup; + +} EFI_ACPI_5_0_CSRT_TABLE; + + + +EFI_ACPI_5_0_CSRT_TABLE Csrt = +{ + //------------------------------------------------------------------------ + // ACPI Table Header + //------------------------------------------------------------------------ + { + EFI_ACPI_5_0_CORE_SYSTEM_RESOURCE_TABLE_SIGNATURE, // Signature "CSRT" + sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(RG_DMA), // Length + EFI_ACPI_5_0_CSRT_REVISION, // Revision + 0x00, // Checksum calculated at runtime. + EFI_ACPI_OEM_ID, // OEMID is a 6 bytes long field "BC2836" + EFI_ACPI_OEM_TABLE_ID, // OEM table identification(8 bytes long) "RPI3EDK2" + EFI_ACPI_OEM_REVISION, // OEM revision number. + EFI_ACPI_CREATOR_ID, // ASL compiler vendor ID. + EFI_ACPI_CREATOR_REVISION // ASL compiler revision number. + }, + + //------------------------------------------------------------------------ + // DMA Resource Group + //------------------------------------------------------------------------ + { + + //------------------------------------------------------------------------ + // DMA Resource Group Header + //------------------------------------------------------------------------ + { + sizeof(RG_DMA), // Resource Group Length + EFI_ACPI_VENDOR_ID, // VendorId + 0, // SubvendorId + EFI_ACPI_CSRT_DEVICE_ID_DMA, // DeviceId 9 + 0, // SubdeviceId + 0, // Revision + 0, // Reserved + 0 // SharedInfoLength + }, + + + //------------------------------------------------------------------------------- + // Resource Descriptor - DMA Controller + //------------------------------------------------------------------------------- + { + { + sizeof(RD_DMA_CONTROLLER), // Length of this Resource Descriptor + EFI_ACPI_CSRT_RESOURCE_TYPE_DMA, // Type for this resource 3=DMA + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CONTROLLER, // Subtype for this resource 1=DMA Controller + EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP+0, // ResourceId - 1st DMA controller + }, + { + sizeof(DMA_CONTROLLER_VENDOR_DATA), // controller vendor data here + 1, + 0x3F007000, // Base address for channels + RPI3_DMA_CHANNEL_COUNT*0x100, // Base size = Number of channels x 0x100 size for each channel + 0x3F007FE0, // Base address for controller + 8, // Base size = two registers + RPI3_DMA_USED_CHANNEL_COUNT, + 0, // cannot use controller interrupt + 0, // Minimum Request Line + DMA_MAX_REQ_LINES-1, // Maximum Request Line + FALSE, + }, + }, + + //------------------------------------------------------------------------ + // Resource Descriptor(s) - DMA Channels 0 to n-1 + //------------------------------------------------------------------------ + { + + // channel 0 + { + { + sizeof(RD_DMA_CHANNEL), // Length of this Resource Descriptor + EFI_ACPI_CSRT_RESOURCE_TYPE_DMA, // Type for this resource 3=DMA + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CHANNEL, // Subtype for this resource 0=DMA Channel + EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP+1, // ResourceId + }, + { + 0, // channel vendor data here + 0x30, // 16+32 dma_int[0] + 0, + 0 + }, + }, + + // channel 1 reserved + { + { + sizeof(RD_DMA_CHANNEL), + EFI_ACPI_CSRT_RESOURCE_TYPE_DMA, + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CHANNEL, + EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP+2, // ResourceId + }, + { + 1, // channel vendor data here + 0x31, // 17+32 dma_int[1] + 1, + 0 + }, + }, + + // channel 2 - VC4 use only + { + { + sizeof(RD_DMA_CHANNEL), + EFI_ACPI_CSRT_RESOURCE_TYPE_DMA, + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CHANNEL, + EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP+3, // ResourceId + }, + { + 2, // channel vendor data here + 0x32, // 18+32 dma_int[2] + 1, + 0 + }, + }, + + // channel 3 - VC4 use only + { + { + sizeof(RD_DMA_CHANNEL), + EFI_ACPI_CSRT_RESOURCE_TYPE_DMA, + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CHANNEL, + EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP+4, + }, + { + 3, // channel vendor data here + 0x33, // 19+32 dma_int[3] + 1, + 0 + }, + }, + + // channel 4 + { + { + sizeof(RD_DMA_CHANNEL), + EFI_ACPI_CSRT_RESOURCE_TYPE_DMA, + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CHANNEL, + EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP+5, + }, + { + 4, // channel vendor data here + 0x34, // 20+32 dma_int[4] + 0, + 1 // SD host controller candidate + }, + }, + + // channel 5 + { + { + sizeof(RD_DMA_CHANNEL), + EFI_ACPI_CSRT_RESOURCE_TYPE_DMA, + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CHANNEL, + EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP+6, + }, + { + 5, // channel vendor data here + 0x35, // 21+32 dma_int[5] + 0, + 0 + }, + }, + + // channel 6 is reserved + { + { + sizeof(RD_DMA_CHANNEL), + EFI_ACPI_CSRT_RESOURCE_TYPE_DMA, + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CHANNEL, + EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP+7, + }, + { + 6, // channel vendor data here + 0x36, // 22+32 dma_int[6] + 1, + 0 + }, + }, + + // channel 7 is reserved + { + { + sizeof(RD_DMA_CHANNEL), + EFI_ACPI_CSRT_RESOURCE_TYPE_DMA, + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CHANNEL, + EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP+8, + }, + { + 7, // channel vendor data here + 0x37, // 23+32 dma_int[7] + 1, + 0 + }, + }, + + // channel 8 + { + { + sizeof(RD_DMA_CHANNEL), + EFI_ACPI_CSRT_RESOURCE_TYPE_DMA, + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CHANNEL, + EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP+9, + }, + { + 8, // channel vendor data here + 0x38, // 24+32 dma_int[8] + 0, + 0 + }, + }, + + // channel 9 + { + { + sizeof(RD_DMA_CHANNEL), + EFI_ACPI_CSRT_RESOURCE_TYPE_DMA, + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CHANNEL, + EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP+10, + }, + { + 9, // channel vendor data here + 0x39, // 25+32 dma_int[9] + 0, + 0 + }, + } + + } // end DMA Channels 0 to 14 + + } // end DMA Resource group +}; + +#pragma pack(pop) + +VOID* ReferenceAcpiTable(VOID) +{ +// +// Reference the table being generated to prevent the optimizer from removing the +// data structure from the exeutable +// + return (VOID*)&Csrt; +} diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Dbg2.aslc b/Platform/Broadcom/Bcm283x/AcpiTables/Dbg2.aslc new file mode 100644 index 000000000000..b728a5f00cfb --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Dbg2.aslc @@ -0,0 +1,32 @@ +/** @file + * + * Debug Port Table (DBG2) + * + * Copyright (c) Microsoft Corporation. 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. + * + **/ + +char DBG2[92] = { + 0x44, 0x42, 0x47, 0x32, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4D, 0x53, 0x46, 0x54, 0x20, 0x20, 0x45, 0x44, 0x4B, 0x32, + 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x4D, 0x53, + 0x46, 0x54, 0x01, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x01, 0x0A, 0x00, + 0x26, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x80, 0x10, 0x00, + 0x00, 0x00, 0x16, 0x00, 0x22, 0x00, 0x00, 0x20, 0x00, 0x10, + 0x00, 0x50, 0x21, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x00, + 0x00, 0x00, '\\', '_', 'S', 'B', '.', 'U', 'R', 'T', + 'M', 0x00, +}; + +void * ReferenceAcpiTable(void) { + return (void *) &DBG2; +} diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Dsdt.asl b/Platform/Broadcom/Bcm283x/AcpiTables/Dsdt.asl new file mode 100644 index 000000000000..69897cb921f7 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Dsdt.asl @@ -0,0 +1,523 @@ +/** @file + * + * Differentiated System Definition Table (DSDT) + * + * Copyright (c) 2018, Andrey Warkentin + * Copyright (c) Microsoft Corporation. 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. + * + **/ + +#define BCM_ALT0 0x4 +#define BCM_ALT1 0x5 +#define BCM_ALT2 0x6 +#define BCM_ALT3 0x7 +#define BCM_ALT4 0x3 +#define BCM_ALT5 0x2 + +DefinitionBlock ("Dsdt.aml", "DSDT", 5, "MSFT", "EDK2", 2) +{ + Scope (\_SB_) + { + include("Sdhc.asl") + include("Pep.asl") + + // + // Description: This is a Processor Device + // + + Device (CPU0) + { + Name (_HID, "ACPI0007") + Name (_UID, 0x0) + Method (_STA) + { + Return(0xf) + } + } + + // + // Description: This is a Processor Device + // + + Device (CPU1) + { + Name (_HID, "ACPI0007") + Name (_UID, 0x1) + Method (_STA) + { + Return(0xf) + } + } + + // + // Description: This is a Processor Device + // + + Device (CPU2) + { + Name (_HID, "ACPI0007") + Name (_UID, 0x2) + Method (_STA) + { + Return(0xf) + } + } + + // + // Description: This is a Processor Device + // + + Device (CPU3) + { + Name (_HID, "ACPI0007") + Name (_UID, 0x3) + Method (_STA) + { + Return(0xf) + } + } + + // + // Description: DWC OTG Controller + // + + Device (USB0) + { + Name (_HID, "BCM2848") + Name (_CID, Package() { "DWC_OTG", "DWC2_OTG"}) + Name (_UID, 0x0) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + MEMORY32FIXED(ReadWrite, 0x3F980000, 0x10000, ) + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x29 } + }) + Return(RBUF) + } + } + + // + // Description: Video Core 4 GPU + // + + Device (GPU0) + { + Name (_HID, "BCM2850") + Name (_CID, "VC4") + Name (_UID, 0x0) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + // Memory and interrupt for the GPU + MEMORY32FIXED(ReadWrite, 0x3FC00000, 0x1000, ) + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x2A } + + // HVS - Hardware Video Scalar + MEMORY32FIXED(ReadWrite, 0x3F400000, 0x6000, ) + // The HVS interrupt is reserved by the VPU + // Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x41 } + + // PixelValve0 - DSI0 or DPI + // MEMORY32FIXED(ReadWrite, 0x3F206000, 0x100, ) + // Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x4D } + + // PixelValve1 - DS1 or SMI + // MEMORY32FIXED(ReadWrite, 0x73F207000, 0x100, ) + // Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x4E } + + // PixelValve2 - HDMI output - connected to HVS display FIFO 1 + MEMORY32FIXED(ReadWrite, 0x3F807000, 0x100, ) + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x4A } + + // HDMI registers + MEMORY32FIXED(ReadWrite, 0x3F902000, 0x600, ) // HDMI registers + MEMORY32FIXED(ReadWrite, 0x3F808000, 0x100, ) // HD registers + // hdmi_int[0] + // Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x48 } + // hdmi_int[1] + // Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x49 } + + // HDMI DDC connection + I2CSerialBus(0x50,, 100000,, "\\_SB.I2C2",,,,) // EDID + I2CSerialBus(0x30,, 100000,, "\\_SB.I2C2",,,,) // E-DDC Segment Pointer + }) + Return(RBUF) + } + + // GPU Power Management Component Data + // Reference : https://github.com/Microsoft/graphics-driver-samples/wiki/Install-Driver-in-a-Windows-VM + Method(PMCD, 0, Serialized) { + + Name(RBUF, Package() { + 1, // Version + 1, // Number of graphics power components + + Package() { // Power components package + + Package() { // GPU component package + 0, // Component Index + 0, // DXGK_POWER_COMPONENT_MAPPING.ComponentType (0 = DXGK_POWER_COMPONENT_ENGINE) + 0, // DXGK_POWER_COMPONENT_MAPPING.NodeIndex + + Buffer() { // DXGK_POWER_RUNTIME_COMPONENT.ComponentGuid + // 9B2D1E26-1575-4747-8FC0-B9EB4BAA2D2B + 0x26, 0x1E, 0x2D, 0x9B, 0x75, 0x15, 0x47, 0x47, + 0x8f, 0xc0, 0xb9, 0xeb, 0x4b, 0xaa, 0x2d, 0x2b + }, + + "VC4_Engine_00",// DXGK_POWER_RUNTIME_COMPONENT.ComponentName + 2, // DXGK_POWER_RUNTIME_COMPONENT.StateCount + + Package() { // DXGK_POWER_RUNTIME_COMPONENT.States[] package + + Package() { // F0 + 0, // DXGK_POWER_RUNTIME_STATE.TransitionLatency + 0, // DXGK_POWER_RUNTIME_STATE.ResidencyRequirement + 1210000, // DXGK_POWER_RUNTIME_STATE.NominalPower (microwatt) + }, + + Package() { // F1 - Placeholder + 10000, // DXGK_POWER_RUNTIME_STATE.TransitionLatency + 10000, // DXGK_POWER_RUNTIME_STATE.ResidencyRequirement + 4, // DXGK_POWER_RUNTIME_STATE.NominalPower + }, + } + } + } + }) + Return(RBUF) + } + } + + // + // Description: PiQ Mailbox Driver + // + + Device (RPIQ) + { + Name (_HID, "BCM2849") + Name (_CID, "RPIQ") + Name (_UID, 0) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + Memory32Fixed (ReadWrite, 0x3F00B880, 0x00000024, ) + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x61 } + }) + Return (RBUF) + } + } + + // + // Description: VCHIQ Driver + // + + Device (VCIQ) + { + Name (_HID, "BCM2835") + Name (_CID, "VCIQ") + Name (_UID, 0) + Name (_DEP, Package() { \_SB.RPIQ }) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + Memory32Fixed (ReadWrite, 0x3F00B840, 0x00000010, ) + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x62 } + }) + Return (RBUF) + } + } + + // + // Description: VC Shared Memory Driver + // + + Device (VCSM) + { + Name (_HID, "BCM2856") + Name (_CID, "VCSM") + Name (_UID, 0) + Name (_DEP, Package() { \_SB.VCIQ }) + Method (_STA) + { + Return(0xf) + } + } + + // + // Description: GPIO + // + Device (GPI0) + { + Name (_HID, "BCM2845") + Name (_CID, "BCMGPIO") + Name (_UID, 0x0) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + MEMORY32FIXED(ReadWrite, 0x3F200000, 0xB4, ) + Interrupt(ResourceConsumer, Level, ActiveHigh, Shared) { 0x51 } + Interrupt(ResourceConsumer, Level, ActiveHigh, Shared) { 0x53 } + }) + Return(RBUF) + } + } + + // + // Description: I2C + // + + Device (I2C1) + { + Name (_HID, "BCM2841") + Name (_CID, "BCMI2C") + Name (_UID, 0x1) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) + { + Name (RBUF, ResourceTemplate() + { + Memory32Fixed(ReadWrite, 0x3F804000, 0x20) + Interrupt(ResourceConsumer, Level, ActiveHigh, Shared) {0x55} + // + // MsftFunctionConfig is encoded as the VendorLong. + // + // MsftFunctionConfig(Exclusive, PullUp, BCM_ALT0, "\\_SB.GPI0", 0, ResourceConsumer, ) {2, 3} + // + VendorLong () // Length = 0x31 + { + /* 0000 */ 0x00, 0x60, 0x44, 0xD5, 0xF3, 0x1F, 0x11, 0x60, // .`D....` + /* 0008 */ 0x4A, 0xB8, 0xB0, 0x9C, 0x2D, 0x23, 0x30, 0xDD, // J...-#0. + /* 0010 */ 0x2F, 0x8D, 0x1D, 0x00, 0x01, 0x10, 0x00, 0x01, // /....... + /* 0018 */ 0x04, 0x00, 0x12, 0x00, 0x00, 0x16, 0x00, 0x20, // ....... + /* 0020 */ 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x5C, // .......\ + /* 0028 */ 0x5F, 0x53, 0x42, 0x2E, 0x47, 0x50, 0x49, 0x30, // _SB.GPI0 + /* 0030 */ 0x00 // . + } + + }) + Return(RBUF) + } + } + + // + // I2C2 is the HDMI DDC connection + // + + Device (I2C2) + { + Name (_HID, "BCM2841") + Name (_CID, "BCMI2C") + Name (_UID, 0x2) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) + { + Name (RBUF, ResourceTemplate() + { + Memory32Fixed(ReadWrite, 0x3F805000, 0x20) + Interrupt(ResourceConsumer, Level, ActiveHigh, Shared) {0x55} + }) + Return(RBUF) + } + } + + // + // Description: SPI + // + + Device (SPI0) + { + Name (_HID, "BCM2838") + Name (_CID, "BCMSPI0") + Name (_UID, 0x0) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + MEMORY32FIXED(ReadWrite, 0x3F204000, 0x20, ) + Interrupt(ResourceConsumer, Level, ActiveHigh, Shared) {0x56} + + // + // MsftFunctionConfig is encoded as the VendorLong. + // + // MsftFunctionConfig(Exclusive, PullDown, BCM_ALT0, "\\_SB.GPI0", 0, ResourceConsumer, ) {9, 10, 11} // MISO, MOSI, SCLK + VendorLong () // Length = 0x33 + { + /* 0000 */ 0x00, 0x60, 0x44, 0xD5, 0xF3, 0x1F, 0x11, 0x60, // .`D....` + /* 0008 */ 0x4A, 0xB8, 0xB0, 0x9C, 0x2D, 0x23, 0x30, 0xDD, // J...-#0. + /* 0010 */ 0x2F, 0x8D, 0x1F, 0x00, 0x01, 0x10, 0x00, 0x02, // /....... + /* 0018 */ 0x04, 0x00, 0x12, 0x00, 0x00, 0x18, 0x00, 0x22, // ......." + /* 0020 */ 0x00, 0x00, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, // ........ + /* 0028 */ 0x00, 0x5C, 0x5F, 0x53, 0x42, 0x2E, 0x47, 0x50, // .\_SB.GP + /* 0030 */ 0x49, 0x30, 0x00 // I0. + } + + // + // MsftFunctionConfig is encoded as the VendorLong. + // + // MsftFunctionConfig(Exclusive, PullUp, BCM_ALT0, "\\_SB.GPI0", 0, ResourceConsumer, ) {8} // CE0 + VendorLong () // Length = 0x2F + { + /* 0000 */ 0x00, 0x60, 0x44, 0xD5, 0xF3, 0x1F, 0x11, 0x60, // .`D....` + /* 0008 */ 0x4A, 0xB8, 0xB0, 0x9C, 0x2D, 0x23, 0x30, 0xDD, // J...-#0. + /* 0010 */ 0x2F, 0x8D, 0x1B, 0x00, 0x01, 0x10, 0x00, 0x01, // /....... + /* 0018 */ 0x04, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x1E, // ........ + /* 0020 */ 0x00, 0x00, 0x00, 0x08, 0x00, 0x5C, 0x5F, 0x53, // .....\_S + /* 0028 */ 0x42, 0x2E, 0x47, 0x50, 0x49, 0x30, 0x00 // B.GPI0. + } + + // + // MsftFunctionConfig is encoded as the VendorLong. + // + // MsftFunctionConfig(Exclusive, PullUp, BCM_ALT0, "\\_SB.GPI0", 0, ResourceConsumer, ) {7} // CE1 + VendorLong () // Length = 0x2F + { + /* 0000 */ 0x00, 0x60, 0x44, 0xD5, 0xF3, 0x1F, 0x11, 0x60, // .`D....` + /* 0008 */ 0x4A, 0xB8, 0xB0, 0x9C, 0x2D, 0x23, 0x30, 0xDD, // J...-#0. + /* 0010 */ 0x2F, 0x8D, 0x1B, 0x00, 0x01, 0x10, 0x00, 0x01, // /....... + /* 0018 */ 0x04, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x1E, // ........ + /* 0020 */ 0x00, 0x00, 0x00, 0x07, 0x00, 0x5C, 0x5F, 0x53, // .....\_S + /* 0028 */ 0x42, 0x2E, 0x47, 0x50, 0x49, 0x30, 0x00 // B.GPI0. + } + }) + Return(RBUF) + } + } + + Device (SPI1) + { + Name (_HID, "BCM2839") + Name (_CID, "BCMAUXSPI") + Name (_UID, 0x1) + Name (_DEP, Package() { \_SB.RPIQ }) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + MEMORY32FIXED(ReadWrite, 0x3F215080, 0x40,) + Interrupt(ResourceConsumer, Level, ActiveHigh, Shared,) {0x3D} + + // + // MsftFunctionConfig is encoded as the VendorLong. + // + // MsftFunctionConfig(Exclusive, PullDown, BCM_ALT4, "\\_SB.GPI0", 0, ResourceConsumer, ) {19, 20, 21} // MISO, MOSI, SCLK + VendorLong () // Length = 0x33 + { + /* 0000 */ 0x00, 0x60, 0x44, 0xD5, 0xF3, 0x1F, 0x11, 0x60, // .`D....` + /* 0008 */ 0x4A, 0xB8, 0xB0, 0x9C, 0x2D, 0x23, 0x30, 0xDD, // J...-#0. + /* 0010 */ 0x2F, 0x8D, 0x1F, 0x00, 0x01, 0x10, 0x00, 0x02, // /....... + /* 0018 */ 0x03, 0x00, 0x12, 0x00, 0x00, 0x18, 0x00, 0x22, // ......." + /* 0020 */ 0x00, 0x00, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, // ........ + /* 0028 */ 0x00, 0x5C, 0x5F, 0x53, 0x42, 0x2E, 0x47, 0x50, // .\_SB.GP + /* 0030 */ 0x49, 0x30, 0x00 // I0. + } + + // + // MsftFunctionConfig is encoded as the VendorLong. + // + // MsftFunctionConfig(Exclusive, PullDown, BCM_ALT4, "\\_SB.GPI0", 0, ResourceConsumer, ) {16} // CE2 + VendorLong () // Length = 0x2F + { + /* 0000 */ 0x00, 0x60, 0x44, 0xD5, 0xF3, 0x1F, 0x11, 0x60, // .`D....` + /* 0008 */ 0x4A, 0xB8, 0xB0, 0x9C, 0x2D, 0x23, 0x30, 0xDD, // J...-#0. + /* 0010 */ 0x2F, 0x8D, 0x1B, 0x00, 0x01, 0x10, 0x00, 0x02, // /....... + /* 0018 */ 0x03, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x1E, // ........ + /* 0020 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x5C, 0x5F, 0x53, // .....\_S + /* 0028 */ 0x42, 0x2E, 0x47, 0x50, 0x49, 0x30, 0x00 // B.GPI0. + } + }) + Return(RBUF) + } + } + + // SPI2 has no pins on GPIO header + // Device (SPI2) + // { + // Name (_HID, "BCM2839") + // Name (_CID, "BCMAUXSPI") + // Name (_UID, 0x2) + // Name (_DEP, Package() { \_SB.RPIQ }) + // Method (_STA) + // { + // Return(0xf) // Disabled + // } + // Method (_CRS, 0x0, Serialized) { + // Name (RBUF, ResourceTemplate () { + // MEMORY32FIXED(ReadWrite, 0x3F2150C0, 0x40,) + // Interrupt(ResourceConsumer, Level, ActiveHigh, Shared,) {0x3D} + // }) + // Return(RBUF) + // } + // } + + // + // Description: PWM Driver + // + + Device (PWM0) + { + Name (_HID, "BCM2844") + Name (_CID, "BCM2844") + Name (_UID, 0) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + // DMA channel 11 control + Memory32Fixed (ReadWrite, 0x3F007B00, 0x00000100, ) + // PWM control + Memory32Fixed (ReadWrite, 0x3F20C000, 0x00000028, ) + // PWM control bus + Memory32Fixed (ReadWrite, 0x7E20C000, 0x00000028, ) + // PWM control uncached + Memory32Fixed (ReadWrite, 0xFF20C000, 0x00000028, ) + // PWM clock control + Memory32Fixed (ReadWrite, 0x3F1010A0, 0x00000008, ) + // Interrupt DMA channel 11 + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x3B } + // DMA channel 11, DREQ 5 for PWM + FixedDMA(5, 11, Width32Bit, ) + }) + Return (RBUF) + } + } + + include("Uart.asl") + include("Rhpx.asl") + } +} diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Fadt.aslc b/Platform/Broadcom/Bcm283x/AcpiTables/Fadt.aslc new file mode 100644 index 000000000000..493a888d3699 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Fadt.aslc @@ -0,0 +1,50 @@ +/** @file + * + * Fixed ACPI Description Table (FADT) + * + * Copyright (c) 2018, Andrey Warkentin + * Copyright (c) Microsoft Corporation. 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. + * + **/ + +char FACP[268] = { + 0x46, 0x41, 0x43, 0x50, 0x0C, 0x01, 0x00, 0x00, 0x05, 0x00, /* 0 */ + 0x42, 0x43, 0x32, 0x38, 0x33, 0x36, 0x45, 0x44, 0x4B, 0x32, /* 10 */ + 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x4D, 0x53, /* 20 */ + 0x46, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, /* 40 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 50 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 60 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 70 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 80 */ + 0x00, 0x04, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x00, /* 90 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, /* 100 */ + 0x00, 0x00, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, /* 110 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 120 */ + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 130 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 140 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 150 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 160 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 170 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 180 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 190 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 200 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 210 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 220 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 230 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 240 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 250 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 268 */ +}; + +void * ReferenceAcpiTable(void) { + return (void *) &FACP; +} diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Gtdt.aslc b/Platform/Broadcom/Bcm283x/AcpiTables/Gtdt.aslc new file mode 100644 index 000000000000..764cc6c09fe7 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Gtdt.aslc @@ -0,0 +1,31 @@ +/** @file + * + * Generic Timer Description Table (GTDT) + * Automatically generated by AutoAcpi + * + * Copyright (c) Microsoft Corporation. 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. + * + **/ + +char GTDT[80] = { + 0x47, 0x54, 0x44, 0x54, 0x50, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x4D, 0x53, 0x46, 0x54, 0x20, 0x20, 0x45, 0x44, 0x4B, 0x32, + 0x20, 0x20, 0x20, 0x20, 0x01, 0x00, 0x00, 0x00, 0x4D, 0x53, + 0x46, 0x54, 0x01, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +void * ReferenceAcpiTable(void) { + return (void *) >DT; +} diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Madt.aslc b/Platform/Broadcom/Bcm283x/AcpiTables/Madt.aslc new file mode 100644 index 000000000000..96f3ee469324 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Madt.aslc @@ -0,0 +1,60 @@ +/** @file + * + * Multiple APIC Description Table (MADT) + * + * Copyright (c) 2018, Andrey Warkentin + * Copyright (c) Microsoft Corporation. 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. + * + **/ + +/* + * Even though the BCM2836 doesn't contain a GIC, these + * GICC definitions enable multi-core support (with PSCI). + * + * Mind the signatures in the header, they must be kept. + */ +char APIC[] = { + 0x41, 0x50, 0x49, 0x43, 0x6c, 0x01, 0x00, 0x00, 0x03, 0xaf, 0x42, 0x43, + 0x32, 0x38, 0x33, 0x36, 0x45, 0x44, 0x4b, 0x32, 0x20, 0x20, 0x20, 0x20, + 0x01, 0x00, 0x00, 0x00, 0x4d, 0x53, 0x46, 0x54, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x50, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0b, 0x50, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0b, 0x50, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x50, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00 +}; + +void * ReferenceAcpiTable(void) { + return (void *) &APIC; +} diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Pep.asl b/Platform/Broadcom/Bcm283x/AcpiTables/Pep.asl new file mode 100644 index 000000000000..c0e07c6eaf42 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Pep.asl @@ -0,0 +1,92 @@ +/** @file + * + * Platform Extension Plugin (PEP). + * + * Copyright (c) 2018, Andrey Warkentin + * Copyright (c) Microsoft Corporation. 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. + * + **/ + +Device(PEPD) +{ + // + // RPI3 PEP virtual device. + // + Name(_HID, "BCM2854") // note: since pep on rpi3 is virtual device, + Name(_CID, "BCM2854") // its device id needs to be generated by Microsoft + Name(_UID, 0x0) + Name(_CRS, ResourceTemplate () { + // No hardware resources for PEP driver are needed. + }) + + // + // Processor info. PEP proprietary method to return + // PEP_PROCESSOR_TABLE_PLAT structure. + // + // See Pep.h and Pep.c. + // + Name(_GPI, Buffer() { + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5C,0x00,0x5F,0x00,0x53, + 0x00,0x42,0x00,0x2E,0x00,0x43,0x00,0x50,0x00,0x55,0x00,0x30, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }) + + // + // Coordinated state info. PEP proprietary method to return + // PEP_COORDINATED_STATE_TABLE_PLAT structure. + // + // See Pep.h and Pep.c. + // + Name(_GCI, Buffer() { + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x01,0x00,0x00,0x00 + }) + + // + // Device info. PEP proprietary method to return + // PEP_DEVICE_TABLE_PLAT structure. + // + // See Pep.h and Pep.c. + // + + Name(_GDI, Buffer() { + 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5C,0x00,0x5F,0x00,0x53, + 0x00,0x42,0x00,0x2E,0x00,0x49,0x00,0x32,0x00,0x43,0x00,0x30, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09, + 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }) +} diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Pep.c b/Platform/Broadcom/Bcm283x/AcpiTables/Pep.c new file mode 100644 index 000000000000..de457daaa547 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Pep.c @@ -0,0 +1,84 @@ +/** @file + * + * PEP device tables + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) Microsoft Corporation. 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 "Pep.h" + +PEP_PROCESSOR_TABLE_PLAT RPI3Processors = { + 1, //Version + 1, //NumberProcessors + { //ProcessorInfo + { //[0] + L"\\_SB.CPU0", //DevicePath , wchar_t[16] + 0, //FeedbackCounterCount + 0x00000000, //Flags + 0, //NumberIdleStates + 0, //NumberPerfStates + { //IdleInfo + }, + { // perfinfo + } + } + } +}; + +PEP_COORDINATED_STATE_TABLE_PLAT RPI3CoordinatedStates = { + 1, //Version + 1, //CoordinatedStateCount + { //CordinatedStates[] + { //[0] + { // DependencyInfo + { //[0] + 1, //ExpectedState + 0, //TargetProcessor + 0x0 | 0x2 | 0x4, //LooseDependency = FALSE, InitialState = TRUE, DependentState = TRUE + } + }, + SOC_STATE_TYPE, //StateType + 0x1, //Flags + 0, //Latency + 0, //BreakEvenDuration + 1, //DependencyCount + 1, //MaximumDependencySize + } + } +}; + +PEP_DEVICE_TABLE_PLAT RPI3Devices = { + 1, //Version + 1, //NumberDevices + { //DeviceInfo + { //[1] + L"\\_SB.I2C0", //DevicePath , wchar_t[16] + 0x1 | (1 << 3), //DStateSupportMask (D0 and D3) + 1, //NumberCompoenents + { //DStateRequirement + { //[0] + PowerDeviceD3 //DState + } + }, + { // FStateRequirement + { //[0] + { //FState + { //[0] + 0 + } + } + } + } + } + } +}; diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Pep.h b/Platform/Broadcom/Bcm283x/AcpiTables/Pep.h new file mode 100644 index 000000000000..16d8c460832e --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Pep.h @@ -0,0 +1,126 @@ +/** @file + * + * PEP device defines + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) Microsoft Corporation. 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. + * + **/ + +/* + * Note: Not everything is here. At least SOC_STATE_TYPE is missing. + */ + +#ifndef _RPI3PEP_H_INCLUDED_ +#define _RPI3PEP_H_INCLUDED_ + +#include + +#define PEP_MAX_DEPENDENCIES_PER_STATE 16 +#define MAX_PROCESSOR_PATH_LENGTH 16 +#define MAX_DEVICE_PATH_LENGTH 32 +#define MAX_COMPONENT_COUNT 8 +#define P_NUMBER_PROCESSORS 1 +#define P_NUMBER_IDLE_STATES 1 +#define P_NUMBER_PERF_STATES 0 +#define P_NUMBER_DEVICES 1 +#define P_NUMBER_COORDINATED_STATS 1 + +typedef struct _PEP_PROCESSOR_IDLE_STATE_INFO { + UINT32 Ulong; + UINT32 Latency; + UINT32 BreakEvenDuration; +} PEP_PROCESSOR_IDLE_STATE_INFO, *PEP_PROCESSOR_IDLE_STATE_INFO; + +typedef struct _PEP_PROCESSOR_IDLE_INFO_PLAT { + // + // Processor idle states. + // + PEP_PROCESSOR_IDLE_STATE_INFO IdleStates[P_NUMBER_IDLE_STATES]; +} PEP_PROCESSOR_IDLE_INFO_PLAT, *PPEP_PROCESSOR_IDLE_INFO_PLAT; + +typedef struct COORDINATED_DEPENDENCY_INFO { + UINT32 ExpectedState; + UINT32 TargetProcessor; + UINT32 Ulong; +} COORDINATED_DEPENDENCY_INFO, *PCOORDINATED_DEPENDENCY_INFO; + +typedef struct { + COORDINATED_DEPENDENCY_INFO DependencyInfo[PEP_MAX_DEPENDENCIES_PER_STATE]; + UINT32 StateType; + UINT32 Ulong; + UINT32 Latency; + UINT32 BreakEvenDuration; + UINT32 DependencyCount; + UINT32 MaximumDependencySize; +} COORDINATED_STATE_INFO; + +typedef struct { + UINT32 Unused; +} PEP_PROCESSOR_PERF_INFO; + +typedef struct { + UINT32 FState[MAX_COMPONENT_COUNT]; +} COORDINATED_FSTATE_REQUIREMENT; + +typedef struct { + UINT32 DState; +} COORDINATED_DSTATE_REQUIREMENT; + +// +// Top level device table +// *N.B. The exact length of the structure is determined by the NumberIdleStates/NumberPerfStates variables. +// + +typedef struct _PEP_PROCESSOR_INFO_PLAT { + WCHAR DevicePath[MAX_PROCESSOR_PATH_LENGTH]; // Null-terminated ACPI name + ULONG FeedbackCounterCount; + ULONG Flags; + + // + // We are putting the idle/perf state count here (instead + // of the PEP_PROCESSOR_xxx_INFO structure for the ease of parsing. + // + ULONG NumberIdleStates; + ULONG NumberPerfStates; + + PEP_PROCESSOR_IDLE_INFO_PLAT IdleInfo; + PEP_PROCESSOR_PERF_INFO PerfInfo; +} PEP_PROCESSOR_INFO_PLAT, *PPEP_PROCESSOR_INFO_PLAT; + +typedef struct _PEP_PROCESSOR_TABLE_PLAT { + UINT32 Version; + UINT32 NumberProcessors; + PEP_PROCESSOR_INFO_PLAT ProcessorInfo[P_NUMBER_PROCESSORS]; +} PEP_PROCESSOR_TABLE_PLAT; + +typedef struct _PEP_COORDINATED_STATE_TABLE_PLAT { + ULONG Version; + ULONG CoordinatedStateCount; + COORDINATED_STATE_INFO CoordinatedStates[P_NUMBER_COORDINATED_STATS]; +} PEP_COORDINATED_STATE_TABLE_PLAT, *PPEP_COORDINATED_STATE_TABLE_PLAT; + +typedef struct _PEP_DEVICE_INFO_PLAT { + WCHAR DevicePath[MAX_DEVICE_PATH_LENGTH]; // Null-terminated ACPI name + ULONG DStateSupportMask; + ULONG NumberComponents; + + COORDINATED_DSTATE_REQUIREMENT DStateRequirement[P_NUMBER_COORDINATED_STATS]; + COORDINATED_FSTATE_REQUIREMENT FStateRequirement[P_NUMBER_COORDINATED_STATS]; +} PEP_DEVICE_INFO_PLAT, *PPEP_DEVICE_INFO_PLAT; + +typedef struct _PEP_DEVICE_TABLE_PLAT { + ULONG Version; + ULONG NumberDevices; + PEP_DEVICE_INFO_PLAT DeviceInfo[P_NUMBER_DEVICES]; +} PEP_DEVICE_TABLE_PLAT, *PPEP_DEVICE_TABLE_PLAT; + +#endif diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Platform.h b/Platform/Broadcom/Bcm283x/AcpiTables/Platform.h new file mode 100644 index 000000000000..826182698fd0 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Platform.h @@ -0,0 +1,82 @@ +/** @file + * + * RPi3 Platform specific defines for constructing ACPI tables + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) Microsoft Corporation. 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 _Platform_H_INCLUDED_ +#define _Platform_H_INCLUDED_ + +#include + +#define EFI_ACPI_OEM_ID {'M','C','R','S','F','T'} // OEMID 6 bytes long +#define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('R','P','I','3','E','D','K','2') // OEM table id 8 bytes long +#define EFI_ACPI_OEM_REVISION 0x02000820 +#define EFI_ACPI_CREATOR_ID SIGNATURE_32('R','P','I','3') +#define EFI_ACPI_CREATOR_REVISION 0x00000097 + +#define EFI_ACPI_VENDOR_ID SIGNATURE_32('M','S','F','T') +#define EFI_ACPI_CSRT_REVISION 0x00000005 +#define EFI_ACPI_CSRT_DEVICE_ID_DMA 0x00000009 // fixed id +#define EFI_ACPI_CSRT_RESOURCE_ID_IN_DMA_GRP 0x0 // count up from 0 + +#define RPI3_DMA_CHANNEL_COUNT 10 // all 10 DMA channels are listed, including the reserved ones +#define RPI3_DMA_USED_CHANNEL_COUNT 5 // use 5 DMA channels + +#define EFI_ACPI_5_0_CSRT_REVISION 0x00000000 + +typedef enum +{ + EFI_ACPI_CSRT_RESOURCE_TYPE_RESERVED, // 0 + EFI_ACPI_CSRT_RESOURCE_TYPE_INTERRUPT, // 1 + EFI_ACPI_CSRT_RESOURCE_TYPE_TIMER, // 2 + EFI_ACPI_CSRT_RESOURCE_TYPE_DMA, // 3 + EFI_ACPI_CSRT_RESOURCE_TYPE_CACHE, // 4 +} +CSRT_RESOURCE_TYPE; + +typedef enum +{ + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CHANNEL, // 0 + EFI_ACPI_CSRT_RESOURCE_SUBTYPE_DMA_CONTROLLER // 1 +} +CSRT_DMA_SUBTYPE; + +//------------------------------------------------------------------------ +// CSRT Resource Group header 24 bytes long +//------------------------------------------------------------------------ +typedef struct +{ + UINT32 Length; // Length + UINT32 VendorID; // 4 bytes + UINT32 SubVendorId; // 4 bytes + UINT16 DeviceId; // 2 bytes + UINT16 SubdeviceId; // 2 bytes + UINT16 Revision; // 2 bytes + UINT16 Reserved; // 2 bytes + UINT32 SharedInfoLength; // 4 bytes +} EFI_ACPI_5_0_CSRT_RESOURCE_GROUP_HEADER; + +//------------------------------------------------------------------------ +// CSRT Resource Descriptor 12 bytes total +//------------------------------------------------------------------------ +typedef struct +{ + UINT32 Length; // 4 bytes + UINT16 ResourceType; // 2 bytes + UINT16 ResourceSubType; // 2 bytes + UINT32 UID; // 4 bytes +} EFI_ACPI_5_0_CSRT_RESOURCE_DESCRIPTOR_HEADER; + +#endif // of _Platform_H_INCLUDED_ diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Rhpx.asl b/Platform/Broadcom/Bcm283x/AcpiTables/Rhpx.asl new file mode 100644 index 000000000000..b197aa53fed4 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Rhpx.asl @@ -0,0 +1,201 @@ +/** @file + * + * [DSDT] RHProxy device to enable WinRT API (RHPX) + * + * Copyright (c) 2018, Andrey Warkentin + * Copyright (c) Microsoft Corporation. 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. + * + **/ + +Device(RHPX) +{ + Name(_HID, "MSFT8000") + Name(_CID, "MSFT8000") + Name(_UID, 1) + + Name(_CRS, ResourceTemplate() + { + // Index 0 + SPISerialBus( // SCKL - GPIO 11 - Pin 23 + // MOSI - GPIO 10 - Pin 19 + // MISO - GPIO 9 - Pin 21 + // CE0 - GPIO 8 - Pin 24 + 0, // Device selection (CE0) + PolarityLow, // Device selection polarity + FourWireMode, // wiremode + 8, // databit len + ControllerInitiated, // slave mode + 4000000, // connection speed + ClockPolarityLow, // clock polarity + ClockPhaseFirst, // clock phase + "\\_SB.SPI0", // ResourceSource: SPI bus controller name + 0, // ResourceSourceIndex + // Resource usage + // DescriptorName: creates name for offset of resource descriptor + ) // Vendor Data + + // Index 1 + SPISerialBus( // SCKL - GPIO 11 - Pin 23 + // MOSI - GPIO 10 - Pin 19 + // MISO - GPIO 9 - Pin 21 + // CE1 - GPIO 7 - Pin 26 + 1, // Device selection (CE1) + PolarityLow, // Device selection polarity + FourWireMode, // wiremode + 8, // databit len + ControllerInitiated, // slave mode + 4000000, // connection speed + ClockPolarityLow, // clock polarity + ClockPhaseFirst, // clock phase + "\\_SB.SPI0", // ResourceSource: SPI bus controller name + 0, // ResourceSourceIndex + // Resource usage + // DescriptorName: creates name for offset of resource descriptor + ) // Vendor Data + + // Index 2 + I2CSerialBus( // Pin 3 (GPIO2, SDA1), 5 (GPIO3, SCL1) + 0xFFFF, // SlaveAddress: placeholder + , // SlaveMode: default to ControllerInitiated + 0, // ConnectionSpeed: placeholder + , // Addressing Mode: default to 7 bit + "\\_SB.I2C1", // ResourceSource: I2C bus controller name + , + , + , // Descriptor Name: creates name for offset of resource descriptor + ) // VendorData + + // Index 3 + SPISerialBus( // SPI1_SCLK - GPIO21 + // SPI1_MOSI - GPIO20 + // SPI1_MISO - GPIO19 + // SPI1_CE2_N - GPIO16 + 2, // Device selection (CE2) + PolarityLow, // Device selection polarity + FourWireMode, // wiremode + 8, // databit len + ControllerInitiated, // slave mode + 4000000, // connection speed + ClockPolarityLow, // clock polarity + ClockPhaseFirst, // clock phase + "\\_SB.SPI1", // ResourceSource: SPI bus controller name + 0, // ResourceSourceIndex + // Resource usage + // DescriptorName: creates name for offset of resource descriptor + ) // Vendor Data + + // GPIO 2 + GpioIO(Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 2 } + GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPI0",) { 2 } + // GPIO 3 + GpioIO(Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 3 } + GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPI0",) { 3 } + // GPIO 4 + GpioIO(Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 4 } + GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPI0",) { 4 } + // GPIO 5 + GpioIO(Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 5 } + GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPI0",) { 5 } + // GPIO 6 + GpioIO(Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 6 } + GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPI0",) { 6 } + // GPIO 7 + GpioIO(Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 7 } + GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPI0",) { 7 } + // GPIO 8 + GpioIO(Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 8 } + GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPI0",) { 8 } + // GPIO 9 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 9 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 9 } + // GPIO 10 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 10 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 10 } + // GPIO 11 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 11 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 11 } + // GPIO 12 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 12 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 12 } + // GPIO 13 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 13 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 13 } + // NTRAID#MSFT-7141401-2016/04/7-jordanrh - disable UART muxing + // until a proper solution can be created for the dmap conflict + // GPIO 14 - UART TX + // GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 14 } + // GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 14 } + // GPIO 15 - UART RX + // GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 15 } + // GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 15 } + // GPIO 16 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 16 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 16 } + // GPIO 17 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 17 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 17 } + // GPIO 18 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 18 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 18 } + // GPIO 19 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 19 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 19 } + // GPIO 20 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 20 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 20 } + // GPIO 21 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 21 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 21 } + // GPIO 22 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 22 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 22 } + // GPIO 23 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 23 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 23 } + // GPIO 24 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 24 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 24 } + // GPIO 25 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 25 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 25 } + // GPIO 26 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 26 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 26 } + // GPIO 27 + GpioIO(Shared, PullDown, 0, 0, IoRestrictionNone, "\\_SB.GPI0", 0, ResourceConsumer, , ) { 27 } + GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 27 } + }) + + Name(_DSD, Package() + { + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + Package() + { + // Reference http://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md + // SPI 0 + Package(2) { "bus-SPI-SPI0", Package() { 0, 1 }}, // Index 0 & 1 + Package(2) { "SPI0-MinClockInHz", 7629 }, // 7629 Hz + Package(2) { "SPI0-MaxClockInHz", 125000000 }, // 125 MHz + Package(2) { "SPI0-SupportedDataBitLengths", Package() { 8 }}, // Data Bit Length + // I2C1 + Package(2) { "bus-I2C-I2C1", Package() { 2 }}, + // GPIO Pin Count and supported drive modes + Package (2) { "GPIO-PinCount", 54 }, + Package (2) { "GPIO-UseDescriptorPinNumbers", 1 }, + Package (2) { "GPIO-SupportedDriveModes", 0xf }, // InputHighImpedance, InputPullUp, InputPullDown, OutputCmos + // SPI 1 + Package(2) { "bus-SPI-SPI1", Package() { 3 }}, // Index 3 + Package(2) { "SPI1-MinClockInHz", 30511 }, // 30.5 kHz + Package(2) { "SPI1-MaxClockInHz", 20000000 }, // 20 MHz + Package(2) { "SPI1-SupportedDataBitLengths", Package() { 8 }}, // Data Bit Length + } + }) +} diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Sdhc.asl b/Platform/Broadcom/Bcm283x/AcpiTables/Sdhc.asl new file mode 100644 index 000000000000..a39138ce5c5c --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Sdhc.asl @@ -0,0 +1,105 @@ +/** @file + * + * [DSDT] SD controller/card definition (SDHC) + * + * Copyright (c) 2018, Andrey Warkentin + * Copyright (c) Microsoft Corporation. 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. + * + **/ + +// +// Note: UEFI can use either SDHost or Arasan. We expose both to the OS. +// + +// +// Description: This is ArasanSD 3.0 SD Host Controller. +// + +Device (SDC1) +{ + Name (_HID, "BCM2847") + Name (_CID, "ARASAN") + Name (_UID, 0x0) + Name (_S1D, 0x1) + Name (_S2D, 0x1) + Name (_S3D, 0x1) + Name (_S4D, 0x1) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + MEMORY32FIXED(ReadWrite, 0x3F300000, 0x100, ) + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x5E } + }) + Return(RBUF) + } + + // + // A child device that represents the + // sd card, which is marked as non-removable. + // + Device (SDMM) + { + Method (_ADR) + { + Return (0) + } + Method (_RMV) // Is removable + { + Return (0) // 0 - fixed + } + } +} + + +// +// Description: This is Broadcom SDHost 2.0 SD Host Controller +// + +Device (SDC2) +{ + Name (_HID, "BCM2855") + Name (_CID, "SDHST") + Name (_UID, 0x0) + Name (_S1D, 0x1) + Name (_S2D, 0x1) + Name (_S3D, 0x1) + Name (_S4D, 0x1) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + MEMORY32FIXED(ReadWrite, 0x3F202000, 0x100, ) + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x58 } + }) + Return(RBUF) + } + + // + // A child device that represents the + // sd card, which is marked as non-removable. + // + Device (SDMM) + { + Method (_ADR) + { + Return (0) + } + Method (_RMV) // Is removable + { + Return (0) // 0 - fixed + } + } +} diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Spcr.asl b/Platform/Broadcom/Bcm283x/AcpiTables/Spcr.asl new file mode 100644 index 000000000000..a6fbfd08e021 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Spcr.asl @@ -0,0 +1,53 @@ +/** @file + * + * Serial Port Console Redirection Table (SPCR) + * + * Copyright (c) 2017-2018, Andrey Warkentin + * + * 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. + * + **/ + +[000h 0000 4] Signature : "SPCR" [Serial Port Console Redirection table] +[004h 0004 4] Table Length : 00000050 +[008h 0008 1] Revision : 01 +[009h 0009 1] Checksum : 00 +[00Ah 0010 6] Oem ID : "RPiEFI" +[010h 0016 8] Oem Table ID : "RPi3UEFI" +[018h 0024 4] Oem Revision : 00000001 +[01Ch 0028 4] Asl Compiler ID : "----" +[020h 0032 4] Asl Compiler Revision : 00000000 + +[024h 0036 1] Interface Type : 10 +[025h 0037 3] Reserved : 000000 + +[028h 0040 12] Serial Port Register : [Generic Address Structure] +[028h 0040 1] Space ID : 00 [SystemMemory] +[029h 0041 1] Bit Width : 20 +[02Ah 0042 1] Bit Offset : 00 +[02Bh 0043 1] Encoded Access Width : 02 [DWord Access:32] +[02Ch 0044 8] Address : 000000003f215000 + +[034h 0052 1] Interrupt Type : 0E +[035h 0053 1] PCAT-compatible IRQ : 00 +[036h 0054 4] Interrupt : 3D +[03Ah 0058 1] Baud Rate : 07 +[03Bh 0059 1] Parity : 00 +[03Ch 0060 1] Stop Bits : 01 +[03Dh 0061 1] Flow Control : 00 +[03Eh 0062 1] Terminal Type : 00 +[04Ch 0076 1] Reserved : 00 +[040h 0064 2] PCI Device ID : FFFF +[042h 0066 2] PCI Vendor ID : FFFF +[044h 0068 1] PCI Bus : 00 +[045h 0069 1] PCI Device : 00 +[046h 0070 1] PCI Function : 00 +[047h 0071 4] PCI Flags : 00000000 +[04Bh 0075 1] PCI Segment : 00 +[04Ch 0076 4] Reserved : 00000000 diff --git a/Platform/Broadcom/Bcm283x/AcpiTables/Uart.asl b/Platform/Broadcom/Bcm283x/AcpiTables/Uart.asl new file mode 100644 index 000000000000..fa92cf24db91 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/AcpiTables/Uart.asl @@ -0,0 +1,155 @@ +/** @file + * + * [DSDT] Serial devices (UART). + * + * Copyright (c) 2018, Andrey Warkentin + * Copyright (c) Microsoft Corporation. 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. + * + **/ + +// +// Description: This is the PL011 based UART. +// + +Device (URT0) +{ + Name (_HID, "BCM2837") + Name (_CID, "HID3123") + Name (_UID, 0x4) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + MEMORY32FIXED(ReadWrite, 0x3F201000, 0x1000, ) + Interrupt(ResourceConsumer, Level, ActiveHigh, Exclusive) { 0x59 } + }) + Return(RBUF) + } + + Name (CLCK, 3000000) + + Name (_DSD, Package () { + ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), + Package () { + Package (2) { "clock-frequency", CLCK }, + } + }) +} + +// +// Description: UART Mini. +// +// This device is referenced in the DBG2 table, which will cause the system to +// not start the driver when the debugger is enabled and to mark the device +// with problem code 53 (CM_PROB_USED_BY_DEBUGGER). +// + +Device (URTM) +{ + Name (_HID, "BCM2836") + Name (_CID, "MINIUART") + Name (_UID, 0x0) + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + MEMORY32FIXED(ReadWrite, 0x3F215000, 0x70, ) + Interrupt(ResourceConsumer, Level, ActiveHigh, Shared) {0x3D} + + // NTRAID#MSFT-7141401-2016/04/7-jordanrh - disable UART muxing + // until a proper solution can be created for the dmap conflict. + // When muxing is enabled, must consider DBG2 table conflict. + // The alternate function resource needs to be reserved when + // the kernel debugger is enabled to prevent another client + // from muxing the pins away. + + // + // MsftFunctionConfig is encoded as the VendorLong. + // + // MsftFunctionConfig(Exclusive, PullDown, BCM_ALT5, "\\_SB.GPI0", 0, ResourceConsumer, ) {14, 15} + // VendorLong () // Length = 0x31 + // { + // /* 0000 */ 0x00, 0x60, 0x44, 0xD5, 0xF3, 0x1F, 0x11, 0x60, // .`D....` + // /* 0008 */ 0x4A, 0xB8, 0xB0, 0x9C, 0x2D, 0x23, 0x30, 0xDD, // J...-#0. + // /* 0010 */ 0x2F, 0x8D, 0x1D, 0x00, 0x01, 0x10, 0x00, 0x02, // /....... + // /* 0018 */ 0x02, 0x00, 0x12, 0x00, 0x00, 0x16, 0x00, 0x20, // ....... + // /* 0020 */ 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x5C, // .......\ + // /* 0028 */ 0x5F, 0x53, 0x42, 0x2E, 0x47, 0x50, 0x49, 0x30, // _SB.GPI0 + // /* 0030 */ 0x00 // . + //} + + }) + Return(RBUF) + } +} + +// +// Multifunction serial bus device to support Bluetooth function. +// + +Device(BTH0) +{ + Name (_HID, "BCM2EA6") + Name (_CID, "BCM2EA6") + Method (_STA) + { + Return(0xf) + } + Method (_CRS, 0x0, Serialized) { + Name (RBUF, ResourceTemplate () { + // + // BT UART: UART0 (PL011) + // + UARTSerialBus( + 115200, // InitialBaudRate: in BPS + , // BitsPerByte: default to 8 bits + , // StopBits: Defaults to one bit + 0x00, // LinesInUse: 8 1-bit flags to + // declare enabled control lines. + // Raspberry Pi does not exposed + // HW control signals -> not supported. + // Optional bits: + // - Bit 7 (0x80) Request To Send (RTS) + // - Bit 6 (0x40) Clear To Send (CTS) + // - Bit 5 (0x20) Data Terminal Ready (DTR) + // - Bit 4 (0x10) Data Set Ready (DSR) + // - Bit 3 (0x08) Ring Indicator (RI) + // - Bit 2 (0x04) Data Carrier Detect (DTD) + // - Bit 1 (0x02) Reserved. Must be 0. + // - Bit 0 (0x01) Reserved. Must be 0. + , // IsBigEndian: + // default to LittleEndian. + , // Parity: Defaults to no parity + , // FlowControl: Defaults to + // no flow control. + 16, // ReceiveBufferSize + 16, // TransmitBufferSize + "\\_SB.URT0", // ResourceSource: + // UART bus controller name + , // ResourceSourceIndex: assumed to be 0 + , // ResourceUsage: assumed to be + // ResourceConsumer + UAR0, // DescriptorName: creates name + // for offset of resource descriptor + ) // Vendor data + + // + // RPIQ connection for BT_ON/OFF + // + GpioIO(Shared, PullUp, 0, 0, IoRestrictionNone, "\\_SB.RPIQ", 0, ResourceConsumer, , ) { 128 } + }) + Return(RBUF) + } +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.c b/Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.c new file mode 100644 index 000000000000..a070b6d5d8d9 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.c @@ -0,0 +1,730 @@ +/** @file + * + * Copyright (c) 2017, Andrei Warkentin + * Copyright (c) Microsoft Corporation. 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 "ArasanMmcHostDxe.h" + +#define DEBUG_MMCHOST_SD DEBUG_VERBOSE + +BOOLEAN PreviousIsCardPresent = FALSE; +UINT32 LastExecutedCommand = (UINT32) -1; + +STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol; + +/** + These SD commands are optional, according to the SD Spec +**/ +BOOLEAN +IgnoreCommand( + UINT32 Command + ) +{ + switch (Command) { + case MMC_CMD20: + return TRUE; + default: + return FALSE; + } +} + +/** + Translates a generic SD command into the format used by the Arasan SD Host Controller +**/ +UINT32 +TranslateCommand( + UINT32 Command, + UINT32 Argument + ) +{ + UINT32 Translation = 0xffffffff; + + if (LastExecutedCommand == CMD55) { + switch (Command) { + case MMC_CMD6: + Translation = ACMD6; + DEBUG((DEBUG_MMCHOST_SD, "ACMD6\n")); + break; + case MMC_ACMD22: + Translation = ACMD22; + DEBUG((DEBUG_MMCHOST_SD, "ACMD22\n")); + break; + case MMC_ACMD41: + Translation = ACMD41; + DEBUG((DEBUG_MMCHOST_SD, "ACMD41\n")); + break; + case MMC_ACMD51: + Translation = ACMD51; + DEBUG((DEBUG_MMCHOST_SD, "ACMD51\n")); + break; + default: + DEBUG((DEBUG_ERROR, "ArasanMMCHost: TranslateCommand(): Unrecognized App command: %d\n", Command)); + } + } else { + switch (Command) { + case MMC_CMD0: + Translation = CMD0; + break; + case MMC_CMD1: + Translation = CMD1; + break; + case MMC_CMD2: + Translation = CMD2; + break; + case MMC_CMD3: + Translation = CMD3; + break; + case MMC_CMD5: + Translation = CMD5; + break; + case MMC_CMD6: + Translation = CMD6; + break; + case MMC_CMD7: + Translation = CMD7; + break; + case MMC_CMD8: { + if (Argument == CMD8_SD_ARG) { + Translation = CMD8_SD; + DEBUG((DEBUG_MMCHOST_SD, "Sending SD CMD8 variant\n")); + } else { + ASSERT (Argument == CMD8_MMC_ARG); + Translation = CMD8_MMC; + DEBUG((DEBUG_MMCHOST_SD, "Sending MMC CMD8 variant\n")); + } + break; + } + case MMC_CMD9: + Translation = CMD9; + break; + case MMC_CMD11: + Translation = CMD11; + break; + case MMC_CMD12: + Translation = CMD12; + break; + case MMC_CMD13: + Translation = CMD13; + break; + case MMC_CMD16: + Translation = CMD16; + break; + case MMC_CMD17: + Translation = CMD17; + break; + case MMC_CMD18: + Translation = CMD18; + break; + case MMC_CMD23: + Translation = CMD23; + break; + case MMC_CMD24: + Translation = CMD24; + break; + case MMC_CMD25: + Translation = CMD25; + break; + case MMC_CMD55: + Translation = CMD55; + break; + default: + DEBUG((DEBUG_ERROR, "ArasanMMCHost: TranslateCommand(): Unrecognized Command: %d\n", Command)); + } + } + + return Translation; +} + +/** + Repeatedly polls a register until its value becomes correct, or until MAX_RETRY_COUNT polls is reached +**/ +EFI_STATUS +PollRegisterWithMask( + IN UINTN Register, + IN UINTN Mask, + IN UINTN ExpectedValue + ) +{ + UINTN RetryCount = 0; + + while (RetryCount < MAX_RETRY_COUNT) { + if ((MmioRead32(Register) & Mask) != ExpectedValue) { + RetryCount++; + gBS->Stall(STALL_AFTER_RETRY_US); + } else { + break; + } + } + + if (RetryCount == MAX_RETRY_COUNT) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SoftReset( + IN UINT32 Mask + ) +{ + MmioOr32(MMCHS_SYSCTL, Mask); + if (PollRegisterWithMask(MMCHS_SYSCTL, Mask, 0) == EFI_TIMEOUT) { + DEBUG((DEBUG_ERROR, "Failed to SoftReset with mask 0x%x\n", Mask)); + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +/** + Calculate the clock divisor +**/ +EFI_STATUS +CalculateClockFrequencyDivisor( + IN UINTN TargetFrequency, + OUT UINT32 *DivisorValue, + OUT UINTN *ActualFrequency + ) +{ + EFI_STATUS Status; + UINT32 Divisor; + UINT32 BaseFrequency = 0; + + Status = mFwProtocol->GetClockRate(RPI_FW_CLOCK_RATE_EMMC, &BaseFrequency); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "Couldn't get RPI_FW_CLOCK_RATE_EMMC\n")); + return Status; + } + + ASSERT (BaseFrequency != 0); + Divisor = BaseFrequency / TargetFrequency; + + // Arasan controller is based on 3.0 spec so the div is multiple of 2 + // Actual Frequency = BaseFequency/(Div*2) + Divisor /= 2; + + if ((TargetFrequency < BaseFrequency) && + (TargetFrequency * 2 * Divisor != BaseFrequency)) { + Divisor += 1; + } + + if (Divisor > MAX_DIVISOR_VALUE) { + Divisor = MAX_DIVISOR_VALUE; + } + + DEBUG((DEBUG_MMCHOST_SD, "ArasanMMCHost: BaseFrequency 0x%x Divisor 0x%x\n", BaseFrequency, Divisor)); + + *DivisorValue = (Divisor & 0xFF) << 8; + Divisor >>= 8; + *DivisorValue |= (Divisor & 0x03) << 6; + + if (ActualFrequency) { + if (Divisor == 0) { + *ActualFrequency = BaseFrequency; + } else { + *ActualFrequency = BaseFrequency / Divisor; + *ActualFrequency >>= 1; + } + DEBUG((DEBUG_MMCHOST_SD, "ArasanMMCHost: *ActualFrequency 0x%x\n", *ActualFrequency)); + } + + DEBUG((DEBUG_MMCHOST_SD, "ArasanMMCHost: *DivisorValue 0x%x\n", *DivisorValue)); + + return EFI_SUCCESS; +} + +BOOLEAN +MMCIsCardPresent( + IN EFI_MMC_HOST_PROTOCOL *This + ) +{ + return TRUE; +} + +BOOLEAN +MMCIsReadOnly( + IN EFI_MMC_HOST_PROTOCOL *This + ) +{ + BOOLEAN IsReadOnly = !((MmioRead32(MMCHS_PRES_STATE) & WRITE_PROTECT_OFF) == WRITE_PROTECT_OFF); + DEBUG((DEBUG_MMCHOST_SD, "ArasanMMCHost: MMCIsReadOnly(): %d\n", IsReadOnly)); + return IsReadOnly; +} + +EFI_STATUS +MMCBuildDevicePath( + IN EFI_MMC_HOST_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode; + EFI_GUID DevicePathGuid = EFI_CALLER_ID_GUID; + + DEBUG((DEBUG_MMCHOST_SD, "ArasanMMCHost: MMCBuildDevicePath()\n")); + + NewDevicePathNode = CreateDeviceNode(HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof(VENDOR_DEVICE_PATH)); + CopyGuid(&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &DevicePathGuid); + *DevicePath = NewDevicePathNode; + + return EFI_SUCCESS; +} + +EFI_STATUS +MMCSendCommand( + IN EFI_MMC_HOST_PROTOCOL *This, + IN MMC_CMD MmcCmd, + IN UINT32 Argument + ) +{ + UINTN MmcStatus; + UINTN RetryCount = 0; + UINTN CmdSendOKMask; + EFI_STATUS Status = EFI_SUCCESS; + BOOLEAN IsAppCmd = (LastExecutedCommand == CMD55); + BOOLEAN IsDATCmd = FALSE; + BOOLEAN IsADTCCmd = FALSE; + + DEBUG((DEBUG_MMCHOST_SD, "ArasanMMCHost: MMCSendCommand(MmcCmd: %08x, Argument: %08x)\n", MmcCmd, Argument)); + + if (IgnoreCommand(MmcCmd)) { + return EFI_SUCCESS; + } + + MmcCmd = TranslateCommand(MmcCmd, Argument); + if (MmcCmd == 0xffffffff) { + return EFI_UNSUPPORTED; + } + + if ((MmcCmd & CMD_R1_ADTC) == CMD_R1_ADTC) { + IsADTCCmd = TRUE; + } + if (((MmcCmd & CMD_R1B) == CMD_R1B && + /* + * Abort commands don't get inhibited by DAT. + */ + (MmcCmd & TYPE(CMD_TYPE_ABORT)) != TYPE(CMD_TYPE_ABORT)) || + IsADTCCmd || + /* + * We want to detect BRR/BWR change. + */ + MmcCmd == CMD_SEND_STATUS) { + IsDATCmd = TRUE; + } + + CmdSendOKMask = CMDI_MASK; + if (IsDATCmd) { + CmdSendOKMask |= DATI_MASK; + } + + if (PollRegisterWithMask(MMCHS_PRES_STATE, + CmdSendOKMask, 0) == EFI_TIMEOUT) { + DEBUG((DEBUG_ERROR, "%a(%u): not ready for MMC_CMD%u PresState 0x%x MmcStatus 0x%x\n", + __FUNCTION__, __LINE__, MMC_CMD_NUM(MmcCmd), + MmioRead32(MMCHS_PRES_STATE), + MmioRead32(MMCHS_INT_STAT))); + Status = EFI_TIMEOUT; + goto out; + } + + if (IsAppCmd && MmcCmd == ACMD22) { + MmioWrite32(MMCHS_BLK, 4); + } else if (IsAppCmd && MmcCmd == ACMD51) { + MmioWrite32(MMCHS_BLK, 8); + } else if (!IsAppCmd && MmcCmd == CMD6) { + MmioWrite32(MMCHS_BLK, 64); + } else if (IsADTCCmd) { + MmioWrite32(MMCHS_BLK, BLEN_512BYTES); + } + + // Set Data timeout counter value to max value. + MmioAndThenOr32(MMCHS_SYSCTL, (UINT32) ~DTO_MASK, DTO_VAL); + + // + // Clear Interrupt Status Register, but not the Card Inserted bit + // to avoid messing with card detection logic. + // + MmioWrite32(MMCHS_INT_STAT, ALL_EN & ~(CARD_INS)); + + // Set command argument register + MmioWrite32(MMCHS_ARG, Argument); + + // Send the command + MmioWrite32(MMCHS_CMD, MmcCmd); + + // Check for the command status. + while (RetryCount < MAX_RETRY_COUNT) { + MmcStatus = MmioRead32(MMCHS_INT_STAT); + + // Read status of command response + if ((MmcStatus & ERRI) != 0) { + // + // CMD5 (CMD_IO_SEND_OP_COND) is only valid for SDIO + // cards and thus expected to fail. + // + if (MmcCmd != CMD_IO_SEND_OP_COND) { + DEBUG((DEBUG_ERROR, "%a(%u): MMC_CMD%u ERRI MmcStatus 0x%x\n", + __FUNCTION__, __LINE__, MMC_CMD_NUM(MmcCmd), MmcStatus)); + } + + SoftReset(SRC); + + Status = EFI_DEVICE_ERROR; + goto out; + } + + // Check if command is completed. + if ((MmcStatus & CC) == CC) { + MmioWrite32(MMCHS_INT_STAT, CC); + break; + } + + RetryCount++; + gBS->Stall(STALL_AFTER_RETRY_US); + } + + gBS->Stall(STALL_AFTER_SEND_CMD_US); + + if (RetryCount == MAX_RETRY_COUNT) { + DEBUG((DEBUG_ERROR, "%a(%u): MMC_CMD%u completion TIMEOUT PresState 0x%x MmcStatus 0x%x\n", + __FUNCTION__, __LINE__, MMC_CMD_NUM(MmcCmd), + MmioRead32(MMCHS_PRES_STATE), + MmcStatus)); + Status = EFI_TIMEOUT; + goto out; + } + + out: + if (EFI_ERROR(Status)) { + LastExecutedCommand = (UINT32) -1; + } else { + LastExecutedCommand = MmcCmd; + } + return Status; +} + +EFI_STATUS +MMCNotifyState( + IN EFI_MMC_HOST_PROTOCOL *This, + IN MMC_STATE State + ) +{ + DEBUG((DEBUG_MMCHOST_SD, "ArasanMMCHost: MMCNotifyState(State: %d)\n", State)); + + switch (State) { + case MmcHwInitializationState: + { + EFI_STATUS Status; + UINT32 Divisor; + + Status = SoftReset(SRA); + if (EFI_ERROR(Status)) { + return Status; + } + + // Attempt to set the clock to 400Khz which is the expected initialization speed + Status = CalculateClockFrequencyDivisor(400000, &Divisor, NULL); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "ArasanMMCHost: MMCNotifyState(): Fail to initialize SD clock\n")); + return Status; + } + + // Set Data Timeout Counter value, set clock frequency, enable internal clock + MmioOr32(MMCHS_SYSCTL, DTO_VAL | Divisor | CEN | ICS | ICE); + + // Enable interrupts + MmioWrite32(MMCHS_IE, ALL_EN); + } + break; + case MmcIdleState: + break; + case MmcReadyState: + break; + case MmcIdentificationState: + break; + case MmcStandByState: { + EFI_STATUS Status; + UINTN ClockFrequency = 25000000; + UINT32 Divisor; + + // First turn off the clock + MmioAnd32(MMCHS_SYSCTL, ~CEN); + + Status = CalculateClockFrequencyDivisor(ClockFrequency, &Divisor, NULL); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "ArasanMMCHost: MmcStandByState(): Fail to initialize SD clock to %u Hz\n", + ClockFrequency)); + return Status; + } + + // Setup new divisor + MmioAndThenOr32(MMCHS_SYSCTL, (UINT32) ~CLKD_MASK, Divisor); + + // Wait for the clock to stabilise + while ((MmioRead32(MMCHS_SYSCTL) & ICS_MASK) != ICS); + + // Set Data Timeout Counter value, set clock frequency, enable internal clock + MmioOr32(MMCHS_SYSCTL, CEN); + } + break; + case MmcTransferState: + break; + case MmcSendingDataState: + break; + case MmcReceiveDataState: + break; + case MmcProgrammingState: + break; + case MmcDisconnectState: + case MmcInvalidState: + default: + DEBUG((DEBUG_ERROR, "ArasanMMCHost: MMCNotifyState(): Invalid State: %d\n", State)); + ASSERT(0); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +MMCReceiveResponse( + IN EFI_MMC_HOST_PROTOCOL *This, + IN MMC_RESPONSE_TYPE Type, + IN UINT32* Buffer + ) +{ + ASSERT (Buffer != NULL); + + if (Type == MMC_RESPONSE_TYPE_R2) { + + // 16-byte response + Buffer[0] = MmioRead32(MMCHS_RSP10); + Buffer[1] = MmioRead32(MMCHS_RSP32); + Buffer[2] = MmioRead32(MMCHS_RSP54); + Buffer[3] = MmioRead32(MMCHS_RSP76); + + Buffer[3] <<= 8; + Buffer[3] |= (Buffer[2] >> 24) & 0xFF; + Buffer[2] <<= 8; + Buffer[2] |= (Buffer[1] >> 24) & 0xFF; + Buffer[1] <<= 8; + Buffer[1] |= (Buffer[0] >> 24) & 0xFF; + Buffer[0] <<= 8; + + DEBUG(( + DEBUG_MMCHOST_SD, + "ArasanMMCHost: MMCReceiveResponse(Type: %x), Buffer[0-3]: %08x, %08x, %08x, %08x\n", + Type, Buffer[0], Buffer[1], Buffer[2], Buffer[3])); + } else { + // 4-byte response + Buffer[0] = MmioRead32(MMCHS_RSP10); + DEBUG((DEBUG_MMCHOST_SD, "ArasanMMCHost: MMCReceiveResponse(Type: %08x), Buffer[0]: %08x\n", Type, Buffer[0])); + } + + gBS->Stall(STALL_AFTER_REC_RESP_US); + if (LastExecutedCommand == CMD_STOP_TRANSMISSION) { + DEBUG((DEBUG_MMCHOST_SD, "ArasanMMCHost: soft-resetting after CMD12\n")); + return SoftReset(SRC | SRD); + } + return EFI_SUCCESS; +} + +EFI_STATUS +MMCReadBlockData( + IN EFI_MMC_HOST_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Length, + IN UINT32* Buffer + ) +{ + UINTN MmcStatus; + UINTN RemLength; + UINTN Count; + + DEBUG((DEBUG_VERBOSE, "%a(%u): LBA: 0x%x, Length: 0x%x, Buffer: 0x%x)\n", + __FUNCTION__, __LINE__, Lba, Length, Buffer)); + + if (Buffer == NULL) { + DEBUG((DEBUG_ERROR, "%a(%u): NULL Buffer\n", + __FUNCTION__, __LINE__)); + return EFI_INVALID_PARAMETER; + } + + if (Length % sizeof(UINT32) != 0) { + DEBUG((DEBUG_ERROR, "%a(%u): bad Length %u\n", + __FUNCTION__, __LINE__, Length)); + return EFI_INVALID_PARAMETER; + } + + RemLength = Length; + while (RemLength != 0) { + UINTN RetryCount = 0; + UINT32 BlockLen = MIN(RemLength, BLEN_512BYTES); + + while (RetryCount < MAX_RETRY_COUNT) { + MmcStatus = MmioRead32(MMCHS_INT_STAT); + if ((MmcStatus & BRR) != 0) { + MmioWrite32(MMCHS_INT_STAT, BRR); + /* + * Data is ready. + */ + mFwProtocol->SetLed(TRUE); + for (Count = 0; Count < BlockLen; Count += 4, Buffer++) { + *Buffer = MmioRead32(MMCHS_DATA); + } + + mFwProtocol->SetLed(FALSE); + break; + } + + gBS->Stall(STALL_AFTER_RETRY_US); + RetryCount++; + } + + if (RetryCount == MAX_RETRY_COUNT) { + DEBUG((DEBUG_ERROR, "%a(%u): %lu/%lu MMCHS_INT_STAT: %08x\n", + __FUNCTION__, __LINE__, Length - RemLength, + Length, MmcStatus)); + return EFI_TIMEOUT; + } + + RemLength -= BlockLen; + gBS->Stall(STALL_AFTER_READ_US); + } + + MmioWrite32(MMCHS_INT_STAT, BRR); + return EFI_SUCCESS; +} + +EFI_STATUS +MMCWriteBlockData( + IN EFI_MMC_HOST_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Length, + IN UINT32* Buffer + ) +{ + UINTN MmcStatus; + UINTN RemLength; + UINTN Count; + + DEBUG((DEBUG_VERBOSE, "%a(%u): LBA: 0x%x, Length: 0x%x, Buffer: 0x%x)\n", + __FUNCTION__, __LINE__, Lba, Length, Buffer)); + + if (Buffer == NULL) { + DEBUG((DEBUG_ERROR, "%a(%u): NULL Buffer\n", + __FUNCTION__, __LINE__)); + return EFI_INVALID_PARAMETER; + } + + if (Length % sizeof(UINT32) != 0) { + DEBUG((DEBUG_ERROR, "%a(%u): bad Length %u\n", + __FUNCTION__, __LINE__, Length)); + return EFI_INVALID_PARAMETER; + } + + RemLength = Length; + while (RemLength != 0) { + UINTN RetryCount = 0; + UINT32 BlockLen = MIN(RemLength, BLEN_512BYTES); + + while (RetryCount < MAX_RETRY_COUNT) { + MmcStatus = MmioRead32(MMCHS_INT_STAT); + if ((MmcStatus & BWR) != 0) { + MmioWrite32(MMCHS_INT_STAT, BWR); + /* + * Can write data. + */ + mFwProtocol->SetLed(TRUE); + for (Count = 0; Count < BlockLen; Count += 4, Buffer++) { + MmioWrite32(MMCHS_DATA, *Buffer); + } + + mFwProtocol->SetLed(FALSE); + break; + } + + gBS->Stall(STALL_AFTER_RETRY_US); + RetryCount++; + } + + if (RetryCount == MAX_RETRY_COUNT) { + DEBUG((DEBUG_ERROR, "%a(%u): %lu/%lu MMCHS_INT_STAT: %08x\n", + __FUNCTION__, __LINE__, Length - RemLength, + Length, MmcStatus)); + return EFI_TIMEOUT; + } + + RemLength -= BlockLen; + gBS->Stall(STALL_AFTER_WRITE_US); + } + + MmioWrite32(MMCHS_INT_STAT, BWR); + return EFI_SUCCESS; +} + +BOOLEAN +MMCIsMultiBlock ( + IN EFI_MMC_HOST_PROTOCOL *This + ) +{ + return TRUE; +} + +EFI_MMC_HOST_PROTOCOL gMMCHost = + { + MMC_HOST_PROTOCOL_REVISION, + MMCIsCardPresent, + MMCIsReadOnly, + MMCBuildDevicePath, + MMCNotifyState, + MMCSendCommand, + MMCReceiveResponse, + MMCReadBlockData, + MMCWriteBlockData, + NULL, + MMCIsMultiBlock + }; + +EFI_STATUS +MMCInitialize( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle = NULL; + + DEBUG((DEBUG_MMCHOST_SD, "ArasanMMCHost: MMCInitialize()\n")); + + if (!PcdGet32 (PcdSdIsArasan)) { + DEBUG((DEBUG_INFO, "SD is not routed to Arasan\n")); + return EFI_REQUEST_UNLOAD_IMAGE; + } + + Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid, NULL, + (VOID **)&mFwProtocol); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->InstallMultipleProtocolInterfaces( + &Handle, + &gRaspberryPiMmcHostProtocolGuid, &gMMCHost, + NULL + ); + ASSERT_EFI_ERROR(Status); + + return Status; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.h b/Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.h new file mode 100644 index 000000000000..6b4f0da4a425 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.h @@ -0,0 +1,50 @@ +/** @file + * + * Copyright (c) Microsoft Corporation. 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 _MMC_HOST_DXE_H_ +#define _MMC_HOST_DXE_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define MAX_RETRY_COUNT (1000 * 20) + +#define STALL_AFTER_SEND_CMD_US (200) // in microseconds +#define STALL_AFTER_REC_RESP_US (50) +#define STALL_AFTER_WRITE_US (200) +#define STALL_AFTER_READ_US (20) +#define STALL_AFTER_RETRY_US (20) + +#define MAX_DIVISOR_VALUE 1023 + +#endif diff --git a/Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.inf new file mode 100644 index 000000000000..4d70c1b72815 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.inf @@ -0,0 +1,53 @@ +#/** @file +# +# Copyright (c) 2017, Andrei Warkentin +# Copyright (c) Microsoft Corporation. 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 = ArasanMMCHost + FILE_GUID = 100c2cfa-b586-4198-9b4c-1683d195b1da + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = MMCInitialize + + +[Sources.common] + ArasanMmcHostDxe.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + PcdLib + UefiLib + UefiDriverEntryPoint + MemoryAllocationLib + IoLib + DmaLib + CacheMaintenanceLib + +[Guids] + +[Protocols] + gRaspberryPiMmcHostProtocolGuid ## PRODUCES + gRaspberryPiFirmwareProtocolGuid ## CONSUMES + +[Pcd] + gRaspberryPiTokenSpaceGuid.PcdSdIsArasan + +[Depex] + gRaspberryPiFirmwareProtocolGuid AND gRaspberryPiConfigAppliedProtocolGuid diff --git a/Platform/Broadcom/Bcm283x/Drivers/Bcm2836InterruptDxe/Bcm2836InterruptDxe.c b/Platform/Broadcom/Bcm283x/Drivers/Bcm2836InterruptDxe/Bcm2836InterruptDxe.c new file mode 100644 index 000000000000..dda61665031d --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/Bcm2836InterruptDxe/Bcm2836InterruptDxe.c @@ -0,0 +1,367 @@ +/** @file + * + * Copyright (c) 2016, Linaro, 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 + +#include +#include + +// +// This currently only implements support for the architected timer interrupts +// on the per-CPU interrupt controllers. +// +#define NUM_IRQS (4) + +#ifdef MDE_CPU_AARCH64 +#define ARM_ARCH_EXCEPTION_IRQ EXCEPT_AARCH64_IRQ +#else +#define ARM_ARCH_EXCEPTION_IRQ EXCEPT_ARM_IRQ +#endif + +STATIC CONST +EFI_PHYSICAL_ADDRESS RegBase = FixedPcdGet32 (PcdInterruptBaseAddress); + +// +// Notifications +// +STATIC EFI_EVENT mExitBootServicesEvent; +STATIC HARDWARE_INTERRUPT_HANDLER mRegisteredInterruptHandlers[NUM_IRQS]; + +/** + Shutdown our hardware + + DXE Core will disable interrupts and turn off the timer and disable interrupts + after all the event handlers have run. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +STATIC +VOID +EFIAPI +ExitBootServicesEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // Disable all interrupts + MmioWrite32 (RegBase + BCM2836_INTC_TIMER_CONTROL_OFFSET, 0); +} + +/** + Enable interrupt source Source. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + + @retval EFI_SUCCESS Source interrupt enabled. + @retval EFI_DEVICE_ERROR Hardware could not be programmed. + +**/ +STATIC +EFI_STATUS +EFIAPI +EnableInterruptSource ( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source + ) +{ + if (Source >= NUM_IRQS) { + ASSERT(FALSE); + return EFI_UNSUPPORTED; + } + + MmioOr32 (RegBase + BCM2836_INTC_TIMER_CONTROL_OFFSET, 1 << Source); + + return EFI_SUCCESS; +} + + +/** + Disable interrupt source Source. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + + @retval EFI_SUCCESS Source interrupt disabled. + @retval EFI_DEVICE_ERROR Hardware could not be programmed. + +**/ +STATIC +EFI_STATUS +EFIAPI +DisableInterruptSource ( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source + ) +{ + if (Source >= NUM_IRQS) { + ASSERT(FALSE); + return EFI_UNSUPPORTED; + } + + MmioAnd32 (RegBase + BCM2836_INTC_TIMER_CONTROL_OFFSET, ~(1 << Source)); + + return EFI_SUCCESS; +} + +/** + Register Handler for the specified interrupt source. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + @param Handler Callback for interrupt. NULL to unregister + + @retval EFI_SUCCESS Source was updated to support Handler. + @retval EFI_DEVICE_ERROR Hardware could not be programmed. + +**/ +STATIC +EFI_STATUS +EFIAPI +RegisterInterruptSource ( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source, + IN HARDWARE_INTERRUPT_HANDLER Handler + ) +{ + if (Source >= NUM_IRQS) { + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + + if (Handler == NULL && mRegisteredInterruptHandlers[Source] == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Handler != NULL && mRegisteredInterruptHandlers[Source] != NULL) { + return EFI_ALREADY_STARTED; + } + + mRegisteredInterruptHandlers[Source] = Handler; + return EnableInterruptSource(This, Source); +} + + +/** + Return current state of interrupt source Source. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + @param InterruptState TRUE: source enabled, FALSE: source disabled. + + @retval EFI_SUCCESS InterruptState is valid + @retval EFI_DEVICE_ERROR InterruptState is not valid + +**/ +STATIC +EFI_STATUS +EFIAPI +GetInterruptSourceState ( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source, + IN BOOLEAN *InterruptState + ) +{ + if (InterruptState == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Source >= NUM_IRQS) { + ASSERT(FALSE); + return EFI_UNSUPPORTED; + } + + *InterruptState = (MmioRead32 (RegBase + BCM2836_INTC_TIMER_CONTROL_OFFSET) & + (1 << Source)) != 0; + + return EFI_SUCCESS; +} + +/** + Signal to the hardware that the End Of Intrrupt state + has been reached. + + @param This Instance pointer for this protocol + @param Source Hardware source of the interrupt + + @retval EFI_SUCCESS Source interrupt EOI'ed. + @retval EFI_DEVICE_ERROR Hardware could not be programmed. + +**/ +STATIC +EFI_STATUS +EFIAPI +EndOfInterrupt ( + IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This, + IN HARDWARE_INTERRUPT_SOURCE Source + ) +{ + return EFI_SUCCESS; +} + + +/** + EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs. + + @param InterruptType Defines the type of interrupt or exception that + occurred on the processor.This parameter is processor + architecture specific. + @param SystemContext A pointer to the processor context when + the interrupt occurred on the processor. + + @return None + +**/ +STATIC +VOID +EFIAPI +IrqInterruptHandler ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + HARDWARE_INTERRUPT_HANDLER InterruptHandler; + HARDWARE_INTERRUPT_SOURCE Source; + UINT32 RegVal; + + RegVal = MmioRead32 (RegBase + BCM2836_INTC_TIMER_PENDING_OFFSET) & + ((1 << NUM_IRQS) - 1); + Source = HighBitSet32 (RegVal); + if (Source < 0) { + return; + } + + InterruptHandler = mRegisteredInterruptHandlers [Source]; + if (InterruptHandler != NULL) { + // Call the registered interrupt handler. + InterruptHandler (Source, SystemContext); + } +} + +// +// The protocol instance produced by this driver +// +STATIC EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptProtocol = { + RegisterInterruptSource, + EnableInterruptSource, + DisableInterruptSource, + GetInterruptSourceState, + EndOfInterrupt +}; + +STATIC VOID *mCpuArchProtocolNotifyEventRegistration; + +STATIC +VOID +EFIAPI +CpuArchEventProtocolNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_CPU_ARCH_PROTOCOL *Cpu; + EFI_STATUS Status; + + // + // Get the CPU protocol that this driver requires. + // + Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu); + if (EFI_ERROR (Status)) { + return; + } + + // + // Unregister the default exception handler. + // + Status = Cpu->RegisterInterruptHandler(Cpu, ARM_ARCH_EXCEPTION_IRQ, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Cpu->RegisterInterruptHandler() - %r\n", + __FUNCTION__, Status)); + ASSERT (FALSE); + return; + } + + // + // Register to receive interrupts + // + Status = Cpu->RegisterInterruptHandler(Cpu, ARM_ARCH_EXCEPTION_IRQ, + IrqInterruptHandler); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Cpu->RegisterInterruptHandler() - %r\n", + __FUNCTION__, Status)); + ASSERT (FALSE); + return; + } +} + + +/** + Initialize the state information for the CPU Architectural Protocol + + @param ImageHandle of the loaded driver + @param SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Protocol registered + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure + @retval EFI_DEVICE_ERROR Hardware problems + +**/ +EFI_STATUS +InterruptDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_EVENT CpuArchEvent; + + // Make sure the Interrupt Controller Protocol is not already installed in the system. + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid); + + Status = gBS->InstallMultipleProtocolInterfaces( + &ImageHandle, + &gHardwareInterruptProtocolGuid, + &gHardwareInterruptProtocol, + NULL); + ASSERT_EFI_ERROR(Status); + + // + // Install the interrupt handler as soon as the CPU arch protocol appears. + // + CpuArchEvent = EfiCreateProtocolNotifyEvent ( + &gEfiCpuArchProtocolGuid, + TPL_CALLBACK, + CpuArchEventProtocolNotify, + NULL, + &mCpuArchProtocolNotifyEventRegistration + ); + ASSERT (CpuArchEvent != NULL); + + // Register for an ExitBootServicesEvent + Status = gBS->CreateEvent(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, + ExitBootServicesEvent, NULL, &mExitBootServicesEvent); + + ASSERT_EFI_ERROR(Status); + + return Status; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/Bcm2836InterruptDxe/Bcm2836InterruptDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/Bcm2836InterruptDxe/Bcm2836InterruptDxe.inf new file mode 100644 index 000000000000..831ae1bfeeab --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/Bcm2836InterruptDxe/Bcm2836InterruptDxe.inf @@ -0,0 +1,48 @@ +#/** @file +# +# Copyright (c) 2017, Andrei Warkentin +# Copyright (c) 2016 Linaro, 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 = 0x00010019 + BASE_NAME = Bcm2836InterruptDxe + FILE_GUID = 3944f2d7-2e09-4fc0-9e98-008375641453 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = InterruptDxeInitialize + +[Sources] + Bcm2836InterruptDxe.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + IoLib + UefiBootServicesTableLib + UefiLib + UefiDriverEntryPoint + +[Protocols] + gHardwareInterruptProtocolGuid ## PRODUCES + gEfiCpuArchProtocolGuid ## CONSUMES ## NOTIFY + +[FixedPcd] + gEmbeddedTokenSpaceGuid.PcdInterruptBaseAddress + +[Depex] + TRUE diff --git a/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxe.c b/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxe.c new file mode 100644 index 000000000000..4e3c68ca2994 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxe.c @@ -0,0 +1,356 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * + * 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 "ConfigDxeFormSetGuid.h" + +extern UINT8 ConfigDxeHiiBin[]; +extern UINT8 ConfigDxeStrings[]; + +STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol; + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +STATIC HII_VENDOR_DEVICE_PATH mVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + CONFIGDXE_FORM_SET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + + +STATIC EFI_STATUS +InstallHiiPages ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + + DriverHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces (&DriverHandle, + &gEfiDevicePathProtocolGuid, + &mVendorDevicePath, + NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + HiiHandle = HiiAddPackages (&gConfigDxeFormSetGuid, + DriverHandle, + ConfigDxeStrings, + ConfigDxeHiiBin, + NULL); + + if (HiiHandle == NULL) { + gBS->UninstallMultipleProtocolInterfaces (DriverHandle, + &gEfiDevicePathProtocolGuid, + &mVendorDevicePath, + NULL); + return EFI_OUT_OF_RESOURCES; + } + return EFI_SUCCESS; +} + + +STATIC EFI_STATUS +SetupVariables ( + VOID + ) +{ + UINTN Size; + UINT32 Var32; + EFI_STATUS Status; + + /* + * Create the vars with default value. + * If we don't, forms won't be able to update. + */ + + Size = sizeof (UINT32); + Status = gRT->GetVariable(L"CpuClock", + &gConfigDxeFormSetGuid, + NULL, &Size, &Var32); + if (EFI_ERROR (Status)) { + PcdSet32 (PcdCpuClock, PcdGet32 (PcdCpuClock)); + } + + Size = sizeof (UINT32); + Status = gRT->GetVariable(L"SdIsArasan", + &gConfigDxeFormSetGuid, + NULL, &Size, &Var32); + if (EFI_ERROR (Status)) { + PcdSet32 (PcdSdIsArasan, PcdGet32 (PcdSdIsArasan)); + } + + Size = sizeof (UINT32); + Status = gRT->GetVariable(L"MmcDisableMulti", + &gConfigDxeFormSetGuid, + NULL, &Size, &Var32); + if (EFI_ERROR (Status)) { + PcdSet32 (PcdMmcDisableMulti, PcdGet32 (PcdMmcDisableMulti)); + } + + Size = sizeof (UINT32); + Status = gRT->GetVariable(L"MmcForce1Bit", + &gConfigDxeFormSetGuid, + NULL, &Size, &Var32); + if (EFI_ERROR (Status)) { + PcdSet32 (PcdMmcForce1Bit, PcdGet32 (PcdMmcForce1Bit)); + } + + Size = sizeof (UINT32); + Status = gRT->GetVariable(L"MmcForceDefaultSpeed", + &gConfigDxeFormSetGuid, + NULL, &Size, &Var32); + if (EFI_ERROR (Status)) { + PcdSet32 (PcdMmcForceDefaultSpeed, PcdGet32 (PcdMmcForceDefaultSpeed)); + } + + Size = sizeof (UINT32); + Status = gRT->GetVariable(L"MmcSdDefaultSpeedMHz", + &gConfigDxeFormSetGuid, + NULL, &Size, &Var32); + if (EFI_ERROR (Status)) { + PcdSet32 (PcdMmcSdDefaultSpeedMHz, PcdGet32 (PcdMmcSdDefaultSpeedMHz)); + } + + Size = sizeof (UINT32); + Status = gRT->GetVariable(L"MmcSdHighSpeedMHz", + &gConfigDxeFormSetGuid, + NULL, &Size, &Var32); + if (EFI_ERROR (Status)) { + PcdSet32 (PcdMmcSdHighSpeedMHz, PcdGet32 (PcdMmcSdHighSpeedMHz)); + } + + Size = sizeof (UINT32); + Status = gRT->GetVariable(L"DebugEnableJTAG", + &gConfigDxeFormSetGuid, + NULL, &Size, &Var32); + if (EFI_ERROR (Status)) { + PcdSet32 (PcdDebugEnableJTAG, PcdGet32 (PcdDebugEnableJTAG)); + } + + Size = sizeof (UINT32); + Status = gRT->GetVariable(L"DebugShowUEFIExit", + &gConfigDxeFormSetGuid, + NULL, &Size, &Var32); + if (EFI_ERROR (Status)) { + PcdSet32 (PcdDebugShowUEFIExit, PcdGet32 (PcdDebugShowUEFIExit)); + } + + Size = sizeof (UINT32); + Status = gRT->GetVariable(L"DisplayEnableVModes", + &gConfigDxeFormSetGuid, + NULL, &Size, &Var32); + if (EFI_ERROR (Status)) { + PcdSet32 (PcdDisplayEnableVModes, PcdGet32 (PcdDisplayEnableVModes)); + } + + Size = sizeof (UINT32); + Status = gRT->GetVariable(L"DisplayEnableSShot", + &gConfigDxeFormSetGuid, + NULL, &Size, &Var32); + if (EFI_ERROR (Status)) { + PcdSet32 (PcdDisplayEnableSShot, PcdGet32 (PcdDisplayEnableSShot)); + } + + return EFI_SUCCESS; +} + + +STATIC VOID +ApplyVariables ( + VOID + ) +{ + UINTN Gpio34Group; + UINTN Gpio48Group; + EFI_STATUS Status; + UINT32 CpuClock = PcdGet32 (PcdCpuClock); + UINT32 Rate = 0; + + if (CpuClock != 0) { + if (CpuClock == 2) { + /* + * Maximum: 1.2GHz on RPi 3, 1.4GHz on RPi 3B+, unless + * overridden with arm_freq=xxx in config.txt. + */ + Status = mFwProtocol->GetMaxClockRate(RPI_FW_CLOCK_RATE_ARM, &Rate); + if (Status != EFI_SUCCESS) { + DEBUG((DEBUG_ERROR, "Couldn't get the max CPU speed, leaving as is: %r\n", + Status)); + } + } else { + Rate = 600 * 1000000; + } + } + + if (Rate != 0) { + DEBUG((DEBUG_INFO, "Setting CPU speed to %uHz\n", Rate)); + Status = mFwProtocol->SetClockRate(RPI_FW_CLOCK_RATE_ARM, Rate); + if (Status != EFI_SUCCESS) { + DEBUG((DEBUG_ERROR, "Couldn't set the CPU speed: %r\n", + Status)); + } + } + + Status = mFwProtocol->GetClockRate(RPI_FW_CLOCK_RATE_ARM, &Rate); + if (Status != EFI_SUCCESS) { + DEBUG((DEBUG_ERROR, "Couldn't get the CPU speed: %r\n", + Status)); + } else { + DEBUG((DEBUG_INFO, "Current CPU speed is %uHz\n", Rate)); + } + + /* + * Switching two groups around, so disable both first. + * + * No, I've not seen a problem, but having a group be + * routed to two sets of pins seems like asking for trouble. + */ + GpioPinFuncSet(34, GPIO_FSEL_INPUT); + GpioPinFuncSet(35, GPIO_FSEL_INPUT); + GpioPinFuncSet(36, GPIO_FSEL_INPUT); + GpioPinFuncSet(37, GPIO_FSEL_INPUT); + GpioPinFuncSet(38, GPIO_FSEL_INPUT); + GpioPinFuncSet(39, GPIO_FSEL_INPUT); + GpioPinFuncSet(48, GPIO_FSEL_INPUT); + GpioPinFuncSet(49, GPIO_FSEL_INPUT); + GpioPinFuncSet(50, GPIO_FSEL_INPUT); + GpioPinFuncSet(51, GPIO_FSEL_INPUT); + GpioPinFuncSet(52, GPIO_FSEL_INPUT); + GpioPinFuncSet(53, GPIO_FSEL_INPUT); + if (PcdGet32 (PcdSdIsArasan)) { + DEBUG((DEBUG_INFO, "Routing SD to Arasan\n")); + Gpio48Group = GPIO_FSEL_ALT3; + /* + * Route SDIO to SdHost. + */ + Gpio34Group = GPIO_FSEL_ALT0; + } else { + DEBUG((DEBUG_INFO, "Routing SD to SdHost\n")); + Gpio48Group = GPIO_FSEL_ALT0; + /* + * Route SDIO to Arasan. + */ + Gpio34Group = GPIO_FSEL_ALT3; + } + GpioPinFuncSet(34, Gpio34Group); + GpioPinFuncSet(35, Gpio34Group); + GpioPinFuncSet(36, Gpio34Group); + GpioPinFuncSet(37, Gpio34Group); + GpioPinFuncSet(38, Gpio34Group); + GpioPinFuncSet(39, Gpio34Group); + GpioPinFuncSet(48, Gpio48Group); + GpioPinFuncSet(49, Gpio48Group); + GpioPinFuncSet(50, Gpio48Group); + GpioPinFuncSet(51, Gpio48Group); + GpioPinFuncSet(52, Gpio48Group); + GpioPinFuncSet(53, Gpio48Group); + + /* + * JTAG pin JTAG sig GPIO Mode Header pin + * 1 VREF N/A 1 + * 3 nTRST GPIO22 ALT4 15 + * 4 GND N/A 9 + * 5 TDI GPIO4 ALT5 7 + * 7 TMS GPIO27 ALT4 13 + * 9 TCK GPIO25 ALT4 22 + * 11 RTCK GPIO23 ALT4 16 + * 13 TDO GPIO24 ALT4 18 + */ + if (PcdGet32 (PcdDebugEnableJTAG)) { + GpioPinFuncSet(22, GPIO_FSEL_ALT4); + GpioPinFuncSet(4, GPIO_FSEL_ALT5); + GpioPinFuncSet(27, GPIO_FSEL_ALT4); + GpioPinFuncSet(25, GPIO_FSEL_ALT4); + GpioPinFuncSet(23, GPIO_FSEL_ALT4); + GpioPinFuncSet(24, GPIO_FSEL_ALT4); + } else { + GpioPinFuncSet(22, GPIO_FSEL_INPUT); + GpioPinFuncSet(4, GPIO_FSEL_INPUT); + GpioPinFuncSet(27, GPIO_FSEL_INPUT); + GpioPinFuncSet(25, GPIO_FSEL_INPUT); + GpioPinFuncSet(23, GPIO_FSEL_INPUT); + GpioPinFuncSet(24, GPIO_FSEL_INPUT); + } +} + + +EFI_STATUS +EFIAPI +ConfigInitialize( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid, + NULL, (VOID **)&mFwProtocol); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = SetupVariables(); + if (Status != EFI_SUCCESS) { + DEBUG((DEBUG_ERROR, "Couldn't not setup NV vars: %r\n", + Status)); + } + + ApplyVariables(); + Status = gBS->InstallProtocolInterface (&ImageHandle, + &gRaspberryPiConfigAppliedProtocolGuid, + EFI_NATIVE_INTERFACE, + NULL); + ASSERT_EFI_ERROR (Status); + + Status = InstallHiiPages(); + if (Status != EFI_SUCCESS) { + DEBUG((DEBUG_ERROR, "Couldn't install ConfigDxe configuration pages: %r\n", + Status)); + } + + return EFI_SUCCESS; +} + diff --git a/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxe.inf new file mode 100644 index 000000000000..1eb429de1ae0 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxe.inf @@ -0,0 +1,81 @@ +#/** @file +# +# Copyright (c) 2018, Andrei Warkentin +# +# 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 = ConfigDxe + FILE_GUID = 755cbac2-b23f-4b92-bc8e-fb01ce5907b7 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = ConfigInitialize + +# +# The following information is for reference only and not required by the build +# tools. +# +# VALID_ARCHITECTURES = AARCH64 +# + +[Sources] + ConfigDxe.c + ConfigDxeHii.vfr + ConfigDxeHii.uni + +[Packages] + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + DxeServicesTableLib + PcdLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + HiiLib + GpioLib + +[Guids] + gConfigDxeFormSetGuid + +[Protocols] + gRaspberryPiFirmwareProtocolGuid ## CONSUMES + gRaspberryPiConfigAppliedProtocolGuid ## PRODUCES + +[Pcd] + gRaspberryPiTokenSpaceGuid.PcdHypEnable + gRaspberryPiTokenSpaceGuid.PcdHypLogMask + gRaspberryPiTokenSpaceGuid.PcdHypWindowsDebugHook + gRaspberryPiTokenSpaceGuid.PcdHypWin2000Mask + gRaspberryPiTokenSpaceGuid.PcdCpuClock + gRaspberryPiTokenSpaceGuid.PcdSdIsArasan + gRaspberryPiTokenSpaceGuid.PcdMmcForce1Bit + gRaspberryPiTokenSpaceGuid.PcdMmcForceDefaultSpeed + gRaspberryPiTokenSpaceGuid.PcdMmcSdDefaultSpeedMHz + gRaspberryPiTokenSpaceGuid.PcdMmcSdHighSpeedMHz + gRaspberryPiTokenSpaceGuid.PcdMmcDisableMulti + gRaspberryPiTokenSpaceGuid.PcdDebugEnableJTAG + gRaspberryPiTokenSpaceGuid.PcdDebugShowUEFIExit + gRaspberryPiTokenSpaceGuid.PcdDisplayEnableVModes + gRaspberryPiTokenSpaceGuid.PcdDisplayEnableSShot + +[FeaturePcd] + +[Depex] + gPcdProtocolGuid AND gRaspberryPiFirmwareProtocolGuid diff --git a/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxeFormSetGuid.h b/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxeFormSetGuid.h new file mode 100644 index 000000000000..b29ae3a42461 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxeFormSetGuid.h @@ -0,0 +1,23 @@ +/** @file + * + * Copyright (c) 2018 Andrei Warkentin + * + * 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 CONFIGDXE_FORM_SET_GUID_H +#define CONFIGDXE_FORM_SET_GUID_H + +#define CONFIGDXE_FORM_SET_GUID \ + {0xCD7CC258, 0x31DB, 0x22E6, {0x9F, 0x22, 0x63, 0xB0, 0xB8, 0xEE, 0xD6, 0xB5}} + +extern EFI_GUID gConfigDxeFormSetGuid; + +#endif /* CONFIGDXE_FORM_SET_GUID_H */ diff --git a/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxeHii.uni b/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxeHii.uni new file mode 100644 index 000000000000..bf09261d5e4a --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxeHii.uni @@ -0,0 +1,100 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * + * 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. + * + **/ + +#langdef en-US "English" + +#string STR_NULL_STRING #language en-US "" + +#string STR_FORM_SET_TITLE #language en-US "Raspberry Pi Configuration" +#string STR_FORM_SET_TITLE_HELP #language en-US "Press to configure system settings." + +/* + * Chipset config. + */ + +#string STR_CHIPSET_FORM_TITLE #language en-US "Chipset Configuration" +#string STR_CHIPSET_FORM_SUBTITLE #language en-US "Note: OS may override settings when booted." + +#string STR_CHIPSET_CLOCK_CPU_PROMPT #language en-US "CPU Clock" +#string STR_CHIPSET_CLOCK_CPU_HELP #language en-US "CPU Speed" +#string STR_CHIPSET_CLOCK_CPU_NA #language en-US "Don't Override" +#string STR_CHIPSET_CLOCK_CPU_600MHZ #language en-US "Min (600MHz)" +#string STR_CHIPSET_CLOCK_CPU_MAX #language en-US "Max" + +#string STR_CHIPSET_SD_PROMPT #language en-US "uSD Routing" +#string STR_CHIPSET_SD_HELP #language en-US "Choose host controller to drive uSD slot" +#string STR_CHIPSET_SD_SDHOST #language en-US "Broadcom SDHOST" +#string STR_CHIPSET_SD_ARASAN #language en-US "Arasan SDHCI" + +/* + * MMC/SD configuration. + */ + +#string STR_MMC_FORM_TITLE #language en-US "SD/MMC Tweaks" +#string STR_MMC_FORM_SUBTITLE #language en-US "Note: UEFI only, OS will override settings when booted." + +#string STR_MMC_DISMULTI_PROMPT #language en-US "Multi-Block Support" +#string STR_MMC_DISMULTI_HELP #language en-US "Use CMD18/CMD25 for transfers when possible" +#string STR_MMC_DISMULTI_N #language en-US "Multi-block transfers" +#string STR_MMC_DISMULTI_Y #language en-US "Single-block transfers" + +#string STR_MMC_FORCE1BIT_PROMPT #language en-US "uSD Max Bus Width" +#string STR_MMC_FORCE1BIT_HELP #language en-US "Tweak for bad media" +#string STR_MMC_FORCE1BIT_Y #language en-US "1 Bit Mode" +#string STR_MMC_FORCE1BIT_N #language en-US "4 Bit Mode" + +#string STR_MMC_FORCEDS_PROMPT #language en-US "uSD Force Default Speed" +#string STR_MMC_FORCEDS_HELP #language en-US "Tweak for bad media" +#string STR_MMC_FORCEDS_Y #language en-US "Force Default Speed" +#string STR_MMC_FORCEDS_N #language en-US "Allow High Speed" + +#string STR_MMC_SD_DS_PROMPT #language en-US "SD Default Speed (MHz)" +#string STR_MMC_SD_DS_HELP #language en-US "Override default 25Mhz" + +#string STR_MMC_SD_HS_PROMPT #language en-US "SD High Speed (MHz)" +#string STR_MMC_SD_HS_HELP #language en-US "Override default 50Mhz" + + +/* + * Display settings. + */ + +#string STR_DISPLAY_FORM_TITLE #language en-US "Display" +#string STR_DISPLAY_FORM_SUBTITLE #language en-US "UEFI video driver settings" + +#string STR_DISPLAY_VMODES_PROMPT #language en-US "Resolutions" +#string STR_DISPLAY_VMODES_HELP #language en-US "Support for non-native modes" +#string STR_DISPLAY_VMODES_ENABLE #language en-US "Also support 640x480, 800x600, 1024x768, 720p and 1080p" +#string STR_DISPLAY_VMODES_DISABLE #language en-US "Only native resolution" + +#string STR_DISPLAY_SSHOT_PROMPT #language en-US "Screenshot Support" +#string STR_DISPLAY_SSHOT_HELP #language en-US "Save screen capture as a BMP on the first writable file system found" +#string STR_DISPLAY_SSHOT_ENABLE #language en-US "Control-Alt-F12" +#string STR_DISPLAY_SSHOT_DISABLE #language en-US "Not Enabled" + +/* + * Debugging settings go here. + */ +#string STR_DEBUG_FORM_TITLE #language en-US "Debugging" +#string STR_DEBUG_FORM_SUBTITLE #language en-US "For UEFI/OS Developers" + +#string STR_DEBUG_JTAG_PROMPT #language en-US "JTAG Routing" +#string STR_DEBUG_JTAG_HELP #language en-US "Signals (nTRST, TDI, TMS, TCK, RTCK, TDO) -> Header pins (15, 7, 13, 22, 16, 18)" +#string STR_DEBUG_JTAG_ENABLE #language en-US "Enable JTAG via GPIO" +#string STR_DEBUG_JTAG_DISABLE #language en-US "Disable JTAG" + +#string STR_DEBUG_EXIT_SHOW_PROMPT #language en-US "Verbose ExitBootServices" +#string STR_DEBUG_EXIT_SHOW_HELP #language en-US "Show message when UEFI hands off to OS" +#string STR_DEBUG_EXIT_SHOW_NO #language en-US "Do nothing" +#string STR_DEBUG_EXIT_SHOW_YES #language en-US "Show farewell message" diff --git a/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxeHii.vfr b/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxeHii.vfr new file mode 100644 index 000000000000..d3d98acc2edf --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxeHii.vfr @@ -0,0 +1,306 @@ +/** @file + * + * Copyright (c) 2018 Andrei Warkentin + * + * 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 "ConfigDxeFormSetGuid.h" + +typedef struct { + /* + * 0 - One mode for the boot resolution. + * 1 - Adds additional "typical" resolutions like + * 640x480, 800x600, 1024 x 768, 720p and 1080p. + */ + UINT32 Enable; +} DISPLAY_ENABLE_VMODES_VARSTORE_DATA; + +typedef struct { + /* + * 0 - No screenshot support. + * 1 - Screenshot support via hotkey. + */ + UINT32 Enable; +} DISPLAY_ENABLE_SSHOT_VARSTORE_DATA; + +typedef struct { + /* + * 0 - No JTAG. + * 1 - JTAG mode. + */ + UINT32 Enable; +} DEBUG_ENABLE_JTAG_VARSTORE_DATA; + +typedef struct { + /* + * 0 - Don't show UEFI exit message. + * 1 - Show UEFI exit message. + */ + UINT32 Show; +} DEBUG_SHOW_UEFI_EXIT_VARSTORE_DATA; + +typedef struct { + /* + * 0 - don't change the clock rate. + * 1 - 600MHz. + * 2 - maximum. + */ + UINT32 Clock; +} CHIPSET_CPU_CLOCK_VARSTORE_DATA; + +typedef struct { + /* + * 0 - uSD slot routed to Broadcom SDHOST. + * 1 - uSD slot routed to Arasan SDHCI. + */ + UINT32 Routing; +} CHIPSET_SD_VARSTORE_DATA; + +typedef struct { + /* + * 0 - Don't disable multi-block. + * 1 - Disable multi-block commands. + */ + UINT32 DisableMulti; +} MMC_DISMULTI_VARSTORE_DATA; + +typedef struct { + /* + * 0 - Don't force 1 bit mode. + * 1 - Force 1 bit mode. + */ + UINT32 Force1Bit; +} MMC_FORCE1BIT_VARSTORE_DATA; + +typedef struct { + /* + * 0 - Don't force default speed. + * 1 - Force default speed. + */ + UINT32 ForceDS; +} MMC_FORCEDS_VARSTORE_DATA; + +typedef struct { + /* + * Default Speed MHz override (25MHz default). + */ + UINT32 MHz; +} MMC_SD_DS_MHZ_VARSTORE_DATA; + +typedef struct { + /* + * High Speed MHz override (50MHz default). + */ + UINT32 MHz; +} MMC_SD_HS_MHZ_VARSTORE_DATA; + +// +// EFI Variable attributes +// +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 +#define EFI_VARIABLE_READ_ONLY 0x00000008 + +formset + guid = CONFIGDXE_FORM_SET_GUID, + title = STRING_TOKEN(STR_FORM_SET_TITLE), + help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP), + classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID, + + efivarstore CHIPSET_CPU_CLOCK_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = CpuClock, + guid = CONFIGDXE_FORM_SET_GUID; + + efivarstore CHIPSET_SD_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = SdIsArasan, + guid = CONFIGDXE_FORM_SET_GUID; + + efivarstore MMC_DISMULTI_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = MmcDisableMulti, + guid = CONFIGDXE_FORM_SET_GUID; + + efivarstore MMC_FORCE1BIT_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = MmcForce1Bit, + guid = CONFIGDXE_FORM_SET_GUID; + + efivarstore MMC_FORCEDS_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = MmcForceDefaultSpeed, + guid = CONFIGDXE_FORM_SET_GUID; + + efivarstore MMC_SD_DS_MHZ_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = MmcSdDefaultSpeedMHz, + guid = CONFIGDXE_FORM_SET_GUID; + + efivarstore MMC_SD_HS_MHZ_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = MmcSdHighSpeedMHz, + guid = CONFIGDXE_FORM_SET_GUID; + + efivarstore DEBUG_ENABLE_JTAG_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = DebugEnableJTAG, + guid = CONFIGDXE_FORM_SET_GUID; + + efivarstore DEBUG_SHOW_UEFI_EXIT_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = DebugShowUEFIExit, + guid = CONFIGDXE_FORM_SET_GUID; + + efivarstore DISPLAY_ENABLE_VMODES_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = DisplayEnableVModes, + guid = CONFIGDXE_FORM_SET_GUID; + + efivarstore DISPLAY_ENABLE_SSHOT_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + name = DisplayEnableSShot, + guid = CONFIGDXE_FORM_SET_GUID; + + form formid = 1, + title = STRING_TOKEN(STR_FORM_SET_TITLE); + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto 0x1002, + prompt = STRING_TOKEN(STR_CHIPSET_FORM_TITLE), + help = STRING_TOKEN(STR_NULL_STRING); + + goto 0x1003, + prompt = STRING_TOKEN(STR_MMC_FORM_TITLE), + help = STRING_TOKEN(STR_NULL_STRING); + + goto 0x1004, + prompt = STRING_TOKEN(STR_DISPLAY_FORM_TITLE), + help = STRING_TOKEN(STR_NULL_STRING); + + goto 0x1005, + prompt = STRING_TOKEN(STR_DEBUG_FORM_TITLE), + help = STRING_TOKEN(STR_NULL_STRING); + endform; + + form formid = 0x1002, + title = STRING_TOKEN(STR_CHIPSET_FORM_TITLE); + subtitle text = STRING_TOKEN(STR_CHIPSET_FORM_SUBTITLE); + + oneof varid = CpuClock.Clock, + prompt = STRING_TOKEN(STR_CHIPSET_CLOCK_CPU_PROMPT), + help = STRING_TOKEN(STR_CHIPSET_CLOCK_CPU_HELP), + flags = NUMERIC_SIZE_4 | INTERACTIVE | RESET_REQUIRED, + option text = STRING_TOKEN(STR_CHIPSET_CLOCK_CPU_NA), value = 0, flags = DEFAULT; + option text = STRING_TOKEN(STR_CHIPSET_CLOCK_CPU_600MHZ), value = 1, flags = 0; + option text = STRING_TOKEN(STR_CHIPSET_CLOCK_CPU_MAX), value = 2, flags = 0; + endoneof; + + oneof varid = SdIsArasan.Routing, + prompt = STRING_TOKEN(STR_CHIPSET_SD_PROMPT), + help = STRING_TOKEN(STR_CHIPSET_SD_HELP), + flags = NUMERIC_SIZE_4 | INTERACTIVE | RESET_REQUIRED, + option text = STRING_TOKEN(STR_CHIPSET_SD_ARASAN), value = 1, flags = 0; + option text = STRING_TOKEN(STR_CHIPSET_SD_SDHOST), value = 0, flags = DEFAULT; + endoneof; + endform; + + form formid = 0x1003, + title = STRING_TOKEN(STR_MMC_FORM_TITLE); + subtitle text = STRING_TOKEN(STR_MMC_FORM_SUBTITLE); + + oneof varid = MmcDisableMulti.DisableMulti, + prompt = STRING_TOKEN(STR_MMC_DISMULTI_PROMPT), + help = STRING_TOKEN(STR_MMC_DISMULTI_HELP), + flags = NUMERIC_SIZE_4 | INTERACTIVE | RESET_REQUIRED, + option text = STRING_TOKEN(STR_MMC_DISMULTI_N), value = 0, flags = DEFAULT; + option text = STRING_TOKEN(STR_MMC_DISMULTI_Y), value = 1, flags = 0; + endoneof; + + oneof varid = MmcForce1Bit.Force1Bit, + prompt = STRING_TOKEN(STR_MMC_FORCE1BIT_PROMPT), + help = STRING_TOKEN(STR_MMC_FORCE1BIT_HELP), + flags = NUMERIC_SIZE_4 | INTERACTIVE | RESET_REQUIRED, + option text = STRING_TOKEN(STR_MMC_FORCE1BIT_N), value = 0, flags = DEFAULT; + option text = STRING_TOKEN(STR_MMC_FORCE1BIT_Y), value = 1, flags = 0; + endoneof; + + oneof varid = MmcForceDefaultSpeed.ForceDS, + prompt = STRING_TOKEN(STR_MMC_FORCEDS_PROMPT), + help = STRING_TOKEN(STR_MMC_FORCEDS_HELP), + flags = NUMERIC_SIZE_4 | INTERACTIVE | RESET_REQUIRED, + option text = STRING_TOKEN(STR_MMC_FORCEDS_N), value = 0, flags = DEFAULT; + option text = STRING_TOKEN(STR_MMC_FORCEDS_Y), value = 1, flags = 0; + endoneof; + + numeric varid = MmcSdDefaultSpeedMHz.MHz, + prompt = STRING_TOKEN(STR_MMC_SD_DS_PROMPT), + help = STRING_TOKEN(STR_MMC_SD_DS_HELP), + flags = DISPLAY_UINT_DEC | NUMERIC_SIZE_4 | INTERACTIVE | RESET_REQUIRED, + minimum = 25, + maximum = 100, + default = 25, + endnumeric; + + numeric varid = MmcSdHighSpeedMHz.MHz, + prompt = STRING_TOKEN(STR_MMC_SD_HS_PROMPT), + help = STRING_TOKEN(STR_MMC_SD_HS_HELP), + flags = DISPLAY_UINT_DEC | NUMERIC_SIZE_4 | INTERACTIVE | RESET_REQUIRED, + minimum = 50, + maximum = 100, + default = 50, + endnumeric; + endform; + + form formid = 0x1004, + title = STRING_TOKEN(STR_DISPLAY_FORM_TITLE); + subtitle text = STRING_TOKEN(STR_DISPLAY_FORM_SUBTITLE); + + oneof varid = DisplayEnableVModes.Enable, + prompt = STRING_TOKEN(STR_DISPLAY_VMODES_PROMPT), + help = STRING_TOKEN(STR_DISPLAY_VMODES_HELP), + flags = NUMERIC_SIZE_4 | INTERACTIVE | RESET_REQUIRED, + option text = STRING_TOKEN(STR_DISPLAY_VMODES_ENABLE), value = 1, flags = DEFAULT; + option text = STRING_TOKEN(STR_DISPLAY_VMODES_DISABLE), value = 0, flags = 0; + endoneof; + + oneof varid = DisplayEnableSShot.Enable, + prompt = STRING_TOKEN(STR_DISPLAY_SSHOT_PROMPT), + help = STRING_TOKEN(STR_DISPLAY_SSHOT_HELP), + flags = NUMERIC_SIZE_4 | INTERACTIVE | RESET_REQUIRED, + option text = STRING_TOKEN(STR_DISPLAY_SSHOT_ENABLE), value = 1, flags = DEFAULT; + option text = STRING_TOKEN(STR_DISPLAY_SSHOT_DISABLE), value = 0, flags = 0; + endoneof; + endform; + + form formid = 0x1005, + title = STRING_TOKEN(STR_DEBUG_FORM_TITLE); + subtitle text = STRING_TOKEN(STR_DEBUG_FORM_SUBTITLE); + + oneof varid = DebugEnableJTAG.Enable, + prompt = STRING_TOKEN(STR_DEBUG_JTAG_PROMPT), + help = STRING_TOKEN(STR_DEBUG_JTAG_HELP), + flags = NUMERIC_SIZE_4 | INTERACTIVE | RESET_REQUIRED, + option text = STRING_TOKEN(STR_DEBUG_JTAG_ENABLE), value = 1, flags = 0; + option text = STRING_TOKEN(STR_DEBUG_JTAG_DISABLE), value = 0, flags = DEFAULT; + endoneof; + + oneof varid = DebugShowUEFIExit.Show, + prompt = STRING_TOKEN(STR_DEBUG_EXIT_SHOW_PROMPT), + help = STRING_TOKEN(STR_DEBUG_EXIT_SHOW_HELP), + flags = NUMERIC_SIZE_4 | INTERACTIVE, + option text = STRING_TOKEN(STR_DEBUG_EXIT_SHOW_NO), value = 0, flags = DEFAULT; + option text = STRING_TOKEN(STR_DEBUG_EXIT_SHOW_YES), value = 1, flags = 0; + endoneof; + endform; +endformset; diff --git a/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/ComponentName.c b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/ComponentName.c new file mode 100644 index 000000000000..e639826c60b1 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/ComponentName.c @@ -0,0 +1,222 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) 2006-2016, Intel Corporation. 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 "DisplayDxe.h" + +STATIC +EFI_STATUS +EFIAPI +ComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName +); + +STATIC +EFI_STATUS +EFIAPI +ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gComponentName = { + ComponentNameGetDriverName, + ComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) ComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) ComponentNameGetControllerName, + "en" +}; + + +STATIC EFI_UNICODE_STRING_TABLE mDriverName[] = { + { + "eng;en", + (CHAR16 *)L"Raspberry Pi Display Driver" + }, + { + NULL, + NULL + } +}; + +STATIC EFI_UNICODE_STRING_TABLE mDeviceName[] = { + { + "eng;en", + (CHAR16 *)L"Raspberry Pi Framebuffer" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +STATIC +EFI_STATUS +EFIAPI +ComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mDriverName, + DriverName, + (BOOLEAN)(This == &gComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param ChildHandle[in] The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +STATIC +EFI_STATUS +EFIAPI +ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mDeviceName, + ControllerName, + (BOOLEAN)(This == &gComponentName) + ); +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.c b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.c new file mode 100644 index 000000000000..e8b7f67c8870 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.c @@ -0,0 +1,606 @@ +/** @file + * + * Copyright (c) 2017-2018, Andrei Warkentin + * Copyright (c) Microsoft Corporation. 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 "DisplayDxe.h" + +#define POS_TO_FB(posX, posY) ((UINT8 *) \ + ((UINTN)This->Mode->FrameBufferBase + \ + (posY) * This->Mode->Info->PixelsPerScanLine * \ + PI3_BYTES_PER_PIXEL + \ + (posX) * PI3_BYTES_PER_PIXEL)) + +STATIC +EFI_STATUS +EFIAPI +DriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +DriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +DriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +STATIC +EFI_STATUS +EFIAPI +DisplayQueryMode( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ); + +STATIC +EFI_STATUS +EFIAPI +DisplaySetMode( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber + ); + +STATIC +EFI_STATUS +EFIAPI +DisplayBlt( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + +STATIC EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = { + DriverSupported, + DriverStart, + DriverStop, + 0xa, + NULL, + NULL +}; + +typedef struct { + VENDOR_DEVICE_PATH DisplayDevicePath; + EFI_DEVICE_PATH EndDevicePath; +} DISPLAY_DEVICE_PATH; + +typedef struct { + UINT32 Width; + UINT32 Height; +} GOP_MODE_DATA; + +STATIC UINT32 mBootWidth; +STATIC UINT32 mBootHeight; +STATIC EFI_HANDLE mDevice; +STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol; +STATIC EFI_CPU_ARCH_PROTOCOL *mCpu; + +STATIC UINTN mLastMode; +STATIC GOP_MODE_DATA mGopModeData[] = { + { 800, 600 }, /* Legacy */ + { 640, 480 }, /* Legacy */ + { 1024, 768 }, /* Legacy */ + { 1280, 720 }, /* 720p */ + { 1920, 1080 }, /* 1080p */ + { 0, 0 }, /* Physical */ +}; + +STATIC DISPLAY_DEVICE_PATH mDisplayProtoDevicePath = + { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8)(sizeof(VENDOR_DEVICE_PATH)), + (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8), + } + }, + EFI_CALLER_ID_GUID, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + sizeof(EFI_DEVICE_PATH_PROTOCOL), + 0 + } + } + }; + +#define PI3_BITS_PER_PIXEL (32) +#define PI3_BYTES_PER_PIXEL (PI3_BITS_PER_PIXEL / 8) + +EFI_GRAPHICS_OUTPUT_PROTOCOL gDisplayProto = { + DisplayQueryMode, + DisplaySetMode, + DisplayBlt, + NULL +}; + +STATIC +EFI_STATUS +EFIAPI +DisplayQueryMode( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +{ + EFI_STATUS Status; + GOP_MODE_DATA *Mode; + + if (ModeNumber > mLastMode) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->AllocatePool( + EfiBootServicesData, + sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), + (VOID **)Info + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Mode = &mGopModeData[ModeNumber]; + + *SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); + (*Info)->Version = This->Mode->Info->Version; + (*Info)->HorizontalResolution = Mode->Width; + (*Info)->VerticalResolution = Mode->Height; + (*Info)->PixelFormat = This->Mode->Info->PixelFormat; + (*Info)->PixelsPerScanLine = Mode->Width; + + return EFI_SUCCESS; +} + +STATIC +VOID +ClearScreen( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This + ) +{ + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill; + + Fill.Red = 0x00; + Fill.Green = 0x00; + Fill.Blue = 0x00; + This->Blt (This, &Fill, EfiBltVideoFill, + 0, 0, 0, 0, This->Mode->Info->HorizontalResolution, + This->Mode->Info->VerticalResolution, + This->Mode->Info->HorizontalResolution * + sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); +} + +STATIC +EFI_STATUS +EFIAPI +DisplaySetMode( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber + ) +{ + UINTN FbSize; + UINTN FbPitch; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS FbBase; + GOP_MODE_DATA *Mode = &mGopModeData[ModeNumber]; + + if (ModeNumber > mLastMode) { + return EFI_UNSUPPORTED; + } + + DEBUG((DEBUG_INFO, "Setting mode %u from %u: %u x %u\n", + ModeNumber, This->Mode->Mode, Mode->Width, Mode->Height)); + Status = mFwProtocol->GetFB(Mode->Width, Mode->Height, + PI3_BITS_PER_PIXEL, &FbBase, + &FbSize, &FbPitch); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "Could not set mode %u\n", ModeNumber)); + return EFI_DEVICE_ERROR; + } + + DEBUG((DEBUG_INFO, "Mode %u: %u x %u framebuffer is %u bytes at %p\n", + ModeNumber, Mode->Width, Mode->Height, FbSize, FbBase)); + + if (FbPitch / PI3_BYTES_PER_PIXEL != Mode->Width) { + DEBUG((DEBUG_ERROR, "Error: Expected width %u, got width %u\n", + Mode->Width, FbPitch / PI3_BYTES_PER_PIXEL)); + return EFI_DEVICE_ERROR; + } + + /* + * WT, because certain OS loaders access the frame buffer directly + * and we don't want to see corruption due to missing WB cache + * maintenance. Performance with WT is good. + */ + Status = mCpu->SetMemoryAttributes(mCpu, FbBase, + ALIGN_VALUE(FbSize, EFI_PAGE_SIZE), + EFI_MEMORY_WT); + if (Status != EFI_SUCCESS) { + DEBUG((DEBUG_ERROR, "Couldn't set framebuffer attributes: %r\n", Status)); + return Status; + } + + This->Mode->Mode = ModeNumber; + This->Mode->Info->Version = 0; + This->Mode->Info->HorizontalResolution = Mode->Width; + This->Mode->Info->VerticalResolution = Mode->Height; + /* + * NOTE: Windows REQUIRES BGR in 32 or 24 bit format. + */ + This->Mode->Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor; + This->Mode->Info->PixelsPerScanLine = Mode->Width; + This->Mode->SizeOfInfo = sizeof(*This->Mode->Info); + This->Mode->FrameBufferBase = FbBase; + This->Mode->FrameBufferSize = FbSize; + + ClearScreen(This); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +DisplayBlt( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +{ + UINT8 *VidBuf, *BltBuf, *VidBuf1; + UINTN i; + + switch(BltOperation) { + case EfiBltVideoFill: + BltBuf = (UINT8 *)BltBuffer; + + for (i = 0; i < Height; i++) { + VidBuf = POS_TO_FB(DestinationX, DestinationY + i); + + SetMem32(VidBuf, Width * PI3_BYTES_PER_PIXEL, *(UINT32 *) BltBuf); + } + break; + + case EfiBltVideoToBltBuffer: + if (Delta == 0) { + Delta = Width * PI3_BYTES_PER_PIXEL; + } + + for (i = 0; i < Height; i++) { + VidBuf = POS_TO_FB(SourceX, SourceY + i); + + BltBuf = (UINT8 *)((UINTN)BltBuffer + (DestinationY + i) * Delta + + DestinationX * PI3_BYTES_PER_PIXEL); + + gBS->CopyMem((VOID *)BltBuf, (VOID *)VidBuf, PI3_BYTES_PER_PIXEL * Width); + } + break; + + case EfiBltBufferToVideo: + if (Delta == 0) { + Delta = Width * PI3_BYTES_PER_PIXEL; + } + + for (i = 0; i < Height; i++) { + VidBuf = POS_TO_FB(DestinationX, DestinationY + i); + BltBuf = (UINT8 *)((UINTN) BltBuffer + (SourceY + i) * Delta + + SourceX * PI3_BYTES_PER_PIXEL); + + gBS->CopyMem((VOID *)VidBuf, (VOID *)BltBuf, Width * PI3_BYTES_PER_PIXEL); + } + break; + + case EfiBltVideoToVideo: + for (i = 0; i < Height; i++) { + VidBuf = POS_TO_FB(SourceX, SourceY + i); + VidBuf1 = POS_TO_FB(DestinationX, DestinationY + i); + + gBS->CopyMem((VOID *)VidBuf1, (VOID *)VidBuf, Width * PI3_BYTES_PER_PIXEL); + } + break; + + default: + ASSERT_EFI_ERROR(EFI_SUCCESS); + break; + } + + return EFI_SUCCESS; +} + +/** + Initialize the state information for the Display Dxe + + @param ImageHandle of the loaded driver + @param SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Protocol registered + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure + @retval EFI_DEVICE_ERROR Hardware problems + +**/ +EFI_STATUS +EFIAPI +DisplayDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid, NULL, + (VOID **)&mFwProtocol); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, + (VOID **) &mCpu); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + // Query the current display resolution from mailbox + Status = mFwProtocol->GetFBSize(&mBootWidth, &mBootHeight); + if(EFI_ERROR(Status)) { + return Status; + } + + DEBUG((DEBUG_INFO, "Display boot mode is %u x %u\n", + mBootWidth, mBootHeight)); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &mDevice, &gEfiDevicePathProtocolGuid, + &mDisplayProtoDevicePath, &gEfiCallerIdGuid, + NULL, NULL); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &mDriverBinding, + ImageHandle, + &gComponentName, + &gComponentName2 + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +DriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + VOID *Temp; + + if (Controller != mDevice) { + return EFI_UNSUPPORTED; + } + + if (gBS->HandleProtocol(Controller, &gEfiGraphicsOutputProtocolGuid, + (VOID **) &Temp) == EFI_SUCCESS) { + return EFI_ALREADY_STARTED; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +DriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + UINTN Index; + EFI_STATUS Status; + VOID *Dummy; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiCallerIdGuid, + (VOID **) &Dummy, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gDisplayProto.Mode = AllocateZeroPool(sizeof(EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE)); + if (gDisplayProto.Mode == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto done; + } + + gDisplayProto.Mode->Info = AllocateZeroPool(sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION)); + if (gDisplayProto.Mode->Info == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto done; + } + + + if (PcdGet32(PcdDisplayEnableVModes)) { + mLastMode = ELES(mGopModeData) - 1; + } else { + mLastMode = 0; + /* + * mBootWidth x mBootHeight may not be sensible, + * so clean it up, since we won't be adding + * any other extra vmodes. + */ + if (mBootWidth < 640 || + mBootHeight < 480) { + mBootWidth = 640; + mBootHeight = 480; + } + } + + mGopModeData[mLastMode].Width = mBootWidth; + mGopModeData[mLastMode].Height = mBootHeight; + + for (Index = 0; Index <= mLastMode; Index++) { + UINTN FbSize; + UINTN FbPitch; + EFI_PHYSICAL_ADDRESS FbBase; + + GOP_MODE_DATA *Mode = &mGopModeData[Index]; + + Status = mFwProtocol->GetFB(Mode->Width, Mode->Height, + PI3_BITS_PER_PIXEL, &FbBase, + &FbSize, &FbPitch); + if (EFI_ERROR(Status)) { + goto done; + } + + // + // There is no way to communicate pitch back to OS. OS and even UEFI + // expect a fully linear frame buffer. So the width should + // be based on the frame buffer's pitch value. In some cases VC + // firmware would allocate ao frame buffer with some padding + // presumably to be 8 byte align. + // + Mode->Width = FbPitch / PI3_BYTES_PER_PIXEL; + + DEBUG((DEBUG_INFO, "Mode %u: %u x %u framebuffer is %u bytes at %p\n", + Index, Mode->Width, Mode->Height, FbSize, FbBase)); + + ASSERT (FbPitch != 0); + ASSERT (FbBase != 0); + ASSERT (FbSize != 0); + } + + // Both set the mode and initialize current mode information. + gDisplayProto.Mode->MaxMode = mLastMode + 1; + DisplaySetMode(&gDisplayProto, 0); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, &gEfiGraphicsOutputProtocolGuid, + &gDisplayProto, NULL); + if (EFI_ERROR (Status)) { + goto done; + } + + if (PcdGet32(PcdDisplayEnableSShot)) { + RegisterScreenshotHandlers(); + } else { + DEBUG((DEBUG_INFO, "Screenshot capture disabled\n")); + } + +done: + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "Could not start DisplayDxe: %r\n", Status)); + if (gDisplayProto.Mode->Info != NULL) { + FreePool(gDisplayProto.Mode->Info); + gDisplayProto.Mode->Info = NULL; + } + + if (gDisplayProto.Mode != NULL) { + FreePool(gDisplayProto.Mode); + gDisplayProto.Mode = NULL; + } + + gBS->CloseProtocol ( + Controller, + &gEfiCallerIdGuid, + This->DriverBindingHandle, + Controller + ); + } + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +DriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + + ClearScreen(&gDisplayProto); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, &gEfiGraphicsOutputProtocolGuid, + &gDisplayProto, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + FreePool(gDisplayProto.Mode->Info); + gDisplayProto.Mode->Info = NULL; + FreePool(gDisplayProto.Mode); + gDisplayProto.Mode = NULL; + + gBS->CloseProtocol ( + Controller, + &gEfiCallerIdGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.h b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.h new file mode 100644 index 000000000000..9fa3d4f6af83 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.h @@ -0,0 +1,43 @@ +/** @file + * + * Copyright (c) 2017-2018, Andrei Warkentin + * Copyright (c) Microsoft Corporation. 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 _DISPLAY_H_ +#define _DISPLAY_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_GRAPHICS_OUTPUT_PROTOCOL gDisplayProto; +extern EFI_COMPONENT_NAME_PROTOCOL gComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gComponentName2; + +VOID +RegisterScreenshotHandlers( + VOID + ); + +#endif /* _DISPLAY_H_ */ diff --git a/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.inf new file mode 100644 index 000000000000..1603edd4909d --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.inf @@ -0,0 +1,71 @@ +#/** @file +# +# Component description file for Graphics Output module +# +# Copyright (c) 2017, Andrei Warkentin +# Copyright (c) Microsoft Corporation. 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 = DisplayDxe + FILE_GUID = c5deae31-fad2-4030-841b-cfc9644d2c5b + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DisplayDxeInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# DRIVER_BINDING = gGraphicsConsoleDriverBinding +# COMPONENT_NAME = gGraphicsConsoleComponentName +# COMPONENT_NAME2 = gGraphicsConsoleComponentName2 +# + +[Sources] + DisplayDxe.c + Screenshot.c + ComponentName.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPkg/ArmPkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + BaseLib + UefiLib + MemoryAllocationLib + UefiDriverEntryPoint + IoLib + TimerLib + BmpSupportLib + UefiRuntimeServicesTableLib + +[Protocols] + gEfiLoadedImageProtocolGuid + gEfiDevicePathProtocolGuid + gEfiGraphicsOutputProtocolGuid + gRaspberryPiFirmwareProtocolGuid + gEfiCpuArchProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEfiSimpleTextInputExProtocolGuid + +[Pcd] + gRaspberryPiTokenSpaceGuid.PcdDisplayEnableVModes + gRaspberryPiTokenSpaceGuid.PcdDisplayEnableSShot + +[Guids] + +[Depex] + gEfiCpuArchProtocolGuid AND gRaspberryPiFirmwareProtocolGuid diff --git a/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/Screenshot.c b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/Screenshot.c new file mode 100644 index 000000000000..a2feeba6084f --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/Screenshot.c @@ -0,0 +1,379 @@ +/** @file + * + * Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved. + * Copyright (c) 2018, Andrei Warkentin + * + * 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. + * + **/ + +/* + * Loosely based on CrScreenShotDxe (https://github.com/LongSoft/CrScreenshotDxe). + * + * Copyright (c) 2016, Nikolaj Schlej, All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + */ + +#include "DisplayDxe.h" +#include +#include +#include +#include + +/* + * ShowStatus defs. + */ +#define STATUS_SQUARE_SIDE 5 +#define STATUS_YELLOW 0xff, 0xff, 0x00 +#define STATUS_GREEN 0x00, 0xff, 0x00 +#define STATUS_BLUE 0x00, 0x00, 0xff +#define STATUS_RED 0xff, 0x00, 0x00 + +EFI_STATUS +ShowStatus ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, + IN UINT8 Red, + IN UINT8 Green, + IN UINT8 Blue + ) +{ + UINTN Index; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Square[STATUS_SQUARE_SIDE * STATUS_SQUARE_SIDE]; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Backup[STATUS_SQUARE_SIDE * STATUS_SQUARE_SIDE]; + + for (Index = 0 ; Index < STATUS_SQUARE_SIDE * STATUS_SQUARE_SIDE; Index++) { + Square[Index].Blue = Blue; + Square[Index].Green = Green; + Square[Index].Red = Red; + Square[Index].Reserved = 0x00; + } + + // Backup current image. + GraphicsOutput->Blt(GraphicsOutput, Backup, + EfiBltVideoToBltBuffer, 0, 0, 0, 0, + STATUS_SQUARE_SIDE, STATUS_SQUARE_SIDE, 0); + + // Draw the status square. + GraphicsOutput->Blt(GraphicsOutput, Square, + EfiBltBufferToVideo, 0, 0, 0, 0, + STATUS_SQUARE_SIDE, STATUS_SQUARE_SIDE, 0); + + // Wait 500ms. + gBS->Stall(500*1000); + + // Restore the backup. + GraphicsOutput->Blt(GraphicsOutput, Backup, + EfiBltBufferToVideo, 0, 0, 0, 0, + STATUS_SQUARE_SIDE, STATUS_SQUARE_SIDE, 0); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +FindWritableFs ( + OUT EFI_FILE_PROTOCOL **WritableFs + ) +{ + EFI_FILE_PROTOCOL *Fs = NULL; + EFI_HANDLE *HandleBuffer = NULL; + UINTN HandleCount; + UINTN Index; + + EFI_STATUS Status = gBS->LocateHandleBuffer(ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, &HandleCount, &HandleBuffer); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs = NULL; + EFI_FILE_PROTOCOL *File = NULL; + + Status = gBS->HandleProtocol(HandleBuffer[Index], + &gEfiSimpleFileSystemProtocolGuid, + (VOID **) &SimpleFs); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + /* + * Not supposed to happen. + */ + continue; + } + + Status = SimpleFs->OpenVolume(SimpleFs, &Fs); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a OpenVolume[%u] returned %r\n", __FUNCTION__, + Index, Status)); + continue; + } + + Status = Fs->Open(Fs, &File, L"--------.---", + EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | + EFI_FILE_MODE_WRITE, 0); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a Open[%u] returned %r\n", __FUNCTION__, + Index, Status)); + continue; + } + + /* + * Okay, we have a writable filesystem! + */ + Fs->Delete(File); + *WritableFs = Fs; + Status = EFI_SUCCESS; + break; + } + + if (HandleBuffer) { + FreePool(HandleBuffer); + } + + return Status; +} + +STATIC +VOID +TakeScreenshot( + VOID + ) +{ + VOID *BmpImage = NULL; + EFI_FILE_PROTOCOL *Fs = NULL; + EFI_FILE_PROTOCOL *File = NULL; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput = &gDisplayProto; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Image = NULL; + EFI_STATUS Status; + CHAR16 FileName[8+1+3+1]; + UINT32 ScreenWidth; + UINT32 ScreenHeight; + UINTN ImageSize; + UINTN BmpSize; + UINTN Index; + EFI_TIME Time; + + Status = FindWritableFs(&Fs); + if (EFI_ERROR (Status)) { + ShowStatus(GraphicsOutput, STATUS_YELLOW); + } + + ScreenWidth = GraphicsOutput->Mode->Info->HorizontalResolution; + ScreenHeight = GraphicsOutput->Mode->Info->VerticalResolution; + ImageSize = ScreenWidth * ScreenHeight; + + Status = gRT->GetTime(&Time, NULL); + if (!EFI_ERROR(Status)) { + UnicodeSPrint(FileName, sizeof(FileName), L"%02d%02d%02d%02d.bmp", + Time.Day, Time.Hour, Time.Minute, Time.Second); + } else { + UnicodeSPrint(FileName, sizeof(FileName), L"scrnshot.bmp"); + } + + Image = AllocatePool(ImageSize * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + if (Image == NULL) { + Status = EFI_OUT_OF_RESOURCES; + ShowStatus(GraphicsOutput, STATUS_RED); + goto done; + } + + Status = GraphicsOutput->Blt(GraphicsOutput, Image, + EfiBltVideoToBltBuffer, 0, 0, 0, 0, + ScreenWidth, ScreenHeight, 0); + if (EFI_ERROR(Status)) { + ShowStatus(GraphicsOutput, STATUS_RED); + goto done; + } + + for (Index = 0; Index < ImageSize; Index++) { + if (Image[Index].Red != 0x00 || + Image[Index].Green != 0x00 || + Image[Index].Blue != 0x00) { + break; + } + } + + if (Index == ImageSize) { + ShowStatus(GraphicsOutput, STATUS_BLUE); + goto done; + } + + Status = TranslateGopBltToBmp(Image, ScreenHeight, ScreenWidth, + &BmpImage, (UINT32 *) &BmpSize); + if (EFI_ERROR(Status)) { + ShowStatus(GraphicsOutput, STATUS_RED); + goto done; + } + + Status = Fs->Open(Fs, &File, FileName, EFI_FILE_MODE_CREATE | + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0); + if (EFI_ERROR (Status)) { + ShowStatus(GraphicsOutput, STATUS_RED); + goto done; + } + + Status = File->Write(File, &BmpSize, BmpImage); + File->Close(File); + if (EFI_ERROR (Status)) { + ShowStatus(GraphicsOutput, STATUS_RED); + goto done; + } + + ShowStatus(GraphicsOutput, STATUS_GREEN); +done: + if (BmpImage != NULL) { + FreePool (BmpImage); + } + + if (Image != NULL) { + FreePool (Image); + } +} + +STATIC +EFI_STATUS +EFIAPI +ScreenshotKeyHandler ( + IN EFI_KEY_DATA *KeyData + ) +{ + TakeScreenshot(); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ProcessScreenshotHandler( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_KEY_DATA ScreenshotKey; + + /* + * LCtrl+LAlt+F12 + */ + ScreenshotKey.Key.ScanCode = SCAN_F12; + ScreenshotKey.Key.UnicodeChar = 0; + ScreenshotKey.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID | + EFI_LEFT_CONTROL_PRESSED | EFI_LEFT_ALT_PRESSED; + ScreenshotKey.KeyState.KeyToggleState = 0; + + Status = SimpleTextInEx->RegisterKeyNotify ( + SimpleTextInEx, + &ScreenshotKey, + ScreenshotKeyHandler, + &Handle + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: couldn't register key notification: %r\n", + __FUNCTION__, Status)); + return Status; + } + + return EFI_SUCCESS; +} + +STATIC +VOID +ProcessScreenshotHandlers( + VOID + ) +{ + UINTN Index; + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx; + + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextInputExProtocolGuid, + NULL, &HandleCount, &HandleBuffer); + if (EFI_ERROR (Status)) { + return; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol (HandleBuffer[Index], + &gEfiSimpleTextInputExProtocolGuid, + (VOID **) &SimpleTextInEx); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + /* + * Not supposed to happen. + */ + continue; + } + + Status = ProcessScreenshotHandler(SimpleTextInEx); + if (EFI_ERROR (Status)) { + continue; + } + } +} + +STATIC +VOID +EFIAPI +OnTextInExInstall ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + ProcessScreenshotHandlers(); +} + +VOID +RegisterScreenshotHandlers( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT TextInExInstallEvent; + VOID *TextInExInstallRegistration; + + ProcessScreenshotHandlers(); + + Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, + OnTextInExInstall, NULL, + &TextInExInstallEvent); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: couldn't create protocol install event: %r\n", + __FUNCTION__, Status)); + return; + } + + Status = gBS->RegisterProtocolNotify(&gEfiSimpleTextInputExProtocolGuid, + TextInExInstallEvent, + &TextInExInstallRegistration); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: couldn't register protocol install notify: %r\n", + __FUNCTION__, Status)); + return; + } +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/ComponentName.c b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/ComponentName.c new file mode 100644 index 000000000000..e5935b19a250 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/ComponentName.c @@ -0,0 +1,183 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) 2006-2016, Intel Corporation. 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 "GraphicsConsole.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gGraphicsConsoleComponentName = { + GraphicsConsoleComponentNameGetDriverName, + GraphicsConsoleComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gGraphicsConsoleComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) GraphicsConsoleComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) GraphicsConsoleComponentNameGetControllerName, + "en" +}; + + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mGraphicsConsoleDriverNameTable[] = { + { + "eng;en", + (CHAR16 *)L"Graphics Console Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mGraphicsConsoleDriverNameTable, + DriverName, + (BOOLEAN)(This == &gGraphicsConsoleComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param ChildHandle[in] The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsole.c b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsole.c new file mode 100644 index 000000000000..4df5b37e5d4f --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsole.c @@ -0,0 +1,1836 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) 2006-2016, Intel Corporation. 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 "GraphicsConsole.h" + +// +// Graphics Console Device Private Data template +// +GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate = { + GRAPHICS_CONSOLE_DEV_SIGNATURE, + (EFI_GRAPHICS_OUTPUT_PROTOCOL *) NULL, + { + GraphicsConsoleConOutReset, + GraphicsConsoleConOutOutputString, + GraphicsConsoleConOutTestString, + GraphicsConsoleConOutQueryMode, + GraphicsConsoleConOutSetMode, + GraphicsConsoleConOutSetAttribute, + GraphicsConsoleConOutClearScreen, + GraphicsConsoleConOutSetCursorPosition, + GraphicsConsoleConOutEnableCursor, + (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL + }, + { + 0, + -1, + EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK), + 0, + 0, + TRUE + }, + (GRAPHICS_CONSOLE_MODE_DATA *) NULL, + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL, + { + (EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *) NULL, + (EFI_GRAPHICS_OUTPUT_PROTOCOL *) NULL, + TRUE, + } +}; + +GRAPHICS_CONSOLE_MODE_DATA mGraphicsConsoleModeData[] = { + {100, 31}, + // + // New modes can be added here. + // The last entry is specific for full screen mode. + // + {0, 0} +}; + +EFI_HII_DATABASE_PROTOCOL *mHiiDatabase; +EFI_HII_FONT_PROTOCOL *mHiiFont; +EFI_HII_HANDLE mHiiHandle; +VOID *mHiiRegistration; + +EFI_GUID mFontPackageListGuid = {0xf5f219d3, 0x7006, 0x4648, {0xac, 0x8d, 0xd6, 0x1d, 0xfb, 0x7b, 0xc6, 0xad}}; + +CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL }; + +EFI_GRAPHICS_OUTPUT_BLT_PIXEL mGraphicsEfiColors[16] = { + // + // B G R reserved + // + {0x00, 0x00, 0x00, 0x00}, // BLACK + {0x98, 0x00, 0x00, 0x00}, // LIGHTBLUE + {0x00, 0x98, 0x00, 0x00}, // LIGHGREEN + {0x98, 0x98, 0x00, 0x00}, // LIGHCYAN + {0x00, 0x00, 0x98, 0x00}, // LIGHRED + {0x98, 0x00, 0x98, 0x00}, // MAGENTA + {0x00, 0x98, 0x98, 0x00}, // BROWN + {0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY + {0x30, 0x30, 0x30, 0x00}, // DARKGRAY - BRIGHT BLACK + {0xff, 0x00, 0x00, 0x00}, // BLUE + {0x00, 0xff, 0x00, 0x00}, // LIME + {0xff, 0xff, 0x00, 0x00}, // CYAN + {0x00, 0x00, 0xff, 0x00}, // RED + {0xff, 0x00, 0xff, 0x00}, // FUCHSIA + {0x00, 0xff, 0xff, 0x00}, // YELLOW + {0xff, 0xff, 0xff, 0x00} // WHITE +}; + +EFI_NARROW_GLYPH mCursorGlyph = { + 0x0000, + 0x00, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF } +}; + +CHAR16 SpaceStr[] = { NARROW_CHAR, ' ', 0 }; + +EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding = { + GraphicsConsoleControllerDriverSupported, + GraphicsConsoleControllerDriverStart, + GraphicsConsoleControllerDriverStop, + 0xa, + NULL, + NULL +}; + +/** + Test to see if Graphics Console could be supported on the Controller. + + Graphics Console could be supported if Graphics Output Protocol + exists on the Controller. + + @param This Protocol instance pointer. + @param Controller Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + GraphicsOutput = NULL; + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &GraphicsOutput, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (GraphicsOutput != NULL); + + // + // We need to ensure that we do not layer on top of a virtual handle. + // We need to ensure that the handles produced by the conspliter do not + // get used. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + goto Error; + } + + // + // Does Hii Exist? If not, we aren't ready to run + // + Status = EfiLocateHiiProtocol (); + + // + // Close the I/O Abstraction(s) used to perform the supported test + // +Error: + gBS->CloseProtocol ( + Controller, + &gEfiGraphicsOutputProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; +} + +/** + Initialize all the text modes which the graphics console supports. + + It returns information for available text modes that the graphics can support. + + @param[in] HorizontalResolution The size of video screen in pixels in the X dimension. + @param[in] VerticalResolution The size of video screen in pixels in the Y dimension. + @param[in] GopModeNumber The graphics mode number which graphis console is based on. + @param[out] TextModeCount The total number of text modes that graphics console supports. + @param[out] TextModeData The buffer to the text modes column and row information. + Caller is responsible to free it when it's non-NULL. + + @retval EFI_SUCCESS The supporting mode information is returned. + @retval EFI_INVALID_PARAMETER The parameters are invalid. + +**/ +EFI_STATUS +InitializeGraphicsConsoleTextMode ( + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 GopModeNumber, + OUT UINTN *TextModeCount, + OUT GRAPHICS_CONSOLE_MODE_DATA **TextModeData + ) +{ + UINTN Index; + UINTN Count; + GRAPHICS_CONSOLE_MODE_DATA *ModeBuffer; + GRAPHICS_CONSOLE_MODE_DATA *NewModeBuffer; + UINTN ValidCount; + UINTN ValidIndex; + UINTN MaxColumns; + UINTN MaxRows; + + if ((TextModeCount == NULL) || (TextModeData == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Count = sizeof (mGraphicsConsoleModeData) / sizeof (GRAPHICS_CONSOLE_MODE_DATA); + + // + // Compute the maximum number of text Rows and Columns that this current graphics mode can support. + // To make graphics console work well, MaxColumns and MaxRows should not be zero. + // + MaxColumns = HorizontalResolution / EFI_GLYPH_WIDTH; + MaxRows = VerticalResolution / EFI_GLYPH_HEIGHT; + + // + // According to UEFI spec, all output devices support at least 80x25 text mode. + // + ASSERT ((MaxColumns >= 80) && (MaxRows >= 25)); + + // + // Add full screen mode to the last entry. + // + mGraphicsConsoleModeData[Count - 1].Columns = MaxColumns; + mGraphicsConsoleModeData[Count - 1].Rows = MaxRows; + + // + // Get defined mode buffer pointer. + // + ModeBuffer = mGraphicsConsoleModeData; + + // + // Here we make sure that the final mode exposed does not include the duplicated modes, + // and does not include the invalid modes which exceed the max column and row. + // Reserve 2 modes for 80x25, 80x50 of graphics console. + // + NewModeBuffer = AllocateZeroPool (sizeof (GRAPHICS_CONSOLE_MODE_DATA) * (Count + 2)); + ASSERT (NewModeBuffer != NULL); + + // + // Mode 0 and mode 1 is for 80x25, 80x50 according to UEFI spec. + // + ValidCount = 0; + + NewModeBuffer[ValidCount].Columns = 80; + NewModeBuffer[ValidCount].Rows = 25; + NewModeBuffer[ValidCount].GopWidth = HorizontalResolution; + NewModeBuffer[ValidCount].GopHeight = VerticalResolution; + NewModeBuffer[ValidCount].GopModeNumber = GopModeNumber; + NewModeBuffer[ValidCount].DeltaX = (HorizontalResolution - (NewModeBuffer[ValidCount].Columns * EFI_GLYPH_WIDTH)) >> 1; + NewModeBuffer[ValidCount].DeltaY = (VerticalResolution - (NewModeBuffer[ValidCount].Rows * EFI_GLYPH_HEIGHT)) >> 1; + ValidCount++; + + if ((MaxColumns >= 80) && (MaxRows >= 50)) { + NewModeBuffer[ValidCount].Columns = 80; + NewModeBuffer[ValidCount].Rows = 50; + NewModeBuffer[ValidCount].DeltaX = (HorizontalResolution - (80 * EFI_GLYPH_WIDTH)) >> 1; + NewModeBuffer[ValidCount].DeltaY = (VerticalResolution - (50 * EFI_GLYPH_HEIGHT)) >> 1; + } + NewModeBuffer[ValidCount].GopWidth = HorizontalResolution; + NewModeBuffer[ValidCount].GopHeight = VerticalResolution; + NewModeBuffer[ValidCount].GopModeNumber = GopModeNumber; + ValidCount++; + + // + // Start from mode 2 to put the valid mode other than 80x25 and 80x50 in the output mode buffer. + // + for (Index = 0; Index < Count; Index++) { + if ((ModeBuffer[Index].Columns == 0) || (ModeBuffer[Index].Rows == 0) || + (ModeBuffer[Index].Columns > MaxColumns) || (ModeBuffer[Index].Rows > MaxRows)) { + // + // Skip the pre-defined mode which is invalid or exceeds the max column and row. + // + continue; + } + for (ValidIndex = 0; ValidIndex < ValidCount; ValidIndex++) { + if ((ModeBuffer[Index].Columns == NewModeBuffer[ValidIndex].Columns) && + (ModeBuffer[Index].Rows == NewModeBuffer[ValidIndex].Rows)) { + // + // Skip the duplicated mode. + // + break; + } + } + if (ValidIndex == ValidCount) { + NewModeBuffer[ValidCount].Columns = ModeBuffer[Index].Columns; + NewModeBuffer[ValidCount].Rows = ModeBuffer[Index].Rows; + NewModeBuffer[ValidCount].GopWidth = HorizontalResolution; + NewModeBuffer[ValidCount].GopHeight = VerticalResolution; + NewModeBuffer[ValidCount].GopModeNumber = GopModeNumber; + NewModeBuffer[ValidCount].DeltaX = (HorizontalResolution - (NewModeBuffer[ValidCount].Columns * EFI_GLYPH_WIDTH)) >> 1; + NewModeBuffer[ValidCount].DeltaY = (VerticalResolution - (NewModeBuffer[ValidCount].Rows * EFI_GLYPH_HEIGHT)) >> 1; + ValidCount++; + } + } + + DEBUG_CODE ( + for (Index = 0; Index < ValidCount; Index++) { + DEBUG ((DEBUG_INFO, "Graphics - Mode %d, Column = %d, Row = %d\n", + Index, NewModeBuffer[Index].Columns, NewModeBuffer[Index].Rows)); + } + ); + + // + // Return valid mode count and mode information buffer. + // + *TextModeCount = ValidCount; + *TextModeData = NewModeBuffer; + return EFI_SUCCESS; +} + +/** + Start this driver on Controller by opening Graphics Output Protocol, + and installing Simple Text Out protocol on Controller. + + @param This Protocol instance pointer. + @param Controller Handle of device to bind driver to + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver is added to Controller. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + GRAPHICS_CONSOLE_DEV *Private; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 ModeIndex; + UINTN MaxMode; + UINT32 ModeNumber; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + + ModeNumber = 0; + + // + // Initialize the Graphics Console device instance + // + Private = AllocateCopyPool ( + sizeof (GRAPHICS_CONSOLE_DEV), + &mGraphicsConsoleDevTemplate + ); + if (Private == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Private->SimpleTextOutput.Mode = &(Private->SimpleTextOutputMode); + + Status = gBS->OpenProtocol ( + Controller, + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &Private->GraphicsOutput, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Private->ExtendedTextOutput.TextOut = &(Private->SimpleTextOutput); + Private->ExtendedTextOutput.GraphicsOutput = Private->GraphicsOutput; + + HorizontalResolution = PcdGet32 (PcdVideoHorizontalResolution); + VerticalResolution = PcdGet32 (PcdVideoVerticalResolution); + + ASSERT (Private->GraphicsOutput != NULL); + // + // The console is build on top of Graphics Output Protocol, find the mode number + // for the user-defined mode; if there are multiple video devices, + // graphic console driver will set all the video devices to the same mode. + // + if ((HorizontalResolution == 0x0) || (VerticalResolution == 0x0)) { + // + // Find the highest resolution which GOP supports. + // + MaxMode = Private->GraphicsOutput->Mode->MaxMode; + + for (ModeIndex = 0; ModeIndex < MaxMode; ModeIndex++) { + Status = Private->GraphicsOutput->QueryMode ( + Private->GraphicsOutput, + ModeIndex, + &SizeOfInfo, + &Info + ); + if (!EFI_ERROR (Status)) { + if ((Info->HorizontalResolution > HorizontalResolution) || + ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution > VerticalResolution))) { + HorizontalResolution = Info->HorizontalResolution; + VerticalResolution = Info->VerticalResolution; + ModeNumber = ModeIndex; + } + FreePool (Info); + } + } + if ((HorizontalResolution == 0x0) || (VerticalResolution == 0x0)) { + Status = EFI_UNSUPPORTED; + goto Error; + } + } else { + // + // Use user-defined resolution + // + Status = CheckModeSupported ( + Private->GraphicsOutput, + HorizontalResolution, + VerticalResolution, + &ModeNumber + ); + if (EFI_ERROR (Status)) { + // + // if not supporting current mode, try 800x600 which is required by UEFI/EFI spec. + // + HorizontalResolution = 800; + VerticalResolution = 600; + Status = CheckModeSupported ( + Private->GraphicsOutput, + HorizontalResolution, + VerticalResolution, + &ModeNumber + ); + Mode = Private->GraphicsOutput->Mode; + if (EFI_ERROR (Status) && Mode->MaxMode != 0) { + // + // Set default mode failed or device don't support default mode, then get the current mode information. + // + HorizontalResolution = Mode->Info->HorizontalResolution; + VerticalResolution = Mode->Info->VerticalResolution; + ModeNumber = Mode->Mode; + } + } + } + if (ModeNumber != Private->GraphicsOutput->Mode->Mode) { + // + // Current graphics mode is not set or is not set to the mode which we has found, + // set the new graphic mode. + // + Status = Private->GraphicsOutput->SetMode (Private->GraphicsOutput, ModeNumber); + if (EFI_ERROR (Status)) { + // + // The mode set operation failed + // + goto Error; + } + } + + DEBUG ((DEBUG_INFO, "GraphicsConsole video resolution %d x %d\n", HorizontalResolution, VerticalResolution)); + + // + // Initialize the mode which GraphicsConsole supports. + // + Status = InitializeGraphicsConsoleTextMode ( + HorizontalResolution, + VerticalResolution, + ModeNumber, + &MaxMode, + &Private->ModeData + ); + + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // Update the maximum number of modes + // + Private->SimpleTextOutputMode.MaxMode = (INT32) MaxMode; + + DEBUG_CODE_BEGIN (); + Status = GraphicsConsoleConOutSetMode (&Private->SimpleTextOutput, 0); + if (EFI_ERROR (Status)) { + goto Error; + } + Status = GraphicsConsoleConOutOutputString (&Private->SimpleTextOutput, (CHAR16 *)L"Graphics Console Started\n\r"); + if (EFI_ERROR (Status)) { + goto Error; + } + DEBUG_CODE_END (); + + // + // Install protocol interfaces for the Graphics Console device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiSimpleTextOutProtocolGuid, + &Private->SimpleTextOutput, + &gExtendedTextOutputProtocolGuid, + &Private->ExtendedTextOutput, + NULL + ); + +Error: + if (EFI_ERROR (Status)) { + // + // Close GOP. + // + gBS->CloseProtocol ( + Controller, + &gEfiGraphicsOutputProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + if (Private->LineBuffer != NULL) { + FreePool (Private->LineBuffer); + } + + if (Private->ModeData != NULL) { + FreePool (Private->ModeData); + } + + // + // Free private data + // + FreePool (Private); + } + + return Status; +} + +/** + Stop this driver on Controller by removing Simple Text Out protocol + and closing the Graphics Output Protocol on Controller. + + + @param This Protocol instance pointer. + @param Controller Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed Controller. + @retval EFI_NOT_STARTED Simple Text Out protocol could not be found the + Controller. + @retval other This driver was not removed from this device. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOutput; + GRAPHICS_CONSOLE_DEV *Private; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &SimpleTextOutput, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_STARTED; + } + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiSimpleTextOutProtocolGuid, + &Private->SimpleTextOutput, + &gExtendedTextOutputProtocolGuid, + &Private->ExtendedTextOutput, + NULL + ); + + if (!EFI_ERROR (Status)) { + // + // Close GOP. + // + gBS->CloseProtocol ( + Controller, + &gEfiGraphicsOutputProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + if (Private->LineBuffer != NULL) { + FreePool (Private->LineBuffer); + } + + if (Private->ModeData != NULL) { + FreePool (Private->ModeData); + } + + // + // Free our instance data + // + FreePool (Private); + } + + return Status; +} + +/** + Check if the current specific mode supported the user defined resolution + for the Graphics Console device based on Graphics Output Protocol. + + If yes, set the graphic devcice's current mode to this specific mode. + + @param GraphicsOutput Graphics Output Protocol instance pointer. + @param HorizontalResolution User defined horizontal resolution + @param VerticalResolution User defined vertical resolution. + @param CurrentModeNumber Current specific mode to be check. + + @retval EFI_SUCCESS The mode is supported. + @retval EFI_UNSUPPORTED The specific mode is out of range of graphics + device supported. + @retval other The specific mode does not support user defined + resolution or failed to set the current mode to the + specific mode on graphics device. + +**/ +EFI_STATUS +CheckModeSupported ( + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + OUT UINT32 *CurrentModeNumber + ) +{ + UINT32 ModeNumber; + EFI_STATUS Status; + UINTN SizeOfInfo; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + UINT32 MaxMode; + + Status = EFI_SUCCESS; + MaxMode = GraphicsOutput->Mode->MaxMode; + + for (ModeNumber = 0; ModeNumber < MaxMode; ModeNumber++) { + Status = GraphicsOutput->QueryMode ( + GraphicsOutput, + ModeNumber, + &SizeOfInfo, + &Info + ); + if (!EFI_ERROR (Status)) { + if ((Info->HorizontalResolution == HorizontalResolution) && + (Info->VerticalResolution == VerticalResolution)) { + if ((GraphicsOutput->Mode->Info->HorizontalResolution == HorizontalResolution) && + (GraphicsOutput->Mode->Info->VerticalResolution == VerticalResolution)) { + // + // If video device has been set to this mode, we do not need to SetMode again + // + FreePool (Info); + break; + } else { + Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber); + if (!EFI_ERROR (Status)) { + FreePool (Info); + break; + } + } + } + FreePool (Info); + } + } + + if (ModeNumber == GraphicsOutput->Mode->MaxMode) { + Status = EFI_UNSUPPORTED; + } + + *CurrentModeNumber = ModeNumber; + return Status; +} + + +/** + Locate HII Database protocol and HII Font protocol. + + @retval EFI_SUCCESS HII Database protocol and HII Font protocol + are located successfully. + @return other Failed to locate HII Database protocol or + HII Font protocol. + +**/ +EFI_STATUS +EfiLocateHiiProtocol ( + VOID + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &mHiiDatabase); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->LocateProtocol (&gEfiHiiFontProtocolGuid, NULL, (VOID **) &mHiiFont); + return Status; +} + +// +// Body of the STO functions +// + +/** + Reset the text output device hardware and optionally run diagnostics. + + Implements SIMPLE_TEXT_OUTPUT.Reset(). + If ExtendeVerification is TRUE, then perform dependent Graphics Console + device reset, and set display mode to mode 0. + If ExtendedVerification is FALSE, only set display mode to mode 0. + + @param This Protocol instance pointer. + @param ExtendedVerification Indicates that the driver may perform a more + exhaustive verification operation of the device + during reset. + + @retval EFI_SUCCESS The text output device was reset. + @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and + could not be reset. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + Status = This->SetMode (This, 0); + if (EFI_ERROR (Status)) { + return Status; + } + Status = This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)); + return Status; +} + + +/** + Write a Unicode string to the output device. + + Implements SIMPLE_TEXT_OUTPUT.OutputString(). + The Unicode string will be converted to Glyphs and will be + sent to the Graphics Console. + + @param This Protocol instance pointer. + @param WString The NULL-terminated Unicode string to be displayed + on the output device(s). All output devices must + also support the Unicode drawing defined in this file. + + @retval EFI_SUCCESS The string was output to the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to output + the text. + @retval EFI_UNSUPPORTED The output device's mode is not currently in a + defined text mode. + @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +{ + GRAPHICS_CONSOLE_DEV *Private; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + INTN Mode; + UINTN MaxColumn; + UINTN MaxRow; + UINTN Width; + UINTN Height; + UINTN Delta; + EFI_STATUS Status; + BOOLEAN Warning; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; + UINTN DeltaX; + UINTN DeltaY; + UINTN Count; + UINTN Index; + INT32 OriginAttribute; + EFI_TPL OldTpl; + + if (This->Mode->Mode == -1) { + // + // If current mode is not valid, return error. + // + return EFI_UNSUPPORTED; + } + + Status = EFI_SUCCESS; + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + // + // Current mode + // + Mode = This->Mode->Mode; + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + GraphicsOutput = Private->GraphicsOutput; + + MaxColumn = Private->ModeData[Mode].Columns; + MaxRow = Private->ModeData[Mode].Rows; + DeltaX = (UINTN) Private->ModeData[Mode].DeltaX; + DeltaY = (UINTN) Private->ModeData[Mode].DeltaY; + Width = MaxColumn * EFI_GLYPH_WIDTH; + Height = (MaxRow - 1) * EFI_GLYPH_HEIGHT; + Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL); + + // + // The Attributes won't change when during the time OutputString is called + // + GetTextColors (This, &Foreground, &Background); + + FlushCursor (This); + + Warning = FALSE; + + // + // Backup attribute + // + OriginAttribute = This->Mode->Attribute; + + while (*WString != L'\0') { + + if (*WString == CHAR_BACKSPACE) { + // + // If the cursor is at the left edge of the display, then move the cursor + // one row up. + // + if (This->Mode->CursorColumn == 0 && This->Mode->CursorRow > 0) { + This->Mode->CursorRow--; + This->Mode->CursorColumn = (INT32) (MaxColumn - 1); + This->OutputString (This, SpaceStr); + FlushCursor (This); + This->Mode->CursorRow--; + This->Mode->CursorColumn = (INT32) (MaxColumn - 1); + } else if (This->Mode->CursorColumn > 0) { + // + // If the cursor is not at the left edge of the display, then move the cursor + // left one column. + // + This->Mode->CursorColumn--; + This->OutputString (This, SpaceStr); + FlushCursor (This); + This->Mode->CursorColumn--; + } + + WString++; + + } else if (*WString == CHAR_LINEFEED) { + // + // If the cursor is at the bottom of the display, then scroll the display one + // row, and do not update the cursor position. Otherwise, move the cursor + // down one row. + // + if (This->Mode->CursorRow == (INT32) (MaxRow - 1)) { + // + // Scroll Screen Up One Row + // + GraphicsOutput->Blt ( + GraphicsOutput, + NULL, + EfiBltVideoToVideo, + DeltaX, + DeltaY + EFI_GLYPH_HEIGHT, + DeltaX, + DeltaY, + Width, + Height, + Delta + ); + + // + // Print Blank Line at last line + // + GraphicsOutput->Blt ( + GraphicsOutput, + &Background, + EfiBltVideoFill, + 0, + 0, + DeltaX, + DeltaY + Height, + Width, + EFI_GLYPH_HEIGHT, + Delta + ); + } else { + This->Mode->CursorRow++; + } + + WString++; + + } else if (*WString == CHAR_CARRIAGE_RETURN) { + // + // Move the cursor to the beginning of the current row. + // + This->Mode->CursorColumn = 0; + WString++; + + } else if (*WString == WIDE_CHAR) { + + This->Mode->Attribute |= EFI_WIDE_ATTRIBUTE; + WString++; + + } else if (*WString == NARROW_CHAR) { + + This->Mode->Attribute &= (~ (UINT32) EFI_WIDE_ATTRIBUTE); + WString++; + + } else { + // + // Print the character at the current cursor position and move the cursor + // right one column. If this moves the cursor past the right edge of the + // display, then the line should wrap to the beginning of the next line. This + // is equivalent to inserting a CR and an LF. Note that if the cursor is at the + // bottom of the display, and the line wraps, then the display will be scrolled + // one line. + // If wide char is going to be displayed, need to display one character at a time + // Or, need to know the display length of a certain string. + // + // Index is used to determine how many character width units (wide = 2, narrow = 1) + // Count is used to determine how many characters are used regardless of their attributes + // + for (Count = 0, Index = 0; (This->Mode->CursorColumn + Index) < MaxColumn; Count++, Index++) { + if (WString[Count] == CHAR_NULL || + WString[Count] == CHAR_BACKSPACE || + WString[Count] == CHAR_LINEFEED || + WString[Count] == CHAR_CARRIAGE_RETURN || + WString[Count] == WIDE_CHAR || + WString[Count] == NARROW_CHAR) { + break; + } + // + // Is the wide attribute on? + // + if ((This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) != 0) { + // + // If wide, add one more width unit than normal since we are going to increment at the end of the for loop + // + Index++; + // + // This is the end-case where if we are at column 79 and about to print a wide character + // We should prevent this from happening because we will wrap inappropriately. We should + // not print this character until the next line. + // + if ((This->Mode->CursorColumn + Index + 1) > MaxColumn) { + Index++; + break; + } + } + } + + Status = DrawUnicodeWeightAtCursorN (This, WString, Count); + if (EFI_ERROR (Status)) { + Warning = TRUE; + } + // + // At the end of line, output carriage return and line feed + // + WString += Count; + This->Mode->CursorColumn += (INT32) Index; + if (This->Mode->CursorColumn > (INT32) MaxColumn) { + This->Mode->CursorColumn -= 2; + This->OutputString (This, SpaceStr); + } + + if (This->Mode->CursorColumn >= (INT32) MaxColumn) { + FlushCursor (This); + if (!Private->ExtendedTextOutput.AutoWrap) { + This->Mode->CursorColumn = MaxColumn - 1; + } else { + This->OutputString (This, mCrLfString); + } + FlushCursor (This); + } + } + } + + This->Mode->Attribute = OriginAttribute; + + FlushCursor (This); + + if (Warning) { + Status = EFI_WARN_UNKNOWN_GLYPH; + } + + gBS->RestoreTPL (OldTpl); + return Status; + +} + +/** + Verifies that all characters in a Unicode string can be output to the + target device. + + Implements SIMPLE_TEXT_OUTPUT.TestString(). + If one of the characters in the *Wstring is neither valid valid Unicode + drawing characters, not ASCII code, then this function will return + EFI_UNSUPPORTED + + @param This Protocol instance pointer. + @param WString The NULL-terminated Unicode string to be examined for the output + device(s). + + @retval EFI_SUCCESS The device(s) are capable of rendering the output string. + @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be + rendered by one or more of the output devices mapped + by the EFI handle. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +{ + EFI_STATUS Status; + UINT16 Count; + + EFI_IMAGE_OUTPUT *Blt; + + Blt = NULL; + Count = 0; + + while (WString[Count] != 0) { + Status = mHiiFont->GetGlyph ( + mHiiFont, + WString[Count], + NULL, + &Blt, + NULL + ); + if (Blt != NULL) { + FreePool (Blt); + Blt = NULL; + } + Count++; + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + } + + return EFI_SUCCESS; +} + + +/** + Returns information for an available text mode that the output device(s) + supports + + Implements SIMPLE_TEXT_OUTPUT.QueryMode(). + It returnes information for an available text mode that the Graphics Console supports. + In this driver,we only support text mode 80x25, which is defined as mode 0. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param Columns The returned columns of the requested mode. + @param Rows The returned rows of the requested mode. + + @retval EFI_SUCCESS The requested mode information is returned. + @retval EFI_UNSUPPORTED The mode number is not valid. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +{ + GRAPHICS_CONSOLE_DEV *Private; + EFI_STATUS Status; + EFI_TPL OldTpl; + + if (ModeNumber >= (UINTN) This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + Status = EFI_SUCCESS; + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + + *Columns = Private->ModeData[ModeNumber].Columns; + *Rows = Private->ModeData[ModeNumber].Rows; + + if (*Columns <= 0 || *Rows <= 0) { + Status = EFI_UNSUPPORTED; + goto Done; + + } + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + + +/** + Sets the output device(s) to a specified mode. + + Implements SIMPLE_TEXT_OUTPUT.SetMode(). + Set the Graphics Console to a specified mode. In this driver, we only support mode 0. + + @param This Protocol instance pointer. + @param ModeNumber The text mode to set. + + @retval EFI_SUCCESS The requested text mode is set. + @retval EFI_DEVICE_ERROR The requested text mode cannot be set because of + Graphics Console device error. + @retval EFI_UNSUPPORTED The text mode number is not valid. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +{ + EFI_STATUS Status; + GRAPHICS_CONSOLE_DEV *Private; + GRAPHICS_CONSOLE_MODE_DATA *ModeData; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewLineBuffer; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_TPL OldTpl; + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + GraphicsOutput = Private->GraphicsOutput; + + // + // Make sure the requested mode number is supported + // + if (ModeNumber >= (UINTN) This->Mode->MaxMode) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + ModeData = &(Private->ModeData[ModeNumber]); + + if (ModeData->Columns <= 0 && ModeData->Rows <= 0) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + // + // If the mode has been set at least one other time, then LineBuffer will not be NULL + // + if (Private->LineBuffer != NULL) { + // + // If the new mode is the same as the old mode, then just return EFI_SUCCESS + // + if ((INT32) ModeNumber == This->Mode->Mode) { + // + // Clear the current text window on the current graphics console + // + This->ClearScreen (This); + Status = EFI_SUCCESS; + goto Done; + } + // + // Otherwise, the size of the text console and/or the GOP mode will + // be changed, so erase the cursor, and free the LineBuffer for the + // current mode + // + FlushCursor (This); + + FreePool (Private->LineBuffer); + } + + // + // Attempt to allocate a line buffer for the requested mode number + // + NewLineBuffer = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeData->Columns * EFI_GLYPH_WIDTH * EFI_GLYPH_HEIGHT); + + if (NewLineBuffer == NULL) { + // + // The new line buffer could not be allocated, so return an error. + // No changes to the state of the current console have been made, so the current console is still valid + // + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Assign the current line buffer to the newly allocated line buffer + // + Private->LineBuffer = NewLineBuffer; + + if (ModeData->GopModeNumber != GraphicsOutput->Mode->Mode) { + // + // Either no graphics mode is currently set, or it is set + // to the wrong resolution, so set the new graphics mode + // + Status = GraphicsOutput->SetMode (GraphicsOutput, ModeData->GopModeNumber); + if (EFI_ERROR (Status)) { + // + // The mode set operation failed + // + goto Done; + } + } else { + // + // The current graphics mode is correct, so simply clear the entire display + // + Status = GraphicsOutput->Blt ( + GraphicsOutput, + &mGraphicsEfiColors[0], + EfiBltVideoFill, + 0, + 0, + 0, + 0, + ModeData->GopWidth, + ModeData->GopHeight, + 0 + ); + } + + // + // The new mode is valid, so commit the mode change + // + This->Mode->Mode = (INT32) ModeNumber; + + // + // Move the text cursor to the upper left hand corner of the display and flush it + // + This->Mode->CursorColumn = 0; + This->Mode->CursorRow = 0; + + FlushCursor (This); + + Status = EFI_SUCCESS; + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + + +/** + Sets the background and foreground colors for the OutputString () and + ClearScreen () functions. + + Implements SIMPLE_TEXT_OUTPUT.SetAttribute(). + + @param This Protocol instance pointer. + @param Attribute The attribute to set. Bits 0..3 are the foreground + color, and bits 4..6 are the background color. + All other bits are undefined and must be zero. + + @retval EFI_SUCCESS The requested attribute is set. + @retval EFI_DEVICE_ERROR The requested attribute cannot be set due to Graphics Console port error. + @retval EFI_UNSUPPORTED The attribute requested is not defined. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ) +{ + EFI_TPL OldTpl; + + if ((Attribute | 0x7F) != 0x7F) { + return EFI_UNSUPPORTED; + } + + if ((INT32) Attribute == This->Mode->Attribute) { + return EFI_SUCCESS; + } + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + FlushCursor (This); + + This->Mode->Attribute = (INT32) Attribute; + + FlushCursor (This); + + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; +} + + +/** + Clears the output device(s) display to the currently selected background + color. + + Implements SIMPLE_TEXT_OUTPUT.ClearScreen(). + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +{ + EFI_STATUS Status; + GRAPHICS_CONSOLE_DEV *Private; + GRAPHICS_CONSOLE_MODE_DATA *ModeData; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background; + EFI_TPL OldTpl; + + if (This->Mode->Mode == -1) { + // + // If current mode is not valid, return error. + // + return EFI_UNSUPPORTED; + } + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + GraphicsOutput = Private->GraphicsOutput; + ModeData = &(Private->ModeData[This->Mode->Mode]); + + GetTextColors (This, &Foreground, &Background); + Status = GraphicsOutput->Blt ( + GraphicsOutput, + &Background, + EfiBltVideoFill, + 0, + 0, + 0, + 0, + ModeData->GopWidth, + ModeData->GopHeight, + 0 + ); + + This->Mode->CursorColumn = 0; + This->Mode->CursorRow = 0; + + FlushCursor (This); + + gBS->RestoreTPL (OldTpl); + + return Status; +} + + +/** + Sets the current coordinates of the cursor position. + + Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition(). + + @param This Protocol instance pointer. + @param Column The position to set the cursor to. Must be greater than or + equal to zero and less than the number of columns and rows + by QueryMode (). + @param Row The position to set the cursor to. Must be greater than or + equal to zero and less than the number of columns and rows + by QueryMode (). + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the + cursor position is invalid for the current mode. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +{ + GRAPHICS_CONSOLE_DEV *Private; + GRAPHICS_CONSOLE_MODE_DATA *ModeData; + EFI_STATUS Status; + EFI_TPL OldTpl; + + if (This->Mode->Mode == -1) { + // + // If current mode is not valid, return error. + // + return EFI_UNSUPPORTED; + } + + Status = EFI_SUCCESS; + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + ModeData = &(Private->ModeData[This->Mode->Mode]); + + if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + if ((This->Mode->CursorColumn == (INT32) Column) && (This->Mode->CursorRow == (INT32) Row)) { + Status = EFI_SUCCESS; + goto Done; + } + + FlushCursor (This); + + This->Mode->CursorColumn = (INT32) Column; + This->Mode->CursorRow = (INT32) Row; + + FlushCursor (This); + +Done: + gBS->RestoreTPL (OldTpl); + + return Status; +} + + +/** + Makes the cursor visible or invisible. + + Implements SIMPLE_TEXT_OUTPUT.EnableCursor(). + + @param This Protocol instance pointer. + @param Visible If TRUE, the cursor is set to be visible, If FALSE, + the cursor is set to be invisible. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_UNSUPPORTED The output device's mode is not currently in a + defined text mode. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +{ + EFI_TPL OldTpl; + + if (This->Mode->Mode == -1) { + // + // If current mode is not valid, return error. + // + return EFI_UNSUPPORTED; + } + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + FlushCursor (This); + + This->Mode->CursorVisible = Visible; + + FlushCursor (This); + + gBS->RestoreTPL (OldTpl); + return EFI_SUCCESS; +} + +/** + Gets Graphics Console devcie's foreground color and background color. + + @param This Protocol instance pointer. + @param Foreground Returned text foreground color. + @param Background Returned text background color. + + @retval EFI_SUCCESS It returned always. + +**/ +EFI_STATUS +GetTextColors ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground, + OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background + ) +{ + INTN Attribute; + + Attribute = This->Mode->Attribute & 0x7F; + + *Foreground = mGraphicsEfiColors[Attribute & 0x0f]; + *Background = mGraphicsEfiColors[Attribute >> 4]; + + return EFI_SUCCESS; +} + +/** + Draw Unicode string on the Graphics Console device's screen. + + @param This Protocol instance pointer. + @param UnicodeWeight One Unicode string to be displayed. + @param Count The count of Unicode string. + + @retval EFI_OUT_OF_RESOURCES If no memory resource to use. + @retval EFI_UNSUPPORTED If no Graphics Output Protocol exists. + @retval EFI_SUCCESS Drawing Unicode string implemented successfully. + +**/ +EFI_STATUS +DrawUnicodeWeightAtCursorN ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *UnicodeWeight, + IN UINTN Count + ) +{ + EFI_STATUS Status; + GRAPHICS_CONSOLE_DEV *Private; + EFI_IMAGE_OUTPUT *Blt; + EFI_STRING String; + EFI_FONT_DISPLAY_INFO *FontInfo; + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + Blt = (EFI_IMAGE_OUTPUT *) AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT)); + if (Blt == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Blt->Width = (UINT16) (Private->ModeData[This->Mode->Mode].GopWidth); + Blt->Height = (UINT16) (Private->ModeData[This->Mode->Mode].GopHeight); + + String = AllocateCopyPool ((Count + 1) * sizeof (CHAR16), UnicodeWeight); + if (String == NULL) { + FreePool (Blt); + return EFI_OUT_OF_RESOURCES; + } + // + // Set the end character + // + *(String + Count) = L'\0'; + + FontInfo = (EFI_FONT_DISPLAY_INFO *) AllocateZeroPool (sizeof (EFI_FONT_DISPLAY_INFO)); + if (FontInfo == NULL) { + FreePool (Blt); + FreePool (String); + return EFI_OUT_OF_RESOURCES; + } + // + // Get current foreground and background colors. + // + GetTextColors (This, &FontInfo->ForegroundColor, &FontInfo->BackgroundColor); + + // + // If Graphics Output protocol exists, using HII Font protocol to draw. + // + Blt->Image.Screen = Private->GraphicsOutput; + + Status = mHiiFont->StringToImage ( + mHiiFont, + EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_DIRECT_TO_SCREEN | EFI_HII_IGNORE_LINE_BREAK, + String, + FontInfo, + &Blt, + This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX, + This->Mode->CursorRow * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY, + NULL, + NULL, + NULL + ); + + if (Blt != NULL) { + FreePool (Blt); + } + if (String != NULL) { + FreePool (String); + } + if (FontInfo != NULL) { + FreePool (FontInfo); + } + return Status; +} + +/** + Flush the cursor on the screen. + + If CursorVisible is FALSE, nothing to do and return directly. + If CursorVisible is TRUE, + i) If the cursor shows on screen, it will be erased. + ii) If the cursor does not show on screen, it will be shown. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The cursor is erased successfully. + +**/ +EFI_STATUS +FlushCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +{ + GRAPHICS_CONSOLE_DEV *Private; + EFI_SIMPLE_TEXT_OUTPUT_MODE *CurrentMode; + INTN GlyphX; + INTN GlyphY; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar[EFI_GLYPH_HEIGHT][EFI_GLYPH_WIDTH]; + UINTN PosX; + UINTN PosY; + + CurrentMode = This->Mode; + + if (!CurrentMode->CursorVisible) { + return EFI_SUCCESS; + } + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + GraphicsOutput = Private->GraphicsOutput; + + // + // In this driver, only narrow character was supported. + // + // + // Blt a character to the screen + // + GlyphX = (CurrentMode->CursorColumn * EFI_GLYPH_WIDTH) + Private->ModeData[CurrentMode->Mode].DeltaX; + GlyphY = (CurrentMode->CursorRow * EFI_GLYPH_HEIGHT) + Private->ModeData[CurrentMode->Mode].DeltaY; + + GraphicsOutput->Blt ( + GraphicsOutput, + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar, + EfiBltVideoToBltBuffer, + GlyphX, + GlyphY, + 0, + 0, + EFI_GLYPH_WIDTH, + EFI_GLYPH_HEIGHT, + EFI_GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + + GetTextColors (This, &Foreground.Pixel, &Background.Pixel); + + // + // Convert Monochrome bitmap of the Glyph to BltBuffer structure + // + for (PosY = 0; PosY < EFI_GLYPH_HEIGHT; PosY++) { + for (PosX = 0; PosX < EFI_GLYPH_WIDTH; PosX++) { + if ((mCursorGlyph.GlyphCol1[PosY] & (BIT0 << PosX)) != 0) { + BltChar[PosY][EFI_GLYPH_WIDTH - PosX - 1].Raw ^= Foreground.Raw; + } + } + } + + GraphicsOutput->Blt ( + GraphicsOutput, + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) BltChar, + EfiBltBufferToVideo, + 0, + 0, + GlyphX, + GlyphY, + EFI_GLYPH_WIDTH, + EFI_GLYPH_HEIGHT, + EFI_GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + ); + + return EFI_SUCCESS; +} + +/** + HII Database Protocol notification event handler. + + Register font package when HII Database Protocol has been installed. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the notification function's context. +**/ +VOID +EFIAPI +RegisterFontPackage ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_HII_SIMPLE_FONT_PACKAGE_HDR *SimplifiedFont; + UINT32 PackageLength; + UINT8 *Package; + UINT8 *Location; + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + + // + // Locate HII Database Protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiDatabaseProtocolGuid, + NULL, + (VOID **) &HiiDatabase + ); + if (EFI_ERROR (Status)) { + return; + } + + // + // Add 4 bytes to the header for entire length for HiiAddPackages use only. + // + // +--------------------------------+ <-- Package + // | | + // | PackageLength(4 bytes) | + // | | + // |--------------------------------| <-- SimplifiedFont + // | | + // |EFI_HII_SIMPLE_FONT_PACKAGE_HDR | + // | | + // |--------------------------------| <-- Location + // | | + // | gUsStdNarrowGlyphData | + // | | + // +--------------------------------+ + + PackageLength = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR) + mNarrowFontSize + 4; + Package = AllocateZeroPool (PackageLength); + ASSERT (Package != NULL); + + WriteUnaligned32((UINT32 *) Package,PackageLength); + SimplifiedFont = (EFI_HII_SIMPLE_FONT_PACKAGE_HDR *) (Package + 4); + SimplifiedFont->Header.Length = (UINT32) (PackageLength - 4); + SimplifiedFont->Header.Type = EFI_HII_PACKAGE_SIMPLE_FONTS; + SimplifiedFont->NumberOfNarrowGlyphs = (UINT16) (mNarrowFontSize / sizeof (EFI_NARROW_GLYPH)); + + Location = (UINT8 *) (&SimplifiedFont->NumberOfWideGlyphs + 1); + CopyMem (Location, gUsStdNarrowGlyphData, mNarrowFontSize); + + // + // Add this simplified font package to a package list then install it. + // + mHiiHandle = HiiAddPackages ( + &mFontPackageListGuid, + NULL, + Package, + NULL + ); + ASSERT (mHiiHandle != NULL); + FreePool (Package); +} + +/** + The user Entry Point for module GraphicsConsole. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @return other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeGraphicsConsole ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Register notify function on HII Database Protocol to add font package. + // + EfiCreateProtocolNotifyEvent ( + &gEfiHiiDatabaseProtocolGuid, + TPL_CALLBACK, + RegisterFontPackage, + NULL, + &mHiiRegistration + ); + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gGraphicsConsoleDriverBinding, + ImageHandle, + &gGraphicsConsoleComponentName, + &gGraphicsConsoleComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsole.h b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsole.h new file mode 100644 index 000000000000..ba93cab86bf3 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsole.h @@ -0,0 +1,591 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) 2006-2016, Intel Corporation. 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 _GRAPHICS_CONSOLE_H_ +#define _GRAPHICS_CONSOLE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_COMPONENT_NAME_PROTOCOL gGraphicsConsoleComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gGraphicsConsoleComponentName2; +extern EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding; +extern EFI_NARROW_GLYPH gUsStdNarrowGlyphData[]; + +extern UINT32 mNarrowFontSize; + +typedef union { + EFI_NARROW_GLYPH NarrowGlyph; + EFI_WIDE_GLYPH WideGlyph; +} GLYPH_UNION; + +// +// Device Structure +// +#define GRAPHICS_CONSOLE_DEV_SIGNATURE SIGNATURE_32 ('g', 's', 't', 'o') + +typedef struct { + UINTN Columns; + UINTN Rows; + INTN DeltaX; + INTN DeltaY; + UINT32 GopWidth; + UINT32 GopHeight; + UINT32 GopModeNumber; +} GRAPHICS_CONSOLE_MODE_DATA; + +typedef struct { + UINTN Signature; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOutput; + EFI_SIMPLE_TEXT_OUTPUT_MODE SimpleTextOutputMode; + GRAPHICS_CONSOLE_MODE_DATA *ModeData; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *LineBuffer; + EXTENDED_TEXT_OUTPUT_PROTOCOL ExtendedTextOutput; +} GRAPHICS_CONSOLE_DEV; + +#define GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS(a) \ + CR (a, GRAPHICS_CONSOLE_DEV, SimpleTextOutput, GRAPHICS_CONSOLE_DEV_SIGNATURE) + + +// +// EFI Component Name Functions +// +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param ChildHandle[in] The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +/** + Reset the text output device hardware and optionally run diagnostics. + + Implements SIMPLE_TEXT_OUTPUT.Reset(). + If ExtendeVerification is TRUE, then perform dependent Graphics Console + device reset, and set display mode to mode 0. + If ExtendedVerification is FALSE, only set display mode to mode 0. + + @param This Protocol instance pointer. + @param ExtendedVerification Indicates that the driver may perform a more + exhaustive verification operation of the device + during reset. + + @retval EFI_SUCCESS The text output device was reset. + @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and + could not be reset. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Write a Unicode string to the output device. + + Implements SIMPLE_TEXT_OUTPUT.OutputString(). + The Unicode string will be converted to Glyphs and will be + sent to the Graphics Console. + + @param This Protocol instance pointer. + @param WString The NULL-terminated Unicode string to be displayed + on the output device(s). All output devices must + also support the Unicode drawing defined in this file. + + @retval EFI_SUCCESS The string was output to the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to output + the text. + @retval EFI_UNSUPPORTED The output device's mode is not currently in a + defined text mode. + @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ); + +/** + Verifies that all characters in a Unicode string can be output to the + target device. + + Implements SIMPLE_TEXT_OUTPUT.TestString(). + If one of the characters in the *Wstring is neither valid valid Unicode + drawing characters, not ASCII code, then this function will return + EFI_UNSUPPORTED + + @param This Protocol instance pointer. + @param WString The NULL-terminated Unicode string to be examined for the output + device(s). + + @retval EFI_SUCCESS The device(s) are capable of rendering the output string. + @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be + rendered by one or more of the output devices mapped + by the EFI handle. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ); + +/** + Returns information for an available text mode that the output device(s) + supports + + Implements SIMPLE_TEXT_OUTPUT.QueryMode(). + It returnes information for an available text mode that the Graphics Console supports. + In this driver,we only support text mode 80x25, which is defined as mode 0. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param Columns The returned columns of the requested mode. + @param Rows The returned rows of the requested mode. + + @retval EFI_SUCCESS The requested mode information is returned. + @retval EFI_UNSUPPORTED The mode number is not valid. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ); + + +/** + Sets the output device(s) to a specified mode. + + Implements SIMPLE_TEXT_OUTPUT.SetMode(). + Set the Graphics Console to a specified mode. In this driver, we only support mode 0. + + @param This Protocol instance pointer. + @param ModeNumber The text mode to set. + + @retval EFI_SUCCESS The requested text mode is set. + @retval EFI_DEVICE_ERROR The requested text mode cannot be set because of + Graphics Console device error. + @retval EFI_UNSUPPORTED The text mode number is not valid. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ); + +/** + Sets the background and foreground colors for the OutputString () and + ClearScreen () functions. + + Implements SIMPLE_TEXT_OUTPUT.SetAttribute(). + + @param This Protocol instance pointer. + @param Attribute The attribute to set. Bits 0..3 are the foreground + color, and bits 4..6 are the background color. + All other bits are undefined and must be zero. + + @retval EFI_SUCCESS The requested attribute is set. + @retval EFI_DEVICE_ERROR The requested attribute cannot be set due to Graphics Console port error. + @retval EFI_UNSUPPORTED The attribute requested is not defined. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ); + +/** + Clears the output device(s) display to the currently selected background + color. + + Implements SIMPLE_TEXT_OUTPUT.ClearScreen(). + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ); + +/** + Sets the current coordinates of the cursor position. + + Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition(). + + @param This Protocol instance pointer. + @param Column The position to set the cursor to. Must be greater than or + equal to zero and less than the number of columns and rows + by QueryMode (). + @param Row The position to set the cursor to. Must be greater than or + equal to zero and less than the number of columns and rows + by QueryMode (). + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the + cursor position is invalid for the current mode. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ); + + +/** + Makes the cursor visible or invisible. + + Implements SIMPLE_TEXT_OUTPUT.EnableCursor(). + + @param This Protocol instance pointer. + @param Visible If TRUE, the cursor is set to be visible, If FALSE, + the cursor is set to be invisible. + + @retval EFI_SUCCESS The operation completed successfully. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleConOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ); + +/** + Test to see if Graphics Console could be supported on the Controller. + + Graphics Console could be supported if Graphics Output Protocol exists + on the Controller. + + @param This Protocol instance pointer. + @param Controller Handle of device to test. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + + +/** + Start this driver on Controller by opening the Graphics Output Protocol, + and installing Simple Text Out protocol on Controller. + + @param This Protocol instance pointer. + @param Controller Handle of device to bind driver to + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver is added to Controller. + @retval other This driver does not support this device. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop this driver on Controller by removing Simple Text Out protocol + and closing the Graphics Output Protocol on Controller. + + @param This Protocol instance pointer. + @param Controller Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed Controller. + @retval EFI_NOT_STARTED Simple Text Out protocol could not be found the + Controller. + @retval other This driver was not removed from this device. + +**/ +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + + +/** + Locate HII Database protocol and HII Font protocol. + + @retval EFI_SUCCESS HII Database protocol and HII Font protocol + are located successfully. + @return other Failed to locate HII Database protocol or + HII Font protocol. + +**/ +EFI_STATUS +EfiLocateHiiProtocol ( + VOID + ); + + +/** + Gets Graphics Console devcie's foreground color and background color. + + @param This Protocol instance pointer. + @param Foreground Returned text foreground color. + @param Background Returned text background color. + + @retval EFI_SUCCESS It returned always. + +**/ +EFI_STATUS +GetTextColors ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Foreground, + OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background + ); + +/** + Draw Unicode string on the Graphics Console device's screen. + + @param This Protocol instance pointer. + @param UnicodeWeight One Unicode string to be displayed. + @param Count The count of Unicode string. + + @retval EFI_OUT_OF_RESOURCES If no memory resource to use. + @retval EFI_UNSUPPORTED If no Graphics Output Protocol exists. + @retval EFI_SUCCESS Drawing Unicode string implemented successfully. + +**/ +EFI_STATUS +DrawUnicodeWeightAtCursorN ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *UnicodeWeight, + IN UINTN Count + ); + +/** + Flush the cursor on the screen. + + If CursorVisible is FALSE, nothing to do and return directly. + If CursorVisible is TRUE, + i) If the cursor shows on screen, it will be erased. + ii) If the cursor does not show on screen, it will be shown. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The cursor is erased successfully. + +**/ +EFI_STATUS +FlushCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ); + +/** + Check if the current specific mode supported the user defined resolution + for the Graphics Console device based on Graphics Output Protocol. + + If yes, set the graphic device's current mode to this specific mode. + + @param GraphicsOutput Graphics Output Protocol instance pointer. + @param HorizontalResolution User defined horizontal resolution + @param VerticalResolution User defined vertical resolution. + @param CurrentModeNumber Current specific mode to be check. + + @retval EFI_SUCCESS The mode is supported. + @retval EFI_UNSUPPORTED The specific mode is out of range of graphics + device supported. + @retval other The specific mode does not support user defined + resolution or failed to set the current mode to the + specific mode on graphics device. + +**/ +EFI_STATUS +CheckModeSupported ( + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + OUT UINT32 *CurrentModeNumber + ); + +#endif diff --git a/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxe.inf new file mode 100644 index 000000000000..cf359b414682 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxe.inf @@ -0,0 +1,74 @@ +#/** @file +# +# Copyright (c) 2006-2014, Intel Corporation. All rights reserved. +# Copyright (c) 2018, Andrei Warkentin +# +# 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 = GraphicsConsoleDxe + MODULE_UNI_FILE = GraphicsConsoleDxe.uni + FILE_GUID = CCCB0C28-4B24-11d5-9A5A-0090273FC14D + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.1 + ENTRY_POINT = InitializeGraphicsConsole + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC AARCH64 +# +# DRIVER_BINDING = gGraphicsConsoleDriverBinding +# COMPONENT_NAME = gGraphicsConsoleComponentName +# COMPONENT_NAME2 = gGraphicsConsoleComponentName2 +# + +[Sources] + ComponentName.c + NewFont.c + GraphicsConsole.c + GraphicsConsole.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + MemoryAllocationLib + BmpSupportLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + DebugLib + HiiLib + PcdLib + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiSimpleTextOutProtocolGuid + gEfiGraphicsOutputProtocolGuid + gEfiHiiFontProtocolGuid + gEfiHiiDatabaseProtocolGuid + gExtendedTextOutputProtocolGuid + +[FeaturePcd] + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution ## SOMETIMES_CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution ## SOMETIMES_CONSUMES + +[UserExtensions.TianoCore."ExtraFiles"] + GraphicsConsoleDxeExtra.uni diff --git a/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxe.uni b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxe.uni new file mode 100644 index 000000000000..09336b5cae36 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxe.uni @@ -0,0 +1,19 @@ +/** @file + * + * Copyright (c) 2006-2014, Intel Corporation. All rights reserved. + * Copyright (c) 2018, Andrei Warkentin + * + * 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. + * + **/ + +#string STR_MODULE_ABSTRACT #language en-US "Console support on graphic devices" + +#string STR_MODULE_DESCRIPTION #language en-US "Install SimpleTextOutputProtocol on GraphicsOutputProtocol devices\n" + diff --git a/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxeExtra.uni b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxeExtra.uni new file mode 100644 index 000000000000..cb8a6e0dbb5e --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxeExtra.uni @@ -0,0 +1,20 @@ +/** @file + * + * Copyright (c) 2006-2014, Intel Corporation. All rights reserved. + * Copyright (c) 2018, Andrei Warkentin + * + * 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. + * + **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"Graphics Console DXE Driver" + + diff --git a/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/NewFont.c b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/NewFont.c new file mode 100644 index 000000000000..6331b89b10dd --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/NewFont.c @@ -0,0 +1,288 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * + * 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. + * + **/ + +/* + * Based on ftp://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP437.TXT and + * https://en.wikipedia.org/wiki/Code_page_437 for the cp437 Unicode equivalents + * and the cp437 8x19 font from that_editor. + * + * https://github.com/bisqwit/that_editor/blob/master/8x19.inc + * https://github.com/bisqwit/that_editor/blob/master/sourcematerial/vga8x19.bdf + * https://github.com/stsp/dosemu2/blob/master/COPYING.DOSEMU + */ + +#include "GraphicsConsole.h" + +EFI_NARROW_GLYPH gUsStdNarrowGlyphData[] = { + { 0x263a, 0x00, {0x00,0x00,0x7E,0x81,0xA5,0xA5,0x81,0x81,0xA5,0xA5,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,0x00}}, + { 0x263b, 0x00, {0x00,0x00,0x7E,0xFF,0xDB,0xFF,0xFF,0xFF,0xDB,0xE7,0xFF,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x00,0x00}}, + { 0x2665, 0x00, {0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2666, 0x00, {0x00,0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2663, 0x00, {0x00,0x00,0x00,0x18,0x3C,0x3C,0xFF,0xE7,0xE7,0xE7,0xFF,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x2660, 0x00, {0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0xFF,0x7E,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x2022, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x25d8, 0x00, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}, + { 0x25cb, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x66,0x42,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x25d9, 0x00, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDB,0x99,0xBD,0xBD,0x99,0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}, + { 0x2642, 0x00, {0x00,0x00,0x1E,0x06,0x0E,0x0A,0x1A,0x78,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,0x00}}, + { 0x2640, 0x00, {0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x266a, 0x00, {0x00,0x00,0x3F,0x33,0x33,0x3F,0x30,0x30,0x30,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00}}, + { 0x266b, 0x00, {0x00,0x00,0x7F,0x63,0x63,0x7F,0x63,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00,0x00}}, + { 0x263c, 0x00, {0x00,0x00,0x00,0x18,0x18,0xDB,0xFF,0x3C,0xE7,0x3C,0xFF,0xDB,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x25ba, 0x00, {0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00}}, + { 0x25c4, 0x00, {0x00,0x02,0x06,0x0E,0x1E,0x3E,0x7E,0xFE,0x7E,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,0x00}}, + { 0x2195, 0x00, {0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x203c, 0x00, {0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b6, 0x00, {0x00,0x00,0x7F,0xDB,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00,0x00}}, + { 0x00a7, 0x00, {0x00,0x00,0x7C,0xC6,0x62,0x30,0x78,0x4C,0x64,0x3C,0x18,0x8C,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x25ac, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00}}, + { 0x21a8, 0x00, {0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,0x00}}, + { 0x2191, 0x00, {0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x2193, 0x00, {0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x2192, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2190, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x221f, 0x00, {0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2194, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x25b2, 0x00, {0x00,0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x25bc, 0x00, {0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0020, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0021, 0x00, {0x00,0x00,0x18,0x3C,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x0022, 0x00, {0x66,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0023, 0x00, {0x00,0x00,0x00,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0024, 0x00, {0x10,0x10,0x7C,0xD6,0xD6,0xD2,0x70,0x38,0x1C,0x16,0x96,0xD6,0xD6,0x7C,0x10,0x10,0x00,0x00,0x00}}, + { 0x0025, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00,0x00}}, + { 0x0026, 0x00, {0x00,0x00,0x38,0x6C,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x0027, 0x00, {0x30,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0028, 0x00, {0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0029, 0x00, {0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00}}, + { 0x002a, 0x00, {0x00,0x00,0x00,0x00,0x00,0x66,0x24,0x3C,0xFF,0x3C,0x24,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x002b, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x002c, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00}}, + { 0x002d, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x002e, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x002f, 0x00, {0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0030, 0x00, {0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,0x00}}, + { 0x0031, 0x00, {0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,0x00}}, + { 0x0032, 0x00, {0x00,0x00,0x7C,0xC6,0x06,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00}}, + { 0x0033, 0x00, {0x00,0x00,0x7C,0xC6,0x06,0x06,0x06,0x3C,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0034, 0x00, {0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00,0x00}}, + { 0x0035, 0x00, {0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0036, 0x00, {0x00,0x00,0x38,0x60,0xC0,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0037, 0x00, {0x00,0x00,0xFE,0xC6,0x06,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,0x00}}, + { 0x0038, 0x00, {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0039, 0x00, {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00,0x00}}, + { 0x003a, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x003b, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00}}, + { 0x003c, 0x00, {0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00,0x00}}, + { 0x003d, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x003e, 0x00, {0x00,0x00,0x00,0xC0,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,0x00,0x00,0x00,0x00}}, + { 0x003f, 0x00, {0x00,0x00,0x7C,0xC6,0x86,0x06,0x0C,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x0040, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xCE,0xDE,0xDE,0xDE,0xDE,0xCC,0xC0,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0041, 0x00, {0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x0042, 0x00, {0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00,0x00}}, + { 0x0043, 0x00, {0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0044, 0x00, {0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00,0x00}}, + { 0x0045, 0x00, {0x00,0x00,0xFE,0x66,0x62,0x62,0x68,0x78,0x68,0x60,0x62,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,0x00}}, + { 0x0046, 0x00, {0x00,0x00,0xFE,0x66,0x62,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,0x00}}, + { 0x0047, 0x00, {0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00,0x00}}, + { 0x0048, 0x00, {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x0049, 0x00, {0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x004a, 0x00, {0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,0x00}}, + { 0x004b, 0x00, {0x00,0x00,0xE6,0x66,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,0x00}}, + { 0x004c, 0x00, {0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,0x00}}, + { 0x004d, 0x00, {0x00,0x00,0xC6,0xEE,0xFE,0xD6,0xD6,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x004e, 0x00, {0x00,0x00,0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x004f, 0x00, {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0050, 0x00, {0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,0x00}}, + { 0x0051, 0x00, {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00,0x00}}, + { 0x0052, 0x00, {0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,0x00}}, + { 0x0053, 0x00, {0x00,0x00,0x7C,0xC6,0xC6,0xC2,0x60,0x38,0x0C,0x06,0x86,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0054, 0x00, {0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0055, 0x00, {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0056, 0x00, {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00,0x00}}, + { 0x0057, 0x00, {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0058, 0x00, {0x00,0x00,0xC6,0xC6,0x6C,0x6C,0x38,0x38,0x38,0x38,0x6C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x0059, 0x00, {0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x005a, 0x00, {0x00,0x00,0xFE,0xC6,0x86,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00}}, + { 0x005b, 0x00, {0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x005c, 0x00, {0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x60,0x30,0x18,0x0C,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x005d, 0x00, {0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x005e, 0x00, {0x00,0x10,0x38,0x6C,0xC6,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x005f, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00}}, + { 0x0060, 0x00, {0x30,0x30,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0061, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x0062, 0x00, {0x00,0x00,0xE0,0x60,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0063, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0064, 0x00, {0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x0065, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0066, 0x00, {0x00,0x00,0x1C,0x36,0x32,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00,0x00}}, + { 0x0067, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0xCC,0x78,0x00}}, + { 0x0068, 0x00, {0x00,0x00,0xE0,0x60,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,0x00}}, + { 0x0069, 0x00, {0x00,0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x006a, 0x00, {0x00,0x00,0x00,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00}}, + { 0x006b, 0x00, {0x00,0x00,0xE0,0x60,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,0x00}}, + { 0x006c, 0x00, {0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x006d, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xD6,0xD6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x006e, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00}}, + { 0x006f, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0070, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0xF0,0x00}}, + { 0x0071, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x0C,0x1E,0x00}}, + { 0x0072, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,0x00}}, + { 0x0073, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC2,0x78,0x0C,0x86,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0074, 0x00, {0x00,0x00,0x10,0x30,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0075, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x0076, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x0077, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00,0x00}}, + { 0x0078, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x10,0x38,0x6C,0xC6,0x82,0x00,0x00,0x00,0x00,0x00}}, + { 0x0079, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x0C,0xF8,0x00}}, + { 0x007a, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00}}, + { 0x007b, 0x00, {0x00,0x00,0x0E,0x18,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00,0x00}}, + { 0x007c, 0x00, {0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x007d, 0x00, {0x00,0x00,0x70,0x18,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,0x00}}, + { 0x007e, 0x00, {0x00,0x76,0xD4,0x9C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2302, 0x00, {0x00,0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00c7, 0x00, {0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00,0x00}}, + { 0x00fc, 0x00, {0x00,0x00,0x00,0xCC,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x00e9, 0x00, {0x00,0x0C,0x18,0x30,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00e2, 0x00, {0x00,0x10,0x38,0x6C,0x00,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x00e4, 0x00, {0x00,0x00,0x00,0xCC,0xCC,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x00e0, 0x00, {0x00,0x60,0x30,0x18,0x0C,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x00e5, 0x00, {0x00,0x38,0x6C,0x6C,0x38,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x00e7, 0x00, {0x00,0x00,0x00,0x00,0x3C,0x66,0x62,0x60,0x60,0x66,0x64,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00ea, 0x00, {0x00,0x10,0x38,0x6C,0x44,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00eb, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00e8, 0x00, {0x00,0x60,0x30,0x18,0x0C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ef, 0x00, {0x00,0x00,0x00,0x66,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ee, 0x00, {0x00,0x18,0x3C,0x66,0x42,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ec, 0x00, {0x00,0x60,0x30,0x18,0x08,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00c4, 0x00, {0xC6,0xC6,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x00c5, 0x00, {0x38,0x28,0x38,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x00c9, 0x00, {0x18,0x30,0x60,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,0x00}}, + { 0x00e6, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00,0x00}}, + { 0x00c6, 0x00, {0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00,0x00}}, + { 0x00f4, 0x00, {0x00,0x10,0x38,0x6C,0x44,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00f6, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00f2, 0x00, {0x00,0x60,0x30,0x18,0x0C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00fb, 0x00, {0x00,0x30,0x78,0xCC,0x84,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x00f9, 0x00, {0x00,0x60,0x30,0x18,0x0C,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ff, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x0C,0x78,0x00}}, + { 0x00d6, 0x00, {0xC6,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00dc, 0x00, {0xC6,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00a2, 0x00, {0x08,0x08,0x3C,0x6E,0xCA,0xC8,0xC8,0xC8,0xC8,0xC8,0xC8,0xCA,0x6E,0x3C,0x08,0x08,0x00,0x00,0x00}}, + { 0x00a3, 0x00, {0x00,0x38,0x6C,0x64,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0x62,0xE6,0xFC,0x00,0x00,0x00,0x00,0x00}}, + { 0x00a5, 0x00, {0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x20a7, 0x00, {0x00,0xF8,0xCC,0xCC,0xFC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x0192, 0x00, {0x00,0x0E,0x1B,0x19,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0x98,0xD8,0x70,0x00,0x00,0x00}}, + { 0x00e1, 0x00, {0x00,0x18,0x30,0x60,0xC0,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ed, 0x00, {0x00,0x0C,0x18,0x30,0x20,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00f3, 0x00, {0x00,0x18,0x30,0x60,0x40,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00fa, 0x00, {0x00,0x18,0x30,0x60,0x40,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x00f1, 0x00, {0x00,0x00,0x36,0xD4,0x88,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00}}, + { 0x00d1, 0x00, {0x36,0xCC,0x00,0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x00aa, 0x00, {0x00,0x3C,0x6C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ba, 0x00, {0x00,0x38,0x6C,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00bf, 0x00, {0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x30,0x60,0xC0,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x2310, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ac, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00}}, + { 0x00bd, 0x00, {0x00,0xC0,0xC0,0xC0,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC0,0x9C,0x06,0x0C,0x18,0x3E,0x00,0x00,0x00}}, + { 0x00bc, 0x00, {0x00,0xC0,0xC0,0xC0,0xC2,0xC6,0x0C,0x18,0x30,0x66,0xCE,0x9A,0x32,0x3E,0x06,0x06,0x00,0x00,0x00}}, + { 0x00a1, 0x00, {0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ab, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00bb, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2591, 0x00, {0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11}}, + { 0x2592, 0x00, {0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55}}, + { 0x2593, 0x00, {0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD}}, + { 0x2502, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x2524, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x2561, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x2562, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x2556, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x2555, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x2563, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x2551, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x2557, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x255d, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x255c, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x255b, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2510, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x2514, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2534, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x252c, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x251c, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x2500, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x253c, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x255e, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x255f, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x255a, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2554, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x2569, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2566, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x2560, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x2550, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x256c, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x2567, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2568, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2564, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x2565, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x2559, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2558, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2552, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x2553, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x256b, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { 0x256a, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x2518, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x250c, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x2588, 0x00, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}, + { 0x2584, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}, + { 0x258c, 0x00, {0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0}}, + { 0x2590, 0x00, {0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F}}, + { 0x2580, 0x00, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x03b1, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00,0x00}}, + { 0x00df, 0x00, {0x00,0x00,0x78,0xCC,0xCC,0xCC,0xCC,0xD8,0xCC,0xC6,0xC6,0xC6,0xC6,0xCC,0x00,0x00,0x00,0x00,0x00}}, + { 0x0393, 0x00, {0x00,0x00,0xFE,0xC6,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00}}, + { 0x03c0, 0x00, {0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}}, + { 0x03a3, 0x00, {0x00,0x00,0x00,0xFE,0xC6,0xC2,0x60,0x30,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00}}, + { 0x03c3, 0x00, {0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b5, 0x00, {0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xC0,0x00,0x00,0x00,0x00}}, + { 0x03c4, 0x00, {0x00,0x00,0x00,0x00,0x76,0xDC,0x98,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x03a6, 0x00, {0x00,0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,0x00}}, + { 0x0398, 0x00, {0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,0x00}}, + { 0x03a9, 0x00, {0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00,0x00}}, + { 0x03b4, 0x00, {0x00,0x00,0x1E,0x20,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00}}, + { 0x221e, 0x00, {0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x03c6, 0x00, {0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xDB,0xDB,0xD3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00,0x00}}, + { 0x03b5, 0x00, {0x00,0x00,0x1C,0x30,0x60,0x60,0x60,0x7C,0x60,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00,0x00}}, + { 0x2229, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x2261, 0x00, {0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b1, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00}}, + { 0x2265, 0x00, {0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x7E,0x00,0x00,0x00,0x00,0x00}}, + { 0x2264, 0x00, {0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x7E,0x00,0x00,0x00,0x00,0x00}}, + { 0x2320, 0x00, {0x00,0x00,0x0E,0x1B,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { 0x2321, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00}}, + { 0x00f7, 0x00, {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2248, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b0, 0x00, {0x00,0x38,0x6C,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x2219, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b7, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x221a, 0x00, {0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00,0x00}}, + { 0x207f, 0x00, {0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b2, 0x00, {0x00,0x70,0xD8,0x10,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x25a0, 0x00, {0x00,0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00a0, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0000, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} //EOL +}; + +// Get available Unicode glyphs narrow fonts(8*19 pixels) size. +UINT32 mNarrowFontSize = sizeof (gUsStdNarrowGlyphData); + diff --git a/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/ComponentName.c b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/ComponentName.c new file mode 100644 index 000000000000..80eb4ff9a870 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/ComponentName.c @@ -0,0 +1,163 @@ +/** @file + * + * Component Name Protocol implementation for the MMC DXE driver + * + * Copyright (c) 2011, 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 "Mmc.h" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gMmcComponentName = { + MmcGetDriverName, + MmcGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gMmcComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) MmcGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) MmcGetControllerName, + "en" +}; + +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE +mMmcDriverNameTable[] = { + {"eng;en", L"MMC/SD Card Interface Driver"}, + {NULL, NULL} +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + @param DriverName A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +MmcGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mMmcDriverNameTable, + DriverName, + (BOOLEAN)(This == &gMmcComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param ControllerHandle The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + @param ChildHandle The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + @param Language A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + @param ControllerName A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +MmcGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/Diagnostics.c b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/Diagnostics.c new file mode 100644 index 000000000000..f0ff16708b67 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/Diagnostics.c @@ -0,0 +1,256 @@ +/** @file + * + * Diagnostics Protocol implementation for the MMC DXE driver + * + * Copyright (c) 2011-2014, ARM Limited. All rights reserved. + * + * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + **/ + +#include +#include +#include +#include +#include + +#include "Mmc.h" + +#define DIAGNOSTIC_LOGBUFFER_MAXCHAR 1024 + +CHAR16* mLogBuffer = NULL; +UINTN mLogRemainChar = 0; + +CHAR16* +DiagnosticInitLog ( + UINTN MaxBufferChar + ) +{ + mLogRemainChar = MaxBufferChar; + mLogBuffer = AllocatePool ((UINTN)MaxBufferChar * sizeof (CHAR16)); + return mLogBuffer; +} + +UINTN +DiagnosticLog ( + CONST CHAR16* Str + ) +{ + UINTN len = StrLen (Str); + if (len < mLogRemainChar) { + StrCpyS (mLogBuffer, mLogRemainChar, Str); + mLogRemainChar -= len; + mLogBuffer += len; + return len; + } else { + return 0; + } +} + +VOID +GenerateRandomBuffer ( + VOID* Buffer, + UINTN BufferSize + ) +{ + UINT64 i; + UINT64* Buffer64 = (UINT64*)Buffer; + + for (i = 0; i < (BufferSize >> 3); i++) { + *Buffer64 = i | (~i << 32); + Buffer64++; + } +} + +BOOLEAN +CompareBuffer ( + VOID *BufferA, + VOID *BufferB, + UINTN BufferSize + ) +{ + UINTN i; + UINT64* BufferA64 = (UINT64*)BufferA; + UINT64* BufferB64 = (UINT64*)BufferB; + + for (i = 0; i < (BufferSize >> 3); i++) { + if (*BufferA64 != *BufferB64) { + DEBUG ((DEBUG_ERROR, "CompareBuffer: Error at %i", i)); + DEBUG ((DEBUG_ERROR, "(0x%lX) != (0x%lX)\n", *BufferA64, *BufferB64)); + return FALSE; + } + BufferA64++; + BufferB64++; + } + return TRUE; +} + +EFI_STATUS +MmcReadWriteDataTest ( + MMC_HOST_INSTANCE *MmcHostInstance, + EFI_LBA Lba, + UINTN BufferSize + ) +{ + VOID *BackBuffer; + VOID *WriteBuffer; + VOID *ReadBuffer; + EFI_STATUS Status; + + // Check if a Media is Present + if (!MmcHostInstance->BlockIo.Media->MediaPresent) { + DiagnosticLog (L"ERROR: No Media Present\n"); + return EFI_NO_MEDIA; + } + + if (MmcHostInstance->State != MmcTransferState) { + DiagnosticLog (L"ERROR: Not ready for Transfer state\n"); + return EFI_NOT_READY; + } + + BackBuffer = AllocatePool (BufferSize); + WriteBuffer = AllocatePool (BufferSize); + ReadBuffer = AllocatePool (BufferSize); + + // Read (and save) buffer at a specific location + Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer); + if (Status != EFI_SUCCESS) { + DiagnosticLog (L"ERROR: Fail to Read Block (1)\n"); + return Status; + } + + // Write buffer at the same location + GenerateRandomBuffer (WriteBuffer,BufferSize); + Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,WriteBuffer); + if (Status != EFI_SUCCESS) { + DiagnosticLog (L"ERROR: Fail to Write Block (1)\n"); + return Status; + } + + // Read the buffer at the same location + Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer); + if (Status != EFI_SUCCESS) { + DiagnosticLog (L"ERROR: Fail to Read Block (2)\n"); + return Status; + } + + // Check that is conform + if (!CompareBuffer (ReadBuffer,WriteBuffer,BufferSize)) { + DiagnosticLog (L"ERROR: Fail to Read/Write Block (1)\n"); + return EFI_INVALID_PARAMETER; + } + + // Restore content at the original location + Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer); + if (Status != EFI_SUCCESS) { + DiagnosticLog (L"ERROR: Fail to Write Block (2)\n"); + return Status; + } + + // Read the restored content + Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer); + if (Status != EFI_SUCCESS) { + DiagnosticLog (L"ERROR: Fail to Read Block (3)\n"); + return Status; + } + + // Check the content is correct + if (!CompareBuffer (ReadBuffer,BackBuffer,BufferSize)) { + DiagnosticLog (L"ERROR: Fail to Read/Write Block (2)\n"); + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +MmcDriverDiagnosticsRunDiagnostics ( + IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, + IN CHAR8 *Language, + OUT EFI_GUID **ErrorType, + OUT UINTN *BufferSize, + OUT CHAR16 **Buffer + ) +{ + LIST_ENTRY *CurrentLink; + MMC_HOST_INSTANCE *MmcHostInstance; + EFI_STATUS Status; + + if ((Language == NULL) || + (ErrorType == NULL) || + (Buffer == NULL) || + (ControllerHandle == NULL) || + (BufferSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // Check Language is supported (i.e. is "en-*" - only English is supported) + if (AsciiStrnCmp (Language, "en", 2) != 0) { + return EFI_UNSUPPORTED; + } + + Status = EFI_SUCCESS; + *ErrorType = NULL; + *BufferSize = DIAGNOSTIC_LOGBUFFER_MAXCHAR; + *Buffer = DiagnosticInitLog (DIAGNOSTIC_LOGBUFFER_MAXCHAR); + + DiagnosticLog (L"MMC Driver Diagnostics\n"); + + // Find the MMC Host instance on which we have been asked to run diagnostics + MmcHostInstance = NULL; + CurrentLink = mMmcHostPool.ForwardLink; + while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) { + MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink); + ASSERT(MmcHostInstance != NULL); + if (MmcHostInstance->MmcHandle == ControllerHandle) { + break; + } + CurrentLink = CurrentLink->ForwardLink; + } + + // If we didn't find the controller, return EFI_UNSUPPORTED + if ((MmcHostInstance == NULL) + || (MmcHostInstance->MmcHandle != ControllerHandle)) { + return EFI_UNSUPPORTED; + } + + // LBA=1 Size=BlockSize + DiagnosticLog (L"MMC Driver Diagnostics - Test: First Block\n"); + Status = MmcReadWriteDataTest (MmcHostInstance, 1, MmcHostInstance->BlockIo.Media->BlockSize); + + // LBA=2 Size=BlockSize + DiagnosticLog (L"MMC Driver Diagnostics - Test: Second Block\n"); + Status = MmcReadWriteDataTest (MmcHostInstance, 2, MmcHostInstance->BlockIo.Media->BlockSize); + + // LBA=10 Size=BlockSize + DiagnosticLog (L"MMC Driver Diagnostics - Test: Any Block\n"); + Status = MmcReadWriteDataTest (MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock >> 1, MmcHostInstance->BlockIo.Media->BlockSize); + + // LBA=LastBlock Size=BlockSize + DiagnosticLog (L"MMC Driver Diagnostics - Test: Last Block\n"); + Status = MmcReadWriteDataTest (MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock, MmcHostInstance->BlockIo.Media->BlockSize); + + // LBA=1 Size=2*BlockSize + DiagnosticLog (L"MMC Driver Diagnostics - Test: First Block / 2 BlockSSize\n"); + Status = MmcReadWriteDataTest (MmcHostInstance, 1, 2 * MmcHostInstance->BlockIo.Media->BlockSize); + + return Status; +} + +// +// EFI Driver Diagnostics 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2 = { + (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) MmcDriverDiagnosticsRunDiagnostics, + "en" +}; diff --git a/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/Mmc.c b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/Mmc.c new file mode 100644 index 000000000000..d90cf3018251 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/Mmc.c @@ -0,0 +1,458 @@ +/** @file + * + * Main file of the MMC Dxe driver. The driver entrypoint is defined into this file. + * + * Copyright (c) 2011-2013, ARM Limited. All rights reserved. + * + * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + **/ + +#include + +#include +#include +#include +#include +#include + +#include "Mmc.h" + +EFI_BLOCK_IO_MEDIA mMmcMediaTemplate = { + SIGNATURE_32('m','m','c','o'), // MediaId + TRUE, // RemovableMedia + FALSE, // MediaPresent + FALSE, // LogicalPartition + FALSE, // ReadOnly + FALSE, // WriteCaching + 512, // BlockSize + 4, // IoAlign + 0, // Pad + 0 // LastBlock +}; + +// +// This device structure is serviced as a header. +// Its next field points to the first root bridge device node. +// +LIST_ENTRY mMmcHostPool; + +/** + Event triggered by the timer to check if any cards have been removed + or if new ones have been plugged in +**/ + +EFI_EVENT gCheckCardsEvent; + +/** + Initialize the MMC Host Pool to support multiple MMC devices +**/ +VOID +InitializeMmcHostPool ( + VOID + ) +{ + InitializeListHead (&mMmcHostPool); +} + +/** + Insert a new Mmc Host controller to the pool +**/ +VOID +InsertMmcHost ( + IN MMC_HOST_INSTANCE *MmcHostInstance + ) +{ + InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link)); +} + +/* + Remove a new Mmc Host controller to the pool +*/ +VOID +RemoveMmcHost ( + IN MMC_HOST_INSTANCE *MmcHostInstance + ) +{ + RemoveEntryList (&(MmcHostInstance->Link)); +} + +MMC_HOST_INSTANCE* CreateMmcHostInstance ( + IN EFI_MMC_HOST_PROTOCOL* MmcHost + ) +{ + EFI_STATUS Status; + MMC_HOST_INSTANCE* MmcHostInstance; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE)); + if (MmcHostInstance == NULL) { + return NULL; + } + + MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE; + + MmcHostInstance->State = MmcHwInitializationState; + + MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate); + if (MmcHostInstance->BlockIo.Media == NULL) { + goto FREE_INSTANCE; + } + + MmcHostInstance->BlockIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION; + MmcHostInstance->BlockIo.Reset = MmcReset; + MmcHostInstance->BlockIo.ReadBlocks = MmcReadBlocks; + MmcHostInstance->BlockIo.WriteBlocks = MmcWriteBlocks; + MmcHostInstance->BlockIo.FlushBlocks = MmcFlushBlocks; + + MmcHostInstance->MmcHost = MmcHost; + + // Create DevicePath for the new MMC Host + Status = MmcHost->BuildDevicePath (MmcHost, &NewDevicePathNode); + if (EFI_ERROR (Status)) { + goto FREE_MEDIA; + } + + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); + if (DevicePath == NULL) { + goto FREE_MEDIA; + } + + SetDevicePathEndNode (DevicePath); + MmcHostInstance->DevicePath = AppendDevicePathNode (DevicePath, NewDevicePathNode); + + // Publish BlockIO protocol interface + Status = gBS->InstallMultipleProtocolInterfaces ( + &MmcHostInstance->MmcHandle, + &gEfiBlockIoProtocolGuid,&MmcHostInstance->BlockIo, + &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath, + NULL + ); + if (EFI_ERROR(Status)) { + goto FREE_DEVICE_PATH; + } + + return MmcHostInstance; + +FREE_DEVICE_PATH: + FreePool(DevicePath); + +FREE_MEDIA: + FreePool(MmcHostInstance->BlockIo.Media); + +FREE_INSTANCE: + FreePool(MmcHostInstance); + + return NULL; +} + +EFI_STATUS DestroyMmcHostInstance ( + IN MMC_HOST_INSTANCE* MmcHostInstance + ) +{ + EFI_STATUS Status; + + // Uninstall Protocol Interfaces + Status = gBS->UninstallMultipleProtocolInterfaces ( + MmcHostInstance->MmcHandle, + &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo), + &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // Free Memory allocated for the instance + if (MmcHostInstance->BlockIo.Media) { + FreePool(MmcHostInstance->BlockIo.Media); + } + if (MmcHostInstance->CardInfo.ECSDData) { + FreePages (MmcHostInstance->CardInfo.ECSDData, EFI_SIZE_TO_PAGES (sizeof (ECSD))); + } + FreePool (MmcHostInstance); + + return Status; +} + +/** + This function checks if the controller implement the Mmc Host and the Device Path Protocols +**/ +EFI_STATUS +EFIAPI +MmcDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_MMC_HOST_PROTOCOL *MmcHost; + EFI_DEV_PATH_PTR Node; + + // + // Check RemainingDevicePath validation + // + if (RemainingDevicePath != NULL) { + // + // Check if RemainingDevicePath is the End of Device Path Node, + // if yes, go on checking other conditions + // + if (!IsDevicePathEnd (RemainingDevicePath)) { + // + // If RemainingDevicePath isn't the End of Device Path Node, + // check its validation + // + Node.DevPath = RemainingDevicePath; + if (Node.DevPath->Type != HARDWARE_DEVICE_PATH || + Node.DevPath->SubType != HW_VENDOR_DP || + DevicePathNodeLength(Node.DevPath) != sizeof(VENDOR_DEVICE_PATH)) { + return EFI_UNSUPPORTED; + } + } + } + + // + // Check if Mmc Host protocol is installed by platform + // + Status = gBS->OpenProtocol ( + Controller, + &gRaspberryPiMmcHostProtocolGuid, + (VOID **) &MmcHost, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Close the Mmc Host used to perform the supported test + // + gBS->CloseProtocol ( + Controller, + &gRaspberryPiMmcHostProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; +} + +/** + +**/ +EFI_STATUS +EFIAPI +MmcDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + MMC_HOST_INSTANCE *MmcHostInstance; + EFI_MMC_HOST_PROTOCOL *MmcHost; + + // + // Check RemainingDevicePath validation + // + if (RemainingDevicePath != NULL) { + // + // Check if RemainingDevicePath is the End of Device Path Node, + // if yes, return EFI_SUCCESS + // + if (IsDevicePathEnd (RemainingDevicePath)) { + return EFI_SUCCESS; + } + } + + // + // Get the Mmc Host protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gRaspberryPiMmcHostProtocolGuid, + (VOID **) &MmcHost, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + return Status; + } + + MmcHostInstance = CreateMmcHostInstance(MmcHost); + if (MmcHostInstance != NULL) { + // Add the handle to the pool + InsertMmcHost (MmcHostInstance); + + MmcHostInstance->Initialized = FALSE; + + // Detect card presence now + CheckCardsCallback (NULL, NULL); + } + + return EFI_SUCCESS; +} + +/** + +**/ +EFI_STATUS +EFIAPI +MmcDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + LIST_ENTRY *CurrentLink; + MMC_HOST_INSTANCE *MmcHostInstance; + + MMC_TRACE("MmcDriverBindingStop()"); + + // For each MMC instance + CurrentLink = mMmcHostPool.ForwardLink; + while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) { + MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink); + ASSERT(MmcHostInstance != NULL); + + // Close gRaspberryPiMmcHostProtocolGuid + Status = gBS->CloseProtocol ( + Controller, + &gRaspberryPiMmcHostProtocolGuid,(VOID **) &MmcHostInstance->MmcHost, + This->DriverBindingHandle + ); + + // Remove MMC Host Instance from the pool + RemoveMmcHost (MmcHostInstance); + + // Destroy MmcHostInstance + DestroyMmcHostInstance (MmcHostInstance); + } + + return Status; +} + +VOID +EFIAPI +CheckCardsCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + LIST_ENTRY *CurrentLink; + MMC_HOST_INSTANCE *MmcHostInstance; + EFI_STATUS Status; + + CurrentLink = mMmcHostPool.ForwardLink; + while (CurrentLink != NULL && CurrentLink != &mMmcHostPool) { + MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink); + ASSERT(MmcHostInstance != NULL); + + if (MmcHostInstance->MmcHost->IsCardPresent (MmcHostInstance->MmcHost) == !MmcHostInstance->Initialized) { + MmcHostInstance->State = MmcHwInitializationState; + MmcHostInstance->BlockIo.Media->MediaPresent = !MmcHostInstance->Initialized; + MmcHostInstance->Initialized = !MmcHostInstance->Initialized; + + if (MmcHostInstance->BlockIo.Media->MediaPresent) { + InitializeMmcDevice (MmcHostInstance); + } + + Status = gBS->ReinstallProtocolInterface ( + (MmcHostInstance->MmcHandle), + &gEfiBlockIoProtocolGuid, + &(MmcHostInstance->BlockIo), + &(MmcHostInstance->BlockIo) + ); + + if (EFI_ERROR(Status)) { + Print(L"MMC Card: Error reinstalling BlockIo interface\n"); + } + } + + CurrentLink = CurrentLink->ForwardLink; + } +} + + +EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = { + MmcDriverBindingSupported, + MmcDriverBindingStart, + MmcDriverBindingStop, + 0xa, + NULL, + NULL +}; + +/** + +**/ +EFI_STATUS +EFIAPI +MmcDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Initializes MMC Host pool + // + InitializeMmcHostPool (); + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gMmcDriverBinding, + ImageHandle, + &gMmcComponentName, + &gMmcComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + // Install driver diagnostics + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiDriverDiagnostics2ProtocolGuid,&gMmcDriverDiagnostics2, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // Use a timer to detect if a card has been plugged in or removed + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL | EVT_TIMER, + TPL_CALLBACK, + CheckCardsCallback, + NULL, + &gCheckCardsEvent); + ASSERT_EFI_ERROR (Status); + + Status = gBS->SetTimer( + gCheckCardsEvent, + TimerPeriodic, + (UINT64)(10*1000*200)); // 200 ms + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/Mmc.h b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/Mmc.h new file mode 100644 index 000000000000..a18f4a82d903 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/Mmc.h @@ -0,0 +1,533 @@ +/** @file + * + * Main Header file for the MMC DXE driver + * + * Copyright (c) 2011-2015, ARM Limited. All rights reserved. + * + * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + **/ + +#ifndef __MMC_H +#define __MMC_H + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#define MMC_TRACE(txt) DEBUG((DEBUG_BLKIO, "MMC: " txt "\n")) + +#define MMC_IOBLOCKS_READ 0 +#define MMC_IOBLOCKS_WRITE 1 + +#define MMC_OCR_POWERUP 0x80000000 + +#define MMC_OCR_ACCESS_MASK 0x3 /* bit[30-29] */ +#define MMC_OCR_ACCESS_BYTE 0x1 /* bit[29] */ +#define MMC_OCR_ACCESS_SECTOR 0x2 /* bit[30] */ + +#define MMC_CSD_GET_CCC(Response) (Response[2] >> 20) +#define MMC_CSD_GET_TRANSPEED(Response) (Response[3] & 0xFF) +#define MMC_CSD_GET_READBLLEN(Response) ((Response[2] >> 16) & 0xF) +#define MMC_CSD_GET_WRITEBLLEN(Response) ((Response[0] >> 22) & 0xF) +#define MMC_CSD_GET_FILEFORMAT(Response) ((Response[0] >> 10) & 0x3) +#define MMC_CSD_GET_FILEFORMATGRP(Response) ((Response[0] >> 15) & 0x1) +#define MMC_CSD_GET_DEVICESIZE(csd) (((Response[1] >> 30) & 0x3) | ((Response[2] & 0x3FF) << 2)) +#define HC_MMC_CSD_GET_DEVICESIZE(Response) ((Response[1] >> 16) | ((Response[2] & 0x3F) << 16)); +#define MMC_CSD_GET_DEVICESIZEMULT(csd) ((Response[1] >> 15) & 0x7) + +#define MMC_R0_READY_FOR_DATA (1 << 8) + +#define MMC_R0_CURRENTSTATE(Response) ((Response[0] >> 9) & 0xF) + +#define MMC_R0_STATE_IDLE 0 +#define MMC_R0_STATE_READY 1 +#define MMC_R0_STATE_IDENT 2 +#define MMC_R0_STATE_STDBY 3 +#define MMC_R0_STATE_TRAN 4 +#define MMC_R0_STATE_DATA 5 +#define MMC_R0_STATE_RECV 6 +#define MMC_R0_STATE_PROG 7 +#define MMC_R0_STATE_DIS 8 + + +#define EMMC_CMD6_ARG_ACCESS(x) (((x) & 0x3) << 24) +#define EMMC_CMD6_ARG_INDEX(x) (((x) & 0xFF) << 16) +#define EMMC_CMD6_ARG_VALUE(x) (((x) & 0xFF) << 8) +#define EMMC_CMD6_ARG_CMD_SET(x) (((x) & 0x7) << 0) + +#define SWITCH_CMD_DATA_LENGTH 64 +#define SD_HIGH_SPEED_SUPPORTED 0x200 +#define SD_DEFAULT_SPEED 25000000 +#define SD_HIGH_SPEED 50000000 +#define SWITCH_CMD_SUCCESS_MASK 0xf + +#define BUSWIDTH_4 4 + +typedef enum { + UNKNOWN_CARD, + MMC_CARD, //MMC card + MMC_CARD_HIGH, //MMC Card with High capacity + EMMC_CARD, //eMMC 4.41 card + SD_CARD, //SD 1.1 card + SD_CARD_2, //SD 2.0 or above standard card + SD_CARD_2_HIGH //SD 2.0 or above high capacity card +} CARD_TYPE; + +typedef struct { + UINT32 Reserved0: 7; // 0 + UINT32 V170_V195: 1; // 1.70V - 1.95V + UINT32 V200_V260: 7; // 2.00V - 2.60V + UINT32 V270_V360: 9; // 2.70V - 3.60V + UINT32 RESERVED_1: 5; // Reserved + UINT32 AccessMode: 2; // 00b (byte mode), 10b (sector mode) + UINT32 PowerUp: 1; // This bit is set to LOW if the card has not finished the power up routine +} OCR; + +typedef struct { + UINT8 SD_SPEC: 4; // SD Memory Card - Spec. Version [59:56] + UINT8 SCR_STRUCTURE: 4; // SCR Structure [63:60] + UINT8 SD_BUS_WIDTHS: 4; // DAT Bus widths supported [51:48] + UINT8 DATA_STAT_AFTER_ERASE: 1; // Data Status after erases [55] + UINT8 SD_SECURITY: 3; // CPRM Security Support [54:52] + UINT8 EX_SECURITY_1: 1; // Extended Security Support [43] + UINT8 SD_SPEC4: 1; // Spec. Version 4.00 or higher [42] + UINT8 RESERVED_1: 2; // Reserved [41:40] + UINT8 SD_SPEC3: 1; // Spec. Version 3.00 or higher [47] + UINT8 EX_SECURITY_2: 3; // Extended Security Support [46:44] + UINT8 CMD_SUPPORT: 4; // Command Support bits [35:32] + UINT8 RESERVED_2: 4; // Reserved [39:36] + UINT32 RESERVED_3; // Manufacturer Usage [31:0] +} SCR; + +typedef struct { + UINT32 NOT_USED; // 1 [0:0] + UINT32 CRC; // CRC7 checksum [7:1] + + UINT32 MDT; // Manufacturing date [19:8] + UINT32 RESERVED_1; // Reserved [23:20] + UINT32 PSN; // Product serial number [55:24] + UINT8 PRV; // Product revision [63:56] + UINT8 PNM[5]; // Product name [64:103] + UINT16 OID; // OEM/Application ID [119:104] + UINT8 MID; // Manufacturer ID [127:120] +} CID; + +typedef struct { + UINT8 NOT_USED: 1; // Not used, always 1 [0:0] + UINT8 CRC: 7; // CRC [7:1] + + UINT8 RESERVED_1: 2; // Reserved [9:8] + UINT8 FILE_FORMAT: 2; // File format [11:10] + UINT8 TMP_WRITE_PROTECT: 1; // Temporary write protection [12:12] + UINT8 PERM_WRITE_PROTECT: 1; // Permanent write protection [13:13] + UINT8 COPY: 1; // Copy flag (OTP) [14:14] + UINT8 FILE_FORMAT_GRP: 1; // File format group [15:15] + + UINT16 RESERVED_2: 5; // Reserved [20:16] + UINT16 WRITE_BL_PARTIAL: 1; // Partial blocks for write allowed [21:21] + UINT16 WRITE_BL_LEN: 4; // Max. write data block length [25:22] + UINT16 R2W_FACTOR: 3; // Write speed factor [28:26] + UINT16 RESERVED_3: 2; // Reserved [30:29] + UINT16 WP_GRP_ENABLE: 1; // Write protect group enable [31:31] + + UINT32 WP_GRP_SIZE: 7; // Write protect group size [38:32] + UINT32 SECTOR_SIZE: 7; // Erase sector size [45:39] + UINT32 ERASE_BLK_EN: 1; // Erase single block enable [46:46] + UINT32 C_SIZE_MULT: 3; // Device size multiplier [49:47] + UINT32 VDD_W_CURR_MAX: 3; // Max. write current @ VDD max [52:50] + UINT32 VDD_W_CURR_MIN: 3; // Max. write current @ VDD min [55:53] + UINT32 VDD_R_CURR_MAX: 3; // Max. read current @ VDD max [58:56] + UINT32 VDD_R_CURR_MIN: 3; // Max. read current @ VDD min [61:59] + UINT32 C_SIZELow2: 2; // Device size [63:62] + + UINT32 C_SIZEHigh10: 10;// Device size [73:64] + UINT32 RESERVED_4: 2; // Reserved [75:74] + UINT32 DSR_IMP: 1; // DSR implemented [76:76] + UINT32 READ_BLK_MISALIGN: 1; // Read block misalignment [77:77] + UINT32 WRITE_BLK_MISALIGN: 1; // Write block misalignment [78:78] + UINT32 READ_BL_PARTIAL: 1; // Partial blocks for read allowed [79:79] + UINT32 READ_BL_LEN: 4; // Max. read data block length [83:80] + UINT32 CCC: 12;// Card command classes [95:84] + + UINT8 TRAN_SPEED ; // Max. bus clock frequency [103:96] + UINT8 NSAC ; // Data read access-time 2 in CLK cycles (NSAC*100) [111:104] + UINT8 TAAC ; // Data read access-time 1 [119:112] + + UINT8 RESERVED_5: 2; // Reserved [121:120] + UINT8 SPEC_VERS: 4; // System specification version [125:122] + UINT8 CSD_STRUCTURE: 2; // CSD structure [127:126] +} CSD; + +typedef struct { + UINT8 RESERVED_1[16]; // Reserved [15:0] + UINT8 SECURE_REMOVAL_TYPE; // Secure Removal Type [16:16] + UINT8 PRODUCT_STATE_AWARENESS_ENABLEMENT; // Product state awareness enablement [17:17] + UINT8 MAX_PRE_LOADING_DATA_SIZE[4]; // MAX pre loading data size [21:18] + UINT8 PRE_LOADING_DATA_SIZE[4]; // Pre loading data size [25:22] + UINT8 FFU_STATUS; // FFU Status [26:26] + UINT8 RESERVED_2[2]; // Reserved [28:27] + UINT8 MODE_OPERATION_CODES; // Mode operation codes [29:29] + UINT8 MODE_CONFIG; // Mode config [30:30] + UINT8 RESERVED_3; // Reserved [31:31] + UINT8 FLUSH_CACHE; // Flushing of the cache [32:32] + UINT8 CACHE_CTRL; // Control to turn the cache ON/OFF [33:33] + UINT8 POWER_OFF_NOTIFICATION; // Power Off Notification [34:34] + UINT8 PACKED_FAILURE_INDEX; // Packed command failure index [35:35] + UINT8 PACKED_COMMAND_STATUS; // Packed command status [36:36] + UINT8 CONTEXT_CONF[15]; // Context configuration [51:37] + UINT8 EXT_PARTITIONS_ATTRIBUTE[2]; // Extended partitions attribute [53:52] + UINT8 EXCEPTION_EVENTS_STATUS[2]; // Exception events status [55:54] + UINT8 EXCEPTION_EVENTS_CTRL[2]; // Exception events control [57:56] + UINT8 DYNCAP_NEEDED; // Number of addressed group to be released [58:58] + UINT8 CLASS_6_CTRL; // Class 6 commands control [59:59] + UINT8 INI_TIMEOUT_EMU; // 1st initialization after disabling sector size emulation [60:60] + UINT8 DATA_SECTOR_SIZE; // Sector size [61:61] + UINT8 USE_NATIVE_SECTOR; // Sector size emulation [62:62] + UINT8 NATIVE_SECTOR_SIZE; // Native sector size [63:63] + UINT8 VENDOR_SPECIFIC_FIELD[64]; // Vendor specific fields [127:64] + UINT8 RESERVED_4[2]; // Reserved [129:128] + UINT8 PROGRAM_CID_CSD_DDR_SUPPORT; // Program CID/CSD in DDR mode support [130:130] + UINT8 PERIODIC_WAKEUP; // Periodic wake-up [131:131] + UINT8 TCASE_SUPPORT; // Package case temperature is controlled [132:132] + UINT8 PRODUCTION_STATE_AWARENESS; // Production state awareness [133:133] + UINT8 SECTOR_BAD_BLK_MGMNT; // Bad block management mode [134:134] + UINT8 RESERVED_5; // Reserved [135:135] + UINT8 ENH_START_ADDR[4]; // Enhanced user data start address [139:136] + UINT8 ENH_SIZE_MULT[3]; // Enhanced user data area size [142:140] + UINT8 GP_SIZE_MULT[12]; // General purpose partition size [154:143] + UINT8 PARTITION_SETTING_COMPLETED; // Partitioning setting [155:155] + UINT8 PARTITIONS_ATTRIBUTE; // Partitions attribute [156:156] + UINT8 MAX_ENH_SIZE_MULT[3]; // Max enhanced area size [159:157] + UINT8 PARTITIONING_SUPPORT; // Partitioning [160:160] + UINT8 HPI_MGMT; // HPI management [161:161] + UINT8 RST_N_FUNCTION; // H/W reset function [162:162] + UINT8 BKOPS_EN; // Enable background operations handshake [163:163] + UINT8 BKOPS_START; // Manually start background operations [164:164] + UINT8 SANITIZE_START; // Start sanitize operation [165:165] + UINT8 WR_REL_PARAM; // Write reliability parameter register [166:166] + UINT8 WR_REL_SET; // Write reliability setting register [167:167] + UINT8 RPMB_SIZE_MULT; // RPMB size [168:168] + UINT8 FW_CONFIG; // FW configuration [169:169] + UINT8 RESERVED_6; // Reserved [170:170] + UINT8 USER_WP; // User area write protection register [171:171] + UINT8 RESERVED_7; // Reserved [172:172] + UINT8 BOOT_WP; // Boot area write protection register [173:173] + UINT8 BOOT_WP_STATUS; // Boot write protection register [174:174] + UINT8 ERASE_GROUP_DEF; // High-density erase group definition [175:175] + UINT8 RESERVED_8; // Reserved [176:176] + UINT8 BOOT_BUS_CONDITIONS; // Boot bus conditions [177:177] + UINT8 BOOT_CONFIG_PROT; // Boot config protection [178:178] + UINT8 PARTITION_CONFIG; // Partition config [179:179] + UINT8 RESERVED_9; // Reserved [180:180] + UINT8 ERASED_MEM_CONT; // Erased memory content [181:181] + UINT8 RESERVED_10; // Reserved [182:182] + UINT8 BUS_WIDTH; // Bus width mode [183:183] + UINT8 RESERVED_11; // Reserved [184:184] + UINT8 HS_TIMING; // High-speed interface timing [185:185] + UINT8 RESERVED_12; // Reserved [186:186] + UINT8 POWER_CLASS; // Power class [187:187] + UINT8 RESERVED_13; // Reserved [188:188] + UINT8 CMD_SET_REV; // Command set revision [189:189] + UINT8 RESERVED_14; // Reserved [190:190] + UINT8 CMD_SET; // Command set [191:191] + UINT8 EXT_CSD_REV; // Extended CSD revision [192:192] + UINT8 RESERVED_15; // Reserved [193:193] + UINT8 CSD_STRUCTURE; // CSD Structure [194:194] + UINT8 RESERVED_16; // Reserved [195:195] + UINT8 DEVICE_TYPE; // Device type [196:196] + UINT8 DRIVER_STRENGTH; // I/O Driver strength [197:197] + UINT8 OUT_OF_INTERRUPT_TIME; // Out-of-interrupt busy timing [198:198] + UINT8 PARTITION_SWITCH_TIME; // Partition switching timing [199:199] + UINT8 PWR_CL_52_195; // Power class for 52MHz at 1.95V 1 R [200:200] + UINT8 PWR_CL_26_195; // Power class for 26MHz at 1.95V 1 R [201:201] + UINT8 PWR_CL_52_360; // Power class for 52MHz at 3.6V 1 R [202:202] + UINT8 PWR_CL_26_360; // Power class for 26MHz at 3.6V 1 R [203:203] + UINT8 RESERVED_17; // Reserved [204:204] + UINT8 MIN_PERF_R_4_26; // Minimum read performance for 4bit at 26MHz [205:205] + UINT8 MIN_PERF_W_4_26; // Minimum write performance for 4bit at 26MHz [206:206] + UINT8 MIN_PERF_R_8_26_4_52; // Minimum read performance for 8bit at 26MHz, for 4bit at 52MHz [207:207] + UINT8 MIN_PERF_W_8_26_4_52; // Minimum write performance for 8bit at 26MHz, for 4bit at 52MHz [208:208] + UINT8 MIN_PERF_R_8_52; // Minimum read performance for 8bit at 52MHz [209:209] + UINT8 MIN_PERF_W_8_52; // Minimum write performance for 8bit at 52MHz [210:210] + UINT8 RESERVED_18; // Reserved [211:211] + UINT32 SECTOR_COUNT; // Sector count [215:212] + UINT8 SLEEP_NOTIFICATION_TIME; // Sleep notification timout [216:216] + UINT8 S_A_TIMEOUT; // Sleep/awake timeout [217:217] + UINT8 PRODUCTION_STATE_AWARENESS_TIMEOUT; // Production state awareness timeout [218:218] + UINT8 S_C_VCCQ; // Sleep current (VCCQ) [219:219] + UINT8 S_C_VCC; // Sleep current (VCC) [220:220] + UINT8 HC_WP_GRP_SIZE; // High-capacity write protect group size [221:221] + UINT8 REL_WR_SECTOR_C; // Reliable write sector count [222:222] + UINT8 ERASE_TIMEOUT_MULT; // High-capacity erase timeout [223:223] + UINT8 HC_ERASE_GRP_SIZE; // High-capacity erase unit size [224:224] + UINT8 ACC_SIZE; // Access size [225:225] + UINT8 BOOT_SIZE_MULTI; // Boot partition size [226:226] + UINT8 RESERVED_19; // Reserved [227:227] + UINT8 BOOT_INFO; // Boot information [228:228] + UINT8 SECURE_TRIM_MULT; // Secure TRIM Multiplier [229:229] + UINT8 SECURE_ERASE_MULT; // Secure Erase Multiplier [230:230] + UINT8 SECURE_FEATURE_SUPPORT; // Secure Feature Support [231:231] + UINT8 TRIM_MULT; // TRIM Multiplier [232:232] + UINT8 RESERVED_20; // Reserved [233:233] + UINT8 MIN_PREF_DDR_R_8_52; // Minimum read performance for 8bit at 52MHz in DDR mode [234:234] + UINT8 MIN_PREF_DDR_W_8_52; // Minimum write performance for 8bit at 52MHz in DDR mode [235:235] + UINT8 PWR_CL_200_130; // Power class for 200MHz at VCCQ=1.3V, VCC=3.6V [236:236] + UINT8 PWR_CL_200_195; // Power class for 200MHz at VCCQ=1.95V, VCC=3.6V [237:237] + UINT8 PWR_CL_DDR_52_195; // Power class for 52MHz, DDR at 1.95V [238:238] + UINT8 PWR_CL_DDR_52_360; // Power class for 52Mhz, DDR at 3.6V [239:239] + UINT8 RESERVED_21; // Reserved [240:240] + UINT8 INI_TIMEOUT_AP; // 1st initialization time after partitioning [241:241] + UINT8 CORRECTLY_PRG_SECTORS_NUM[4]; // Number of correctly programmed sectors [245:242] + UINT8 BKOPS_STATUS; // Background operations status [246:246] + UINT8 POWER_OFF_LONG_TIME; // Power off notification (long) timeout [247:247] + UINT8 GENERIC_CMD6_TIME; // Generic CMD6 timeout [248:248] + UINT8 CACHE_SIZE[4]; // Cache size [252:249] + UINT8 PWR_CL_DDR_200_360; // Power class for 200MHz, DDR at VCC=3.6V [253:253] + UINT8 FIRMWARE_VERSION[8]; // Firmware version [261:254] + UINT8 DEVICE_VERSION[2]; // Device version [263:262] + UINT8 OPTIMAL_TRIM_UNIT_SIZE; // Optimal trim unit size [264:264] + UINT8 OPTIMAL_WRITE_SIZE; // Optimal write size [265:265] + UINT8 OPTIMAL_READ_SIZE; // Optimal read size [266:266] + UINT8 PRE_EOL_INFO; // Pre EOL information [267:267] + UINT8 DEVICE_LIFE_TIME_EST_TYP_A; // Device life time estimation type A [268:268] + UINT8 DEVICE_LIFE_TIME_EST_TYP_B; // Device life time estimation type B [269:269] + UINT8 VENDOR_PROPRIETARY_HEALTH_REPORT[32]; // Vendor proprietary health report [301:270] + UINT8 NUMBER_OF_FW_SECTORS_CORRECTLY_PROGRAMMED[4]; // Number of FW sectors correctly programmed [305:302] + UINT8 RESERVED_22[181]; // Reserved [486:306] + UINT8 FFU_ARG[4]; // FFU argument [490:487] + UINT8 OPERATION_CODE_TIMEOUT; // Operation codes timeout [491:491] + UINT8 FFU_FEATURES; // FFU features [492:492] + UINT8 SUPPORTED_MODES; // Supported modes [493:493] + UINT8 EXT_SUPPORT; // Extended partitions attribute support [494:494] + UINT8 LARGE_UNIT_SIZE_M1; // Large unit size [495:495] + UINT8 CONTEXT_CAPABILITIES; // Context management capabilities [496:496] + UINT8 TAG_RES_SIZE; // Tag resource size [497:497] + UINT8 TAG_UNIT_SIZE; // Tag unit size [498:498] + UINT8 DATA_TAG_SUPPORT; // Data tag support [499:499] + UINT8 MAX_PACKED_WRITES; // Max packed write commands [500:500] + UINT8 MAX_PACKED_READS; // Max packed read commands [501:501] + UINT8 BKOPS_SUPPORT; // Background operations support [502:502] + UINT8 HPI_FEATURES; // HPI features [503:503] + UINT8 S_CMD_SET; // Supported command sets [504:504] + UINT8 EXT_SECURITY_ERR; // Extended security commands error [505:505] + UINT8 RESERVED_23[6]; // Reserved [511:506] +} ECSD; + +typedef struct { + UINT16 RCA; + CARD_TYPE CardType; + OCR OCRData; + CID CIDData; + CSD CSDData; + ECSD *ECSDData; // MMC V4 extended card specific +} CARD_INFO; + +typedef struct _MMC_HOST_INSTANCE { + UINTN Signature; + LIST_ENTRY Link; + EFI_HANDLE MmcHandle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + MMC_STATE State; + EFI_BLOCK_IO_PROTOCOL BlockIo; + CARD_INFO CardInfo; + EFI_MMC_HOST_PROTOCOL *MmcHost; + + BOOLEAN Initialized; +} MMC_HOST_INSTANCE; + +#define MMC_HOST_INSTANCE_SIGNATURE SIGNATURE_32('m', 'm', 'c', 'h') +#define MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS(a) CR (a, MMC_HOST_INSTANCE, BlockIo, MMC_HOST_INSTANCE_SIGNATURE) +#define MMC_HOST_INSTANCE_FROM_LINK(a) CR (a, MMC_HOST_INSTANCE, Link, MMC_HOST_INSTANCE_SIGNATURE) + + +EFI_STATUS +EFIAPI +MmcGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +MmcGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +extern EFI_COMPONENT_NAME_PROTOCOL gMmcComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gMmcComponentName2; + +extern EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2; + +extern LIST_ENTRY mMmcHostPool; + +/** + Reset the block device. + + This function implements EFI_BLOCK_IO_PROTOCOL.Reset(). + It resets the block device hardware. + ExtendedVerification is ignored in this implementation. + + @param This Indicates a pointer to the calling context. + @param ExtendedVerification Indicates that the driver may perform a more exhaustive + verification operation of the device during reset. + + @retval EFI_SUCCESS The block device was reset. + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be reset. + +**/ +EFI_STATUS +EFIAPI +MmcReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Reads the requested number of blocks from the device. + + This function implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks(). + It reads the requested number of blocks from the device. + All the blocks are read, or an error is returned. + + @param This Indicates a pointer to the calling context. + @param MediaId The media ID that the read request is for. + @param Lba The starting logical block address to read from on the device. + @param BufferSize The size of the Buffer in bytes. + This must be a multiple of the intrinsic block size of the device. + @param Buffer A pointer to the destination buffer for the data. The caller is + responsible for either having implicit or explicit ownership of the buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the read operation. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the buffer is not on proper alignment. + +**/ +EFI_STATUS +EFIAPI +MmcReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + Writes a specified number of blocks to the device. + + This function implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks(). + It writes a specified number of blocks to the device. + All blocks are written, or an error is returned. + + @param This Indicates a pointer to the calling context. + @param MediaId The media ID that the write request is for. + @param Lba The starting logical block address to be written. + @param BufferSize The size of the Buffer in bytes. + This must be a multiple of the intrinsic block size of the device. + @param Buffer Pointer to the source buffer for the data. + + @retval EFI_SUCCESS The data were written correctly to the device. + @retval EFI_WRITE_PROTECTED The device cannot be written to. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the write operation. + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the intrinsic + block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid, + or the buffer is not on proper alignment. + +**/ +EFI_STATUS +EFIAPI +MmcWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +/** + Flushes all modified data to a physical block device. + + @param This Indicates a pointer to the calling context. + + @retval EFI_SUCCESS All outstanding data were written correctly to the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to write data. + @retval EFI_NO_MEDIA There is no media in the device. + +**/ +EFI_STATUS +EFIAPI +MmcFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ); + +EFI_STATUS +MmcNotifyState ( + IN MMC_HOST_INSTANCE *MmcHostInstance, + IN MMC_STATE State + ); + +EFI_STATUS +InitializeMmcDevice ( + IN MMC_HOST_INSTANCE *MmcHost + ); + +VOID +EFIAPI +CheckCardsCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +VOID +PrintCSD ( + IN UINT32* Csd + ); + +VOID +PrintRCA ( + IN UINT32 Rca + ); + +VOID +PrintOCR ( + IN UINT32 Ocr + ); + +VOID +PrintResponseR1 ( + IN UINT32 Response + ); + +VOID +PrintCID ( + IN UINT32* Cid + ); + +#endif diff --git a/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcBlockIo.c b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcBlockIo.c new file mode 100644 index 000000000000..54cdbde95292 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcBlockIo.c @@ -0,0 +1,473 @@ +/** @file + * + * Copyright (c) 2011-2015, ARM Limited. All rights reserved. + * + * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + **/ + +#include + +#include "Mmc.h" + +#define MMCI0_BLOCKLEN 512 +#define MMCI0_TIMEOUT 1000 + +STATIC +EFI_STATUS +R1TranAndReady(UINT32 *Response) +{ + if ((*Response & MMC_R0_READY_FOR_DATA) != 0 && + MMC_R0_CURRENTSTATE(Response) == MMC_R0_STATE_TRAN) { + return EFI_SUCCESS; + } + + return EFI_NOT_READY; +} + +STATIC +EFI_STATUS +ValidateWrittenBlockCount( + IN MMC_HOST_INSTANCE *MmcHostInstance, + IN UINTN Count, + OUT UINTN *TransferredBlocks + ) +{ + UINT32 R1; + UINT8 Data[4]; + EFI_STATUS Status; + UINT32 BlocksWritten; + EFI_MMC_HOST_PROTOCOL *MmcHost = MmcHostInstance->MmcHost; + + if (MmcHostInstance->CardInfo.CardType == MMC_CARD || + MmcHostInstance->CardInfo.CardType == MMC_CARD_HIGH || + MmcHostInstance->CardInfo.CardType == EMMC_CARD) { + /* + * Not on MMC. + */ + return EFI_SUCCESS; + } + + Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, + MmcHostInstance->CardInfo.RCA << 16); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(%u): error: %r\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } + + Status = MmcHost->SendCommand (MmcHost, MMC_ACMD22, 0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(%u): error: %r\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } + + MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, &R1); + Status = R1TranAndReady(&R1); + if (EFI_ERROR (Status)) { + return Status; + } + + // Read Data + Status = MmcHost->ReadBlockData (MmcHost, 0, sizeof(Data), + (VOID *) Data); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(%u): error: %r\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } + + /* + * Big Endian. + */ + BlocksWritten = ((UINT32) Data[0] << 24) | + ((UINT32) Data[1] << 16) | + ((UINT32) Data[2] << 8) | + ((UINT32) Data[3] << 0); + if (BlocksWritten != Count) { + DEBUG ((DEBUG_ERROR, "%a(%u): expected %u != gotten %u\n", + __FUNCTION__, __LINE__, Count, BlocksWritten)); + if (BlocksWritten == 0) { + return EFI_DEVICE_ERROR; + } + } + + *TransferredBlocks = BlocksWritten; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +WaitUntilTran( + IN MMC_HOST_INSTANCE *MmcHostInstance + ) +{ + INTN Timeout; + UINT32 Response[1]; + EFI_STATUS Status = EFI_SUCCESS; + EFI_MMC_HOST_PROTOCOL *MmcHost = MmcHostInstance->MmcHost; + + Timeout = MMCI0_TIMEOUT; + while(Timeout--) { + /* + * We expect CMD13 to timeout while card is programming, + * because the card holds DAT0 low (busy). + */ + Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, + MmcHostInstance->CardInfo.RCA << 16); + if (EFI_ERROR(Status) && Status != EFI_TIMEOUT) { + DEBUG ((DEBUG_ERROR, "%a(%u) CMD13 failed: %r\n", + __FUNCTION__, __LINE__, Status)); + break; + } + + if (Status == EFI_SUCCESS) { + MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response); + Status = R1TranAndReady(Response); + if (!EFI_ERROR(Status)) { + break; + } + } + + gBS->Stall(1000); + } + + if (0 == Timeout) { + DEBUG ((DEBUG_ERROR, "%a(%u) card is busy\n", __FUNCTION__, __LINE__)); + return EFI_NOT_READY; + } + + return Status; +} + +EFI_STATUS +MmcNotifyState ( + IN MMC_HOST_INSTANCE *MmcHostInstance, + IN MMC_STATE State + ) +{ + MmcHostInstance->State = State; + return MmcHostInstance->MmcHost->NotifyState (MmcHostInstance->MmcHost, State); +} + +EFI_STATUS +EFIAPI +MmcReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + MMC_HOST_INSTANCE *MmcHostInstance; + + MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This); + + if (MmcHostInstance->MmcHost == NULL) { + // Nothing to do + return EFI_SUCCESS; + } + + // If a card is not present then clear all media settings + if (!MmcHostInstance->MmcHost->IsCardPresent (MmcHostInstance->MmcHost)) { + MmcHostInstance->BlockIo.Media->MediaPresent = FALSE; + MmcHostInstance->BlockIo.Media->LastBlock = 0; + MmcHostInstance->BlockIo.Media->BlockSize = 512; // Should be zero but there is a bug in DiskIo + MmcHostInstance->BlockIo.Media->ReadOnly = FALSE; + + // Indicate that the driver requires initialization + MmcHostInstance->State = MmcHwInitializationState; + + return EFI_SUCCESS; + } + + // Implement me. Either send a CMD0 (could not work for some MMC host) or just turn off/turn + // on power and restart Identification mode + return EFI_SUCCESS; +} + +EFI_STATUS +MmcDetectCard ( + EFI_MMC_HOST_PROTOCOL *MmcHost + ) +{ + if (!MmcHost->IsCardPresent (MmcHost)) { + return EFI_NO_MEDIA; + } else { + return EFI_SUCCESS; + } +} + +EFI_STATUS +MmcStopTransmission ( + EFI_MMC_HOST_PROTOCOL *MmcHost + ) +{ + EFI_STATUS Status; + UINT32 Response[4]; + // Command 12 - Stop transmission (ends read or write) + // Normally only needed for streaming transfers or after error. + Status = MmcHost->SendCommand (MmcHost, MMC_CMD12, 0); + if (!EFI_ERROR (Status)) { + MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1b, Response); + } + return Status; +} + +STATIC +EFI_STATUS +MmcTransferBlock ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINTN Cmd, + IN UINTN Transfer, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer, + OUT UINTN *TransferredSize + ) +{ + EFI_STATUS Status; + MMC_HOST_INSTANCE *MmcHostInstance; + EFI_MMC_HOST_PROTOCOL *MmcHost; + UINTN CmdArg; + + MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This); + MmcHost = MmcHostInstance->MmcHost; + + //Set command argument based on the card access mode (Byte mode or Block mode) + if ((MmcHostInstance->CardInfo.OCRData.AccessMode & MMC_OCR_ACCESS_MASK) == + MMC_OCR_ACCESS_SECTOR) { + CmdArg = Lba; + } else { + CmdArg = Lba * This->Media->BlockSize; + } + + Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(MMC_CMD%d): Error %r\n", __func__, + MMC_INDX(Cmd), Status)); + return Status; + } + + if (Transfer == MMC_IOBLOCKS_READ) { + Status = MmcHost->ReadBlockData (MmcHost, Lba, BufferSize, Buffer); + } else { + Status = MmcHost->WriteBlockData (MmcHost, Lba, BufferSize, Buffer); + if (!EFI_ERROR (Status)) { + Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a() : Error MmcProgrammingState\n", __func__)); + return Status; + } + } + } + + if (EFI_ERROR (Status) || + BufferSize > This->Media->BlockSize) { + /* + * CMD12 needs to be set for multiblock (to transition from + * RECV to PROG) or for errors. + */ + EFI_STATUS Status2 = MmcStopTransmission (MmcHost); + if (EFI_ERROR (Status2)) { + DEBUG ((DEBUG_ERROR, "MmcIoBlocks() : CMD12 error on Status %r: %r\n", + Status, Status2)); + return Status2; + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_BLKIO, "%a(): Error %a Block Data and Status = %r\n", + __func__, Transfer == MMC_IOBLOCKS_READ ? "Read" : "Write", + Status)); + return Status; + } + + ASSERT (Cmd == MMC_CMD25 || Cmd == MMC_CMD18); + } + + // + // For reads, should be already in TRAN. For writes, wait + // until programming finishes. + // + Status = WaitUntilTran(MmcHostInstance); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "WaitUntilTran after write failed\n")); + return Status; + } + + Status = MmcNotifyState (MmcHostInstance, MmcTransferState); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIoBlocks() : Error MmcTransferState\n")); + return Status; + } + + if (Transfer != MMC_IOBLOCKS_READ) { + UINTN BlocksWritten = 0; + + Status = ValidateWrittenBlockCount (MmcHostInstance, + BufferSize / + This->Media->BlockSize, + &BlocksWritten); + *TransferredSize = BlocksWritten * + This->Media->BlockSize; + } else { + *TransferredSize = BufferSize; + } + + return Status; +} + +EFI_STATUS +MmcIoBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINTN Transfer, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINTN Cmd; + MMC_HOST_INSTANCE *MmcHostInstance; + EFI_MMC_HOST_PROTOCOL *MmcHost; + UINTN BytesRemainingToBeTransfered; + UINTN BlockCount; + UINTN ConsumeSize; + + BlockCount = 1; + MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This); + ASSERT (MmcHostInstance != NULL); + MmcHost = MmcHostInstance->MmcHost; + ASSERT (MmcHost); + + if (This->Media->MediaId != MediaId) { + return EFI_MEDIA_CHANGED; + } + + if ((MmcHost == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // Check if a Card is Present + if (!MmcHostInstance->BlockIo.Media->MediaPresent) { + return EFI_NO_MEDIA; + } + + if (PcdGet32(PcdMmcDisableMulti) == 0 && + MMC_HOST_HAS_ISMULTIBLOCK(MmcHost) && + MmcHost->IsMultiBlock(MmcHost)) { + BlockCount = (BufferSize + This->Media->BlockSize - 1) / This->Media->BlockSize; + } + + // All blocks must be within the device + if ((Lba + (BufferSize / This->Media->BlockSize)) > (This->Media->LastBlock + 1)) { + return EFI_INVALID_PARAMETER; + } + + if ((Transfer == MMC_IOBLOCKS_WRITE) && (This->Media->ReadOnly == TRUE)) { + return EFI_WRITE_PROTECTED; + } + + // Reading 0 Byte is valid + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + // The buffer size must be an exact multiple of the block size + if ((BufferSize % This->Media->BlockSize) != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + // Check the alignment + if ((This->Media->IoAlign > 2) && (((UINTN)Buffer & (This->Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + + BytesRemainingToBeTransfered = BufferSize; + while (BytesRemainingToBeTransfered > 0) { + Status = WaitUntilTran(MmcHostInstance); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "WaitUntilTran before IO failed")); + return Status; + } + + if (Transfer == MMC_IOBLOCKS_READ) { + if (BlockCount == 1) { + // Read a single block + Cmd = MMC_CMD17; + } else { + // Read multiple blocks + Cmd = MMC_CMD18; + } + } else { + if (BlockCount == 1) { + // Write a single block + Cmd = MMC_CMD24; + } else { + // Write multiple blocks + Cmd = MMC_CMD25; + } + } + + ConsumeSize = BlockCount * This->Media->BlockSize; + if (BytesRemainingToBeTransfered < ConsumeSize) { + ConsumeSize = BytesRemainingToBeTransfered; + } + + Status = MmcTransferBlock (This, Cmd, Transfer, MediaId, Lba, ConsumeSize, Buffer, &ConsumeSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(): Failed to transfer block and Status:%r\n", __func__, Status)); + return Status; + } + + BytesRemainingToBeTransfered -= ConsumeSize; + if (BytesRemainingToBeTransfered > 0) { + Lba += BlockCount; + Buffer = (UINT8 *)Buffer + ConsumeSize; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +MmcReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + return MmcIoBlocks (This, MMC_IOBLOCKS_READ, MediaId, Lba, BufferSize, Buffer); +} + +EFI_STATUS +EFIAPI +MmcWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + return MmcIoBlocks (This, MMC_IOBLOCKS_WRITE, MediaId, Lba, BufferSize, Buffer); +} + +EFI_STATUS +EFIAPI +MmcFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + return EFI_SUCCESS; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcDebug.c b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcDebug.c new file mode 100644 index 000000000000..ea53700caaf8 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcDebug.c @@ -0,0 +1,169 @@ +/** @file + * + * Copyright (c) 2011-2013, ARM Limited. All rights reserved. + * + * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + **/ + +#include "Mmc.h" + +#if !defined(MDEPKG_NDEBUG) +CONST CHAR8* mStrUnit[] = { "100kbit/s", "1Mbit/s", "10Mbit/s", "100MBit/s", + "Unknown", "Unknown", "Unknown", "Unknown" }; +CONST CHAR8* mStrValue[] = { "1.0", "1.2", "1.3", "1.5", "2.0", "2.5", + "3.0", "3.5", "4.0", "4.5", "5.0", "5.5", + "6.0", "7.0", "8.0" }; +#endif + +VOID +PrintCID ( + IN UINT32* Cid + ) +{ + DEBUG ((DEBUG_ERROR, "- PrintCID\n")); + DEBUG ((DEBUG_ERROR, "\t- Manufacturing date: %d/%d\n", (Cid[0] >> 8) & 0xF, (Cid[0] >> 12) & 0xFF)); + DEBUG ((DEBUG_ERROR, "\t- Product serial number: 0x%X%X\n", Cid[1] & 0xFFFFFF, (Cid[0] >> 24) & 0xFF)); + DEBUG ((DEBUG_ERROR, "\t- Product revision: %d\n", Cid[1] >> 24)); + //DEBUG ((DEBUG_ERROR, "\t- Product name: %s\n", (char*)(Cid + 2))); + DEBUG ((DEBUG_ERROR, "\t- OEM ID: %c%c\n", (Cid[3] >> 8) & 0xFF, (Cid[3] >> 16) & 0xFF)); +} + + +VOID +PrintCSD ( + IN UINT32* Csd + ) +{ + UINTN Value; + + if (((Csd[2] >> 30) & 0x3) == 0) { + DEBUG ((DEBUG_ERROR, "- PrintCSD Version 1.01-1.10/Version 2.00/Standard Capacity\n")); + } else if (((Csd[2] >> 30) & 0x3) == 1) { + DEBUG ((DEBUG_ERROR, "- PrintCSD Version 2.00/High Capacity\n")); + } else { + DEBUG ((DEBUG_ERROR, "- PrintCSD Version Higher than v3.3\n")); + } + + DEBUG ((DEBUG_ERROR, "\t- Supported card command class: 0x%X\n", MMC_CSD_GET_CCC (Csd))); + DEBUG ((DEBUG_ERROR, "\t- Max Speed: %a * %a\n",mStrValue[(MMC_CSD_GET_TRANSPEED (Csd) >> 3) & 0xF],mStrUnit[MMC_CSD_GET_TRANSPEED (Csd) & 7])); + DEBUG ((DEBUG_ERROR, "\t- Maximum Read Data Block: %d\n",2 << (MMC_CSD_GET_READBLLEN (Csd)-1))); + DEBUG ((DEBUG_ERROR, "\t- Maximum Write Data Block: %d\n",2 << (MMC_CSD_GET_WRITEBLLEN (Csd)-1))); + + if (!MMC_CSD_GET_FILEFORMATGRP (Csd)) { + Value = MMC_CSD_GET_FILEFORMAT (Csd); + if (Value == 0) { + DEBUG ((DEBUG_ERROR, "\t- Format (0): Hard disk-like file system with partition table\n")); + } else if (Value == 1) { + DEBUG ((DEBUG_ERROR, "\t- Format (1): DOS FAT (floppy-like) with boot sector only (no partition table)\n")); + } else if (Value == 2) { + DEBUG ((DEBUG_ERROR, "\t- Format (2): Universal File Format\n")); + } else { + DEBUG ((DEBUG_ERROR, "\t- Format (3): Others/Unknown\n")); + } + } else { + DEBUG ((DEBUG_ERROR, "\t- Format: Reserved\n")); + } +} + +VOID +PrintRCA ( + IN UINT32 Rca + ) +{ + DEBUG ((DEBUG_ERROR, "- PrintRCA: 0x%X\n", Rca)); + DEBUG ((DEBUG_ERROR, "\t- Status: 0x%X\n", Rca & 0xFFFF)); + DEBUG ((DEBUG_ERROR, "\t- RCA: 0x%X\n", (Rca >> 16) & 0xFFFF)); +} + +VOID +PrintOCR ( + IN UINT32 Ocr + ) +{ + UINTN MinV; + UINTN MaxV; + UINTN Volts; + UINTN Loop; + + MinV = 36; // 3.6 + MaxV = 20; // 2.0 + Volts = 20; // 2.0 + + // The MMC register bits [23:8] indicate the working range of the card + for (Loop = 8; Loop < 24; Loop++) { + if (Ocr & (1 << Loop)) { + if (MinV > Volts) { + MinV = Volts; + } + if (MaxV < Volts) { + MaxV = Volts + 1; + } + } + Volts++; + } + + DEBUG ((DEBUG_ERROR, "- PrintOCR Ocr (0x%X)\n",Ocr)); + DEBUG ((DEBUG_ERROR, "\t- Card operating voltage: %d.%d to %d.%d\n", MinV/10, MinV % 10, MaxV/10, MaxV % 10)); + if (((Ocr >> 29) & 3) == 0) { + DEBUG ((DEBUG_ERROR, "\t- AccessMode: Byte Mode\n")); + } else { + DEBUG ((DEBUG_ERROR, "\t- AccessMode: Block Mode (0x%X)\n", ((Ocr >> 29) & 3))); + } + + if (Ocr & MMC_OCR_POWERUP) { + DEBUG ((DEBUG_ERROR, "\t- PowerUp\n")); + } else { + DEBUG ((DEBUG_ERROR, "\t- Voltage Not Supported\n")); + } +} + +VOID +PrintResponseR1 ( + IN UINT32 Response + ) +{ + DEBUG ((DEBUG_INFO, "Response: 0x%X\n", Response)); + if (Response & MMC_R0_READY_FOR_DATA) { + DEBUG ((DEBUG_INFO, "\t- READY_FOR_DATA\n")); + } + + switch ((Response >> 9) & 0xF) { + case 0: + DEBUG ((DEBUG_INFO, "\t- State: Idle\n")); + break; + case 1: + DEBUG ((DEBUG_INFO, "\t- State: Ready\n")); + break; + case 2: + DEBUG ((DEBUG_INFO, "\t- State: Ident\n")); + break; + case 3: + DEBUG ((DEBUG_INFO, "\t- State: StandBy\n")); + break; + case 4: + DEBUG ((DEBUG_INFO, "\t- State: Tran\n")); + break; + case 5: + DEBUG ((DEBUG_INFO, "\t- State: Data\n")); + break; + case 6: + DEBUG ((DEBUG_INFO, "\t- State: Rcv\n")); + break; + case 7: + DEBUG ((DEBUG_INFO, "\t- State: Prg\n")); + break; + case 8: + DEBUG ((DEBUG_INFO, "\t- State: Dis\n")); + break; + default: + DEBUG ((DEBUG_INFO, "\t- State: Reserved\n")); + break; + } +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcDxe.inf new file mode 100644 index 000000000000..fd91f47aeaf0 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcDxe.inf @@ -0,0 +1,58 @@ +#/** @file +# +# Copyright (c) 2018, Andrei Warkentin +# Copyright (c) 2011-2015, ARM Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PiMmcDxe + FILE_GUID = b6f44cc0-9e45-11df-be21-0002a5f5f51b + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = MmcDxeInitialize + +[Sources.common] + ComponentName.c + Mmc.c + MmcBlockIo.c + MmcIdentification.c + MmcDebug.c + Diagnostics.c + +[Packages] + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + UefiLib + UefiDriverEntryPoint + BaseMemoryLib + +[Protocols] + gEfiDiskIoProtocolGuid + gEfiBlockIoProtocolGuid + gEfiDevicePathProtocolGuid + gEfiDriverDiagnostics2ProtocolGuid + gRaspberryPiMmcHostProtocolGuid + +[Pcd] + gRaspberryPiTokenSpaceGuid.PcdMmcForce1Bit + gRaspberryPiTokenSpaceGuid.PcdMmcForceDefaultSpeed + gRaspberryPiTokenSpaceGuid.PcdMmcSdDefaultSpeedMHz + gRaspberryPiTokenSpaceGuid.PcdMmcSdHighSpeedMHz + gRaspberryPiTokenSpaceGuid.PcdMmcDisableMulti + +[Depex] + TRUE diff --git a/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcIdentification.c b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcIdentification.c new file mode 100644 index 000000000000..ef819fb753c6 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcIdentification.c @@ -0,0 +1,993 @@ +/** @file + * + * Copyright (c) 2011-2015, ARM Limited. All rights reserved. + * + * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + **/ + +#include +#include +#include + +#include "Mmc.h" + +typedef union { + UINT32 Raw; + OCR Ocr; +} OCR_RESPONSE; + +#define MAX_RETRY_COUNT 1000 +#define CMD_RETRY_COUNT 20 +#define RCA_SHIFT_OFFSET 16 +#define EMMC_CARD_SIZE 512 +#define EMMC_ECSD_SIZE_OFFSET 53 + +#define EXTCSD_BUS_WIDTH 183 +#define EXTCSD_HS_TIMING 185 + +#define EMMC_TIMING_BACKWARD 0 +#define EMMC_TIMING_HS 1 +#define EMMC_TIMING_HS200 2 +#define EMMC_TIMING_HS400 3 + +#define EMMC_BUS_WIDTH_1BIT 0 +#define EMMC_BUS_WIDTH_4BIT 1 +#define EMMC_BUS_WIDTH_8BIT 2 +#define EMMC_BUS_WIDTH_DDR_4BIT 5 +#define EMMC_BUS_WIDTH_DDR_8BIT 6 + +#define EMMC_SWITCH_ERROR (1 << 7) + +#define SD_BUS_WIDTH_1BIT (1 << 0) +#define SD_BUS_WIDTH_4BIT (1 << 2) + +#define SD_CCC_SWITCH (1 << 10) + +#define DEVICE_STATE(x) (((x) >> 9) & 0xf) +typedef enum _EMMC_DEVICE_STATE { + EMMC_IDLE_STATE = 0, + EMMC_READY_STATE, + EMMC_IDENT_STATE, + EMMC_STBY_STATE, + EMMC_TRAN_STATE, + EMMC_DATA_STATE, + EMMC_RCV_STATE, + EMMC_PRG_STATE, + EMMC_DIS_STATE, + EMMC_BTST_STATE, + EMMC_SLP_STATE +} EMMC_DEVICE_STATE; + +UINT32 mEmmcRcaCount = 0; + +STATIC +EFI_STATUS +EFIAPI +EmmcGetDeviceState ( + IN MMC_HOST_INSTANCE *MmcHostInstance, + OUT EMMC_DEVICE_STATE *State + ) +{ + EFI_MMC_HOST_PROTOCOL *Host; + EFI_STATUS Status; + UINT32 Data, RCA; + + if (State == NULL) { + return EFI_INVALID_PARAMETER; + } + + Host = MmcHostInstance->MmcHost; + RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET; + Status = Host->SendCommand (Host, MMC_CMD13, RCA); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcGetDeviceState(): Failed to get card status, Status=%r.\n", Status)); + return Status; + } + Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R1, &Data); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcGetDeviceState(): Failed to get response of CMD13, Status=%r.\n", Status)); + return Status; + } + if (Data & EMMC_SWITCH_ERROR) { + DEBUG ((DEBUG_ERROR, "EmmcGetDeviceState(): Failed to switch expected mode, Status=%r.\n", Status)); + return EFI_DEVICE_ERROR; + } + *State = DEVICE_STATE(Data); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +EmmcSetEXTCSD ( + IN MMC_HOST_INSTANCE *MmcHostInstance, + UINT32 ExtCmdIndex, + UINT32 Value + ) +{ + EFI_MMC_HOST_PROTOCOL *Host; + EMMC_DEVICE_STATE State; + EFI_STATUS Status; + UINT32 Argument; + + Host = MmcHostInstance->MmcHost; + Argument = EMMC_CMD6_ARG_ACCESS(3) | EMMC_CMD6_ARG_INDEX(ExtCmdIndex) | + EMMC_CMD6_ARG_VALUE(Value) | EMMC_CMD6_ARG_CMD_SET(1); + Status = Host->SendCommand (Host, MMC_CMD6, Argument); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcSetEXTCSD(): Failed to send CMD6, Status=%r.\n", Status)); + return Status; + } + // Make sure device exiting prog mode + do { + Status = EmmcGetDeviceState (MmcHostInstance, &State); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcSetEXTCSD(): Failed to get device state, Status=%r.\n", Status)); + return Status; + } + } while (State == EMMC_PRG_STATE); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +EmmcIdentificationMode ( + IN MMC_HOST_INSTANCE *MmcHostInstance, + IN OCR_RESPONSE Response + ) +{ + EFI_MMC_HOST_PROTOCOL *Host; + EFI_BLOCK_IO_MEDIA *Media; + EFI_STATUS Status; + EMMC_DEVICE_STATE State; + UINT32 RCA; + + Host = MmcHostInstance->MmcHost; + Media = MmcHostInstance->BlockIo.Media; + + // Fetch card identity register + Status = Host->SendCommand (Host, MMC_CMD2, 0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): Failed to send CMD2, Status=%r.\n", Status)); + return Status; + } + + Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R2, (UINT32 *)&(MmcHostInstance->CardInfo.CIDData)); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): CID retrieval error, Status=%r.\n", Status)); + return Status; + } + + // Assign a relative address value to the card + MmcHostInstance->CardInfo.RCA = ++mEmmcRcaCount; // TODO: might need a more sophisticated way of doing this + RCA = MmcHostInstance->CardInfo.RCA << RCA_SHIFT_OFFSET; + Status = Host->SendCommand (Host, MMC_CMD3, RCA); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): RCA set error, Status=%r.\n", Status)); + return Status; + } + + // Fetch card specific data + Status = Host->SendCommand (Host, MMC_CMD9, RCA); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): Failed to send CMD9, Status=%r.\n", Status)); + return Status; + } + + Status = Host->ReceiveResponse (Host, MMC_RESPONSE_TYPE_R2, (UINT32 *)&(MmcHostInstance->CardInfo.CSDData)); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): CSD retrieval error, Status=%r.\n", Status)); + return Status; + } + + // Select the card + Status = Host->SendCommand (Host, MMC_CMD7, RCA); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): Card selection error, Status=%r.\n", Status)); + } + + if (MMC_HOST_HAS_SETIOS(Host)) { + // Set 1-bit bus width + Status = Host->SetIos (Host, 0, 1, EMMCBACKWARD); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): Set 1-bit bus width error, Status=%r.\n", Status)); + return Status; + } + + // Set 1-bit bus width for EXTCSD + Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, EMMC_BUS_WIDTH_1BIT); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): Set extcsd bus width error, Status=%r.\n", Status)); + return Status; + } + } + + // Fetch ECSD + MmcHostInstance->CardInfo.ECSDData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ECSD))); + if (MmcHostInstance->CardInfo.ECSDData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = Host->SendCommand (Host, MMC_CMD8, 0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): ECSD fetch error, Status=%r.\n", Status)); + } + + Status = Host->ReadBlockData (Host, 0, 512, (UINT32 *)MmcHostInstance->CardInfo.ECSDData); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): ECSD read error, Status=%r.\n", Status)); + goto FreePageExit; + } + + // Make sure device exiting data mode + do { + Status = EmmcGetDeviceState (MmcHostInstance, &State); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "EmmcIdentificationMode(): Failed to get device state, Status=%r.\n", Status)); + goto FreePageExit; + } + } while (State == EMMC_DATA_STATE); + + // Set up media + Media->BlockSize = EMMC_CARD_SIZE; // 512-byte support is mandatory for eMMC cards + Media->MediaId = MmcHostInstance->CardInfo.CIDData.PSN; + Media->ReadOnly = MmcHostInstance->CardInfo.CSDData.PERM_WRITE_PROTECT; + Media->LogicalBlocksPerPhysicalBlock = 1; + Media->IoAlign = 4; + // Compute last block using bits [215:212] of the ECSD + Media->LastBlock = MmcHostInstance->CardInfo.ECSDData->SECTOR_COUNT - 1; // eMMC isn't supposed to report this for + // Cards <2GB in size, but the model does. + + // Setup card type + MmcHostInstance->CardInfo.CardType = EMMC_CARD; + return EFI_SUCCESS; + +FreePageExit: + FreePages (MmcHostInstance->CardInfo.ECSDData, EFI_SIZE_TO_PAGES (sizeof (ECSD))); + return Status; +} + +STATIC +EFI_STATUS +InitializeEmmcDevice ( + IN MMC_HOST_INSTANCE *MmcHostInstance + ) +{ + EFI_MMC_HOST_PROTOCOL *Host; + EFI_STATUS Status = EFI_SUCCESS; + ECSD *ECSDData; + UINT32 BusClockFreq, Idx, BusMode; + UINT32 BusWidth = 8; + UINT32 TimingMode[4] = {EMMCHS52DDR1V2, EMMCHS52DDR1V8, EMMCHS52, EMMCHS26}; + + Host = MmcHostInstance->MmcHost; + ECSDData = MmcHostInstance->CardInfo.ECSDData; + if (ECSDData->DEVICE_TYPE == EMMCBACKWARD){ + return EFI_SUCCESS; + } + + if (PcdGet32(PcdMmcForceDefaultSpeed)) { + DEBUG((DEBUG_WARN, "Forcing default speed mode\n")); + return EFI_SUCCESS; + } + + if (PcdGet32(PcdMmcForce1Bit)) { + DEBUG((DEBUG_WARN, "Forcing 1 bit mode\n")); + BusWidth = 1; + } + + if (!MMC_HOST_HAS_SETIOS(Host)) { + DEBUG((DEBUG_ERROR, "Controller doesn't support speed / bus width change\n")); + return EFI_SUCCESS; + } + + Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_HS_TIMING, EMMC_TIMING_HS); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to switch high speed mode, Status:%r.\n", Status)); + return Status; + } + + for (Idx = 0; Idx < 4; Idx++) { + switch (TimingMode[Idx]) { + case EMMCHS52DDR1V2: + case EMMCHS52DDR1V8: + case EMMCHS52: + BusClockFreq = 52000000; + break; + case EMMCHS26: + BusClockFreq = 26000000; + break; + default: + return EFI_UNSUPPORTED; + } + Status = Host->SetIos (Host, BusClockFreq, BusWidth, TimingMode[Idx]); + if (!EFI_ERROR (Status)) { + switch (TimingMode[Idx]) { + case EMMCHS52DDR1V2: + case EMMCHS52DDR1V8: + BusMode = EMMC_BUS_WIDTH_DDR_8BIT; + break; + case EMMCHS52: + case EMMCHS26: + BusMode = EMMC_BUS_WIDTH_8BIT; + break; + default: + return EFI_UNSUPPORTED; + } + Status = EmmcSetEXTCSD (MmcHostInstance, EXTCSD_BUS_WIDTH, BusMode); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "InitializeEmmcDevice(): Failed to set EXTCSD bus width, Status:%r\n", Status)); + } + return Status; + } + } + return Status; +} + +STATIC +UINT32 +SdSwitchCmdArgument ( + IN UINT32 AccessMode, + IN UINT32 CommandSystem, + IN UINT32 DriveStrength, + IN UINT32 PowerLimit, + IN BOOLEAN Mode + ) +{ + return (AccessMode & 0xF) | ((PowerLimit & 0xF) << 4) | \ + ((DriveStrength & 0xF) << 8) | ((DriveStrength & 0xF) << 12) | \ + (Mode ? BIT31 : 0); +} + +STATIC +EFI_STATUS +SdSelect ( + IN MMC_HOST_INSTANCE *MmcHostInstance + ) +{ + /* + * Moves a card from standby to transfer state. + */ + EFI_STATUS Status; + EFI_MMC_HOST_PROTOCOL *MmcHost = MmcHostInstance->MmcHost; + + Status = MmcHost->SendCommand (MmcHost, MMC_CMD7, + MmcHostInstance->CardInfo.RCA << 16); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a: error: %r\n", + __FUNCTION__, Status)); + } + + return Status; +} + +STATIC +EFI_STATUS +SdDeselect ( + IN MMC_HOST_INSTANCE *MmcHostInstance + ) +{ + /* + * Moves a card from transfer to standby. + */ + EFI_STATUS Status; + EFI_MMC_HOST_PROTOCOL *MmcHost = MmcHostInstance->MmcHost; + + Status = MmcHost->SendCommand (MmcHost, MMC_CMD7, 0); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a: error: %r\n", + __FUNCTION__, Status)); + } + + return Status; +} + +STATIC +EFI_STATUS +SdGetCsd( + IN MMC_HOST_INSTANCE *MmcHostInstance, + IN UINT32 *Response, + IN BOOLEAN Print + ) +{ + EFI_STATUS Status; + EFI_MMC_HOST_PROTOCOL *MmcHost = MmcHostInstance->MmcHost; + + Status = MmcHost->SendCommand (MmcHost, MMC_CMD9, + MmcHostInstance->CardInfo.RCA << 16); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a(%u): error: %r\n", __FUNCTION__, + __LINE__, Status)); + return Status; + } + + Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CSD, + Response); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a(%u): error %r\n", __FUNCTION__, + __LINE__, Status)); + return Status; + } + + if (Print) { + PrintCSD (Response); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SdSet4Bit( + IN MMC_HOST_INSTANCE *MmcHostInstance + ) +{ + UINT32 CmdArg; + EFI_STATUS Status; + EFI_MMC_HOST_PROTOCOL *MmcHost = MmcHostInstance->MmcHost; + + if (PcdGet32(PcdMmcForce1Bit)) { + DEBUG((DEBUG_WARN, "Forcing 1 bit mode\n")); + return EFI_SUCCESS; + } + + if (!MMC_HOST_HAS_SETIOS(MmcHost)) { + DEBUG((DEBUG_WARN, "Controller doesn't support bus width change\n")); + return EFI_SUCCESS; + } + + CmdArg = MmcHostInstance->CardInfo.RCA << 16; + Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, CmdArg); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(%u): error: %r\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } + + /* Width: 4 */ + Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, 2); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(%u): error %r\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } + + Status = MmcHost->SetIos (MmcHost, 0, BUSWIDTH_4, EMMCBACKWARD); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(%u): error: %r\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SdSetSpeed( + IN MMC_HOST_INSTANCE *MmcHostInstance, + IN BOOLEAN CccSwitch + ) +{ + UINT32 Speed; + UINT32 CmdArg; + EFI_STATUS Status; + UINT32 Buffer[16]; + UINT32 Response[4]; + EFI_MMC_HOST_PROTOCOL *MmcHost = MmcHostInstance->MmcHost; + + if (!MMC_HOST_HAS_SETIOS(MmcHost)) { + DEBUG((DEBUG_WARN, "Controller doesn't support speed change\n")); + return EFI_SUCCESS; + } + + Speed = PcdGet32(PcdMmcSdDefaultSpeedMHz) * 1000000; + if (Speed == 0) { + Speed = SD_DEFAULT_SPEED; + } else { + DEBUG((DEBUG_INFO, "Using default speed override %u Hz\n", + Speed)); + } + + /* + * First set base speed. We'll then try HS. + */ + Status = MmcHost->SetIos (MmcHost, Speed, 0, EMMCBACKWARD); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a: error setting speed %u: %r\n", + __FUNCTION__, Speed, Status)); + return Status; + } + + if (PcdGet32(PcdMmcForceDefaultSpeed)) { + DEBUG((DEBUG_WARN, "Forcing default speed mode\n")); + return EFI_SUCCESS; + } + + if (!CccSwitch) { + return EFI_SUCCESS; + } + + /* Query. */ + CmdArg = SdSwitchCmdArgument(0xf, 0xf, 0xf, 0xf, FALSE); + Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a(%u): error: %r\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } else { + Status = MmcHost->ReadBlockData (MmcHost, 0, SWITCH_CMD_DATA_LENGTH, + Buffer); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a(%u): error: %r\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } + } + + if (!(Buffer[3] & SD_HIGH_SPEED_SUPPORTED)) { + DEBUG((DEBUG_ERROR, "%a: High Speed not supported by Card\n")); + return EFI_SUCCESS; + } + + /* Switch to high speed. */ + CmdArg = SdSwitchCmdArgument(1, 0xf, 0xf, 0xf, TRUE); + Status = MmcHost->SendCommand (MmcHost, MMC_CMD6, CmdArg); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a(%u): error: %r\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } else { + Status = MmcHost->ReadBlockData (MmcHost, 0, + SWITCH_CMD_DATA_LENGTH, Buffer); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a(%u): error: %r\n", + __FUNCTION__, __LINE__, Status)); + return Status; + } + + if ((Buffer[4] & SWITCH_CMD_SUCCESS_MASK) != 0x1) { + DEBUG((DEBUG_ERROR, "Problem switching SD card into HS mode\n")); + DEBUG((DEBUG_ERROR, "%08x %08x %08x %08x\n", + Buffer[0], Buffer[1], Buffer[2], Buffer[3])); + DEBUG((DEBUG_ERROR, "%08x %08x %08x %08x\n", + Buffer[4], Buffer[5], Buffer[6], Buffer[8])); + return Status; + } + } + + DEBUG((DEBUG_ERROR, "Dumping CSD after high-speed switch\n")); + SdDeselect(MmcHostInstance); + SdGetCsd(MmcHostInstance, Response, TRUE); + SdSelect(MmcHostInstance); + + Speed = PcdGet32(PcdMmcSdHighSpeedMHz) * 1000000; + if (Speed == 0) { + Speed = SD_HIGH_SPEED; + } else { + DEBUG((DEBUG_INFO, "Using high speed override %u Hz\n", + Speed)); + } + + Status = MmcHost->SetIos (MmcHost, Speed, 0, EMMCBACKWARD); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a: error setting speed %u: %r\n", + __FUNCTION__, Speed, Status)); + return Status; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +InitializeSdMmcDevice ( + IN MMC_HOST_INSTANCE *MmcHostInstance + ) +{ + UINT32 Response[4]; + UINT32 Buffer[128]; + UINTN BlockSize; + UINTN CardSize; + UINTN NumBlocks; + BOOLEAN CccSwitch; + SCR Scr; + EFI_STATUS Status; + EFI_MMC_HOST_PROTOCOL *MmcHost = MmcHostInstance->MmcHost; + + Status = SdGetCsd (MmcHostInstance, Response, TRUE); + if (EFI_ERROR (Status)) { + return Status; + } + + if (MMC_CSD_GET_CCC(Response) & SD_CCC_SWITCH) { + CccSwitch = TRUE; + } else { + CccSwitch = FALSE; + } + + if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) { + CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response); + NumBlocks = ((CardSize + 1) * 1024); + BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response); + } else { + CardSize = MMC_CSD_GET_DEVICESIZE (Response); + NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT (Response) + 2)); + BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response); + } + + // For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes. + if (BlockSize > 512) { + NumBlocks = MultU64x32 (NumBlocks, BlockSize / 512); + BlockSize = 512; + } + + MmcHostInstance->BlockIo.Media->LastBlock = (NumBlocks - 1); + MmcHostInstance->BlockIo.Media->BlockSize = BlockSize; + MmcHostInstance->BlockIo.Media->ReadOnly = MmcHost->IsReadOnly (MmcHost); + MmcHostInstance->BlockIo.Media->MediaPresent = TRUE; + MmcHostInstance->BlockIo.Media->MediaId++; + + Status = SdSelect(MmcHostInstance); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, + MmcHostInstance->CardInfo.RCA << 16); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a (MMC_CMD55): Error and Status = %r\n", __FUNCTION__, Status)); + return Status; + } + Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a (MMC_CMD55): Error and Status = %r\n", __FUNCTION__, Status)); + return Status; + } + if ((Response[0] & MMC_STATUS_APP_CMD) == 0) { + return EFI_SUCCESS; + } + + /* SCR */ + Status = MmcHost->SendCommand (MmcHost, MMC_ACMD51, 0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(MMC_ACMD51): Error and Status = %r\n", __func__, Status)); + return Status; + } else { + Status = MmcHost->ReadBlockData (MmcHost, 0, 8, Buffer); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a(MMC_ACMD51): ReadBlockData Error and Status = %r\n", __func__, Status)); + return Status; + } + CopyMem (&Scr, Buffer, 8); + if (Scr.SD_SPEC == 2) { + if (Scr.SD_SPEC3 == 1) { + if (Scr.SD_SPEC4 == 1) { + DEBUG ((DEBUG_INFO, "Found SD Card for Spec Version 4.xx\n")); + } else { + DEBUG ((DEBUG_INFO, "Found SD Card for Spec Version 3.0x\n")); + } + } else { + if (Scr.SD_SPEC4 == 0) { + DEBUG ((DEBUG_INFO, "Found SD Card for Spec Version 2.0\n")); + } else { + DEBUG ((DEBUG_ERROR, "Found invalid SD Card\n")); + } + } + } else { + if ((Scr.SD_SPEC3 == 0) && (Scr.SD_SPEC4 == 0)) { + if (Scr.SD_SPEC == 1) { + DEBUG ((DEBUG_INFO, "Found SD Card for Spec Version 1.10\n")); + } else { + DEBUG ((DEBUG_INFO, "Found SD Card for Spec Version 1.0\n")); + } + } else { + DEBUG ((DEBUG_ERROR, "Found invalid SD Card\n")); + } + } + } + + Status = SdSetSpeed(MmcHostInstance, CccSwitch); + if (EFI_ERROR(Status)) { + return Status; + } + + if (Scr.SD_BUS_WIDTHS & SD_BUS_WIDTH_4BIT) { + Status = SdSet4Bit(MmcHostInstance); + if (EFI_ERROR(Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +MmcIdentificationMode ( + IN MMC_HOST_INSTANCE *MmcHostInstance + ) +{ + EFI_STATUS Status; + UINT32 Response[4]; + UINTN Timeout; + UINTN CmdArg; + BOOLEAN IsHCS; + EFI_MMC_HOST_PROTOCOL *MmcHost; + OCR_RESPONSE OcrResponse; + + MmcHost = MmcHostInstance->MmcHost; + CmdArg = 0; + IsHCS = FALSE; + + if (MmcHost == NULL) { + return EFI_INVALID_PARAMETER; + } + + // We can get into this function if we restart the identification mode + if (MmcHostInstance->State == MmcHwInitializationState) { + // Initialize the MMC Host HW + Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState, Status=%r.\n", Status)); + return Status; + } + } + + Status = MmcHost->SendCommand (MmcHost, MMC_CMD0, 0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode(MMC_CMD0): Error, Status=%r.\n", Status)); + return Status; + } + Status = MmcNotifyState (MmcHostInstance, MmcIdleState); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcIdleState, Status=%r.\n", Status)); + return Status; + } + + // Send CMD1 to get OCR (MMC) + // This command only valid for MMC and eMMC + Timeout = MAX_RETRY_COUNT; + do { + Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, EMMC_CMD1_CAPACITY_GREATER_THAN_2GB); + if (EFI_ERROR (Status)) + break; + Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, (UINT32 *)&OcrResponse); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status)); + return Status; + } + Timeout--; + } while (!OcrResponse.Ocr.PowerUp && (Timeout > 0)); + if (Status == EFI_SUCCESS) { + if (!OcrResponse.Ocr.PowerUp) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode(MMC_CMD1): Card initialisation failure, Status=%r.\n", Status)); + return EFI_DEVICE_ERROR; + } + OcrResponse.Ocr.PowerUp = 0; + if (OcrResponse.Raw == EMMC_CMD1_CAPACITY_GREATER_THAN_2GB) { + MmcHostInstance->CardInfo.OCRData.AccessMode = BIT1; + } + else { + MmcHostInstance->CardInfo.OCRData.AccessMode = 0x0; + } + // Check whether MMC or eMMC + if (OcrResponse.Raw == EMMC_CMD1_CAPACITY_GREATER_THAN_2GB || + OcrResponse.Raw == EMMC_CMD1_CAPACITY_LESS_THAN_2GB) { + return EmmcIdentificationMode (MmcHostInstance, OcrResponse); + } + } + + // Are we using SDIO ? + Status = MmcHost->SendCommand (MmcHost, MMC_CMD5, 0); + if (Status == EFI_SUCCESS) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported, Status=%r.\n", Status)); + return EFI_UNSUPPORTED; + } + + // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1) + CmdArg = (0x0UL << 12 | BIT8 | 0xCEUL << 0); + Status = MmcHost->SendCommand (MmcHost, MMC_CMD8, CmdArg); + if (Status == EFI_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Card is SD2.0 => Supports high capacity\n")); + IsHCS = TRUE; + Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R7, Response); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Failed to receive response to CMD8, Status=%r.\n", Status)); + return Status; + } + PrintResponseR1 (Response[0]); + // Check if it is valid response + if (Response[0] != CmdArg) { + DEBUG ((DEBUG_ERROR, "The Card is not usable\n")); + return EFI_UNSUPPORTED; + } + } else { + DEBUG ((DEBUG_ERROR, "Not a SD2.0 Card\n")); + } + + // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.PowerUp == 1) + Timeout = MAX_RETRY_COUNT; + while (Timeout > 0) { + // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command + Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, 0); + if (Status == EFI_SUCCESS) { + DEBUG ((DEBUG_INFO, "Card should be SD\n")); + if (IsHCS) { + MmcHostInstance->CardInfo.CardType = SD_CARD_2; + } else { + MmcHostInstance->CardInfo.CardType = SD_CARD; + } + + // Note: The first time CmdArg will be zero + CmdArg = ((UINTN *) &(MmcHostInstance->CardInfo.OCRData))[0]; + if (IsHCS) { + CmdArg |= BIT30; + } + Status = MmcHost->SendCommand (MmcHost, MMC_ACMD41, CmdArg); + if (!EFI_ERROR (Status)) { + Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status)); + return Status; + } + ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0]; + } + } else { + DEBUG ((DEBUG_INFO, "Card should be MMC\n")); + MmcHostInstance->CardInfo.CardType = MMC_CARD; + + Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, 0x800000); + if (!EFI_ERROR (Status)) { + Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Failed to receive OCR, Status=%r.\n", Status)); + return Status; + } + ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0]; + } + } + + if (!EFI_ERROR (Status)) { + if (!MmcHostInstance->CardInfo.OCRData.PowerUp) { + gBS->Stall (1); + Timeout--; + } else { + if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) { + MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH; + DEBUG ((DEBUG_ERROR, "High capacity card.\n")); + } + break; // The MMC/SD card is ready. Continue the Identification Mode + } + } else { + gBS->Stall (1); + Timeout--; + } + } + + if (Timeout == 0) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode(): No Card\n")); + return EFI_NO_MEDIA; + } else { + PrintOCR (Response[0]); + } + + Status = MmcNotifyState (MmcHostInstance, MmcReadyState); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcReadyState\n")); + return Status; + } + + Status = MmcHost->SendCommand (MmcHost, MMC_CMD2, 0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n")); + return Status; + } + Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CID, Response); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Failed to receive CID, Status=%r.\n", Status)); + return Status; + } + + PrintCID (Response); + + Status = MmcHost->NotifyState (MmcHost, MmcIdentificationState); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcIdentificationState\n")); + return Status; + } + + // + // Note, SD specifications say that "if the command execution causes a state change, it + // will be visible to the host in the response to the next command" + // The status returned for this CMD3 will be 2 - identification + // + CmdArg = 1; + Status = MmcHost->SendCommand (MmcHost, MMC_CMD3, CmdArg); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n")); + return Status; + } + + Status = MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_RCA, Response); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Failed to receive RCA, Status=%r.\n", Status)); + return Status; + } + PrintRCA (Response[0]); + + // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card + if (MmcHostInstance->CardInfo.CardType != MMC_CARD) { + MmcHostInstance->CardInfo.RCA = Response[0] >> 16; + } else { + MmcHostInstance->CardInfo.RCA = CmdArg; + } + Status = MmcNotifyState (MmcHostInstance, MmcStandByState); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "MmcIdentificationMode() : Error MmcStandByState\n")); + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +InitializeMmcDevice ( + IN MMC_HOST_INSTANCE *MmcHostInstance + ) +{ + EFI_STATUS Status; + EFI_MMC_HOST_PROTOCOL *MmcHost; + UINTN BlockCount; + + BlockCount = 1; + MmcHost = MmcHostInstance->MmcHost; + + Status = MmcIdentificationMode (MmcHostInstance); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "InitializeMmcDevice(): Error in Identification Mode, Status=%r\n", Status)); + return Status; + } + + Status = MmcNotifyState (MmcHostInstance, MmcTransferState); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "InitializeMmcDevice(): Error MmcTransferState, Status=%r\n", Status)); + return Status; + } + + if (MmcHostInstance->CardInfo.CardType != EMMC_CARD) { + Status = InitializeSdMmcDevice (MmcHostInstance); + } else { + Status = InitializeEmmcDevice (MmcHostInstance); + } + if (EFI_ERROR (Status)) { + return Status; + } + + // Set Block Length + Status = MmcHost->SendCommand (MmcHost, MMC_CMD16, MmcHostInstance->BlockIo.Media->BlockSize); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "InitializeMmcDevice(MMC_CMD16): Error MmcHostInstance->BlockIo.Media->BlockSize: %d and Error = %r\n", + MmcHostInstance->BlockIo.Media->BlockSize, Status)); + return Status; + } + + // Block Count (not used). Could return an error for SD card + if (MmcHostInstance->CardInfo.CardType == MMC_CARD) { + Status = MmcHost->SendCommand (MmcHost, MMC_CMD23, BlockCount); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "InitializeMmcDevice(MMC_CMD23): Error, Status=%r\n", Status)); + return Status; + } + } + + return EFI_SUCCESS; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c b/Platform/Broadcom/Bcm283x/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c new file mode 100644 index 000000000000..36b953d9c5f4 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.c @@ -0,0 +1,915 @@ +/** @file + * + * Static SMBIOS Table for ARM platform + * Derived from EmulatorPkg package + * + * Note SMBIOS 2.7.1 Required structures: + * BIOS Information (Type 0) + * System Information (Type 1) + * Board Information (Type 2) + * System Enclosure (Type 3) + * Processor Information (Type 4) - CPU Driver + * Cache Information (Type 7) - For cache that is external to processor + * System Slots (Type 9) - If system has slots + * Physical Memory Array (Type 16) + * Memory Device (Type 17) - For each socketed system-memory Device + * Memory Array Mapped Address (Type 19) - One per contiguous block per Physical Memroy Array + * System Boot Information (Type 32) + * + * Copyright (c) 2017-2018, Andrey Warkentin + * Copyright (c) 2013, Linaro.org + * Copyright (c) 2012, Apple Inc. All rights reserved.
+ * Copyright (c) Microsoft Corporation. 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 +#include +#include +#include +#include +#include + +STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol; + +/*********************************************************************** + SMBIOS data definition TYPE0 BIOS Information +************************************************************************/ +SMBIOS_TABLE_TYPE0 mBIOSInfoType0 = { + { EFI_SMBIOS_TYPE_BIOS_INFORMATION, sizeof (SMBIOS_TABLE_TYPE0), 0 }, + 1, // Vendor String + 2, // BiosVersion String + 0x0, // BiosSegment + 3, // BiosReleaseDate String + 0x1F, // BiosSize + { // BiosCharacteristics + 0, // Reserved :2; ///< Bits 0-1. + 0, // Unknown :1; + 0, // BiosCharacteristicsNotSupported :1; + 0, // IsaIsSupported :1; + 0, // McaIsSupported :1; + 0, // EisaIsSupported :1; + 0, // PciIsSupported :1; + 0, // PcmciaIsSupported :1; + 0, // PlugAndPlayIsSupported :1; + 0, // ApmIsSupported :1; + 0, // BiosIsUpgradable :1; + 0, // BiosShadowingAllowed :1; + 0, // VlVesaIsSupported :1; + 0, // EscdSupportIsAvailable :1; + 0, // BootFromCdIsSupported :1; + 1, // SelectableBootIsSupported :1; + 0, // RomBiosIsSocketed :1; + 0, // BootFromPcmciaIsSupported :1; + 0, // EDDSpecificationIsSupported :1; + 0, // JapaneseNecFloppyIsSupported :1; + 0, // JapaneseToshibaFloppyIsSupported :1; + 0, // Floppy525_360IsSupported :1; + 0, // Floppy525_12IsSupported :1; + 0, // Floppy35_720IsSupported :1; + 0, // Floppy35_288IsSupported :1; + 0, // PrintScreenIsSupported :1; + 0, // Keyboard8042IsSupported :1; + 0, // SerialIsSupported :1; + 0, // PrinterIsSupported :1; + 0, // CgaMonoIsSupported :1; + 0, // NecPc98 :1; + 0 // ReservedForVendor :32; ///< Bits 32-63. Bits 32-47 reserved for BIOS vendor + ///< and bits 48-63 reserved for System Vendor. + }, + { // BIOSCharacteristicsExtensionBytes[] + 0x01, // AcpiIsSupported :1; + // UsbLegacyIsSupported :1; + // AgpIsSupported :1; + // I2OBootIsSupported :1; + // Ls120BootIsSupported :1; + // AtapiZipDriveBootIsSupported :1; + // Boot1394IsSupported :1; + // SmartBatteryIsSupported :1; + // BIOSCharacteristicsExtensionBytes[1] + 0x0e, // BiosBootSpecIsSupported :1; + // FunctionKeyNetworkBootIsSupported :1; + // TargetContentDistributionEnabled :1; + // UefiSpecificationSupported :1; + // VirtualMachineSupported :1; + // ExtensionByte2Reserved :3; + }, + 0xFF, // SystemBiosMajorRelease + 0xFF, // SystemBiosMinorRelease + 0xFF, // EmbeddedControllerFirmwareMajorRelease + 0xFF, // EmbeddedControllerFirmwareMinorRelease +}; + +CHAR8 *mBIOSInfoType0Strings[] = { + "https://github.com/andreiw/RaspberryPiPkg", // Vendor String + "Raspberry Pi 64-bit UEFI (" __DATE__ " " __TIME__ ")", // BiosVersion String + __DATE__, + NULL +}; + +/*********************************************************************** + SMBIOS data definition TYPE1 System Information +************************************************************************/ +SMBIOS_TABLE_TYPE1 mSysInfoType1 = { + { EFI_SMBIOS_TYPE_SYSTEM_INFORMATION, sizeof (SMBIOS_TABLE_TYPE1), 0 }, + 1, // Manufacturer String + 2, // ProductName String + 3, // Version String + 4, // SerialNumber String + { 0x25EF0280, 0xEC82, 0x42B0, { 0x8F, 0xB6, 0x10, 0xAD, 0xCC, 0xC6, 0x7C, 0x02 } }, + SystemWakeupTypePowerSwitch, + 5, // SKUNumber String + 6, // Family String +}; + +#define PROD_BASE 8 +#define PROD_KNOWN 13 +#define PROD_UNKNOWN 11 +CHAR8 *ProductNames[] = { + /* 8 */ "3", + /* 9 */ "Zero", + /* 10 */ "CM3", + /* 11 */ "???", + /* 12 */ "Zero W", + /* 13 */ "3B+" +}; + +#define MANU_UNKNOWN 0 +#define MANU_KNOWN 4 +#define MANU_BASE 1 +CHAR8 *ManufNames[] = { + "???", + /* 0 */ "Sony", + /* 1 */ "Egoman", + /* 2 */ "Embest", + /* 3 */ "Sony Japan", + /* 4 */ "Embest" +}; + +CHAR8 mSysInfoManufName[sizeof("Sony Japan")]; +CHAR8 mSysInfoProductName[sizeof("64-bit Raspberry Pi XXXXXX (rev. xxxxxxxx)")]; +CHAR8 mSysInfoSerial[sizeof(UINT64) * 2 + 1]; +CHAR8 mSysInfoSKU[sizeof(UINT64) * 2 + 1]; + +CHAR8 *mSysInfoType1Strings[] = { + mSysInfoManufName, + mSysInfoProductName, + mSysInfoProductName, + mSysInfoSerial, + mSysInfoSKU, + "edk2", + NULL +}; + +/*********************************************************************** + SMBIOS data definition TYPE2 Board Information +************************************************************************/ +SMBIOS_TABLE_TYPE2 mBoardInfoType2 = { + { EFI_SMBIOS_TYPE_BASEBOARD_INFORMATION, sizeof (SMBIOS_TABLE_TYPE2), 0 }, + 1, // Manufacturer String + 2, // ProductName String + 3, // Version String + 4, // SerialNumber String + 5, // AssetTag String + { // FeatureFlag + 1, // Motherboard :1; + 0, // RequiresDaughterCard :1; + 0, // Removable :1; + 0, // Replaceable :1; + 0, // HotSwappable :1; + 0, // Reserved :3; + }, + 6, // LocationInChassis String + 0, // ChassisHandle; + BaseBoardTypeMotherBoard, // BoardType; + 0, // NumberOfContainedObjectHandles; + { 0 } // ContainedObjectHandles[1]; +}; +CHAR8 *mBoardInfoType2Strings[] = { + mSysInfoManufName, + mSysInfoProductName, + mSysInfoProductName, + mSysInfoSerial, + "None", + mSysInfoSKU, + NULL +}; + +/*********************************************************************** + SMBIOS data definition TYPE3 Enclosure Information +************************************************************************/ +SMBIOS_TABLE_TYPE3 mEnclosureInfoType3 = { + { EFI_SMBIOS_TYPE_SYSTEM_ENCLOSURE, sizeof (SMBIOS_TABLE_TYPE3), 0 }, + 1, // Manufacturer String + MiscChassisEmbeddedPc, // Type; + 2, // Version String + 3, // SerialNumber String + 4, // AssetTag String + ChassisStateSafe, // BootupState; + ChassisStateSafe, // PowerSupplyState; + ChassisStateSafe, // ThermalState; + ChassisSecurityStatusNone,// SecurityStatus; + { 0, 0, 0, 0 }, // OemDefined[4]; + 0, // Height; + 0, // NumberofPowerCords; + 0, // ContainedElementCount; + 0, // ContainedElementRecordLength; + { { 0 } }, // ContainedElements[1]; +}; +CHAR8 *mEnclosureInfoType3Strings[] = { + mSysInfoManufName, + mSysInfoProductName, + mSysInfoSerial, + "None", + NULL +}; + +/*********************************************************************** + SMBIOS data definition TYPE4 Processor Information +************************************************************************/ +SMBIOS_TABLE_TYPE4 mProcessorInfoType4 = { + { EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, sizeof (SMBIOS_TABLE_TYPE4), 0}, + 1, // Socket String + CentralProcessor, // ProcessorType; ///< The enumeration value from PROCESSOR_TYPE_DATA. + ProcessorFamilyIndicatorFamily2, // ProcessorFamily; ///< The enumeration value from PROCESSOR_FAMILY2_DATA. + 2, // ProcessorManufacture String; + { // ProcessorId; + { // PROCESSOR_SIGNATURE + 0, // ProcessorSteppingId:4; + 0, // ProcessorModel: 4; + 0, // ProcessorFamily: 4; + 0, // ProcessorType: 2; + 0, // ProcessorReserved1: 2; + 0, // ProcessorXModel: 4; + 0, // ProcessorXFamily: 8; + 0, // ProcessorReserved2: 4; + }, + + { // PROCESSOR_FEATURE_FLAGS + 0, // ProcessorFpu :1; + 0, // ProcessorVme :1; + 0, // ProcessorDe :1; + 0, // ProcessorPse :1; + 0, // ProcessorTsc :1; + 0, // ProcessorMsr :1; + 0, // ProcessorPae :1; + 0, // ProcessorMce :1; + 0, // ProcessorCx8 :1; + 0, // ProcessorApic :1; + 0, // ProcessorReserved1 :1; + 0, // ProcessorSep :1; + 0, // ProcessorMtrr :1; + 0, // ProcessorPge :1; + 0, // ProcessorMca :1; + 0, // ProcessorCmov :1; + 0, // ProcessorPat :1; + 0, // ProcessorPse36 :1; + 0, // ProcessorPsn :1; + 0, // ProcessorClfsh :1; + 0, // ProcessorReserved2 :1; + 0, // ProcessorDs :1; + 0, // ProcessorAcpi :1; + 0, // ProcessorMmx :1; + 0, // ProcessorFxsr :1; + 0, // ProcessorSse :1; + 0, // ProcessorSse2 :1; + 0, // ProcessorSs :1; + 0, // ProcessorReserved3 :1; + 0, // ProcessorTm :1; + 0, // ProcessorReserved4 :2; + } + }, + 3, // ProcessorVersion String; + { // Voltage; + 1, // ProcessorVoltageCapability5V :1; + 1, // ProcessorVoltageCapability3_3V :1; + 1, // ProcessorVoltageCapability2_9V :1; + 0, // ProcessorVoltageCapabilityReserved :1; ///< Bit 3, must be zero. + 0, // ProcessorVoltageReserved :3; ///< Bits 4-6, must be zero. + 0 // ProcessorVoltageIndicateLegacy :1; + }, + 0, // ExternalClock; + 0, // MaxSpeed; + 0, // CurrentSpeed; + 0x41, // Status; + ProcessorUpgradeOther, // ProcessorUpgrade; ///< The enumeration value from PROCESSOR_UPGRADE. + 0, // L1CacheHandle; + 0, // L2CacheHandle; + 0, // L3CacheHandle; + 4, // SerialNumber; + 5, // AssetTag; + 6, // PartNumber; + 4, // CoreCount; + 4, // EnabledCoreCount; + 4, // ThreadCount; + 0x6C, // ProcessorCharacteristics; + ProcessorFamilyARM, // ARM Processor Family; +}; + +CHAR8 *mProcessorInfoType4Strings[] = { + "Socket", + "ARM", + "BCM2837 ARMv8", + "1.0", + "1.0", + "1.0", + NULL +}; + +/*********************************************************************** + SMBIOS data definition TYPE7 Cache Information +************************************************************************/ +SMBIOS_TABLE_TYPE7 mCacheInfoType7 = { + { EFI_SMBIOS_TYPE_CACHE_INFORMATION, sizeof (SMBIOS_TABLE_TYPE7), 0 }, + 1, // SocketDesignation String + 0x018A, // Cache Configuration + 0x00FF, // Maximum Size 256k + 0x00FF, // Install Size 256k + { // Supported SRAM Type + 0, //Other :1 + 0, //Unknown :1 + 0, //NonBurst :1 + 1, //Burst :1 + 0, //PiplelineBurst :1 + 1, //Synchronous :1 + 0, //Asynchronous :1 + 0 //Reserved :9 + }, + { // Current SRAM Type + 0, //Other :1 + 0, //Unknown :1 + 0, //NonBurst :1 + 1, //Burst :1 + 0, //PiplelineBurst :1 + 1, //Synchronous :1 + 0, //Asynchronous :1 + 0 //Reserved :9 + }, + 0, // Cache Speed unknown + CacheErrorMultiBit, // Error Correction Multi + CacheTypeUnknown, // System Cache Type + CacheAssociativity2Way // Associativity +}; +CHAR8 *mCacheInfoType7Strings[] = { + "Cache1", + NULL +}; + +/*********************************************************************** + SMBIOS data definition TYPE9 System Slot Information +************************************************************************/ +SMBIOS_TABLE_TYPE9 mSysSlotInfoType9 = { + { EFI_SMBIOS_TYPE_SYSTEM_SLOTS, sizeof (SMBIOS_TABLE_TYPE9), 0 }, + 1, // SlotDesignation String + SlotTypeOther, // SlotType; ///< The enumeration value from MISC_SLOT_TYPE. + SlotDataBusWidthOther, // SlotDataBusWidth; ///< The enumeration value from MISC_SLOT_DATA_BUS_WIDTH. + SlotUsageAvailable, // CurrentUsage; ///< The enumeration value from MISC_SLOT_USAGE. + SlotLengthOther, // SlotLength; ///< The enumeration value from MISC_SLOT_LENGTH. + 0, // SlotID; + { // SlotCharacteristics1; + 1, // CharacteristicsUnknown :1; + 0, // Provides50Volts :1; + 0, // Provides33Volts :1; + 0, // SharedSlot :1; + 0, // PcCard16Supported :1; + 0, // CardBusSupported :1; + 0, // ZoomVideoSupported :1; + 0, // ModemRingResumeSupported:1; + }, + { // SlotCharacteristics2; + 0, // PmeSignalSupported :1; + 0, // HotPlugDevicesSupported :1; + 0, // SmbusSignalSupported :1; + 0, // Reserved :5; ///< Set to 0. + }, + 0, // SegmentGroupNum; + 0, // BusNum; + 0, // DevFuncNum; +}; +CHAR8 *mSysSlotInfoType9Strings[] = { + "SD Card", + NULL +}; + +/*********************************************************************** + SMBIOS data definition TYPE16 Physical Memory ArrayInformation +************************************************************************/ +SMBIOS_TABLE_TYPE16 mPhyMemArrayInfoType16 = { + { EFI_SMBIOS_TYPE_PHYSICAL_MEMORY_ARRAY, sizeof (SMBIOS_TABLE_TYPE16), 0 }, + MemoryArrayLocationSystemBoard, // Location; ///< The enumeration value from MEMORY_ARRAY_LOCATION. + MemoryArrayUseSystemMemory, // Use; ///< The enumeration value from MEMORY_ARRAY_USE. + MemoryErrorCorrectionUnknown, // MemoryErrorCorrection; ///< The enumeration value from MEMORY_ERROR_CORRECTION. + 0x40000000, // MaximumCapacity; + 0xFFFE, // MemoryErrorInformationHandle; + 1, // NumberOfMemoryDevices; + 0x40000000ULL, // ExtendedMaximumCapacity; +}; +CHAR8 *mPhyMemArrayInfoType16Strings[] = { + NULL +}; + +/*********************************************************************** + SMBIOS data definition TYPE17 Memory Device Information +************************************************************************/ +SMBIOS_TABLE_TYPE17 mMemDevInfoType17 = { + { EFI_SMBIOS_TYPE_MEMORY_DEVICE, sizeof (SMBIOS_TABLE_TYPE17), 0 }, + 0, // MemoryArrayHandle; // Should match SMBIOS_TABLE_TYPE16.Handle, initialized at runtime, refer to PhyMemArrayInfoUpdateSmbiosType16() + 0xFFFE, // MemoryErrorInformationHandle; + 0xFFFF, // TotalWidth; + 0xFFFF, // DataWidth; + 0x0400, // Size; // When bit 15 is 0: Size in MB + // When bit 15 is 1: Size in KB, and continues in ExtendedSize + MemoryFormFactorUnknown, // FormFactor; ///< The enumeration value from MEMORY_FORM_FACTOR. + 0xff, // DeviceSet; + 1, // DeviceLocator String + 2, // BankLocator String + MemoryTypeDram, // MemoryType; ///< The enumeration value from MEMORY_DEVICE_TYPE. + { // TypeDetail; + 0, // Reserved :1; + 0, // Other :1; + 1, // Unknown :1; + 0, // FastPaged :1; + 0, // StaticColumn :1; + 0, // PseudoStatic :1; + 0, // Rambus :1; + 0, // Synchronous :1; + 0, // Cmos :1; + 0, // Edo :1; + 0, // WindowDram :1; + 0, // CacheDram :1; + 0, // Nonvolatile :1; + 0, // Registered :1; + 0, // Unbuffered :1; + 0, // Reserved1 :1; + }, + 0, // Speed; + 3, // Manufacturer String + 0, // SerialNumber String + 0, // AssetTag String + 0, // PartNumber String + 0, // Attributes; + 0, // ExtendedSize; + 0, // ConfiguredMemoryClockSpeed; +}; +CHAR8 *mMemDevInfoType17Strings[] = { + "OS Virtual Memory", + "malloc", + "OSV", + NULL +}; + +/*********************************************************************** + SMBIOS data definition TYPE19 Memory Array Mapped Address Information +************************************************************************/ +SMBIOS_TABLE_TYPE19 mMemArrMapInfoType19 = { + { EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS, sizeof (SMBIOS_TABLE_TYPE19), 0 }, + 0x00000000, // StartingAddress; + 0x00000000, // EndingAddress; + 0, // MemoryArrayHandle; + 1, // PartitionWidth; + 0, // ExtendedStartingAddress; + 0, // ExtendedEndingAddress; +}; +CHAR8 *mMemArrMapInfoType19Strings[] = { + NULL +}; + +/*********************************************************************** + SMBIOS data definition TYPE32 Boot Information +************************************************************************/ +SMBIOS_TABLE_TYPE32 mBootInfoType32 = { + { EFI_SMBIOS_TYPE_SYSTEM_BOOT_INFORMATION, sizeof (SMBIOS_TABLE_TYPE32), 0 }, + { 0, 0, 0, 0, 0, 0 }, // Reserved[6]; + BootInformationStatusNoError // BootStatus +}; + +CHAR8 *mBootInfoType32Strings[] = { + NULL +}; + + +/** + + Create SMBIOS record. + + Converts a fixed SMBIOS structure and an array of pointers to strings into + an SMBIOS record where the strings are cat'ed on the end of the fixed record + and terminated via a double NULL and add to SMBIOS table. + + SMBIOS_TABLE_TYPE32 gSmbiosType12 = { + { EFI_SMBIOS_TYPE_SYSTEM_CONFIGURATION_OPTIONS, sizeof (SMBIOS_TABLE_TYPE12), 0 }, + 1 // StringCount + }; + + CHAR8 *gSmbiosType12Strings[] = { + "Not Found", + NULL + }; + + ... + + LogSmbiosData ( + (EFI_SMBIOS_TABLE_HEADER*)&gSmbiosType12, + gSmbiosType12Strings + ); + + @param Template Fixed SMBIOS structure, required. + @param StringPack Array of strings to convert to an SMBIOS string pack. + NULL is OK. + @param DataSmbiosHande The new SMBIOS record handle . + NULL is OK. +**/ + +EFI_STATUS +EFIAPI +LogSmbiosData ( + IN EFI_SMBIOS_TABLE_HEADER *Template, + IN CHAR8 **StringPack, + OUT EFI_SMBIOS_HANDLE *DataSmbiosHande + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_PROTOCOL *Smbios; + EFI_SMBIOS_HANDLE SmbiosHandle; + EFI_SMBIOS_TABLE_HEADER *Record; + UINTN Index; + UINTN StringSize; + UINTN Size; + CHAR8 *Str; + + // + // Locate Smbios protocol. + // + Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios); + + if (EFI_ERROR (Status)) { + return Status; + } + + // Calculate the size of the fixed record and optional string pack + + Size = Template->Length; + if (StringPack == NULL) { + // At least a double null is required + Size += 2; + } else { + for (Index = 0; StringPack[Index] != NULL; Index++) { + StringSize = AsciiStrSize (StringPack[Index]); + Size += StringSize; + } + if (StringPack[0] == NULL) { + // At least a double null is required + Size += 1; + } + + // Don't forget the terminating double null + Size += 1; + } + + // Copy over Template + Record = (EFI_SMBIOS_TABLE_HEADER *)AllocateZeroPool (Size); + if (Record == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (Record, Template, Template->Length); + + // Append string pack + Str = ((CHAR8 *)Record) + Record->Length; + + for (Index = 0; StringPack[Index] != NULL; Index++) { + StringSize = AsciiStrSize (StringPack[Index]); + CopyMem (Str, StringPack[Index], StringSize); + Str += StringSize; + } + + *Str = 0; + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = Smbios->Add ( + Smbios, + gImageHandle, + &SmbiosHandle, + Record + ); + + if ((Status == EFI_SUCCESS) && (DataSmbiosHande != NULL)) { + *DataSmbiosHande = SmbiosHandle; + } + + ASSERT_EFI_ERROR (Status); + FreePool (Record); + return Status; +} + +/*********************************************************************** + SMBIOS data update TYPE0 BIOS Information +************************************************************************/ +VOID +BIOSInfoUpdateSmbiosType0 ( + VOID + ) +{ + LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mBIOSInfoType0, mBIOSInfoType0Strings, NULL); +} + +/*********************************************************************** + SMBIOS data update TYPE1 System Information +************************************************************************/ +VOID +I64ToHexString( + IN OUT CHAR8* TargetStringSz, + IN UINT32 TargetStringSize, + IN UINT64 Value + ) +{ + static CHAR8 ItoH[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; + UINT8 StringInx; + INT8 NibbleInx; + + ZeroMem((void*)TargetStringSz, TargetStringSize); + + // + // Convert each nibble to hex string, starting from + // the highest non-zero nibble. + // + StringInx = 0; + for (NibbleInx = sizeof(UINT64) * 2; NibbleInx > 0; --NibbleInx) { + UINT64 NibbleMask = (((UINT64)0xF) << ((NibbleInx - 1) * 4)); + UINT8 Nibble = (UINT8)((Value & NibbleMask) >> ((NibbleInx - 1) * 4)); + + ASSERT(Nibble <= 0xF); + + if (StringInx < (TargetStringSize-1)) { + TargetStringSz[StringInx++] = ItoH[Nibble]; + } else { + break; + } + } +} + +VOID +SysInfoUpdateSmbiosType1 ( + VOID + ) +{ + UINT32 BoardRevision = 0; + EFI_STATUS Status = EFI_SUCCESS; + UINT64 BoardSerial = 0; + UINTN Prod = PROD_UNKNOWN; + UINTN Manu = MANU_UNKNOWN; + + Status = mFwProtocol->GetModelRevision(&BoardRevision); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, + "Failed to get board model: %r\n", + Status)); + } else { + Prod = X(BoardRevision, 4, 11); + } + + if (Prod > PROD_KNOWN) { + Prod = PROD_UNKNOWN; + } + Prod -= PROD_BASE; + AsciiSPrint(mSysInfoProductName, + sizeof(mSysInfoProductName), + "64-bit Raspberry Pi %a (rev. %x)", + ProductNames[Prod], BoardRevision); + + Manu = X(BoardRevision, 16, 19); + if (Manu > MANU_KNOWN) { + Manu = MANU_UNKNOWN; + } else { + Manu += MANU_BASE; + } + AsciiSPrint(mSysInfoManufName, + sizeof(mSysInfoManufName), + "%a", ManufNames[Manu]); + + I64ToHexString(mSysInfoSKU, + sizeof(mSysInfoSKU), + BoardRevision); + + Status = mFwProtocol->GetSerial(&BoardSerial); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, + "Failed to get board serial: %r\n", + Status)); + } + + I64ToHexString(mSysInfoSerial, + sizeof(mSysInfoSerial), + BoardSerial); + + DEBUG ((DEBUG_ERROR, "Board Serial Number: %a\n", mSysInfoSerial)); + + mSysInfoType1.Uuid.Data1= *(UINT32 *)"RPi3"; + mSysInfoType1.Uuid.Data2=0x0; + mSysInfoType1.Uuid.Data3=0x0; + CopyMem(mSysInfoType1.Uuid.Data4, + &BoardSerial, sizeof(BoardSerial)); + + LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mSysInfoType1, mSysInfoType1Strings, NULL); +} + +/*********************************************************************** + SMBIOS data update TYPE2 Board Information +************************************************************************/ +VOID +BoardInfoUpdateSmbiosType2 ( + VOID + ) +{ + LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mBoardInfoType2, mBoardInfoType2Strings, NULL); +} + +/*********************************************************************** + SMBIOS data update TYPE3 Enclosure Information +************************************************************************/ +VOID +EnclosureInfoUpdateSmbiosType3 ( + VOID + ) +{ + LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mEnclosureInfoType3, mEnclosureInfoType3Strings, NULL); +} + +/*********************************************************************** + SMBIOS data update TYPE4 Processor Information +************************************************************************/ +VOID +ProcessorInfoUpdateSmbiosType4 ( + IN UINTN MaxCpus + ) +{ + EFI_STATUS Status; + UINT32 Rate; + + mProcessorInfoType4.CoreCount = (UINT8) MaxCpus; + mProcessorInfoType4.EnabledCoreCount = (UINT8) MaxCpus; + mProcessorInfoType4.ThreadCount = (UINT8) MaxCpus; + + Status = mFwProtocol->GetMaxClockRate(RPI_FW_CLOCK_RATE_ARM, &Rate); + if (Status != EFI_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Couldn't get the max CPU speed: %r\n", Status)); + } else { + mProcessorInfoType4.MaxSpeed = Rate / 1000000; + DEBUG ((DEBUG_INFO, "Max CPU speed: %uHz\n", Rate)); + } + + Status = mFwProtocol->GetClockRate(RPI_FW_CLOCK_RATE_ARM, &Rate); + if (Status != EFI_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Couldn't get the current CPU speed: %r\n", Status)); + } else { + mProcessorInfoType4.CurrentSpeed = Rate / 1000000; + DEBUG ((DEBUG_INFO, "Current CPU speed: %uHz\n", Rate)); + } + + LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mProcessorInfoType4, mProcessorInfoType4Strings, NULL); +} + +/*********************************************************************** + SMBIOS data update TYPE7 Cache Information +************************************************************************/ +VOID +CacheInfoUpdateSmbiosType7 ( + VOID + ) +{ + LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mCacheInfoType7, mCacheInfoType7Strings, NULL); +} + +/*********************************************************************** + SMBIOS data update TYPE9 System Slot Information +************************************************************************/ +VOID +SysSlotInfoUpdateSmbiosType9 ( + VOID + ) +{ + LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mSysSlotInfoType9, mSysSlotInfoType9Strings, NULL); +} + +/*********************************************************************** + SMBIOS data update TYPE16 Physical Memory Array Information +************************************************************************/ +VOID +PhyMemArrayInfoUpdateSmbiosType16 ( + VOID + ) +{ + EFI_SMBIOS_HANDLE MemArraySmbiosHande; + + LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mPhyMemArrayInfoType16, mPhyMemArrayInfoType16Strings, &MemArraySmbiosHande); + + // + // Update the memory device information + // + mMemDevInfoType17.MemoryArrayHandle = MemArraySmbiosHande; +} + +/*********************************************************************** + SMBIOS data update TYPE17 Memory Device Information +************************************************************************/ +VOID +MemDevInfoUpdateSmbiosType17 ( + VOID + ) +{ + LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mMemDevInfoType17, mMemDevInfoType17Strings, NULL); +} + +/*********************************************************************** + SMBIOS data update TYPE19 Memory Array Map Information +************************************************************************/ +VOID +MemArrMapInfoUpdateSmbiosType19 ( + VOID + ) +{ + EFI_STATUS Status; + UINT32 Base; + UINT32 Size; + + Status = mFwProtocol->GetArmMem(&Base, &Size); + if (Status != EFI_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Couldn't get the ARM memory size: %r\n", Status)); + } else { + mMemArrMapInfoType19.StartingAddress = Base / 1024; + mMemArrMapInfoType19.EndingAddress = (Base + Size - 1) / 1024; + } + + LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mMemArrMapInfoType19, mMemArrMapInfoType19Strings, NULL); +} + + +/*********************************************************************** + SMBIOS data update TYPE32 Boot Information +************************************************************************/ +VOID +BootInfoUpdateSmbiosType32 ( + VOID + ) +{ + LogSmbiosData ((EFI_SMBIOS_TABLE_HEADER *)&mBootInfoType32, mBootInfoType32Strings, NULL); +} + +/*********************************************************************** + Driver Entry +************************************************************************/ +EFI_STATUS +EFIAPI +PlatformSmbiosDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid, NULL, + (VOID **)&mFwProtocol); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + BIOSInfoUpdateSmbiosType0(); + + SysInfoUpdateSmbiosType1(); + + BoardInfoUpdateSmbiosType2(); + + EnclosureInfoUpdateSmbiosType3(); + + ProcessorInfoUpdateSmbiosType4 (4); //One example for creating and updating + + CacheInfoUpdateSmbiosType7(); + + SysSlotInfoUpdateSmbiosType9(); + + PhyMemArrayInfoUpdateSmbiosType16(); + + MemDevInfoUpdateSmbiosType17(); + + MemArrMapInfoUpdateSmbiosType19(); + + BootInfoUpdateSmbiosType32(); + + return EFI_SUCCESS; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf new file mode 100644 index 000000000000..ada4c3fc228d --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf @@ -0,0 +1,56 @@ +#/** @file +# +# SMBIOS Table for ARM platform +# +# Copyright (c) 2017, Andrei Warkentin +# Copyright (c) Microsoft Corporation. All rights reserved. +# Copyright (c) 2013 Linaro.org +# +# 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 = PlatformSmbiosDxe + FILE_GUID = BAD0554E-22E9-4D83-9AFD-CC87727A1A45 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PlatformSmbiosDriverEntryPoint + +[Sources] + PlatformSmbiosDxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + ArmPkg/ArmPkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiLib + UefiDriverEntryPoint + DebugLib + PrintLib + +[Protocols] + gEfiSmbiosProtocolGuid # PROTOCOL SOMETIMES_CONSUMED + gRaspberryPiFirmwareProtocolGuid ## CONSUMES +[Guids] + +[Depex] + gEfiSmbiosProtocolGuid AND gRaspberryPiFirmwareProtocolGuid + +[Pcd] + gArmTokenSpaceGuid.PcdSystemMemorySize diff --git a/Platform/Broadcom/Bcm283x/Drivers/RpiFdtDxe/RpiFdtDxe.c b/Platform/Broadcom/Bcm283x/Drivers/RpiFdtDxe/RpiFdtDxe.c new file mode 100644 index 000000000000..f2b0117629fd --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/RpiFdtDxe/RpiFdtDxe.c @@ -0,0 +1,370 @@ +/** @file + * + * Copyright (c) 2017, Andrey Warkentin + * Copyright (c) 2016, Linaro, 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 + +#include + +#include + +STATIC VOID *mFdtImage; + +STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol; + +STATIC +VOID +UpdateMacAddress ( + VOID + ) +{ + INTN Node; + INTN Retval; + EFI_STATUS Status; + UINT8 MacAddress[6]; + + // + // Locate the node that the 'ethernet' alias refers to + // + Node = fdt_path_offset(mFdtImage, "ethernet"); + if (Node < 0) { + DEBUG ((DEBUG_ERROR, "%a: failed to locate 'ethernet' alias\n", + __FUNCTION__)); + return; + } + + // + // Get the MAC address from the firmware + // + Status = mFwProtocol->GetMacAddress (MacAddress); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: failed to retrieve MAC address\n", __FUNCTION__)); + return; + } + + Retval = fdt_setprop (mFdtImage, Node, "mac-address", MacAddress, + sizeof MacAddress); + if (Retval != 0) { + DEBUG ((DEBUG_ERROR, "%a: failed to create 'mac-address' property (%d)\n", + __FUNCTION__, Retval)); + return; + } + + DEBUG ((DEBUG_INFO, + "%a: setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, MacAddress[0], MacAddress[1], MacAddress[2], MacAddress[3], + MacAddress[4], MacAddress[5])); +} + +STATIC +VOID +CleanMemoryNodes ( + VOID + ) +{ + INTN Node; + INT32 Retval; + + Node = fdt_path_offset(mFdtImage, "/memory"); + if (Node < 0) { + return; + } + + /* + * Remove bogus memory nodes which can make the booted + * OS go crazy and ignore the UEFI map. + */ + DEBUG ((DEBUG_INFO, "Removing bogus /memory\n")); + Retval = fdt_del_node(mFdtImage, Node); + if (Retval != 0) { + DEBUG ((DEBUG_ERROR, "Failed to remove /memory\n")); + } +} + +STATIC +VOID +SanitizePSCI ( + VOID + ) +{ + INTN Node; + INTN Root; + INT32 Retval; + + Root = fdt_path_offset(mFdtImage, "/"); + ASSERT (Root >= 0); + if (Root < 0) { + return; + } + + Node = fdt_path_offset(mFdtImage, "/psci"); + if (Node < 0) { + Node = fdt_add_subnode(mFdtImage, Root, "psci"); + } + + ASSERT (Node >= 0); + if (Node < 0) { + DEBUG ((DEBUG_ERROR, "Couldn't find/create /psci\n")); + return; + } + + Retval = fdt_setprop_string(mFdtImage, Node, "compatible", + "arm,psci-1.0"); + if (Retval != 0) { + DEBUG ((DEBUG_ERROR, "Couldn't set /psci compatible property\n")); + return; + } + + Retval = fdt_setprop_string(mFdtImage, Node, "method", "smc"); + if (Retval != 0) { + DEBUG ((DEBUG_ERROR, "Couldn't set /psci method property\n")); + return; + } + + Root = fdt_path_offset(mFdtImage, "/cpus"); + if (Root < 0) { + DEBUG ((DEBUG_ERROR, "No CPUs to update with PSCI enable-method?\n")); + return; + } + + Node = fdt_first_subnode(mFdtImage, Root); + while (Node >= 0) { + if (fdt_setprop_string(mFdtImage, Node, "enable-method", "psci") != 0) { + DEBUG ((DEBUG_ERROR, "Failed to update enable-method for a CPU\n")); + return; + } + + fdt_delprop(mFdtImage, Node, "cpu-release-addr"); + Node = fdt_next_subnode(mFdtImage, Node); + } +} + +STATIC +VOID +CleanSimpleFramebuffer ( + VOID + ) +{ + INTN Node; + INT32 Retval; + + /* + * Should look for nodes by kind and remove aliases + * by matching against device. + */ + Node = fdt_path_offset(mFdtImage, "display0"); + if (Node < 0) { + return; + } + + /* + * Remove bogus GPU-injected simple-framebuffer, which + * doesn't reflect the framebuffer built by UEFI. + */ + DEBUG ((DEBUG_INFO, "Removing bogus display0\n")); + Retval = fdt_del_node(mFdtImage, Node); + if (Retval != 0) { + DEBUG ((DEBUG_ERROR, "Failed to remove display0\n")); + return; + } + + Node = fdt_path_offset(mFdtImage, "/aliases"); + if (Node < 0) { + DEBUG ((DEBUG_ERROR, "Couldn't find /aliases to remove display0\n")); + return; + } + + Retval = fdt_delprop(mFdtImage, Node, "display0"); + if (Retval != 0) { + DEBUG ((DEBUG_ERROR, "Failed to remove display0 alias\n")); + } +} + +#define MAX_CMDLINE_SIZE 512 + +STATIC +VOID +UpdateBootArgs ( + VOID + ) +{ + INTN Node; + INTN Retval; + EFI_STATUS Status; + CHAR8 *CommandLine; + + // + // Locate the /chosen node + // + Node = fdt_path_offset(mFdtImage, "/chosen"); + if (Node < 0) { + DEBUG ((DEBUG_ERROR, "%a: failed to locate /chosen node\n", + __FUNCTION__)); + return; + } + + // + // If /chosen/bootargs already exists, we want to add a space character + // before adding the firmware supplied arguments. However, the RpiFirmware + // protocol expects a 32-bit aligned buffer. So let's allocate 4 bytes of + // slack, and skip the first 3 when passing this buffer into libfdt. + // + CommandLine = AllocatePool (MAX_CMDLINE_SIZE) + 4; + if (!CommandLine) { + DEBUG ((DEBUG_ERROR, "%a: failed to allocate memory\n", __FUNCTION__)); + return; + } + + // + // Get the command line from the firmware + // + Status = mFwProtocol->GetCommandLine (MAX_CMDLINE_SIZE, CommandLine + 4); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: failed to retrieve command line\n", + __FUNCTION__)); + return; + } + + if (AsciiStrLen (CommandLine + 4) == 0) { + DEBUG ((DEBUG_INFO, "%a: empty command line received\n", __FUNCTION__)); + return; + } + + CommandLine[3] = ' '; + + Retval = fdt_appendprop_string (mFdtImage, Node, "bootargs", &CommandLine[3]); + if (Retval != 0) { + DEBUG ((DEBUG_ERROR, "%a: failed to set /chosen/bootargs property (%d)\n", + __FUNCTION__, Retval)); + } + + DEBUG_CODE_BEGIN (); + CONST CHAR8 *Prop; + INT32 Length; + INT32 Index; + + Node = fdt_path_offset (mFdtImage, "/chosen"); + ASSERT (Node >= 0); + + Prop = fdt_getprop (mFdtImage, Node, "bootargs", &Length); + ASSERT (Prop != NULL); + + DEBUG ((DEBUG_INFO, "Command line set from firmware (length %d):\n'", Length)); + + for (Index = 0; Index < Length; Index++, Prop++) { + if (*Prop == '\0') { + continue; + } + DEBUG ((DEBUG_INFO, "%c", *Prop)); + } + + DEBUG ((DEBUG_INFO, "'\n")); + DEBUG_CODE_END (); + + FreePool (CommandLine - 4); +} + + +/** + @param ImageHandle of the loaded driver + @param SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Protocol registered + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure + @retval EFI_DEVICE_ERROR Hardware problems + +**/ +EFI_STATUS +EFIAPI +RpiFdtDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + VOID *FdtImage; + UINTN FdtSize; + INT32 Retval; + BOOLEAN Internal; + + Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid, NULL, + (VOID **)&mFwProtocol); + ASSERT_EFI_ERROR (Status); + + Internal = FALSE; + FdtImage = (VOID *) (UINTN) PcdGet32(PcdFdtBaseAddress); + Retval = fdt_check_header (FdtImage); + if (Retval == 0) { + /* + * Have FDT passed via config.txt. + */ + FdtSize = fdt_totalsize (FdtImage); + DEBUG ((DEBUG_INFO, "DTB passed via config.txt of 0x%lx bytes\n", FdtSize)); + Status = EFI_SUCCESS; + } else { + Internal = TRUE; + DEBUG ((DEBUG_INFO, "No/bad FDT at %p (%a), trying internal DTB...\n", + FdtImage, fdt_strerror (Retval))); + Status = GetSectionFromAnyFv (&gRaspberryPiFdtFileGuid, EFI_SECTION_RAW, 0, + &FdtImage, &FdtSize); + if (Status == EFI_SUCCESS) { + if (fdt_check_header (FdtImage) != 0) { + Status = EFI_INCOMPATIBLE_VERSION; + } + } + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to locate device tree: %r\n", Status)); + return Status; + } + + /* + * Probably overkill. + */ + FdtSize += EFI_PAGE_SIZE * 2; + Status = gBS->AllocatePages (AllocateAnyPages, EfiRuntimeServicesData, + EFI_SIZE_TO_PAGES(FdtSize), + (EFI_PHYSICAL_ADDRESS *) &mFdtImage); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to allocate new device tree: %r\n", Status)); + return Status; + } + + Retval = fdt_open_into (FdtImage, mFdtImage, FdtSize); + ASSERT (Retval == 0); + + SanitizePSCI (); + CleanMemoryNodes (); + CleanSimpleFramebuffer (); + UpdateMacAddress (); + if (Internal) { + /* + * A GPU-provided DTB already has the full command line. + */ + UpdateBootArgs (); + } + + DEBUG ((DEBUG_INFO, "Installed FDT is at %p\n", mFdtImage)); + Status = gBS->InstallConfigurationTable (&gFdtTableGuid, mFdtImage); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/RpiFdtDxe/RpiFdtDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/RpiFdtDxe/RpiFdtDxe.inf new file mode 100644 index 000000000000..a79e9ddcdc8a --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/RpiFdtDxe/RpiFdtDxe.inf @@ -0,0 +1,53 @@ +#/** @file +# +# Copyright (c) 2017, Andrei Warkentin +# Copyright (c) 2016, Linaro, 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 = 0x00010019 + BASE_NAME = RpiFdtDxe + FILE_GUID = 8505280f-109e-437e-9fe4-1aa09c7074d9 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = RpiFdtDxeInitialize + +[Sources] + RpiFdtDxe.c + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + DxeServicesLib + FdtLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Guids] + gFdtTableGuid + gRaspberryPiFdtFileGuid + +[Protocols] + gRaspberryPiFirmwareProtocolGuid ## CONSUMES + +[Depex] + gRaspberryPiFirmwareProtocolGuid + +[FixedPcd] + gRaspberryPiTokenSpaceGuid.PcdFdtBaseAddress diff --git a/Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c b/Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c new file mode 100644 index 000000000000..50f3ed3f1e36 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c @@ -0,0 +1,1085 @@ +/** @file + * + * Copyright (c) 2017-2018, Andrei Warkentin + * Copyright (c) 2016, Linaro, 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 +#include +#include +#include + +#include +#include + +#include + +// +// The number of statically allocated buffer pages +// +#define NUM_PAGES 1 + +// +// The number of iterations to perform when waiting for the mailbox +// status to change +// +#define MAX_TRIES 0x100000 + +STATIC VOID *mDmaBuffer; +STATIC VOID *mDmaBufferMapping; +STATIC UINTN mDmaBufferBusAddress; + +STATIC SPIN_LOCK mMailboxLock; + +STATIC +BOOLEAN +DrainMailbox ( + VOID + ) +{ + INTN Tries; + UINT32 Val; + + // + // Get rid of stale response data in the mailbox + // + Tries = 0; + do { + Val = MmioRead32 (BCM2836_MBOX_BASE_ADDRESS + BCM2836_MBOX_STATUS_OFFSET); + if (Val & (1U << BCM2836_MBOX_STATUS_EMPTY)) { + return TRUE; + } + ArmDataSynchronizationBarrier (); + MmioRead32 (BCM2836_MBOX_BASE_ADDRESS + BCM2836_MBOX_READ_OFFSET); + } while (++Tries < MAX_TRIES); + + return FALSE; +} + +STATIC +BOOLEAN +MailboxWaitForStatusCleared ( + IN UINTN StatusMask + ) +{ + INTN Tries; + UINT32 Val; + + // + // Get rid of stale response data in the mailbox + // + Tries = 0; + do { + Val = MmioRead32 (BCM2836_MBOX_BASE_ADDRESS + BCM2836_MBOX_STATUS_OFFSET); + if ((Val & StatusMask) == 0) { + return TRUE; + } + ArmDataSynchronizationBarrier (); + } while (++Tries < MAX_TRIES); + + return FALSE; +} + +STATIC +EFI_STATUS +MailboxTransaction ( + IN UINTN Length, + IN UINTN Channel, + OUT UINT32 *Result + ) +{ + if (Channel >= BCM2836_MBOX_NUM_CHANNELS) { + return EFI_INVALID_PARAMETER; + } + + // + // Get rid of stale response data in the mailbox + // + if (!DrainMailbox ()) { + DEBUG ((DEBUG_ERROR, "%a: timeout waiting for mailbox to drain\n", + __FUNCTION__)); + return EFI_TIMEOUT; + } + + // + // Wait for the 'output register full' bit to become clear + // + if (!MailboxWaitForStatusCleared (1U << BCM2836_MBOX_STATUS_FULL)) { + DEBUG ((DEBUG_ERROR, "%a: timeout waiting for outbox to become empty\n", + __FUNCTION__)); + return EFI_TIMEOUT; + } + + ArmDataSynchronizationBarrier (); + + // + // Start the mailbox transaction + // + MmioWrite32 (BCM2836_MBOX_BASE_ADDRESS + BCM2836_MBOX_WRITE_OFFSET, + (UINT32)((UINTN)mDmaBufferBusAddress | Channel)); + + ArmDataSynchronizationBarrier (); + + // + // Wait for the 'input register empty' bit to clear + // + if (!MailboxWaitForStatusCleared (1U << BCM2836_MBOX_STATUS_EMPTY)) { + DEBUG ((DEBUG_ERROR, "%a: timeout waiting for inbox to become full\n", + __FUNCTION__)); + return EFI_TIMEOUT; + } + + // + // Read back the result + // + ArmDataSynchronizationBarrier (); + *Result = MmioRead32 (BCM2836_MBOX_BASE_ADDRESS + BCM2836_MBOX_READ_OFFSET); + ArmDataSynchronizationBarrier (); + + return EFI_SUCCESS; +} + +#pragma pack(1) +typedef struct { + UINT32 BufferSize; + UINT32 Response; +} RPI_FW_BUFFER_HEAD; + +typedef struct { + UINT32 TagId; + UINT32 TagSize; + UINT32 TagValueSize; +} RPI_FW_TAG_HEAD; + +typedef struct { + UINT32 DeviceId; + UINT32 PowerState; +} RPI_FW_POWER_STATE_TAG; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD TagHead; + RPI_FW_POWER_STATE_TAG TagBody; + UINT32 EndTag; +} RPI_FW_SET_POWER_STATE_CMD; +#pragma pack() + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareSetPowerState ( + IN UINT32 DeviceId, + IN BOOLEAN PowerState, + IN BOOLEAN Wait + ) +{ + RPI_FW_SET_POWER_STATE_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd); + + Cmd->BufferHead.BufferSize = sizeof *Cmd; + Cmd->BufferHead.Response = 0; + Cmd->TagHead.TagId = RPI_FW_SET_POWER_STATE; + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; + Cmd->TagHead.TagValueSize = 0; + Cmd->TagBody.DeviceId = DeviceId; + Cmd->TagBody.PowerState = (PowerState ? RPI_FW_POWER_STATE_ENABLE : 0) | + (Wait ? RPI_FW_POWER_STATE_WAIT : 0); + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + Status = EFI_DEVICE_ERROR; + } + + if (!EFI_ERROR (Status) && + PowerState ^ (Cmd->TagBody.PowerState & RPI_FW_POWER_STATE_ENABLE)) { + DEBUG ((DEBUG_ERROR, "%a: failed to %sable power for device %d\n", + __FUNCTION__, PowerState ? "en" : "dis", DeviceId)); + Status = EFI_DEVICE_ERROR; + } + + return Status; +} + +#pragma pack() +typedef struct { + UINT32 Base; + UINT32 Size; +} RPI_FW_ARM_MEMORY_TAG; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD TagHead; + RPI_FW_ARM_MEMORY_TAG TagBody; + UINT32 EndTag; +} RPI_FW_GET_ARM_MEMORY_CMD; +#pragma pack() + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetArmMemory ( + OUT UINT32 *Base, + OUT UINT32 *Size + ) +{ + RPI_FW_GET_ARM_MEMORY_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd); + + Cmd->BufferHead.BufferSize = sizeof *Cmd; + Cmd->BufferHead.Response = 0; + Cmd->TagHead.TagId = RPI_FW_GET_ARM_MEMSIZE; + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + return EFI_DEVICE_ERROR; + } + + *Base = Cmd->TagBody.Base; + *Size = Cmd->TagBody.Size; + return EFI_SUCCESS; +} + +#pragma pack() +typedef struct { + UINT8 MacAddress[6]; + UINT32 Padding; +} RPI_FW_MAC_ADDR_TAG; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD TagHead; + RPI_FW_MAC_ADDR_TAG TagBody; + UINT32 EndTag; +} RPI_FW_GET_MAC_ADDR_CMD; +#pragma pack() + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetMacAddress ( + OUT UINT8 MacAddress[6] + ) +{ + RPI_FW_GET_MAC_ADDR_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd); + + Cmd->BufferHead.BufferSize = sizeof *Cmd; + Cmd->BufferHead.Response = 0; + Cmd->TagHead.TagId = RPI_FW_GET_MAC_ADDRESS; + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + return EFI_DEVICE_ERROR; + } + + CopyMem (MacAddress, Cmd->TagBody.MacAddress, sizeof Cmd->TagBody.MacAddress); + return EFI_SUCCESS; +} + +#pragma pack() +typedef struct { + UINT64 Serial; +} RPI_FW_SERIAL_TAG; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD TagHead; + RPI_FW_SERIAL_TAG TagBody; + UINT32 EndTag; +} RPI_FW_GET_SERIAL_CMD; +#pragma pack() + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetSerial ( + OUT UINT64 *Serial + ) +{ + RPI_FW_GET_SERIAL_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd); + + Cmd->BufferHead.BufferSize = sizeof *Cmd; + Cmd->BufferHead.Response = 0; + Cmd->TagHead.TagId = RPI_FW_GET_BOARD_SERIAL; + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + return EFI_DEVICE_ERROR; + } + + *Serial = Cmd->TagBody.Serial; + return EFI_SUCCESS; +} + +#pragma pack() +typedef struct { + UINT32 Model; +} RPI_FW_MODEL_TAG; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD TagHead; + RPI_FW_MODEL_TAG TagBody; + UINT32 EndTag; +} RPI_FW_GET_MODEL_CMD; +#pragma pack() + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetModel ( + OUT UINT32 *Model + ) +{ + RPI_FW_GET_MODEL_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd); + + Cmd->BufferHead.BufferSize = sizeof *Cmd; + Cmd->BufferHead.Response = 0; + Cmd->TagHead.TagId = RPI_FW_GET_BOARD_MODEL; + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + return EFI_DEVICE_ERROR; + } + + *Model = Cmd->TagBody.Model; + return EFI_SUCCESS; +} + +#pragma pack() +typedef struct { + UINT32 Revision; +} RPI_FW_MODEL_REVISION_TAG; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD TagHead; + RPI_FW_MODEL_REVISION_TAG TagBody; + UINT32 EndTag; +} RPI_FW_GET_MODEL_REVISION_CMD; +#pragma pack() + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetModelRevision ( + OUT UINT32 *Revision + ) +{ + RPI_FW_GET_MODEL_REVISION_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd); + + Cmd->BufferHead.BufferSize = sizeof *Cmd; + Cmd->BufferHead.Response = 0; + Cmd->TagHead.TagId = RPI_FW_GET_BOARD_REVISION; + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + return EFI_DEVICE_ERROR; + } + + *Revision = Cmd->TagBody.Revision; + return EFI_SUCCESS; +} + +#pragma pack() +typedef struct { + UINT32 Width; + UINT32 Height; +} RPI_FW_FB_SIZE_TAG; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD TagHead; + RPI_FW_FB_SIZE_TAG TagBody; + UINT32 EndTag; +} RPI_FW_GET_FB_SIZE_CMD; + +typedef struct { + UINT32 Depth; +} RPI_FW_FB_DEPTH_TAG; + +typedef struct { + UINT32 Pitch; +} RPI_FW_FB_PITCH_TAG; + +typedef struct { + UINT32 AlignmentBase; + UINT32 Size; +} RPI_FW_FB_ALLOC_TAG; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD FreeFbTag; + UINT32 EndTag; +} RPI_FW_FREE_FB_CMD; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD PhysSizeTag; + RPI_FW_FB_SIZE_TAG PhysSize; + RPI_FW_TAG_HEAD VirtSizeTag; + RPI_FW_FB_SIZE_TAG VirtSize; + RPI_FW_TAG_HEAD DepthTag; + RPI_FW_FB_DEPTH_TAG Depth; + RPI_FW_TAG_HEAD AllocFbTag; + RPI_FW_FB_ALLOC_TAG AllocFb; + RPI_FW_TAG_HEAD PitchTag; + RPI_FW_FB_PITCH_TAG Pitch; + UINT32 EndTag; +} RPI_FW_INIT_FB_CMD; +#pragma pack() + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetFbSize ( + OUT UINT32 *Width, + OUT UINT32 *Height + ) +{ + RPI_FW_GET_FB_SIZE_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd); + + Cmd->BufferHead.BufferSize = sizeof *Cmd; + Cmd->BufferHead.Response = 0; + Cmd->TagHead.TagId = RPI_FW_GET_FB_GEOMETRY; + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + return EFI_DEVICE_ERROR; + } + + *Width = Cmd->TagBody.Width; + *Height = Cmd->TagBody.Height; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareFreeFb (VOID) +{ + RPI_FW_FREE_FB_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd); + + Cmd->BufferHead.BufferSize = sizeof *Cmd; + Cmd->BufferHead.Response = 0; + + Cmd->FreeFbTag.TagId = RPI_FW_FREE_FB; + Cmd->FreeFbTag.TagSize = 0; + Cmd->FreeFbTag.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareAllocFb ( + IN UINT32 Width, + IN UINT32 Height, + IN UINT32 Depth, + OUT EFI_PHYSICAL_ADDRESS *FbBase, + OUT UINTN *FbSize, + OUT UINTN *Pitch) +{ + RPI_FW_INIT_FB_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + ASSERT (FbSize != NULL); + ASSERT (FbBase != NULL); + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd); + + Cmd->BufferHead.BufferSize = sizeof *Cmd; + Cmd->BufferHead.Response = 0; + + Cmd->PhysSizeTag.TagId = RPI_FW_SET_FB_PGEOM; + Cmd->PhysSizeTag.TagSize = sizeof Cmd->PhysSize; + Cmd->PhysSize.Width = Width; + Cmd->PhysSize.Height = Height; + Cmd->VirtSizeTag.TagId = RPI_FW_SET_FB_VGEOM; + Cmd->VirtSizeTag.TagSize = sizeof Cmd->VirtSize; + Cmd->VirtSize.Width = Width; + Cmd->VirtSize.Height = Height; + Cmd->DepthTag.TagId = RPI_FW_SET_FB_DEPTH; + Cmd->DepthTag.TagSize = sizeof Cmd->Depth; + Cmd->Depth.Depth = Depth; + Cmd->AllocFbTag.TagId = RPI_FW_ALLOC_FB; + Cmd->AllocFbTag.TagSize = sizeof Cmd->AllocFb; + Cmd->AllocFb.AlignmentBase = 32; + Cmd->PitchTag.TagId = RPI_FW_GET_FB_LINELENGTH; + Cmd->PitchTag.TagSize = sizeof Cmd->Pitch; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + return EFI_DEVICE_ERROR; + } + + *Pitch = Cmd->Pitch.Pitch; + *FbBase = Cmd->AllocFb.AlignmentBase - BCM2836_DMA_DEVICE_OFFSET; + *FbSize = Cmd->AllocFb.Size; + return EFI_SUCCESS; +} + +#pragma pack() +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD TagHead; + UINT8 CommandLine[0]; +} RPI_FW_GET_COMMAND_LINE_CMD; +#pragma pack() + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetCommmandLine ( + IN UINTN BufferSize, + OUT CHAR8 CommandLine[] + ) +{ + RPI_FW_GET_COMMAND_LINE_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if ((BufferSize % sizeof (UINT32)) != 0) { + DEBUG ((DEBUG_ERROR, "%a: BufferSize must be a multiple of 4\n", + __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + if (sizeof *Cmd + BufferSize > EFI_PAGES_TO_SIZE (NUM_PAGES)) { + DEBUG ((DEBUG_ERROR, "%a: BufferSize exceeds size of DMA buffer\n", + __FUNCTION__)); + return EFI_OUT_OF_RESOURCES; + } + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd + BufferSize + sizeof (UINT32)); + + Cmd->BufferHead.BufferSize = sizeof *Cmd + BufferSize + sizeof (UINT32); + Cmd->BufferHead.Response = 0; + Cmd->TagHead.TagId = RPI_FW_GET_COMMAND_LINE; + Cmd->TagHead.TagSize = BufferSize; + Cmd->TagHead.TagValueSize = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + return EFI_DEVICE_ERROR; + } + + Cmd->TagHead.TagValueSize &= ~RPI_FW_VALUE_SIZE_RESPONSE_MASK; + if (Cmd->TagHead.TagValueSize >= BufferSize && + Cmd->CommandLine[Cmd->TagHead.TagValueSize - 1] != '\0') { + DEBUG ((DEBUG_ERROR, "%a: insufficient buffer size\n", __FUNCTION__)); + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (CommandLine, Cmd->CommandLine, Cmd->TagHead.TagValueSize); + + if (CommandLine[Cmd->TagHead.TagValueSize - 1] != '\0') { + // + // Add a NUL terminator if required. + // + CommandLine[Cmd->TagHead.TagValueSize] = '\0'; + } + + return EFI_SUCCESS; +} + +#pragma pack() +typedef struct { + UINT32 ClockId; + UINT32 ClockRate; + UINT32 SkipTurbo; +} RPI_FW_SET_CLOCK_RATE_TAG; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD TagHead; + RPI_FW_SET_CLOCK_RATE_TAG TagBody; + UINT32 EndTag; +} RPI_FW_SET_CLOCK_RATE_CMD; +#pragma pack() + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareSetClockRate ( + IN UINT32 ClockId, + IN UINT32 ClockRate + ) +{ + RPI_FW_SET_CLOCK_RATE_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd); + + Cmd->BufferHead.BufferSize = sizeof *Cmd; + Cmd->BufferHead.Response = 0; + Cmd->TagHead.TagId = RPI_FW_SET_CLOCK_RATE, + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; + Cmd->TagHead.TagValueSize = 0; + Cmd->TagBody.ClockId = ClockId; + Cmd->TagBody.ClockRate = ClockRate; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + + +#pragma pack() +typedef struct { + UINT32 ClockId; + UINT32 ClockRate; +} RPI_FW_CLOCK_RATE_TAG; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD TagHead; + RPI_FW_CLOCK_RATE_TAG TagBody; + UINT32 EndTag; +} RPI_FW_GET_CLOCK_RATE_CMD; +#pragma pack() + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetClockRate ( + IN UINT32 ClockId, + IN UINT32 ClockKind, + OUT UINT32 *ClockRate + ) +{ + RPI_FW_GET_CLOCK_RATE_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd); + + Cmd->BufferHead.BufferSize = sizeof *Cmd; + Cmd->BufferHead.Response = 0; + Cmd->TagHead.TagId = ClockKind, + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; + Cmd->TagHead.TagValueSize = 0; + Cmd->TagBody.ClockId = ClockId; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + return EFI_DEVICE_ERROR; + } + + *ClockRate = Cmd->TagBody.ClockRate; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetCurrentClockRate ( + IN UINT32 ClockId, + OUT UINT32 *ClockRate + ) +{ + return RpiFirmwareGetClockRate(ClockId, RPI_FW_GET_CLOCK_RATE, ClockRate); +} + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetMaxClockRate ( + IN UINT32 ClockId, + OUT UINT32 *ClockRate + ) +{ + return RpiFirmwareGetClockRate(ClockId, RPI_FW_GET_MAX_CLOCK_RATE, ClockRate); +} + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetMinClockRate ( + IN UINT32 ClockId, + OUT UINT32 *ClockRate + ) +{ + return RpiFirmwareGetClockRate(ClockId, RPI_FW_GET_MIN_CLOCK_RATE, ClockRate); +} + +#pragma pack() +typedef struct { + UINT32 Pin; + UINT32 State; +} RPI_FW_SET_GPIO_TAG; + +typedef struct { + RPI_FW_BUFFER_HEAD BufferHead; + RPI_FW_TAG_HEAD TagHead; + RPI_FW_SET_GPIO_TAG TagBody; + UINT32 EndTag; +} RPI_FW_SET_GPIO_CMD; +#pragma pack() + +STATIC +VOID +RpiFirmwareLedSet ( + IN BOOLEAN On + ) +{ + RPI_FW_SET_GPIO_CMD *Cmd; + EFI_STATUS Status; + UINT32 Result; + + if (!AcquireSpinLockOrFail (&mMailboxLock)) { + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); + return; + } + + Cmd = mDmaBuffer; + ZeroMem (Cmd, sizeof *Cmd); + + Cmd->BufferHead.BufferSize = sizeof *Cmd; + Cmd->BufferHead.Response = 0; + Cmd->TagHead.TagId = RPI_FW_SET_GPIO; + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; + /* + * GPIO_PIN_2 = Activity LED + * GPIO_PIN_4 = HDMI Detect (Input / Active Low) + * GPIO_PIN_7 = Power LED (Input / Active Low) + * + * There's also a 128 pin offset. + */ + Cmd->TagBody.Pin = 128 + 2; + Cmd->TagBody.State = On; + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { + DEBUG ((DEBUG_ERROR, + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", + __FUNCTION__, Status, Cmd->BufferHead.Response)); + } +} + +STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL mRpiFirmwareProtocol = { + RpiFirmwareSetPowerState, + RpiFirmwareGetMacAddress, + RpiFirmwareGetCommmandLine, + RpiFirmwareGetCurrentClockRate, + RpiFirmwareGetMaxClockRate, + RpiFirmwareGetMinClockRate, + RpiFirmwareSetClockRate, + RpiFirmwareAllocFb, + RpiFirmwareFreeFb, + RpiFirmwareGetFbSize, + RpiFirmwareLedSet, + RpiFirmwareGetSerial, + RpiFirmwareGetModel, + RpiFirmwareGetModelRevision, + RpiFirmwareGetArmMemory +}; + +/** + Initialize the state information for the CPU Architectural Protocol + + @param ImageHandle of the loaded driver + @param SystemTable Pointer to the System Table + + @retval EFI_SUCCESS Protocol registered + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure + @retval EFI_DEVICE_ERROR Hardware problems + +**/ +EFI_STATUS +RpiFirmwareDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + + // + // We only need one of these + // + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gRaspberryPiFirmwareProtocolGuid); + + InitializeSpinLock (&mMailboxLock); + + Status = DmaAllocateBuffer (EfiBootServicesData, NUM_PAGES, &mDmaBuffer); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: failed to allocate DMA buffer (Status == %r)\n", + __FUNCTION__)); + return Status; + } + + BufferSize = EFI_PAGES_TO_SIZE (NUM_PAGES); + Status = DmaMap (MapOperationBusMasterCommonBuffer, mDmaBuffer, &BufferSize, + &mDmaBufferBusAddress, &mDmaBufferMapping); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: failed to map DMA buffer (Status == %r)\n", + __FUNCTION__)); + goto FreeBuffer; + } + + // + // The channel index is encoded in the low bits of the bus address, + // so make sure these are cleared. + // + ASSERT (!(mDmaBufferBusAddress & (BCM2836_MBOX_NUM_CHANNELS - 1))); + + Status = gBS->InstallProtocolInterface (&ImageHandle, + &gRaspberryPiFirmwareProtocolGuid, EFI_NATIVE_INTERFACE, + &mRpiFirmwareProtocol); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a: failed to install RPI firmware protocol (Status == %r)\n", + __FUNCTION__, Status)); + goto UnmapBuffer; + } + + return EFI_SUCCESS; + +UnmapBuffer: + DmaUnmap (mDmaBufferMapping); +FreeBuffer: + DmaFreeBuffer (NUM_PAGES, mDmaBuffer); + + return Status; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf new file mode 100644 index 000000000000..2ab57bbf54f0 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf @@ -0,0 +1,49 @@ +#/** @file +# +# Copyright (c) 2017-2018, Andrei Warkentin +# Copyright (c) 2016, Linaro, 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 = 0x00010019 + BASE_NAME = RpiFirmwareDxe + FILE_GUID = 6d4628df-49a0-4b67-a325-d5af35c65745 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = RpiFirmwareDxeInitialize + +[Sources] + RpiFirmwareDxe.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + ArmLib + BaseLib + BaseMemoryLib + DebugLib + DmaLib + IoLib + SynchronizationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + +[Protocols] + gRaspberryPiFirmwareProtocolGuid ## PRODUCES + +[Depex] + TRUE diff --git a/Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.c b/Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.c new file mode 100644 index 000000000000..7dd76098c8a1 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.c @@ -0,0 +1,830 @@ +/** @file + * + * Copyright (c) 2017, Andrei Warkentin + * Copyright (c) Microsoft Corporation. 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 +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define SDHOST_BLOCK_BYTE_LENGTH 512 + +// Driver Timing Parameters +#define CMD_STALL_AFTER_POLL_US 1 +#define CMD_MIN_POLL_TOTAL_TIME_US 100000 // 100ms +#define CMD_MAX_POLL_COUNT (CMD_MIN_POLL_TOTAL_TIME_US / CMD_STALL_AFTER_POLL_US) +#define CMD_MAX_RETRY_COUNT 3 +#define CMD_STALL_AFTER_RETRY_US 20 // 20us +#define FIFO_MAX_POLL_COUNT 1000000 +#define STALL_TO_STABILIZE_US 10000 // 10ms + +#define IDENT_MODE_SD_CLOCK_FREQ_HZ 400000 // 400KHz + +// Macros adopted from MmcDxe internal header +#define SDHOST_R0_READY_FOR_DATA BIT8 +#define SDHOST_R0_CURRENTSTATE(Response) ((Response >> 9) & 0xF) + +#define DEBUG_MMCHOST_SD DEBUG_VERBOSE +#define DEBUG_MMCHOST_SD_INFO DEBUG_INFO +#define DEBUG_MMCHOST_SD_ERROR DEBUG_ERROR + +STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol; + +// Per Physical Layer Simplified Specs +#ifndef NDEBUG +STATIC CONST CHAR8* mStrSdState[] = { "idle", "ready", "ident", "stby", + "tran", "data", "rcv", "prg", "dis", + "ina" }; +STATIC CONST CHAR8 *mFsmState[] = { "identmode", "datamode", "readdata", + "writedata", "readwait", "readcrc", + "writecrc", "writewait1", "powerdown", + "powerup", "writestart1", "writestart2", + "genpulses", "writewait2", "?", + "startpowdown" }; +#endif /* NDEBUG */ +STATIC UINT32 mLastGoodCmd = MMC_GET_INDX(MMC_CMD0); + +STATIC inline BOOLEAN +IsAppCmd( + VOID + ) +{ + return mLastGoodCmd == MMC_CMD55; +} + +STATIC BOOLEAN +IsBusyCmd( + IN UINT32 MmcCmd + ) +{ + if (IsAppCmd()) { + return FALSE; + } + + return MmcCmd == MMC_CMD7 || MmcCmd == MMC_CMD12; +} + +STATIC BOOLEAN +IsWriteCmd( + IN UINT32 MmcCmd + ) +{ + if (IsAppCmd()) { + return FALSE; + } + + return MmcCmd == MMC_CMD24 || MmcCmd == MMC_CMD25; +} + +STATIC BOOLEAN +IsReadCmd( + IN UINT32 MmcCmd, + IN UINT32 Argument + ) +{ + if (MmcCmd == MMC_CMD8 && !IsAppCmd()) { + if (Argument == CMD8_MMC_ARG) { + DEBUG((DEBUG_MMCHOST_SD, "Sending MMC CMD8 variant\n")); + return TRUE; + } else { + ASSERT (Argument == CMD8_SD_ARG); + DEBUG((DEBUG_MMCHOST_SD, "Sending SD CMD8 variant\n")); + return FALSE; + } + } + + return + (MmcCmd == MMC_CMD6 && !IsAppCmd()) || + (MmcCmd == MMC_CMD17 && !IsAppCmd()) || + (MmcCmd == MMC_CMD18 && !IsAppCmd()) || + (MmcCmd == MMC_CMD13 && IsAppCmd()) || + (MmcCmd == MMC_ACMD22 && IsAppCmd()) || + (MmcCmd == MMC_ACMD51 && IsAppCmd()); +} + +STATIC VOID +SdHostDumpRegisters( + VOID + ) +{ + DEBUG((DEBUG_MMCHOST_SD, "SdHost: Registers Dump:\n")); + DEBUG((DEBUG_MMCHOST_SD, " CMD: 0x%8.8X\n", MmioRead32(SDHOST_CMD))); + DEBUG((DEBUG_MMCHOST_SD, " ARG: 0x%8.8X\n", MmioRead32(SDHOST_ARG))); + DEBUG((DEBUG_MMCHOST_SD, " TOUT: 0x%8.8X\n", MmioRead32(SDHOST_TOUT))); + DEBUG((DEBUG_MMCHOST_SD, " CDIV: 0x%8.8X\n", MmioRead32(SDHOST_CDIV))); + DEBUG((DEBUG_MMCHOST_SD, " RSP0: 0x%8.8X\n", MmioRead32(SDHOST_RSP0))); + DEBUG((DEBUG_MMCHOST_SD, " RSP1: 0x%8.8X\n", MmioRead32(SDHOST_RSP1))); + DEBUG((DEBUG_MMCHOST_SD, " RSP2: 0x%8.8X\n", MmioRead32(SDHOST_RSP2))); + DEBUG((DEBUG_MMCHOST_SD, " RSP3: 0x%8.8X\n", MmioRead32(SDHOST_RSP3))); + DEBUG((DEBUG_MMCHOST_SD, " HSTS: 0x%8.8X\n", MmioRead32(SDHOST_HSTS))); + DEBUG((DEBUG_MMCHOST_SD, " VDD: 0x%8.8X\n", MmioRead32(SDHOST_VDD))); + DEBUG((DEBUG_MMCHOST_SD, " EDM: 0x%8.8X\n", MmioRead32(SDHOST_EDM))); + DEBUG((DEBUG_MMCHOST_SD, " HCFG: 0x%8.8X\n", MmioRead32(SDHOST_HCFG))); + DEBUG((DEBUG_MMCHOST_SD, " HBCT: 0x%8.8X\n", MmioRead32(SDHOST_HBCT))); + DEBUG((DEBUG_MMCHOST_SD, " HBLC: 0x%8.8X\n\n", MmioRead32(SDHOST_HBLC))); +} + +#ifndef NDEBUG +STATIC EFI_STATUS +SdHostGetSdStatus( + UINT32* SdStatus + ) +{ + ASSERT(SdStatus != NULL); + + // On command completion with R1 or R1b response type + // the SDCard status will be in RSP0 + UINT32 Rsp0 = MmioRead32(SDHOST_RSP0); + if (Rsp0 != 0xFFFFFFFF) { + *SdStatus = Rsp0; + return EFI_SUCCESS; + } + + return EFI_NO_RESPONSE; +} +#endif /* NDEBUG */ + +STATIC VOID +SdHostDumpSdCardStatus( + VOID + ) +{ +#ifndef NDEBUG + UINT32 SdCardStatus; + EFI_STATUS Status = SdHostGetSdStatus(&SdCardStatus); + if (!EFI_ERROR(Status)) { + UINT32 CurrState = SDHOST_R0_CURRENTSTATE(SdCardStatus); + DEBUG(( + DEBUG_MMCHOST_SD, + "SdHost: SdCardStatus 0x%8.8X: ReadyForData?%d, State[%d]: %a\n", + SdCardStatus, + ((SdCardStatus & SDHOST_R0_READY_FOR_DATA) ? 1 : 0), + CurrState, + ((CurrState < (sizeof(mStrSdState) / sizeof(*mStrSdState))) ? + mStrSdState[CurrState] : "UNDEF"))); + } +#endif /* NDEBUG */ +} + +STATIC VOID +SdHostDumpStatus( + VOID + ) +{ + SdHostDumpRegisters(); + +#ifndef NDEBUG + UINT32 Hsts = MmioRead32(SDHOST_HSTS); + + if (Hsts & SDHOST_HSTS_ERROR) { + DEBUG((DEBUG_MMCHOST_SD_ERROR, + "SdHost: Diagnose HSTS: 0x%8.8X\n", Hsts)); + + DEBUG((DEBUG_MMCHOST_SD_ERROR, "SdHost: Last Good CMD = %u\n", + MMC_GET_INDX(mLastGoodCmd))); + if (Hsts & SDHOST_HSTS_FIFO_ERROR) + DEBUG((DEBUG_MMCHOST_SD_ERROR, " - Fifo Error\n")); + if (Hsts & SDHOST_HSTS_CRC7_ERROR) + DEBUG((DEBUG_MMCHOST_SD_ERROR, " - CRC7 Error\n")); + if (Hsts & SDHOST_HSTS_CRC16_ERROR) + DEBUG((DEBUG_MMCHOST_SD_ERROR, " - CRC16 Error\n")); + if (Hsts & SDHOST_HSTS_CMD_TIME_OUT) + DEBUG((DEBUG_MMCHOST_SD_ERROR, " - CMD Timeout (TOUT %x)\n", + MmioRead32(SDHOST_TOUT))); + if (Hsts & SDHOST_HSTS_REW_TIME_OUT) + DEBUG((DEBUG_MMCHOST_SD_ERROR, " - Read/Erase/Write Transfer Timeout\n")); + } + + UINT32 Edm = MmioRead32(SDHOST_EDM); + DEBUG(((Hsts & SDHOST_HSTS_ERROR) ? + DEBUG_MMCHOST_SD_ERROR : DEBUG_MMCHOST_SD, + "SdHost: Diagnose EDM: 0x%8.8X\n", Edm)); + DEBUG(((Hsts & SDHOST_HSTS_ERROR) ? + DEBUG_MMCHOST_SD_ERROR : DEBUG_MMCHOST_SD, + " - FSM: 0x%x (%a)\n", (Edm & 0xF), mFsmState[Edm & 0xF])); + DEBUG(((Hsts & SDHOST_HSTS_ERROR) ? + DEBUG_MMCHOST_SD_ERROR : DEBUG_MMCHOST_SD, + " - Fifo Count: %d\n", ((Edm >> 4) & 0x1F))); + DEBUG(((Hsts & SDHOST_HSTS_ERROR) ? + DEBUG_MMCHOST_SD_ERROR : DEBUG_MMCHOST_SD, + " - Fifo Write Threshold: %d\n", + ((Edm >> SDHOST_EDM_WRITE_THRESHOLD_SHIFT) & + SDHOST_EDM_THRESHOLD_MASK))); + DEBUG(((Hsts & SDHOST_HSTS_ERROR) ? + DEBUG_MMCHOST_SD_ERROR : DEBUG_MMCHOST_SD, + " - Fifo Read Threshold: %d\n", + ((Edm >> SDHOST_EDM_READ_THRESHOLD_SHIFT) & SDHOST_EDM_THRESHOLD_MASK))); +#endif + + SdHostDumpSdCardStatus(); +} + +STATIC EFI_STATUS +SdHostSetClockFrequency( + IN UINTN TargetSdFreqHz + ) +{ + EFI_STATUS Status; + UINT32 CoreClockFreqHz = 0; + + // First figure out the core clock + Status = mFwProtocol->GetClockRate(RPI_FW_CLOCK_RATE_CORE, &CoreClockFreqHz); + if (EFI_ERROR(Status)) { + return Status; + } + + ASSERT (CoreClockFreqHz != 0); + + // fSDCLK = fcore_pclk/(ClockDiv+2) + UINT32 ClockDiv = (CoreClockFreqHz - (2 * TargetSdFreqHz)) / TargetSdFreqHz; + UINT32 ActualSdFreqHz = CoreClockFreqHz / (ClockDiv + 2); + + DEBUG(( + DEBUG_MMCHOST_SD_INFO, + "SdHost: CoreClock=%dHz, CDIV=%d, Requested SdClock=%dHz, Actual SdClock=%dHz\n", + CoreClockFreqHz, + ClockDiv, + TargetSdFreqHz, + ActualSdFreqHz)); + + MmioWrite32(SDHOST_CDIV, ClockDiv); + // Set timeout after 1 second, i.e ActualSdFreqHz SD clock cycles + MmioWrite32(SDHOST_TOUT, ActualSdFreqHz); + + gBS->Stall(STALL_TO_STABILIZE_US); + + return Status; +} + +STATIC BOOLEAN +SdIsCardPresent( + IN EFI_MMC_HOST_PROTOCOL *This + ) +{ + return TRUE; +} + +STATIC BOOLEAN +SdIsReadOnly( + IN EFI_MMC_HOST_PROTOCOL *This + ) +{ + return FALSE; +} + +STATIC EFI_STATUS +SdBuildDevicePath( + IN EFI_MMC_HOST_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode; + EFI_GUID DevicePathGuid = EFI_CALLER_ID_GUID; + + DEBUG((DEBUG_MMCHOST_SD, "SdHost: SdBuildDevicePath()\n")); + + NewDevicePathNode = CreateDeviceNode(HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof(VENDOR_DEVICE_PATH)); + CopyGuid(&((VENDOR_DEVICE_PATH*)NewDevicePathNode)->Guid, &DevicePathGuid); + *DevicePath = NewDevicePathNode; + + return EFI_SUCCESS; +} + +STATIC EFI_STATUS +SdSendCommand( + IN EFI_MMC_HOST_PROTOCOL *This, + IN MMC_CMD MmcCmd, + IN UINT32 Argument + ) +{ + UINT32 Hsts; + + // + // Fail fast, CMD5 (CMD_IO_SEND_OP_COND) + // is only valid for SDIO cards and thus + // expected to always fail. + // + if (MmcCmd == MMC_CMD5) { + DEBUG(( + DEBUG_MMCHOST_SD, + "SdHost: SdSendCommand(CMD%d, Argument: %08x) ignored\n", + MMC_GET_INDX(MmcCmd), + Argument)); + return EFI_UNSUPPORTED; + } + + if (MmioRead32(SDHOST_CMD) & SDHOST_CMD_NEW_FLAG) { + DEBUG(( + DEBUG_MMCHOST_SD_ERROR, + "SdHost: SdSendCommand(): Failed to execute CMD%d, a CMD is already being executed.\n", + MMC_GET_INDX(MmcCmd))); + SdHostDumpStatus(); + return EFI_DEVICE_ERROR; + } + + // Write command argument + MmioWrite32(SDHOST_ARG, Argument); + + UINT32 SdCmd = 0; + { + // Set response type + if (MmcCmd & MMC_CMD_WAIT_RESPONSE) { + if (MmcCmd & MMC_CMD_LONG_RESPONSE) { + SdCmd |= SDHOST_CMD_RESPONSE_CMD_LONG_RESP; + } + } else { + SdCmd |= SDHOST_CMD_RESPONSE_CMD_NO_RESP; + } + + if (IsBusyCmd(MmcCmd)) { + SdCmd |= SDHOST_CMD_BUSY_CMD; + } + + if (IsReadCmd(MmcCmd, Argument)) { + SdCmd |= SDHOST_CMD_READ_CMD; + } + + if (IsWriteCmd(MmcCmd)) { + SdCmd |= SDHOST_CMD_WRITE_CMD; + } + + SdCmd |= MMC_GET_INDX(MmcCmd); + } + + if (IsReadCmd(MmcCmd, Argument) || IsWriteCmd(MmcCmd)) { + if (IsAppCmd() && MmcCmd == MMC_ACMD22) { + MmioWrite32(SDHOST_HBCT, 0x4); + } else if (IsAppCmd() && MmcCmd == MMC_ACMD51) { + MmioWrite32(SDHOST_HBCT, 0x8); + } else if (!IsAppCmd() && MmcCmd == MMC_CMD6) { + MmioWrite32(SDHOST_HBCT, 0x40); + } else { + MmioWrite32(SDHOST_HBCT, SDHOST_BLOCK_BYTE_LENGTH); + } + } + + DEBUG(( + DEBUG_MMCHOST_SD, + "SdHost: SdSendCommand(CMD%d, Argument: %08x): BUSY=%d, RESP=%d, WRITE=%d, READ=%d\n", + MMC_GET_INDX(MmcCmd), + Argument, + ((SdCmd & SDHOST_CMD_BUSY_CMD) ? 1 : 0), + ((SdCmd & (SDHOST_CMD_RESPONSE_CMD_LONG_RESP | SDHOST_CMD_RESPONSE_CMD_NO_RESP)) >> 9), + ((SdCmd & SDHOST_CMD_WRITE_CMD) ? 1 : 0), + ((SdCmd & SDHOST_CMD_READ_CMD) ? 1 : 0))); + + UINT32 PollCount = 0; + UINT32 RetryCount = 0; + BOOLEAN IsCmdExecuted = FALSE; + EFI_STATUS Status = EFI_SUCCESS; + + // Keep retrying the command until it succeeds. + while ((RetryCount < CMD_MAX_RETRY_COUNT) && !IsCmdExecuted) { + Status = EFI_SUCCESS; + + // Clear prev cmd status + MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_CLEAR); + + if (IsReadCmd(MmcCmd, Argument) || IsWriteCmd(MmcCmd)) { + // Flush Fifo if this cmd will start a new transfer in case + // there is stale bytes in the Fifo + MmioOr32(SDHOST_EDM, SDHOST_EDM_FIFO_CLEAR); + } + + if (MmioRead32(SDHOST_CMD) & SDHOST_CMD_NEW_FLAG) { + DEBUG(( + DEBUG_MMCHOST_SD_ERROR, + "%a(%u): CMD%d is still being executed after %d trial(s)\n", + __FUNCTION__, __LINE__, MMC_GET_INDX(MmcCmd), RetryCount)); + } + + // Write command and set it to start execution + MmioWrite32(SDHOST_CMD, SDHOST_CMD_NEW_FLAG | SdCmd); + + // Poll for the command status until it finishes execution + while (PollCount < CMD_MAX_POLL_COUNT) { + UINT32 CmdReg = MmioRead32(SDHOST_CMD); + + // Read status of command response + if (CmdReg & SDHOST_CMD_FAIL_FLAG) { + Status = EFI_DEVICE_ERROR; + /* + * Must fall-through and wait for the command completion! + */ + } + + // Check if command is completed. + if (!(CmdReg & SDHOST_CMD_NEW_FLAG)) { + IsCmdExecuted = TRUE; + break; + } + + ++PollCount; + gBS->Stall(CMD_STALL_AFTER_POLL_US); + } + + if (!IsCmdExecuted) { + ++RetryCount; + gBS->Stall(CMD_STALL_AFTER_RETRY_US); + } + } + + if (RetryCount == CMD_MAX_RETRY_COUNT) { + Status = EFI_TIMEOUT; + } + + Hsts = MmioRead32(SDHOST_HSTS); + if (EFI_ERROR(Status) || + (Hsts & SDHOST_HSTS_ERROR) != 0) { + if (MmcCmd == MMC_CMD1 && + (Hsts & SDHOST_HSTS_CRC7_ERROR) != 0) { + /* + * SdHost seems to have no way to specify + * R3 as a transfer type. + */ + IsCmdExecuted = TRUE; + Status = EFI_SUCCESS; + MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_CLEAR); + } else if (MmcCmd == MMC_CMD7 && Argument == 0) { + /* + * Deselecting the SDCard with CMD7 and RCA=0x0 + * always timeout on SDHost. + */ + Status = EFI_SUCCESS; + } else { + DEBUG(( + DEBUG_MMCHOST_SD_ERROR, + "%a(%u): CMD%d execution failed after %d trial(s)\n", + __FUNCTION__, __LINE__, + MMC_GET_INDX(MmcCmd), + RetryCount)); + SdHostDumpStatus(); + } + + MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_CLEAR); + } + + if (IsCmdExecuted && !EFI_ERROR(Status)) { + ASSERT(!(MmioRead32(SDHOST_HSTS) & SDHOST_HSTS_ERROR)); + mLastGoodCmd = MmcCmd; + } + + return Status; +} + +STATIC EFI_STATUS +SdReceiveResponse( + IN EFI_MMC_HOST_PROTOCOL *This, + IN MMC_RESPONSE_TYPE Type, + IN UINT32* Buffer + ) +{ + if (Buffer == NULL) { + DEBUG((DEBUG_MMCHOST_SD_ERROR, + "SdHost: SdReceiveResponse(): Input Buffer is NULL\n")); + return EFI_INVALID_PARAMETER; + } + + if ((Type == MMC_RESPONSE_TYPE_R1) || + (Type == MMC_RESPONSE_TYPE_R1b) || + (Type == MMC_RESPONSE_TYPE_R3) || + (Type == MMC_RESPONSE_TYPE_R6) || + (Type == MMC_RESPONSE_TYPE_R7)) { + Buffer[0] = MmioRead32(SDHOST_RSP0); + DEBUG(( + DEBUG_MMCHOST_SD, + "SdHost: SdReceiveResponse(Type: %x), Buffer[0]: %08x\n", + Type, Buffer[0])); + + } else if (Type == MMC_RESPONSE_TYPE_R2) { + Buffer[0] = MmioRead32(SDHOST_RSP0); + Buffer[1] = MmioRead32(SDHOST_RSP1); + Buffer[2] = MmioRead32(SDHOST_RSP2); + Buffer[3] = MmioRead32(SDHOST_RSP3); + + DEBUG(( + DEBUG_MMCHOST_SD, + "SdHost: SdReceiveResponse(Type: %x), Buffer[0-3]: %08x, %08x, %08x, %08x\n", + Type, Buffer[0], Buffer[1], Buffer[2], Buffer[3])); + } + + return EFI_SUCCESS; +} + +STATIC EFI_STATUS +SdReadBlockData( + IN EFI_MMC_HOST_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Length, + IN UINT32* Buffer + ) +{ + DEBUG(( + DEBUG_MMCHOST_SD, + "SdHost: SdReadBlockData(LBA: 0x%x, Length: 0x%x, Buffer: 0x%x)\n", + (UINT32)Lba, Length, Buffer)); + + ASSERT(Buffer != NULL); + ASSERT(Length % 4 == 0); + + EFI_STATUS Status = EFI_SUCCESS; + + mFwProtocol->SetLed(TRUE); + { + UINT32 NumWords = Length / 4; + UINT32 WordIdx; + + for (WordIdx = 0; WordIdx < NumWords; ++WordIdx) { + UINT32 PollCount = 0; + while (PollCount < FIFO_MAX_POLL_COUNT) { + UINT32 Hsts = MmioRead32(SDHOST_HSTS); + if ((Hsts & SDHOST_HSTS_DATA_FLAG) != 0) { + MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_DATA_FLAG); + Buffer[WordIdx] = MmioRead32(SDHOST_DATA); + break; + } + + ++PollCount; + gBS->Stall(CMD_STALL_AFTER_RETRY_US); + } + + if (PollCount == FIFO_MAX_POLL_COUNT) { + DEBUG( + (DEBUG_MMCHOST_SD_ERROR, + "SdHost: SdReadBlockData(): Block Word%d read poll timed-out\n", + WordIdx)); + SdHostDumpStatus(); + MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_CLEAR); + Status = EFI_TIMEOUT; + break; + } + } + } + mFwProtocol->SetLed(FALSE); + + return Status; +} + +STATIC EFI_STATUS +SdWriteBlockData( + IN EFI_MMC_HOST_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Length, + IN UINT32* Buffer + ) +{ + DEBUG(( + DEBUG_MMCHOST_SD, + "SdHost: SdWriteBlockData(LBA: 0x%x, Length: 0x%x, Buffer: 0x%x)\n", + (UINT32)Lba, Length, Buffer)); + + ASSERT(Buffer != NULL); + ASSERT(Length % SDHOST_BLOCK_BYTE_LENGTH == 0); + + EFI_STATUS Status = EFI_SUCCESS; + + mFwProtocol->SetLed(TRUE); + { + UINT32 NumWords = Length / 4; + UINT32 WordIdx; + + for (WordIdx = 0; WordIdx < NumWords; ++WordIdx) { + UINT32 PollCount = 0; + while (PollCount < FIFO_MAX_POLL_COUNT) { + if (MmioRead32(SDHOST_HSTS) & SDHOST_HSTS_DATA_FLAG) { + MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_DATA_FLAG); + MmioWrite32(SDHOST_DATA, Buffer[WordIdx]); + break; + } + + ++PollCount; + gBS->Stall(CMD_STALL_AFTER_RETRY_US); + } + + if (PollCount == FIFO_MAX_POLL_COUNT) { + DEBUG(( + DEBUG_MMCHOST_SD_ERROR, + "SdHost: SdWriteBlockData(): Block Word%d write poll timed-out\n", + WordIdx)); + SdHostDumpStatus(); + MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_CLEAR); + Status = EFI_TIMEOUT; + break; + } + } + } + mFwProtocol->SetLed(FALSE); + + return Status; +} + +STATIC EFI_STATUS +SdSetIos ( + IN EFI_MMC_HOST_PROTOCOL *This, + IN UINT32 BusClockFreq, + IN UINT32 BusWidth, + IN UINT32 TimingMode + ) +{ + if (BusWidth != 0) { + UINT32 Hcfg = MmioRead32(SDHOST_HCFG); + + DEBUG((DEBUG_MMCHOST_SD_INFO, "Setting BusWidth %u\n", BusWidth)); + if (BusWidth == 4) { + Hcfg |= SDHOST_HCFG_WIDE_EXT_BUS; + } else { + Hcfg &= ~SDHOST_HCFG_WIDE_EXT_BUS; + } + + Hcfg |= SDHOST_HCFG_WIDE_INT_BUS | SDHOST_HCFG_SLOW_CARD; + MmioWrite32(SDHOST_HCFG, Hcfg); + } + + if (BusClockFreq != 0) { + DEBUG((DEBUG_MMCHOST_SD_INFO, "Setting Freq %u Hz\n", BusClockFreq)); + SdHostSetClockFrequency(BusClockFreq); + } + + return EFI_SUCCESS; +} + +STATIC EFI_STATUS +SdNotifyState( + IN EFI_MMC_HOST_PROTOCOL *This, + IN MMC_STATE State + ) +{ + DEBUG((DEBUG_MMCHOST_SD, "SdHost: SdNotifyState(State: %d) ", State)); + + switch (State) { + case MmcHwInitializationState: + { + DEBUG((DEBUG_MMCHOST_SD, "MmcHwInitializationState\n", State)); + + // Turn-off SD Card power + MmioWrite32(SDHOST_VDD, 0); + { + // Reset command and arg + MmioWrite32(SDHOST_CMD, 0); + MmioWrite32(SDHOST_ARG, 0); + // Reset clock divider + MmioWrite32(SDHOST_CDIV, 0); + // Default timeout + MmioWrite32(SDHOST_TOUT, 0xffffffff); + // Clear status flags + MmioWrite32(SDHOST_HSTS, SDHOST_HSTS_CLEAR);; + // Reset controller configs + MmioWrite32(SDHOST_HCFG, 0); + MmioWrite32(SDHOST_HBCT, 0); + MmioWrite32(SDHOST_HBLC, 0); + + gBS->Stall(STALL_TO_STABILIZE_US); + } + // Turn-on SD Card power + MmioWrite32(SDHOST_VDD, 1); + + gBS->Stall(STALL_TO_STABILIZE_US); + + // Write controller configs + UINT32 Hcfg = 0; + Hcfg |= SDHOST_HCFG_WIDE_INT_BUS; + Hcfg |= SDHOST_HCFG_SLOW_CARD; // Use all bits of CDIV in DataMode + MmioWrite32(SDHOST_HCFG, Hcfg); + + // Set default clock frequency + EFI_STATUS Status = SdHostSetClockFrequency(IDENT_MODE_SD_CLOCK_FREQ_HZ); + if (EFI_ERROR(Status)) { + DEBUG(( + DEBUG_MMCHOST_SD_ERROR, + "SdHost: SdNotifyState(): Fail to initialize SD clock to %dHz\n", + IDENT_MODE_SD_CLOCK_FREQ_HZ)); + SdHostDumpStatus(); + return Status; + } + } + break; + case MmcIdleState: + DEBUG((DEBUG_MMCHOST_SD, "MmcIdleState\n", State)); + break; + case MmcReadyState: + DEBUG((DEBUG_MMCHOST_SD, "MmcReadyState\n", State)); + break; + case MmcIdentificationState: + DEBUG((DEBUG_MMCHOST_SD, "MmcIdentificationState\n", State)); + break; + case MmcStandByState: + DEBUG((DEBUG_MMCHOST_SD, "MmcStandByState\n", State)); + break; + case MmcTransferState: + DEBUG((DEBUG_MMCHOST_SD, "MmcTransferState\n", State)); + break; + break; + case MmcSendingDataState: + DEBUG((DEBUG_MMCHOST_SD, "MmcSendingDataState\n", State)); + break; + case MmcReceiveDataState: + DEBUG((DEBUG_MMCHOST_SD, "MmcReceiveDataState\n", State)); + break; + case MmcProgrammingState: + DEBUG((DEBUG_MMCHOST_SD, "MmcProgrammingState\n", State)); + break; + case MmcDisconnectState: + case MmcInvalidState: + default: + DEBUG((DEBUG_MMCHOST_SD_ERROR, + "SdHost: SdNotifyState(): Invalid State: %d\n", State)); + ASSERT(0); + } + + return EFI_SUCCESS; +} + +BOOLEAN +SdIsMultiBlock ( + IN EFI_MMC_HOST_PROTOCOL *This + ) +{ + return TRUE; +} + +EFI_MMC_HOST_PROTOCOL gMmcHost = + { + MMC_HOST_PROTOCOL_REVISION, + SdIsCardPresent, + SdIsReadOnly, + SdBuildDevicePath, + SdNotifyState, + SdSendCommand, + SdReceiveResponse, + SdReadBlockData, + SdWriteBlockData, + SdSetIos, + SdIsMultiBlock + }; + +EFI_STATUS +SdHostInitialize( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle = NULL; + + if (PcdGet32 (PcdSdIsArasan)) { + DEBUG((DEBUG_INFO, "SD is not routed to SdHost\n")); + return EFI_REQUEST_UNLOAD_IMAGE; + } + + Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid, NULL, + (VOID **)&mFwProtocol); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG((DEBUG_MMCHOST_SD, "SdHost: Initialize\n")); + DEBUG((DEBUG_MMCHOST_SD, "Config:\n")); + DEBUG((DEBUG_MMCHOST_SD, " - FIFO_MAX_POLL_COUNT=%d\n", FIFO_MAX_POLL_COUNT)); + DEBUG((DEBUG_MMCHOST_SD, " - CMD_STALL_AFTER_POLL_US=%dus\n", CMD_STALL_AFTER_POLL_US)); + DEBUG((DEBUG_MMCHOST_SD, " - CMD_MIN_POLL_TOTAL_TIME_US=%dms\n", CMD_MIN_POLL_TOTAL_TIME_US / 1000)); + DEBUG((DEBUG_MMCHOST_SD, " - CMD_MAX_POLL_COUNT=%d\n", CMD_MAX_POLL_COUNT)); + DEBUG((DEBUG_MMCHOST_SD, " - CMD_MAX_RETRY_COUNT=%d\n", CMD_MAX_RETRY_COUNT)); + DEBUG((DEBUG_MMCHOST_SD, " - CMD_STALL_AFTER_RETRY_US=%dus\n", CMD_STALL_AFTER_RETRY_US)); + + Status = gBS->InstallMultipleProtocolInterfaces( + &Handle, + &gRaspberryPiMmcHostProtocolGuid, &gMmcHost, + NULL + ); + ASSERT_EFI_ERROR(Status); + return Status; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.inf new file mode 100644 index 000000000000..3469b4611cc9 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.inf @@ -0,0 +1,54 @@ +#/** @file +# +# Copyright (c) 2017, Andrei Warkentin +# Copyright (c) Microsoft Corporation. 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 = SdHost + FILE_GUID = 58ABD787-F64D-4CA2-A034-B9AC2D5AD0CF + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = SdHostInitialize + + +[Sources.common] + SdHostDxe.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + PcdLib + UefiLib + UefiDriverEntryPoint + MemoryAllocationLib + IoLib + DmaLib + CacheMaintenanceLib + +[Guids] + +[Protocols] + gRaspberryPiMmcHostProtocolGuid ## PRODUCES + gRaspberryPiFirmwareProtocolGuid ## CONSUMES + +[Pcd] + gRaspberryPiTokenSpaceGuid.PcdSdIsArasan + +[Depex] + gRaspberryPiFirmwareProtocolGuid AND gRaspberryPiConfigAppliedProtocolGuid diff --git a/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/FileIo.c b/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/FileIo.c new file mode 100644 index 000000000000..961de586c78b --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/FileIo.c @@ -0,0 +1,196 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) 2007-2009, Intel Corporation. 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 "VarBlockService.h" + + +EFI_STATUS +FileWrite ( + IN EFI_FILE_PROTOCOL *File, + IN UINTN Offset, + IN UINTN Buffer, + IN UINTN Size + ) +{ + EFI_STATUS Status; + + Status = File->SetPosition (File, Offset); + ASSERT_EFI_ERROR (Status); + if (!EFI_ERROR (Status)) { + Status = File->Write (File, &Size, (VOID *) Buffer); + ASSERT_EFI_ERROR (Status); + } + return Status; +} + + +VOID +FileClose ( + IN EFI_FILE_PROTOCOL *File + ) +{ + File->Flush (File); + File->Close (File); +} + + +EFI_STATUS +FileOpen ( + IN EFI_DEVICE_PATH_PROTOCOL *Device, + IN CHAR16 *MappedFile, + OUT EFI_FILE_PROTOCOL **File, + IN UINT64 OpenMode + ) +{ + EFI_HANDLE Handle; + EFI_FILE_HANDLE Root; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; + EFI_STATUS Status; + + *File = NULL; + + Status = gBS->LocateDevicePath ( + &gEfiSimpleFileSystemProtocolGuid, + &Device, + &Handle + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->HandleProtocol ( + Handle, + &gEfiSimpleFileSystemProtocolGuid, + (void **) &Volume + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Open the root directory of the volume + // + Root = NULL; + Status = Volume->OpenVolume ( + Volume, + &Root + ); + ASSERT_EFI_ERROR (Status); + ASSERT (Root != NULL); + + // + // Open file + // + Status = Root->Open ( + Root, + File, + MappedFile, + OpenMode, + 0 + ); + if (EFI_ERROR (Status)) { + *File = NULL; + } + + // + // Close the Root directory + // + Root->Close (Root); + return Status; +} + + +EFI_STATUS +CheckStore ( + IN EFI_HANDLE SimpleFileSystemHandle, + OUT EFI_DEVICE_PATH_PROTOCOL **Device + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + EFI_FILE_PROTOCOL *File; + + *Device = NULL; + Status = gBS->HandleProtocol ( + SimpleFileSystemHandle, + &gEfiBlockIoProtocolGuid, + (VOID*)&BlkIo + ); + + if (EFI_ERROR (Status)) { + goto ErrHandle; + } + if (!BlkIo->Media->MediaPresent) { + DEBUG ((DEBUG_ERROR, "FwhMappedFile: Media not present!\n")); + Status = EFI_NO_MEDIA; + goto ErrHandle; + } + if (BlkIo->Media->ReadOnly) { + DEBUG ((DEBUG_ERROR, "FwhMappedFile: Media is read-only!\n")); + Status = EFI_ACCESS_DENIED; + goto ErrHandle; + } + + Status = FileOpen (DevicePathFromHandle (SimpleFileSystemHandle), + mFvInstance->MappedFile, &File, + EFI_FILE_MODE_READ); + if (EFI_ERROR (Status)) { + goto ErrHandle; + } + + /* We found it! Maybe do more checks...? */ + + FileClose (File); + *Device = DuplicateDevicePath (DevicePathFromHandle (SimpleFileSystemHandle)); + + ASSERT (*Device != NULL); + +ErrHandle: + return Status; +} + + +EFI_STATUS +CheckStoreExists ( + IN EFI_DEVICE_PATH_PROTOCOL *Device + ) +{ + EFI_HANDLE Handle; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; + EFI_STATUS Status; + + Status = gBS->LocateDevicePath ( + &gEfiSimpleFileSystemProtocolGuid, + &Device, + &Handle + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->HandleProtocol ( + Handle, + &gEfiSimpleFileSystemProtocolGuid, + (void **) &Volume + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/FvbInfo.c b/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/FvbInfo.c new file mode 100644 index 000000000000..ddfd746b0eca --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/FvbInfo.c @@ -0,0 +1,118 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) 2006-2014, Intel Corporation. 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 + +typedef struct { + UINT64 FvLength; + EFI_FIRMWARE_VOLUME_HEADER FvbInfo; + // + // EFI_FV_BLOCK_MAP_ENTRY ExtraBlockMap[n];//n=0 + // + EFI_FV_BLOCK_MAP_ENTRY End[1]; +} EFI_FVB_MEDIA_INFO; + +EFI_FVB_MEDIA_INFO mPlatformFvbMediaInfo[] = { + // + // System NvStorage FVB + // + { + FixedPcdGet32 (PcdFlashNvStorageVariableSize) + + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize) + + FixedPcdGet32 (PcdNvStorageEventLogSize), + { + { + 0, + }, // ZeroVector[16] + EFI_SYSTEM_NV_DATA_FV_GUID, + FixedPcdGet32 (PcdFlashNvStorageVariableSize) + + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize) + + FixedPcdGet32 (PcdNvStorageEventLogSize), + EFI_FVH_SIGNATURE, + EFI_FVB2_MEMORY_MAPPED | + EFI_FVB2_READ_ENABLED_CAP | + EFI_FVB2_READ_STATUS | + EFI_FVB2_WRITE_ENABLED_CAP | + EFI_FVB2_WRITE_STATUS | + EFI_FVB2_ERASE_POLARITY | + EFI_FVB2_ALIGNMENT_16, + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY), + 0, // CheckSum + 0, // ExtHeaderOffset + { + 0, + }, // Reserved[1] + 2, // Revision + { + { + (FixedPcdGet32 (PcdFlashNvStorageVariableSize) + + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize) + + FixedPcdGet32 (PcdNvStorageEventLogSize)) / + FixedPcdGet32 (PcdFirmwareBlockSize), + FixedPcdGet32 (PcdFirmwareBlockSize), + } + } // BlockMap[1] + }, + { + { + 0, + 0 + } + } // End[1] + } +}; + + +EFI_STATUS +GetFvbInfo ( + IN UINT64 FvLength, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ) +{ + STATIC BOOLEAN Checksummed = FALSE; + UINTN Index; + + if (!Checksummed) { + for (Index = 0; + Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB_MEDIA_INFO); + Index += 1) { + UINT16 Checksum; + mPlatformFvbMediaInfo[Index].FvbInfo.Checksum = 0; + Checksum = CalculateCheckSum16 ( + (UINT16*) &mPlatformFvbMediaInfo[Index].FvbInfo, + mPlatformFvbMediaInfo[Index].FvbInfo.HeaderLength + ); + mPlatformFvbMediaInfo[Index].FvbInfo.Checksum = Checksum; + } + Checksummed = TRUE; + } + + for (Index = 0; + Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB_MEDIA_INFO); + Index += 1) { + if (mPlatformFvbMediaInfo[Index].FvLength == FvLength) { + *FvbInfo = &mPlatformFvbMediaInfo[Index].FvbInfo; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockService.c b/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockService.c new file mode 100644 index 000000000000..1cea51936ba2 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockService.c @@ -0,0 +1,984 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) 2006 - 2014, Intel Corporation. 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 "VarBlockService.h" + +#define EFI_FVB2_STATUS \ + (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS) + +EFI_FW_VOL_INSTANCE *mFvInstance; + +FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = { + { + { + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + { + (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), + (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) + } + }, + EfiMemoryMappedIO, + (EFI_PHYSICAL_ADDRESS) 0, + (EFI_PHYSICAL_ADDRESS) 0, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = { + { + { + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_VOL_DP, + { + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)), + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8) + } + }, + { 0 } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = { + NULL, + { + FvbProtocolGetAttributes, + FvbProtocolSetAttributes, + FvbProtocolGetPhysicalAddress, + FvbProtocolGetBlockSize, + FvbProtocolRead, + FvbProtocolWrite, + FvbProtocolEraseBlocks, + NULL + } +}; + + +EFI_STATUS +VarStoreWrite ( + IN UINTN Address, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + CopyMem ((VOID *) Address, Buffer, *NumBytes); + mFvInstance->Dirty = TRUE; + + return EFI_SUCCESS; +} + + +EFI_STATUS +VarStoreErase ( + IN UINTN Address, + IN UINTN LbaLength + ) +{ + SetMem ((VOID *)Address, LbaLength, 0xff); + mFvInstance->Dirty = TRUE; + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvbGetVolumeAttributes ( + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + *Attributes = mFvInstance->VolumeHeader->Attributes; + return EFI_SUCCESS; +} + + +EFI_STATUS +FvbGetLbaAddress ( + IN EFI_LBA Lba, + OUT UINTN *LbaAddress, + OUT UINTN *LbaLength, + OUT UINTN *NumOfBlocks + ) +/*++ + + Routine Description: + Retrieves the starting address of an LBA in an FV + + Arguments: + Lba - The logical block address + LbaAddress - On output, contains the physical starting address + of the Lba + LbaLength - On output, contains the length of the block + NumOfBlocks - A pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + +--*/ +{ + UINT32 NumBlocks; + UINT32 BlockLength; + UINTN Offset; + EFI_LBA StartLba; + EFI_LBA NextLba; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + + StartLba = 0; + Offset = 0; + BlockMap = &(mFvInstance->VolumeHeader->BlockMap[0]); + + // + // Parse the blockmap of the FV to find which map entry the Lba belongs to. + // + while (TRUE) { + NumBlocks = BlockMap->NumBlocks; + BlockLength = BlockMap->Length; + + if (NumBlocks == 0 || BlockLength == 0) { + return EFI_INVALID_PARAMETER; + } + + NextLba = StartLba + NumBlocks; + + // + // The map entry found. + // + if (Lba >= StartLba && Lba < NextLba) { + Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength); + if (LbaAddress != NULL) { + *LbaAddress = mFvInstance->FvBase + Offset; + } + + if (LbaLength != NULL) { + *LbaLength = BlockLength; + } + + if (NumOfBlocks != NULL) { + *NumOfBlocks = (UINTN) (NextLba - Lba); + } + + return EFI_SUCCESS; + } + + StartLba = NextLba; + Offset = Offset + NumBlocks * BlockLength; + BlockMap++; + } +} + + +EFI_STATUS +FvbEraseBlock ( + IN EFI_LBA Lba + ) +/*++ + +Routine Description: + Erases and initializes a firmware volume block + +Arguments: + Lba - The logical block index to be erased + +Returns: + EFI_SUCCESS - The erase request was successfully completed + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written. Firmware device may have been + partially erased + EFI_INVALID_PARAMETER + +--*/ +{ + EFI_FVB_ATTRIBUTES_2 Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + + // + // Check if the FV is write enabled + // + FvbGetVolumeAttributes (&Attributes); + + if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + // + // Get the starting address of the block for erase. For debug reasons, + // LbaWriteAddress may not be the same as LbaAddress. + // + Status = FvbGetLbaAddress (Lba, &LbaAddress, &LbaLength, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + return VarStoreErase ( + LbaAddress, + LbaLength + ); +} + + +EFI_STATUS +FvbSetVolumeAttributes ( + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +/*++ + + Routine Description: + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + + Arguments: + Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2 + containing the desired firmware volume settings. + On successful return, it contains the new setting. + + Returns: + EFI_SUCCESS - Successfully returns + EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified + EFI_INVALID_PARAMETER + +--*/ +{ + EFI_FVB_ATTRIBUTES_2 OldAttributes; + EFI_FVB_ATTRIBUTES_2 *AttribPtr; + UINT32 Capabilities; + UINT32 OldStatus; + UINT32 NewStatus; + EFI_FVB_ATTRIBUTES_2 UnchangedAttributes; + + AttribPtr = + (EFI_FVB_ATTRIBUTES_2 *) &(mFvInstance->VolumeHeader->Attributes); + OldAttributes = *AttribPtr; + Capabilities = OldAttributes & (EFI_FVB2_READ_DISABLED_CAP | \ + EFI_FVB2_READ_ENABLED_CAP | \ + EFI_FVB2_WRITE_DISABLED_CAP | \ + EFI_FVB2_WRITE_ENABLED_CAP | \ + EFI_FVB2_LOCK_CAP \ + ); + OldStatus = OldAttributes & EFI_FVB2_STATUS; + NewStatus = *Attributes & EFI_FVB2_STATUS; + + UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP | \ + EFI_FVB2_READ_ENABLED_CAP | \ + EFI_FVB2_WRITE_DISABLED_CAP | \ + EFI_FVB2_WRITE_ENABLED_CAP | \ + EFI_FVB2_LOCK_CAP | \ + EFI_FVB2_STICKY_WRITE | \ + EFI_FVB2_MEMORY_MAPPED | \ + EFI_FVB2_ERASE_POLARITY | \ + EFI_FVB2_READ_LOCK_CAP | \ + EFI_FVB2_WRITE_LOCK_CAP | \ + EFI_FVB2_ALIGNMENT; + + // + // Some attributes of FV is read only can *not* be set. + // + if ((OldAttributes & UnchangedAttributes) ^ + (*Attributes & UnchangedAttributes)) { + return EFI_INVALID_PARAMETER; + } + + // + // If firmware volume is locked, no status bit can be updated. + // + if (OldAttributes & EFI_FVB2_LOCK_STATUS) { + if (OldStatus ^ NewStatus) { + return EFI_ACCESS_DENIED; + } + } + + // + // Test read disable. + // + if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) { + if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test read enable. + // + if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) { + if (NewStatus & EFI_FVB2_READ_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test write disable. + // + if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) { + if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test write enable. + // + if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) { + if (NewStatus & EFI_FVB2_WRITE_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test lock. + // + if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) { + if (NewStatus & EFI_FVB2_LOCK_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS)); + *AttribPtr = (*AttribPtr) | NewStatus; + *Attributes = *AttribPtr; + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + *Address = mFvInstance->FvBase; + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +/*++ + + Routine Description: + Retrieve the size of a logical block + + Arguments: + This - Calling context + Lba - Indicates which block to return the size for. + BlockSize - A pointer to a caller allocated UINTN in which + the size of the block is returned + NumOfBlocks - a pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + + Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + +--*/ +{ + return FvbGetLbaAddress ( + Lba, + NULL, + BlockSize, + NumOfBlocks + ); +} + + +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +/*++ + + Routine Description: + Retrieves Volume attributes. No polarity translations are done. + + Arguments: + This - Calling context + Attributes - output buffer which contains attributes + + Returns: + EFI_SUCCESS - Successfully returns + +--*/ +{ + return FvbGetVolumeAttributes (Attributes); +} + + +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +/*++ + + Routine Description: + Sets Volume attributes. No polarity translations are done. + + Arguments: + This - Calling context + Attributes - output buffer which contains attributes + + Returns: + EFI_SUCCESS - Successfully returns + +--*/ +{ + return FvbSetVolumeAttributes (Attributes); +} + + +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL*This, + ... + ) +/*++ + + Routine Description: + + The EraseBlock() function erases one or more blocks as denoted by the + variable argument list. The entire parameter list of blocks must be + verified prior to erasing any blocks. If a block is requested that does + not exist within the associated firmware volume (it has a larger index than + the last block of the firmware volume), the EraseBlock() function must + return EFI_INVALID_PARAMETER without modifying the contents of the firmware + volume. + + Arguments: + This - Calling context + ... - Starting LBA followed by Number of Lba to erase. + a -1 to terminate the list. + + Returns: + EFI_SUCCESS - The erase request was successfully completed + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written. Firmware device may have been + partially erased + +--*/ +{ + UINTN NumOfBlocks; + VA_LIST args; + EFI_LBA StartingLba; + UINTN NumOfLba; + EFI_STATUS Status; + + NumOfBlocks = mFvInstance->NumOfBlocks; + VA_START (args, This); + + do { + StartingLba = VA_ARG (args, EFI_LBA); + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { + break; + } + + NumOfLba = VA_ARG (args, UINTN); + + if ((NumOfLba == 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) { + VA_END (args); + return EFI_INVALID_PARAMETER; + } + } while (1); + + VA_END (args); + + VA_START (args, This); + do { + StartingLba = VA_ARG (args, EFI_LBA); + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { + break; + } + + NumOfLba = VA_ARG (args, UINTN); + + while (NumOfLba > 0) { + Status = FvbEraseBlock (StartingLba); + if (EFI_ERROR (Status)) { + VA_END (args); + return Status; + } + + StartingLba++; + NumOfLba--; + } + + } while (1); + + VA_END (args); + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + + Routine Description: + + Writes data beginning at Lba:Offset from FV. The write terminates either + when *NumBytes of data have been written, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write opertion does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + + Arguments: + This - Calling context + Lba - Block in which to begin write + Offset - Offset in the block at which to begin write + NumBytes - On input, indicates the requested write size. On + output, indicates the actual number of bytes + written + Buffer - Buffer containing source data for the write. + + Returns: + EFI_SUCCESS - The firmware volume was written successfully + EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes + actually written + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written + EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL + +--*/ +{ + EFI_FVB_ATTRIBUTES_2 Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + + // + // Check for invalid conditions. + // + if ((NumBytes == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (*NumBytes == 0) { + return EFI_INVALID_PARAMETER; + } + + Status = FvbGetLbaAddress (Lba, &LbaAddress, &LbaLength, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check if the FV is write enabled. + // + FvbGetVolumeAttributes (&Attributes); + + if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + + // + // Perform boundary checks and adjust NumBytes. + // + if (Offset > LbaLength) { + return EFI_INVALID_PARAMETER; + } + + if (LbaLength < (*NumBytes + Offset)) { + *NumBytes = (UINT32) (LbaLength - Offset); + Status = EFI_BAD_BUFFER_SIZE; + } + + ReturnStatus = VarStoreWrite ( + LbaAddress + Offset, + NumBytes, + Buffer + ); + if (EFI_ERROR (ReturnStatus)) { + return ReturnStatus; + } + + return Status; +} + + +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + IN CONST UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + + Routine Description: + + Reads data beginning at Lba:Offset from FV. The Read terminates either + when *NumBytes of data have been read, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write opertion does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + + Arguments: + This - Calling context + Lba - Block in which to begin Read + Offset - Offset in the block at which to begin Read + NumBytes - On input, indicates the requested write size. On + output, indicates the actual number of bytes Read + Buffer - Buffer containing source data for the Read. + + Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes + returned in Buffer + EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be read + EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL + +--*/ +{ + EFI_FVB_ATTRIBUTES_2 Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + + // + // Check for invalid conditions. + // + if ((NumBytes == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (*NumBytes == 0) { + return EFI_INVALID_PARAMETER; + } + + Status = FvbGetLbaAddress (Lba, &LbaAddress, &LbaLength, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check if the FV is read enabled. + // + FvbGetVolumeAttributes (&Attributes); + + if ((Attributes & EFI_FVB2_READ_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + + // + // Perform boundary checks and adjust NumBytes. + // + if (Offset > LbaLength) { + return EFI_INVALID_PARAMETER; + } + + if (LbaLength < (*NumBytes + Offset)) { + *NumBytes = (UINT32) (LbaLength - Offset); + Status = EFI_BAD_BUFFER_SIZE; + } + + CopyMem (Buffer, (VOID *) (LbaAddress + Offset), (UINTN) *NumBytes); + + return Status; +} + + +EFI_STATUS +ValidateFvHeader ( + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ) +/*++ + + Routine Description: + Check the integrity of firmware volume header + + Arguments: + FwVolHeader - A pointer to a firmware volume header + + Returns: + EFI_SUCCESS - The firmware volume is consistent + EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an + FV + +--*/ +{ + UINT16 Checksum; + + // + // Verify the header revision, header signature, length + // Length of FvBlock cannot be 2**64-1 + // HeaderLength cannot be an odd number. + // + if ((FwVolHeader->Revision != EFI_FVH_REVISION) || + (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || + (FwVolHeader->FvLength == ((UINTN) -1)) || + ((FwVolHeader->HeaderLength & 0x01) != 0) + ) { + return EFI_NOT_FOUND; + } + + // + // Verify the header checksum. + // + + Checksum = CalculateSum16 ((UINT16 *) FwVolHeader, + FwVolHeader->HeaderLength); + if (Checksum != 0) { + UINT16 Expected; + + Expected = + (UINT16) (((UINTN) FwVolHeader->Checksum + 0x10000 - Checksum) & 0xffff); + + DEBUG ((DEBUG_INFO, "FV@%p Checksum is 0x%x, expected 0x%x\n", + FwVolHeader, FwVolHeader->Checksum, Expected)); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +FvbInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + + Routine Description: + This function does common initialization for FVB services + + Arguments: + + Returns: + +--*/ +{ + EFI_STATUS Status; + UINT32 BufferSize; + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + UINT32 MaxLbaSize; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINTN Length; + UINTN NumOfBlocks; + RETURN_STATUS PcdStatus; + UINTN StartOffset; + + BaseAddress = PcdGet32 (PcdNvStorageVariableBase); + Length = (FixedPcdGet32 (PcdFlashNvStorageVariableSize) + + FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) + + FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize) + + FixedPcdGet32 (PcdNvStorageEventLogSize)); + StartOffset = BaseAddress - FixedPcdGet64 (PcdFdBaseAddress); + + BufferSize = sizeof (EFI_FW_VOL_INSTANCE); + + mFvInstance = AllocateRuntimeZeroPool (BufferSize); + if (mFvInstance == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + mFvInstance->FvBase = (UINTN) BaseAddress; + mFvInstance->FvLength = (UINTN) Length; + mFvInstance->Offset = StartOffset; + /* + * Should I parse config.txt instead and find the real name? + */ + mFvInstance->MappedFile = L"RPI_EFI.FD"; + + Status = ValidateFvHeader (mFvInstance->VolumeHeader); + if (!EFI_ERROR (Status)) { + if (mFvInstance->VolumeHeader->FvLength != Length || + mFvInstance->VolumeHeader->BlockMap[0].Length != + PcdGet32 (PcdFirmwareBlockSize)) { + Status = EFI_VOLUME_CORRUPTED; + } + } + if (EFI_ERROR (Status)) { + EFI_FIRMWARE_VOLUME_HEADER *GoodFwVolHeader; + UINTN WriteLength; + + DEBUG ((DEBUG_INFO, + "Variable FV header is not valid. It will be reinitialized.\n")); + + // + // Get FvbInfo + // + Status = GetFvbInfo (Length, &GoodFwVolHeader); + ASSERT_EFI_ERROR (Status); + + // + // Erase all the blocks + // + Status = VarStoreErase ((UINTN) mFvInstance->FvBase, + mFvInstance->FvLength); + ASSERT_EFI_ERROR (Status); + // + // Write good FV header + // + WriteLength = GoodFwVolHeader->HeaderLength; + Status = VarStoreWrite((UINTN) mFvInstance->FvBase, + &WriteLength, + (UINT8*) GoodFwVolHeader); + ASSERT_EFI_ERROR (Status); + ASSERT (WriteLength == GoodFwVolHeader->HeaderLength); + + Status = ValidateFvHeader (mFvInstance->VolumeHeader); + ASSERT_EFI_ERROR (Status); + } + + MaxLbaSize = 0; + NumOfBlocks = 0; + for (PtrBlockMapEntry = mFvInstance->VolumeHeader->BlockMap; + PtrBlockMapEntry->NumBlocks != 0; + PtrBlockMapEntry++) { + // + // Get the maximum size of a block. + // + if (MaxLbaSize < PtrBlockMapEntry->Length) { + MaxLbaSize = PtrBlockMapEntry->Length; + } + + NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks; + } + + // + // The total number of blocks in the FV. + // + mFvInstance->NumOfBlocks = NumOfBlocks; + + // + // Add a FVB Protocol Instance + // + FvbDevice = AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE)); + ASSERT (FvbDevice != NULL); + CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE)); + + // + // Set up the devicepath + // + if (mFvInstance->VolumeHeader->ExtHeaderOffset == 0) { + FV_MEMMAP_DEVICE_PATH *FvMemmapDevicePath; + + // + // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH + // + FvMemmapDevicePath = AllocateCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), + &mFvMemmapDevicePathTemplate); + FvMemmapDevicePath->MemMapDevPath.StartingAddress = mFvInstance->FvBase; + FvMemmapDevicePath->MemMapDevPath.EndingAddress = mFvInstance->FvBase + + mFvInstance->FvLength - 1; + FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)FvMemmapDevicePath; + } else { + FV_PIWG_DEVICE_PATH *FvPiwgDevicePath; + + FvPiwgDevicePath = AllocateCopyPool (sizeof (FV_PIWG_DEVICE_PATH), + &mFvPIWGDevicePathTemplate); + CopyGuid ( + &FvPiwgDevicePath->FvDevPath.FvName, + (GUID *)(UINTN)(mFvInstance->FvBase + + mFvInstance->VolumeHeader->ExtHeaderOffset) + ); + FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)FvPiwgDevicePath; + } + + // + // Module type specific hook. + // + InstallProtocolInterfaces (FvbDevice); + + // + // Set several PCD values to point to flash. + // + PcdStatus = PcdSet64S ( + PcdFlashNvStorageVariableBase64, + (UINTN) PcdGet32 (PcdNvStorageVariableBase) + ); + ASSERT_RETURN_ERROR (PcdStatus); + PcdStatus = PcdSet32S ( + PcdFlashNvStorageFtwWorkingBase, + PcdGet32 (PcdNvStorageFtwWorkingBase) + ); + ASSERT_RETURN_ERROR (PcdStatus); + PcdStatus = PcdSet32S ( + PcdFlashNvStorageFtwSpareBase, + PcdGet32 (PcdNvStorageFtwSpareBase) + ); + ASSERT_RETURN_ERROR (PcdStatus); + + InstallFSNotifyHandler (); + InstallDumpVarEventHandlers (); + InstallVirtualAddressChangeHandler (); + + return EFI_SUCCESS; +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockService.h b/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockService.h new file mode 100644 index 000000000000..3596c4ac55b9 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockService.h @@ -0,0 +1,217 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) 2007-2009, Intel Corporation. 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 _FW_BLOCK_SERVICE_H +#define _FW_BLOCK_SERVICE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + union { + UINTN FvBase; + EFI_FIRMWARE_VOLUME_HEADER *VolumeHeader; + }; + UINTN FvLength; + UINTN Offset; + UINTN NumOfBlocks; + EFI_DEVICE_PATH_PROTOCOL *Device; + CHAR16 *MappedFile; + BOOLEAN Dirty; +} EFI_FW_VOL_INSTANCE; + +extern EFI_FW_VOL_INSTANCE *mFvInstance; + +typedef struct { + MEDIA_FW_VOL_DEVICE_PATH FvDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_PIWG_DEVICE_PATH; + +typedef struct { + MEMMAP_DEVICE_PATH MemMapDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_MEMMAP_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance; +} EFI_FW_VOL_BLOCK_DEVICE; + +EFI_STATUS +GetFvbInfo ( + IN UINT64 FvLength, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ); + +EFI_STATUS +FvbSetVolumeAttributes ( + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +EFI_STATUS +FvbGetVolumeAttributes ( + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +EFI_STATUS +FvbGetPhysicalAddress ( + OUT EFI_PHYSICAL_ADDRESS *Address + ); + +EFI_STATUS +EFIAPI +FvbInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +VOID +EFIAPI +FvbClassAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +EFI_STATUS +FvbGetLbaAddress ( + IN EFI_LBA Lba, + OUT UINTN *LbaAddress, + OUT UINTN *LbaLength, + OUT UINTN *NumOfBlocks + ); + +// +// Protocol APIs +// +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ); + +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ); + +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN CONST EFI_LBA Lba, + IN CONST UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ); + +VOID +InstallProtocolInterfaces ( + IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice + ); + +VOID +InstallVirtualAddressChangeHandler ( + VOID + ); + +VOID +InstallFSNotifyHandler ( + VOID + ); + +VOID +InstallDumpVarEventHandlers ( + VOID +); + +EFI_STATUS +FileWrite ( + IN EFI_FILE_PROTOCOL *File, + IN UINTN Offset, + IN UINTN Buffer, + IN UINTN Size + ); + +EFI_STATUS +CheckStore ( + IN EFI_HANDLE SimpleFileSystemHandle, + OUT EFI_DEVICE_PATH_PROTOCOL **Device + ); + +EFI_STATUS +CheckStoreExists ( + IN EFI_DEVICE_PATH_PROTOCOL *Device + ); + +EFI_STATUS +FileOpen ( + IN EFI_DEVICE_PATH_PROTOCOL *Device, + IN CHAR16 *MappedFile, + OUT EFI_FILE_PROTOCOL **File, + IN UINT64 OpenMode + ); + +VOID +FileClose ( + IN EFI_FILE_PROTOCOL *File + ); + +#endif diff --git a/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockServiceDxe.c b/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockServiceDxe.c new file mode 100644 index 000000000000..8c4db3dcfd59 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockServiceDxe.c @@ -0,0 +1,334 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (C) 2015, Red Hat, Inc. + * Copyright (c) 2006-2014, Intel Corporation. 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 "VarBlockService.h" + +VOID *mSFSRegistration; + + +VOID +InstallProtocolInterfaces ( + IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice + ) +{ + EFI_STATUS Status; + EFI_HANDLE FwbHandle; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface; + + // + // Find a handle with a matching device path that has supports FW Block + // protocol. + // + Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, + &FvbDevice->DevicePath, &FwbHandle); + if (EFI_ERROR (Status)) { + // + // LocateDevicePath fails so install a new interface and device path. + // + FwbHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + &FvbDevice->FwVolBlockInstance, + &gEfiDevicePathProtocolGuid, + FvbDevice->DevicePath, + NULL + ); + ASSERT_EFI_ERROR (Status); + } else if (IsDevicePathEnd (FvbDevice->DevicePath)) { + // + // Device already exists, so reinstall the FVB protocol + // + Status = gBS->HandleProtocol ( + FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID**)&OldFwbInterface + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->ReinstallProtocolInterface ( + FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + OldFwbInterface, + &FvbDevice->FwVolBlockInstance + ); + ASSERT_EFI_ERROR (Status); + } else { + // + // There was a FVB protocol on an End Device Path node + // + ASSERT (FALSE); + } +} + + +STATIC +VOID +EFIAPI +FvbVirtualAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + + Routine Description: + + Fixup internal data so that EFI can be called in virtual mode. + + Arguments: + + (Standard EFI notify event - EFI_EVENT_NOTIFY) + + Returns: + + None + +--*/ +{ + EfiConvertPointer (0x0, (VOID **) &mFvInstance->FvBase); + EfiConvertPointer (0x0, (VOID **) &mFvInstance->VolumeHeader); + EfiConvertPointer (0x0, (VOID **) &mFvInstance); +} + + +VOID +InstallVirtualAddressChangeHandler ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT VirtualAddressChangeEvent; + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + FvbVirtualAddressChangeEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &VirtualAddressChangeEvent + ); + ASSERT_EFI_ERROR (Status); +} + + +STATIC +EFI_STATUS +DoDump( + IN EFI_DEVICE_PATH_PROTOCOL *Device + ) +{ + EFI_STATUS Status; + EFI_FILE_PROTOCOL *File; + + Status = FileOpen (Device, + mFvInstance->MappedFile, + &File, + EFI_FILE_MODE_WRITE | + EFI_FILE_MODE_READ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = FileWrite (File, + mFvInstance->Offset, + mFvInstance->FvBase, + mFvInstance->FvLength); + FileClose (File); + return Status; +} + + +STATIC +VOID +EFIAPI +DumpVars( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + + if (mFvInstance->Device == NULL) { + DEBUG((DEBUG_INFO, "Variable store not found?\n")); + return; + } + + if (!mFvInstance->Dirty) { + DEBUG((DEBUG_INFO, "Variables not dirty, not dumping!\n")); + return; + } + + Status = DoDump (mFvInstance->Device); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "Couldn't dump '%s'\n", + mFvInstance->MappedFile)); + ASSERT_EFI_ERROR(Status); + return; + } + + DEBUG((DEBUG_INFO, "Variables dumped!\n")); + mFvInstance->Dirty = FALSE; +} + + +VOID +ReadyToBootHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_EVENT ImageInstallEvent; + VOID *ImageRegistration; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + DumpVars, + NULL, + &ImageInstallEvent + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->RegisterProtocolNotify ( + &gEfiLoadedImageProtocolGuid, + ImageInstallEvent, + &ImageRegistration + ); + ASSERT_EFI_ERROR (Status); + + DumpVars(NULL, NULL); + Status = gBS->CloseEvent(Event); + ASSERT_EFI_ERROR (Status); +} + + +VOID +InstallDumpVarEventHandlers ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT ResetEvent; + EFI_EVENT ReadyToBootEvent; + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + DumpVars, + NULL, + &gRaspberryPiEventResetGuid, + &ResetEvent + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + ReadyToBootHandler, + NULL, + &gEfiEventReadyToBootGuid, + &ReadyToBootEvent + ); + ASSERT_EFI_ERROR (Status); +} + + +VOID +EFIAPI +OnSimpleFileSystemInstall ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINTN HandleSize; + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *Device; + + if ((mFvInstance->Device != NULL) && + !EFI_ERROR (CheckStoreExists (mFvInstance->Device)) + ) { + // + // We've already found the variable store before, + // and that device is not removed from the ssystem. + // + return; + } + + while (TRUE) { + HandleSize = sizeof (EFI_HANDLE); + Status = gBS->LocateHandle ( + ByRegisterNotify, + NULL, + mSFSRegistration, + &HandleSize, + &Handle + ); + if (Status == EFI_NOT_FOUND) { + break; + } + + ASSERT_EFI_ERROR (Status); + + Status = CheckStore (Handle, &Device); + if (EFI_ERROR (Status)) { + continue; + } + + Status = DoDump (Device); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "Couldn't update '%s'\n", + mFvInstance->MappedFile)); + ASSERT_EFI_ERROR(Status); + continue; + } + + if (mFvInstance->Device != NULL) { + gBS->FreePool (mFvInstance->Device); + } + + DEBUG((DEBUG_INFO, "Found variable store!\n")); + mFvInstance->Device = Device; + break; + } +} + + +VOID +InstallFSNotifyHandler ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + OnSimpleFileSystemInstall, + NULL, + &Event + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->RegisterProtocolNotify ( + &gEfiSimpleFileSystemProtocolGuid, + Event, + &mSFSRegistration + ); + ASSERT_EFI_ERROR (Status); +} diff --git a/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockServiceDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockServiceDxe.inf new file mode 100644 index 000000000000..95ec0f8a64e9 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockServiceDxe.inf @@ -0,0 +1,93 @@ +#/** @file +# +# Support for the FS-backed "flash" device. +# The trick is to keep it inside the RPI firmware file itself... +# +# Copyright (c) 2018, Andrei Warkentin +# Copyright (c) 2006-2013, Intel Corporation. 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 = VarBlockServiceDxe + FILE_GUID = 733cbac2-b23f-4b92-bc8e-fb01ce5907b7 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = FvbInitialize + +# +# The following information is for reference only and not required by the build +# tools. +# +# VALID_ARCHITECTURES = AARCH64 +# + +[Sources] + FvbInfo.c + VarBlockService.c + VarBlockServiceDxe.c + FileIo.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + DxeServicesTableLib + MemoryAllocationLib + PcdLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiRuntimeLib + +[Guids] + gEfiEventVirtualAddressChangeGuid + gRaspberryPiEventResetGuid + gEfiEventReadyToBootGuid + +[Protocols] + gEfiSimpleFileSystemProtocolGuid + gEfiLoadedImageProtocolGuid + gEfiBlockIoProtocolGuid + gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL SOMETIMES_PRODUCED + gEfiDevicePathProtocolGuid # PROTOCOL SOMETIMES_PRODUCED + +[FixedPcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + gRaspberryPiTokenSpaceGuid.PcdNvStorageVariableBase + gRaspberryPiTokenSpaceGuid.PcdNvStorageFtwWorkingBase + gRaspberryPiTokenSpaceGuid.PcdNvStorageFtwSpareBase + gRaspberryPiTokenSpaceGuid.PcdNvStorageEventLogSize + gRaspberryPiTokenSpaceGuid.PcdFirmwareBlockSize + gArmTokenSpaceGuid.PcdFdBaseAddress + gArmTokenSpaceGuid.PcdFdSize + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gRaspberryPiTokenSpaceGuid.PcdNvStorageEventLogBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 + +[FeaturePcd] + +[Depex] + TRUE diff --git a/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836.h b/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836.h new file mode 100644 index 000000000000..bd30324ff073 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836.h @@ -0,0 +1,70 @@ +/** @file + * + * Copyright (c) 2017, Andrei Warkentin + * Copyright (c) 2016, Linaro Limited. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 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. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + * + **/ + +/* + * Both "core" and SoC perpherals (1M each). + */ +#define BCM2836_SOC_REGISTERS 0x3f000000 +#define BCM2836_SOC_REGISTER_LENGTH 0x02000000 + +/* Synopsis DW2/DWC USB 2.0 OTG. */ +#define BCM2836_USB_DW2_BASE_ADDRESS 0x3f980000 + +/* + * Offset between the CPU's view and the VC's view of system memory. + */ +#define BCM2836_DMA_DEVICE_OFFSET 0xc0000000 + +/* watchdog constants */ +#define BCM2836_WDOG_BASE_ADDRESS 0x3f100000 +#define BCM2836_WDOG_PASSWORD 0x5a000000 +#define BCM2836_WDOG_RSTC_OFFSET 0x0000001c +#define BCM2836_WDOG_WDOG_OFFSET 0x00000024 +#define BCM2836_WDOG_RSTC_WRCFG_MASK 0x00000030 +#define BCM2836_WDOG_RSTC_WRCFG_FULL_RESET 0x00000020 + +/* mailbox interface constants */ +#define BCM2836_MBOX_BASE_ADDRESS 0x3f00b880 +#define BCM2836_MBOX_READ_OFFSET 0x00000000 +#define BCM2836_MBOX_STATUS_OFFSET 0x00000018 +#define BCM2836_MBOX_CONFIG_OFFSET 0x0000001c +#define BCM2836_MBOX_WRITE_OFFSET 0x00000020 + +#define BCM2836_MBOX_STATUS_FULL 0x1f +#define BCM2836_MBOX_STATUS_EMPTY 0x1e + +#define BCM2836_MBOX_NUM_CHANNELS 16 + +/* interrupt controller constants */ +#define BCM2836_INTC_TIMER_CONTROL_OFFSET 0x00000040 +#define BCM2836_INTC_TIMER_PENDING_OFFSET 0x00000060 diff --git a/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836MmcHs.h b/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836MmcHs.h new file mode 100644 index 000000000000..2bd1742fcdff --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836MmcHs.h @@ -0,0 +1,199 @@ +/** @file + * + * Copyright (c) Microsoft Corporation. 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 __BCM2836SDIO_H__ +#define __BCM2836SDIO_H__ + +//MMC/SD/SDIO1 register definitions. +#define MMCHS1BASE 0x3F300000 + +#define MMCHS_BLK (MMCHS1BASE + 0x4) +#define BLEN_512BYTES (0x200UL << 0) + +#define MMCHS_ARG (MMCHS1BASE + 0x8) + +#define MMCHS_CMD (MMCHS1BASE + 0xC) +#define BCE_ENABLE BIT1 +#define DDIR_READ BIT4 +#define DDIR_WRITE (0x0UL << 4) +#define MSBS_SGLEBLK (0x0UL << 5) +#define MSBS_MULTBLK BIT5 +#define RSP_TYPE_MASK (0x3UL << 16) +#define RSP_TYPE_136BITS BIT16 +#define RSP_TYPE_48BITS (0x2UL << 16) +#define RSP_TYPE_48BUSY (0x3UL << 16) +#define CCCE_ENABLE BIT19 +#define CICE_ENABLE BIT20 +#define DP_ENABLE BIT21 + +#define CMD_TYPE_NORMAL 0 +#define CMD_TYPE_ABORT 3 +#define TYPE(CMD_TYPE) (((CMD_TYPE) & 0x3) << 22) +#define _INDX(CMD_INDX) ((CMD_INDX & 0x3F) << 24) +#define MMC_CMD_NUM(CMD) (((CMD) >> 24) & 0x3F) +#define INDX(CMD_INDX) (TYPE(CMD_TYPE_NORMAL) | _INDX(CMD_INDX)) +#define INDX_ABORT(CMD_INDX) (TYPE(CMD_TYPE_ABORT) | _INDX(CMD_INDX)) + +#define MMCHS_RSP10 (MMCHS1BASE + 0x10) +#define MMCHS_RSP32 (MMCHS1BASE + 0x14) +#define MMCHS_RSP54 (MMCHS1BASE + 0x18) +#define MMCHS_RSP76 (MMCHS1BASE + 0x1C) +#define MMCHS_DATA (MMCHS1BASE + 0x20) + +#define MMCHS_PRES_STATE (MMCHS1BASE + 0x24) +#define CMDI_MASK BIT0 +#define CMDI_ALLOWED (0x0UL << 0) +#define CMDI_NOT_ALLOWED BIT0 +#define DATI_MASK BIT1 +#define DATI_ALLOWED (0x0UL << 1) +#define DATI_NOT_ALLOWED BIT1 +#define WRITE_PROTECT_OFF BIT19 + +#define MMCHS_HCTL (MMCHS1BASE + 0x28) +#define DTW_1_BIT (0x0UL << 1) +#define DTW_4_BIT BIT1 +#define SDBP_MASK BIT8 +#define SDBP_OFF (0x0UL << 8) +#define SDBP_ON BIT8 +#define SDVS_1_8_V (0x5UL << 9) +#define SDVS_3_0_V (0x6UL << 9) +#define IWE BIT24 + +#define MMCHS_SYSCTL (MMCHS1BASE + 0x2C) +#define ICE BIT0 +#define ICS_MASK BIT1 +#define ICS BIT1 +#define CEN BIT2 +#define CLKD_MASK (0x3FFUL << 6) +#define CLKD_80KHZ (0x258UL) //(96*1000/80)/2 +#define CLKD_400KHZ (0xF0UL) +#define CLKD_12500KHZ (0x200UL) +#define DTO_MASK (0xFUL << 16) +#define DTO_VAL (0xEUL << 16) +#define SRA BIT24 +#define SRC_MASK BIT25 +#define SRC BIT25 +#define SRD BIT26 + +#define MMCHS_INT_STAT (MMCHS1BASE + 0x30) +#define CC BIT0 +#define TC BIT1 +#define BWR BIT4 +#define BRR BIT5 +#define CARD_INS BIT6 +#define ERRI BIT15 +#define CTO BIT16 +#define DTO BIT20 +#define DCRC BIT21 +#define DEB BIT22 + +#define MMCHS_IE (MMCHS1BASE + 0x34) +#define CC_EN BIT0 +#define TC_EN BIT1 +#define BWR_EN BIT4 +#define BRR_EN BIT5 +#define CTO_EN BIT16 +#define CCRC_EN BIT17 +#define CEB_EN BIT18 +#define CIE_EN BIT19 +#define DTO_EN BIT20 +#define DCRC_EN BIT21 +#define DEB_EN BIT22 +#define CERR_EN BIT28 +#define BADA_EN BIT29 +#define ALL_EN 0xFFFFFFFF + +#define MMCHS_ISE (MMCHS1BASE + 0x38) +#define CC_SIGEN BIT0 +#define TC_SIGEN BIT1 +#define BWR_SIGEN BIT4 +#define BRR_SIGEN BIT5 +#define CTO_SIGEN BIT16 +#define CCRC_SIGEN BIT17 +#define CEB_SIGEN BIT18 +#define CIE_SIGEN BIT19 +#define DTO_SIGEN BIT20 +#define DCRC_SIGEN BIT21 +#define DEB_SIGEN BIT22 +#define CERR_SIGEN BIT28 +#define BADA_SIGEN BIT29 + +#define MMCHS_AC12 (MMCHS1BASE + 0x3C) + +#define MMCHS_CAPA (MMCHS1BASE + 0x40) +#define VS30 BIT25 +#define VS18 BIT26 + +#define MMCHS_CUR_CAPA (MMCHS1BASE + 0x48) +#define MMCHS_REV (MMCHS1BASE + 0xFC) + +#define BLOCK_COUNT_SHIFT 16 +#define RCA_SHIFT 16 + +#define CMD_R1 (RSP_TYPE_48BITS | CCCE_ENABLE | CICE_ENABLE) +#define CMD_R1B (RSP_TYPE_48BUSY | CCCE_ENABLE | CICE_ENABLE) +#define CMD_R2 (RSP_TYPE_136BITS | CCCE_ENABLE) +#define CMD_R3 (RSP_TYPE_48BITS) +#define CMD_R6 (RSP_TYPE_48BITS | CCCE_ENABLE | CICE_ENABLE) +#define CMD_R7 (RSP_TYPE_48BITS | CCCE_ENABLE | CICE_ENABLE) + +#define CMD_R1_ADTC (CMD_R1 | DP_ENABLE) +#define CMD_R1_ADTC_READ (CMD_R1_ADTC | DDIR_READ) +#define CMD_R1_ADTC_WRITE (CMD_R1_ADTC | DDIR_WRITE) + +#define CMD0 (INDX(0)) // Go idle +#define CMD1 (INDX(1) | CMD_R3) // MMC: Send Op Cond +#define CMD2 (INDX(2) | CMD_R2) // Send CID +#define CMD3 (INDX(3) | CMD_R6) // Set Relative Addr +#define CMD4 (INDX(4)) // Set DSR +#define CMD5 (INDX(5) | CMD_R1B) // SDIO: Sleep/Awake +#define CMD6 (INDX(6) | CMD_R1_ADTC_READ) // Switch +#define CMD7 (INDX(7) | CMD_R1B) // Select/Deselect +#define CMD8_SD (INDX(8) | CMD_R7) // Send If Cond +#define CMD8_SD_ARG (0x0UL << 12 | BIT8 | 0xCEUL << 0) +#define CMD8_MMC (INDX(8) | CMD_R1_ADTC_READ) // Send Ext Csd +#define CMD8_MMC_ARG (0) +#define CMD9 (INDX(9) | CMD_R2) // Send CSD +#define CMD10 (INDX(10) | CMD_R2) // Send CID +#define CMD11 (INDX(11) | CMD_R1) // Voltage Switch +#define CMD12 (INDX_ABORT(12) | CMD_R1B) // Stop Transmission +#define CMD13 (INDX(13) | CMD_R1) // Send Status +#define CMD15 (INDX(15)) // Go inactive state +#define CMD16 (INDX(16) | CMD_R1) // Set Blocklen +#define CMD17 (INDX(17) | CMD_R1_ADTC_READ) // Read Single Block +#define CMD18 (INDX(18) | CMD_R1_ADTC_READ | MSBS_MULTBLK) // Read Multiple Blocks +#define CMD19 (INDX(19) | CMD_R1_ADTC_READ) // SD: Send Tuning Block (64 bytes) +#define CMD20 (INDX(20) | CMD_R1B) // SD: Speed Class Control +#define CMD23 (INDX(23) | CMD_R1) // Set Block Count for CMD18 and CMD25 +#define CMD24 (INDX(24) | CMD_R1_ADTC_WRITE) // Write Block +#define CMD25 (INDX(25) | CMD_R1_ADTC_WRITE | MSBS_MULTBLK) // Write Multiple Blocks +#define CMD55 (INDX(55) | CMD_R1) // App Cmd + +#define ACMD6 (INDX(6) | CMD_R1) // Set Bus Width +#define ACMD22 (INDX(22) | CMD_R1_ADTC_READ) // SEND_NUM_WR_BLOCKS +#define ACMD41 (INDX(41) | CMD_R3) // Send Op Cond +#define ACMD51 (INDX(51) | CMD_R1_ADTC_READ) // Send SCR + +// User-friendly command names +#define CMD_IO_SEND_OP_COND CMD5 +#define CMD_SEND_CSD CMD9 // CSD: Card-Specific Data +#define CMD_STOP_TRANSMISSION CMD12 +#define CMD_SEND_STATUS CMD13 +#define CMD_READ_SINGLE_BLOCK CMD17 +#define CMD_READ_MULTIPLE_BLOCK CMD18 +#define CMD_SET_BLOCK_COUNT CMD23 +#define CMD_WRITE_SINGLE_BLOCK CMD24 +#define CMD_WRITE_MULTIPLE_BLOCK CMD25 + +#endif //__BCM2836SDIO_H__ diff --git a/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836SdHost.h b/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836SdHost.h new file mode 100644 index 000000000000..fb3d6b5ccad3 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2836SdHost.h @@ -0,0 +1,92 @@ +/** @file + * + * Copyright (c) 2017, Andrei Warkentin + * Copyright (c) Microsoft Corporation. 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 __BCM2836SDHOST_H__ +#define __BCM2836SDHOST_H__ + +#define SDHOST_BASE_ADDRESS (BCM2836_SOC_REGISTERS + 0x00202000) +#define SDHOST_REG(X) (SDHOST_BASE_ADDRESS + (X)) +#define SDHOST_CMD SDHOST_REG(0x0) +#define SDHOST_ARG SDHOST_REG(0x4) +#define SDHOST_TOUT SDHOST_REG(0x8) +#define SDHOST_CDIV SDHOST_REG(0xC) +#define SDHOST_RSP0 SDHOST_REG(0x10) // [31:0] +#define SDHOST_RSP1 SDHOST_REG(0x14) // [63:32] +#define SDHOST_RSP2 SDHOST_REG(0x18) // [95:64] +#define SDHOST_RSP3 SDHOST_REG(0x1C) // [127:96] +#define SDHOST_HSTS SDHOST_REG(0x20) +#define SDHOST_VDD SDHOST_REG(0x30) +#define SDHOST_EDM SDHOST_REG(0x34) +#define SDHOST_HCFG SDHOST_REG(0x38) +#define SDHOST_HBCT SDHOST_REG(0x3C) +#define SDHOST_DATA SDHOST_REG(0x40) +#define SDHOST_HBLC SDHOST_REG(0x50) + +// +// CMD +// +#define SDHOST_CMD_READ_CMD BIT6 +#define SDHOST_CMD_WRITE_CMD BIT7 +#define SDHOST_CMD_RESPONSE_CMD_LONG_RESP BIT9 +#define SDHOST_CMD_RESPONSE_CMD_NO_RESP BIT10 +#define SDHOST_CMD_BUSY_CMD BIT11 +#define SDHOST_CMD_FAIL_FLAG BIT14 +#define SDHOST_CMD_NEW_FLAG BIT15 + +// +// VDD +// +#define SDHOST_VDD_POWER_ON BIT0 + +// +// HSTS +// +#define SDHOST_HSTS_CLEAR 0x7F8 +#define SDHOST_HSTS_BLOCK_IRPT BIT9 +#define SDHOST_HSTS_REW_TIME_OUT BIT7 +#define SDHOST_HSTS_CMD_TIME_OUT BIT6 +#define SDHOST_HSTS_CRC16_ERROR BIT5 +#define SDHOST_HSTS_CRC7_ERROR BIT4 +#define SDHOST_HSTS_FIFO_ERROR BIT3 +#define SDHOST_HSTS_DATA_FLAG BIT0 + +#define SDHOST_HSTS_TIMOUT_ERROR (SDHOST_HSTS_CMD_TIME_OUT | SDHOST_HSTS_REW_TIME_OUT) +#define SDHOST_HSTS_TRANSFER_ERROR (SDHOST_HSTS_FIFO_ERROR | SDHOST_HSTS_CRC7_ERROR | SDHOST_HSTS_CRC16_ERROR) +#define SDHOST_HSTS_ERROR (SDHOST_HSTS_TIMOUT_ERROR | SDHOST_HSTS_TRANSFER_ERROR) + +// +// HCFG +// +#define SDHOST_HCFG_SLOW_CARD BIT3 +#define SDHOST_HCFG_WIDE_EXT_BUS BIT2 +#define SDHOST_HCFG_WIDE_INT_BUS BIT1 +#define SDHOST_HCFG_DATA_IRPT_EN BIT4 +#define SDHOST_HCFG_BLOCK_IRPT_EN BIT8 +#define SDHOST_HCFG_BUSY_IRPT_EN BIT10 + +// +// EDM +// +#define SDHOST_EDM_FIFO_CLEAR BIT21 +#define SDHOST_EDM_WRITE_THRESHOLD_SHIFT 9 +#define SDHOST_EDM_READ_THRESHOLD_SHIFT 14 +#define SDHOST_EDM_THRESHOLD_MASK 0x1F +#define SDHOST_EDM_READ_THRESHOLD(X) ((X) << SDHOST_EDM_READ_THRESHOLD_SHIFT) +#define SDHOST_EDM_WRITE_THRESHOLD(X) ((X) << SDHOST_EDM_WRITE_THRESHOLD_SHIFT) + +#define CMD8_SD_ARG (0x0UL << 12 | BIT8 | 0xCEUL << 0) +#define CMD8_MMC_ARG (0) + +#endif //__BCM2836SDHOST_H__ diff --git a/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2837Gpio.h b/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2837Gpio.h new file mode 100644 index 000000000000..27e6665f1745 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Include/IndustryStandard/Bcm2837Gpio.h @@ -0,0 +1,50 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) Microsoft Corporation. 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 __BCM2837GPIO_H__ +#define __BCM2837GPIO_H__ + +#define GPIO_BASE_ADDRESS (BCM2836_SOC_REGISTERS + 0x00200000) + +#define GPIO_GPFSEL0 (GPIO_BASE_ADDRESS + 0x00) +#define GPIO_GPFSEL1 (GPIO_BASE_ADDRESS + 0x04) +#define GPIO_GPFSEL2 (GPIO_BASE_ADDRESS + 0x08) +#define GPIO_GPFSEL3 (GPIO_BASE_ADDRESS + 0x0C) +#define GPIO_GPFSEL4 (GPIO_BASE_ADDRESS + 0x10) +#define GPIO_GPFSEL5 (GPIO_BASE_ADDRESS + 0x14) + +#define GPIO_GPCLR0 (GPIO_BASE_ADDRESS + 0x28) +#define GPIO_GPCLR1 (GPIO_BASE_ADDRESS + 0x2C) + +#define GPIO_GPSET0 (GPIO_BASE_ADDRESS + 0x1C) +#define GPIO_GPSET1 (GPIO_BASE_ADDRESS + 0x20) + +#define GPIO_FSEL_INPUT 0x0 +#define GPIO_FSEL_OUTPUT 0x1 +#define GPIO_FSEL_ALT0 0x4 +#define GPIO_FSEL_ALT1 0x5 +#define GPIO_FSEL_ALT2 0x6 +#define GPIO_FSEL_ALT3 0x7 +#define GPIO_FSEL_ALT4 0x3 +#define GPIO_FSEL_ALT5 0x2 + +#define GPIO_FSEL_PINS_PER_REGISTER 10 +#define GPIO_FSEL_BITS_PER_PIN 3 +#define GPIO_FSEL_MASK ((1 << GPIO_FSEL_BITS_PER_PIN) - 1) + +#define GPIO_PINS 54 + +#endif // __BCM2837GPIO_H__ + diff --git a/Platform/Broadcom/Bcm283x/Include/IndustryStandard/RpiFirmware.h b/Platform/Broadcom/Bcm283x/Include/IndustryStandard/RpiFirmware.h new file mode 100644 index 000000000000..83f8633c26cf --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Include/IndustryStandard/RpiFirmware.h @@ -0,0 +1,93 @@ +/** @file + * + * Copyright (c) 2016, Linaro Limited. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 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. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. + * + **/ + +#define RPI_FW_MBOX_CHANNEL 0x00000008 + +#define RPI_FW_RESP_SUCCESS 0x80000000 +#define RPI_FW_RESP_FAILURE 0x80000001 + +#define RPI_FW_VALUE_SIZE_RESPONSE_MASK BIT31 + +#define RPI_FW_GET_REVISION 0x00000001 +#define RPI_FW_GET_BOARD_MODEL 0x00010001 +#define RPI_FW_GET_BOARD_REVISION 0x00010002 +#define RPI_FW_GET_MAC_ADDRESS 0x00010003 +#define RPI_FW_GET_BOARD_SERIAL 0x00010004 +#define RPI_FW_GET_ARM_MEMSIZE 0x00010005 + +#define RPI_FW_SET_POWER_STATE 0x00028001 + +#define RPI_FW_POWER_STATE_SDHCI 0x00000000 +#define RPI_FW_POWER_STATE_UART0 0x00000001 +#define RPI_FW_POWER_STATE_UART1 0x00000002 +#define RPI_FW_POWER_STATE_USB_HCD 0x00000003 +#define RPI_FW_POWER_STATE_I2C0 0x00000004 +#define RPI_FW_POWER_STATE_I2C1 0x00000005 +#define RPI_FW_POWER_STATE_I2C2 0x00000006 +#define RPI_FW_POWER_STATE_SPI 0x00000007 +#define RPI_FW_POWER_STATE_CCP2TX 0x00000008 + +#define RPI_FW_GET_CLOCK_RATE 0x00030002 +#define RPI_FW_GET_MAX_CLOCK_RATE 0x00030004 +#define RPI_FW_GET_MIN_CLOCK_RATE 0x00030007 + +#define RPI_FW_SET_CLOCK_RATE 0x00038002 +#define RPI_FW_SET_GPIO 0x00038041 + +#define RPI_FW_GET_FB_GEOMETRY 0x00040003 +#define RPI_FW_GET_FB_LINELENGTH 0x00040008 +#define RPI_FW_GET_FB_COLOR_DEPTH 0x00040005 +#define RPI_FW_GET_FB_REGION 0x00040001 + +#define RPI_FW_SET_FB_PGEOM 0x00048003 +#define RPI_FW_SET_FB_VGEOM 0x00048004 +#define RPI_FW_SET_FB_DEPTH 0x00048005 +#define RPI_FW_ALLOC_FB 0x00040001 +#define RPI_FW_FREE_FB 0x00048001 + +#define RPI_FW_GET_COMMAND_LINE 0x00050001 + +#define RPI_FW_POWER_STATE_ENABLE BIT0 +#define RPI_FW_POWER_STATE_WAIT BIT1 + +#define RPI_FW_CLOCK_RATE_EMMC 0x000000001 +#define RPI_FW_CLOCK_RATE_UART 0x000000002 +#define RPI_FW_CLOCK_RATE_ARM 0x000000003 +#define RPI_FW_CLOCK_RATE_CORE 0x000000004 +#define RPI_FW_CLOCK_RATE_V3D 0x000000005 +#define RPI_FW_CLOCK_RATE_H264 0x000000006 +#define RPI_FW_CLOCK_RATE_ISP 0x000000007 +#define RPI_FW_CLOCK_RATE_SDRAM 0x000000008 +#define RPI_FW_CLOCK_RATE_PIXEL 0x000000009 +#define RPI_FW_CLOCK_RATE_PWM 0x00000000a + +#define RPI_FB_MBOX_CHANNEL 0x1 diff --git a/Platform/Broadcom/Bcm283x/Include/Library/GpioLib.h b/Platform/Broadcom/Bcm283x/Include/Library/GpioLib.h new file mode 100644 index 000000000000..ca9da4b11a87 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Include/Library/GpioLib.h @@ -0,0 +1,33 @@ +/** @file + * + * GPIO manipulation. + * + * Copyright (c) 2018, Andrei Warkentin + * + * 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 __GPIO_LIB__ +#define __GPIO_LIB__ + +#include + +VOID +GpioPinFuncSet( + IN UINTN Pin, + IN UINTN Function + ); + +UINTN +GpioPinFuncGet( + IN UINTN Pin + ); + +#endif /* __GPIO_LIB__ */ diff --git a/Platform/Broadcom/Bcm283x/Include/Protocol/DwUsb.h b/Platform/Broadcom/Bcm283x/Include/Protocol/DwUsb.h new file mode 100644 index 000000000000..dfad80c719e1 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Include/Protocol/DwUsb.h @@ -0,0 +1,53 @@ +/** @file + * + * Copyright (c) 2015-2016, Linaro. All rights reserved. + * Copyright (c) 2015-2016, Hisilicon 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 __DW_USB_H__ +#define __DW_USB_H__ + +// +// Protocol GUID +// +#define DW_USB_PROTOCOL_GUID { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }} + +// +// Protocol interface structure +// +typedef struct _DW_USB_PROTOCOL DW_USB_PROTOCOL; + +#define USB_HOST_MODE 0 +#define USB_DEVICE_MODE 1 +#define USB_CABLE_NOT_ATTACHED 2 + +typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_SERIAL_NO) ( + OUT CHAR16 *SerialNo, + OUT UINT8 *Length + ); + +typedef +EFI_STATUS +(EFIAPI *DW_USB_PHY_INIT) ( + IN UINT8 Mode + ); + +struct _DW_USB_PROTOCOL { + DW_USB_GET_SERIAL_NO Get; + DW_USB_PHY_INIT PhyInit; +}; + +extern EFI_GUID gDwUsbProtocolGuid; + +#endif diff --git a/Platform/Broadcom/Bcm283x/Include/Protocol/ExtendedTextOut.h b/Platform/Broadcom/Bcm283x/Include/Protocol/ExtendedTextOut.h new file mode 100644 index 000000000000..35e82a17e922 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Include/Protocol/ExtendedTextOut.h @@ -0,0 +1,36 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * + * 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 __EXTENDED_TEXT_OUT_H__ +#define __EXTENDED_TEXT_OUT_H__ + +#include +#include + +#define EXTENDED_TEXT_OUTPUT_PROTOCOL_GUID \ + { \ + 0x387477ff, 0xffc7, 0xffd2, {0x8e, 0x39, 0x0, 0xff, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct _EXTENDED_TEXT_OUTPUT_PROTOCOL EXTENDED_TEXT_OUTPUT_PROTOCOL; + +struct _EXTENDED_TEXT_OUTPUT_PROTOCOL { + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + BOOLEAN AutoWrap; +}; + +extern EFI_GUID gExtendedTextOutputProtocolGuid; + +#endif /* __EXTENDED_TEXT_OUT__ */ diff --git a/Platform/Broadcom/Bcm283x/Include/Protocol/PiMmcHost.h b/Platform/Broadcom/Bcm283x/Include/Protocol/PiMmcHost.h new file mode 100644 index 000000000000..c0e65687e8d4 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Include/Protocol/PiMmcHost.h @@ -0,0 +1,187 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) 2011-2014, ARM Limited. All rights reserved. + * + * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + **/ + +#ifndef __PI_MMC_HOST_H__ +#define __PI_MMC_HOST_H__ + +/// +/// Global ID for the MMC Host Protocol +/// +#define RASPBERRY_PI_MMC_HOST_PROTOCOL_GUID \ + { 0x3e591c00, 0x9e4a, 0x11df, {0x92, 0x44, 0x00, 0x02, 0xA5, 0xF5, 0xF5, 0x1B } } + +#define MMC_RESPONSE_TYPE_R1 0 +#define MMC_RESPONSE_TYPE_R1b 0 +#define MMC_RESPONSE_TYPE_R2 1 +#define MMC_RESPONSE_TYPE_R3 0 +#define MMC_RESPONSE_TYPE_R6 0 +#define MMC_RESPONSE_TYPE_R7 0 +#define MMC_RESPONSE_TYPE_OCR 0 +#define MMC_RESPONSE_TYPE_CID 1 +#define MMC_RESPONSE_TYPE_CSD 1 +#define MMC_RESPONSE_TYPE_RCA 0 + +typedef UINT32 MMC_RESPONSE_TYPE; + +typedef UINT32 MMC_CMD; + +#define MMC_CMD_WAIT_RESPONSE (1 << 16) +#define MMC_CMD_LONG_RESPONSE (1 << 17) +#define MMC_CMD_NO_CRC_RESPONSE (1 << 18) + +#define MMC_INDX(Index) ((Index) & 0xFFFF) +#define MMC_GET_INDX(MmcCmd) ((MmcCmd) & 0xFFFF) + +#define MMC_CMD0 (MMC_INDX(0) | MMC_CMD_NO_CRC_RESPONSE) +#define MMC_CMD1 (MMC_INDX(1) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE) +#define MMC_CMD2 (MMC_INDX(2) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE) +#define MMC_CMD3 (MMC_INDX(3) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD5 (MMC_INDX(5) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE) +#define MMC_CMD6 (MMC_INDX(6) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD7 (MMC_INDX(7) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD8 (MMC_INDX(8) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD9 (MMC_INDX(9) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_LONG_RESPONSE) +#define MMC_CMD11 (MMC_INDX(11) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD12 (MMC_INDX(12) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD13 (MMC_INDX(13) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD16 (MMC_INDX(16) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD17 (MMC_INDX(17) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD18 (MMC_INDX(18) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD20 (MMC_INDX(20) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD23 (MMC_INDX(23) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD24 (MMC_INDX(24) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD25 (MMC_INDX(25) | MMC_CMD_WAIT_RESPONSE) +#define MMC_CMD55 (MMC_INDX(55) | MMC_CMD_WAIT_RESPONSE) +#define MMC_ACMD22 (MMC_INDX(22) | MMC_CMD_WAIT_RESPONSE) +#define MMC_ACMD41 (MMC_INDX(41) | MMC_CMD_WAIT_RESPONSE | MMC_CMD_NO_CRC_RESPONSE) +#define MMC_ACMD51 (MMC_INDX(51) | MMC_CMD_WAIT_RESPONSE) + +// Valid responses for CMD1 in eMMC +#define EMMC_CMD1_CAPACITY_LESS_THAN_2GB 0x00FF8080 // Capacity <= 2GB, byte addressing used +#define EMMC_CMD1_CAPACITY_GREATER_THAN_2GB 0x40FF8080 // Capacity > 2GB, 512-byte sector addressing used + +#define MMC_STATUS_APP_CMD (1 << 5) + +typedef enum _MMC_STATE { + MmcInvalidState = 0, + MmcHwInitializationState, + MmcIdleState, + MmcReadyState, + MmcIdentificationState, + MmcStandByState, + MmcTransferState, + MmcSendingDataState, + MmcReceiveDataState, + MmcProgrammingState, + MmcDisconnectState, +} MMC_STATE; + +#define EMMCBACKWARD (0) +#define EMMCHS26 (1 << 0) // High-Speed @26MHz at rated device voltages +#define EMMCHS52 (1 << 1) // High-Speed @52MHz at rated device voltages +#define EMMCHS52DDR1V8 (1 << 2) // High-Speed Dual Data Rate @52MHz 1.8V or 3V I/O +#define EMMCHS52DDR1V2 (1 << 3) // High-Speed Dual Data Rate @52MHz 1.2V I/O +#define EMMCHS200SDR1V8 (1 << 4) // HS200 Single Data Rate @200MHz 1.8V I/O +#define EMMCHS200SDR1V2 (1 << 5) // HS200 Single Data Rate @200MHz 1.2V I/O +#define EMMCHS400DDR1V8 (1 << 6) // HS400 Dual Data Rate @400MHz 1.8V I/O +#define EMMCHS400DDR1V2 (1 << 7) // HS400 Dual Data Rate @400MHz 1.2V I/O + +/// +/// Forward declaration for EFI_MMC_HOST_PROTOCOL +/// +typedef struct _EFI_MMC_HOST_PROTOCOL EFI_MMC_HOST_PROTOCOL; + +typedef BOOLEAN (EFIAPI *MMC_ISCARDPRESENT) ( + IN EFI_MMC_HOST_PROTOCOL *This + ); + +typedef BOOLEAN (EFIAPI *MMC_ISREADONLY) ( + IN EFI_MMC_HOST_PROTOCOL *This + ); + +typedef EFI_STATUS (EFIAPI *MMC_BUILDDEVICEPATH) ( + IN EFI_MMC_HOST_PROTOCOL *This, + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + +typedef EFI_STATUS (EFIAPI *MMC_NOTIFYSTATE) ( + IN EFI_MMC_HOST_PROTOCOL *This, + IN MMC_STATE State + ); + +typedef EFI_STATUS (EFIAPI *MMC_SENDCOMMAND) ( + IN EFI_MMC_HOST_PROTOCOL *This, + IN MMC_CMD Cmd, + IN UINT32 Argument + ); + +typedef EFI_STATUS (EFIAPI *MMC_RECEIVERESPONSE) ( + IN EFI_MMC_HOST_PROTOCOL *This, + IN MMC_RESPONSE_TYPE Type, + IN UINT32 *Buffer + ); + +typedef EFI_STATUS (EFIAPI *MMC_READBLOCKDATA) ( + IN EFI_MMC_HOST_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Length, + OUT UINT32 *Buffer + ); + +typedef EFI_STATUS (EFIAPI *MMC_WRITEBLOCKDATA) ( + IN EFI_MMC_HOST_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Length, + IN UINT32 *Buffer + ); + +typedef EFI_STATUS (EFIAPI *MMC_SETIOS) ( + IN EFI_MMC_HOST_PROTOCOL *This, + IN UINT32 BusClockFreq, + IN UINT32 BusWidth, + IN UINT32 TimingMode + ); + +typedef BOOLEAN (EFIAPI *MMC_ISMULTIBLOCK) ( + IN EFI_MMC_HOST_PROTOCOL *This + ); + +struct _EFI_MMC_HOST_PROTOCOL { + UINT32 Revision; + MMC_ISCARDPRESENT IsCardPresent; + MMC_ISREADONLY IsReadOnly; + MMC_BUILDDEVICEPATH BuildDevicePath; + + MMC_NOTIFYSTATE NotifyState; + + MMC_SENDCOMMAND SendCommand; + MMC_RECEIVERESPONSE ReceiveResponse; + + MMC_READBLOCKDATA ReadBlockData; + MMC_WRITEBLOCKDATA WriteBlockData; + + MMC_SETIOS SetIos; + MMC_ISMULTIBLOCK IsMultiBlock; +}; + +#define MMC_HOST_PROTOCOL_REVISION 0x00010002 // 1.2 + +#define MMC_HOST_HAS_SETIOS(Host) (Host->Revision >= MMC_HOST_PROTOCOL_REVISION && \ + Host->SetIos != NULL) +#define MMC_HOST_HAS_ISMULTIBLOCK(Host) (Host->Revision >= MMC_HOST_PROTOCOL_REVISION && \ + Host->IsMultiBlock != NULL) + +#endif + diff --git a/Platform/Broadcom/Bcm283x/Include/Protocol/RaspberryPiFirmware.h b/Platform/Broadcom/Bcm283x/Include/Protocol/RaspberryPiFirmware.h new file mode 100644 index 000000000000..2a4247584641 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Include/Protocol/RaspberryPiFirmware.h @@ -0,0 +1,131 @@ +/** @file + * + * Copyright (c) 2016, Linaro 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 __RASPBERRY_PI_FIRMWARE_PROTOCOL_H__ +#define __RASPBERRY_PI_FIRMWARE_PROTOCOL_H__ + +#define RASPBERRY_PI_FIRMWARE_PROTOL_GUID \ + { 0x0ACA9535, 0x7AD0, 0x4286, { 0xB0, 0x2E, 0x87, 0xFA, 0x7E, 0x2A, 0x57, 0x11 } } + +typedef +EFI_STATUS +(EFIAPI *SET_POWER_STATE) ( + IN UINT32 DeviceId, + IN BOOLEAN PowerState, + IN BOOLEAN Wait + ); + +typedef +EFI_STATUS +(EFIAPI *GET_MAC_ADDRESS) ( + OUT UINT8 MacAddress[6] + ); + +typedef +EFI_STATUS +(EFIAPI *GET_COMMAND_LINE) ( + IN UINTN BufferSize, + OUT CHAR8 CommandLine[] + ); + +typedef +EFI_STATUS +(EFIAPI *GET_CLOCK_RATE) ( + IN UINT32 ClockId, + OUT UINT32 *ClockRate + ); + +typedef +EFI_STATUS +(EFIAPI *SET_CLOCK_RATE) ( + IN UINT32 ClockId, + OUT UINT32 ClockRate + ); + +typedef +EFI_STATUS +(EFIAPI *GET_FB) ( + IN UINT32 Width, + IN UINT32 Height, + IN UINT32 Depth, + OUT EFI_PHYSICAL_ADDRESS *FbBase, + OUT UINTN *FbSize, + OUT UINTN *Pitch + ); + +typedef +EFI_STATUS +(EFIAPI *GET_FB_SIZE) ( + OUT UINT32 *Width, + OUT UINT32 *Height + ); + +typedef +EFI_STATUS +(EFIAPI *FREE_FB) ( + VOID + ); + +typedef +VOID +(EFIAPI *SET_LED) ( + BOOLEAN On + ); + +typedef +EFI_STATUS +(EFIAPI *GET_SERIAL) ( + UINT64 *Serial + ); + +typedef +EFI_STATUS +(EFIAPI *GET_MODEL) ( + UINT32 *Model + ); + +typedef +EFI_STATUS +(EFIAPI *GET_MODEL_REVISION) ( + UINT32 *Revision + ); + +typedef +EFI_STATUS +(EFIAPI *GET_ARM_MEM) ( + UINT32 *Base, + UINT32 *Size + ); + +typedef struct { + SET_POWER_STATE SetPowerState; + GET_MAC_ADDRESS GetMacAddress; + GET_COMMAND_LINE GetCommandLine; + GET_CLOCK_RATE GetClockRate; + GET_CLOCK_RATE GetMaxClockRate; + GET_CLOCK_RATE GetMinClockRate; + SET_CLOCK_RATE SetClockRate; + GET_FB GetFB; + FREE_FB FreeFB; + GET_FB_SIZE GetFBSize; + SET_LED SetLed; + GET_SERIAL GetSerial; + GET_MODEL GetModel; + GET_MODEL_REVISION GetModelRevision; + GET_ARM_MEM GetArmMem; +} RASPBERRY_PI_FIRMWARE_PROTOCOL; + +extern EFI_GUID gRaspberryPiFirmwareProtocolGuid; + +#endif diff --git a/Platform/Broadcom/Bcm283x/Include/Utils.h b/Platform/Broadcom/Bcm283x/Include/Utils.h new file mode 100644 index 000000000000..47713275de3f --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Include/Utils.h @@ -0,0 +1,33 @@ +/** @file + * + * Copyright (c) 2018, Andrei Warkentin + * + * 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 UTILS_H +#define UTILS_H + +#define _IX_BITS(sm, bg) ((bg) - (sm) + 1) +#define _IX_MASK(sm, bg) ((1ul << _IX_BITS((sm), (bg))) - 1) +#define _X(val, sm, bg) ((val) >> (sm)) & _IX_MASK((sm), (bg)) +#define X(val, ix1, ix2) (((ix1) < (ix2)) ? _X((val), (ix1), (ix2)) : \ + _X((val), (ix2), (ix1))) + +#define _I(val, sm, bg) (((val) & _IX_MASK((sm), (bg))) << (sm)) +#define I(val, ix1, ix2) (((ix1) < (ix2)) ? _I((val), (ix1), (ix2)) : \ + _I((val), (ix2), (ix1))) +#define _M(val, sm, bg) ((val) & (_IX_MASK((sm), (bg)) << (sm))) +#define M(val, ix1, ix2) (((ix1) < (ix2)) ? _M((val), (ix1), (ix2)) : \ + _M((val), (ix2), (ix1))) + +#define ELES(x) (sizeof((x)) / sizeof((x)[0])) + +#endif /* UTILS_H */ diff --git a/Platform/Broadcom/Bcm283x/Library/GpioLib/GpioLib.c b/Platform/Broadcom/Bcm283x/Library/GpioLib/GpioLib.c new file mode 100644 index 000000000000..db38acefb7c3 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/GpioLib/GpioLib.c @@ -0,0 +1,79 @@ +/** @file + * + * GPIO manipulation. + * + * Copyright (c) 2018, Andrei Warkentin + * + * 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 + +STATIC VOID +GpioFSELModify( + IN UINTN RegIndex, + IN UINT32 ModifyMask, + IN UINT32 FunctionMask + ) +{ + UINT32 Val; + EFI_PHYSICAL_ADDRESS Reg = RegIndex * sizeof(UINT32) + GPIO_GPFSEL0; + + ASSERT(Reg <= GPIO_GPFSEL5); + ASSERT((~ModifyMask & FunctionMask) == 0); + + Val = MmioRead32(Reg); + Val &= ~ModifyMask; + Val |= FunctionMask; + MmioWrite32(Reg, Val); +} + +VOID +GpioPinFuncSet( + IN UINTN Pin, + IN UINTN Function + ) +{ + UINTN RegIndex = Pin / 10; + UINTN SelIndex = Pin % 10; + UINT32 ModifyMask; + UINT32 FunctionMask; + + ASSERT(Pin < GPIO_PINS); + ASSERT(Function <= GPIO_FSEL_MASK); + + ModifyMask = GPIO_FSEL_MASK << (SelIndex * GPIO_FSEL_BITS_PER_PIN); + FunctionMask = Function << (SelIndex * GPIO_FSEL_BITS_PER_PIN); + GpioFSELModify(RegIndex, ModifyMask, FunctionMask); +} + +UINTN +GpioPinFuncGet( + IN UINTN Pin + ) +{ + UINT32 Val; + UINTN RegIndex = Pin / 10; + UINTN SelIndex = Pin % 10; + EFI_PHYSICAL_ADDRESS Reg = RegIndex * sizeof(UINT32) + GPIO_GPFSEL0; + + ASSERT(Pin < GPIO_PINS); + + Val = MmioRead32(Reg); + Val >>= SelIndex * GPIO_FSEL_BITS_PER_PIN; + Val &= GPIO_FSEL_MASK; + return Val; +} diff --git a/Platform/Broadcom/Bcm283x/Library/GpioLib/GpioLib.inf b/Platform/Broadcom/Bcm283x/Library/GpioLib/GpioLib.inf new file mode 100644 index 000000000000..82114568b0a6 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/GpioLib/GpioLib.inf @@ -0,0 +1,39 @@ +#/** @file +# +# Manipulate GPIOs. +# +# Copyright (c) 2018, Andrei Warkentin +# +# 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 = GpioLib + FILE_GUID = B9F59B6B-B105-41C7-8F5A-2C60DD7FD7AB + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = GpioLib + +[Sources] + GpioLib.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + IoLib + +[Guids] diff --git a/Platform/Broadcom/Bcm283x/Library/MemoryInitPeiLib/MemoryInitPeiLib.c b/Platform/Broadcom/Bcm283x/Library/MemoryInitPeiLib/MemoryInitPeiLib.c new file mode 100644 index 000000000000..81d810b5d428 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/MemoryInitPeiLib/MemoryInitPeiLib.c @@ -0,0 +1,183 @@ +/** @file + * + * Copyright (c) 2017-2018, Andrey Warkentin + * Copyright (c) 2011-2015, ARM Limited. All rights reserved. + * + * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + **/ + +#include + +#include +#include +#include +#include +#include +#include + +extern UINT64 mSystemMemoryEnd; + +VOID +BuildMemoryTypeInformationHob ( + VOID + ); + +STATIC +VOID +InitMmu ( + IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable + ) +{ + + VOID *TranslationTableBase; + UINTN TranslationTableSize; + RETURN_STATUS Status; + + //Note: Because we called PeiServicesInstallPeiMemory() before to call InitMmu() the MMU Page Table resides in + // DRAM (even at the top of DRAM as it is the first permanent memory allocation) + Status = ArmConfigureMmu (MemoryTable, &TranslationTableBase, &TranslationTableSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Error: Failed to enable MMU\n")); + } +} + +STATIC +VOID +AddAndRTSData(ARM_MEMORY_REGION_DESCRIPTOR *Desc) +{ + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED, + Desc->PhysicalBase, + Desc->Length + ); + + BuildMemoryAllocationHob ( + Desc->PhysicalBase, + Desc->Length, + EfiRuntimeServicesData + ); +} + +STATIC +VOID +AddAndReserved(ARM_MEMORY_REGION_DESCRIPTOR *Desc) +{ + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED, + Desc->PhysicalBase, + Desc->Length + ); + + BuildMemoryAllocationHob ( + Desc->PhysicalBase, + Desc->Length, + EfiReservedMemoryType + ); +} + +STATIC +VOID +AddAndMmio(ARM_MEMORY_REGION_DESCRIPTOR *Desc) +{ + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED), + Desc->PhysicalBase, + Desc->Length + ); + + BuildMemoryAllocationHob ( + Desc->PhysicalBase, + Desc->Length, + EfiMemoryMappedIO + ); +} + +/*++ + +Routine Description: + + + +Arguments: + + FileHandle - Handle of the file being invoked. + PeiServices - Describes the list of possible PEI Services. + +Returns: + + Status - EFI_SUCCESS if the boot mode could be set + +--*/ +EFI_STATUS +EFIAPI +MemoryPeim ( + IN EFI_PHYSICAL_ADDRESS UefiMemoryBase, + IN UINT64 UefiMemorySize + ) +{ + ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable; + + // Get Virtual Memory Map from the Platform Library + ArmPlatformGetVirtualMemoryMap (&MemoryTable); + + // Ensure PcdSystemMemorySize has been set + ASSERT (PcdGet64 (PcdSystemMemorySize) != 0); + + // FD without variable store + AddAndReserved(&MemoryTable[0]); + + // Variable store. + AddAndRTSData(&MemoryTable[1]); + + // Trusted Firmware region + AddAndReserved(&MemoryTable[2]); + + // Usable memory. + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED, + MemoryTable[3].PhysicalBase, + MemoryTable[3].Length + ); + + AddAndReserved(&MemoryTable[4]); + AddAndMmio(&MemoryTable[5]); + + // Build Memory Allocation Hob + InitMmu (MemoryTable); + + if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) { + // Optional feature that helps prevent EFI memory map fragmentation. + BuildMemoryTypeInformationHob (); + } + + return EFI_SUCCESS; +} diff --git a/Platform/Broadcom/Bcm283x/Library/MemoryInitPeiLib/MemoryInitPeiLib.inf b/Platform/Broadcom/Bcm283x/Library/MemoryInitPeiLib/MemoryInitPeiLib.inf new file mode 100644 index 000000000000..9f5204a210de --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/MemoryInitPeiLib/MemoryInitPeiLib.inf @@ -0,0 +1,51 @@ +#/** @file +# +# Copyright (c) 2016, Linaro, Ltd. All rights reserved. +# Copyright (c) 2011-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 = 0x00010005 + BASE_NAME = MemoryInitPeiLib + FILE_GUID = 4bbc9c10-a100-43fb-8311-332ba497d1b4 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = MemoryInitPeiLib|SEC PEIM + +[Sources] + MemoryInitPeiLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + +[LibraryClasses] + DebugLib + HobLib + ArmMmuLib + ArmPlatformLib + +[Guids] + gEfiMemoryTypeInformationGuid + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob + +[FixedPcd] + gArmTokenSpaceGuid.PcdSystemMemoryBase + gArmTokenSpaceGuid.PcdSystemMemorySize + +[Depex] + TRUE diff --git a/Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBm.c b/Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBm.c new file mode 100644 index 000000000000..58eeb117c769 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBm.c @@ -0,0 +1,831 @@ +/** @file + * + * Copyright (c) 2018, Pete Batard + * Copyright (c) 2017-2018, Andrei Warkentin + * Copyright (c) 2016, Linaro Ltd. All rights reserved. + * Copyright (c) 2015-2016, Red Hat, Inc. + * Copyright (c) 2014, ARM Ltd. All rights reserved. + * Copyright (c) 2004-2016, Intel Corporation. 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 +#include +#include +#include +#include +#include + +#include "PlatformBm.h" + +#define BOOT_PROMPT L"ESC (setup), F1 (shell), ENTER (boot)" + +#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) } + +#pragma pack (1) +typedef struct { + VENDOR_DEVICE_PATH SerialDxe; + UART_DEVICE_PATH Uart; + VENDOR_DEFINED_DEVICE_PATH TermType; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_SERIAL_CONSOLE; +#pragma pack () + +typedef struct { + VENDOR_DEVICE_PATH Custom; + USB_DEVICE_PATH Hub; + USB_DEVICE_PATH Dev; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} PLATFORM_USB_DEV; + +typedef struct { + VENDOR_DEVICE_PATH Custom; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} PLATFORM_SD_DEV; + +#define DW_USB_DXE_FILE_GUID { \ + 0x4bf1704c, 0x03f4, 0x46d5, \ + { 0xbc, 0xa6, 0x82, 0xfa, 0x58, 0x0b, 0xad, 0xfd } \ + } + +#define ARASAN_MMC_DXE_FILE_GUID { \ + 0x100c2cfa, 0xb586, 0x4198, \ + { 0x9b, 0x4c, 0x16, 0x83, 0xd1, 0x95, 0xb1, 0xda } \ + } + +#define SDHOST_MMC_DXE_FILE_GUID { \ + 0x58abd787, 0xf64d, 0x4ca2, \ + { 0xa0, 0x34, 0xb9, 0xac, 0x2d, 0x5a, 0xd0, 0xcf } \ + } + +STATIC PLATFORM_SD_DEV mArasan = { + // + // VENDOR_DEVICE_PATH ArasanMMCHostDxe + // + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, + ARASAN_MMC_DXE_FILE_GUID + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + +STATIC PLATFORM_SD_DEV mSDHost = { + // + // VENDOR_DEVICE_PATH SdHostDxe + // + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, + SDHOST_MMC_DXE_FILE_GUID + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + +STATIC PLATFORM_USB_DEV mUsbHubPort = { + // + // VENDOR_DEVICE_PATH DwUsbHostDxe + // + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, + DW_USB_DXE_FILE_GUID + }, + + // + // USB_DEVICE_PATH Hub + // + { + { MESSAGING_DEVICE_PATH, MSG_USB_DP, DP_NODE_LEN (USB_DEVICE_PATH) }, + 0, 0 + }, + + // + // USB_DEVICE_PATH Dev + // + { + { MESSAGING_DEVICE_PATH, MSG_USB_DP, DP_NODE_LEN (USB_DEVICE_PATH) }, + 1, 0 + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + +#define SERIAL_DXE_FILE_GUID { \ + 0xD3987D4B, 0x971A, 0x435F, \ + { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \ + } + +STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = { + // + // VENDOR_DEVICE_PATH SerialDxe + // + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) }, + SERIAL_DXE_FILE_GUID + }, + + // + // UART_DEVICE_PATH Uart + // + { + { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) }, + 0, // Reserved + FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate + FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits + FixedPcdGet8 (PcdUartDefaultParity), // Parity + FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits + }, + + // + // VENDOR_DEFINED_DEVICE_PATH TermType + // + { + { + MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, + DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH) + } + // + // Guid to be filled in dynamically + // + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + + +#pragma pack (1) +typedef struct { + USB_CLASS_DEVICE_PATH Keyboard; + EFI_DEVICE_PATH_PROTOCOL End; +} PLATFORM_USB_KEYBOARD; +#pragma pack () + +STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = { + // + // USB_CLASS_DEVICE_PATH Keyboard + // + { + { + MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP, + DP_NODE_LEN (USB_CLASS_DEVICE_PATH) + }, + 0xFFFF, // VendorId: any + 0xFFFF, // ProductId: any + 3, // DeviceClass: HID + 1, // DeviceSubClass: boot + 1 // DeviceProtocol: keyboard + }, + + // + // EFI_DEVICE_PATH_PROTOCOL End + // + { + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, + DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL) + } +}; + +STATIC EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *mSerialConProtocol; + +/** + Check if the handle satisfies a particular condition. + + @param[in] Handle The handle to check. + @param[in] ReportText A caller-allocated string passed in for reporting + purposes. It must never be NULL. + + @retval TRUE The condition is satisfied. + @retval FALSE Otherwise. This includes the case when the condition could not + be fully evaluated due to an error. +**/ +typedef +BOOLEAN +(EFIAPI *FILTER_FUNCTION) ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ); + + +/** + Process a handle. + + @param[in] Handle The handle to process. + @param[in] ReportText A caller-allocated string passed in for reporting + purposes. It must never be NULL. +**/ +typedef +VOID +(EFIAPI *CALLBACK_FUNCTION) ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ); + +/** + Locate all handles that carry the specified protocol, filter them with a + callback function, and pass each handle that passes the filter to another + callback. + + @param[in] ProtocolGuid The protocol to look for. + + @param[in] Filter The filter function to pass each handle to. If this + parameter is NULL, then all handles are processed. + + @param[in] Process The callback function to pass each handle to that + clears the filter. +**/ +STATIC +VOID +FilterAndProcess ( + IN EFI_GUID *ProtocolGuid, + IN FILTER_FUNCTION Filter OPTIONAL, + IN CALLBACK_FUNCTION Process + ) +{ + EFI_STATUS Status; + EFI_HANDLE *Handles; + UINTN NoHandles; + UINTN Idx; + + Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid, + NULL /* SearchKey */, &NoHandles, &Handles); + if (EFI_ERROR (Status)) { + // + // This is not an error, just an informative condition. + // + DEBUG ((DEBUG_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid, + Status)); + return; + } + + ASSERT (NoHandles > 0); + for (Idx = 0; Idx < NoHandles; ++Idx) { + CHAR16 *DevicePathText; + STATIC CHAR16 Fallback[] = L""; + + // + // The ConvertDevicePathToText() function handles NULL input transparently. + // + DevicePathText = ConvertDevicePathToText ( + DevicePathFromHandle (Handles[Idx]), + FALSE, // DisplayOnly + FALSE // AllowShortcuts + ); + if (DevicePathText == NULL) { + DevicePathText = Fallback; + } + + if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) { + Process (Handles[Idx], DevicePathText); + } + + if (DevicePathText != Fallback) { + FreePool (DevicePathText); + } + } + gBS->FreePool (Handles); +} + +/** + This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the + handle, and adds it to ConOut and ErrOut. +**/ +STATIC +VOID +EFIAPI +AddOutput ( + IN EFI_HANDLE Handle, + IN CONST CHAR16 *ReportText + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath = DevicePathFromHandle (Handle); + if (DevicePath == NULL) { + DEBUG ((DEBUG_ERROR, "%a: %s: handle %p: device path not found\n", + __FUNCTION__, ReportText, Handle)); + return; + } + + Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__, + ReportText, Status)); + return; + } + + Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__, + ReportText, Status)); + return; + } + + DEBUG ((DEBUG_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__, + ReportText)); +} + +STATIC +INTN +PlatformRegisterBootOption ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath, + CHAR16 *Description, + UINT32 Attributes + ) +{ + EFI_STATUS Status; + INTN OptionIndex; + EFI_BOOT_MANAGER_LOAD_OPTION NewOption; + EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions; + UINTN BootOptionCount; + + Status = EfiBootManagerInitializeLoadOption ( + &NewOption, + LoadOptionNumberUnassigned, + LoadOptionTypeBoot, + Attributes, + Description, + DevicePath, + NULL, + 0 + ); + ASSERT_EFI_ERROR (Status); + + BootOptions = EfiBootManagerGetLoadOptions ( + &BootOptionCount, LoadOptionTypeBoot + ); + + OptionIndex = EfiBootManagerFindLoadOption ( + &NewOption, BootOptions, BootOptionCount + ); + + if (OptionIndex == -1) { + Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN); + ASSERT_EFI_ERROR (Status); + OptionIndex = BootOptionCount; + } + + EfiBootManagerFreeLoadOption (&NewOption); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); + + return OptionIndex; +} + +STATIC +INTN +PlatformRegisterFvBootOption ( + CONST EFI_GUID *FileGuid, + CHAR16 *Description, + UINT32 Attributes + ) +{ + EFI_STATUS Status; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + INTN OptionIndex; + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + ASSERT_EFI_ERROR (Status); + + EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid); + DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle); + ASSERT (DevicePath != NULL); + DevicePath = AppendDevicePathNode ( + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &FileNode + ); + ASSERT (DevicePath != NULL); + + OptionIndex = PlatformRegisterBootOption (DevicePath, + Description, + Attributes); + FreePool (DevicePath); + + return OptionIndex; +} + + +STATIC +VOID +PlatformRegisterOptionsAndKeys ( + VOID + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Enter; + EFI_INPUT_KEY F1; + EFI_INPUT_KEY Esc; + EFI_BOOT_MANAGER_LOAD_OPTION BootOption; + INTN ShellOption; + + ShellOption = PlatformRegisterFvBootOption (&gUefiShellFileGuid, L"UEFI Shell", + LOAD_OPTION_ACTIVE); + if (ShellOption != -1) { + // + // F1 boots Shell. + // + F1.ScanCode = SCAN_F1; + F1.UnicodeChar = CHAR_NULL; + Status = EfiBootManagerAddKeyOptionVariable ( + NULL, (UINT16) ShellOption, 0, &F1, NULL); + ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); + } + + // + // Register ENTER as CONTINUE key + // + Enter.ScanCode = SCAN_NULL; + Enter.UnicodeChar = CHAR_CARRIAGE_RETURN; + Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL); + ASSERT_EFI_ERROR (Status); + + // + // Map ESC to Boot Manager Menu + // + Esc.ScanCode = SCAN_ESC; + Esc.UnicodeChar = CHAR_NULL; + Status = EfiBootManagerGetBootManagerMenu (&BootOption); + ASSERT_EFI_ERROR (Status); + Status = EfiBootManagerAddKeyOptionVariable ( + NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL + ); + ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); +} + +STATIC VOID +SerialConPrint ( + IN CHAR16 *Text + ) +{ + if (mSerialConProtocol != NULL) { + mSerialConProtocol->OutputString (mSerialConProtocol, Text); + } +} + +STATIC VOID EFIAPI +ExitBootServicesHandler ( + EFI_EVENT Event, + VOID *Context + ) +{ + EFI_STATUS Status; + CHAR16 *OsBootStr; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Green; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Yellow; + // + // Long enough to occlude the string printed + // in PlatformBootManagerWaitCallback. + // + STATIC CHAR16 *OsBootStrEL1 = L"Exiting UEFI and booting EL1 OS kernel!\r\n"; + STATIC CHAR16 *OsBootStrEL2 = L"Exiting UEFI and booting EL2 OS kernel!\r\n"; + + if (!PcdGet32 (PcdDebugShowUEFIExit)) { + return; + } + + if (PcdGet32 (PcdHypEnable)) { + OsBootStr = OsBootStrEL1; + } else { + OsBootStr = OsBootStrEL2; + } + + Green.Raw = 0x00007F00; + Black.Raw = 0x00000000; + Yellow.Raw = 0x00FFFF00; + + Status = BootLogoUpdateProgress (Yellow.Pixel, + Black.Pixel, + OsBootStr, + Green.Pixel, + 100, 0); + if (Status == EFI_SUCCESS) { + SerialConPrint(OsBootStr); + } else { + Print(L"\n"); + Print(OsBootStr); + Print(L"\n"); + } +} + +// +// BDS Platform Functions +// +/** + Do the platform init, can be customized by OEM/IBV + Possible things that can be done in PlatformBootManagerBeforeConsole: + > Update console variable: 1. include hot-plug devices; + > 2. Clear ConIn and add SOL for AMT + > Register new Driver#### or Boot#### + > Register new Key####: e.g.: F12 + > Signal ReadyToLock event + > Authentication action: 1. connect Auth devices; + > 2. Identify auto logon user. +**/ +VOID +EFIAPI +PlatformBootManagerBeforeConsole ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT ExitBSEvent; + ESRT_MANAGEMENT_PROTOCOL *EsrtManagement; + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + ExitBootServicesHandler, + NULL, + &gEfiEventExitBootServicesGuid, + &ExitBSEvent + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: failed to register ExitBootServices handler\n", + __FUNCTION__)); + } + + if (GetBootModeHob() == BOOT_ON_FLASH_UPDATE) { + DEBUG ((DEBUG_INFO, "ProcessCapsules Before EndOfDxe ......\n")); + Status = ProcessCapsules (); + DEBUG ((DEBUG_INFO, "ProcessCapsules returned %r\n", Status)); + } else { + Status = gBS->LocateProtocol (&gEsrtManagementProtocolGuid, NULL, + (VOID **)&EsrtManagement); + if (!EFI_ERROR (Status)) { + EsrtManagement->SyncEsrtFmp (); + } + } + + // + // Now add the device path of all handles with GOP on them to ConOut and + // ErrOut. + // + FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput); + + // + // Add the hardcoded short-form USB keyboard device path to ConIn. + // + EfiBootManagerUpdateConsoleVariable (ConIn, + (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL); + + // + // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut. + // + ASSERT (FixedPcdGet8 (PcdDefaultTerminalType) == 4); + CopyGuid (&mSerialConsole.TermType.Guid, &gEfiTtyTermGuid); + + EfiBootManagerUpdateConsoleVariable (ConIn, + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); + EfiBootManagerUpdateConsoleVariable (ConOut, + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, + (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL); + + // + // Signal EndOfDxe PI Event + // + EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid); + + // + // Dispatch deferred images after EndOfDxe event and ReadyToLock installation. + // + EfiBootManagerDispatchDeferredImages (); +} + +/** + Do the platform specific action after the console is ready + Possible things that can be done in PlatformBootManagerAfterConsole: + > Console post action: + > Dynamically switch output mode from 100x31 to 80x25 for certain senarino + > Signal console ready platform customized event + > Run diagnostics like memory testing + > Connect certain devices + > Dispatch aditional option roms + > Special boot: e.g.: USB boot, enter UI +**/ +VOID +EFIAPI +PlatformBootManagerAfterConsole ( + VOID + ) +{ + UINTN Index; + ESRT_MANAGEMENT_PROTOCOL *EsrtManagement; + EFI_STATUS Status; + EFI_HANDLE SerialHandle; + + Status = EfiBootManagerConnectDevicePath((EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, &SerialHandle); + if (Status == EFI_SUCCESS) { + gBS->HandleProtocol(SerialHandle, &gEfiSimpleTextOutProtocolGuid, + (VOID **) &mSerialConProtocol); + } + + // + // Show the splash screen. + // + Status = BootLogoEnableLogo (); + if (Status == EFI_SUCCESS) { + SerialConPrint(BOOT_PROMPT); + } else { + Print(BOOT_PROMPT); + } + + // + // Connect the rest of the devices. + // + EfiBootManagerConnectAll (); + + Status = gBS->LocateProtocol (&gEsrtManagementProtocolGuid, NULL, + (VOID **)&EsrtManagement); + if (!EFI_ERROR (Status)) { + EsrtManagement->SyncEsrtFmp (); + } + + if (GetBootModeHob() == BOOT_ON_FLASH_UPDATE) { + DEBUG((DEBUG_INFO, "ProcessCapsules After EndOfDxe ......\n")); + Status = ProcessCapsules (); + DEBUG((DEBUG_INFO, "ProcessCapsules returned %r\n", Status)); + } + + for (Index = 1; Index < 5; Index++) { + UINT16 Desc[11]; + /* + * Add boot options to allow booting from + * a mass storage device plugged into any + * of the RPi USB ports. + */ + mUsbHubPort.Dev.ParentPortNumber = Index; + UnicodeSPrint(Desc, sizeof (Desc), L"USB Port %u", Index); + PlatformRegisterBootOption ((VOID *) &mUsbHubPort, + Desc, LOAD_OPTION_ACTIVE); + } + + PlatformRegisterBootOption ((VOID *) &mSDHost, + L"uSD on SD Host", + LOAD_OPTION_ACTIVE); + PlatformRegisterBootOption ((VOID *) &mArasan, + L"uSD on Arasan MMC Host", + LOAD_OPTION_ACTIVE); + + PlatformRegisterOptionsAndKeys (); +} + +/** + This function is called each second during the boot manager waits the + timeout. + + @param TimeoutRemain The remaining timeout. +**/ +VOID +EFIAPI +PlatformBootManagerWaitCallback ( + UINT16 TimeoutRemain + ) +{ + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White; + UINT16 Timeout; + EFI_STATUS Status; + EFI_BOOT_LOGO_PROTOCOL *BootLogo; + + Timeout = PcdGet16 (PcdPlatformBootTimeOut); + + Black.Raw = 0x00000000; + White.Raw = 0x00FFFFFF; + + Status = BootLogoUpdateProgress ( + White.Pixel, + Black.Pixel, + BOOT_PROMPT, + White.Pixel, + (Timeout - TimeoutRemain) * 100 / Timeout, + 0 + ); + if (Status == EFI_SUCCESS) { + SerialConPrint(L"."); + } else { + Print(L"."); + } + + if (TimeoutRemain == 0) { + BootLogo = NULL; + + // + // Clear out the boot logo so that Windows displays its own logo + // instead of ours. + // + Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo); + if (!EFI_ERROR (Status) && (BootLogo != NULL)) { + Status = BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0); + ASSERT_EFI_ERROR (Status); + }; + + gST->ConOut->ClearScreen (gST->ConOut); + } +} + +/** + The function is called when no boot option could be launched, + including platform recovery options and options pointing to applications + built into firmware volumes. + If this function returns, BDS attempts to enter an infinite loop. +**/ +VOID +EFIAPI +PlatformBootManagerUnableToBoot( + VOID +) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu; + UINTN Index; + + // + // BootManagerMenu doesn't contain the correct information when return status + // is EFI_NOT_FOUND. + // + Status = EfiBootManagerGetBootManagerMenu(&BootManagerMenu); + if (EFI_ERROR(Status)) { + return; + } + // + // Normally BdsDxe does not print anything to the system console, but this is + // a last resort -- the end-user will likely not see any DEBUG messages + // logged in this situation. + // + // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn + // here to see if it makes sense to request and wait for a keypress. + // + if (gST->ConIn != NULL) { + AsciiPrint( + "%a: No bootable option or device was found.\n" + "%a: Press any key to enter the Boot Manager Menu.\n", + gEfiCallerBaseName, + gEfiCallerBaseName + ); + Status = gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &Index); + ASSERT_EFI_ERROR(Status); + ASSERT(Index == 0); + + // + // Drain any queued keys. + // + while (!EFI_ERROR(gST->ConIn->ReadKeyStroke(gST->ConIn, &Key))) { + // + // just throw away Key + // + } + } + + for (;;) { + EfiBootManagerBoot(&BootManagerMenu); + } +} diff --git a/Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBm.h b/Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBm.h new file mode 100644 index 000000000000..3717ba6174df --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBm.h @@ -0,0 +1,60 @@ +/** @file + * + * Copyright (c) 2017-2018, Andrei Warkentin + * Copyright (c) 2016, Linaro Ltd. All rights reserved. + * Copyright (c) 2015-2016, Red Hat, Inc. + * Copyright (c) 2014, ARM Ltd. All rights reserved. + * Copyright (c) 2004-2016, Intel Corporation. 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 _PLATFORM_BM_H_ +#define _PLATFORM_BM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Use SystemTable Conout to stop video based Simple Text Out consoles from + going to the video device. Put up LogoFile on every video device that is a + console. + + @param[in] LogoFile File name of logo to display on the center of the + screen. + + @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and logo + displayed. + @retval EFI_UNSUPPORTED Logo not found +**/ +EFI_STATUS +EnableQuietBoot ( + IN EFI_GUID *LogoFile + ); + +/** + Use SystemTable Conout to turn on video based Simple Text Out consoles. The + Simple Text Out screens will now be synced up with all non video output + devices + + @retval EFI_SUCCESS UGA devices are back in text mode and synced up. +**/ +EFI_STATUS +DisableQuietBoot ( + VOID + ); + +#endif // _PLATFORM_BM_H_ diff --git a/Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf new file mode 100644 index 000000000000..cb1d42364265 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf @@ -0,0 +1,90 @@ +#/** @file +# +# Copyright (c) 2017-2018, Andrei Warkentin +# Copyright (c) 2016, Linaro Ltd. All rights reserved. +# Copyright (c) 2015-2016, Red Hat, Inc. +# Copyright (c) 2014, ARM Ltd. All rights reserved. +# Copyright (c) 2007-2014, Intel Corporation. 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 = PlatformBootManagerLib + FILE_GUID = 92FD2DE3-B9CB-4B35-8141-42AD34D73C9F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = AARCH64 +# + +[Sources] + PlatformBm.c + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + BootLogoLib + CapsuleLib + DebugLib + DevicePathLib + DxeServicesLib + HobLib + MemoryAllocationLib + PcdLib + PrintLib + UefiBootManagerLib + UefiBootServicesTableLib + UefiLib + +[FeaturePcd] + gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport + +[FixedPcd] + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits + gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut + gRaspberryPiTokenSpaceGuid.PcdHypEnable + gRaspberryPiTokenSpaceGuid.PcdDebugShowUEFIExit + +[Guids] + gEfiFileInfoGuid + gEfiFileSystemInfoGuid + gEfiFileSystemVolumeLabelInfoIdGuid + gEfiEndOfDxeEventGroupGuid + gEfiTtyTermGuid + gUefiShellFileGuid + gEfiEventExitBootServicesGuid + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiGraphicsOutputProtocolGuid + gEfiLoadedImageProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEsrtManagementProtocolGuid + gEfiUsb2HcProtocolGuid + gEfiBootLogoProtocolGuid diff --git a/Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/AArch64/RaspberryPiHelper.S b/Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/AArch64/RaspberryPiHelper.S new file mode 100644 index 000000000000..91567de8bb78 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/AArch64/RaspberryPiHelper.S @@ -0,0 +1,107 @@ +/** @file + * + * Copyright (c) 2016, Linaro Limited. All rights reserved. + * Copyright (c) 2011-2013, ARM Limited. All rights reserved. + * + * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + **/ + +#include +#include +#include +#include + +#define MAX_TRIES 0x100000 + + .macro drain + mov x5, #MAX_TRIES +0: ldr w6, [x4, #BCM2836_MBOX_STATUS_OFFSET] + tbnz w6, #BCM2836_MBOX_STATUS_EMPTY, 1f + dmb ld + ldr wzr, [x4, #BCM2836_MBOX_READ_OFFSET] + subs x5, x5, #1 + b.ne 0b +1: + .endm + + .macro poll, status + mov x5, #MAX_TRIES +0: ldr w6, [x4, #BCM2836_MBOX_STATUS_OFFSET] + tbz w6, #\status, 1f + dmb ld + subs x5, x5, #1 + b.ne 0b +1: + .endm + +ASM_FUNC(ArmPlatformPeiBootAction) + adr x0, .Lmeminfo_buffer + mov x1, #FixedPcdGet64 (PcdDmaDeviceOffset) + orr x0, x0, #RPI_FW_MBOX_CHANNEL + add x0, x0, x1 + + MOV32 (x4, BCM2836_MBOX_BASE_ADDRESS) + + drain + poll BCM2836_MBOX_STATUS_FULL + str w0, [x4, #BCM2836_MBOX_WRITE_OFFSET] + dmb sy + poll BCM2836_MBOX_STATUS_EMPTY + dmb sy + ldr wzr, [x4, #BCM2836_MBOX_READ_OFFSET] + dmb ld + + ldr w0, .Lmemsize + sub x0, x0, #1 + adr x1, mSystemMemoryEnd + str x0, [x1] + ret + + .align 4 +.Lmeminfo_buffer: + .long .Lbuffer_size + .long 0x0 + .long RPI_FW_GET_ARM_MEMSIZE + .long 8 // buf size + .long 0 // input len + .long 0 // mem base +.Lmemsize: + .long 0 // mem size + .long 0 // end tag + .set .Lbuffer_size, . - .Lmeminfo_buffer + +//UINTN +//ArmPlatformGetPrimaryCoreMpId ( +// VOID +// ); +ASM_FUNC(ArmPlatformGetPrimaryCoreMpId) + MOV32 (w0, FixedPcdGet32 (PcdArmPrimaryCore)) + ret + +//UINTN +//ArmPlatformIsPrimaryCore ( +// IN UINTN MpId +// ); +ASM_FUNC(ArmPlatformIsPrimaryCore) + mov x0, #1 + ret + +//UINTN +//ArmPlatformGetCorePosition ( +// IN UINTN MpId +// ); +// With this function: CorePos = (ClusterId * 4) + CoreId +ASM_FUNC(ArmPlatformGetCorePosition) + and x1, x0, #ARM_CORE_MASK + and x0, x0, #ARM_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPi.c b/Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPi.c new file mode 100644 index 000000000000..ae0b7680f3c3 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPi.c @@ -0,0 +1,99 @@ +/** @file + * + * Copyright (c) 2014-2016, Linaro Limited. All rights reserved. + * Copyright (c) 2014, Red Hat, Inc. + * Copyright (c) 2011-2013, ARM Limited. All rights reserved. + * + * + * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + * + **/ + +#include +#include +#include +#include + +#include + +/** + Return the current Boot Mode + + This function returns the boot reason on the platform + + @return Return the current Boot Mode of the platform + +**/ +EFI_BOOT_MODE +ArmPlatformGetBootMode ( + VOID + ) +{ + return BOOT_WITH_FULL_CONFIGURATION; +} + +/** + This function is called by PrePeiCore, in the SEC phase. +**/ +RETURN_STATUS +ArmPlatformInitialize ( + IN UINTN MpId + ) +{ + return RETURN_SUCCESS; +} + +VOID +ArmPlatformInitializeSystemMemory ( + VOID + ) +{ +} + +STATIC ARM_CORE_INFO mRpi3InfoTable[] = { + { 0x0, 0x0, }, // Cluster 0, Core 0 + { 0x0, 0x1, }, // Cluster 0, Core 1 + { 0x0, 0x2, }, // Cluster 0, Core 2 + { 0x0, 0x3, }, // Cluster 0, Core 3 +}; + +STATIC +EFI_STATUS +PrePeiCoreGetMpCoreInfo ( + OUT UINTN *CoreCount, + OUT ARM_CORE_INFO **ArmCoreTable + ) +{ + // Only support one cluster + *CoreCount = sizeof(mRpi3InfoTable) / sizeof(ARM_CORE_INFO); + *ArmCoreTable = mRpi3InfoTable; + + return EFI_SUCCESS; +} + +STATIC ARM_MP_CORE_INFO_PPI mMpCoreInfoPpi = { + PrePeiCoreGetMpCoreInfo +}; +STATIC EFI_PEI_PPI_DESCRIPTOR mPlatformPpiTable[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gArmMpCoreInfoPpiGuid, + &mMpCoreInfoPpi + } +}; + +VOID +ArmPlatformGetPlatformPpiList ( + OUT UINTN *PpiListSize, + OUT EFI_PEI_PPI_DESCRIPTOR **PpiList + ) +{ + *PpiListSize = sizeof(mPlatformPpiTable); + *PpiList = mPlatformPpiTable; +} diff --git a/Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPiMem.c b/Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPiMem.c new file mode 100644 index 000000000000..69821e405134 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPiMem.c @@ -0,0 +1,160 @@ +/** @file + * + * Copyright (c) 2017-2018, Andrey Warkentin + * Copyright (c) 2014, Linaro 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 + +extern UINT64 mSystemMemoryEnd; +extern UINT64 mGPUMemoryBase; +extern UINT64 mGPUMemoryLength; + +#define VariablesSize (FixedPcdGet32(PcdFlashNvStorageVariableSize) + \ + FixedPcdGet32(PcdFlashNvStorageFtwWorkingSize) + \ + FixedPcdGet32(PcdFlashNvStorageFtwSpareSize) + \ + FixedPcdGet32(PcdNvStorageEventLogSize)) + +#define VariablesBase (FixedPcdGet64(PcdFdBaseAddress) + \ + FixedPcdGet32(PcdFdSize) - \ + VariablesSize) + +#define ATFBase (FixedPcdGet64(PcdFdBaseAddress) + FixedPcdGet32(PcdFdSize)) + +STATIC ARM_MEMORY_REGION_DESCRIPTOR RaspberryPiMemoryRegionDescriptor[] = { + { + /* Firmware Volume. */ + FixedPcdGet64(PcdFdBaseAddress), FixedPcdGet64(PcdFdBaseAddress), + FixedPcdGet32(PcdFdSize) - VariablesSize, + ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK + }, + { + /* Variables Volume. */ + VariablesBase, VariablesBase, + VariablesSize, + ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK + }, + { + /* ATF reserved RAM. */ + ATFBase, ATFBase, + FixedPcdGet64(PcdSystemMemoryBase) - ATFBase, + ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK + }, + { + /* System RAM. */ + FixedPcdGet64(PcdSystemMemoryBase), FixedPcdGet64(PcdSystemMemoryBase), + 0, + ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK + }, + { + /* Reserved GPU RAM. */ + 0, + 0, + 0, + ARM_MEMORY_REGION_ATTRIBUTE_DEVICE + }, + { + /* SOC registers. */ + BCM2836_SOC_REGISTERS, + BCM2836_SOC_REGISTERS, + BCM2836_SOC_REGISTER_LENGTH, + ARM_MEMORY_REGION_ATTRIBUTE_DEVICE + }, + { + } +}; + +/** + Return the Virtual Memory Map of your platform + + This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU + on your platform. + + @param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_DESCRIPTOR + describing a Physical-to-Virtual Memory + mapping. This array must be ended by a + zero-filled entry + +**/ +VOID +ArmPlatformGetVirtualMemoryMap ( + IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap + ) +{ + RaspberryPiMemoryRegionDescriptor[3].Length = mSystemMemoryEnd + 1 - + FixedPcdGet64(PcdSystemMemoryBase); + + RaspberryPiMemoryRegionDescriptor[4].PhysicalBase = + RaspberryPiMemoryRegionDescriptor[3].PhysicalBase + + RaspberryPiMemoryRegionDescriptor[3].Length; + + RaspberryPiMemoryRegionDescriptor[4].VirtualBase = + RaspberryPiMemoryRegionDescriptor[4].PhysicalBase; + + RaspberryPiMemoryRegionDescriptor[4].Length = + RaspberryPiMemoryRegionDescriptor[5].PhysicalBase - + RaspberryPiMemoryRegionDescriptor[4].PhysicalBase; + + DEBUG ((DEBUG_INFO, "FD:\n" + "\tPhysicalBase: 0x%lX\n" + "\tVirtualBase: 0x%lX\n" + "\tLength: 0x%lX\n", + RaspberryPiMemoryRegionDescriptor[0].PhysicalBase, + RaspberryPiMemoryRegionDescriptor[0].VirtualBase, + RaspberryPiMemoryRegionDescriptor[0].Length + + RaspberryPiMemoryRegionDescriptor[1].Length)); + + DEBUG ((DEBUG_INFO, "Variables (part of FD):\n" + "\tPhysicalBase: 0x%lX\n" + "\tVirtualBase: 0x%lX\n" + "\tLength: 0x%lX\n", + RaspberryPiMemoryRegionDescriptor[1].PhysicalBase, + RaspberryPiMemoryRegionDescriptor[1].VirtualBase, + RaspberryPiMemoryRegionDescriptor[1].Length)); + + DEBUG ((DEBUG_INFO, "ATF RAM:\n" + "\tPhysicalBase: 0x%lX\n" + "\tVirtualBase: 0x%lX\n" + "\tLength: 0x%lX\n", + RaspberryPiMemoryRegionDescriptor[2].PhysicalBase, + RaspberryPiMemoryRegionDescriptor[2].VirtualBase, + RaspberryPiMemoryRegionDescriptor[2].Length)); + + DEBUG ((DEBUG_INFO, "System RAM:\n" + "\tPhysicalBase: 0x%lX\n" + "\tVirtualBase: 0x%lX\n" + "\tLength: 0x%lX\n", + RaspberryPiMemoryRegionDescriptor[3].PhysicalBase, + RaspberryPiMemoryRegionDescriptor[3].VirtualBase, + RaspberryPiMemoryRegionDescriptor[3].Length)); + + DEBUG ((DEBUG_INFO, "GPU Reserved:\n" + "\tPhysicalBase: 0x%lX\n" + "\tVirtualBase: 0x%lX\n" + "\tLength: 0x%lX\n", + RaspberryPiMemoryRegionDescriptor[4].PhysicalBase, + RaspberryPiMemoryRegionDescriptor[4].VirtualBase, + RaspberryPiMemoryRegionDescriptor[4].Length)); + + DEBUG ((DEBUG_INFO, "SoC reserved:\n" + "\tPhysicalBase: 0x%lX\n" + "\tVirtualBase: 0x%lX\n" + "\tLength: 0x%lX\n", + RaspberryPiMemoryRegionDescriptor[5].PhysicalBase, + RaspberryPiMemoryRegionDescriptor[5].VirtualBase, + RaspberryPiMemoryRegionDescriptor[5].Length)); + + *VirtualMemoryMap = RaspberryPiMemoryRegionDescriptor; +} diff --git a/Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPiPlatformLib.inf b/Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPiPlatformLib.inf new file mode 100644 index 000000000000..2ee4450d79e4 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPiPlatformLib.inf @@ -0,0 +1,64 @@ +#/** @file +# +# Copyright (c) 2017-2018, Andrei Warkentin +# Copyright (c) 2014-2016, Linaro Limited. All rights reserved. +# Copyright (c) 2011-2014, ARM Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = RaspberryPiPlatformLib + FILE_GUID = 050182ef-f708-4148-b4bc-256cabf74fea + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmPlatformLib|SEC PEIM + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + ArmLib + FdtLib + IoLib + MemoryAllocationLib + PcdLib + PrintLib + +[Sources.common] + RaspberryPi.c + RaspberryPiMem.c + +[Sources.AARCH64] + AArch64/RaspberryPiHelper.S + +[FixedPcd] + gArmTokenSpaceGuid.PcdFdBaseAddress + gArmTokenSpaceGuid.PcdFvBaseAddress + gArmPlatformTokenSpaceGuid.PcdCoreCount + gArmTokenSpaceGuid.PcdArmPrimaryCoreMask + gArmTokenSpaceGuid.PcdArmPrimaryCore + gArmTokenSpaceGuid.PcdFdSize + gEmbeddedTokenSpaceGuid.PcdDmaDeviceOffset + gArmTokenSpaceGuid.PcdSystemMemoryBase + gArmTokenSpaceGuid.PcdSystemMemorySize + gRaspberryPiTokenSpaceGuid.PcdNvStorageEventLogSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + +[Ppis] + gArmMpCoreInfoPpiGuid diff --git a/Platform/Broadcom/Bcm283x/Library/ResetLib/ResetLib.c b/Platform/Broadcom/Bcm283x/Library/ResetLib/ResetLib.c new file mode 100644 index 000000000000..1a3944b71d03 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/ResetLib/ResetLib.c @@ -0,0 +1,104 @@ +/** @file + * + * Support ResetSystem Runtime call using PSCI calls. + * Signals the gRaspberryPiEventResetGuid event group on reset. + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) 2014, Linaro Ltd. All rights reserved. + * Copyright (c) 2013-2015, ARM Ltd. All rights reserved. + * Copyright (c) 2008-2009, 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. + * + **/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +/** + Resets the entire platform. + + @param ResetType The type of reset to perform. + @param ResetStatus The status code for the reset. + @param DataSize The size, in bytes, of WatchdogData. + @param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or + EfiResetShutdown the data buffer starts with a Null-terminated + Unicode string, optionally followed by additional binary data. + +**/ +EFI_STATUS +EFIAPI +LibResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData OPTIONAL + ) +{ + ARM_SMC_ARGS ArmSmcArgs; + + if (!EfiAtRuntime ()) { + /* + * Only if still in UEFI. + */ + EfiEventGroupSignal(&gRaspberryPiEventResetGuid); + } + + switch (ResetType) { + case EfiResetPlatformSpecific: + // Map the platform specific reset as reboot + case EfiResetWarm: + // Map a warm reset into a cold reset + case EfiResetCold: + // Send a PSCI 0.2 SYSTEM_RESET command + ArmSmcArgs.Arg0 = ARM_SMC_ID_PSCI_SYSTEM_RESET; + break; + case EfiResetShutdown: + // Send a PSCI 0.2 SYSTEM_OFF command + ArmSmcArgs.Arg0 = ARM_SMC_ID_PSCI_SYSTEM_OFF; + break; + default: + ASSERT (FALSE); + return EFI_UNSUPPORTED; + } + + ArmCallSmc (&ArmSmcArgs); + + // We should never be here + DEBUG ((DEBUG_ERROR, "%a: PSCI Reset failed\n", __FUNCTION__)); + CpuDeadLoop (); + return EFI_UNSUPPORTED; +} + +/** + Initialize any infrastructure required for LibResetSystem () to function. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +LibInitializeResetSystem ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} diff --git a/Platform/Broadcom/Bcm283x/Library/ResetLib/ResetLib.inf b/Platform/Broadcom/Bcm283x/Library/ResetLib/ResetLib.inf new file mode 100644 index 000000000000..1c32a4b08162 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/ResetLib/ResetLib.inf @@ -0,0 +1,46 @@ +#/** @file +# +# Reset System lib using PSCI hypervisor or secure monitor calls. +# Signals the gRaspberryPiEventResetGuid event group on reset. +# +# Copyright (c) 2018, Andrei Warkentin +# Copyright (c) 2014, Linaro Ltd. All rights reserved. +# Copyright (c) 2014, ARM Ltd. All rights reserved. +# Copyright (c) 2008, 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. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ResetLib + FILE_GUID = B9F59B69-A105-41C7-8F5A-2C60DD7FD7AB + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = EfiResetSystemLib + +[Sources] + ResetLib.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + DebugLib + BaseLib + ArmSmcLib + UefiLib + UefiRuntimeLib + +[Guids] + gRaspberryPiEventResetGuid diff --git a/Platform/Broadcom/Bcm283x/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c b/Platform/Broadcom/Bcm283x/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c new file mode 100644 index 000000000000..5e1dd768331a --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c @@ -0,0 +1,222 @@ +/** @file + * + * Implement dummy EFI RealTimeClock runtime services. + * + * Copyright (c) 2018, Andrei Warkentin + * Copyright (c) Microsoft Corporation. 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 + +/** + Returns the current time and date information, and the time-keeping capabilities + of the virtual RTC. + + For simplicity, this LibGetTime does not report Years/Months, instead it will only report current + Day, Hours, Minutes and Seconds starting from the begining of CPU up-time. Otherwise, a more + complex logic will be required to account for leap years and days/month differences. + + @param Time A pointer to storage to receive a snapshot of the current time. + @param Capabilities An optional pointer to a buffer to receive the real time clock + device's capabilities. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Time is NULL. + @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. + +**/ +EFI_STATUS +EFIAPI +LibGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ) +{ + UINTN DataSize; + UINT64 Counter; + EFI_STATUS Status; + UINTN ElapsedSeconds; + UINT32 Remainder; + UINT32 Freq = ArmGenericTimerGetTimerFreq(); + + if (Time == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Depend on ARM generic timer to report date/time relative to the + // start of CPU timer counting where date and time will always + // be relative to the date/time 1/1/1900 00H:00M:00S + // + + ASSERT (Freq != 0); + if (Freq == 0) { + return EFI_DEVICE_ERROR; + } + + if (Capabilities) { + Capabilities->Accuracy = 0; + Capabilities->Resolution = Freq; + Capabilities->SetsToZero = FALSE; + } + + DataSize = sizeof (UINTN); + ElapsedSeconds = 0; + Status = EfiGetVariable (L"RtcEpochSeconds", + &gEfiCallerIdGuid, + NULL, + &DataSize, + &ElapsedSeconds); + if (EFI_ERROR (Status)) { + ElapsedSeconds = PcdGet64(PcdBootEpochSeconds); + } + Counter = GetPerformanceCounter (); + ElapsedSeconds += DivU64x32Remainder (Counter, Freq, &Remainder); + EpochToEfiTime (ElapsedSeconds, Time); + + // + // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000) + // will not overflow 64-bit. + // + Time->Nanosecond = DivU64x32 (MultU64x64 ((UINT64) Remainder, + 1000000000U), Freq); + + return EFI_SUCCESS; +} + + +/** + Sets the current local time and date information. + + @param Time A pointer to the current time. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. + +**/ +EFI_STATUS +EFIAPI +LibSetTime ( + IN EFI_TIME *Time + ) +{ + UINTN Epoch; + + if (!IsTimeValid(Time)) { + return EFI_INVALID_PARAMETER; + } + + Epoch = EfiTimeToEpoch(Time); + return EfiSetVariable(L"RtcEpochSeconds", &gEfiCallerIdGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + sizeof (Epoch), + &Epoch); +} + + +/** + Returns the current wakeup alarm clock setting. + + @param Enabled Indicates if the alarm is currently enabled or disabled. + @param Pending Indicates if the alarm signal is pending and requires acknowledgement. + @param Time The current alarm setting. + + @retval EFI_SUCCESS The alarm settings were returned. + @retval EFI_INVALID_PARAMETER Any parameter is NULL. + @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error. + +**/ +EFI_STATUS +EFIAPI +LibGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Sets the system wakeup alarm clock time. + + @param Enabled Enable or disable the wakeup alarm. + @param Time If Enable is TRUE, the time to set the wakeup alarm for. + + @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If + Enable is FALSE, then the wakeup alarm was disabled. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error. + @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. + +**/ +EFI_STATUS +EFIAPI +LibSetWakeupTime ( + IN BOOLEAN Enabled, + OUT EFI_TIME *Time + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + This is the declaration of an EFI image entry point. This can be the entry point to an application + written to this specification, an EFI boot service driver, or an EFI runtime driver. + + @param ImageHandle Handle that identifies the loaded image. + @param SystemTable System Table for this image. + + @retval EFI_SUCCESS The operation completed successfully. + +**/ +EFI_STATUS +EFIAPI +LibRtcInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + + +/** + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +LibRtcVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + return; +} diff --git a/Platform/Broadcom/Bcm283x/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf b/Platform/Broadcom/Bcm283x/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf new file mode 100644 index 000000000000..847bcfadd824 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf @@ -0,0 +1,43 @@ +#/** @file +# +# Implement dummy EFI RealTimeClock runtime services. +# +# Copyright (c) 2018, Andrei Warkentin +# Copyright (c) Microsoft Corporation. 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 = VirtualRealTimeClockLib + FILE_GUID = 1E27D461-78F3-4F7D-B1C2-F72384F13A6E + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = RealTimeClockLib + +[Sources.common] + VirtualRealTimeClockLib.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec + +[LibraryClasses] + IoLib + DebugLib + TimerLib + TimeBaseLib + UefiRuntimeLib + +[Pcd] + gRaspberryPiTokenSpaceGuid.PcdBootEpochSeconds diff --git a/Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec b/Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec new file mode 100644 index 000000000000..51f2f07aab8a --- /dev/null +++ b/Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec @@ -0,0 +1,63 @@ +## @file +# +# Copyright (c) 2016, Linaro, Ltd. All rights reserved. +# Copyright (c) 2017 - 2018, Andrei Warkentin +# +# 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 = RaspberryPiPkg + PACKAGE_GUID = DFA0CA8B-F3AC-4607-96AC-46FA04B84DCC + PACKAGE_VERSION = 0.1 + +[Includes] + Include + +[Protocols] + gRaspberryPiFirmwareProtocolGuid = { 0x0ACA9535, 0x7AD0, 0x4286, { 0xB0, 0x2E, 0x87, 0xFA, 0x7E, 0x2A, 0x57, 0x11 } } + gRaspberryPiConfigAppliedProtocolGuid = { 0x0ACA4444, 0x7AD0, 0x4286, { 0xB0, 0x2E, 0x87, 0xFA, 0x7E, 0x2A, 0x57, 0x11 } } + gRaspberryPiMmcHostProtocolGuid = { 0x3e591c00, 0x9e4a, 0x11df, {0x92, 0x44, 0x00, 0x02, 0xA5, 0xF5, 0xF5, 0x1B } } + gExtendedTextOutputProtocolGuid = { 0x387477ff, 0xffc7, 0xffd2, {0x8e, 0x39, 0x0, 0xff, 0xc9, 0x69, 0x72, 0x3b } } + +[Guids] + gRaspberryPiTokenSpaceGuid = {0xCD7CC258, 0x31DB, 0x11E6, {0x9F, 0xD3, 0x63, 0xB0, 0xB8, 0xEE, 0xD6, 0xB5}} + gRaspberryPiFdtFileGuid = {0xDF5DA223, 0x1D27, 0x47C3, { 0x8D, 0x1B, 0x9A, 0x41, 0xB5, 0x5A, 0x18, 0xBC}} + gRaspberryPiEventResetGuid = {0xCD7CC258, 0x31DB, 0x11E6, {0x9F, 0xD3, 0x63, 0xB4, 0xB4, 0xE4, 0xD4, 0xB4}} + gConfigDxeFormSetGuid = {0xCD7CC258, 0x31DB, 0x22E6, {0x9F, 0x22, 0x63, 0xB0, 0xB8, 0xEE, 0xD6, 0xB5}} + +[PcdsFixedAtBuild.common] + gRaspberryPiTokenSpaceGuid.PcdFdtBaseAddress|0x10000|UINT32|0x00000001 + gRaspberryPiTokenSpaceGuid.PcdFirmwareBlockSize|0x0|UINT32|0x00000002 + gRaspberryPiTokenSpaceGuid.PcdNvStorageEventLogBase|0x0|UINT32|0x00000003 + gRaspberryPiTokenSpaceGuid.PcdNvStorageEventLogSize|0x0|UINT32|0x00000004 + gRaspberryPiTokenSpaceGuid.PcdNvStorageVariableBase|0x0|UINT32|0x00000005 + gRaspberryPiTokenSpaceGuid.PcdNvStorageFtwSpareBase|0x0|UINT32|0x00000006 + gRaspberryPiTokenSpaceGuid.PcdNvStorageFtwWorkingBase|0x0|UINT32|0x00000007 + gRaspberryPiTokenSpaceGuid.PcdBootEpochSeconds|0x0|UINT64|0x00000008 + +[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx] + gRaspberryPiTokenSpaceGuid.PcdHypEnable|0|UINT32|0x00000009 + gRaspberryPiTokenSpaceGuid.PcdHypLogMask|0|UINT32|0x0000000a + gRaspberryPiTokenSpaceGuid.PcdHypWindowsDebugHook|0|UINT32|0x0000000b + gRaspberryPiTokenSpaceGuid.PcdHypWin2000Mask|0|UINT32|0x0000000c + gRaspberryPiTokenSpaceGuid.PcdCpuClock|0|UINT32|0x0000000d + gRaspberryPiTokenSpaceGuid.PcdSdIsArasan|0|UINT32|0x0000000e + gRaspberryPiTokenSpaceGuid.PcdMmcForce1Bit|0|UINT32|0x0000000f + gRaspberryPiTokenSpaceGuid.PcdMmcForceDefaultSpeed|0|UINT32|0x00000010 + gRaspberryPiTokenSpaceGuid.PcdMmcSdDefaultSpeedMHz|0|UINT32|0x00000011 + gRaspberryPiTokenSpaceGuid.PcdMmcSdHighSpeedMHz|0|UINT32|0x00000012 + gRaspberryPiTokenSpaceGuid.PcdMmcDisableMulti|0|UINT32|0x00000013 + gRaspberryPiTokenSpaceGuid.PcdDebugEnableJTAG|0|UINT32|0x00000014 + gRaspberryPiTokenSpaceGuid.PcdDebugShowUEFIExit|0|UINT32|0x00000015 + gRaspberryPiTokenSpaceGuid.PcdDisplayEnableVModes|0|UINT32|0x00000017 + gRaspberryPiTokenSpaceGuid.PcdDisplayEnableSShot|0|UINT32|0x00000018 diff --git a/Platform/Broadcom/Bcm283x/RaspberryPiPkg.dsc b/Platform/Broadcom/Bcm283x/RaspberryPiPkg.dsc new file mode 100644 index 000000000000..8610fae0b92f --- /dev/null +++ b/Platform/Broadcom/Bcm283x/RaspberryPiPkg.dsc @@ -0,0 +1,636 @@ +# @file +# +# Copyright (c) 2011-2015, ARM Limited. All rights reserved. +# Copyright (c) 2014, Linaro Limited. All rights reserved. +# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved. +# Copyright (c) 2017 - 2018, Andrei Warkentin +# +# 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 Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = RaspberryPi + PLATFORM_GUID = 5d30c4fc-93cf-40c9-8486-3badc0410816 + PLATFORM_VERSION = 0.3 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/RaspberryPiPkg + SUPPORTED_ARCHITECTURES = AARCH64 + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = Platform/Broadcom/Bcm283x/RaspberryPiPkg.fdf + + # + # Defines for default states. These can be changed on the command line. + # -D FLAG=VALUE + # + DEFINE SECURE_BOOT_ENABLE = FALSE + DEFINE DEBUG_PRINT_ERROR_LEVEL = 0x8000004F + +!ifndef BUILD_EPOCH + DEFINE BUILD_EPOCH = 1546300800 +!endif +################################################################################ +# +# Library Class section - list of all Library Classes needed by this Platform. +# +################################################################################ +[LibraryClasses.common] +!if $(TARGET) == RELEASE + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf +!else + DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf +!endif + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf + + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + + # + # Ramdisk Requirements + # + FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf + + # Allow dynamic PCDs + # + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + + # use the accelerated BaseMemoryLibOptDxe by default, overrides for SEC/PEI below + BaseMemoryLib|MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf + + # Networking Requirements + NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf + DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf + UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf + IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf + + # + # It is not possible to prevent the ARM compiler from inserting calls to intrinsic functions. + # This library provides the instrinsic functions such a compiler may generate calls to. + # + NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf + + # Add support for GCC stack protector + NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf + + # ARM Architectural Libraries + CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf + DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf + CpuExceptionHandlerLib|ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf + ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf + DmaLib|EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf + TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf + ArmPlatformStackLib|ArmPlatformPkg/Library/ArmPlatformStackLib/ArmPlatformStackLib.inf + ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf + ArmHvcLib|ArmPkg/Library/ArmHvcLib/ArmHvcLib.inf + ArmGenericTimerCounterLib|ArmPkg/Library/ArmGenericTimerPhyCounterLib/ArmGenericTimerPhyCounterLib.inf + + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf + SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf + + # + # Uncomment (and comment out the next line) For RealView Debugger. The Standard IO window + # in the debugger will show load and unload commands for symbols. You can cut and paste this + # into the command window to load symbols. We should be able to use a script to do this, but + # the version of RVD I have does not support scripts accessing system memory. + # + #PeCoffExtraActionLib|ArmPkg/Library/RvdPeCoffExtraActionLib/RvdPeCoffExtraActionLib.inf + PeCoffExtraActionLib|ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.inf + #PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + DebugAgentTimerLib|EmbeddedPkg/Library/DebugAgentTimerLibNull/DebugAgentTimerLibNull.inf + + # Flattened Device Tree (FDT) access library + FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf + + # USB Libraries + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + + # + # Secure Boot dependencies + # +!if $(SECURE_BOOT_ENABLE) == TRUE + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf + AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + + # re-use the UserPhysicalPresent() dummy implementation from the ovmf tree + PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf +!else + TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf +!endif + VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf + GpioLib|Platform/Broadcom/Bcm283x/Library/GpioLib/GpioLib.inf + +[LibraryClasses.common.SEC] + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + MemoryInitPeiLib|Platform/Broadcom/Bcm283x/Library/MemoryInitPeiLib/MemoryInitPeiLib.inf + PlatformPeiLib|ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf + ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf + LzmaDecompressLib|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf + PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf + HobLib|EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf + PrePiHobListPointerLib|ArmPlatformPkg/Library/PrePiHobListPointerLib/PrePiHobListPointerLib.inf + MemoryAllocationLib|EmbeddedPkg/Library/PrePiMemoryAllocationLib/PrePiMemoryAllocationLib.inf + +[LibraryClasses.common.DXE_CORE] + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf + +[LibraryClasses.common.DXE_DRIVER] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + +[LibraryClasses.common.UEFI_APPLICATION] + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + UefiDecompressLib|IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + EfiResetSystemLib|Platform/Broadcom/Bcm283x/Library/ResetLib/ResetLib.inf + ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf + +!if $(SECURE_BOOT_ENABLE) == TRUE + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf +!endif + +################################################################################################### +# BuildOptions Section - Define the module specific tool chain flags that should be used as +# the default flags for a module. These flags are appended to any +# standard flags that are defined by the build process. +################################################################################################### + +[BuildOptions] + GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG -DNDEBUG + +[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER] + GCC:*_*_AARCH64_DLINK_FLAGS = -z common-page-size=0x10000 + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ + +[PcdsFeatureFlag.common] + # Use the Vector Table location in CpuDxe. We will not copy the Vector Table at PcdCpuVectorBaseAddress + gArmTokenSpaceGuid.PcdRelocateVectorTable|FALSE + + gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|TRUE + + ## If TRUE, Graphics Output Protocol will be installed on virtual handle created by ConsplitterDxe. + # It could be set FALSE to save size. + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE + +[PcdsFixedAtBuild.common] + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|1000000 + gEfiMdePkgTokenSpaceGuid.PcdSpinLockTimeout|10000000 + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue|0xAF + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|1 + gEfiMdePkgTokenSpaceGuid.PcdPostCodePropertyMask|0 + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|320 + + # DEBUG_ASSERT_ENABLED 0x01 + # DEBUG_PRINT_ENABLED 0x02 + # DEBUG_CODE_ENABLED 0x04 + # CLEAR_MEMORY_ENABLED 0x08 + # ASSERT_BREAKPOINT_ENABLED 0x10 + # ASSERT_DEADLOOP_ENABLED 0x20 +!if $(TARGET) == RELEASE + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x21 +!else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2f +!endif + + # DEBUG_INIT 0x00000001 // Initialization + # DEBUG_WARN 0x00000002 // Warnings + # DEBUG_LOAD 0x00000004 // Load events + # DEBUG_FS 0x00000008 // EFI File system + # DEBUG_POOL 0x00000010 // Alloc & Free (pool) + # DEBUG_PAGE 0x00000020 // Alloc & Free (page) + # DEBUG_INFO 0x00000040 // Informational debug messages + # DEBUG_DISPATCH 0x00000080 // PEI/DXE/SMM Dispatchers + # DEBUG_VARIABLE 0x00000100 // Variable + # DEBUG_BM 0x00000400 // Boot Manager + # DEBUG_BLKIO 0x00001000 // BlkIo Driver + # DEBUG_NET 0x00004000 // SNP Driver + # DEBUG_UNDI 0x00010000 // UNDI Driver + # DEBUG_LOADFILE 0x00020000 // LoadFile + # DEBUG_EVENT 0x00080000 // Event messages + # DEBUG_GCD 0x00100000 // Global Coherency Database changes + # DEBUG_CACHE 0x00200000 // Memory range cachability changes + # DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may + # // significantly impact boot performance + # DEBUG_ERROR 0x80000000 // Error + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|$(DEBUG_PRINT_ERROR_LEVEL) + + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 + + # + # Optional feature to help prevent EFI memory map fragments + # Turned on and off via: PcdPrePiProduceMemoryTypeInformationHob + # Values are in EFI Pages (4K). DXE Core will make sure that + # at least this much of each type of memory can be allocated + # from a single memory range. This way you only end up with + # maximum of two fragments for each type in the memory map + # (the memory used, and the free memory that was prereserved + # but not used). + # + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0 +!if $(SECURE_BOOT_ENABLE) == TRUE + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|600 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|400 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|1500 +!else + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|300 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|150 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesCode|1000 +!endif + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiBootServicesData|12000 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderCode|20 + gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiLoaderData|0 + + gEmbeddedTokenSpaceGuid.PcdDmaDeviceOffset|0xc0000000 + +!if $(SECURE_BOOT_ENABLE) == TRUE + # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot + gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x04 + gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy|0x04 + gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy|0x04 +!endif + + gEmbeddedTokenSpaceGuid.PcdInterruptBaseAddress|0x40000000 + gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum|0x0 + gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|0x1 + gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|0x2 + gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum|0x3 + +[LibraryClasses.common] + ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf + ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf + ArmPlatformLib|Platform/Broadcom/Bcm283x/Library/RaspberryPiPlatformLib/RaspberryPiPlatformLib.inf + TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf + BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf + PlatformBootManagerLib|Platform/Broadcom/Bcm283x/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf + CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf + FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf + +[LibraryClasses.common.UEFI_DRIVER] + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf + + +################################################################################ +# +# Pcd Section - list of all EDK II PCD Entries defined by this Platform +# +################################################################################ + +[PcdsFeatureFlag.common] + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE + +[PcdsFixedAtBuild.common] + gArmPlatformTokenSpaceGuid.PcdCoreCount|4 + gArmTokenSpaceGuid.PcdVFPEnabled|1 + + gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize|0x4000 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000 + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800 + + # Size of the region used by UEFI in permanent memory (Reserved 64MB) + gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize|0x04000000 + # + # This matches PcdFvBaseAddress, since everything less is ATF, and + # will be reserved away. + # + gArmTokenSpaceGuid.PcdSystemMemoryBase|0x00400000 + gArmTokenSpaceGuid.PcdSystemMemorySize|0x3FC00000 + + ## NS16550 compatible UART + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x3f215040 + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|TRUE + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|4 + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|500000000 + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl|0x27 + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialExtendedTxFifoSize|8 + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200 + + ## Default Terminal Type + ## 0-PCANSI, 1-VT100, 2-VT00+, 3-UTF8, 4-TTYTERM + gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|4 + + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 } + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 } + + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|L"Raspberry Pi 3 64-bit UEFI" + + # + # Build timestamp. This is used if RtcEpochSeconds NVRAM + # variable is not present. + # + gRaspberryPiTokenSpaceGuid.PcdBootEpochSeconds|$(BUILD_EPOCH) + gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack|TRUE + +[PcdsDynamicHii.common.DEFAULT] + + # + # Clock overrides. + # + + gRaspberryPiTokenSpaceGuid.PcdCpuClock|L"CpuClock"|gConfigDxeFormSetGuid|0x0|0 + + # + # SD-related. + # + + gRaspberryPiTokenSpaceGuid.PcdSdIsArasan|L"SdIsArasan"|gConfigDxeFormSetGuid|0x0|0 + gRaspberryPiTokenSpaceGuid.PcdMmcForce1Bit|L"MmcForce1Bit"|gConfigDxeFormSetGuid|0x0|0 + gRaspberryPiTokenSpaceGuid.PcdMmcForceDefaultSpeed|L"MmcForceDefaultSpeed"|gConfigDxeFormSetGuid|0x0|0 + gRaspberryPiTokenSpaceGuid.PcdMmcSdDefaultSpeedMHz|L"MmcSdDefaultSpeedMHz"|gConfigDxeFormSetGuid|0x0|25 + gRaspberryPiTokenSpaceGuid.PcdMmcSdHighSpeedMHz|L"MmcSdHighSpeedMHz"|gConfigDxeFormSetGuid|0x0|50 + gRaspberryPiTokenSpaceGuid.PcdMmcDisableMulti|L"MmcDisableMulti"|gConfigDxeFormSetGuid|0x0|0 + + # + # Debug-related. + # + + gRaspberryPiTokenSpaceGuid.PcdDebugEnableJTAG|L"DebugEnableJTAG"|gConfigDxeFormSetGuid|0x0|0 + gRaspberryPiTokenSpaceGuid.PcdDebugShowUEFIExit|L"DebugShowUEFIExit"|gConfigDxeFormSetGuid|0x0|0 + + # + # Display-related. + # + gRaspberryPiTokenSpaceGuid.PcdDisplayEnableVModes|L"DisplayEnableVModes"|gConfigDxeFormSetGuid|0x0|0 + gRaspberryPiTokenSpaceGuid.PcdDisplayEnableSShot|L"DisplayEnableSShot"|gConfigDxeFormSetGuid|0x0|1 + + # + # Common UEFI ones. + # + + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|5 + # + # This is silly, but by pointing SetupConXXX and ConXXX PCDs to + # the same variables, I can use the graphical configuration to + # change the mode used by ConSplitter. + # + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutColumn|L"Columns"|gRaspberryPiTokenSpaceGuid|0x0|80 + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|L"Columns"|gRaspberryPiTokenSpaceGuid|0x0|80 + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow|L"Rows"|gRaspberryPiTokenSpaceGuid|0x0|25 + gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|L"Rows"|gRaspberryPiTokenSpaceGuid|0x0|25 + +[PcdsDynamicDefault.common] + # + # Set video resolution for boot options and for text setup. + # + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|640 + gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|480 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0 + +################################################################################ +# +# Components Section - list of all EDK II Modules needed by this Platform +# +################################################################################ +[Components.common] + # + # PEI Phase modules + # + ArmPlatformPkg/PrePi/PeiUniCore.inf + + # + # DXE + # + MdeModulePkg/Core/Dxe/DxeMain.inf { + + NULL|MdeModulePkg/Library/DxeCrc32GuidedSectionExtractLib/DxeCrc32GuidedSectionExtractLib.inf + } + MdeModulePkg/Universal/PCD/Dxe/Pcd.inf { + + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + } + + # + # Architectural Protocols + # + ArmPkg/Drivers/CpuDxe/CpuDxe.inf + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockServiceDxe.inf + MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf { + + NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + } +!if $(SECURE_BOOT_ENABLE) == TRUE + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf { + + NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf + } + SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +!else + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf +!endif + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf { + + RealTimeClockLib|Platform/Broadcom/Bcm283x/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf + } + EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf + + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + MdeModulePkg/Universal/SerialDxe/SerialDxe.inf + Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.inf + + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + + UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf + Platform/Broadcom/Bcm283x/Drivers/Bcm2836InterruptDxe/Bcm2836InterruptDxe.inf + Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf + Platform/Broadcom/Bcm283x/Drivers/RpiFdtDxe/RpiFdtDxe.inf + Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxe.inf + ArmPkg/Drivers/TimerDxe/TimerDxe.inf + MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + MdeModulePkg/Universal/EbcDxe/EbcDxe.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + FatPkg/EnhancedFatDxe/Fat.inf + + # + # ACPI Support + # + MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf + MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf + MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf + Platform/Broadcom/Bcm283x/AcpiTables/AcpiTables.inf + + # + # SMBIOS Support + # + Platform/Broadcom/Bcm283x/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf + MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + + # + # Bds + # + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf + MdeModulePkg/Universal/BdsDxe/BdsDxe.inf + Platform/Broadcom/Bcm283x/Drivers/Logo/LogoDxe.inf + MdeModulePkg/Application/UiApp/UiApp.inf { + + NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf + NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf + NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf + } + + # + # SCSI Bus and Disk Driver + # + MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + + # + # USB Support + # + Platform/Broadcom/Bcm283x/Drivers/DwUsbHostDxe/DwUsbHostDxe.inf + MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf + MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772b/Ax88772b.inf + + # + # SD/MMC support + # + Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.inf + Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.inf + Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcDxe.inf + + # + # Networking stack + # + MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf + MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf + MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf + MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf + MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf + MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf + MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf + MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf + MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf + MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf + MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf + + # + # UEFI application (Shell Embedded Boot Loader) + # + ShellPkg/Application/Shell/Shell.inf { + + ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf + NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf + NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf + NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf + NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf + HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf + + + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF + gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000 + gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize|0x200000 + } diff --git a/Platform/Broadcom/Bcm283x/RaspberryPiPkg.fdf b/Platform/Broadcom/Bcm283x/RaspberryPiPkg.fdf new file mode 100644 index 000000000000..4da8849b3646 --- /dev/null +++ b/Platform/Broadcom/Bcm283x/RaspberryPiPkg.fdf @@ -0,0 +1,450 @@ +## @file +# +# Copyright (c) 2011-2015, ARM Limited. All rights reserved. +# Copyright (c) 2014, Linaro Limited. All rights reserved. +# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved. +# Copyright (c) 2017 - 2018, Andrei Warkentin +# +# 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. +# +## + +################################################################################ +# +# FD Section +# The [FD] Section is made up of the definition statements and a +# description of what goes into the Flash Device Image. Each FD section +# defines one flash "device" image. A flash device image may be one of +# the following: Removable media bootable image (like a boot floppy +# image,) an Option ROM image (that would be "flashed" into an add-in +# card,) a System "Flash" image (that would be burned into a system's +# flash) or an Update ("Capsule") image that will be used to update and +# existing system flash. +# +################################################################################ + +[FD.RPI_EFI] +BaseAddress = 0x00000000|gArmTokenSpaceGuid.PcdFdBaseAddress +Size = 0x00200000|gArmTokenSpaceGuid.PcdFdSize +ErasePolarity = 1 + +BlockSize = 0x00001000|gRaspberryPiTokenSpaceGuid.PcdFirmwareBlockSize +NumBlocks = 0x200 + +################################################################################ +# +# Following are lists of FD Region layout which correspond to the locations of different +# images within the flash device. +# +# Regions must be defined in ascending order and may not overlap. +# +# A Layout Region start with a eight digit hex offset (leading "0x" required) followed by +# the pipe "|" character, followed by the size of the region, also in hex with the leading +# "0x" characters. Like: +# Offset|Size +# PcdOffsetCName|PcdSizeCName +# RegionType +# +################################################################################ + +# +# ATF primary boot image +# +0x00000000|0x00010000 +FILE = Platform/Broadcom/Bcm283x/Binary/bl1.bin + +# +# DTB. +# +0x00010000|0x00010000 +DATA = { 0x00 } + +# +# ATF secondary boot image in FIP format (BL2 + BL31) +# +0x00020000|0x00010000 +FILE = Platform/Broadcom/Bcm283x/Binary/fip.bin + +# +# UEFI image +# +0x00030000|0x001b0000 +gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize +FV = FVMAIN_COMPACT + +# +# Variables (0x20000 overall). +# +# 0x001e0000 - 0x001edfff EFI_FIRMWARE_VOLUME_HEADER +# 0x001ee000 - 0x001eefff Event log +# 0x001ef000 - 0x001effff EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER- +# 0x001f0000 - 0x001fffff Data +# + +# NV_VARIABLE_STORE +0x001e0000|0x0000e000 +gRaspberryPiTokenSpaceGuid.PcdNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + +DATA = { + ## This is the EFI_FIRMWARE_VOLUME_HEADER + # ZeroVector [] + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + # FileSystemGuid: gEfiSystemNvDataFvGuid = + # { 0xFFF12B8D, 0x7696, 0x4C8B, + # { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }} + 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, + 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50, + # FvLength: 0x20000 + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + # Signature "_FVH" # Attributes + 0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00, + # HeaderLength + 0x48, 0x00, + # CheckSum + 0x19, 0xF9, + # ExtHeaderOffset #Reserved #Revision + 0x00, 0x00, 0x00, 0x02, + # Blockmap[0]: 0x20 Blocks * 0x1000 Bytes / Block + 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + # Blockmap[1]: End + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ## This is the VARIABLE_STORE_HEADER + # It is compatible with SECURE_BOOT_ENABLE == FALSE as well. + # Signature: gEfiAuthenticatedVariableGuid = + # { 0xaaf32c78, 0x947b, 0x439a, + # { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 }} + 0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43, + 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92, + # Size: 0xe000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) - + # 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0xdfb8 + # This can speed up the Variable Dispatch a bit. + 0xB8, 0xDF, 0x00, 0x00, + # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32 + 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} + +# NV_EVENT_LOG +0x001ee000|0x00001000 +gRaspberryPiTokenSpaceGuid.PcdNvStorageEventLogBase|gRaspberryPiTokenSpaceGuid.PcdNvStorageEventLogSize + +# NV_FTW_WORKING header +0x001ef000|0x00001000 +gRaspberryPiTokenSpaceGuid.PcdNvStorageFtwWorkingBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + +DATA = { + # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid = + # { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95 }} + 0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49, + 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95, + # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved + 0x2c, 0xaf, 0x2c, 0x64, 0xFE, 0xFF, 0xFF, 0xFF, + # WriteQueueSize: UINT64 + 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} + +# NV_FTW_WORKING data +0x001f0000|0x00010000 +gRaspberryPiTokenSpaceGuid.PcdNvStorageFtwSpareBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + +################################################################################ +# +# FV Section +# +# [FV] section is used to define what components or modules are placed within a flash +# device file. This section also defines order the components and modules are positioned +# within the image. The [FV] section consists of define statements, set statements and +# module statements. +# +################################################################################ + +[FV.FvMain] +FvNameGuid = 9a15aa37-d555-4a4e-b541-86391ff68164 +BlockSize = 0x40 +NumBlocks = 0 # This FV gets compressed so make it just big enough +FvAlignment = 16 # FV alignment and FV attributes setting. +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + INF MdeModulePkg/Core/Dxe/DxeMain.inf + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + + # + # PI DXE Drivers producing Architectural Protocols (EFI Services) + # + INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf + INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf + INF Platform/Broadcom/Bcm283x/Drivers/VarBlockServiceDxe/VarBlockServiceDxe.inf + INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf + INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf +!if $(SECURE_BOOT_ENABLE) == TRUE + INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +!endif + INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + INF EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf + INF EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf + INF EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf + INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + + # + # Multiple Console IO support + # + INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + INF Platform/Broadcom/Bcm283x/Drivers/GraphicsConsoleDxe/GraphicsConsoleDxe.inf + INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + INF MdeModulePkg/Universal/SerialDxe/SerialDxe.inf + INF Platform/Broadcom/Bcm283x/Drivers/DisplayDxe/DisplayDxe.inf + + INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf + INF Platform/Broadcom/Bcm283x/Drivers/Bcm2836InterruptDxe/Bcm2836InterruptDxe.inf + INF Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf + INF Platform/Broadcom/Bcm283x/Drivers/RpiFdtDxe/RpiFdtDxe.inf + INF Platform/Broadcom/Bcm283x/Drivers/ConfigDxe/ConfigDxe.inf + INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf + INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf + INF MdeModulePkg/Universal/EbcDxe/EbcDxe.inf + + # + # FAT filesystem + GPT/MBR partitioning + # + INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + INF FatPkg/EnhancedFatDxe/Fat.inf + INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + + # + # UEFI application (Shell Embedded Boot Loader) + # + INF ShellPkg/Application/Shell/Shell.inf + + # + # ACPI Support + # + INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf + INF MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf + INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf + INF RuleOverride = ACPITABLE Platform/Broadcom/Bcm283x/AcpiTables/AcpiTables.inf + + # + # SMBIOS Support + # + INF Platform/Broadcom/Bcm283x/Drivers/PlatformSmbiosDxe/PlatformSmbiosDxe.inf + INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + + # + # Bds + # + INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + INF MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf + INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf + INF MdeModulePkg/Application/UiApp/UiApp.inf + + # + # Networking stack + # + INF MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf + INF MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf + INF MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf + INF MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf + INF MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf + INF MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf + INF MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf + INF MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf + INF MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf + INF MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf + INF MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf + + # + # SCSI Bus and Disk Driver + # + INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + + # + # USB Support + # + INF Platform/Broadcom/Bcm283x/Drivers/DwUsbHostDxe/DwUsbHostDxe.inf + INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf + INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf + INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf + INF OptionRomPkg/Bus/Usb/UsbNetworking/Ax88772b/Ax88772b.inf + + # + # SD/MMC support + # + INF Platform/Broadcom/Bcm283x/Drivers/SdHostDxe/SdHostDxe.inf + INF Platform/Broadcom/Bcm283x/Drivers/ArasanMmcHostDxe/ArasanMmcHostDxe.inf + INF Platform/Broadcom/Bcm283x/Drivers/PiMmcDxe/MmcDxe.inf + + # + # Pi logo (splash screen) + # + INF Platform/Broadcom/Bcm283x/Drivers/Logo/LogoDxe.inf + + # + # FDT (GUID matches mRaspberryPiFfsFileGuid in RaspberryPiPlatformDxe) + # + FILE FREEFORM = DF5DA223-1D27-47C3-8D1B-9A41B55A18BC { + SECTION RAW = Platform/Broadcom/Bcm283x/DeviceTree/bcm2710-rpi-3-b.dtb + } + +[FV.FVMAIN_COMPACT] +FvAlignment = 16 +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + + INF ArmPlatformPkg/PrePi/PeiUniCore.inf + FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 { + SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE { + SECTION FV_IMAGE = FVMAIN + } + } + +################################################################################ +# +# Rules are use with the [FV] section's module INF type to define +# how an FFS file is created for a given INF file. The following Rule are the default +# rules for the different module type. User can add the customized rules to define the +# content of the FFS file. +# +################################################################################ + + +############################################################################ +# Example of a DXE_DRIVER FFS file with a Checksum encapsulation section # +############################################################################ +# +#[Rule.Common.DXE_DRIVER] +# FILE DRIVER = $(NAMED_GUID) { +# DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex +# COMPRESS PI_STD { +# GUIDED { +# PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi +# UI STRING="$(MODULE_NAME)" Optional +# VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) +# } +# } +# } +# +############################################################################ + +[Rule.Common.SEC] + FILE SEC = $(NAMED_GUID) RELOCS_STRIPPED FIXED { + TE TE Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) FIXED { + TE TE Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING ="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM] + FILE PEIM = $(NAMED_GUID) FIXED { + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + TE TE Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.PEIM.TIANOCOMPRESSED] + FILE PEIM = $(NAMED_GUID) DEBUG_MYTOOLS_IA32 { + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + GUIDED A31280AD-481E-41B6-95E8-127F4C984779 PROCESSING_REQUIRED = TRUE { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + } + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + } + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(NAMED_GUID) { + UI STRING ="$(MODULE_NAME)" Optional + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + } + +[Rule.Common.UEFI_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_APPLICATION.BINARY] + FILE APPLICATION = $(NAMED_GUID) { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.USER_DEFINED.ACPITABLE] + FILE FREEFORM = $(NAMED_GUID) { + RAW ACPI |.acpi + RAW ASL |.aml + } diff --git a/Platform/Broadcom/Bcm283x/Readme.md b/Platform/Broadcom/Bcm283x/Readme.md new file mode 100644 index 000000000000..a2633434c7bf --- /dev/null +++ b/Platform/Broadcom/Bcm283x/Readme.md @@ -0,0 +1,263 @@ +Raspberry Pi (Broadcom BCM283x) EDK2 Platform Support +===================================================== + +# Summary + +This is a port of 64-bit Tiano Core UEFI firmware for the Raspberry Pi 3/3B+ platforms, +based on [Ard Bisheuvel's 64-bit](http://www.workofard.com/2017/02/uefi-on-the-pi/) +and [Microsoft's 32-bit](https://github.com/ms-iot/RPi-UEFI/tree/ms-iot/Pi3BoardPkg) +implementations, as maintained by [Andrei Warkentin](https://github.com/andreiw/RaspberryPiPkg). + +This is meant as a generally useful 64-bit ATF + UEFI implementation for the Raspberry +Pi 3/3B+ which should be good enough for most kind of UEFI development, as well as for +running consummer Operating Systems in such as Linux or Windows. + +Raspberry Pi is a trademark of the [Raspberry Pi Foundation](http://www.raspberrypi.org). + +# Status + +This firmware, that has been validated to compile against the current +[edk2](https://github.com/tianocore/edk2)/[edk2-platforms](https://github.com/tianocore/edk2-platforms), +should be able to boot Linux (SUSE, Ubuntu), NetBSD, FreeBSD as well as Windows 10 ARM64 +(full GUI version). + +It also provides support for ATF ([Arm Trusted Platform](https://github.com/ARM-software/arm-trusted-firmware)). + +HDMI and the mini-UART serial port can be used for output devices, with mirrored output. +USB keyboards and the mini-UART serial port can be used as input. + +The boot order is currently hardcoded, first to the USB ports and then to the uSD card. +If there no bootable media media is found, the UEFI Shell is launched. +Esc enters platform setup. F1 boots the UEFI Shell. + +# Building + +(These instructions were validated against the latest edk2 / edk2-platforms / +edk2-non-osi as of 2018.12.06, on a Debian 9.6 x64 system). + +You may need to install the relevant compilation tools. Especially you should have the +ACPI Source Language (ASL) compiler, `nasm` as well as a native compiler installed. +On a Debian system, you can get these prerequisites installed with: +``` +sudo apt-get install build-essential acpica-tools nasm uuid-dev +``` + +**IMPORTANT:** Do not be tempted to install Debian's ARM64 GCC cross compiler package, +as this currently results in GCC 6.x being installed, which is known to create issues. +Instead, you should stick with GCC 5.5, such as the one provided by Linaro, as per the +instructions below. + +You can then build the firmware as follows: + +``` +mkdir ~/workspace +cd ~/workspace +git clone https://github.com/tianocore/edk2.git +# The following is only needed once, after you cloned edk2 +make -C edk2/BaseTools +# You may also have to issue git submodule init/update in edk2 if you want to enable Secure Boot +git clone https://github.com/tianocore/edk2-platforms.git +git clone https://github.com/tianocore/edk2-non-osi.git +# You *MUST* use a GCC5 toolchain (*NOT* GCC6 or later), such as the one from +# https://releases.linaro.org/components/toolchain/binaries/5.5-2017.10/aarch64-linux-gnu/ +# GCC6 and later toolchains may result in Synchronous Exceptions. You have been warned! +wget https://releases.linaro.org/components/toolchain/binaries/5.5-2017.10/aarch64-linux-gnu/gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu.tar.xz +tar -xJvf gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu.tar.xz +# If you have multiple AARCH64 toolchains, make sure the GCC5 one comes first in your path +export PATH=$PWD/gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu/bin:$PATH +export GCC5_AARCH64_PREFIX=aarch64-linux-gnu- +export WORKSPACE=$PWD +export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/edk2-platforms:$WORKSPACE/edk2-non-osi +. edk2/edksetup.sh +build -a AARCH64 -t GCC5 -p edk2-platforms/Platform/Broadcom/Bcm283x/RaspberryPiPkg.dsc -b RELEASE -DBUILD_EPOCH=`date +%s` +``` + +# Booting the firmware + +1. Format a uSD card as FAT32 +2. Copy the generated `RPI_EFI.fd` firmware onto the partition +3. Download and copy the following files from https://github.com/raspberrypi/firmware/tree/master/boot + - `bootcode.bin` + - `fixup.dat` + - `start.elf` +4. Create a `config.txt` with the following content: + ``` + arm_control=0x200 + enable_uart=1 + armstub=RPI_EFI.fd + disable_commandline_tags=1 + ``` +5. Insert the uSD card and power up the Pi. + +Note that if you have a model 3+ or a model 3 where you enabled USB boot through OTP +(see [here](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/msd.md)) +you may also be able to boot from a FAT32 USB driver rather than uSD. + +# Notes + +## ARM Trusted Firmware (ATF) + +The ATF binaries being used were compiled from the latest ATF source. + +For more details on the ATF compilation, see the [README](./Binary/README.md) in the `Binary/` directory. + +## Custom Device Tree + +The default Device Tree included in the firmware is the one for a Raspberry Pi 3 Model B (not B+). +If you want to use a different Device Tree, to boot a Pi 3 Model B+ for instance (for which a +DTB is also provided under `DeviceTree/`), you should copy the relevant `.dtb` into the root of +the SD or USB, and then edit your `config.txt` so that it looks like: + +``` +(...) +disable_commandline_tags=2 +device_tree_address=0x10000 +device_tree_end=0x20000 +device_tree=bcm2710-rpi-3-b-plus.dtb +``` + +Note: the address range **must** be `[0x10000:0x20000]`. +`dtoverlay` and `dtparam` parameters are also supported **when** providing a Device Tree`. + +## Custom `bootargs` + +This firmware will honor the command line passed by the GPU via `cmdline.txt`. + +Note, that the ultimate contents of `/chosen/bootargs` are a combination of several pieces: +- Original `/chosen/bootargs` if using the internal DTB. Seems to be completely discarded by GPU when booting with a custom device tree. +- GPU-passed hardware configuration. This one is always present. +- Additional boot options passed via `cmdline.txt`. + +# Tested Platforms + +## Ubuntu + +[Ubuntu 18.04 LTS](http://releases.ubuntu.com/18.04/) has been tested and confirmed to work, +on a Raspberry 3 Model B, including the installation process. Note however that network +installation and networking may not work on the Model B+, due to the `lan78xx` Linux driver +still requiring some support. + +Below are the steps you can follow to install Ubuntu LTS onto SD/USB: +* Download the latest Ubuntu LTS ARM64 [`mini.iso`](http://ports.ubuntu.com/ubuntu-ports/dists/bionic/main/installer-arm64/current/images/netboot/mini.iso). +* Partition the media as MBR and create a ~200 MB FAT32 partition on it with MBR type `0x0c`. + Note: Do not be tempted to use GPT partition scheme or `0xef` (EFI System Partition) for the + type, as none of these are supported by the Raspberry Pi's internal boot rom. +* Extract the full content of the ISO onto the partition you created. +* Also extract the GRUB EFI bootloader `bootaa64.efi` from `/boot/grub/efi.img` to `/boot/grub/`. + Note: Do not be tempted to copy this file to another directory (such as `/efi/boot/`) as GRUB looks for its + modules and configuration data in the same directory as the EFI loader and also, the installation + process will create a `bootaa64.efi` into `/efi/boot/`. +* If needed, copy the UEFI firmware files (`RPI_EFI.fd`, `bootcode.bin`, `fixup.dat` and `start.elf`) + onto the FAT partition. +* Boot the pi and let it go into the UEFI shell. +* Navigate to `fs0:` then `/boot/grub/` and launch the GRUB efi loader. +* Follow the Ubuntu installation process. + +Note: Because Ubuntu operates in quiet mode by default (no boot messages), you may think the system is frozen +on first reboot after installation. However, if you wait long enough you **will** get to a login prompt. + +Once Linux is running, if desired, you can disable quiet boot, as well as force the display +of the GRUB selector, by editing `/etc/default/grub` and changing: +* `GRUB_TIMEOUT_STYLE=hidden` → `GRUB_TIMEOUT_STYLE=menu` +* `GRUB_CMDLINE_LINUX_DEFAULT="splash quiet"` → `GRUB_CMDLINE_LINUX_DEFAULT=""` + +Then, to have your changes applied run `update-grub` and reboot. + +## Other Linux distributions + +* Debian ARM64 does not currently work, most likely due to missing required module support + in its kernel. However its installation process works, so it may be possible to get it + running with a custom kernel. + +* OpenSUSE Leap 42.3 has been reported to work on Raspberry 3 Model B. + +* Other ARM64 Linux releases, that support UEFI boot and have the required hardware support + for Pi hardware are expected to run, though their installation process might require some + cajoling. + +## Windows + +Windows 10 1809 for ARM64 (build 17763) has been tested and confirmed to work (after replacing +`C:\Windows\System32\Drivers\WppRecorder.sys` with an older version, since the one from 1809 +appears to be buggy across all archs, and results in a similar BSOD when trying to run Windows +To Go on x64 with native drivers for instance). + +Windows 10 1803 for ARM64 and earlier do not work due to the presence of a hardware ASSERT check +in the Windows kernel, that was removed in later versions. + +You probably want to look at https://www.worproject.ml/ as well as the +[Windows thread in the original RaspberryPiPkg](https://github.com/andreiw/RaspberryPiPkg/issues/12) +for installation details. + +## Other platforms + +Details you may need to run other platforms, including FreeBSD, is provided in the +[Readme from the original RaspberryPiPkg](https://github.com/andreiw/RaspberryPiPkg). + +# Limitations + +## HDMI + +The UEFI HDMI video support relies on the VC (that's the GPU) +firmware to correctly detect and configure the attached screen. +Some screens are slow, and this detection may not occur fast +enough. Finally, you may wish to be able to boot your Pi +headless, yet be able to attach a display to it later for +debugging. + +To accommodate these issues, the following extra lines +are recommended for your `config.txt`: +- `hdmi_force_hotplug=1` to allow plugging in video after system is booted. +- `hdmi_group=1` and `hdmi_mode=4` to force a specific mode, both to accommodate + late-plugged screens or buggy/slow screens. See [official documentation](https://www.raspberrypi.org/documentation/configuration/config-txt/video.md) + to make sense of these parameters (example above sets up 720p 60Hz). + +## NVRAM + +The Raspberry Pi has no NVRAM. + +NVRAM is emulated, with the non-volatile store backed by the UEFI image itself. This means +that any changes made in UEFI proper will be persisted, but changes made in HLOS will not. +It would be nice to implement ATF-assisted warm reboot, to allow persisting HLOS +NVRAM changes. + +## RTC + +The Rasberry Pi has no RTC. + +`RtcEpochSeconds` NVRAM variable is used to store the boot time +This should allow you to set whatever date/time you +want using the Shell date and time commands. While in UEFI +or HLOS, the time will tick forward. `RtcEpochSeconds` +is not updated on reboots. + +## uSD + +UEFI supports both the Arasan SDHCI and the Broadcom SDHost controllers to access the uSD slot. +You can use either. The other controller gets routed to the SDIO card. The choice made will +impact ACPI OSes booted (e.g. Windows 10). Arasan, being an SDIO controller, is usually used +with the WiFi adapter where available. SDHost cannot be used with SDIO. In UEFI setup screen: +- go to `Device Manager` +- go to `Raspberry Pi Configuration` +- go to `Chipset` +- configure `Boot uSD Routing` + +Known issues: +- Arasan HS/4bit support is missing. +- No 8 bit mode support for (e)MMC (irrelevant for the Pi 3). +- Hacky (e)MMC support (no HS). +- No card removal/replacement detection, tons of timeouts and slow down during boot without an uSD card present. + +## USB + +- USB1 BBB mass storage devices untested (USB2 and USB3 devices are fine). +- USB1 CBI mass storage devices don't work (e.g. HP FD-05PUB floppy). + +## ACPI + +ACPI should match the MS-IoT one. Both Arasan and SDHost SD controllers are exposed. + +## Missing Functionality + +- Network booting via onboard NIC. +- Ability to switch UART use to PL011. -- 2.17.0.windows.1