public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Pete Batard <pete@akeo.ie>
To: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: "edk2-devel@lists.01.org" <edk2-devel@lists.01.org>,
	Leif Lindholm <leif.lindholm@linaro.org>
Subject: Re: [PATCH v2 edk2-platforms 07/20] Platform/Broadcom/RPi3: Add Firmware driver
Date: Thu, 13 Dec 2018 10:49:44 +0000	[thread overview]
Message-ID: <1e9e713e-f56a-5237-2f43-6770160cdbb2@akeo.ie> (raw)
In-Reply-To: <CAKv+Gu9YmP0N-uynOJhG5ZZU07yh1q6zckhzOYgUadfpDvtyQw@mail.gmail.com>

On 2018.12.12 21:17, Ard Biesheuvel wrote:
> On Mon, 10 Dec 2018 at 13:39, Pete Batard <pete@akeo.ie> wrote:
>>
>> Contributed-under: TianoCore Contribution Agreement 1.1
>> Signed-off-by: Pete Batard <pete@akeo.ie>
>> ---
>>   Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c   | 1085 ++++++++++++++++++++
>>   Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf |   49 +
>>   Platform/Broadcom/Bcm283x/Include/Protocol/RaspberryPiFirmware.h    |  131 +++
>>   3 files changed, 1265 insertions(+)
>>
> 
> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> 
> Please move this patch forward in the series. It is depended upon by
> earlier patches

I'll move the patch forward. Thanks for the reviews.

>> 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 <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/RpiFirmware.h>
>> +
>> +#include <Protocol/RaspberryPiFirmware.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_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 <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                    = 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/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
>> --
>> 2.17.0.windows.1
>>



  reply	other threads:[~2018-12-13 10:49 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-10 12:38 [PATCH v2 edk2-platforms 00/20] Platform/Broadcom: Add Raspberry Pi 3 support Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 01/20] Platform/Broadcom/RPi3: Add Reset and Memory Init libraries Pete Batard
2018-12-12 20:43   ` Ard Biesheuvel
2018-12-13 10:48     ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 02/20] Platform/Broadcom/RPi3: Add Platform library Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 03/20] Platform/Broadcom/RPi3: Add GPIO and RTC libraries Pete Batard
2018-12-12 20:50   ` Ard Biesheuvel
2018-12-13 10:49     ` Pete Batard
2018-12-13 10:55       ` Leif Lindholm
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 04/20] Platform/Broadcom/RPi3: Add ACPI Tables Pete Batard
2018-12-12 20:52   ` Ard Biesheuvel
2018-12-13 10:49     ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 05/20] Platform/Broadcom/RPi3: Add Boot Manager library Pete Batard
2018-12-12 20:56   ` Ard Biesheuvel
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 06/20] Platform/Broadcom/RPi3: Add Interrupt and Device Tree drivers Pete Batard
2018-12-12 21:09   ` Ard Biesheuvel
2018-12-13 10:49     ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 07/20] Platform/Broadcom/RPi3: Add Firmware driver Pete Batard
2018-12-12 21:17   ` Ard Biesheuvel
2018-12-13 10:49     ` Pete Batard [this message]
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 08/20] Platform/Broadcom/RPi3: Add Display driver Pete Batard
2018-12-14 15:06   ` Ard Biesheuvel
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 09/20] Platform/Broadcom/RPi3: Add Graphic Console driver Pete Batard
2018-12-14 15:31   ` Ard Biesheuvel
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 10/20] Platform/Broadcom/RPi3: Add Base MMC driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 11/20] Platform/Broadcom/RPi3: Add Arasan " Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 12/20] Platform/Broadcom/RPi3: Add SD Host driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 13/20] Platform/Broadcom/RPi3: Add SMBIOS driver Pete Batard
2018-12-14 15:36   ` Ard Biesheuvel
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 14/20] Platform/Broadcom/RPi3: Add NV Storage driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 15/20] Platform/Broadcom/RPi3: Add Platform Config driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 16/20] Platform/Broadcom/RPi3: Add Raspberry Pi 3 Platform Pete Batard
2018-12-14 15:39   ` Ard Biesheuvel
2018-12-14 16:21     ` Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 17/20] Platform/Broadcom/RPi3 *NON-OSI*: Add ATF binaries Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 18/20] Platform/Broadcom/RPi3 *NON-OSI*: Add Device Tree binaries Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 19/20] Platform/Broadcom/RPi3 *NON-OSI*: Add USB Host driver Pete Batard
2018-12-10 12:38 ` [PATCH v2 edk2-platforms 20/20] Platform/Broadcom/RPi3 *NON-OSI*: Add Logo driver Pete Batard
2018-12-11 18:10 ` [PATCH v2 edk2-platforms 00/20] Platform/Broadcom: Add Raspberry Pi 3 support Leif Lindholm
2018-12-11 20:16   ` Pete Batard
2018-12-11 21:20     ` Ard Biesheuvel
2018-12-12 18:32     ` Leif Lindholm
2018-12-12 19:53       ` Pete Batard
2018-12-12 20:01         ` Leif Lindholm
2018-12-14 16:14           ` Philippe Mathieu-Daudé
2018-12-14 16:36             ` Leif Lindholm
2018-12-14 17:08               ` Pete Batard
2018-12-14 18:41                 ` 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=1e9e713e-f56a-5237-2f43-6770160cdbb2@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