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