]> git.proxmox.com Git - mirror_edk2.git/blame - EdkUnixPkg/Dxe/PlatformBds/Generic/BootMaint/BmLib.c
fix some minor warning
[mirror_edk2.git] / EdkUnixPkg / Dxe / PlatformBds / Generic / BootMaint / BmLib.c
CommitLineData
c9093a06 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 BmLib.c\r
15 \r
16AgBStract:\r
17\r
18 Boot Maintainence Helper functions\r
19\r
20--*/\r
21\r
22#include "BootMaint.h"\r
23\r
24EFI_STATUS\r
25EfiLibLocateProtocol (\r
26 IN EFI_GUID *ProtocolGuid,\r
27 OUT VOID **Interface\r
28 )\r
29/*++\r
30\r
31Routine Description:\r
32\r
33 Find the first instance of this Protocol \r
34 in the system and return it's interface\r
35\r
36Arguments:\r
37\r
38 ProtocolGuid - Provides the protocol to search for\r
39 Interface - On return, a pointer to the first interface \r
40 that matches ProtocolGuid\r
41\r
42Returns:\r
43\r
44 EFI_SUCCESS - A protocol instance matching ProtocolGuid was found\r
45\r
46 EFI_NOT_FOUND - No protocol instances were found that match ProtocolGuid\r
47\r
48--*/\r
49{\r
50 EFI_STATUS Status;\r
51\r
52 Status = gBS->LocateProtocol (\r
53 ProtocolGuid,\r
54 NULL,\r
55 Interface\r
56 );\r
57 return Status;\r
58}\r
59\r
60EFI_FILE_HANDLE\r
61EfiLibOpenRoot (\r
62 IN EFI_HANDLE DeviceHandle\r
63 )\r
64/*++\r
65\r
66Routine Description:\r
67\r
68 Function opens and returns a file handle to the root directory of a volume.\r
69\r
70Arguments:\r
71\r
72 DeviceHandle - A handle for a device\r
73\r
74Returns:\r
75 \r
76 A valid file handle or NULL is returned\r
77\r
78--*/\r
79{\r
80 EFI_STATUS Status;\r
81 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
82 EFI_FILE_HANDLE File;\r
83\r
84 File = NULL;\r
85\r
86 //\r
87 // File the file system interface to the device\r
88 //\r
89 Status = gBS->HandleProtocol (\r
90 DeviceHandle,\r
91 &gEfiSimpleFileSystemProtocolGuid,\r
92 (VOID *) &Volume\r
93 );\r
94\r
95 //\r
96 // Open the root directory of the volume\r
97 //\r
98 if (!EFI_ERROR (Status)) {\r
99 Status = Volume->OpenVolume (\r
100 Volume,\r
101 &File\r
102 );\r
103 }\r
104 //\r
105 // Done\r
106 //\r
107 return EFI_ERROR (Status) ? NULL : File;\r
108}\r
109\r
110BOOLEAN\r
111EfiGrowBuffer (\r
112 IN OUT EFI_STATUS *Status,\r
113 IN OUT VOID **Buffer,\r
114 IN UINTN BufferSize\r
115 )\r
116/*++\r
117\r
118Routine Description:\r
119\r
120 Helper function called as part of the code needed\r
121 to allocate the proper sized buffer for various \r
122 EFI interfaces.\r
123\r
124Arguments:\r
125\r
126 Status - Current status\r
127\r
128 Buffer - Current allocated buffer, or NULL\r
129\r
130 BufferSize - Current buffer size needed\r
131 \r
132Returns:\r
133 \r
134 TRUE - if the buffer was reallocated and the caller \r
135 should try the API again.\r
136\r
137--*/\r
138{\r
139 BOOLEAN TryAgain;\r
140\r
141 //\r
142 // If this is an initial request, buffer will be null with a new buffer size\r
143 //\r
144 if (!*Buffer && BufferSize) {\r
145 *Status = EFI_BUFFER_TOO_SMALL;\r
146 }\r
147 //\r
148 // If the status code is "buffer too small", resize the buffer\r
149 //\r
150 TryAgain = FALSE;\r
151 if (*Status == EFI_BUFFER_TOO_SMALL) {\r
152\r
153 SafeFreePool (*Buffer);\r
154\r
155 *Buffer = AllocateZeroPool (BufferSize);\r
156\r
157 if (*Buffer) {\r
158 TryAgain = TRUE;\r
159 } else {\r
160 *Status = EFI_OUT_OF_RESOURCES;\r
161 }\r
162 }\r
163 //\r
164 // If there's an error, free the buffer\r
165 //\r
166 if (!TryAgain && EFI_ERROR (*Status) && *Buffer) {\r
167 SafeFreePool (*Buffer);\r
168 *Buffer = NULL;\r
169 }\r
170\r
171 return TryAgain;\r
172}\r
173\r
174VOID *\r
175EfiLibGetVariable (\r
176 IN CHAR16 *Name,\r
177 IN EFI_GUID *VendorGuid\r
178 )\r
179/*++\r
180\r
181Routine Description:\r
182 Function returns the value of the specified variable.\r
183\r
184Arguments:\r
185 Name - A Null-terminated Unicode string that is \r
186 the name of the vendor's variable.\r
187\r
188 VendorGuid - A unique identifier for the vendor.\r
189\r
190Returns:\r
191\r
192 None\r
193\r
194--*/\r
195{\r
196 UINTN VarSize;\r
197\r
198 return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize);\r
199}\r
200\r
201EFI_STATUS\r
202EfiLibDeleteVariable (\r
203 IN CHAR16 *VarName,\r
204 IN EFI_GUID *VarGuid\r
205 )\r
206/*++\r
207\r
208Routine Description:\r
209 Function deletes the variable specified by VarName and VarGuid.\r
210\r
211Arguments:\r
212 VarName - A Null-terminated Unicode string that is \r
213 the name of the vendor's variable.\r
214\r
215 VendorGuid - A unique identifier for the vendor.\r
216\r
217Returns:\r
218\r
219 EFI_SUCCESS - The variable was found and removed\r
220\r
221 EFI_UNSUPPORTED - The variable store was inaccessible\r
222\r
223 EFI_OUT_OF_RESOURCES - The temporary buffer was not available\r
224\r
225 EFI_NOT_FOUND - The variable was not found\r
226\r
227--*/\r
228{\r
229 VOID *VarBuf;\r
230 EFI_STATUS Status;\r
231\r
232 VarBuf = EfiLibGetVariable (VarName, VarGuid);\r
233 Status = EFI_NOT_FOUND;\r
234\r
235 if (VarBuf) {\r
236 //\r
237 // Delete variable from Storage\r
238 //\r
239 Status = gRT->SetVariable (VarName, VarGuid, VAR_FLAG, 0, NULL);\r
240 ASSERT (!EFI_ERROR (Status));\r
241 SafeFreePool (VarBuf);\r
242 }\r
243\r
244 return Status;\r
245}\r
246\r
247EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *\r
248EfiLibFileSystemVolumeLabelInfo (\r
249 IN EFI_FILE_HANDLE FHand\r
250 )\r
251/*++\r
252\r
253Routine Description:\r
254\r
255 Function gets the file system information from an open file descriptor, \r
256 and stores it in a buffer allocated from pool.\r
257\r
258Arguments:\r
259\r
260 Fhand - A file handle\r
261\r
262Returns:\r
263 \r
264 A pointer to a buffer with file information or NULL is returned\r
265\r
266--*/\r
267{\r
268 EFI_STATUS Status;\r
269 EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer;\r
270 UINTN BufferSize;\r
271 //\r
272 // Initialize for GrowBuffer loop\r
273 //\r
274 Buffer = NULL;\r
275 BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200;\r
276\r
277 //\r
278 // Call the real function\r
279 //\r
280 while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
281 Status = FHand->GetInfo (\r
282 FHand,\r
283 &gEfiFileSystemVolumeLabelInfoIdGuid,\r
284 &BufferSize,\r
285 Buffer\r
286 );\r
287 }\r
288\r
289 return Buffer;\r
290}\r
291\r
292CHAR16 *\r
293EfiStrDuplicate (\r
294 IN CHAR16 *Src\r
295 )\r
296{\r
297 CHAR16 *Dest;\r
298 UINTN Size;\r
299\r
300 Size = StrSize (Src);\r
301 Dest = AllocateZeroPool (Size);\r
302 ASSERT (Dest != NULL);\r
303 if (Dest) {\r
304 CopyMem (Dest, Src, Size);\r
305 }\r
306\r
307 return Dest;\r
308}\r
309\r
310EFI_FILE_INFO *\r
311EfiLibFileInfo (\r
312 IN EFI_FILE_HANDLE FHand\r
313 )\r
314/*++\r
315\r
316Routine Description:\r
317\r
318 Function gets the file information from an open file descriptor, and stores it \r
319 in a buffer allocated from pool.\r
320\r
321Arguments:\r
322\r
323 Fhand - A file handle\r
324\r
325Returns:\r
326 \r
327 A pointer to a buffer with file information or NULL is returned\r
328\r
329--*/\r
330{\r
331 EFI_STATUS Status;\r
332 EFI_FILE_INFO *Buffer;\r
333 UINTN BufferSize;\r
334\r
335 //\r
336 // Initialize for GrowBuffer loop\r
337 //\r
338 Buffer = NULL;\r
339 BufferSize = SIZE_OF_EFI_FILE_INFO + 200;\r
340\r
341 //\r
342 // Call the real function\r
343 //\r
344 while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {\r
345 Status = FHand->GetInfo (\r
346 FHand,\r
347 &gEfiFileInfoGuid,\r
348 &BufferSize,\r
349 Buffer\r
350 );\r
351 }\r
352\r
353 return Buffer;\r
354}\r
355\r
356UINTN\r
357EfiDevicePathInstanceCount (\r
358 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
359 )\r
360/*++\r
361\r
362Routine Description:\r
363 Function is used to determine the number of device path instances \r
364 that exist in a device path.\r
365\r
366Arguments:\r
367 DevicePath - A pointer to a device path data structure.\r
368\r
369Returns:\r
370\r
371 This function counts and returns the number of device path instances \r
372 in DevicePath.\r
373\r
374--*/\r
375{\r
376 UINTN Count;\r
377 UINTN Size;\r
378\r
379 Count = 0;\r
380 while (GetNextDevicePathInstance (&DevicePath, &Size)) {\r
381 Count += 1;\r
382 }\r
383\r
384 return Count;\r
385}\r
386\r
387VOID *\r
388EfiReallocatePool (\r
389 IN VOID *OldPool,\r
390 IN UINTN OldSize,\r
391 IN UINTN NewSize\r
392 )\r
393/*++\r
394\r
395Routine Description:\r
396 Adjusts the size of a previously allocated buffer.\r
397\r
398Arguments:\r
399 OldPool - A pointer to the buffer whose size is being adjusted.\r
400 OldSize - The size of the current buffer.\r
401 NewSize - The size of the new buffer.\r
402\r
403Returns:\r
404\r
405 EFI_SUCEESS - The requested number of bytes were allocated.\r
406\r
407 EFI_OUT_OF_RESOURCES - The pool requested could not be allocated.\r
408\r
409 EFI_INVALID_PARAMETER - The buffer was invalid.\r
410\r
411--*/\r
412{\r
413 VOID *NewPool;\r
414\r
415 NewPool = NULL;\r
416 if (NewSize) {\r
417 NewPool = AllocateZeroPool (NewSize);\r
418 }\r
419\r
420 if (OldPool) {\r
421 if (NewPool) {\r
422 CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);\r
423 }\r
424\r
425 SafeFreePool (OldPool);\r
426 }\r
427\r
428 return NewPool;\r
429}\r
430\r
431EFI_STATUS\r
432EfiLibGetStringFromToken (\r
433 IN EFI_GUID *ProducerGuid,\r
434 IN STRING_REF Token,\r
435 OUT CHAR16 **String\r
436 )\r
437/*++\r
438\r
439Routine Description:\r
440 \r
441 Acquire the string associated with the ProducerGuid and return it.\r
442\r
443Arguments:\r
444 \r
445 ProducerGuid - The Guid to search the HII database for\r
446 Token - The token value of the string to extract\r
447 String - The string that is extracted\r
448 \r
449Returns:\r
450\r
451 EFI_SUCCESS - Buffer filled with the requested forms. BufferLength\r
452 was updated.\r
453 EFI_BUFFER_TOO_SMALL - The buffer provided was not large enough to allow the form to be stored.\r
454\r
455--*/\r
456{\r
457 EFI_STATUS Status;\r
458 UINT16 HandleBufferLength;\r
459 EFI_HII_HANDLE *HiiHandleBuffer;\r
460 UINTN StringBufferLength;\r
461 UINTN NumberOfHiiHandles;\r
462 UINTN Index;\r
463 UINT16 Length;\r
464 EFI_GUID HiiGuid;\r
465 EFI_HII_PROTOCOL *Hii;\r
466\r
467 HandleBufferLength = 0x1000;\r
468 HiiHandleBuffer = NULL;\r
469 Status = gBS->LocateProtocol (\r
470 &gEfiHiiProtocolGuid,\r
471 NULL,\r
997e26f6 472 (VOID**) &Hii\r
c9093a06 473 );\r
474 if (EFI_ERROR (Status)) {\r
475 *String = NULL;\r
476 return Status;\r
477 }\r
478 //\r
479 // Get all the Hii handles\r
480 //\r
481 HiiHandleBuffer = AllocateZeroPool (HandleBufferLength);\r
482 ASSERT (HiiHandleBuffer != NULL);\r
483\r
484 Status = Hii->FindHandles (Hii, &HandleBufferLength, HiiHandleBuffer);\r
485 ASSERT_EFI_ERROR (Status);\r
486\r
487 //\r
488 // Get the Hii Handle that matches the StructureNode->ProducerName\r
489 //\r
490 NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);\r
491 for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
492 Length = 0;\r
493 Status = ExtractDataFromHiiHandle (\r
494 HiiHandleBuffer[Index],\r
495 &Length,\r
496 NULL,\r
497 &HiiGuid\r
498 );\r
499 if (CompareGuid (ProducerGuid, &HiiGuid)) {\r
500 break;\r
501 }\r
502 }\r
503 //\r
504 // Find the string based on the current language\r
505 //\r
506 StringBufferLength = 0x100;\r
507 *String = AllocateZeroPool (0x100);\r
508 ASSERT (*String != NULL);\r
509\r
510 Status = Hii->GetString (\r
511 Hii,\r
512 HiiHandleBuffer[Index],\r
513 Token,\r
514 FALSE,\r
515 NULL,\r
516 &StringBufferLength,\r
517 *String\r
518 );\r
519\r
520 gBS->FreePool (HiiHandleBuffer);\r
521\r
522 return Status;\r
523}\r
524\r
525BOOLEAN\r
526TimeCompare (\r
527 IN EFI_TIME *FirstTime,\r
528 IN EFI_TIME *SecondTime\r
529 )\r
530/*++\r
531\r
532Routine Description:\r
533 Compare two EFI_TIME data.\r
534\r
535Arguments:\r
536\r
537 FirstTime - A pointer to the first EFI_TIME data.\r
538 SecondTime - A pointer to the second EFI_TIME data.\r
539\r
540Returns:\r
541 TRUE The FirstTime is not later than the SecondTime.\r
542 FALSE The FirstTime is later than the SecondTime.\r
543 \r
544--*/\r
545{\r
546 if (FirstTime->Year != SecondTime->Year) {\r
547 return (BOOLEAN) (FirstTime->Year < SecondTime->Year);\r
548 } else if (FirstTime->Month != SecondTime->Month) {\r
549 return (BOOLEAN) (FirstTime->Month < SecondTime->Month);\r
550 } else if (FirstTime->Day != SecondTime->Day) {\r
551 return (BOOLEAN) (FirstTime->Day < SecondTime->Day);\r
552 } else if (FirstTime->Hour != SecondTime->Hour) {\r
553 return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);\r
554 } else if (FirstTime->Minute != SecondTime->Minute) {\r
555 return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);\r
556 } else if (FirstTime->Second != SecondTime->Second) {\r
557 return (BOOLEAN) (FirstTime->Second < SecondTime->Second);\r
558 }\r
559\r
560 return (BOOLEAN) (FirstTime->Nanosecond <= SecondTime->Nanosecond);\r
561}\r
562\r
563UINT16 *\r
564EfiLibStrFromDatahub (\r
565 IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
566 )\r
567{\r
568 EFI_STATUS Status;\r
569 UINT16 *Desc;\r
570 EFI_DATA_HUB_PROTOCOL *Datahub;\r
571 UINT64 Count;\r
572 EFI_DATA_RECORD_HEADER *Record;\r
573 EFI_SUBCLASS_TYPE1_HEADER *DataHdr;\r
574 EFI_GUID MiscGuid = EFI_MISC_SUBCLASS_GUID;\r
575 EFI_MISC_ONBOARD_DEVICE_DATA *ob;\r
576 EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *Port;\r
577 EFI_TIME CurTime;\r
578\r
579 Status = gBS->LocateProtocol (\r
580 &gEfiDataHubProtocolGuid,\r
581 NULL,\r
997e26f6 582 (VOID**) &Datahub\r
c9093a06 583 );\r
584 if (EFI_ERROR (Status)) {\r
585 return NULL;\r
586 }\r
587\r
588 Status = gRT->GetTime (&CurTime, NULL);\r
589 if (EFI_ERROR (Status)) {\r
590 return NULL;\r
591 }\r
592\r
593 Count = 0;\r
594 do {\r
595 Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record);\r
596\r
597 if (EFI_ERROR (Status)) {\r
598 break;\r
599 }\r
600\r
601 if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) {\r
602 //\r
603 // This record is what we need\r
604 //\r
605 DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
606 if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) {\r
607 ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1);\r
608 if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &ob->OnBoardDevicePath, DevPath)) {\r
609 EfiLibGetStringFromToken (&Record->ProducerName, ob->OnBoardDeviceDescription, &Desc);\r
610 return Desc;\r
611 }\r
612 }\r
613\r
614 if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) {\r
615 Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1);\r
616 if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) {\r
617 EfiLibGetStringFromToken (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc);\r
618 return Desc;\r
619 }\r
620 }\r
621 }\r
622\r
623 } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0);\r
624\r
625 return NULL;\r
626}\r