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