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