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