The function was allocating a buffer for the read value from the UEFI Variable. But it was returning the pointer of the default value when the variable was not present. It could cause error when the default value and the returned value were free when these addresses were the same (double FreePool on the same address). Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin <olivier.martin@arm.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15427 6f19259b-4bc3-4df7-8a09-765794883524
361 lines
12 KiB
C
361 lines
12 KiB
C
/** @file
|
|
*
|
|
* Copyright (c) 2011-2013, ARM Limited. All rights reserved.
|
|
*
|
|
* This program and the accompanying materials
|
|
* are licensed and made available under the terms and conditions of the BSD License
|
|
* which accompanies this distribution. The full text of the license may be found at
|
|
* http://opensource.org/licenses/bsd-license.php
|
|
*
|
|
* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
*
|
|
**/
|
|
|
|
#include "BdsInternal.h"
|
|
|
|
#include <Library/DxeServicesTableLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Library/TimerLib.h>
|
|
#include <Library/PrintLib.h>
|
|
#include <Library/SerialPortLib.h>
|
|
|
|
STATIC CHAR8 *mTokenList[] = {
|
|
/*"SEC",*/
|
|
"PEI",
|
|
"DXE",
|
|
"BDS",
|
|
NULL
|
|
};
|
|
|
|
EFI_STATUS
|
|
ShutdownUefiBootServices (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN MemoryMapSize;
|
|
EFI_MEMORY_DESCRIPTOR *MemoryMap;
|
|
UINTN MapKey;
|
|
UINTN DescriptorSize;
|
|
UINT32 DescriptorVersion;
|
|
UINTN Pages;
|
|
|
|
MemoryMap = NULL;
|
|
MemoryMapSize = 0;
|
|
Pages = 0;
|
|
|
|
do {
|
|
Status = gBS->GetMemoryMap (
|
|
&MemoryMapSize,
|
|
MemoryMap,
|
|
&MapKey,
|
|
&DescriptorSize,
|
|
&DescriptorVersion
|
|
);
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
|
|
Pages = EFI_SIZE_TO_PAGES (MemoryMapSize) + 1;
|
|
MemoryMap = AllocatePages (Pages);
|
|
|
|
//
|
|
// Get System MemoryMap
|
|
//
|
|
Status = gBS->GetMemoryMap (
|
|
&MemoryMapSize,
|
|
MemoryMap,
|
|
&MapKey,
|
|
&DescriptorSize,
|
|
&DescriptorVersion
|
|
);
|
|
}
|
|
|
|
// Don't do anything between the GetMemoryMap() and ExitBootServices()
|
|
if (!EFI_ERROR(Status)) {
|
|
Status = gBS->ExitBootServices (gImageHandle, MapKey);
|
|
if (EFI_ERROR(Status)) {
|
|
FreePages (MemoryMap, Pages);
|
|
MemoryMap = NULL;
|
|
MemoryMapSize = 0;
|
|
}
|
|
}
|
|
} while (EFI_ERROR(Status));
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Connect all DXE drivers
|
|
|
|
@retval EFI_SUCCESS All drivers have been connected
|
|
@retval EFI_NOT_FOUND No handles match the search.
|
|
@retval EFI_OUT_OF_RESOURCES There is not resource pool memory to store the matching results.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
BdsConnectAllDrivers (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN HandleCount, Index;
|
|
EFI_HANDLE *HandleBuffer;
|
|
EFI_STATUS Status;
|
|
|
|
do {
|
|
// Locate all the driver handles
|
|
Status = gBS->LocateHandleBuffer (
|
|
AllHandles,
|
|
NULL,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
// Connect every handles
|
|
for (Index = 0; Index < HandleCount; Index++) {
|
|
gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
|
|
}
|
|
|
|
if (HandleBuffer != NULL) {
|
|
FreePool (HandleBuffer);
|
|
}
|
|
|
|
// Check if new handles have been created after the start of the previous handles
|
|
Status = gDS->Dispatch ();
|
|
} while (!EFI_ERROR(Status));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
InsertSystemMemoryResources (
|
|
LIST_ENTRY *ResourceList,
|
|
EFI_HOB_RESOURCE_DESCRIPTOR *ResHob
|
|
)
|
|
{
|
|
BDS_SYSTEM_MEMORY_RESOURCE *NewResource;
|
|
LIST_ENTRY *Link;
|
|
LIST_ENTRY *NextLink;
|
|
LIST_ENTRY AttachedResources;
|
|
BDS_SYSTEM_MEMORY_RESOURCE *Resource;
|
|
EFI_PHYSICAL_ADDRESS NewResourceEnd;
|
|
|
|
if (IsListEmpty (ResourceList)) {
|
|
NewResource = AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE));
|
|
NewResource->PhysicalStart = ResHob->PhysicalStart;
|
|
NewResource->ResourceLength = ResHob->ResourceLength;
|
|
InsertTailList (ResourceList, &NewResource->Link);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
InitializeListHead (&AttachedResources);
|
|
|
|
Link = ResourceList->ForwardLink;
|
|
ASSERT (Link != NULL);
|
|
while (Link != ResourceList) {
|
|
Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;
|
|
|
|
// Sanity Check. The resources should not overlapped.
|
|
ASSERT(!((ResHob->PhysicalStart >= Resource->PhysicalStart) && (ResHob->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))));
|
|
ASSERT(!((ResHob->PhysicalStart + ResHob->ResourceLength - 1 >= Resource->PhysicalStart) &&
|
|
((ResHob->PhysicalStart + ResHob->ResourceLength - 1) < (Resource->PhysicalStart + Resource->ResourceLength))));
|
|
|
|
// The new resource is attached after this resource descriptor
|
|
if (ResHob->PhysicalStart == Resource->PhysicalStart + Resource->ResourceLength) {
|
|
Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength;
|
|
|
|
NextLink = RemoveEntryList (&Resource->Link);
|
|
InsertTailList (&AttachedResources, &Resource->Link);
|
|
Link = NextLink;
|
|
}
|
|
// The new resource is attached before this resource descriptor
|
|
else if (ResHob->PhysicalStart + ResHob->ResourceLength == Resource->PhysicalStart) {
|
|
Resource->PhysicalStart = ResHob->PhysicalStart;
|
|
Resource->ResourceLength = Resource->ResourceLength + ResHob->ResourceLength;
|
|
|
|
NextLink = RemoveEntryList (&Resource->Link);
|
|
InsertTailList (&AttachedResources, &Resource->Link);
|
|
Link = NextLink;
|
|
} else {
|
|
Link = Link->ForwardLink;
|
|
}
|
|
}
|
|
|
|
if (!IsListEmpty (&AttachedResources)) {
|
|
// See if we can merge the attached resource with other resources
|
|
|
|
NewResource = (BDS_SYSTEM_MEMORY_RESOURCE*)GetFirstNode (&AttachedResources);
|
|
Link = RemoveEntryList (&NewResource->Link);
|
|
while (!IsListEmpty (&AttachedResources)) {
|
|
// Merge resources
|
|
Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)Link;
|
|
|
|
// Ensure they overlap each other
|
|
ASSERT(
|
|
((NewResource->PhysicalStart >= Resource->PhysicalStart) && (NewResource->PhysicalStart < (Resource->PhysicalStart + Resource->ResourceLength))) ||
|
|
(((NewResource->PhysicalStart + NewResource->ResourceLength) >= Resource->PhysicalStart) && ((NewResource->PhysicalStart + NewResource->ResourceLength) < (Resource->PhysicalStart + Resource->ResourceLength)))
|
|
);
|
|
|
|
NewResourceEnd = MAX (NewResource->PhysicalStart + NewResource->ResourceLength, Resource->PhysicalStart + Resource->ResourceLength);
|
|
NewResource->PhysicalStart = MIN (NewResource->PhysicalStart, Resource->PhysicalStart);
|
|
NewResource->ResourceLength = NewResourceEnd - NewResource->PhysicalStart;
|
|
|
|
Link = RemoveEntryList (Link);
|
|
}
|
|
} else {
|
|
// None of the Resource of the list is attached to this ResHob. Create a new entry for it
|
|
NewResource = AllocateZeroPool (sizeof(BDS_SYSTEM_MEMORY_RESOURCE));
|
|
NewResource->PhysicalStart = ResHob->PhysicalStart;
|
|
NewResource->ResourceLength = ResHob->ResourceLength;
|
|
}
|
|
InsertTailList (ResourceList, &NewResource->Link);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetSystemMemoryResources (
|
|
IN LIST_ENTRY *ResourceList
|
|
)
|
|
{
|
|
EFI_HOB_RESOURCE_DESCRIPTOR *ResHob;
|
|
|
|
InitializeListHead (ResourceList);
|
|
|
|
// Find the first System Memory Resource Descriptor
|
|
ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
|
|
while ((ResHob != NULL) && (ResHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY)) {
|
|
ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
|
|
}
|
|
|
|
// Did not find any
|
|
if (ResHob == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
} else {
|
|
InsertSystemMemoryResources (ResourceList, ResHob);
|
|
}
|
|
|
|
ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
|
|
while (ResHob != NULL) {
|
|
if (ResHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
|
|
InsertSystemMemoryResources (ResourceList, ResHob);
|
|
}
|
|
ResHob = (EFI_HOB_RESOURCE_DESCRIPTOR *)GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,(VOID *)((UINTN)ResHob + ResHob->Header.HobLength));
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
PrintPerformance (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN Key;
|
|
CONST VOID *Handle;
|
|
CONST CHAR8 *Token, *Module;
|
|
UINT64 Start, Stop, TimeStamp;
|
|
UINT64 Delta, TicksPerSecond, Milliseconds;
|
|
UINTN Index;
|
|
CHAR8 Buffer[100];
|
|
UINTN CharCount;
|
|
BOOLEAN CountUp;
|
|
|
|
TicksPerSecond = GetPerformanceCounterProperties (&Start, &Stop);
|
|
if (Start < Stop) {
|
|
CountUp = TRUE;
|
|
} else {
|
|
CountUp = FALSE;
|
|
}
|
|
|
|
TimeStamp = 0;
|
|
Key = 0;
|
|
do {
|
|
Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);
|
|
if (Key != 0) {
|
|
for (Index = 0; mTokenList[Index] != NULL; Index++) {
|
|
if (AsciiStriCmp (mTokenList[Index], Token) == 0) {
|
|
Delta = CountUp?(Stop - Start):(Start - Stop);
|
|
TimeStamp += Delta;
|
|
Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL);
|
|
CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"%6a %6ld ms\n", Token, Milliseconds);
|
|
SerialPortWrite ((UINT8 *) Buffer, CharCount);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} while (Key != 0);
|
|
|
|
CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));
|
|
SerialPortWrite ((UINT8 *) Buffer, CharCount);
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetGlobalEnvironmentVariable (
|
|
IN CONST CHAR16* VariableName,
|
|
IN VOID* DefaultValue,
|
|
IN OUT UINTN* Size,
|
|
OUT VOID** Value
|
|
)
|
|
{
|
|
return GetEnvironmentVariable (VariableName, &gEfiGlobalVariableGuid,
|
|
DefaultValue, Size, Value);
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetEnvironmentVariable (
|
|
IN CONST CHAR16* VariableName,
|
|
IN EFI_GUID* VendorGuid,
|
|
IN VOID* DefaultValue,
|
|
IN OUT UINTN* Size,
|
|
OUT VOID** Value
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN VariableSize;
|
|
|
|
// Try to get the variable size.
|
|
*Value = NULL;
|
|
VariableSize = 0;
|
|
Status = gRT->GetVariable ((CHAR16 *) VariableName, VendorGuid, NULL, &VariableSize, *Value);
|
|
if (Status == EFI_NOT_FOUND) {
|
|
if ((DefaultValue != NULL) && (Size != NULL) && (*Size != 0)) {
|
|
// If the environment variable does not exist yet then set it with the default value
|
|
Status = gRT->SetVariable (
|
|
(CHAR16*)VariableName,
|
|
VendorGuid,
|
|
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
|
*Size,
|
|
DefaultValue
|
|
);
|
|
*Value = AllocateCopyPool (*Size, DefaultValue);
|
|
} else {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
} else if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
// Get the environment variable value
|
|
*Value = AllocatePool (VariableSize);
|
|
if (*Value == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Status = gRT->GetVariable ((CHAR16 *)VariableName, VendorGuid, NULL, &VariableSize, *Value);
|
|
if (EFI_ERROR (Status)) {
|
|
FreePool(*Value);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Size) {
|
|
*Size = VariableSize;
|
|
}
|
|
} else {
|
|
*Value = AllocateCopyPool (*Size, DefaultValue);
|
|
return Status;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|