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