]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/BdsDxe/BootMaint/BmLib.c
Clean up BootMaint module in BdsDxe.
[mirror_edk2.git] / MdeModulePkg / Universal / BdsDxe / BootMaint / BmLib.c
CommitLineData
fd6a62f3 1/** @file\r
2 Utility routines used by boot maintenance modules.\r
93e3992d 3\r
fd6a62f3 4Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
93e3992d 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
fd6a62f3 13**/\r
93e3992d 14\r
15#include "BootMaint.h"\r
16\r
b30312ba 17/**\r
93e3992d 18\r
19 Find the first instance of this Protocol\r
20 in the system and return it's interface\r
21\r
93e3992d 22\r
dce655e8 23 @param ProtocolGuid Provides the protocol to search for\r
24 @param Interface On return, a pointer to the first interface\r
b30312ba 25 that matches ProtocolGuid\r
93e3992d 26\r
b30312ba 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
93e3992d 29\r
b30312ba 30**/\r
31EFI_STATUS\r
32EfiLibLocateProtocol (\r
33 IN EFI_GUID *ProtocolGuid,\r
34 OUT VOID **Interface\r
35 )\r
93e3992d 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
b30312ba 47/**\r
93e3992d 48\r
49 Function opens and returns a file handle to the root directory of a volume.\r
50\r
93e3992d 51\r
b30312ba 52 @param DeviceHandle - A handle for a device\r
93e3992d 53\r
b30312ba 54 @return A valid file handle or NULL is returned\r
93e3992d 55\r
b30312ba 56**/\r
57EFI_FILE_HANDLE\r
58EfiLibOpenRoot (\r
59 IN EFI_HANDLE DeviceHandle\r
60 )\r
93e3992d 61{\r
62 EFI_STATUS Status;\r
63 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
64 EFI_FILE_HANDLE File;\r
65\r
66 File = NULL;\r
67\r
68 //\r
69 // File the file system interface to the device\r
70 //\r
71 Status = gBS->HandleProtocol (\r
72 DeviceHandle,\r
73 &gEfiSimpleFileSystemProtocolGuid,\r
74 (VOID *) &Volume\r
75 );\r
76\r
77 //\r
78 // Open the root directory of the volume\r
79 //\r
80 if (!EFI_ERROR (Status)) {\r
81 Status = Volume->OpenVolume (\r
82 Volume,\r
83 &File\r
84 );\r
85 }\r
86 //\r
87 // Done\r
88 //\r
89 return EFI_ERROR (Status) ? NULL : File;\r
90}\r
91\r
b30312ba 92/**\r
93\r
94 Helper function called as part of the code needed\r
95 to allocate the proper sized buffer for various\r
96 EFI interfaces.\r
97\r
98\r
99 @param Status - Current status\r
100 @param Buffer - Current allocated buffer, or NULL\r
101 @param BufferSize - Current buffer size needed\r
102\r
103 @retval TRUE if the buffer was reallocated and the caller\r
104 should try the API again.\r
dce655e8 105 @retval FALSE The caller should not call this function again.\r
b30312ba 106\r
107**/\r
93e3992d 108BOOLEAN\r
109EfiGrowBuffer (\r
110 IN OUT EFI_STATUS *Status,\r
111 IN OUT VOID **Buffer,\r
112 IN UINTN BufferSize\r
113 )\r
93e3992d 114{\r
115 BOOLEAN TryAgain;\r
116\r
117 //\r
118 // If this is an initial request, buffer will be null with a new buffer size\r
119 //\r
a78b08d1 120 if ((*Buffer == NULL) && (BufferSize != 0)) {\r
93e3992d 121 *Status = EFI_BUFFER_TOO_SMALL;\r
122 }\r
123 //\r
124 // If the status code is "buffer too small", resize the buffer\r
125 //\r
126 TryAgain = FALSE;\r
127 if (*Status == EFI_BUFFER_TOO_SMALL) {\r
128\r
129 SafeFreePool (*Buffer);\r
130\r
dce655e8 131 *Buffer = AllocateZeroPool (BufferSize);\r
93e3992d 132\r
a78b08d1 133 if (*Buffer != NULL) {\r
93e3992d 134 TryAgain = TRUE;\r
135 } else {\r
136 *Status = EFI_OUT_OF_RESOURCES;\r
137 }\r
138 }\r
139 //\r
140 // If there's an error, free the buffer\r
141 //\r
a78b08d1 142 if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) {\r
93e3992d 143 SafeFreePool (*Buffer);\r
144 *Buffer = NULL;\r
145 }\r
146\r
147 return TryAgain;\r
148}\r
149\r
b30312ba 150/**\r
93e3992d 151 Function returns the value of the specified variable.\r
152\r
93e3992d 153\r
dce655e8 154 @param Name A Null-terminated Unicode string that is\r
b30312ba 155 the name of the vendor's variable.\r
dce655e8 156 @param VendorGuid A unique identifier for the vendor.\r
93e3992d 157\r
b30312ba 158 @return The payload of the variable.\r
dce655e8 159 @retval NULL If the variable can't be read.\r
93e3992d 160\r
b30312ba 161**/\r
162VOID *\r
163EfiLibGetVariable (\r
164 IN CHAR16 *Name,\r
165 IN EFI_GUID *VendorGuid\r
166 )\r
93e3992d 167{\r
168 UINTN VarSize;\r
169\r
170 return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize);\r
171}\r
172\r
b30312ba 173/**\r
93e3992d 174 Function deletes the variable specified by VarName and VarGuid.\r
175\r
93e3992d 176\r
b30312ba 177 @param VarName - A Null-terminated Unicode string that is\r
178 the name of the vendor's variable.\r
179 \r
180 @param VendorGuid - A unique identifier for the vendor.\r
93e3992d 181\r
b30312ba 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
93e3992d 186\r
b30312ba 187**/\r
188EFI_STATUS\r
189EfiLibDeleteVariable (\r
190 IN CHAR16 *VarName,\r
191 IN EFI_GUID *VarGuid\r
192 )\r
93e3992d 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
a78b08d1 200 if (VarBuf != NULL) {\r
93e3992d 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 SafeFreePool (VarBuf);\r
207 }\r
208\r
209 return Status;\r
210}\r
211\r
b30312ba 212/**\r
93e3992d 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
93e3992d 217\r
b30312ba 218 @param FHand The file handle.\r
93e3992d 219\r
dce655e8 220 @return A pointer to a buffer with file information.\r
221 @retval NULL is returned if failed to get Vaolume Label Info.\r
93e3992d 222\r
b30312ba 223**/\r
224EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *\r
225EfiLibFileSystemVolumeLabelInfo (\r
226 IN EFI_FILE_HANDLE FHand\r
227 )\r
93e3992d 228{\r
229 EFI_STATUS Status;\r
230 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *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_INFO + 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
b30312ba 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
dce655e8 259 @retval NULL If there is not enough memory.\r
b30312ba 260\r
261**/\r
93e3992d 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
dce655e8 271 Dest = AllocateZeroPool (Size);\r
93e3992d 272 ASSERT (Dest != NULL);\r
a78b08d1 273 if (Dest != NULL) {\r
93e3992d 274 CopyMem (Dest, Src, Size);\r
275 }\r
276\r
277 return Dest;\r
278}\r
279\r
b30312ba 280/**\r
93e3992d 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
b30312ba 285 @param FHand File Handle.\r
93e3992d 286\r
b30312ba 287 @return A pointer to a buffer with file information or NULL is returned\r
93e3992d 288\r
b30312ba 289**/\r
290EFI_FILE_INFO *\r
291EfiLibFileInfo (\r
292 IN EFI_FILE_HANDLE FHand\r
293 )\r
93e3992d 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
b30312ba 320/**\r
93e3992d 321 Function is used to determine the number of device path instances\r
322 that exist in a device path.\r
323\r
93e3992d 324\r
dce655e8 325 @param DevicePath A pointer to a device path data structure.\r
93e3992d 326\r
b30312ba 327 @return This function counts and returns the number of device path instances\r
328 in DevicePath.\r
93e3992d 329\r
b30312ba 330**/\r
331UINTN\r
332EfiDevicePathInstanceCount (\r
333 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
334 )\r
93e3992d 335{\r
336 UINTN Count;\r
337 UINTN Size;\r
338\r
339 Count = 0;\r
340 while (GetNextDevicePathInstance (&DevicePath, &Size)) {\r
341 Count += 1;\r
342 }\r
343\r
344 return Count;\r
345}\r
346\r
b30312ba 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
dce655e8 355 @return The newly allocated buffer.\r
356 @retval NULL Allocation failed.\r
b30312ba 357\r
358**/\r
93e3992d 359VOID *\r
360EfiReallocatePool (\r
361 IN VOID *OldPool,\r
362 IN UINTN OldSize,\r
363 IN UINTN NewSize\r
364 )\r
93e3992d 365{\r
366 VOID *NewPool;\r
367\r
368 NewPool = NULL;\r
a78b08d1 369 if (NewSize != 0) {\r
dce655e8 370 NewPool = AllocateZeroPool (NewSize);\r
93e3992d 371 }\r
372\r
a78b08d1 373 if (OldPool != NULL) {\r
374 if (NewPool != NULL) {\r
93e3992d 375 CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
376 }\r
377\r
378 SafeFreePool (OldPool);\r
379 }\r
380\r
381 return NewPool;\r
382}\r
383\r
b30312ba 384/**\r
93e3992d 385 Compare two EFI_TIME data.\r
386\r
93e3992d 387\r
b30312ba 388 @param FirstTime - A pointer to the first EFI_TIME data.\r
389 @param SecondTime - A pointer to the second EFI_TIME data.\r
93e3992d 390\r
b30312ba 391 @retval TRUE The FirstTime is not later than the SecondTime.\r
392 @retval FALSE The FirstTime is later than the SecondTime.\r
93e3992d 393\r
b30312ba 394**/\r
395BOOLEAN\r
396TimeCompare (\r
397 IN EFI_TIME *FirstTime,\r
398 IN EFI_TIME *SecondTime\r
399 )\r
93e3992d 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
b30312ba 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
dce655e8 426 @retval NULL If failed to get the String from Data Hub.\r
b30312ba 427\r
428**/\r
93e3992d 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 = EFI_MISC_SUBCLASS_GUID;\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 Status = gBS->LocateProtocol (\r
446 &gEfiDataHubProtocolGuid,\r
447 NULL,\r
448 (VOID **) &Datahub\r
449 );\r
450 if (EFI_ERROR (Status)) {\r
451 return NULL;\r
452 }\r
453\r
454 Status = gRT->GetTime (&CurTime, NULL);\r
455 if (EFI_ERROR (Status)) {\r
456 return NULL;\r
457 }\r
458\r
459 Count = 0;\r
460 do {\r
461 Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record);\r
462\r
463 if (EFI_ERROR (Status)) {\r
464 break;\r
465 }\r
466\r
467 if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) {\r
468 //\r
469 // This record is what we need\r
470 //\r
471 DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
472 if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) {\r
473 ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1);\r
474 if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &ob->OnBoardDevicePath, DevPath)) {\r
475 GetProducerString (&Record->ProducerName, ob->OnBoardDeviceDescription, &Desc);\r
476 return Desc;\r
477 }\r
478 }\r
479\r
480 if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) {\r
481 Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1);\r
482 if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) {\r
483 GetProducerString (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc);\r
484 return Desc;\r
485 }\r
486 }\r
487 }\r
488\r
489 } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0);\r
490\r
491 return NULL;\r
492}\r