TianoCore EDK2 master
Loading...
Searching...
No Matches
BmMisc.c
Go to the documentation of this file.
1
10#include "InternalBm.h"
11
29 )
30{
32 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
33 EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
34 UINTN InstanceSize;
35 UINTN SingleDpSize;
36
37 NewDevicePath = NULL;
38 TempNewDevicePath = NULL;
39
40 if ((Multi == NULL) || (Single == NULL)) {
41 return Multi;
42 }
43
44 Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
45 SingleDpSize = GetDevicePathSize (Single) - END_DEVICE_PATH_LENGTH;
46 InstanceSize -= END_DEVICE_PATH_LENGTH;
47
48 while (Instance != NULL) {
49 if (CompareMem (Instance, Single, MIN (SingleDpSize, InstanceSize)) != 0) {
50 //
51 // Append the device path instance which does not match with Single
52 //
53 TempNewDevicePath = NewDevicePath;
54 NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance);
55 if (TempNewDevicePath != NULL) {
56 FreePool (TempNewDevicePath);
57 }
58 }
59
60 FreePool (Instance);
61 Instance = GetNextDevicePathInstance (&Multi, &InstanceSize);
62 InstanceSize -= END_DEVICE_PATH_LENGTH;
63 }
64
65 return NewDevicePath;
66}
67
81BOOLEAN
85 )
86{
87 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
88 EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;
89 UINTN Size;
90
91 if ((Multi == NULL) || (Single == NULL)) {
92 return FALSE;
93 }
94
95 DevicePath = Multi;
96 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
97
98 //
99 // Search for the match of 'Single' in 'Multi'
100 //
101 while (DevicePathInst != NULL) {
102 //
103 // If the single device path is found in multiple device paths,
104 // return success
105 //
106 if (CompareMem (Single, DevicePathInst, Size) == 0) {
107 FreePool (DevicePathInst);
108 return TRUE;
109 }
110
111 FreePool (DevicePathInst);
112 DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);
113 }
114
115 return FALSE;
116}
117
128VOID
130 IN BOOLEAN Boot
131 )
132{
133 EFI_STATUS Status;
134 EFI_MEMORY_TYPE_INFORMATION *PreviousMemoryTypeInformation;
135 EFI_MEMORY_TYPE_INFORMATION *CurrentMemoryTypeInformation;
136 UINTN VariableSize;
137 UINTN Index;
138 UINTN Index1;
139 UINT32 Previous;
140 UINT32 Current;
141 UINT32 Next;
142 EFI_HOB_GUID_TYPE *GuidHob;
143 BOOLEAN MemoryTypeInformationModified;
144 BOOLEAN MemoryTypeInformationVariableExists;
145 EFI_BOOT_MODE BootMode;
146
147 MemoryTypeInformationModified = FALSE;
148 MemoryTypeInformationVariableExists = FALSE;
149
150 BootMode = GetBootModeHob ();
151 //
152 // In BOOT_IN_RECOVERY_MODE, Variable region is not reliable.
153 //
154 if (BootMode == BOOT_IN_RECOVERY_MODE) {
155 return;
156 }
157
158 //
159 // Only check the the Memory Type Information variable in the boot mode
160 // other than BOOT_WITH_DEFAULT_SETTINGS because the Memory Type
161 // Information is not valid in this boot mode.
162 //
163 if (BootMode != BOOT_WITH_DEFAULT_SETTINGS) {
164 VariableSize = 0;
165 Status = gRT->GetVariable (
166 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
167 &gEfiMemoryTypeInformationGuid,
168 NULL,
169 &VariableSize,
170 NULL
171 );
172 if (Status == EFI_BUFFER_TOO_SMALL) {
173 MemoryTypeInformationVariableExists = TRUE;
174 }
175 }
176
177 //
178 // Retrieve the current memory usage statistics. If they are not found, then
179 // no adjustments can be made to the Memory Type Information variable.
180 //
182 &gEfiMemoryTypeInformationGuid,
183 (VOID **)&CurrentMemoryTypeInformation
184 );
185 if (EFI_ERROR (Status) || (CurrentMemoryTypeInformation == NULL)) {
186 return;
187 }
188
189 //
190 // Get the Memory Type Information settings from Hob if they exist,
191 // PEI is responsible for getting them from variable and build a Hob to save them.
192 // If the previous Memory Type Information is not available, then set defaults
193 //
194 GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
195 if (GuidHob == NULL) {
196 //
197 // If Platform has not built Memory Type Info into the Hob, just return.
198 //
199 return;
200 }
201
202 VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
203 PreviousMemoryTypeInformation = AllocateCopyPool (VariableSize, GET_GUID_HOB_DATA (GuidHob));
204 if (PreviousMemoryTypeInformation == NULL) {
205 return;
206 }
207
208 //
209 // Use a heuristic to adjust the Memory Type Information for the next boot
210 //
211 DEBUG ((DEBUG_INFO, "Memory Previous Current Next \n"));
212 DEBUG ((DEBUG_INFO, " Type Pages Pages Pages \n"));
213 DEBUG ((DEBUG_INFO, "====== ======== ======== ========\n"));
214
215 for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {
216 for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {
217 if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {
218 break;
219 }
220 }
221
222 if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {
223 continue;
224 }
225
226 //
227 // Previous is the number of pages pre-allocated
228 // Current is the number of pages actually needed
229 //
230 Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;
231 Current = CurrentMemoryTypeInformation[Index1].NumberOfPages;
232 Next = Previous;
233
234 //
235 // Inconsistent Memory Reserved across bootings may lead to S4 fail
236 // Write next varible to 125% * current when the pre-allocated memory is:
237 // 1. More than 150% of needed memory and boot mode is BOOT_WITH_DEFAULT_SETTING
238 // 2. Less than the needed memory
239 //
240 if ((Current + (Current >> 1)) < Previous) {
241 if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
242 Next = Current + (Current >> 2);
243 }
244 } else if (Current > Previous) {
245 Next = Current + (Current >> 2);
246 }
247
248 if ((Next > 0) && (Next < 4)) {
249 Next = 4;
250 }
251
252 if (Next != Previous) {
253 PreviousMemoryTypeInformation[Index].NumberOfPages = Next;
254 MemoryTypeInformationModified = TRUE;
255 }
256
257 DEBUG ((DEBUG_INFO, " %02x %08x %08x %08x\n", PreviousMemoryTypeInformation[Index].Type, Previous, Current, Next));
258 }
259
260 //
261 // If any changes were made to the Memory Type Information settings, then set the new variable value;
262 // Or create the variable in first boot.
263 //
264 if (MemoryTypeInformationModified || !MemoryTypeInformationVariableExists) {
266 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
267 &gEfiMemoryTypeInformationGuid,
268 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
269 VariableSize,
270 PreviousMemoryTypeInformation
271 );
272
273 if (!EFI_ERROR (Status)) {
274 //
275 // If the Memory Type Information settings have been modified and the boot option belongs to boot category,
276 // then reset the platform so the new Memory Type Information setting will be used to guarantee that an S4
277 // entry/resume cycle will not fail.
278 //
279 if (MemoryTypeInformationModified) {
280 DEBUG ((DEBUG_INFO, "Memory Type Information settings change.\n"));
281 if (Boot && PcdGetBool (PcdResetOnMemoryTypeInformationChange)) {
282 DEBUG ((DEBUG_INFO, "...Warm Reset!!!\n"));
283 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
284 }
285 }
286 } else {
287 DEBUG ((DEBUG_ERROR, "Memory Type Information settings cannot be saved. OS S4 may fail!\n"));
288 }
289 }
290
291 FreePool (PreviousMemoryTypeInformation);
292}
293
329 IN CHAR16 *VariableName,
330 IN EFI_GUID *VendorGuid,
331 IN UINT32 Attributes,
332 IN UINTN DataSize,
333 IN VOID *Data
334 )
335{
336 EFI_STATUS Status;
337 EDKII_SET_VARIABLE_STATUS *SetVariableStatus;
338 UINTN NameSize;
339
340 Status = gRT->SetVariable (
341 VariableName,
342 VendorGuid,
343 Attributes,
344 DataSize,
345 Data
346 );
347 if (EFI_ERROR (Status)) {
348 NameSize = StrSize (VariableName);
349 SetVariableStatus = AllocatePool (sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize);
350 if (SetVariableStatus != NULL) {
351 CopyGuid (&SetVariableStatus->Guid, VendorGuid);
352 SetVariableStatus->NameSize = NameSize;
353 SetVariableStatus->DataSize = DataSize;
354 SetVariableStatus->SetStatus = Status;
355 SetVariableStatus->Attributes = Attributes;
356 CopyMem (SetVariableStatus + 1, VariableName, NameSize);
357 CopyMem (((UINT8 *)(SetVariableStatus + 1)) + NameSize, Data, DataSize);
358
360 EFI_ERROR_CODE,
361 PcdGet32 (PcdErrorCodeSetVariable),
362 0,
363 NULL,
364 &gEdkiiStatusCodeDataTypeVariableGuid,
365 SetVariableStatus,
366 sizeof (EDKII_SET_VARIABLE_STATUS) + NameSize + DataSize
367 );
368
369 FreePool (SetVariableStatus);
370 }
371 }
372
373 return Status;
374}
375
381VOID
383 EFI_DEVICE_PATH_PROTOCOL *DevicePath
384 )
385{
386 CHAR16 *Str;
387
388 Str = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
389 DEBUG ((DEBUG_INFO, "%s", Str));
390 if (Str != NULL) {
391 FreePool (Str);
392 }
393}
394
403UINTN
405 IN CHAR16 Char
406 )
407{
408 if ((Char >= L'0') && (Char <= L'9')) {
409 return (Char - L'0');
410 }
411
412 if ((Char >= L'A') && (Char <= L'F')) {
413 return (Char - L'A' + 0xA);
414 }
415
416 return (UINTN)-1;
417}
418
427EFIAPI
429 VOID
430 )
431{
432 EFI_STATUS Status;
434 UINTN HandleCount;
435 EFI_HANDLE *Handles;
436 UINTN Index;
437 UINTN ImageIndex;
438 EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
439 VOID *Image;
440 UINTN ImageSize;
441 BOOLEAN BootOption;
442 EFI_HANDLE ImageHandle;
443 UINTN ImageCount;
444 UINTN LoadCount;
445
446 //
447 // Find all the deferred image load protocols.
448 //
449 HandleCount = 0;
450 Handles = NULL;
451 Status = gBS->LocateHandleBuffer (
453 &gEfiDeferredImageLoadProtocolGuid,
454 NULL,
455 &HandleCount,
456 &Handles
457 );
458 if (EFI_ERROR (Status)) {
459 return EFI_NOT_FOUND;
460 }
461
462 ImageCount = 0;
463 LoadCount = 0;
464 for (Index = 0; Index < HandleCount; Index++) {
465 Status = gBS->HandleProtocol (Handles[Index], &gEfiDeferredImageLoadProtocolGuid, (VOID **)&DeferredImage);
466 if (EFI_ERROR (Status)) {
467 continue;
468 }
469
470 for (ImageIndex = 0; ; ImageIndex++) {
471 //
472 // Load all the deferred images in this protocol instance.
473 //
474 Status = DeferredImage->GetImageInfo (
475 DeferredImage,
476 ImageIndex,
477 &ImageDevicePath,
478 (VOID **)&Image,
479 &ImageSize,
480 &BootOption
481 );
482 if (EFI_ERROR (Status)) {
483 break;
484 }
485
486 ImageCount++;
487 //
488 // Load and start the image.
489 //
490 Status = gBS->LoadImage (
491 BootOption,
493 ImageDevicePath,
494 NULL,
495 0,
496 &ImageHandle
497 );
498 if (EFI_ERROR (Status)) {
499 //
500 // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created
501 // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.
502 // If the caller doesn't have the option to defer the execution of an image, we should
503 // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.
504 //
505 if (Status == EFI_SECURITY_VIOLATION) {
506 gBS->UnloadImage (ImageHandle);
507 }
508 } else {
509 LoadCount++;
510 //
511 // Before calling the image, enable the Watchdog Timer for
512 // a 5 Minute period
513 //
514 gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);
515 gBS->StartImage (ImageHandle, NULL, NULL);
516
517 //
518 // Clear the Watchdog Timer after the image returns.
519 //
520 gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
521 }
522 }
523 }
524
525 if (Handles != NULL) {
526 FreePool (Handles);
527 }
528
529 if (ImageCount == 0) {
530 return EFI_NOT_FOUND;
531 } else {
532 if (LoadCount == 0) {
533 return EFI_ACCESS_DENIED;
534 } else {
535 return EFI_SUCCESS;
536 }
537 }
538}
UINT64 UINTN
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition: HobLib.c:215
EFI_BOOT_MODE EFIAPI GetBootModeHob(VOID)
Definition: HobLib.c:240
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
EFI_STATUS EFIAPI EfiBootManagerDispatchDeferredImages(VOID)
Definition: BmMisc.c:428
VOID BmSetMemoryTypeInformationVariable(IN BOOLEAN Boot)
Definition: BmMisc.c:129
VOID BmPrintDp(EFI_DEVICE_PATH_PROTOCOL *DevicePath)
Definition: BmMisc.c:382
UINTN BmCharToUint(IN CHAR16 Char)
Definition: BmMisc.c:404
EFI_STATUS BmSetVariableAndReportStatusCodeOnError(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data)
Definition: BmMisc.c:328
EFI_DEVICE_PATH_PROTOCOL * BmDelPartMatchInstance(IN EFI_DEVICE_PATH_PROTOCOL *Multi, IN EFI_DEVICE_PATH_PROTOCOL *Single)
Definition: BmMisc.c:26
BOOLEAN BmMatchDevicePaths(IN EFI_DEVICE_PATH_PROTOCOL *Multi, IN EFI_DEVICE_PATH_PROTOCOL *Single)
Definition: BmMisc.c:82
EFI_DEVICE_PATH_PROTOCOL *EFIAPI AppendDevicePathInstance(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL, IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL)
EFI_DEVICE_PATH_PROTOCOL *EFIAPI GetNextDevicePathInstance(IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, OUT UINTN *Size)
CHAR16 *EFIAPI ConvertDevicePathToText(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN BOOLEAN DisplayOnly, IN BOOLEAN AllowShortcuts)
UINTN EFIAPI GetDevicePathSize(IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define MIN(a, b)
Definition: Base.h:1007
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define REPORT_STATUS_CODE_EX(Type, Value, Instance, CallerId, ExtendedDataGuid, ExtendedData, ExtendedDataSize)
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
UINT32 EFI_BOOT_MODE
Definition: PiBootMode.h:18
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiGetSystemConfigurationTable(IN EFI_GUID *TableGuid, OUT VOID **Table)
Definition: UefiLib.c:82
@ EfiResetWarm
#define EFI_VARIABLE_NON_VOLATILE
@ ByProtocol
Definition: UefiSpec.h:1518
UINT32 NumberOfPages
The pages of this type memory.
UINT32 Type
EFI memory type defined in UEFI specification.
Definition: Base.h:213