1 /** @file 2 Utility routines used by boot maintenance modules. 3 4 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR> 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 "BootMaint.h" 16 17 /** 18 19 Function opens and returns a file handle to the root directory of a volume. 20 21 @param DeviceHandle A handle for a device 22 23 @return A valid file handle or NULL is returned 24 25 **/ 26 EFI_FILE_HANDLE 27 EfiLibOpenRoot ( 28 IN EFI_HANDLE DeviceHandle 29 ) 30 { 31 EFI_STATUS Status; 32 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; 33 EFI_FILE_HANDLE File; 34 35 File = NULL; 36 37 // 38 // File the file system interface to the device 39 // 40 Status = gBS->HandleProtocol ( 41 DeviceHandle, 42 &gEfiSimpleFileSystemProtocolGuid, 43 (VOID *) &Volume 44 ); 45 46 // 47 // Open the root directory of the volume 48 // 49 if (!EFI_ERROR (Status)) { 50 Status = Volume->OpenVolume ( 51 Volume, 52 &File 53 ); 54 } 55 // 56 // Done 57 // 58 return EFI_ERROR (Status) ? NULL : File; 59 } 60 61 /** 62 63 Helper function called as part of the code needed 64 to allocate the proper sized buffer for various 65 EFI interfaces. 66 67 68 @param Status Current status 69 @param Buffer Current allocated buffer, or NULL 70 @param BufferSize Current buffer size needed 71 72 @retval TRUE if the buffer was reallocated and the caller 73 should try the API again. 74 @retval FALSE The caller should not call this function again. 75 76 **/ 77 BOOLEAN 78 EfiGrowBuffer ( 79 IN OUT EFI_STATUS *Status, 80 IN OUT VOID **Buffer, 81 IN UINTN BufferSize 82 ) 83 { 84 BOOLEAN TryAgain; 85 86 // 87 // If this is an initial request, buffer will be null with a new buffer size 88 // 89 if ((*Buffer == NULL) && (BufferSize != 0)) { 90 *Status = EFI_BUFFER_TOO_SMALL; 91 } 92 // 93 // If the status code is "buffer too small", resize the buffer 94 // 95 TryAgain = FALSE; 96 if (*Status == EFI_BUFFER_TOO_SMALL) { 97 98 if (*Buffer != NULL) { 99 FreePool (*Buffer); 100 } 101 102 *Buffer = AllocateZeroPool (BufferSize); 103 104 if (*Buffer != NULL) { 105 TryAgain = TRUE; 106 } else { 107 *Status = EFI_OUT_OF_RESOURCES; 108 } 109 } 110 // 111 // If there's an error, free the buffer 112 // 113 if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) { 114 FreePool (*Buffer); 115 *Buffer = NULL; 116 } 117 118 return TryAgain; 119 } 120 121 /** 122 Function returns the value of the specified variable. 123 124 125 @param Name A Null-terminated Unicode string that is 126 the name of the vendor's variable. 127 @param VendorGuid A unique identifier for the vendor. 128 129 @return The payload of the variable. 130 @retval NULL If the variable can't be read. 131 132 **/ 133 VOID * 134 EfiLibGetVariable ( 135 IN CHAR16 *Name, 136 IN EFI_GUID *VendorGuid 137 ) 138 { 139 UINTN VarSize; 140 141 return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize); 142 } 143 144 /** 145 Function deletes the variable specified by VarName and VarGuid. 146 147 @param VarName A Null-terminated Unicode string that is 148 the name of the vendor's variable. 149 150 @param VarGuid A unique identifier for the vendor. 151 152 @retval EFI_SUCCESS The variable was found and removed 153 @retval EFI_UNSUPPORTED The variable store was inaccessible 154 @retval EFI_OUT_OF_RESOURCES The temporary buffer was not available 155 @retval EFI_NOT_FOUND The variable was not found 156 157 **/ 158 EFI_STATUS 159 EfiLibDeleteVariable ( 160 IN CHAR16 *VarName, 161 IN EFI_GUID *VarGuid 162 ) 163 { 164 VOID *VarBuf; 165 EFI_STATUS Status; 166 167 VarBuf = EfiLibGetVariable (VarName, VarGuid); 168 Status = EFI_NOT_FOUND; 169 170 if (VarBuf != NULL) { 171 // 172 // Delete variable from Storage 173 // 174 Status = gRT->SetVariable ( 175 VarName, 176 VarGuid, 177 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, 178 0, 179 NULL 180 ); 181 // 182 // Deleting variable with current variable implementation shouldn't fail. 183 // 184 ASSERT_EFI_ERROR (Status); 185 FreePool (VarBuf); 186 } 187 188 return Status; 189 } 190 191 /** 192 193 Function gets the file system information from an open file descriptor, 194 and stores it in a buffer allocated from pool. 195 196 197 @param FHand The file handle. 198 199 @return A pointer to a buffer with file information. 200 @retval NULL is returned if failed to get Vaolume Label Info. 201 202 **/ 203 EFI_FILE_SYSTEM_VOLUME_LABEL * 204 EfiLibFileSystemVolumeLabelInfo ( 205 IN EFI_FILE_HANDLE FHand 206 ) 207 { 208 EFI_STATUS Status; 209 EFI_FILE_SYSTEM_VOLUME_LABEL *Buffer; 210 UINTN BufferSize; 211 // 212 // Initialize for GrowBuffer loop 213 // 214 Buffer = NULL; 215 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200; 216 217 // 218 // Call the real function 219 // 220 while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { 221 Status = FHand->GetInfo ( 222 FHand, 223 &gEfiFileSystemVolumeLabelInfoIdGuid, 224 &BufferSize, 225 Buffer 226 ); 227 } 228 229 return Buffer; 230 } 231 232 /** 233 Duplicate a string. 234 235 @param Src The source. 236 237 @return A new string which is duplicated copy of the source. 238 @retval NULL If there is not enough memory. 239 240 **/ 241 CHAR16 * 242 EfiStrDuplicate ( 243 IN CHAR16 *Src 244 ) 245 { 246 CHAR16 *Dest; 247 UINTN Size; 248 249 Size = StrSize (Src); 250 Dest = AllocateZeroPool (Size); 251 ASSERT (Dest != NULL); 252 if (Dest != NULL) { 253 CopyMem (Dest, Src, Size); 254 } 255 256 return Dest; 257 } 258 259 /** 260 261 Function gets the file information from an open file descriptor, and stores it 262 in a buffer allocated from pool. 263 264 @param FHand File Handle. 265 266 @return A pointer to a buffer with file information or NULL is returned 267 268 **/ 269 EFI_FILE_INFO * 270 EfiLibFileInfo ( 271 IN EFI_FILE_HANDLE FHand 272 ) 273 { 274 EFI_STATUS Status; 275 EFI_FILE_INFO *Buffer; 276 UINTN BufferSize; 277 278 // 279 // Initialize for GrowBuffer loop 280 // 281 Buffer = NULL; 282 BufferSize = SIZE_OF_EFI_FILE_INFO + 200; 283 284 // 285 // Call the real function 286 // 287 while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { 288 Status = FHand->GetInfo ( 289 FHand, 290 &gEfiFileInfoGuid, 291 &BufferSize, 292 Buffer 293 ); 294 } 295 296 return Buffer; 297 } 298 299 /** 300 Function is used to determine the number of device path instances 301 that exist in a device path. 302 303 304 @param DevicePath A pointer to a device path data structure. 305 306 @return This function counts and returns the number of device path instances 307 in DevicePath. 308 309 **/ 310 UINTN 311 EfiDevicePathInstanceCount ( 312 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath 313 ) 314 { 315 UINTN Count; 316 UINTN Size; 317 318 Count = 0; 319 while (GetNextDevicePathInstance (&DevicePath, &Size) != NULL) { 320 Count += 1; 321 } 322 323 return Count; 324 } 325 326 /** 327 Adjusts the size of a previously allocated buffer. 328 329 330 @param OldPool - A pointer to the buffer whose size is being adjusted. 331 @param OldSize - The size of the current buffer. 332 @param NewSize - The size of the new buffer. 333 334 @return The newly allocated buffer. 335 @retval NULL Allocation failed. 336 337 **/ 338 VOID * 339 EfiReallocatePool ( 340 IN VOID *OldPool, 341 IN UINTN OldSize, 342 IN UINTN NewSize 343 ) 344 { 345 VOID *NewPool; 346 347 NewPool = NULL; 348 if (NewSize != 0) { 349 NewPool = AllocateZeroPool (NewSize); 350 } 351 352 if (OldPool != NULL) { 353 if (NewPool != NULL) { 354 CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); 355 } 356 357 FreePool (OldPool); 358 } 359 360 return NewPool; 361 } 362 363 /** 364 Get a string from the Data Hub record based on 365 a device path. 366 367 @param DevPath The device Path. 368 369 @return A string located from the Data Hub records based on 370 the device path. 371 @retval NULL If failed to get the String from Data Hub. 372 373 **/ 374 UINT16 * 375 EfiLibStrFromDatahub ( 376 IN EFI_DEVICE_PATH_PROTOCOL *DevPath 377 ) 378 { 379 return NULL; 380 } 381 382 /** 383 384 Find the first instance of this Protocol 385 in the system and return it's interface. 386 387 388 @param ProtocolGuid Provides the protocol to search for 389 @param Interface On return, a pointer to the first interface 390 that matches ProtocolGuid 391 392 @retval EFI_SUCCESS A protocol instance matching ProtocolGuid was found 393 @retval EFI_NOT_FOUND No protocol instances were found that match ProtocolGuid 394 395 **/ 396 EFI_STATUS 397 EfiLibLocateProtocol ( 398 IN EFI_GUID *ProtocolGuid, 399 OUT VOID **Interface 400 ) 401 { 402 EFI_STATUS Status; 403 404 Status = gBS->LocateProtocol ( 405 ProtocolGuid, 406 NULL, 407 (VOID **) Interface 408 ); 409 return Status; 410 } 411 412