From: Pete Batard <pete@akeo.ie>
To: edk2-devel@lists.01.org
Subject: [PATCH v5 edk2-platforms 06/22] Platform/RaspberryPi/RPi3: Add firmware driver
Date: Tue, 5 Feb 2019 16:25:21 +0000 [thread overview]
Message-ID: <20190205162537.6472-7-pete@akeo.ie> (raw)
In-Reply-To: <20190205162537.6472-1-pete@akeo.ie>
Implements the base driver that is used to provide or set platform
specific configuration data.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Pete Batard <pete@akeo.ie>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
Platform/RaspberryPi/RPi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c | 1084 ++++++++++++++++++++
Platform/RaspberryPi/RPi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf | 50 +
Platform/RaspberryPi/RPi3/Include/Protocol/RpiFirmware.h | 131 +++
3 files changed, 1265 insertions(+)
diff --git a/Platform/RaspberryPi/RPi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c b/Platform/RaspberryPi/RPi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c
new file mode 100644
index 000000000000..d330e45fdc4c
--- /dev/null
+++ b/Platform/RaspberryPi/RPi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c
@@ -0,0 +1,1084 @@
+/** @file
+ *
+ * Copyright (c) 2017-2018, Andrei Warkentin <andrey.warkentin@gmail.com>
+ * 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 <PiDxe.h>
+
+#include <Library/ArmLib.h>
+#include <Library/DmaLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/SynchronizationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <IndustryStandard/Bcm2836.h>
+#include <IndustryStandard/RpiMbox.h>
+
+#include <Protocol/RpiFirmware.h>
+
+//
+// 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/RaspberryPi/RPi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf b/Platform/RaspberryPi/RPi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf
new file mode 100644
index 000000000000..45af4d08b228
--- /dev/null
+++ b/Platform/RaspberryPi/RPi3/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf
@@ -0,0 +1,50 @@
+#/** @file
+#
+# Copyright (c) 2017-2018, Andrei Warkentin <andrey.warkentin@gmail.com>
+# 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/RaspberryPi/RPi3/RPi3.dec
+
+[LibraryClasses]
+ ArmLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DmaLib
+ IoLib
+ SynchronizationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gRaspberryPiFirmwareProtocolGuid ## PRODUCES
+
+[Depex]
+ TRUE
diff --git a/Platform/RaspberryPi/RPi3/Include/Protocol/RpiFirmware.h b/Platform/RaspberryPi/RPi3/Include/Protocol/RpiFirmware.h
new file mode 100644
index 000000000000..7583d7e1fcee
--- /dev/null
+++ b/Platform/RaspberryPi/RPi3/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
next prev parent reply other threads:[~2019-02-05 16:26 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-05 16:25 [PATCH v5 edk2-platforms 00/22] Platform/RaspberryPi: Add Raspberry Pi 3 support Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 01/22] Silicon/Broadcom/Bcm283x: Add interrupt driver Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 02/22] Silicon/Broadcom/Bcm283x: Add GpioLib Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 03/22] Platform/RaspberryPi/RPi3: Add ACPI tables Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 04/22] Platform/RaspberryPi/RPi3: Add reset and memory init libraries Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 05/22] Platform/RaspberryPi/RPi3: Add platform library Pete Batard
2019-02-05 16:25 ` Pete Batard [this message]
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 07/22] Platform/RaspberryPi/RPi3: Add platform config driver Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 08/22] Platform/RaspberryPi/RPi3: Add SMBIOS driver Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 09/22] Platform/RaspberryPi/RPi3: Add display driver Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 10/22] Platform/RaspberryPi/RPi3: Add console driver Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 11/22] Platform/RaspberryPi/RPi3: Add NV storage driver Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 12/22] Platform/RaspberryPi/RPi3: Add Device Tree driver Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 13/22] Platform/RaspberryPi/RPi3: Add base MMC driver Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 14/22] Platform/RaspberryPi/RPi3: Add Arasan " Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 15/22] Platform/RaspberryPi/RPi3: Add SD Host driver Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 16/22] Platform/RaspberryPi/RPi3: Add platform boot manager and helper libs Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 17/22] Platform/RaspberryPi/RPi3: Add USB host driver Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 18/22] Platform/RaspberryPi/RPi3 *NON-OSI*: Add ATF binaries Pete Batard
2019-02-06 22:39 ` Kinney, Michael D
2019-02-07 0:52 ` Pete Batard
2019-02-07 2:35 ` Kinney, Michael D
2019-02-07 11:26 ` Pete Batard
2019-02-07 14:25 ` Ard Biesheuvel
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 19/22] Platform/RaspberryPi/RPi3 *NON-OSI*: Add Device Tree binaries Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 20/22] Platform/RaspberryPi/RPi3 *NON-OSI*: Add logo driver Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 21/22] Platform/RaspberryPi/RPi3: Add platform Pete Batard
2019-02-05 16:25 ` [PATCH v5 edk2-platforms 22/22] Platform/RaspberryPi/RPi3: Add platform readme's Pete Batard
2019-02-14 18:42 ` Leif Lindholm
2019-02-13 3:41 ` [PATCH v5 edk2-platforms 00/22] Platform/RaspberryPi: Add Raspberry Pi 3 support Jeremy Linton
2019-02-15 10:27 ` Ard Biesheuvel
2019-02-15 11:05 ` Ard Biesheuvel
2019-02-15 14:56 ` Pete Batard
2019-02-14 18:45 ` Leif Lindholm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190205162537.6472-7-pete@akeo.ie \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox