mirror of https://github.com/acidanthera/audk.git
137 lines
4.2 KiB
C
137 lines
4.2 KiB
C
/** @file
|
|
|
|
Copyright (c) 2014-2018, Linaro Ltd. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/VirtNorFlashPlatformLib.h>
|
|
|
|
#include <Protocol/FdtClient.h>
|
|
|
|
#define QEMU_NOR_BLOCK_SIZE SIZE_256KB
|
|
|
|
#define MAX_FLASH_BANKS 4
|
|
|
|
EFI_STATUS
|
|
VirtNorFlashPlatformInitialization (
|
|
VOID
|
|
)
|
|
{
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC VIRT_NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS];
|
|
|
|
EFI_STATUS
|
|
VirtNorFlashPlatformGetDevices (
|
|
OUT VIRT_NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
|
|
OUT UINT32 *Count
|
|
)
|
|
{
|
|
FDT_CLIENT_PROTOCOL *FdtClient;
|
|
INT32 Node;
|
|
EFI_STATUS Status;
|
|
EFI_STATUS FindNodeStatus;
|
|
CONST UINT32 *Reg;
|
|
UINT32 PropSize;
|
|
UINT32 Num;
|
|
UINT64 Base;
|
|
UINT64 Size;
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gFdtClientProtocolGuid,
|
|
NULL,
|
|
(VOID **)&FdtClient
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Num = 0;
|
|
for (FindNodeStatus = FdtClient->FindCompatibleNode (
|
|
FdtClient,
|
|
"cfi-flash",
|
|
&Node
|
|
);
|
|
!EFI_ERROR (FindNodeStatus) && Num < MAX_FLASH_BANKS;
|
|
FindNodeStatus = FdtClient->FindNextCompatibleNode (
|
|
FdtClient,
|
|
"cfi-flash",
|
|
Node,
|
|
&Node
|
|
))
|
|
{
|
|
Status = FdtClient->GetNodeProperty (
|
|
FdtClient,
|
|
Node,
|
|
"reg",
|
|
(CONST VOID **)&Reg,
|
|
&PropSize
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((
|
|
DEBUG_ERROR,
|
|
"%a: GetNodeProperty () failed (Status == %r)\n",
|
|
__func__,
|
|
Status
|
|
));
|
|
continue;
|
|
}
|
|
|
|
ASSERT ((PropSize % (4 * sizeof (UINT32))) == 0);
|
|
|
|
while (PropSize >= (4 * sizeof (UINT32)) && Num < MAX_FLASH_BANKS) {
|
|
Base = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[0]));
|
|
Size = SwapBytes64 (ReadUnaligned64 ((VOID *)&Reg[2]));
|
|
Reg += 4;
|
|
|
|
PropSize -= 4 * sizeof (UINT32);
|
|
|
|
//
|
|
// Disregard any flash devices that overlap with the primary FV.
|
|
// The firmware is not updatable from inside the guest anyway.
|
|
//
|
|
if ((PcdGet64 (PcdFvBaseAddress) + PcdGet32 (PcdFvSize) > Base) &&
|
|
((Base + Size) > PcdGet64 (PcdFvBaseAddress)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
mNorFlashDevices[Num].DeviceBaseAddress = (UINTN)Base;
|
|
mNorFlashDevices[Num].RegionBaseAddress = (UINTN)Base;
|
|
mNorFlashDevices[Num].Size = (UINTN)Size;
|
|
mNorFlashDevices[Num].BlockSize = QEMU_NOR_BLOCK_SIZE;
|
|
Num++;
|
|
}
|
|
|
|
//
|
|
// UEFI takes ownership of the NOR flash, and exposes its functionality
|
|
// through the UEFI Runtime Services GetVariable, SetVariable, etc. This
|
|
// means we need to disable it in the device tree to prevent the OS from
|
|
// attaching its device driver as well.
|
|
// Note that this also hides other flash banks, but the only other flash
|
|
// bank we expect to encounter is the one that carries the UEFI executable
|
|
// code, which is not intended to be guest updatable, and is usually backed
|
|
// in a readonly manner by QEMU anyway.
|
|
//
|
|
Status = FdtClient->SetNodeProperty (
|
|
FdtClient,
|
|
Node,
|
|
"status",
|
|
"disabled",
|
|
sizeof ("disabled")
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_WARN, "Failed to set NOR flash status to 'disabled'\n"));
|
|
}
|
|
}
|
|
|
|
*NorFlashDescriptions = mNorFlashDevices;
|
|
*Count = Num;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|