123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- /** @file
- * Virtio FDT client protocol driver for virtio,mmio DT node
- *
- * Copyright (c) 2014 - 2016, Linaro Ltd. All rights reserved.<BR>
- *
- * SPDX-License-Identifier: BSD-2-Clause-Patent
- *
- **/
- #include <Library/BaseLib.h>
- #include <Library/BaseMemoryLib.h>
- #include <Library/DebugLib.h>
- #include <Library/DevicePathLib.h>
- #include <Library/MemoryAllocationLib.h>
- #include <Library/UefiBootServicesTableLib.h>
- #include <Library/UefiDriverEntryPoint.h>
- #include <Library/VirtioMmioDeviceLib.h>
- #include <Guid/VirtioMmioTransport.h>
- #include <Protocol/FdtClient.h>
- #pragma pack (1)
- typedef struct {
- VENDOR_DEVICE_PATH Vendor;
- UINT64 PhysBase;
- EFI_DEVICE_PATH_PROTOCOL End;
- } VIRTIO_TRANSPORT_DEVICE_PATH;
- #pragma pack ()
- EFI_STATUS
- EFIAPI
- InitializeVirtioFdtDxe (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status, FindNodeStatus;
- FDT_CLIENT_PROTOCOL *FdtClient;
- INT32 Node;
- CONST UINT64 *Reg;
- UINT32 RegSize;
- VIRTIO_TRANSPORT_DEVICE_PATH *DevicePath;
- EFI_HANDLE Handle;
- UINT64 RegBase;
- Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
- (VOID **)&FdtClient);
- ASSERT_EFI_ERROR (Status);
- for (FindNodeStatus = FdtClient->FindCompatibleNode (FdtClient,
- "virtio,mmio", &Node);
- !EFI_ERROR (FindNodeStatus);
- FindNodeStatus = FdtClient->FindNextCompatibleNode (FdtClient,
- "virtio,mmio", Node, &Node)) {
- Status = FdtClient->GetNodeProperty (FdtClient, Node, "reg",
- (CONST VOID **)&Reg, &RegSize);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "%a: GetNodeProperty () failed (Status == %r)\n",
- __FUNCTION__, Status));
- continue;
- }
- ASSERT (RegSize == 16);
- //
- // Create a unique device path for this transport on the fly
- //
- RegBase = SwapBytes64 (*Reg);
- DevicePath = (VIRTIO_TRANSPORT_DEVICE_PATH *)CreateDeviceNode (
- HARDWARE_DEVICE_PATH,
- HW_VENDOR_DP,
- sizeof (VIRTIO_TRANSPORT_DEVICE_PATH));
- if (DevicePath == NULL) {
- DEBUG ((EFI_D_ERROR, "%a: Out of memory\n", __FUNCTION__));
- continue;
- }
- CopyGuid (&DevicePath->Vendor.Guid, &gVirtioMmioTransportGuid);
- DevicePath->PhysBase = RegBase;
- SetDevicePathNodeLength (&DevicePath->Vendor,
- sizeof (*DevicePath) - sizeof (DevicePath->End));
- SetDevicePathEndNode (&DevicePath->End);
- Handle = NULL;
- Status = gBS->InstallProtocolInterface (&Handle,
- &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,
- DevicePath);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "%a: Failed to install the EFI_DEVICE_PATH "
- "protocol on a new handle (Status == %r)\n",
- __FUNCTION__, Status));
- FreePool (DevicePath);
- continue;
- }
- Status = VirtioMmioInstallDevice (RegBase, Handle);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "%a: Failed to install VirtIO transport @ 0x%Lx "
- "on handle %p (Status == %r)\n", __FUNCTION__, RegBase,
- Handle, Status));
- Status = gBS->UninstallProtocolInterface (Handle,
- &gEfiDevicePathProtocolGuid, DevicePath);
- ASSERT_EFI_ERROR (Status);
- FreePool (DevicePath);
- continue;
- }
- }
- if (EFI_ERROR (FindNodeStatus) && FindNodeStatus != EFI_NOT_FOUND) {
- DEBUG ((EFI_D_ERROR, "%a: Error occurred while iterating DT nodes "
- "(FindNodeStatus == %r)\n", __FUNCTION__, FindNodeStatus));
- }
- return EFI_SUCCESS;
- }
|