1 /** @file 2 Internal file explorer helper functions for RamDiskDxe driver. 3 4 Copyright (c) 2016, 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 "RamDiskImpl.h" 16 17 18 /** 19 Helper function called as part of the code needed to allocate the proper 20 sized buffer for various EFI interfaces. 21 22 @param[in, out] Status Current status. 23 @param[in, out] Buffer Current allocated buffer, or NULL. 24 @param[in] BufferSize Current buffer size needed. 25 26 @retval TRUE If the buffer was reallocated and the caller should 27 try the API again. 28 @retval FALSE The caller should not call this function again. 29 30 **/ 31 BOOLEAN 32 GrowBuffer ( 33 IN OUT EFI_STATUS *Status, 34 IN OUT VOID **Buffer, 35 IN UINTN BufferSize 36 ) 37 { 38 BOOLEAN TryAgain; 39 40 // 41 // If this is an initial request, buffer will be null with a new buffer size 42 // 43 if ((*Buffer == NULL) && (BufferSize != 0)) { 44 *Status = EFI_BUFFER_TOO_SMALL; 45 } 46 // 47 // If the status code is "buffer too small", resize the buffer 48 // 49 TryAgain = FALSE; 50 if (*Status == EFI_BUFFER_TOO_SMALL) { 51 52 if (*Buffer != NULL) { 53 FreePool (*Buffer); 54 } 55 56 *Buffer = AllocateZeroPool (BufferSize); 57 58 if (*Buffer != NULL) { 59 TryAgain = TRUE; 60 } else { 61 *Status = EFI_OUT_OF_RESOURCES; 62 } 63 } 64 // 65 // If there's an error, free the buffer 66 // 67 if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) { 68 FreePool (*Buffer); 69 *Buffer = NULL; 70 } 71 72 return TryAgain; 73 } 74 75 76 /** 77 This function gets the file information from an open file descriptor, 78 and stores it in a buffer allocated from pool. 79 80 @param[in] FHand File Handle. 81 82 @return A pointer to a buffer with file information or NULL is returned. 83 84 **/ 85 EFI_FILE_INFO * 86 FileInfo ( 87 IN EFI_FILE_HANDLE FHand 88 ) 89 { 90 EFI_STATUS Status; 91 EFI_FILE_INFO *Buffer; 92 UINTN BufferSize; 93 94 // 95 // Initialize for GrowBuffer loop 96 // 97 Buffer = NULL; 98 BufferSize = SIZE_OF_EFI_FILE_INFO + 200; 99 100 // 101 // Call the real function 102 // 103 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { 104 Status = FHand->GetInfo ( 105 FHand, 106 &gEfiFileInfoGuid, 107 &BufferSize, 108 Buffer 109 ); 110 } 111 112 return Buffer; 113 } 114 115 116 /** 117 This function will open a file or directory referenced by DevicePath. 118 119 This function opens a file with the open mode according to the file path. The 120 Attributes is valid only for EFI_FILE_MODE_CREATE. 121 122 @param[in, out] FilePath On input, the device path to the file. 123 On output, the remaining device path. 124 @param[out] FileHandle Pointer to the file handle. 125 @param[in] OpenMode The mode to open the file with. 126 @param[in] Attributes The file's file attributes. 127 128 @retval EFI_SUCCESS The information was set. 129 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. 130 @retval EFI_UNSUPPORTED Could not open the file path. 131 @retval EFI_NOT_FOUND The specified file could not be found on the 132 device or the file system could not be found 133 on the device. 134 @retval EFI_NO_MEDIA The device has no medium. 135 @retval EFI_MEDIA_CHANGED The device has a different medium in it or 136 the medium is no longer supported. 137 @retval EFI_DEVICE_ERROR The device reported an error. 138 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. 139 @retval EFI_WRITE_PROTECTED The file or medium is write protected. 140 @retval EFI_ACCESS_DENIED The file was opened read only. 141 @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open 142 the file. 143 @retval EFI_VOLUME_FULL The volume is full. 144 **/ 145 EFI_STATUS 146 EFIAPI 147 OpenFileByDevicePath( 148 IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, 149 OUT EFI_FILE_HANDLE *FileHandle, 150 IN UINT64 OpenMode, 151 IN UINT64 Attributes 152 ) 153 { 154 EFI_STATUS Status; 155 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol; 156 EFI_FILE_PROTOCOL *Handle1; 157 EFI_FILE_PROTOCOL *Handle2; 158 EFI_HANDLE DeviceHandle; 159 160 if ((FilePath == NULL || FileHandle == NULL)) { 161 return EFI_INVALID_PARAMETER; 162 } 163 164 Status = gBS->LocateDevicePath ( 165 &gEfiSimpleFileSystemProtocolGuid, 166 FilePath, 167 &DeviceHandle 168 ); 169 if (EFI_ERROR (Status)) { 170 return Status; 171 } 172 173 Status = gBS->OpenProtocol( 174 DeviceHandle, 175 &gEfiSimpleFileSystemProtocolGuid, 176 (VOID**)&EfiSimpleFileSystemProtocol, 177 gImageHandle, 178 NULL, 179 EFI_OPEN_PROTOCOL_GET_PROTOCOL 180 ); 181 if (EFI_ERROR (Status)) { 182 return Status; 183 } 184 185 Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1); 186 if (EFI_ERROR (Status)) { 187 FileHandle = NULL; 188 return Status; 189 } 190 191 // 192 // go down directories one node at a time. 193 // 194 while (!IsDevicePathEnd (*FilePath)) { 195 // 196 // For file system access each node should be a file path component 197 // 198 if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH || 199 DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP 200 ) { 201 FileHandle = NULL; 202 return (EFI_INVALID_PARAMETER); 203 } 204 // 205 // Open this file path node 206 // 207 Handle2 = Handle1; 208 Handle1 = NULL; 209 210 // 211 // Try to test opening an existing file 212 // 213 Status = Handle2->Open ( 214 Handle2, 215 &Handle1, 216 ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, 217 OpenMode &~EFI_FILE_MODE_CREATE, 218 0 219 ); 220 221 // 222 // see if the error was that it needs to be created 223 // 224 if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) { 225 Status = Handle2->Open ( 226 Handle2, 227 &Handle1, 228 ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName, 229 OpenMode, 230 Attributes 231 ); 232 } 233 // 234 // Close the last node 235 // 236 Handle2->Close (Handle2); 237 238 if (EFI_ERROR(Status)) { 239 return (Status); 240 } 241 242 // 243 // Get the next node 244 // 245 *FilePath = NextDevicePathNode (*FilePath); 246 } 247 248 // 249 // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also! 250 // 251 *FileHandle = (VOID*)Handle1; 252 return EFI_SUCCESS; 253 } 254