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
EfiLibOpenRoot(IN EFI_HANDLE DeviceHandle)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
EfiGrowBuffer(IN OUT EFI_STATUS * Status,IN OUT VOID ** Buffer,IN UINTN BufferSize)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 *
EfiLibGetVariable(IN CHAR16 * Name,IN EFI_GUID * VendorGuid)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
EfiLibDeleteVariable(IN CHAR16 * VarName,IN EFI_GUID * VarGuid)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 *
EfiLibFileSystemVolumeLabelInfo(IN EFI_FILE_HANDLE FHand)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 *
EfiStrDuplicate(IN CHAR16 * Src)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 *
EfiLibFileInfo(IN EFI_FILE_HANDLE FHand)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
EfiDevicePathInstanceCount(IN EFI_DEVICE_PATH_PROTOCOL * DevicePath)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 *
EfiReallocatePool(IN VOID * OldPool,IN UINTN OldSize,IN UINTN NewSize)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 *
EfiLibStrFromDatahub(IN EFI_DEVICE_PATH_PROTOCOL * DevPath)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
EfiLibLocateProtocol(IN EFI_GUID * ProtocolGuid,OUT VOID ** Interface)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