mirror of https://github.com/acidanthera/audk.git
218 lines
6.4 KiB
C
218 lines
6.4 KiB
C
/** @file
|
|
|
|
Copyright (c) 2013-2015, ARM Ltd. All rights reserved.<BR>
|
|
|
|
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 "ArmVExpressInternal.h"
|
|
|
|
#include <PiDxe.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/VirtioMmioDeviceLib.h>
|
|
#include <Library/ArmShellCmdLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/DevicePathLib.h>
|
|
|
|
#include <Protocol/FirmwareVolume2.h>
|
|
|
|
#define ARM_FVP_BASE_VIRTIO_BLOCK_BASE 0x1c130000
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
VENDOR_DEVICE_PATH Vendor;
|
|
EFI_DEVICE_PATH_PROTOCOL End;
|
|
} VIRTIO_BLK_DEVICE_PATH;
|
|
#pragma pack()
|
|
|
|
VIRTIO_BLK_DEVICE_PATH mVirtioBlockDevicePath =
|
|
{
|
|
{
|
|
{
|
|
HARDWARE_DEVICE_PATH,
|
|
HW_VENDOR_DP,
|
|
{
|
|
(UINT8)( sizeof(VENDOR_DEVICE_PATH) ),
|
|
(UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8)
|
|
}
|
|
},
|
|
EFI_CALLER_ID_GUID,
|
|
},
|
|
{
|
|
END_DEVICE_PATH_TYPE,
|
|
END_ENTIRE_DEVICE_PATH_SUBTYPE,
|
|
{
|
|
sizeof (EFI_DEVICE_PATH_PROTOCOL),
|
|
0
|
|
}
|
|
}
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
InternalFindFdtByGuid (
|
|
IN OUT EFI_DEVICE_PATH **FdtDevicePath,
|
|
IN CONST EFI_GUID *FdtGuid
|
|
)
|
|
{
|
|
MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileDevicePath;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINTN HandleCount;
|
|
UINTN Index;
|
|
EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
|
|
EFI_GUID NameGuid;
|
|
UINTN Size;
|
|
VOID *Key;
|
|
EFI_FV_FILETYPE FileType;
|
|
EFI_FV_FILE_ATTRIBUTES Attributes;
|
|
EFI_DEVICE_PATH *FvDevicePath;
|
|
EFI_STATUS Status;
|
|
|
|
if (FdtGuid == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
EfiInitializeFwVolDevicepathNode (&FileDevicePath, FdtGuid);
|
|
|
|
HandleBuffer = NULL;
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiFirmwareVolume2ProtocolGuid,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
for (Index = 0; Index < HandleCount; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[Index],
|
|
&gEfiFirmwareVolume2ProtocolGuid,
|
|
(VOID **) &FvProtocol
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
// Allocate Key
|
|
Key = AllocatePool (FvProtocol->KeySize);
|
|
ASSERT (Key != NULL);
|
|
ZeroMem (Key, FvProtocol->KeySize);
|
|
|
|
do {
|
|
FileType = EFI_FV_FILETYPE_RAW;
|
|
Status = FvProtocol->GetNextFile (FvProtocol, Key, &FileType, &NameGuid, &Attributes, &Size);
|
|
if (Status == EFI_NOT_FOUND) {
|
|
break;
|
|
}
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Check whether this file is the one we are looking for. If so,
|
|
// create a device path for it and return it to the caller.
|
|
//
|
|
if (CompareGuid (&NameGuid, FdtGuid)) {
|
|
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
|
|
if (!EFI_ERROR (Status)) {
|
|
*FdtDevicePath = AppendDevicePathNode (FvDevicePath,
|
|
(EFI_DEVICE_PATH_PROTOCOL *)&FileDevicePath);
|
|
}
|
|
goto Done;
|
|
}
|
|
} while (TRUE);
|
|
FreePool (Key);
|
|
}
|
|
|
|
if (Index == HandleCount) {
|
|
Status = EFI_NOT_FOUND;
|
|
}
|
|
return Status;
|
|
|
|
Done:
|
|
FreePool (Key);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
* Generic UEFI Entrypoint for 'ArmFvpDxe' driver
|
|
* See UEFI specification for the details of the parameters
|
|
*/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ArmFvpInitialise (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
CONST ARM_VEXPRESS_PLATFORM* Platform;
|
|
EFI_STATUS Status;
|
|
CHAR16 *TextDevicePath;
|
|
UINTN TextDevicePathSize;
|
|
VOID *Buffer;
|
|
EFI_DEVICE_PATH *FdtDevicePath;
|
|
|
|
Status = gBS->InstallProtocolInterface (&ImageHandle,
|
|
&gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,
|
|
&mVirtioBlockDevicePath);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = ArmVExpressGetPlatform (&Platform);
|
|
if (!EFI_ERROR (Status)) {
|
|
FdtDevicePath = NULL;
|
|
Status = InternalFindFdtByGuid (&FdtDevicePath, Platform->FdtGuid);
|
|
if (!EFI_ERROR (Status)) {
|
|
TextDevicePath = ConvertDevicePathToText (FdtDevicePath, FALSE, FALSE);
|
|
if (TextDevicePath != NULL) {
|
|
TextDevicePathSize = StrSize (TextDevicePath);
|
|
}
|
|
FreePool (FdtDevicePath);
|
|
} else {
|
|
TextDevicePathSize = StrSize ((CHAR16*)PcdGetPtr (PcdFvpFdtDevicePathsBase)) - sizeof (CHAR16);
|
|
TextDevicePathSize += StrSize (Platform->FdtName);
|
|
|
|
TextDevicePath = AllocatePool (TextDevicePathSize);
|
|
if (TextDevicePath != NULL) {
|
|
StrCpy (TextDevicePath, ((CHAR16*)PcdGetPtr (PcdFvpFdtDevicePathsBase)));
|
|
StrCat (TextDevicePath, Platform->FdtName);
|
|
}
|
|
}
|
|
if (TextDevicePath != NULL) {
|
|
Buffer = PcdSetPtr (PcdFdtDevicePaths, &TextDevicePathSize, TextDevicePath);
|
|
if (Buffer == NULL) {
|
|
DEBUG ((
|
|
EFI_D_ERROR,
|
|
"ArmFvpDxe: Setting of FDT device path in PcdFdtDevicePaths failed - %r\n", EFI_BUFFER_TOO_SMALL
|
|
));
|
|
}
|
|
FreePool (TextDevicePath);
|
|
}
|
|
}
|
|
|
|
// Declare the Virtio BlockIo device
|
|
Status = VirtioMmioInstallDevice (ARM_FVP_BASE_VIRTIO_BLOCK_BASE, ImageHandle);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "ArmFvpDxe: Failed to install Virtio block device\n"));
|
|
}
|
|
|
|
// Install dynamic Shell command to run baremetal binaries.
|
|
Status = ShellDynCmdRunAxfInstall (ImageHandle);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "ArmFvpDxe: Failed to install ShellDynCmdRunAxf\n"));
|
|
}
|
|
|
|
return Status;
|
|
}
|