1 /** @file 2 * 3 * Copyright (c) 2011-2015, ARM Limited. All rights reserved. 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 "BdsInternal.h" 16 17 /** 18 Locate an EFI application in a the Firmware Volumes by its Name 19 20 @param EfiAppGuid Guid of the EFI Application into the Firmware Volume 21 @param DevicePath EFI Device Path of the EFI application 22 23 @return EFI_SUCCESS The function completed successfully. 24 @return EFI_NOT_FOUND The protocol could not be located. 25 @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. 26 27 **/ 28 EFI_STATUS 29 LocateEfiApplicationInFvByName ( 30 IN CONST CHAR16* EfiAppName, 31 OUT EFI_DEVICE_PATH **DevicePath 32 ) 33 { 34 VOID *Key; 35 EFI_STATUS Status, FileStatus; 36 EFI_GUID NameGuid; 37 EFI_FV_FILETYPE FileType; 38 EFI_FV_FILE_ATTRIBUTES Attributes; 39 UINTN Size; 40 UINTN UiStringLen; 41 CHAR16 *UiSection; 42 UINT32 Authentication; 43 EFI_DEVICE_PATH *FvDevicePath; 44 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileDevicePath; 45 EFI_HANDLE *HandleBuffer; 46 UINTN NumberOfHandles; 47 UINTN Index; 48 EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; 49 50 ASSERT (DevicePath != NULL); 51 52 // Length of FilePath 53 UiStringLen = StrLen (EfiAppName); 54 55 // Locate all the Firmware Volume protocols. 56 Status = gBS->LocateHandleBuffer ( 57 ByProtocol, 58 &gEfiFirmwareVolume2ProtocolGuid, 59 NULL, 60 &NumberOfHandles, 61 &HandleBuffer 62 ); 63 if (EFI_ERROR (Status)) { 64 return Status; 65 } 66 67 *DevicePath = NULL; 68 69 // Looking for FV with ACPI storage file 70 for (Index = 0; Index < NumberOfHandles; Index++) { 71 // 72 // Get the protocol on this handle 73 // This should not fail because of LocateHandleBuffer 74 // 75 Status = gBS->HandleProtocol ( 76 HandleBuffer[Index], 77 &gEfiFirmwareVolume2ProtocolGuid, 78 (VOID**) &FvInstance 79 ); 80 if (EFI_ERROR (Status)) { 81 goto FREE_HANDLE_BUFFER; 82 } 83 84 // Allocate Key 85 Key = AllocatePool (FvInstance->KeySize); 86 ASSERT (Key != NULL); 87 ZeroMem (Key, FvInstance->KeySize); 88 89 do { 90 // Search in all files 91 FileType = EFI_FV_FILETYPE_ALL; 92 93 Status = FvInstance->GetNextFile (FvInstance, Key, &FileType, &NameGuid, &Attributes, &Size); 94 if (!EFI_ERROR (Status)) { 95 UiSection = NULL; 96 FileStatus = FvInstance->ReadSection ( 97 FvInstance, 98 &NameGuid, 99 EFI_SECTION_USER_INTERFACE, 100 0, 101 (VOID **)&UiSection, 102 &Size, 103 &Authentication 104 ); 105 if (!EFI_ERROR (FileStatus)) { 106 if (StrnCmp (EfiAppName, UiSection, UiStringLen) == 0) { 107 // 108 // We found a UiString match. 109 // 110 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath); 111 112 // Generate the Device Path for the file 113 EfiInitializeFwVolDevicepathNode (&FileDevicePath, &NameGuid); 114 *DevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FileDevicePath); 115 ASSERT (*DevicePath != NULL); 116 117 FreePool (Key); 118 FreePool (UiSection); 119 FreePool (HandleBuffer); 120 return FileStatus; 121 } 122 FreePool (UiSection); 123 } 124 } 125 } while (!EFI_ERROR (Status)); 126 127 FreePool (Key); 128 } 129 130 FREE_HANDLE_BUFFER: 131 FreePool (HandleBuffer); 132 return EFI_NOT_FOUND; 133 } 134 135 /** 136 Locate an EFI application in a the Firmware Volumes by its GUID 137 138 @param EfiAppGuid Guid of the EFI Application into the Firmware Volume 139 @param DevicePath EFI Device Path of the EFI application 140 141 @return EFI_SUCCESS The function completed successfully. 142 @return EFI_NOT_FOUND The protocol could not be located. 143 @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol. 144 145 **/ 146 EFI_STATUS 147 LocateEfiApplicationInFvByGuid ( 148 IN CONST EFI_GUID *EfiAppGuid, 149 OUT EFI_DEVICE_PATH **DevicePath 150 ) 151 { 152 EFI_STATUS Status; 153 EFI_DEVICE_PATH *FvDevicePath; 154 EFI_HANDLE *HandleBuffer; 155 UINTN NumberOfHandles; 156 UINTN Index; 157 EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; 158 EFI_FV_FILE_ATTRIBUTES Attributes; 159 UINT32 AuthenticationStatus; 160 EFI_FV_FILETYPE Type; 161 UINTN Size; 162 CHAR16 *UiSection; 163 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileDevicePath; 164 165 ASSERT (DevicePath != NULL); 166 167 // Locate all the Firmware Volume protocols. 168 Status = gBS->LocateHandleBuffer ( 169 ByProtocol, 170 &gEfiFirmwareVolume2ProtocolGuid, 171 NULL, 172 &NumberOfHandles, 173 &HandleBuffer 174 ); 175 if (EFI_ERROR (Status)) { 176 return Status; 177 } 178 179 *DevicePath = NULL; 180 181 // Looking for FV with ACPI storage file 182 for (Index = 0; Index < NumberOfHandles; Index++) { 183 // 184 // Get the protocol on this handle 185 // This should not fail because of LocateHandleBuffer 186 // 187 Status = gBS->HandleProtocol ( 188 HandleBuffer[Index], 189 &gEfiFirmwareVolume2ProtocolGuid, 190 (VOID**) &FvInstance 191 ); 192 if (EFI_ERROR (Status)) { 193 goto FREE_HANDLE_BUFFER; 194 } 195 196 Status = FvInstance->ReadFile ( 197 FvInstance, 198 EfiAppGuid, 199 NULL, 200 &Size, 201 &Type, 202 &Attributes, 203 &AuthenticationStatus 204 ); 205 if (EFI_ERROR (Status)) { 206 // 207 // Skip if no EFI application file in the FV 208 // 209 continue; 210 } else { 211 UiSection = NULL; 212 Status = FvInstance->ReadSection ( 213 FvInstance, 214 EfiAppGuid, 215 EFI_SECTION_USER_INTERFACE, 216 0, 217 (VOID **)&UiSection, 218 &Size, 219 &AuthenticationStatus 220 ); 221 if (!EFI_ERROR (Status)) { 222 // 223 // Create the EFI Device Path for the application using the Filename of the application 224 // 225 *DevicePath = FileDevicePath (HandleBuffer[Index], UiSection); 226 } else { 227 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID**)&FvDevicePath); 228 ASSERT_EFI_ERROR (Status); 229 230 // 231 // Create the EFI Device Path for the application using the EFI GUID of the application 232 // 233 EfiInitializeFwVolDevicepathNode (&FvFileDevicePath, EfiAppGuid); 234 235 *DevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FvFileDevicePath); 236 ASSERT (*DevicePath != NULL); 237 } 238 break; 239 } 240 } 241 242 FREE_HANDLE_BUFFER: 243 // 244 // Free any allocated buffers 245 // 246 FreePool (HandleBuffer); 247 248 if (*DevicePath == NULL) { 249 return EFI_NOT_FOUND; 250 } else { 251 return EFI_SUCCESS; 252 } 253 } 254