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
GrowBuffer(IN OUT EFI_STATUS * Status,IN OUT VOID ** Buffer,IN UINTN BufferSize)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 *
FileInfo(IN EFI_FILE_HANDLE FHand)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
OpenFileByDevicePath(IN OUT EFI_DEVICE_PATH_PROTOCOL ** FilePath,OUT EFI_FILE_HANDLE * FileHandle,IN UINT64 OpenMode,IN UINT64 Attributes)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