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