• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
InternalFindFdtByGuid(IN OUT EFI_DEVICE_PATH ** FdtDevicePath,IN CONST EFI_GUID * FdtGuid)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
ArmFvpInitialise(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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