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