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::544; helo=mail-ed1-x544.google.com; envelope-from=pete@akeo.ie; receiver=edk2-devel@lists.01.org Received: from mail-ed1-x544.google.com (mail-ed1-x544.google.com [IPv6:2a00:1450:4864:20::544]) (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 A48CF2194D3AE for ; Tue, 29 Jan 2019 08:27:26 -0800 (PST) Received: by mail-ed1-x544.google.com with SMTP id b3so16525642ede.1 for ; Tue, 29 Jan 2019 08:27:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=akeo-ie.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=LDjTyIZ4AbVsBNXYL60CNJYG0HFMFLnTr9tj/8g6dDI=; b=rJudtp6XHBErjFPddrP9c4VdqNuq5O1xQyQz/09FLf0zj1k20Af3vXqy/A/EIWoi8r G2tztXPiBxjOFaAQAybyUH5TtjzvtDKl8pxF7Jaf80V7vt4ahqY2vXTxlQicqmiDJFdB 0+O2QjsSv/183c/Op9imLUJ19mvDzMcI8A9lZQS6N2RwgFWzKBi2i2TStXVCacxGk3S0 qbowOh7t6SgDg58QM+TV6/0vl/IGVmCN71uTwUxNs0V1yrZFsVqGFSkLSCZtWFKLHshU Y6GDtk9DvV4v1bRocNdfajZRH+o3FxTmcIYxGnMaywgr8vdPZ0HgyhOmrR/arVxLerbA wmbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=LDjTyIZ4AbVsBNXYL60CNJYG0HFMFLnTr9tj/8g6dDI=; b=gZCxkT6i8hCFJiHMmSqsvEdJFMPcpWh8gjxqjLDpOEnoWQzQo94Pla+kk3oQtANH+m +50B+9TXed5TrS2tdkEt+bBCofe+XhEZRenCFKMNcj15AbvrTZb5gCIg1lx33M6xkjur S0lwAHsDhFkOXMVARk39ovP06k8skpMJWFNNhC7vzdKqCA7twevhtxCwshtGiO71L/tY wR2uS556vY70L2xSpgFcs+q+gVHACr8VsuctmZqNL7ByT8/13eozEwSZuxD2B93KKVO3 tgDjVDcTOZN954At+ydepnkY86IHFyaxjIYwWeZC6Kw1vDTxtmMc7Jh2mlg4Peq25IHa evbQ== X-Gm-Message-State: AJcUukei5Q6dIbQrmELMvPg993hlQ6ly0u22zLPoEoPUJR31roNK+iVh N90I6f64gZyGKVrZCSYzedCpreilxuA= X-Google-Smtp-Source: ALg8bN7KYeA9a7EShWe7qpTsmTqxJWKH/hDjtnieJINnD/r31x0dJpAJHjXlXO2At/f56kgr09okZQ== X-Received: by 2002:a50:95b4:: with SMTP id w49mr25736259eda.186.1548779244427; Tue, 29 Jan 2019 08:27:24 -0800 (PST) Received: from localhost.localdomain ([84.203.95.186]) by smtp.gmail.com with ESMTPSA id p16-v6sm8303056eju.73.2019.01.29.08.27.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 29 Jan 2019 08:27:23 -0800 (PST) From: Pete Batard To: edk2-devel@lists.01.org Date: Tue, 29 Jan 2019 16:26:39 +0000 Message-Id: <20190129162655.3800-8-pete@akeo.ie> X-Mailer: git-send-email 2.17.0.windows.1 In-Reply-To: <20190129162655.3800-1-pete@akeo.ie> References: <20190129162655.3800-1-pete@akeo.ie> Subject: [PATCH v4 edk2-platforms 07/23] Platform/Raspberry/Pi3: Add firmware driver 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: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 X-List-Received-Date: Tue, 29 Jan 2019 16:27:27 -0000 Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Pete Batard Reviewed-by: Ard Biesheuvel --- Platform/Raspberry/Pi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c | 1084 ++++++++++++++++++++ Platform/Raspberry/Pi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf | 50 + Platform/Raspberry/Pi3/Include/Protocol/RpiFirmware.h | 131 +++ 3 files changed, 1265 insertions(+) diff --git a/Platform/Raspberry/Pi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c b/Platform/Raspberry/Pi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c new file mode 100644 index 000000000000..d330e45fdc4c --- /dev/null +++ b/Platform/Raspberry/Pi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c @@ -0,0 +1,1084 @@ +/** @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_MBOX_SET_POWER_STATE; + Cmd->TagHead.TagSize = sizeof (Cmd->TagBody); + Cmd->TagHead.TagValueSize = 0; + Cmd->TagBody.DeviceId = DeviceId; + Cmd->TagBody.PowerState = (PowerState ? RPI_MBOX_POWER_STATE_ENABLE : 0) | + (Wait ? RPI_MBOX_POWER_STATE_WAIT : 0); + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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_MBOX_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_MBOX_GET_ARM_MEMSIZE; + Cmd->TagHead.TagSize = sizeof (Cmd->TagBody); + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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_MBOX_GET_MAC_ADDRESS; + Cmd->TagHead.TagSize = sizeof (Cmd->TagBody); + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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_MBOX_GET_BOARD_SERIAL; + Cmd->TagHead.TagSize = sizeof (Cmd->TagBody); + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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_MBOX_GET_BOARD_MODEL; + Cmd->TagHead.TagSize = sizeof (Cmd->TagBody); + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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_MBOX_GET_BOARD_REVISION; + Cmd->TagHead.TagSize = sizeof (Cmd->TagBody); + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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_MBOX_GET_FB_GEOMETRY; + Cmd->TagHead.TagSize = sizeof (Cmd->TagBody); + Cmd->TagHead.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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_MBOX_FREE_FB; + Cmd->FreeFbTag.TagSize = 0; + Cmd->FreeFbTag.TagValueSize = 0; + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result); + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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_MBOX_SET_FB_PGEOM; + Cmd->PhysSizeTag.TagSize = sizeof (Cmd->PhysSize); + Cmd->PhysSize.Width = Width; + Cmd->PhysSize.Height = Height; + Cmd->VirtSizeTag.TagId = RPI_MBOX_SET_FB_VGEOM; + Cmd->VirtSizeTag.TagSize = sizeof (Cmd->VirtSize); + Cmd->VirtSize.Width = Width; + Cmd->VirtSize.Height = Height; + Cmd->DepthTag.TagId = RPI_MBOX_SET_FB_DEPTH; + Cmd->DepthTag.TagSize = sizeof (Cmd->Depth); + Cmd->Depth.Depth = Depth; + Cmd->AllocFbTag.TagId = RPI_MBOX_ALLOC_FB; + Cmd->AllocFbTag.TagSize = sizeof (Cmd->AllocFb); + Cmd->AllocFb.AlignmentBase = 32; + Cmd->PitchTag.TagId = RPI_MBOX_GET_FB_LINELENGTH; + Cmd->PitchTag.TagSize = sizeof (Cmd->Pitch); + Cmd->EndTag = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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_MBOX_GET_COMMAND_LINE; + Cmd->TagHead.TagSize = BufferSize; + Cmd->TagHead.TagValueSize = 0; + + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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_MBOX_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_MBOX_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_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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_MBOX_GET_CLOCK_RATE, ClockRate); +} + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetMaxClockRate ( + IN UINT32 ClockId, + OUT UINT32 *ClockRate + ) +{ + return RpiFirmwareGetClockRate (ClockId, RPI_MBOX_GET_MAX_CLOCK_RATE, ClockRate); +} + +STATIC +EFI_STATUS +EFIAPI +RpiFirmwareGetMinClockRate ( + IN UINT32 ClockId, + OUT UINT32 *ClockRate + ) +{ + return RpiFirmwareGetClockRate (ClockId, RPI_MBOX_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 +RpiFirmwareSetLed ( + 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_MBOX_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_MBOX_VC_CHANNEL, &Result); + + ReleaseSpinLock (&mMailboxLock); + + if (EFI_ERROR (Status) || + Cmd->BufferHead.Response != RPI_MBOX_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, + RpiFirmwareSetLed, + 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/Raspberry/Pi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf b/Platform/Raspberry/Pi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf new file mode 100644 index 000000000000..1178d0b60237 --- /dev/null +++ b/Platform/Raspberry/Pi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf @@ -0,0 +1,50 @@ +#/** @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 = 0x0001001A + 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 + Silicon/Broadcom/Bcm283x/Bcm283x.dec + Platform/Raspberry/Pi3/RPi3.dec + +[LibraryClasses] + ArmLib + BaseLib + BaseMemoryLib + DebugLib + DmaLib + IoLib + SynchronizationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + +[Protocols] + gRaspberryPiFirmwareProtocolGuid ## PRODUCES + +[Depex] + TRUE diff --git a/Platform/Raspberry/Pi3/Include/Protocol/RpiFirmware.h b/Platform/Raspberry/Pi3/Include/Protocol/RpiFirmware.h new file mode 100644 index 000000000000..7583d7e1fcee --- /dev/null +++ b/Platform/Raspberry/Pi3/Include/Protocol/RpiFirmware.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 /* __RASPBERRY_PI_FIRMWARE_PROTOCOL_H__ */ -- 2.17.0.windows.1