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