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