]> git.proxmox.com Git - mirror_edk2.git/blame - EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BmLib.c
BDS code calls Hii->FindHandles() with hardcoded length.
[mirror_edk2.git] / EdkNt32Pkg / Dxe / PlatformBds / Generic / BootMaint / BmLib.c
CommitLineData
878ddf1f 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
a0a1e5aa 14 BmLib.c\r
878ddf1f 15 \r
16AgBStract:\r
17\r
18 Boot Maintainence Helper functions\r
19\r
20--*/\r
21\r
a0a1e5aa 22#include "BootMaint.h"\r
878ddf1f 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
0e7bfce8 467 //\r
468 // Initialize params.\r
469 //\r
470 HandleBufferLength = 0;\r
878ddf1f 471 HiiHandleBuffer = NULL;\r
0e7bfce8 472 \r
878ddf1f 473 Status = gBS->LocateProtocol (\r
474 &gEfiHiiProtocolGuid,\r
475 NULL,\r
476 &Hii\r
477 );\r
478 if (EFI_ERROR (Status)) {\r
479 *String = NULL;\r
480 return Status;\r
481 }\r
482 //\r
483 // Get all the Hii handles\r
484 //\r
0e7bfce8 485 Status = BdsLibGetHiiHandles (Hii, &HandleBufferLength, &HiiHandleBuffer);\r
878ddf1f 486 ASSERT_EFI_ERROR (Status);\r
0e7bfce8 487 \r
878ddf1f 488 //\r
489 // Get the Hii Handle that matches the StructureNode->ProducerName\r
490 //\r
491 NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE);\r
492 for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
493 Length = 0;\r
494 Status = ExtractDataFromHiiHandle (\r
495 HiiHandleBuffer[Index],\r
496 &Length,\r
497 NULL,\r
498 &HiiGuid\r
499 );\r
500 if (CompareGuid (ProducerGuid, &HiiGuid)) {\r
501 break;\r
502 }\r
503 }\r
504 //\r
505 // Find the string based on the current language\r
506 //\r
507 StringBufferLength = 0x100;\r
508 *String = AllocateZeroPool (0x100);\r
509 ASSERT (*String != NULL);\r
510\r
511 Status = Hii->GetString (\r
512 Hii,\r
513 HiiHandleBuffer[Index],\r
514 Token,\r
515 FALSE,\r
516 NULL,\r
517 &StringBufferLength,\r
518 *String\r
519 );\r
520\r
521 gBS->FreePool (HiiHandleBuffer);\r
522\r
523 return Status;\r
524}\r
525\r
526BOOLEAN\r
527TimeCompare (\r
528 IN EFI_TIME *FirstTime,\r
529 IN EFI_TIME *SecondTime\r
530 )\r
531/*++\r
532\r
533Routine Description:\r
534 Compare two EFI_TIME data.\r
535\r
536Arguments:\r
537\r
538 FirstTime - A pointer to the first EFI_TIME data.\r
539 SecondTime - A pointer to the second EFI_TIME data.\r
540\r
541Returns:\r
542 TRUE The FirstTime is not later than the SecondTime.\r
543 FALSE The FirstTime is later than the SecondTime.\r
544 \r
545--*/\r
546{\r
547 if (FirstTime->Year != SecondTime->Year) {\r
548 return (BOOLEAN) (FirstTime->Year < SecondTime->Year);\r
549 } else if (FirstTime->Month != SecondTime->Month) {\r
550 return (BOOLEAN) (FirstTime->Month < SecondTime->Month);\r
551 } else if (FirstTime->Day != SecondTime->Day) {\r
552 return (BOOLEAN) (FirstTime->Day < SecondTime->Day);\r
553 } else if (FirstTime->Hour != SecondTime->Hour) {\r
554 return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);\r
555 } else if (FirstTime->Minute != SecondTime->Minute) {\r
556 return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute);\r
557 } else if (FirstTime->Second != SecondTime->Second) {\r
558 return (BOOLEAN) (FirstTime->Second < SecondTime->Second);\r
559 }\r
560\r
561 return (BOOLEAN) (FirstTime->Nanosecond <= SecondTime->Nanosecond);\r
562}\r
563\r
564UINT16 *\r
565EfiLibStrFromDatahub (\r
566 IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
567 )\r
568{\r
569 EFI_STATUS Status;\r
570 UINT16 *Desc;\r
571 EFI_DATA_HUB_PROTOCOL *Datahub;\r
572 UINT64 Count;\r
573 EFI_DATA_RECORD_HEADER *Record;\r
574 EFI_SUBCLASS_TYPE1_HEADER *DataHdr;\r
575 EFI_GUID MiscGuid = EFI_MISC_SUBCLASS_GUID;\r
576 EFI_MISC_ONBOARD_DEVICE_DATA *ob;\r
577 EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *Port;\r
578 EFI_TIME CurTime;\r
579\r
580 Status = gBS->LocateProtocol (\r
581 &gEfiDataHubProtocolGuid,\r
582 NULL,\r
583 &Datahub\r
584 );\r
585 if (EFI_ERROR (Status)) {\r
586 return NULL;\r
587 }\r
588\r
589 Status = gRT->GetTime (&CurTime, NULL);\r
590 if (EFI_ERROR (Status)) {\r
591 return NULL;\r
592 }\r
593\r
594 Count = 0;\r
595 do {\r
596 Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record);\r
597\r
598 if (EFI_ERROR (Status)) {\r
599 break;\r
600 }\r
601\r
602 if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) {\r
603 //\r
604 // This record is what we need\r
605 //\r
606 DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1);\r
607 if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) {\r
608 ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1);\r
609 if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &ob->OnBoardDevicePath, DevPath)) {\r
610 EfiLibGetStringFromToken (&Record->ProducerName, ob->OnBoardDeviceDescription, &Desc);\r
611 return Desc;\r
612 }\r
613 }\r
614\r
615 if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) {\r
616 Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1);\r
617 if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) {\r
618 EfiLibGetStringFromToken (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc);\r
619 return Desc;\r
620 }\r
621 }\r
622 }\r
623\r
624 } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0);\r
625\r
626 return NULL;\r
627}\r