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