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