From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4864:20::141; helo=mail-it1-x141.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-it1-x141.google.com (mail-it1-x141.google.com [IPv6:2607:f8b0:4864:20::141]) (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 1D1E12119EBDB for ; Wed, 12 Dec 2018 13:17:47 -0800 (PST) Received: by mail-it1-x141.google.com with SMTP id g85so538659ita.3 for ; Wed, 12 Dec 2018 13:17:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=ZuBzbhG2BMv3YqfpPs1ywcA8FkNx8E7r2N85lI8ql0I=; b=LcDDHYSMIid0IIE1hulkEpFeDlPpd/HpraDlJeZwx7L3Caeiv0vXPUva04vh7PXJxk 3tWts/3tZsniWLq0R/MLBx6zYYHO1E9CjcjYzgEtVlCBypVdGdKqWvBBcVtcevhcl6zN qY4ObDeCuKRVVPLQrJa7jom8opZag+ysMd3W0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=ZuBzbhG2BMv3YqfpPs1ywcA8FkNx8E7r2N85lI8ql0I=; b=FO/U0FabtLIANkXvf+Rp6GgLzGqdMgNGYVOSFiF+3vTg07EaC1Hn9mxwE+/jSo1Xa6 +JfXkL1iPNvBQjD5rU5HcUbdqEL/36JtTUJFu9qEPmUvX3C3BS6bLBMvizpfltvjZaUg bYU9/0XYdGEip0R+IG+dprynoSU0epjp1hu+WERKm/9wHZuOU72OhhhwW9r/6kIrS7Kw 2r7FX4gj/pQqRCf8mdVTWzZJVGGGjeIP9SZrDwLV0y+HUngQSQdffE594LFeN61QotmU Y8z5sbbeQSFmeZRgoiKbiMlMyH2U2mD5+8O3t+An0zTxM0S1MXWNjm1HHSJxa3hoc/dL NmsA== X-Gm-Message-State: AA+aEWabcRt0ABobZu2EbElMdZyu/X6VK3CNquOdpJGnTdO8blKW1gfj 5fP1d0DTuuFzRrRZGv/pzUI5aFiWTJf3kInhNTYA0A== X-Google-Smtp-Source: AFSGD/XzS3SKR6C4kR1RyRi4IJw7JxUmXQTi15cn3fM91JfBH72m4byghkNUptpstrMqBfWruI1+K/18cn8jcM504Tw= X-Received: by 2002:a05:660c:4b:: with SMTP id p11mr7688992itk.71.1544649466078; Wed, 12 Dec 2018 13:17:46 -0800 (PST) MIME-Version: 1.0 References: <20181210123853.4864-1-pete@akeo.ie> <20181210123853.4864-8-pete@akeo.ie> In-Reply-To: <20181210123853.4864-8-pete@akeo.ie> From: Ard Biesheuvel Date: Wed, 12 Dec 2018 22:17:33 +0100 Message-ID: To: Pete Batard Cc: "edk2-devel@lists.01.org" Subject: Re: [PATCH v2 edk2-platforms 07/20] Platform/Broadcom/RPi3: 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: Wed, 12 Dec 2018 21:17:47 -0000 Content-Type: text/plain; charset="UTF-8" On Mon, 10 Dec 2018 at 13:39, Pete Batard wrote: > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Pete Batard > --- > 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 Please move this patch forward in the series. It is depended upon by earlier patches > diff --git a/Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c b/Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c > new file mode 100644 > index 000000000000..50f3ed3f1e36 > --- /dev/null > +++ b/Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c > @@ -0,0 +1,1085 @@ > +/** @file > + * > + * Copyright (c) 2017-2018, Andrei Warkentin > + * Copyright (c) 2016, Linaro, Ltd. All rights reserved. > + * > + * This program and the accompanying materials > + * are licensed and made available under the terms and conditions of the BSD License > + * which accompanies this distribution. The full text of the license may be found at > + * http://opensource.org/licenses/bsd-license.php > + * > + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > + * > + **/ > + > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > + > +#include > + > +// > +// The number of statically allocated buffer pages > +// > +#define NUM_PAGES 1 > + > +// > +// The number of iterations to perform when waiting for the mailbox > +// status to change > +// > +#define MAX_TRIES 0x100000 > + > +STATIC VOID *mDmaBuffer; > +STATIC VOID *mDmaBufferMapping; > +STATIC UINTN mDmaBufferBusAddress; > + > +STATIC SPIN_LOCK mMailboxLock; > + > +STATIC > +BOOLEAN > +DrainMailbox ( > + VOID > + ) > +{ > + INTN Tries; > + UINT32 Val; > + > + // > + // Get rid of stale response data in the mailbox > + // > + Tries = 0; > + do { > + Val = MmioRead32 (BCM2836_MBOX_BASE_ADDRESS + BCM2836_MBOX_STATUS_OFFSET); > + if (Val & (1U << BCM2836_MBOX_STATUS_EMPTY)) { > + return TRUE; > + } > + ArmDataSynchronizationBarrier (); > + MmioRead32 (BCM2836_MBOX_BASE_ADDRESS + BCM2836_MBOX_READ_OFFSET); > + } while (++Tries < MAX_TRIES); > + > + return FALSE; > +} > + > +STATIC > +BOOLEAN > +MailboxWaitForStatusCleared ( > + IN UINTN StatusMask > + ) > +{ > + INTN Tries; > + UINT32 Val; > + > + // > + // Get rid of stale response data in the mailbox > + // > + Tries = 0; > + do { > + Val = MmioRead32 (BCM2836_MBOX_BASE_ADDRESS + BCM2836_MBOX_STATUS_OFFSET); > + if ((Val & StatusMask) == 0) { > + return TRUE; > + } > + ArmDataSynchronizationBarrier (); > + } while (++Tries < MAX_TRIES); > + > + return FALSE; > +} > + > +STATIC > +EFI_STATUS > +MailboxTransaction ( > + IN UINTN Length, > + IN UINTN Channel, > + OUT UINT32 *Result > + ) > +{ > + if (Channel >= BCM2836_MBOX_NUM_CHANNELS) { > + return EFI_INVALID_PARAMETER; > + } > + > + // > + // Get rid of stale response data in the mailbox > + // > + if (!DrainMailbox ()) { > + DEBUG ((DEBUG_ERROR, "%a: timeout waiting for mailbox to drain\n", > + __FUNCTION__)); > + return EFI_TIMEOUT; > + } > + > + // > + // Wait for the 'output register full' bit to become clear > + // > + if (!MailboxWaitForStatusCleared (1U << BCM2836_MBOX_STATUS_FULL)) { > + DEBUG ((DEBUG_ERROR, "%a: timeout waiting for outbox to become empty\n", > + __FUNCTION__)); > + return EFI_TIMEOUT; > + } > + > + ArmDataSynchronizationBarrier (); > + > + // > + // Start the mailbox transaction > + // > + MmioWrite32 (BCM2836_MBOX_BASE_ADDRESS + BCM2836_MBOX_WRITE_OFFSET, > + (UINT32)((UINTN)mDmaBufferBusAddress | Channel)); > + > + ArmDataSynchronizationBarrier (); > + > + // > + // Wait for the 'input register empty' bit to clear > + // > + if (!MailboxWaitForStatusCleared (1U << BCM2836_MBOX_STATUS_EMPTY)) { > + DEBUG ((DEBUG_ERROR, "%a: timeout waiting for inbox to become full\n", > + __FUNCTION__)); > + return EFI_TIMEOUT; > + } > + > + // > + // Read back the result > + // > + ArmDataSynchronizationBarrier (); > + *Result = MmioRead32 (BCM2836_MBOX_BASE_ADDRESS + BCM2836_MBOX_READ_OFFSET); > + ArmDataSynchronizationBarrier (); > + > + return EFI_SUCCESS; > +} > + > +#pragma pack(1) > +typedef struct { > + UINT32 BufferSize; > + UINT32 Response; > +} RPI_FW_BUFFER_HEAD; > + > +typedef struct { > + UINT32 TagId; > + UINT32 TagSize; > + UINT32 TagValueSize; > +} RPI_FW_TAG_HEAD; > + > +typedef struct { > + UINT32 DeviceId; > + UINT32 PowerState; > +} RPI_FW_POWER_STATE_TAG; > + > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD TagHead; > + RPI_FW_POWER_STATE_TAG TagBody; > + UINT32 EndTag; > +} RPI_FW_SET_POWER_STATE_CMD; > +#pragma pack() > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareSetPowerState ( > + IN UINT32 DeviceId, > + IN BOOLEAN PowerState, > + IN BOOLEAN Wait > + ) > +{ > + RPI_FW_SET_POWER_STATE_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd; > + Cmd->BufferHead.Response = 0; > + Cmd->TagHead.TagId = RPI_FW_SET_POWER_STATE; > + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; > + Cmd->TagHead.TagValueSize = 0; > + Cmd->TagBody.DeviceId = DeviceId; > + Cmd->TagBody.PowerState = (PowerState ? RPI_FW_POWER_STATE_ENABLE : 0) | > + (Wait ? RPI_FW_POWER_STATE_WAIT : 0); > + Cmd->EndTag = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + Status = EFI_DEVICE_ERROR; > + } > + > + if (!EFI_ERROR (Status) && > + PowerState ^ (Cmd->TagBody.PowerState & RPI_FW_POWER_STATE_ENABLE)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to %sable power for device %d\n", > + __FUNCTION__, PowerState ? "en" : "dis", DeviceId)); > + Status = EFI_DEVICE_ERROR; > + } > + > + return Status; > +} > + > +#pragma pack() > +typedef struct { > + UINT32 Base; > + UINT32 Size; > +} RPI_FW_ARM_MEMORY_TAG; > + > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD TagHead; > + RPI_FW_ARM_MEMORY_TAG TagBody; > + UINT32 EndTag; > +} RPI_FW_GET_ARM_MEMORY_CMD; > +#pragma pack() > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareGetArmMemory ( > + OUT UINT32 *Base, > + OUT UINT32 *Size > + ) > +{ > + RPI_FW_GET_ARM_MEMORY_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd; > + Cmd->BufferHead.Response = 0; > + Cmd->TagHead.TagId = RPI_FW_GET_ARM_MEMSIZE; > + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; > + Cmd->TagHead.TagValueSize = 0; > + Cmd->EndTag = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + return EFI_DEVICE_ERROR; > + } > + > + *Base = Cmd->TagBody.Base; > + *Size = Cmd->TagBody.Size; > + return EFI_SUCCESS; > +} > + > +#pragma pack() > +typedef struct { > + UINT8 MacAddress[6]; > + UINT32 Padding; > +} RPI_FW_MAC_ADDR_TAG; > + > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD TagHead; > + RPI_FW_MAC_ADDR_TAG TagBody; > + UINT32 EndTag; > +} RPI_FW_GET_MAC_ADDR_CMD; > +#pragma pack() > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareGetMacAddress ( > + OUT UINT8 MacAddress[6] > + ) > +{ > + RPI_FW_GET_MAC_ADDR_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd; > + Cmd->BufferHead.Response = 0; > + Cmd->TagHead.TagId = RPI_FW_GET_MAC_ADDRESS; > + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; > + Cmd->TagHead.TagValueSize = 0; > + Cmd->EndTag = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + return EFI_DEVICE_ERROR; > + } > + > + CopyMem (MacAddress, Cmd->TagBody.MacAddress, sizeof Cmd->TagBody.MacAddress); > + return EFI_SUCCESS; > +} > + > +#pragma pack() > +typedef struct { > + UINT64 Serial; > +} RPI_FW_SERIAL_TAG; > + > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD TagHead; > + RPI_FW_SERIAL_TAG TagBody; > + UINT32 EndTag; > +} RPI_FW_GET_SERIAL_CMD; > +#pragma pack() > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareGetSerial ( > + OUT UINT64 *Serial > + ) > +{ > + RPI_FW_GET_SERIAL_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd; > + Cmd->BufferHead.Response = 0; > + Cmd->TagHead.TagId = RPI_FW_GET_BOARD_SERIAL; > + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; > + Cmd->TagHead.TagValueSize = 0; > + Cmd->EndTag = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + return EFI_DEVICE_ERROR; > + } > + > + *Serial = Cmd->TagBody.Serial; > + return EFI_SUCCESS; > +} > + > +#pragma pack() > +typedef struct { > + UINT32 Model; > +} RPI_FW_MODEL_TAG; > + > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD TagHead; > + RPI_FW_MODEL_TAG TagBody; > + UINT32 EndTag; > +} RPI_FW_GET_MODEL_CMD; > +#pragma pack() > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareGetModel ( > + OUT UINT32 *Model > + ) > +{ > + RPI_FW_GET_MODEL_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd; > + Cmd->BufferHead.Response = 0; > + Cmd->TagHead.TagId = RPI_FW_GET_BOARD_MODEL; > + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; > + Cmd->TagHead.TagValueSize = 0; > + Cmd->EndTag = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + return EFI_DEVICE_ERROR; > + } > + > + *Model = Cmd->TagBody.Model; > + return EFI_SUCCESS; > +} > + > +#pragma pack() > +typedef struct { > + UINT32 Revision; > +} RPI_FW_MODEL_REVISION_TAG; > + > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD TagHead; > + RPI_FW_MODEL_REVISION_TAG TagBody; > + UINT32 EndTag; > +} RPI_FW_GET_MODEL_REVISION_CMD; > +#pragma pack() > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareGetModelRevision ( > + OUT UINT32 *Revision > + ) > +{ > + RPI_FW_GET_MODEL_REVISION_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd; > + Cmd->BufferHead.Response = 0; > + Cmd->TagHead.TagId = RPI_FW_GET_BOARD_REVISION; > + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; > + Cmd->TagHead.TagValueSize = 0; > + Cmd->EndTag = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + return EFI_DEVICE_ERROR; > + } > + > + *Revision = Cmd->TagBody.Revision; > + return EFI_SUCCESS; > +} > + > +#pragma pack() > +typedef struct { > + UINT32 Width; > + UINT32 Height; > +} RPI_FW_FB_SIZE_TAG; > + > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD TagHead; > + RPI_FW_FB_SIZE_TAG TagBody; > + UINT32 EndTag; > +} RPI_FW_GET_FB_SIZE_CMD; > + > +typedef struct { > + UINT32 Depth; > +} RPI_FW_FB_DEPTH_TAG; > + > +typedef struct { > + UINT32 Pitch; > +} RPI_FW_FB_PITCH_TAG; > + > +typedef struct { > + UINT32 AlignmentBase; > + UINT32 Size; > +} RPI_FW_FB_ALLOC_TAG; > + > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD FreeFbTag; > + UINT32 EndTag; > +} RPI_FW_FREE_FB_CMD; > + > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD PhysSizeTag; > + RPI_FW_FB_SIZE_TAG PhysSize; > + RPI_FW_TAG_HEAD VirtSizeTag; > + RPI_FW_FB_SIZE_TAG VirtSize; > + RPI_FW_TAG_HEAD DepthTag; > + RPI_FW_FB_DEPTH_TAG Depth; > + RPI_FW_TAG_HEAD AllocFbTag; > + RPI_FW_FB_ALLOC_TAG AllocFb; > + RPI_FW_TAG_HEAD PitchTag; > + RPI_FW_FB_PITCH_TAG Pitch; > + UINT32 EndTag; > +} RPI_FW_INIT_FB_CMD; > +#pragma pack() > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareGetFbSize ( > + OUT UINT32 *Width, > + OUT UINT32 *Height > + ) > +{ > + RPI_FW_GET_FB_SIZE_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd; > + Cmd->BufferHead.Response = 0; > + Cmd->TagHead.TagId = RPI_FW_GET_FB_GEOMETRY; > + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; > + Cmd->TagHead.TagValueSize = 0; > + Cmd->EndTag = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + return EFI_DEVICE_ERROR; > + } > + > + *Width = Cmd->TagBody.Width; > + *Height = Cmd->TagBody.Height; > + return EFI_SUCCESS; > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareFreeFb (VOID) > +{ > + RPI_FW_FREE_FB_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd; > + Cmd->BufferHead.Response = 0; > + > + Cmd->FreeFbTag.TagId = RPI_FW_FREE_FB; > + Cmd->FreeFbTag.TagSize = 0; > + Cmd->FreeFbTag.TagValueSize = 0; > + Cmd->EndTag = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + return EFI_DEVICE_ERROR; > + } > + > + return EFI_SUCCESS; > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareAllocFb ( > + IN UINT32 Width, > + IN UINT32 Height, > + IN UINT32 Depth, > + OUT EFI_PHYSICAL_ADDRESS *FbBase, > + OUT UINTN *FbSize, > + OUT UINTN *Pitch) > +{ > + RPI_FW_INIT_FB_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + ASSERT (FbSize != NULL); > + ASSERT (FbBase != NULL); > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd; > + Cmd->BufferHead.Response = 0; > + > + Cmd->PhysSizeTag.TagId = RPI_FW_SET_FB_PGEOM; > + Cmd->PhysSizeTag.TagSize = sizeof Cmd->PhysSize; > + Cmd->PhysSize.Width = Width; > + Cmd->PhysSize.Height = Height; > + Cmd->VirtSizeTag.TagId = RPI_FW_SET_FB_VGEOM; > + Cmd->VirtSizeTag.TagSize = sizeof Cmd->VirtSize; > + Cmd->VirtSize.Width = Width; > + Cmd->VirtSize.Height = Height; > + Cmd->DepthTag.TagId = RPI_FW_SET_FB_DEPTH; > + Cmd->DepthTag.TagSize = sizeof Cmd->Depth; > + Cmd->Depth.Depth = Depth; > + Cmd->AllocFbTag.TagId = RPI_FW_ALLOC_FB; > + Cmd->AllocFbTag.TagSize = sizeof Cmd->AllocFb; > + Cmd->AllocFb.AlignmentBase = 32; > + Cmd->PitchTag.TagId = RPI_FW_GET_FB_LINELENGTH; > + Cmd->PitchTag.TagSize = sizeof Cmd->Pitch; > + Cmd->EndTag = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + return EFI_DEVICE_ERROR; > + } > + > + *Pitch = Cmd->Pitch.Pitch; > + *FbBase = Cmd->AllocFb.AlignmentBase - BCM2836_DMA_DEVICE_OFFSET; > + *FbSize = Cmd->AllocFb.Size; > + return EFI_SUCCESS; > +} > + > +#pragma pack() > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD TagHead; > + UINT8 CommandLine[0]; > +} RPI_FW_GET_COMMAND_LINE_CMD; > +#pragma pack() > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareGetCommmandLine ( > + IN UINTN BufferSize, > + OUT CHAR8 CommandLine[] > + ) > +{ > + RPI_FW_GET_COMMAND_LINE_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + if ((BufferSize % sizeof (UINT32)) != 0) { > + DEBUG ((DEBUG_ERROR, "%a: BufferSize must be a multiple of 4\n", > + __FUNCTION__)); > + return EFI_INVALID_PARAMETER; > + } > + > + if (sizeof *Cmd + BufferSize > EFI_PAGES_TO_SIZE (NUM_PAGES)) { > + DEBUG ((DEBUG_ERROR, "%a: BufferSize exceeds size of DMA buffer\n", > + __FUNCTION__)); > + return EFI_OUT_OF_RESOURCES; > + } > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd + BufferSize + sizeof (UINT32)); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd + BufferSize + sizeof (UINT32); > + Cmd->BufferHead.Response = 0; > + Cmd->TagHead.TagId = RPI_FW_GET_COMMAND_LINE; > + Cmd->TagHead.TagSize = BufferSize; > + Cmd->TagHead.TagValueSize = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd->TagHead.TagValueSize &= ~RPI_FW_VALUE_SIZE_RESPONSE_MASK; > + if (Cmd->TagHead.TagValueSize >= BufferSize && > + Cmd->CommandLine[Cmd->TagHead.TagValueSize - 1] != '\0') { > + DEBUG ((DEBUG_ERROR, "%a: insufficient buffer size\n", __FUNCTION__)); > + return EFI_OUT_OF_RESOURCES; > + } > + > + CopyMem (CommandLine, Cmd->CommandLine, Cmd->TagHead.TagValueSize); > + > + if (CommandLine[Cmd->TagHead.TagValueSize - 1] != '\0') { > + // > + // Add a NUL terminator if required. > + // > + CommandLine[Cmd->TagHead.TagValueSize] = '\0'; > + } > + > + return EFI_SUCCESS; > +} > + > +#pragma pack() > +typedef struct { > + UINT32 ClockId; > + UINT32 ClockRate; > + UINT32 SkipTurbo; > +} RPI_FW_SET_CLOCK_RATE_TAG; > + > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD TagHead; > + RPI_FW_SET_CLOCK_RATE_TAG TagBody; > + UINT32 EndTag; > +} RPI_FW_SET_CLOCK_RATE_CMD; > +#pragma pack() > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareSetClockRate ( > + IN UINT32 ClockId, > + IN UINT32 ClockRate > + ) > +{ > + RPI_FW_SET_CLOCK_RATE_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd; > + Cmd->BufferHead.Response = 0; > + Cmd->TagHead.TagId = RPI_FW_SET_CLOCK_RATE, > + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; > + Cmd->TagHead.TagValueSize = 0; > + Cmd->TagBody.ClockId = ClockId; > + Cmd->TagBody.ClockRate = ClockRate; > + Cmd->EndTag = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + return EFI_DEVICE_ERROR; > + } > + > + return EFI_SUCCESS; > +} > + > + > +#pragma pack() > +typedef struct { > + UINT32 ClockId; > + UINT32 ClockRate; > +} RPI_FW_CLOCK_RATE_TAG; > + > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD TagHead; > + RPI_FW_CLOCK_RATE_TAG TagBody; > + UINT32 EndTag; > +} RPI_FW_GET_CLOCK_RATE_CMD; > +#pragma pack() > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareGetClockRate ( > + IN UINT32 ClockId, > + IN UINT32 ClockKind, > + OUT UINT32 *ClockRate > + ) > +{ > + RPI_FW_GET_CLOCK_RATE_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return EFI_DEVICE_ERROR; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd; > + Cmd->BufferHead.Response = 0; > + Cmd->TagHead.TagId = ClockKind, > + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; > + Cmd->TagHead.TagValueSize = 0; > + Cmd->TagBody.ClockId = ClockId; > + Cmd->EndTag = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + return EFI_DEVICE_ERROR; > + } > + > + *ClockRate = Cmd->TagBody.ClockRate; > + return EFI_SUCCESS; > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareGetCurrentClockRate ( > + IN UINT32 ClockId, > + OUT UINT32 *ClockRate > + ) > +{ > + return RpiFirmwareGetClockRate(ClockId, RPI_FW_GET_CLOCK_RATE, ClockRate); > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareGetMaxClockRate ( > + IN UINT32 ClockId, > + OUT UINT32 *ClockRate > + ) > +{ > + return RpiFirmwareGetClockRate(ClockId, RPI_FW_GET_MAX_CLOCK_RATE, ClockRate); > +} > + > +STATIC > +EFI_STATUS > +EFIAPI > +RpiFirmwareGetMinClockRate ( > + IN UINT32 ClockId, > + OUT UINT32 *ClockRate > + ) > +{ > + return RpiFirmwareGetClockRate(ClockId, RPI_FW_GET_MIN_CLOCK_RATE, ClockRate); > +} > + > +#pragma pack() > +typedef struct { > + UINT32 Pin; > + UINT32 State; > +} RPI_FW_SET_GPIO_TAG; > + > +typedef struct { > + RPI_FW_BUFFER_HEAD BufferHead; > + RPI_FW_TAG_HEAD TagHead; > + RPI_FW_SET_GPIO_TAG TagBody; > + UINT32 EndTag; > +} RPI_FW_SET_GPIO_CMD; > +#pragma pack() > + > +STATIC > +VOID > +RpiFirmwareLedSet ( > + IN BOOLEAN On > + ) > +{ > + RPI_FW_SET_GPIO_CMD *Cmd; > + EFI_STATUS Status; > + UINT32 Result; > + > + if (!AcquireSpinLockOrFail (&mMailboxLock)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__)); > + return; > + } > + > + Cmd = mDmaBuffer; > + ZeroMem (Cmd, sizeof *Cmd); > + > + Cmd->BufferHead.BufferSize = sizeof *Cmd; > + Cmd->BufferHead.Response = 0; > + Cmd->TagHead.TagId = RPI_FW_SET_GPIO; > + Cmd->TagHead.TagSize = sizeof Cmd->TagBody; > + /* > + * GPIO_PIN_2 = Activity LED > + * GPIO_PIN_4 = HDMI Detect (Input / Active Low) > + * GPIO_PIN_7 = Power LED (Input / Active Low) > + * > + * There's also a 128 pin offset. > + */ > + Cmd->TagBody.Pin = 128 + 2; > + Cmd->TagBody.State = On; > + Cmd->TagHead.TagValueSize = 0; > + Cmd->EndTag = 0; > + > + Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_FW_MBOX_CHANNEL, &Result); > + > + ReleaseSpinLock (&mMailboxLock); > + > + if (EFI_ERROR (Status) || > + Cmd->BufferHead.Response != RPI_FW_RESP_SUCCESS) { > + DEBUG ((DEBUG_ERROR, > + "%a: mailbox transaction error: Status == %r, Response == 0x%x\n", > + __FUNCTION__, Status, Cmd->BufferHead.Response)); > + } > +} > + > +STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL mRpiFirmwareProtocol = { > + RpiFirmwareSetPowerState, > + RpiFirmwareGetMacAddress, > + RpiFirmwareGetCommmandLine, > + RpiFirmwareGetCurrentClockRate, > + RpiFirmwareGetMaxClockRate, > + RpiFirmwareGetMinClockRate, > + RpiFirmwareSetClockRate, > + RpiFirmwareAllocFb, > + RpiFirmwareFreeFb, > + RpiFirmwareGetFbSize, > + RpiFirmwareLedSet, > + RpiFirmwareGetSerial, > + RpiFirmwareGetModel, > + RpiFirmwareGetModelRevision, > + RpiFirmwareGetArmMemory > +}; > + > +/** > + Initialize the state information for the CPU Architectural Protocol > + > + @param ImageHandle of the loaded driver > + @param SystemTable Pointer to the System Table > + > + @retval EFI_SUCCESS Protocol registered > + @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure > + @retval EFI_DEVICE_ERROR Hardware problems > + > +**/ > +EFI_STATUS > +RpiFirmwareDxeInitialize ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + UINTN BufferSize; > + > + // > + // We only need one of these > + // > + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gRaspberryPiFirmwareProtocolGuid); > + > + InitializeSpinLock (&mMailboxLock); > + > + Status = DmaAllocateBuffer (EfiBootServicesData, NUM_PAGES, &mDmaBuffer); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to allocate DMA buffer (Status == %r)\n", > + __FUNCTION__)); > + return Status; > + } > + > + BufferSize = EFI_PAGES_TO_SIZE (NUM_PAGES); > + Status = DmaMap (MapOperationBusMasterCommonBuffer, mDmaBuffer, &BufferSize, > + &mDmaBufferBusAddress, &mDmaBufferMapping); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "%a: failed to map DMA buffer (Status == %r)\n", > + __FUNCTION__)); > + goto FreeBuffer; > + } > + > + // > + // The channel index is encoded in the low bits of the bus address, > + // so make sure these are cleared. > + // > + ASSERT (!(mDmaBufferBusAddress & (BCM2836_MBOX_NUM_CHANNELS - 1))); > + > + Status = gBS->InstallProtocolInterface (&ImageHandle, > + &gRaspberryPiFirmwareProtocolGuid, EFI_NATIVE_INTERFACE, > + &mRpiFirmwareProtocol); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, > + "%a: failed to install RPI firmware protocol (Status == %r)\n", > + __FUNCTION__, Status)); > + goto UnmapBuffer; > + } > + > + return EFI_SUCCESS; > + > +UnmapBuffer: > + DmaUnmap (mDmaBufferMapping); > +FreeBuffer: > + DmaFreeBuffer (NUM_PAGES, mDmaBuffer); > + > + return Status; > +} > diff --git a/Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf b/Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf > new file mode 100644 > index 000000000000..2ab57bbf54f0 > --- /dev/null > +++ b/Platform/Broadcom/Bcm283x/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.inf > @@ -0,0 +1,49 @@ > +#/** @file > +# > +# Copyright (c) 2017-2018, Andrei Warkentin > +# Copyright (c) 2016, Linaro, Ltd. All rights reserved. > +# > +# This program and the accompanying materials > +# are licensed and made available under the terms and conditions of the BSD License > +# which accompanies this distribution. The full text of the license may be found at > +# http://opensource.org/licenses/bsd-license.php > +# > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. > +# > +#**/ > + > +[Defines] > + INF_VERSION = 0x00010019 > + BASE_NAME = RpiFirmwareDxe > + FILE_GUID = 6d4628df-49a0-4b67-a325-d5af35c65745 > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = RpiFirmwareDxeInitialize > + > +[Sources] > + RpiFirmwareDxe.c > + > +[Packages] > + ArmPkg/ArmPkg.dec > + MdePkg/MdePkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + Platform/Broadcom/Bcm283x/RaspberryPiPkg.dec > + > +[LibraryClasses] > + ArmLib > + BaseLib > + BaseMemoryLib > + DebugLib > + DmaLib > + IoLib > + SynchronizationLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + UefiLib > + > +[Protocols] > + gRaspberryPiFirmwareProtocolGuid ## PRODUCES > + > +[Depex] > + TRUE > diff --git a/Platform/Broadcom/Bcm283x/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 >