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