Home | History | Annotate | Download | only in ArmVExpressDxe
      1 /** @file
      2 
      3   Copyright (c) 2013-2015, ARM Ltd. All rights reserved.<BR>
      4 
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "ArmVExpressInternal.h"
     16 
     17 #include <PiDxe.h>
     18 #include <Library/BaseMemoryLib.h>
     19 #include <Library/VirtioMmioDeviceLib.h>
     20 #include <Library/ArmShellCmdLib.h>
     21 #include <Library/MemoryAllocationLib.h>
     22 #include <Library/DevicePathLib.h>
     23 
     24 #include <Protocol/FirmwareVolume2.h>
     25 
     26 #define ARM_FVP_BASE_VIRTIO_BLOCK_BASE    0x1c130000
     27 
     28 #pragma pack(1)
     29 typedef struct {
     30   VENDOR_DEVICE_PATH                  Vendor;
     31   EFI_DEVICE_PATH_PROTOCOL            End;
     32 } VIRTIO_BLK_DEVICE_PATH;
     33 #pragma pack()
     34 
     35 VIRTIO_BLK_DEVICE_PATH mVirtioBlockDevicePath =
     36 {
     37   {
     38     {
     39       HARDWARE_DEVICE_PATH,
     40       HW_VENDOR_DP,
     41       {
     42         (UINT8)( sizeof(VENDOR_DEVICE_PATH) ),
     43         (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8)
     44       }
     45     },
     46     EFI_CALLER_ID_GUID,
     47   },
     48   {
     49     END_DEVICE_PATH_TYPE,
     50     END_ENTIRE_DEVICE_PATH_SUBTYPE,
     51     {
     52       sizeof (EFI_DEVICE_PATH_PROTOCOL),
     53       0
     54     }
     55   }
     56 };
     57 
     58 STATIC
     59 EFI_STATUS
     60 InternalFindFdtByGuid (
     61   IN OUT   EFI_DEVICE_PATH  **FdtDevicePath,
     62   IN CONST EFI_GUID         *FdtGuid
     63   )
     64 {
     65   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH    FileDevicePath;
     66   EFI_HANDLE                           *HandleBuffer;
     67   UINTN                                HandleCount;
     68   UINTN                                Index;
     69   EFI_FIRMWARE_VOLUME2_PROTOCOL        *FvProtocol;
     70   EFI_GUID                             NameGuid;
     71   UINTN                                Size;
     72   VOID                                 *Key;
     73   EFI_FV_FILETYPE                      FileType;
     74   EFI_FV_FILE_ATTRIBUTES               Attributes;
     75   EFI_DEVICE_PATH                      *FvDevicePath;
     76   EFI_STATUS                           Status;
     77 
     78   if (FdtGuid == NULL) {
     79     return EFI_NOT_FOUND;
     80   }
     81 
     82   EfiInitializeFwVolDevicepathNode (&FileDevicePath, FdtGuid);
     83 
     84   HandleBuffer = NULL;
     85   Status = gBS->LocateHandleBuffer (
     86                   ByProtocol,
     87                   &gEfiFirmwareVolume2ProtocolGuid,
     88                   NULL,
     89                   &HandleCount,
     90                   &HandleBuffer
     91                   );
     92   if (EFI_ERROR (Status)) {
     93     return Status;
     94   }
     95 
     96   for (Index = 0; Index < HandleCount; Index++) {
     97     Status = gBS->HandleProtocol (
     98                     HandleBuffer[Index],
     99                     &gEfiFirmwareVolume2ProtocolGuid,
    100                     (VOID **) &FvProtocol
    101                     );
    102     if (EFI_ERROR (Status)) {
    103       return Status;
    104     }
    105 
    106     // Allocate Key
    107     Key = AllocatePool (FvProtocol->KeySize);
    108     ASSERT (Key != NULL);
    109     ZeroMem (Key, FvProtocol->KeySize);
    110 
    111     do {
    112       FileType = EFI_FV_FILETYPE_RAW;
    113       Status = FvProtocol->GetNextFile (FvProtocol, Key, &FileType, &NameGuid, &Attributes, &Size);
    114       if (Status == EFI_NOT_FOUND) {
    115         break;
    116       }
    117       if (EFI_ERROR (Status)) {
    118         return Status;
    119       }
    120 
    121       //
    122       // Check whether this file is the one we are looking for. If so,
    123       // create a device path for it and return it to the caller.
    124       //
    125       if (CompareGuid (&NameGuid, FdtGuid)) {
    126           Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
    127           if (!EFI_ERROR (Status)) {
    128             *FdtDevicePath = AppendDevicePathNode (FvDevicePath,
    129                                (EFI_DEVICE_PATH_PROTOCOL *)&FileDevicePath);
    130           }
    131           goto Done;
    132       }
    133     } while (TRUE);
    134     FreePool (Key);
    135   }
    136 
    137   if (Index == HandleCount) {
    138     Status = EFI_NOT_FOUND;
    139   }
    140   return Status;
    141 
    142 Done:
    143   FreePool (Key);
    144   return Status;
    145 }
    146 
    147 /**
    148  * Generic UEFI Entrypoint for 'ArmFvpDxe' driver
    149  * See UEFI specification for the details of the parameters
    150  */
    151 EFI_STATUS
    152 EFIAPI
    153 ArmFvpInitialise (
    154   IN EFI_HANDLE         ImageHandle,
    155   IN EFI_SYSTEM_TABLE   *SystemTable
    156   )
    157 {
    158   CONST ARM_VEXPRESS_PLATFORM* Platform;
    159   EFI_STATUS                   Status;
    160   CHAR16                       *TextDevicePath;
    161   UINTN                        TextDevicePathSize;
    162   VOID                         *Buffer;
    163   EFI_DEVICE_PATH              *FdtDevicePath;
    164 
    165   Status = gBS->InstallProtocolInterface (&ImageHandle,
    166                  &gEfiDevicePathProtocolGuid, EFI_NATIVE_INTERFACE,
    167                  &mVirtioBlockDevicePath);
    168   if (EFI_ERROR (Status)) {
    169     return Status;
    170   }
    171 
    172   Status = ArmVExpressGetPlatform (&Platform);
    173   if (!EFI_ERROR (Status)) {
    174     FdtDevicePath = NULL;
    175     Status = InternalFindFdtByGuid (&FdtDevicePath, Platform->FdtGuid);
    176     if (!EFI_ERROR (Status)) {
    177       TextDevicePath = ConvertDevicePathToText (FdtDevicePath, FALSE, FALSE);
    178       if (TextDevicePath != NULL) {
    179         TextDevicePathSize = StrSize (TextDevicePath);
    180       }
    181       FreePool (FdtDevicePath);
    182     } else {
    183       TextDevicePathSize  = StrSize ((CHAR16*)PcdGetPtr (PcdFvpFdtDevicePathsBase)) - sizeof (CHAR16);
    184       TextDevicePathSize += StrSize (Platform->FdtName);
    185 
    186       TextDevicePath = AllocatePool (TextDevicePathSize);
    187       if (TextDevicePath != NULL) {
    188         StrCpy (TextDevicePath, ((CHAR16*)PcdGetPtr (PcdFvpFdtDevicePathsBase)));
    189         StrCat (TextDevicePath, Platform->FdtName);
    190       }
    191     }
    192     if (TextDevicePath != NULL) {
    193       Buffer = PcdSetPtr (PcdFdtDevicePaths, &TextDevicePathSize, TextDevicePath);
    194       if (Buffer == NULL) {
    195         DEBUG ((
    196           EFI_D_ERROR,
    197           "ArmFvpDxe: Setting of FDT device path in PcdFdtDevicePaths failed - %r\n", EFI_BUFFER_TOO_SMALL
    198           ));
    199       }
    200       FreePool (TextDevicePath);
    201     }
    202   }
    203 
    204   // Declare the Virtio BlockIo device
    205   Status = VirtioMmioInstallDevice (ARM_FVP_BASE_VIRTIO_BLOCK_BASE, ImageHandle);
    206   if (EFI_ERROR (Status)) {
    207     DEBUG ((EFI_D_ERROR, "ArmFvpDxe: Failed to install Virtio block device\n"));
    208   }
    209 
    210   // Install dynamic Shell command to run baremetal binaries.
    211   Status = ShellDynCmdRunAxfInstall (ImageHandle);
    212   if (EFI_ERROR (Status)) {
    213     DEBUG ((EFI_D_ERROR, "ArmFvpDxe: Failed to install ShellDynCmdRunAxf\n"));
    214   }
    215 
    216   return Status;
    217 }
    218