ARM Packages: Fixed line endings

This large code change only modifies the line endings to be CRLF to be
compliant with the EDK2 coding convention document.



git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14088 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
oliviermartin
2013-01-25 11:28:06 +00:00
parent 5767f22fca
commit 1e57a46299
280 changed files with 48862 additions and 48862 deletions

View File

@@ -1,144 +1,144 @@
/** @file
*
* Copyright (c) 2011-2012, 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/DxeServicesLib.h>
STATIC
EFI_STATUS
BdsLoadFileFromFirmwareVolume (
IN EFI_HANDLE FvHandle,
IN CHAR16 *FilePath,
IN EFI_FV_FILETYPE FileTypeFilter,
OUT EFI_DEVICE_PATH **EfiAppDevicePath
)
{
EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
VOID *Key;
EFI_STATUS Status, FileStatus;
EFI_GUID NameGuid;
EFI_FV_FILETYPE FileType;
EFI_FV_FILE_ATTRIBUTES Attributes;
UINTN Size;
UINTN UiStringLen;
CHAR16 *UiSection;
UINT32 Authentication;
EFI_DEVICE_PATH *FvDevicePath;
MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileDevicePath;
Status = gBS->HandleProtocol (FvHandle,&gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FvProtocol);
if (EFI_ERROR(Status)) {
return Status;
}
// Length of FilePath
UiStringLen = StrLen (FilePath);
// Allocate Key
Key = AllocatePool (FvProtocol->KeySize);
ASSERT (Key != NULL);
ZeroMem (Key, FvProtocol->KeySize);
do {
// Search in all files
FileType = FileTypeFilter;
Status = FvProtocol->GetNextFile (FvProtocol, Key, &FileType, &NameGuid, &Attributes, &Size);
if (!EFI_ERROR (Status)) {
UiSection = NULL;
FileStatus = FvProtocol->ReadSection (
FvProtocol,
&NameGuid,
EFI_SECTION_USER_INTERFACE,
0,
(VOID **)&UiSection,
&Size,
&Authentication
);
if (!EFI_ERROR (FileStatus)) {
if (StrnCmp (FilePath, UiSection, UiStringLen) == 0) {
//
// We found a UiString match.
//
Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
// Generate the Device Path for the file
//DevicePath = DuplicateDevicePath(FvDevicePath);
EfiInitializeFwVolDevicepathNode (&FileDevicePath, &NameGuid);
*EfiAppDevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FileDevicePath);
FreePool (Key);
FreePool (UiSection);
return FileStatus;
}
FreePool (UiSection);
}
}
} while (!EFI_ERROR (Status));
FreePool(Key);
return Status;
}
/**
Start an EFI Application from any Firmware Volume
@param EfiApp EFI Application Name
@retval EFI_SUCCESS All drivers have been connected
@retval EFI_NOT_FOUND The Linux kernel Device Path has not been found
@retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.
**/
EFI_STATUS
BdsLoadApplication (
IN EFI_HANDLE ParentImageHandle,
IN CHAR16* EfiApp,
IN UINTN LoadOptionsSize,
IN VOID* LoadOptions
)
{
EFI_STATUS Status;
UINTN NoHandles, HandleIndex;
EFI_HANDLE *Handles;
EFI_DEVICE_PATH *EfiAppDevicePath;
// Need to connect every drivers to ensure no dependencies are missing for the application
Status = BdsConnectAllDrivers();
if (EFI_ERROR(Status)) {
DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n"));
return Status;
}
// Search the application in any Firmware Volume
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NoHandles, &Handles);
if (EFI_ERROR (Status) || (NoHandles == 0)) {
DEBUG ((EFI_D_ERROR, "FAIL to find Firmware Volume\n"));
return Status;
}
// Search in all Firmware Volume for the EFI Application
for (HandleIndex = 0; HandleIndex < NoHandles; HandleIndex++) {
EfiAppDevicePath = NULL;
Status = BdsLoadFileFromFirmwareVolume (Handles[HandleIndex], EfiApp, EFI_FV_FILETYPE_APPLICATION, &EfiAppDevicePath);
if (!EFI_ERROR (Status)) {
// Start the application
Status = BdsStartEfiApplication (ParentImageHandle, EfiAppDevicePath, LoadOptionsSize, LoadOptions);
return Status;
}
}
return Status;
}
/** @file
*
* Copyright (c) 2011-2012, 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/DxeServicesLib.h>
STATIC
EFI_STATUS
BdsLoadFileFromFirmwareVolume (
IN EFI_HANDLE FvHandle,
IN CHAR16 *FilePath,
IN EFI_FV_FILETYPE FileTypeFilter,
OUT EFI_DEVICE_PATH **EfiAppDevicePath
)
{
EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
VOID *Key;
EFI_STATUS Status, FileStatus;
EFI_GUID NameGuid;
EFI_FV_FILETYPE FileType;
EFI_FV_FILE_ATTRIBUTES Attributes;
UINTN Size;
UINTN UiStringLen;
CHAR16 *UiSection;
UINT32 Authentication;
EFI_DEVICE_PATH *FvDevicePath;
MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileDevicePath;
Status = gBS->HandleProtocol (FvHandle,&gEfiFirmwareVolume2ProtocolGuid, (VOID **)&FvProtocol);
if (EFI_ERROR(Status)) {
return Status;
}
// Length of FilePath
UiStringLen = StrLen (FilePath);
// Allocate Key
Key = AllocatePool (FvProtocol->KeySize);
ASSERT (Key != NULL);
ZeroMem (Key, FvProtocol->KeySize);
do {
// Search in all files
FileType = FileTypeFilter;
Status = FvProtocol->GetNextFile (FvProtocol, Key, &FileType, &NameGuid, &Attributes, &Size);
if (!EFI_ERROR (Status)) {
UiSection = NULL;
FileStatus = FvProtocol->ReadSection (
FvProtocol,
&NameGuid,
EFI_SECTION_USER_INTERFACE,
0,
(VOID **)&UiSection,
&Size,
&Authentication
);
if (!EFI_ERROR (FileStatus)) {
if (StrnCmp (FilePath, UiSection, UiStringLen) == 0) {
//
// We found a UiString match.
//
Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);
// Generate the Device Path for the file
//DevicePath = DuplicateDevicePath(FvDevicePath);
EfiInitializeFwVolDevicepathNode (&FileDevicePath, &NameGuid);
*EfiAppDevicePath = AppendDevicePathNode (FvDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&FileDevicePath);
FreePool (Key);
FreePool (UiSection);
return FileStatus;
}
FreePool (UiSection);
}
}
} while (!EFI_ERROR (Status));
FreePool(Key);
return Status;
}
/**
Start an EFI Application from any Firmware Volume
@param EfiApp EFI Application Name
@retval EFI_SUCCESS All drivers have been connected
@retval EFI_NOT_FOUND The Linux kernel Device Path has not been found
@retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.
**/
EFI_STATUS
BdsLoadApplication (
IN EFI_HANDLE ParentImageHandle,
IN CHAR16* EfiApp,
IN UINTN LoadOptionsSize,
IN VOID* LoadOptions
)
{
EFI_STATUS Status;
UINTN NoHandles, HandleIndex;
EFI_HANDLE *Handles;
EFI_DEVICE_PATH *EfiAppDevicePath;
// Need to connect every drivers to ensure no dependencies are missing for the application
Status = BdsConnectAllDrivers();
if (EFI_ERROR(Status)) {
DEBUG ((EFI_D_ERROR, "FAIL to connect all drivers\n"));
return Status;
}
// Search the application in any Firmware Volume
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &NoHandles, &Handles);
if (EFI_ERROR (Status) || (NoHandles == 0)) {
DEBUG ((EFI_D_ERROR, "FAIL to find Firmware Volume\n"));
return Status;
}
// Search in all Firmware Volume for the EFI Application
for (HandleIndex = 0; HandleIndex < NoHandles; HandleIndex++) {
EfiAppDevicePath = NULL;
Status = BdsLoadFileFromFirmwareVolume (Handles[HandleIndex], EfiApp, EFI_FV_FILETYPE_APPLICATION, &EfiAppDevicePath);
if (!EFI_ERROR (Status)) {
// Start the application
Status = BdsStartEfiApplication (ParentImageHandle, EfiAppDevicePath, LoadOptionsSize, LoadOptions);
return Status;
}
}
return Status;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,347 +1,347 @@
/** @file
*
* Copyright (c) 2011-2012, 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
GetEnvironmentVariable (
IN CONST CHAR16* VariableName,
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, &gEfiGlobalVariableGuid, 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,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
*Size,
DefaultValue
);
*Value = 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, &gEfiGlobalVariableGuid, NULL, &VariableSize, *Value);
if (EFI_ERROR (Status)) {
FreePool(*Value);
return EFI_INVALID_PARAMETER;
}
if (Size) {
*Size = VariableSize;
}
} else {
*Value = DefaultValue;
return Status;
}
return EFI_SUCCESS;
}
/** @file
*
* Copyright (c) 2011-2012, 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
GetEnvironmentVariable (
IN CONST CHAR16* VariableName,
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, &gEfiGlobalVariableGuid, 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,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
*Size,
DefaultValue
);
*Value = 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, &gEfiGlobalVariableGuid, NULL, &VariableSize, *Value);
if (EFI_ERROR (Status)) {
FreePool(*Value);
return EFI_INVALID_PARAMETER;
}
if (Size) {
*Size = VariableSize;
}
} else {
*Value = DefaultValue;
return Status;
}
return EFI_SUCCESS;
}

View File

@@ -1,98 +1,98 @@
/** @file
*
* Copyright (c) 2011-2012, 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.
*
**/
#ifndef __BDS_INTERNAL_H__
#define __BDS_INTERNAL_H__
#include <PiDxe.h>
#include <Library/ArmLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/HobLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/DevicePathLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/BdsLib.h>
#include <Library/PcdLib.h>
#include <Library/PerformanceLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Guid/ArmMpCoreInfo.h>
#include <Guid/GlobalVariable.h>
#include <Guid/FileInfo.h>
#include <Protocol/DevicePath.h>
#include <Protocol/DevicePathFromText.h>
#include <Protocol/SimpleFileSystem.h>
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/LoadFile.h>
#include <Protocol/PxeBaseCode.h>
#include <Uefi.h>
typedef BOOLEAN (*BDS_FILE_LOADER_SUPPORT) (
IN EFI_DEVICE_PATH *DevicePath,
IN EFI_HANDLE Handle,
IN EFI_DEVICE_PATH *RemainingDevicePath
);
typedef EFI_STATUS (*BDS_FILE_LOADER_LOAD_IMAGE) (
IN EFI_DEVICE_PATH *DevicePath,
IN EFI_HANDLE Handle,
IN EFI_DEVICE_PATH *RemainingDevicePath,
IN EFI_ALLOCATE_TYPE Type,
IN OUT EFI_PHYSICAL_ADDRESS* Image,
OUT UINTN *ImageSize
);
typedef struct {
BDS_FILE_LOADER_SUPPORT Support;
BDS_FILE_LOADER_LOAD_IMAGE LoadImage;
} BDS_FILE_LOADER;
typedef struct _BDS_SYSTEM_MEMORY_RESOURCE {
LIST_ENTRY Link; // This attribute must be the first entry of this structure (to avoid pointer computation)
EFI_PHYSICAL_ADDRESS PhysicalStart;
UINT64 ResourceLength;
} BDS_SYSTEM_MEMORY_RESOURCE;
// BdsHelper.c
EFI_STATUS
ShutdownUefiBootServices (
VOID
);
EFI_STATUS
GetSystemMemoryResources (
LIST_ENTRY *ResourceList
);
VOID
PrintPerformance (
VOID
);
EFI_STATUS
BdsLoadImage (
IN EFI_DEVICE_PATH *DevicePath,
IN EFI_ALLOCATE_TYPE Type,
IN OUT EFI_PHYSICAL_ADDRESS* Image,
OUT UINTN *FileSize
);
#endif
/** @file
*
* Copyright (c) 2011-2012, 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.
*
**/
#ifndef __BDS_INTERNAL_H__
#define __BDS_INTERNAL_H__
#include <PiDxe.h>
#include <Library/ArmLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/HobLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/DevicePathLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/BdsLib.h>
#include <Library/PcdLib.h>
#include <Library/PerformanceLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Guid/ArmMpCoreInfo.h>
#include <Guid/GlobalVariable.h>
#include <Guid/FileInfo.h>
#include <Protocol/DevicePath.h>
#include <Protocol/DevicePathFromText.h>
#include <Protocol/SimpleFileSystem.h>
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/LoadFile.h>
#include <Protocol/PxeBaseCode.h>
#include <Uefi.h>
typedef BOOLEAN (*BDS_FILE_LOADER_SUPPORT) (
IN EFI_DEVICE_PATH *DevicePath,
IN EFI_HANDLE Handle,
IN EFI_DEVICE_PATH *RemainingDevicePath
);
typedef EFI_STATUS (*BDS_FILE_LOADER_LOAD_IMAGE) (
IN EFI_DEVICE_PATH *DevicePath,
IN EFI_HANDLE Handle,
IN EFI_DEVICE_PATH *RemainingDevicePath,
IN EFI_ALLOCATE_TYPE Type,
IN OUT EFI_PHYSICAL_ADDRESS* Image,
OUT UINTN *ImageSize
);
typedef struct {
BDS_FILE_LOADER_SUPPORT Support;
BDS_FILE_LOADER_LOAD_IMAGE LoadImage;
} BDS_FILE_LOADER;
typedef struct _BDS_SYSTEM_MEMORY_RESOURCE {
LIST_ENTRY Link; // This attribute must be the first entry of this structure (to avoid pointer computation)
EFI_PHYSICAL_ADDRESS PhysicalStart;
UINT64 ResourceLength;
} BDS_SYSTEM_MEMORY_RESOURCE;
// BdsHelper.c
EFI_STATUS
ShutdownUefiBootServices (
VOID
);
EFI_STATUS
GetSystemMemoryResources (
LIST_ENTRY *ResourceList
);
VOID
PrintPerformance (
VOID
);
EFI_STATUS
BdsLoadImage (
IN EFI_DEVICE_PATH *DevicePath,
IN EFI_ALLOCATE_TYPE Type,
IN OUT EFI_PHYSICAL_ADDRESS* Image,
OUT UINTN *FileSize
);
#endif

View File

@@ -1,77 +1,77 @@
#/* @file
#
# Copyright (c) 2011-2012, 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.
#
#*/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = BdsLib
FILE_GUID = ddbf73a0-bb25-11df-8e4e-0002a5d5c51b
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = BdsLib
[Sources.common]
BdsFilePath.c
BdsAppLoader.c
BdsHelper.c
BdsLoadOption.c
BdsLinuxLoader.c
BdsLinuxAtag.c
BdsLinuxFdt.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
ArmPkg/ArmPkg.dec
[LibraryClasses]
ArmLib
BaseLib
DebugLib
DevicePathLib
HobLib
PerformanceLib
SerialPortLib
FdtLib
[Guids]
gEfiFileInfoGuid
gArmMpCoreInfoGuid
[Protocols]
gEfiBdsArchProtocolGuid
gEfiDevicePathProtocolGuid
gEfiDevicePathFromTextProtocolGuid
gEfiSimpleFileSystemProtocolGuid
gEfiFirmwareVolume2ProtocolGuid
gEfiLoadFileProtocolGuid
gEfiPxeBaseCodeProtocolGuid
gEfiDiskIoProtocolGuid
gEfiUsbIoProtocolGuid
gEfiLoadedImageProtocolGuid
[FeaturePcd]
[FixedPcd]
gArmTokenSpaceGuid.PcdSystemMemoryBase
gArmTokenSpaceGuid.PcdSystemMemorySize
gArmTokenSpaceGuid.PcdArmMachineType
gArmTokenSpaceGuid.PcdArmLinuxFdtMaxOffset
gArmTokenSpaceGuid.PcdArmLinuxKernelFixedOffset
gArmTokenSpaceGuid.PcdArmLinuxKernelMaxOffset
gArmTokenSpaceGuid.PcdArmLinuxAtagMaxOffset
[Depex]
TRUE
#/* @file
#
# Copyright (c) 2011-2012, 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.
#
#*/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = BdsLib
FILE_GUID = ddbf73a0-bb25-11df-8e4e-0002a5d5c51b
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = BdsLib
[Sources.common]
BdsFilePath.c
BdsAppLoader.c
BdsHelper.c
BdsLoadOption.c
BdsLinuxLoader.c
BdsLinuxAtag.c
BdsLinuxFdt.c
[Packages]
MdePkg/MdePkg.dec
EmbeddedPkg/EmbeddedPkg.dec
ArmPkg/ArmPkg.dec
[LibraryClasses]
ArmLib
BaseLib
DebugLib
DevicePathLib
HobLib
PerformanceLib
SerialPortLib
FdtLib
[Guids]
gEfiFileInfoGuid
gArmMpCoreInfoGuid
[Protocols]
gEfiBdsArchProtocolGuid
gEfiDevicePathProtocolGuid
gEfiDevicePathFromTextProtocolGuid
gEfiSimpleFileSystemProtocolGuid
gEfiFirmwareVolume2ProtocolGuid
gEfiLoadFileProtocolGuid
gEfiPxeBaseCodeProtocolGuid
gEfiDiskIoProtocolGuid
gEfiUsbIoProtocolGuid
gEfiLoadedImageProtocolGuid
[FeaturePcd]
[FixedPcd]
gArmTokenSpaceGuid.PcdSystemMemoryBase
gArmTokenSpaceGuid.PcdSystemMemorySize
gArmTokenSpaceGuid.PcdArmMachineType
gArmTokenSpaceGuid.PcdArmLinuxFdtMaxOffset
gArmTokenSpaceGuid.PcdArmLinuxKernelFixedOffset
gArmTokenSpaceGuid.PcdArmLinuxKernelMaxOffset
gArmTokenSpaceGuid.PcdArmLinuxAtagMaxOffset
[Depex]
TRUE

View File

@@ -1,173 +1,173 @@
/** @file
*
* Copyright (c) 2011-2012, 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 "BdsLinuxLoader.h"
// Point to the current ATAG
STATIC LINUX_ATAG *mLinuxKernelCurrentAtag;
STATIC
VOID
SetupCoreTag (
IN UINT32 PageSize
)
{
mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_CORE);
mLinuxKernelCurrentAtag->header.type = ATAG_CORE;
mLinuxKernelCurrentAtag->body.core_tag.flags = 1; /* ensure read-only */
mLinuxKernelCurrentAtag->body.core_tag.pagesize = PageSize; /* systems PageSize (4k) */
mLinuxKernelCurrentAtag->body.core_tag.rootdev = 0; /* zero root device (typically overridden from kernel command line )*/
// move pointer to next tag
mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);
}
STATIC
VOID
SetupMemTag (
IN UINTN StartAddress,
IN UINT32 Size
)
{
mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_MEM);
mLinuxKernelCurrentAtag->header.type = ATAG_MEM;
mLinuxKernelCurrentAtag->body.mem_tag.start = StartAddress; /* Start of memory chunk for AtagMem */
mLinuxKernelCurrentAtag->body.mem_tag.size = Size; /* Size of memory chunk for AtagMem */
// move pointer to next tag
mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);
}
STATIC
VOID
SetupCmdlineTag (
IN CONST CHAR8 *CmdLine
)
{
UINT32 LineLength;
// Increment the line length by 1 to account for the null string terminator character
LineLength = AsciiStrLen(CmdLine) + 1;
/* Check for NULL strings.
* Do not insert a tag for an empty CommandLine, don't even modify the tag address pointer.
* Remember, you have at least one null string terminator character.
*/
if(LineLength > 1) {
mLinuxKernelCurrentAtag->header.size = ((UINT32)sizeof(LINUX_ATAG_HEADER) + LineLength + (UINT32)3) >> 2;
mLinuxKernelCurrentAtag->header.type = ATAG_CMDLINE;
/* place CommandLine into tag */
AsciiStrCpy(mLinuxKernelCurrentAtag->body.cmdline_tag.cmdline, CmdLine);
// move pointer to next tag
mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);
}
}
STATIC
VOID
SetupInitrdTag (
IN UINT32 InitrdImage,
IN UINT32 InitrdImageSize
)
{
mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_INITRD2);
mLinuxKernelCurrentAtag->header.type = ATAG_INITRD2;
mLinuxKernelCurrentAtag->body.initrd2_tag.start = InitrdImage;
mLinuxKernelCurrentAtag->body.initrd2_tag.size = InitrdImageSize;
// Move pointer to next tag
mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);
}
STATIC
VOID
SetupEndTag (
VOID
)
{
// Empty tag ends list; this has zero length and no body
mLinuxKernelCurrentAtag->header.type = ATAG_NONE;
mLinuxKernelCurrentAtag->header.size = 0;
/* We can not calculate the next address by using the standard macro:
* Params = next_tag_address(Params);
* because it relies on the header.size, which here it is 0 (zero).
* The easiest way is to add the sizeof(mLinuxKernelCurrentAtag->header).
*/
mLinuxKernelCurrentAtag = (LINUX_ATAG*)((UINT32)mLinuxKernelCurrentAtag + sizeof(mLinuxKernelCurrentAtag->header));
}
EFI_STATUS
PrepareAtagList (
IN CONST CHAR8* CommandLineString,
IN EFI_PHYSICAL_ADDRESS InitrdImage,
IN UINTN InitrdImageSize,
OUT EFI_PHYSICAL_ADDRESS *AtagBase,
OUT UINT32 *AtagSize
)
{
EFI_STATUS Status;
LIST_ENTRY *ResourceLink;
LIST_ENTRY ResourceList;
EFI_PHYSICAL_ADDRESS AtagStartAddress;
BDS_SYSTEM_MEMORY_RESOURCE *Resource;
AtagStartAddress = LINUX_ATAG_MAX_OFFSET;
Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress);
if (EFI_ERROR(Status)) {
DEBUG ((EFI_D_WARN, "Warning: Failed to allocate Atag at 0x%lX (%r). The Atag will be allocated somewhere else in System Memory.\n", AtagStartAddress, Status));
Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress);
ASSERT_EFI_ERROR(Status);
}
// Ready to setup the atag list
mLinuxKernelCurrentAtag = (LINUX_ATAG*)(UINTN)AtagStartAddress;
// Standard core tag 4k PageSize
SetupCoreTag( (UINT32)SIZE_4KB );
// Physical memory setup
GetSystemMemoryResources (&ResourceList);
ResourceLink = ResourceList.ForwardLink;
while (ResourceLink != NULL && ResourceLink != &ResourceList) {
Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)ResourceLink;
DEBUG((EFI_D_INFO,"- [0x%08X,0x%08X]\n",(UINT32)Resource->PhysicalStart,(UINT32)Resource->PhysicalStart+(UINT32)Resource->ResourceLength));
SetupMemTag( (UINT32)Resource->PhysicalStart, (UINT32)Resource->ResourceLength );
ResourceLink = ResourceLink->ForwardLink;
}
// CommandLine setting root device
if (CommandLineString) {
SetupCmdlineTag (CommandLineString);
}
if (InitrdImageSize > 0 && InitrdImage != 0) {
SetupInitrdTag ((UINT32)InitrdImage, (UINT32)InitrdImageSize);
}
// End of tags
SetupEndTag();
// Calculate atag list size
*AtagBase = AtagStartAddress;
*AtagSize = (UINT32)mLinuxKernelCurrentAtag - (UINT32)AtagStartAddress + 1;
return EFI_SUCCESS;
}
/** @file
*
* Copyright (c) 2011-2012, 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 "BdsLinuxLoader.h"
// Point to the current ATAG
STATIC LINUX_ATAG *mLinuxKernelCurrentAtag;
STATIC
VOID
SetupCoreTag (
IN UINT32 PageSize
)
{
mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_CORE);
mLinuxKernelCurrentAtag->header.type = ATAG_CORE;
mLinuxKernelCurrentAtag->body.core_tag.flags = 1; /* ensure read-only */
mLinuxKernelCurrentAtag->body.core_tag.pagesize = PageSize; /* systems PageSize (4k) */
mLinuxKernelCurrentAtag->body.core_tag.rootdev = 0; /* zero root device (typically overridden from kernel command line )*/
// move pointer to next tag
mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);
}
STATIC
VOID
SetupMemTag (
IN UINTN StartAddress,
IN UINT32 Size
)
{
mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_MEM);
mLinuxKernelCurrentAtag->header.type = ATAG_MEM;
mLinuxKernelCurrentAtag->body.mem_tag.start = StartAddress; /* Start of memory chunk for AtagMem */
mLinuxKernelCurrentAtag->body.mem_tag.size = Size; /* Size of memory chunk for AtagMem */
// move pointer to next tag
mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);
}
STATIC
VOID
SetupCmdlineTag (
IN CONST CHAR8 *CmdLine
)
{
UINT32 LineLength;
// Increment the line length by 1 to account for the null string terminator character
LineLength = AsciiStrLen(CmdLine) + 1;
/* Check for NULL strings.
* Do not insert a tag for an empty CommandLine, don't even modify the tag address pointer.
* Remember, you have at least one null string terminator character.
*/
if(LineLength > 1) {
mLinuxKernelCurrentAtag->header.size = ((UINT32)sizeof(LINUX_ATAG_HEADER) + LineLength + (UINT32)3) >> 2;
mLinuxKernelCurrentAtag->header.type = ATAG_CMDLINE;
/* place CommandLine into tag */
AsciiStrCpy(mLinuxKernelCurrentAtag->body.cmdline_tag.cmdline, CmdLine);
// move pointer to next tag
mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);
}
}
STATIC
VOID
SetupInitrdTag (
IN UINT32 InitrdImage,
IN UINT32 InitrdImageSize
)
{
mLinuxKernelCurrentAtag->header.size = tag_size(LINUX_ATAG_INITRD2);
mLinuxKernelCurrentAtag->header.type = ATAG_INITRD2;
mLinuxKernelCurrentAtag->body.initrd2_tag.start = InitrdImage;
mLinuxKernelCurrentAtag->body.initrd2_tag.size = InitrdImageSize;
// Move pointer to next tag
mLinuxKernelCurrentAtag = next_tag_address(mLinuxKernelCurrentAtag);
}
STATIC
VOID
SetupEndTag (
VOID
)
{
// Empty tag ends list; this has zero length and no body
mLinuxKernelCurrentAtag->header.type = ATAG_NONE;
mLinuxKernelCurrentAtag->header.size = 0;
/* We can not calculate the next address by using the standard macro:
* Params = next_tag_address(Params);
* because it relies on the header.size, which here it is 0 (zero).
* The easiest way is to add the sizeof(mLinuxKernelCurrentAtag->header).
*/
mLinuxKernelCurrentAtag = (LINUX_ATAG*)((UINT32)mLinuxKernelCurrentAtag + sizeof(mLinuxKernelCurrentAtag->header));
}
EFI_STATUS
PrepareAtagList (
IN CONST CHAR8* CommandLineString,
IN EFI_PHYSICAL_ADDRESS InitrdImage,
IN UINTN InitrdImageSize,
OUT EFI_PHYSICAL_ADDRESS *AtagBase,
OUT UINT32 *AtagSize
)
{
EFI_STATUS Status;
LIST_ENTRY *ResourceLink;
LIST_ENTRY ResourceList;
EFI_PHYSICAL_ADDRESS AtagStartAddress;
BDS_SYSTEM_MEMORY_RESOURCE *Resource;
AtagStartAddress = LINUX_ATAG_MAX_OFFSET;
Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress);
if (EFI_ERROR(Status)) {
DEBUG ((EFI_D_WARN, "Warning: Failed to allocate Atag at 0x%lX (%r). The Atag will be allocated somewhere else in System Memory.\n", AtagStartAddress, Status));
Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesData, EFI_SIZE_TO_PAGES(ATAG_MAX_SIZE), &AtagStartAddress);
ASSERT_EFI_ERROR(Status);
}
// Ready to setup the atag list
mLinuxKernelCurrentAtag = (LINUX_ATAG*)(UINTN)AtagStartAddress;
// Standard core tag 4k PageSize
SetupCoreTag( (UINT32)SIZE_4KB );
// Physical memory setup
GetSystemMemoryResources (&ResourceList);
ResourceLink = ResourceList.ForwardLink;
while (ResourceLink != NULL && ResourceLink != &ResourceList) {
Resource = (BDS_SYSTEM_MEMORY_RESOURCE*)ResourceLink;
DEBUG((EFI_D_INFO,"- [0x%08X,0x%08X]\n",(UINT32)Resource->PhysicalStart,(UINT32)Resource->PhysicalStart+(UINT32)Resource->ResourceLength));
SetupMemTag( (UINT32)Resource->PhysicalStart, (UINT32)Resource->ResourceLength );
ResourceLink = ResourceLink->ForwardLink;
}
// CommandLine setting root device
if (CommandLineString) {
SetupCmdlineTag (CommandLineString);
}
if (InitrdImageSize > 0 && InitrdImage != 0) {
SetupInitrdTag ((UINT32)InitrdImage, (UINT32)InitrdImageSize);
}
// End of tags
SetupEndTag();
// Calculate atag list size
*AtagBase = AtagStartAddress;
*AtagSize = (UINT32)mLinuxKernelCurrentAtag - (UINT32)AtagStartAddress + 1;
return EFI_SUCCESS;
}

View File

@@ -1,274 +1,274 @@
/** @file
*
* Copyright (c) 2011-2012, 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 "BdsLinuxLoader.h"
#define ALIGN32_BELOW(addr) ALIGN_POINTER(addr - 32,32)
STATIC
EFI_STATUS
PreparePlatformHardware (
VOID
)
{
//Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called.
// Clean, invalidate, disable data cache
ArmDisableDataCache();
ArmCleanInvalidateDataCache();
// Invalidate and disable the Instruction cache
ArmDisableInstructionCache ();
ArmInvalidateInstructionCache ();
// Turn off MMU
ArmDisableMmu();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
StartLinux (
IN EFI_PHYSICAL_ADDRESS LinuxImage,
IN UINTN LinuxImageSize,
IN EFI_PHYSICAL_ADDRESS KernelParamsAddress,
IN UINTN KernelParamsSize,
IN UINT32 MachineType
)
{
EFI_STATUS Status;
LINUX_KERNEL LinuxKernel;
// Shut down UEFI boot services. ExitBootServices() will notify every driver that created an event on
// ExitBootServices event. Example the Interrupt DXE driver will disable the interrupts on this event.
Status = ShutdownUefiBootServices ();
if(EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR,"ERROR: Can not shutdown UEFI boot services. Status=0x%X\n", Status));
goto Exit;
}
// Move the kernel parameters to any address inside the first 1MB.
// This is necessary because the ARM Linux kernel requires
// the FTD / ATAG List to reside entirely inside the first 1MB of
// physical memory.
//Note: There is no requirement on the alignment
if (MachineType != ARM_FDT_MACHINE_TYPE) {
if (((UINTN)KernelParamsAddress > LINUX_ATAG_MAX_OFFSET) && (KernelParamsSize < PcdGet32(PcdArmLinuxAtagMaxOffset))) {
KernelParamsAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CopyMem (ALIGN32_BELOW(LINUX_ATAG_MAX_OFFSET - KernelParamsSize), (VOID*)(UINTN)KernelParamsAddress, KernelParamsSize);
}
} else {
if (((UINTN)KernelParamsAddress > LINUX_FDT_MAX_OFFSET) && (KernelParamsSize < PcdGet32(PcdArmLinuxFdtMaxOffset))) {
KernelParamsAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CopyMem (ALIGN32_BELOW(LINUX_FDT_MAX_OFFSET - KernelParamsSize), (VOID*)(UINTN)KernelParamsAddress, KernelParamsSize);
}
}
if ((UINTN)LinuxImage > LINUX_KERNEL_MAX_OFFSET) {
//Note: There is no requirement on the alignment
LinuxKernel = (LINUX_KERNEL)CopyMem (ALIGN32_BELOW(LINUX_KERNEL_MAX_OFFSET - LinuxImageSize), (VOID*)(UINTN)LinuxImage, LinuxImageSize);
} else {
LinuxKernel = (LINUX_KERNEL)(UINTN)LinuxImage;
}
// Check if the Linux Image is a uImage
if (*(UINT32*)LinuxKernel == LINUX_UIMAGE_SIGNATURE) {
// Assume the Image Entry Point is just after the uImage header (64-byte size)
LinuxKernel = (LINUX_KERNEL)((UINTN)LinuxKernel + 64);
LinuxImageSize -= 64;
}
//TODO: Check there is no overlapping between kernel and Atag
//
// Switch off interrupts, caches, mmu, etc
//
Status = PreparePlatformHardware ();
ASSERT_EFI_ERROR(Status);
// Register and print out performance information
PERF_END (NULL, "BDS", NULL, 0);
if (PerformanceMeasurementEnabled ()) {
PrintPerformance ();
}
//
// Start the Linux Kernel
//
// Outside BootServices, so can't use Print();
DEBUG((EFI_D_ERROR, "\nStarting the kernel:\n\n"));
// Jump to kernel with register set
LinuxKernel ((UINTN)0, MachineType, (UINTN)KernelParamsAddress);
// Kernel should never exit
// After Life services are not provided
ASSERT(FALSE);
Exit:
// Only be here if we fail to start Linux
Print (L"ERROR : Can not start the kernel. Status=0x%X\n", Status);
// Free Runtimee Memory (kernel and FDT)
return Status;
}
/**
Start a Linux kernel from a Device Path
@param LinuxKernel Device Path to the Linux Kernel
@param Parameters Linux kernel arguments
@param Fdt Device Path to the Flat Device Tree
@retval EFI_SUCCESS All drivers have been connected
@retval EFI_NOT_FOUND The Linux kernel Device Path has not been found
@retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.
**/
EFI_STATUS
BdsBootLinuxAtag (
IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,
IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,
IN CONST CHAR8* CommandLineArguments
)
{
EFI_STATUS Status;
UINT32 LinuxImageSize;
UINT32 InitrdImageSize = 0;
UINT32 AtagSize;
EFI_PHYSICAL_ADDRESS AtagBase;
EFI_PHYSICAL_ADDRESS LinuxImage;
EFI_PHYSICAL_ADDRESS InitrdImage;
PERF_START (NULL, "BDS", NULL, 0);
// Load the Linux kernel from a device path
LinuxImage = LINUX_KERNEL_MAX_OFFSET;
Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);
if (EFI_ERROR(Status)) {
Print (L"ERROR: Did not find Linux kernel.\n");
return Status;
}
if (InitrdDevicePath) {
// Load the initrd near to the Linux kernel
InitrdImage = LINUX_KERNEL_MAX_OFFSET;
Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, &InitrdImageSize);
if (Status == EFI_OUT_OF_RESOURCES) {
Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize);
}
if (EFI_ERROR(Status)) {
Print (L"ERROR: Did not find initrd image.\n");
return Status;
}
// Check if the initrd is a uInitrd
if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {
// Skip the 64-byte image header
InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);
InitrdImageSize -= 64;
}
}
//
// Setup the Linux Kernel Parameters
//
// By setting address=0 we leave the memory allocation to the function
Status = PrepareAtagList (CommandLineArguments, InitrdImage, InitrdImageSize, &AtagBase, &AtagSize);
if (EFI_ERROR(Status)) {
Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", Status);
return Status;
}
return StartLinux (LinuxImage, LinuxImageSize, AtagBase, AtagSize, PcdGet32(PcdArmMachineType));
}
/**
Start a Linux kernel from a Device Path
@param LinuxKernel Device Path to the Linux Kernel
@param Parameters Linux kernel arguments
@param Fdt Device Path to the Flat Device Tree
@retval EFI_SUCCESS All drivers have been connected
@retval EFI_NOT_FOUND The Linux kernel Device Path has not been found
@retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.
**/
EFI_STATUS
BdsBootLinuxFdt (
IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,
IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,
IN CONST CHAR8* CommandLineArguments,
IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath
)
{
EFI_STATUS Status;
UINT32 LinuxImageSize;
UINT32 InitrdImageSize = 0;
UINT32 FdtBlobSize;
EFI_PHYSICAL_ADDRESS FdtBlobBase;
EFI_PHYSICAL_ADDRESS LinuxImage;
EFI_PHYSICAL_ADDRESS InitrdImage;
PERF_START (NULL, "BDS", NULL, 0);
// Load the Linux kernel from a device path
LinuxImage = LINUX_KERNEL_MAX_OFFSET;
Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);
if (EFI_ERROR(Status)) {
Print (L"ERROR: Did not find Linux kernel.\n");
return Status;
}
if (InitrdDevicePath) {
InitrdImage = LINUX_KERNEL_MAX_OFFSET;
Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, &InitrdImageSize);
if (Status == EFI_OUT_OF_RESOURCES) {
Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize);
}
if (EFI_ERROR(Status)) {
Print (L"ERROR: Did not find initrd image.\n");
return Status;
}
// Check if the initrd is a uInitrd
if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {
// Skip the 64-byte image header
InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);
InitrdImageSize -= 64;
}
}
// Load the FDT binary from a device path. The FDT will be reloaded later to a more appropriate location for the Linux kernel.
FdtBlobBase = 0;
Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);
if (EFI_ERROR(Status)) {
Print (L"ERROR: Did not find Device Tree blob.\n");
return Status;
}
// Update the Fdt with the Initrd information. The FDT will increase in size.
// By setting address=0 we leave the memory allocation to the function
Status = PrepareFdt (CommandLineArguments, InitrdImage, InitrdImageSize, &FdtBlobBase, &FdtBlobSize);
if (EFI_ERROR(Status)) {
Print(L"ERROR: Can not load kernel with FDT. Status=%r\n", Status);
return Status;
}
return StartLinux (LinuxImage, LinuxImageSize, FdtBlobBase, FdtBlobSize, ARM_FDT_MACHINE_TYPE);
}
/** @file
*
* Copyright (c) 2011-2012, 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 "BdsLinuxLoader.h"
#define ALIGN32_BELOW(addr) ALIGN_POINTER(addr - 32,32)
STATIC
EFI_STATUS
PreparePlatformHardware (
VOID
)
{
//Note: Interrupts will be disabled by the GIC driver when ExitBootServices() will be called.
// Clean, invalidate, disable data cache
ArmDisableDataCache();
ArmCleanInvalidateDataCache();
// Invalidate and disable the Instruction cache
ArmDisableInstructionCache ();
ArmInvalidateInstructionCache ();
// Turn off MMU
ArmDisableMmu();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
StartLinux (
IN EFI_PHYSICAL_ADDRESS LinuxImage,
IN UINTN LinuxImageSize,
IN EFI_PHYSICAL_ADDRESS KernelParamsAddress,
IN UINTN KernelParamsSize,
IN UINT32 MachineType
)
{
EFI_STATUS Status;
LINUX_KERNEL LinuxKernel;
// Shut down UEFI boot services. ExitBootServices() will notify every driver that created an event on
// ExitBootServices event. Example the Interrupt DXE driver will disable the interrupts on this event.
Status = ShutdownUefiBootServices ();
if(EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR,"ERROR: Can not shutdown UEFI boot services. Status=0x%X\n", Status));
goto Exit;
}
// Move the kernel parameters to any address inside the first 1MB.
// This is necessary because the ARM Linux kernel requires
// the FTD / ATAG List to reside entirely inside the first 1MB of
// physical memory.
//Note: There is no requirement on the alignment
if (MachineType != ARM_FDT_MACHINE_TYPE) {
if (((UINTN)KernelParamsAddress > LINUX_ATAG_MAX_OFFSET) && (KernelParamsSize < PcdGet32(PcdArmLinuxAtagMaxOffset))) {
KernelParamsAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CopyMem (ALIGN32_BELOW(LINUX_ATAG_MAX_OFFSET - KernelParamsSize), (VOID*)(UINTN)KernelParamsAddress, KernelParamsSize);
}
} else {
if (((UINTN)KernelParamsAddress > LINUX_FDT_MAX_OFFSET) && (KernelParamsSize < PcdGet32(PcdArmLinuxFdtMaxOffset))) {
KernelParamsAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CopyMem (ALIGN32_BELOW(LINUX_FDT_MAX_OFFSET - KernelParamsSize), (VOID*)(UINTN)KernelParamsAddress, KernelParamsSize);
}
}
if ((UINTN)LinuxImage > LINUX_KERNEL_MAX_OFFSET) {
//Note: There is no requirement on the alignment
LinuxKernel = (LINUX_KERNEL)CopyMem (ALIGN32_BELOW(LINUX_KERNEL_MAX_OFFSET - LinuxImageSize), (VOID*)(UINTN)LinuxImage, LinuxImageSize);
} else {
LinuxKernel = (LINUX_KERNEL)(UINTN)LinuxImage;
}
// Check if the Linux Image is a uImage
if (*(UINT32*)LinuxKernel == LINUX_UIMAGE_SIGNATURE) {
// Assume the Image Entry Point is just after the uImage header (64-byte size)
LinuxKernel = (LINUX_KERNEL)((UINTN)LinuxKernel + 64);
LinuxImageSize -= 64;
}
//TODO: Check there is no overlapping between kernel and Atag
//
// Switch off interrupts, caches, mmu, etc
//
Status = PreparePlatformHardware ();
ASSERT_EFI_ERROR(Status);
// Register and print out performance information
PERF_END (NULL, "BDS", NULL, 0);
if (PerformanceMeasurementEnabled ()) {
PrintPerformance ();
}
//
// Start the Linux Kernel
//
// Outside BootServices, so can't use Print();
DEBUG((EFI_D_ERROR, "\nStarting the kernel:\n\n"));
// Jump to kernel with register set
LinuxKernel ((UINTN)0, MachineType, (UINTN)KernelParamsAddress);
// Kernel should never exit
// After Life services are not provided
ASSERT(FALSE);
Exit:
// Only be here if we fail to start Linux
Print (L"ERROR : Can not start the kernel. Status=0x%X\n", Status);
// Free Runtimee Memory (kernel and FDT)
return Status;
}
/**
Start a Linux kernel from a Device Path
@param LinuxKernel Device Path to the Linux Kernel
@param Parameters Linux kernel arguments
@param Fdt Device Path to the Flat Device Tree
@retval EFI_SUCCESS All drivers have been connected
@retval EFI_NOT_FOUND The Linux kernel Device Path has not been found
@retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.
**/
EFI_STATUS
BdsBootLinuxAtag (
IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,
IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,
IN CONST CHAR8* CommandLineArguments
)
{
EFI_STATUS Status;
UINT32 LinuxImageSize;
UINT32 InitrdImageSize = 0;
UINT32 AtagSize;
EFI_PHYSICAL_ADDRESS AtagBase;
EFI_PHYSICAL_ADDRESS LinuxImage;
EFI_PHYSICAL_ADDRESS InitrdImage;
PERF_START (NULL, "BDS", NULL, 0);
// Load the Linux kernel from a device path
LinuxImage = LINUX_KERNEL_MAX_OFFSET;
Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);
if (EFI_ERROR(Status)) {
Print (L"ERROR: Did not find Linux kernel.\n");
return Status;
}
if (InitrdDevicePath) {
// Load the initrd near to the Linux kernel
InitrdImage = LINUX_KERNEL_MAX_OFFSET;
Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, &InitrdImageSize);
if (Status == EFI_OUT_OF_RESOURCES) {
Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize);
}
if (EFI_ERROR(Status)) {
Print (L"ERROR: Did not find initrd image.\n");
return Status;
}
// Check if the initrd is a uInitrd
if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {
// Skip the 64-byte image header
InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);
InitrdImageSize -= 64;
}
}
//
// Setup the Linux Kernel Parameters
//
// By setting address=0 we leave the memory allocation to the function
Status = PrepareAtagList (CommandLineArguments, InitrdImage, InitrdImageSize, &AtagBase, &AtagSize);
if (EFI_ERROR(Status)) {
Print(L"ERROR: Can not prepare ATAG list. Status=0x%X\n", Status);
return Status;
}
return StartLinux (LinuxImage, LinuxImageSize, AtagBase, AtagSize, PcdGet32(PcdArmMachineType));
}
/**
Start a Linux kernel from a Device Path
@param LinuxKernel Device Path to the Linux Kernel
@param Parameters Linux kernel arguments
@param Fdt Device Path to the Flat Device Tree
@retval EFI_SUCCESS All drivers have been connected
@retval EFI_NOT_FOUND The Linux kernel Device Path has not been found
@retval EFI_OUT_OF_RESOURCES There is not enough resource memory to store the matching results.
**/
EFI_STATUS
BdsBootLinuxFdt (
IN EFI_DEVICE_PATH_PROTOCOL* LinuxKernelDevicePath,
IN EFI_DEVICE_PATH_PROTOCOL* InitrdDevicePath,
IN CONST CHAR8* CommandLineArguments,
IN EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath
)
{
EFI_STATUS Status;
UINT32 LinuxImageSize;
UINT32 InitrdImageSize = 0;
UINT32 FdtBlobSize;
EFI_PHYSICAL_ADDRESS FdtBlobBase;
EFI_PHYSICAL_ADDRESS LinuxImage;
EFI_PHYSICAL_ADDRESS InitrdImage;
PERF_START (NULL, "BDS", NULL, 0);
// Load the Linux kernel from a device path
LinuxImage = LINUX_KERNEL_MAX_OFFSET;
Status = BdsLoadImage (LinuxKernelDevicePath, AllocateMaxAddress, &LinuxImage, &LinuxImageSize);
if (EFI_ERROR(Status)) {
Print (L"ERROR: Did not find Linux kernel.\n");
return Status;
}
if (InitrdDevicePath) {
InitrdImage = LINUX_KERNEL_MAX_OFFSET;
Status = BdsLoadImage (InitrdDevicePath, AllocateMaxAddress, &InitrdImage, &InitrdImageSize);
if (Status == EFI_OUT_OF_RESOURCES) {
Status = BdsLoadImage (InitrdDevicePath, AllocateAnyPages, &InitrdImage, &InitrdImageSize);
}
if (EFI_ERROR(Status)) {
Print (L"ERROR: Did not find initrd image.\n");
return Status;
}
// Check if the initrd is a uInitrd
if (*(UINT32*)((UINTN)InitrdImage) == LINUX_UIMAGE_SIGNATURE) {
// Skip the 64-byte image header
InitrdImage = (EFI_PHYSICAL_ADDRESS)((UINTN)InitrdImage + 64);
InitrdImageSize -= 64;
}
}
// Load the FDT binary from a device path. The FDT will be reloaded later to a more appropriate location for the Linux kernel.
FdtBlobBase = 0;
Status = BdsLoadImage (FdtDevicePath, AllocateAnyPages, &FdtBlobBase, &FdtBlobSize);
if (EFI_ERROR(Status)) {
Print (L"ERROR: Did not find Device Tree blob.\n");
return Status;
}
// Update the Fdt with the Initrd information. The FDT will increase in size.
// By setting address=0 we leave the memory allocation to the function
Status = PrepareFdt (CommandLineArguments, InitrdImage, InitrdImageSize, &FdtBlobBase, &FdtBlobSize);
if (EFI_ERROR(Status)) {
Print(L"ERROR: Can not load kernel with FDT. Status=%r\n", Status);
return Status;
}
return StartLinux (LinuxImage, LinuxImageSize, FdtBlobBase, FdtBlobSize, ARM_FDT_MACHINE_TYPE);
}

View File

@@ -1,156 +1,156 @@
/** @file
*
* Copyright (c) 2011-2012, 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.
*
**/
#ifndef __BDSLINUXLOADER_H
#define __BDSLINUXLOADER_H
#define LINUX_UIMAGE_SIGNATURE 0x56190527
#define LINUX_KERNEL_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxKernelMaxOffset))
#define LINUX_ATAG_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxAtagMaxOffset))
#define LINUX_FDT_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxFdtMaxOffset))
// Additional size that could be used for FDT entries added by the UEFI OS Loader
// Estimation based on: EDID (300bytes) + bootargs (200bytes) + initrd region (20bytes)
// + system memory region (20bytes) + mp_core entries (200 bytes)
#define FDT_ADDITIONAL_ENTRIES_SIZE 0x300
#define ARM_FDT_MACHINE_TYPE 0xFFFFFFFF
typedef VOID (*LINUX_KERNEL)(UINT32 Zero, UINT32 Arch, UINTN ParametersBase);
//
// ATAG Definitions
//
#define ATAG_MAX_SIZE 0x3000
/* ATAG : list of possible tags */
#define ATAG_NONE 0x00000000
#define ATAG_CORE 0x54410001
#define ATAG_MEM 0x54410002
#define ATAG_VIDEOTEXT 0x54410003
#define ATAG_RAMDISK 0x54410004
#define ATAG_INITRD2 0x54420005
#define ATAG_SERIAL 0x54410006
#define ATAG_REVISION 0x54410007
#define ATAG_VIDEOLFB 0x54410008
#define ATAG_CMDLINE 0x54410009
#define ATAG_ARM_MP_CORE 0x5441000A
#define next_tag_address(t) ((LINUX_ATAG*)((UINT32)(t) + (((t)->header.size) << 2) ))
#define tag_size(type) ((UINT32)((sizeof(LINUX_ATAG_HEADER) + sizeof(type)) >> 2))
typedef struct {
UINT32 size; /* length of tag in words including this header */
UINT32 type; /* tag type */
} LINUX_ATAG_HEADER;
typedef struct {
UINT32 flags;
UINT32 pagesize;
UINT32 rootdev;
} LINUX_ATAG_CORE;
typedef struct {
UINT32 size;
UINTN start;
} LINUX_ATAG_MEM;
typedef struct {
UINT8 x;
UINT8 y;
UINT16 video_page;
UINT8 video_mode;
UINT8 video_cols;
UINT16 video_ega_bx;
UINT8 video_lines;
UINT8 video_isvga;
UINT16 video_points;
} LINUX_ATAG_VIDEOTEXT;
typedef struct {
UINT32 flags;
UINT32 size;
UINTN start;
} LINUX_ATAG_RAMDISK;
typedef struct {
UINT32 start;
UINT32 size;
} LINUX_ATAG_INITRD2;
typedef struct {
UINT32 low;
UINT32 high;
} LINUX_ATAG_SERIALNR;
typedef struct {
UINT32 rev;
} LINUX_ATAG_REVISION;
typedef struct {
UINT16 lfb_width;
UINT16 lfb_height;
UINT16 lfb_depth;
UINT16 lfb_linelength;
UINT32 lfb_base;
UINT32 lfb_size;
UINT8 red_size;
UINT8 red_pos;
UINT8 green_size;
UINT8 green_pos;
UINT8 blue_size;
UINT8 blue_pos;
UINT8 rsvd_size;
UINT8 rsvd_pos;
} LINUX_ATAG_VIDEOLFB;
typedef struct {
CHAR8 cmdline[1];
} LINUX_ATAG_CMDLINE;
typedef struct {
LINUX_ATAG_HEADER header;
union {
LINUX_ATAG_CORE core_tag;
LINUX_ATAG_MEM mem_tag;
LINUX_ATAG_VIDEOTEXT videotext_tag;
LINUX_ATAG_RAMDISK ramdisk_tag;
LINUX_ATAG_INITRD2 initrd2_tag;
LINUX_ATAG_SERIALNR serialnr_tag;
LINUX_ATAG_REVISION revision_tag;
LINUX_ATAG_VIDEOLFB videolfb_tag;
LINUX_ATAG_CMDLINE cmdline_tag;
} body;
} LINUX_ATAG;
EFI_STATUS
PrepareAtagList (
IN CONST CHAR8* CommandLineString,
IN EFI_PHYSICAL_ADDRESS InitrdImage,
IN UINTN InitrdImageSize,
OUT EFI_PHYSICAL_ADDRESS *AtagBase,
OUT UINT32 *AtagSize
);
EFI_STATUS
PrepareFdt (
IN CONST CHAR8* CommandLineArguments,
IN EFI_PHYSICAL_ADDRESS InitrdImage,
IN UINTN InitrdImageSize,
IN OUT EFI_PHYSICAL_ADDRESS *FdtBlobBase,
IN OUT UINT32 *FdtBlobSize
);
#endif
/** @file
*
* Copyright (c) 2011-2012, 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.
*
**/
#ifndef __BDSLINUXLOADER_H
#define __BDSLINUXLOADER_H
#define LINUX_UIMAGE_SIGNATURE 0x56190527
#define LINUX_KERNEL_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxKernelMaxOffset))
#define LINUX_ATAG_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxAtagMaxOffset))
#define LINUX_FDT_MAX_OFFSET (PcdGet32(PcdSystemMemoryBase) + PcdGet32(PcdArmLinuxFdtMaxOffset))
// Additional size that could be used for FDT entries added by the UEFI OS Loader
// Estimation based on: EDID (300bytes) + bootargs (200bytes) + initrd region (20bytes)
// + system memory region (20bytes) + mp_core entries (200 bytes)
#define FDT_ADDITIONAL_ENTRIES_SIZE 0x300
#define ARM_FDT_MACHINE_TYPE 0xFFFFFFFF
typedef VOID (*LINUX_KERNEL)(UINT32 Zero, UINT32 Arch, UINTN ParametersBase);
//
// ATAG Definitions
//
#define ATAG_MAX_SIZE 0x3000
/* ATAG : list of possible tags */
#define ATAG_NONE 0x00000000
#define ATAG_CORE 0x54410001
#define ATAG_MEM 0x54410002
#define ATAG_VIDEOTEXT 0x54410003
#define ATAG_RAMDISK 0x54410004
#define ATAG_INITRD2 0x54420005
#define ATAG_SERIAL 0x54410006
#define ATAG_REVISION 0x54410007
#define ATAG_VIDEOLFB 0x54410008
#define ATAG_CMDLINE 0x54410009
#define ATAG_ARM_MP_CORE 0x5441000A
#define next_tag_address(t) ((LINUX_ATAG*)((UINT32)(t) + (((t)->header.size) << 2) ))
#define tag_size(type) ((UINT32)((sizeof(LINUX_ATAG_HEADER) + sizeof(type)) >> 2))
typedef struct {
UINT32 size; /* length of tag in words including this header */
UINT32 type; /* tag type */
} LINUX_ATAG_HEADER;
typedef struct {
UINT32 flags;
UINT32 pagesize;
UINT32 rootdev;
} LINUX_ATAG_CORE;
typedef struct {
UINT32 size;
UINTN start;
} LINUX_ATAG_MEM;
typedef struct {
UINT8 x;
UINT8 y;
UINT16 video_page;
UINT8 video_mode;
UINT8 video_cols;
UINT16 video_ega_bx;
UINT8 video_lines;
UINT8 video_isvga;
UINT16 video_points;
} LINUX_ATAG_VIDEOTEXT;
typedef struct {
UINT32 flags;
UINT32 size;
UINTN start;
} LINUX_ATAG_RAMDISK;
typedef struct {
UINT32 start;
UINT32 size;
} LINUX_ATAG_INITRD2;
typedef struct {
UINT32 low;
UINT32 high;
} LINUX_ATAG_SERIALNR;
typedef struct {
UINT32 rev;
} LINUX_ATAG_REVISION;
typedef struct {
UINT16 lfb_width;
UINT16 lfb_height;
UINT16 lfb_depth;
UINT16 lfb_linelength;
UINT32 lfb_base;
UINT32 lfb_size;
UINT8 red_size;
UINT8 red_pos;
UINT8 green_size;
UINT8 green_pos;
UINT8 blue_size;
UINT8 blue_pos;
UINT8 rsvd_size;
UINT8 rsvd_pos;
} LINUX_ATAG_VIDEOLFB;
typedef struct {
CHAR8 cmdline[1];
} LINUX_ATAG_CMDLINE;
typedef struct {
LINUX_ATAG_HEADER header;
union {
LINUX_ATAG_CORE core_tag;
LINUX_ATAG_MEM mem_tag;
LINUX_ATAG_VIDEOTEXT videotext_tag;
LINUX_ATAG_RAMDISK ramdisk_tag;
LINUX_ATAG_INITRD2 initrd2_tag;
LINUX_ATAG_SERIALNR serialnr_tag;
LINUX_ATAG_REVISION revision_tag;
LINUX_ATAG_VIDEOLFB videolfb_tag;
LINUX_ATAG_CMDLINE cmdline_tag;
} body;
} LINUX_ATAG;
EFI_STATUS
PrepareAtagList (
IN CONST CHAR8* CommandLineString,
IN EFI_PHYSICAL_ADDRESS InitrdImage,
IN UINTN InitrdImageSize,
OUT EFI_PHYSICAL_ADDRESS *AtagBase,
OUT UINT32 *AtagSize
);
EFI_STATUS
PrepareFdt (
IN CONST CHAR8* CommandLineArguments,
IN EFI_PHYSICAL_ADDRESS InitrdImage,
IN UINTN InitrdImageSize,
IN OUT EFI_PHYSICAL_ADDRESS *FdtBlobBase,
IN OUT UINT32 *FdtBlobSize
);
#endif

View File

@@ -1,270 +1,270 @@
/** @file
*
* Copyright (c) 2011-2012, 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"
EFI_STATUS
BootOptionParseLoadOption (
IN EFI_LOAD_OPTION EfiLoadOption,
IN UINTN EfiLoadOptionSize,
IN OUT BDS_LOAD_OPTION **BdsLoadOption
)
{
BDS_LOAD_OPTION *LoadOption;
UINTN DescriptionLength;
if (EfiLoadOption == NULL) {
return EFI_INVALID_PARAMETER;
}
if (EfiLoadOptionSize < sizeof(UINT32) + sizeof(UINT16) + sizeof(CHAR16) + sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
return EFI_BAD_BUFFER_SIZE;
}
if (*BdsLoadOption == NULL) {
LoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));
if (LoadOption == NULL) {
return EFI_OUT_OF_RESOURCES;
}
} else {
LoadOption = *BdsLoadOption;
}
LoadOption->LoadOption = EfiLoadOption;
LoadOption->LoadOptionSize = EfiLoadOptionSize;
LoadOption->Attributes = *(UINT32*)EfiLoadOption;
LoadOption->FilePathListLength = *(UINT16*)(EfiLoadOption + sizeof(UINT32));
LoadOption->Description = (CHAR16*)(EfiLoadOption + sizeof(UINT32) + sizeof(UINT16));
DescriptionLength = StrSize (LoadOption->Description);
LoadOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)(EfiLoadOption + sizeof(UINT32) + sizeof(UINT16) + DescriptionLength);
// If ((End of EfiLoadOptiony - Start of EfiLoadOption) == EfiLoadOptionSize) then No Optional Data
if ((UINTN)((UINTN)LoadOption->FilePathList + LoadOption->FilePathListLength - (UINTN)EfiLoadOption) == EfiLoadOptionSize) {
LoadOption->OptionalData = NULL;
LoadOption->OptionalDataSize = 0;
} else {
LoadOption->OptionalData = (VOID*)((UINTN)(LoadOption->FilePathList) + LoadOption->FilePathListLength);
LoadOption->OptionalDataSize = EfiLoadOptionSize - ((UINTN)LoadOption->OptionalData - (UINTN)EfiLoadOption);
}
if (*BdsLoadOption == NULL) {
*BdsLoadOption = LoadOption;
}
return EFI_SUCCESS;
}
EFI_STATUS
BootOptionFromLoadOptionVariable (
IN CHAR16* BootVariableName,
OUT BDS_LOAD_OPTION** BdsLoadOption
)
{
EFI_STATUS Status;
EFI_LOAD_OPTION EfiLoadOption;
UINTN EfiLoadOptionSize;
Status = GetEnvironmentVariable (BootVariableName, NULL, &EfiLoadOptionSize, (VOID**)&EfiLoadOption);
if (!EFI_ERROR(Status)) {
*BdsLoadOption = NULL;
Status = BootOptionParseLoadOption (EfiLoadOption, EfiLoadOptionSize, BdsLoadOption);
}
return Status;
}
EFI_STATUS
BootOptionFromLoadOptionIndex (
IN UINT16 LoadOptionIndex,
OUT BDS_LOAD_OPTION **BdsLoadOption
)
{
CHAR16 BootVariableName[9];
EFI_STATUS Status;
UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", LoadOptionIndex);
Status = BootOptionFromLoadOptionVariable (BootVariableName, BdsLoadOption);
if (!EFI_ERROR(Status)) {
(*BdsLoadOption)->LoadOptionIndex = LoadOptionIndex;
}
return Status;
}
EFI_STATUS
BootOptionToLoadOptionVariable (
IN BDS_LOAD_OPTION* BdsLoadOption
)
{
EFI_STATUS Status;
UINTN DescriptionSize;
//UINT16 FilePathListLength;
EFI_DEVICE_PATH_PROTOCOL* DevicePathNode;
UINTN NodeLength;
UINT8* EfiLoadOptionPtr;
VOID* OldLoadOption;
CHAR16 BootVariableName[9];
UINTN BootOrderSize;
UINT16* BootOrder;
// If we are overwriting an existent Boot Option then we have to free previously allocated memory
if (BdsLoadOption->LoadOptionSize > 0) {
OldLoadOption = BdsLoadOption->LoadOption;
} else {
OldLoadOption = NULL;
// If this function is called at the creation of the Boot Device entry (not at the update) the
// BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry
BdsLoadOption->LoadOptionIndex = BootOptionAllocateBootIndex ();
//TODO: Add to the the Boot Entry List
}
DescriptionSize = StrSize(BdsLoadOption->Description);
// Ensure the FilePathListLength information is correct
ASSERT (GetDevicePathSize (BdsLoadOption->FilePathList) == BdsLoadOption->FilePathListLength);
// Allocate the memory for the EFI Load Option
BdsLoadOption->LoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + DescriptionSize + BdsLoadOption->FilePathListLength + BdsLoadOption->OptionalDataSize;
BdsLoadOption->LoadOption = (EFI_LOAD_OPTION)AllocateZeroPool (BdsLoadOption->LoadOptionSize);
if (BdsLoadOption->LoadOption == NULL) {
return EFI_OUT_OF_RESOURCES;
}
EfiLoadOptionPtr = BdsLoadOption->LoadOption;
//
// Populate the EFI Load Option and BDS Boot Option structures
//
// Attributes fields
*(UINT32*)EfiLoadOptionPtr = BdsLoadOption->Attributes;
EfiLoadOptionPtr += sizeof(UINT32);
// FilePath List fields
*(UINT16*)EfiLoadOptionPtr = BdsLoadOption->FilePathListLength;
EfiLoadOptionPtr += sizeof(UINT16);
// Boot description fields
CopyMem (EfiLoadOptionPtr, BdsLoadOption->Description, DescriptionSize);
EfiLoadOptionPtr += DescriptionSize;
// File path fields
DevicePathNode = BdsLoadOption->FilePathList;
while (!IsDevicePathEndType (DevicePathNode)) {
NodeLength = DevicePathNodeLength(DevicePathNode);
CopyMem (EfiLoadOptionPtr, DevicePathNode, NodeLength);
EfiLoadOptionPtr += NodeLength;
DevicePathNode = NextDevicePathNode (DevicePathNode);
}
// Set the End Device Path Type
SetDevicePathEndNode (EfiLoadOptionPtr);
EfiLoadOptionPtr += sizeof(EFI_DEVICE_PATH);
// Fill the Optional Data
if (BdsLoadOption->OptionalDataSize > 0) {
CopyMem (EfiLoadOptionPtr, BdsLoadOption->OptionalData, BdsLoadOption->OptionalDataSize);
}
// Case where the fields have been updated
if (OldLoadOption) {
// Now, the old data has been copied to the new allocated packed structure, we need to update the pointers of BdsLoadOption
BootOptionParseLoadOption (BdsLoadOption->LoadOption, BdsLoadOption->LoadOptionSize, &BdsLoadOption);
// Free the old packed structure
FreePool (OldLoadOption);
}
// Create/Update Boot#### environment variable
UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex);
Status = gRT->SetVariable (
BootVariableName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
BdsLoadOption->LoadOptionSize,
BdsLoadOption->LoadOption
);
// When it is a new entry we must add the entry to the BootOrder
if (OldLoadOption == NULL) {
// Add the new Boot Index to the list
Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
if (!EFI_ERROR(Status)) {
BootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof(UINT16), BootOrder);
// Add the new index at the end
BootOrder[BootOrderSize / sizeof(UINT16)] = BdsLoadOption->LoadOptionIndex;
BootOrderSize += sizeof(UINT16);
} else {
// BootOrder does not exist. Create it
BootOrderSize = sizeof(UINT16);
BootOrder = &(BdsLoadOption->LoadOptionIndex);
}
// Update (or Create) the BootOrder environment variable
gRT->SetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
BootOrderSize,
BootOrder
);
DEBUG((EFI_D_ERROR,"Create %s\n",BootVariableName));
// Free memory allocated by GetEnvironmentVariable
if (!EFI_ERROR(Status)) {
FreePool (BootOrder);
}
} else {
DEBUG((EFI_D_ERROR,"Update %s\n",BootVariableName));
}
return EFI_SUCCESS;
}
UINT16
BootOptionAllocateBootIndex (
VOID
)
{
EFI_STATUS Status;
UINTN Index;
UINT32 BootIndex;
UINT16 *BootOrder;
UINTN BootOrderSize;
BOOLEAN Found;
// Get the Boot Option Order from the environment variable
Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
if (!EFI_ERROR(Status)) {
for (BootIndex = 0; BootIndex <= 0xFFFF; BootIndex++) {
Found = FALSE;
for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
if (BootOrder[Index] == BootIndex) {
Found = TRUE;
break;
}
}
if (!Found) {
return BootIndex;
}
}
FreePool (BootOrder);
}
// Return the first index
return 0;
}
/** @file
*
* Copyright (c) 2011-2012, 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"
EFI_STATUS
BootOptionParseLoadOption (
IN EFI_LOAD_OPTION EfiLoadOption,
IN UINTN EfiLoadOptionSize,
IN OUT BDS_LOAD_OPTION **BdsLoadOption
)
{
BDS_LOAD_OPTION *LoadOption;
UINTN DescriptionLength;
if (EfiLoadOption == NULL) {
return EFI_INVALID_PARAMETER;
}
if (EfiLoadOptionSize < sizeof(UINT32) + sizeof(UINT16) + sizeof(CHAR16) + sizeof(EFI_DEVICE_PATH_PROTOCOL)) {
return EFI_BAD_BUFFER_SIZE;
}
if (*BdsLoadOption == NULL) {
LoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION));
if (LoadOption == NULL) {
return EFI_OUT_OF_RESOURCES;
}
} else {
LoadOption = *BdsLoadOption;
}
LoadOption->LoadOption = EfiLoadOption;
LoadOption->LoadOptionSize = EfiLoadOptionSize;
LoadOption->Attributes = *(UINT32*)EfiLoadOption;
LoadOption->FilePathListLength = *(UINT16*)(EfiLoadOption + sizeof(UINT32));
LoadOption->Description = (CHAR16*)(EfiLoadOption + sizeof(UINT32) + sizeof(UINT16));
DescriptionLength = StrSize (LoadOption->Description);
LoadOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)(EfiLoadOption + sizeof(UINT32) + sizeof(UINT16) + DescriptionLength);
// If ((End of EfiLoadOptiony - Start of EfiLoadOption) == EfiLoadOptionSize) then No Optional Data
if ((UINTN)((UINTN)LoadOption->FilePathList + LoadOption->FilePathListLength - (UINTN)EfiLoadOption) == EfiLoadOptionSize) {
LoadOption->OptionalData = NULL;
LoadOption->OptionalDataSize = 0;
} else {
LoadOption->OptionalData = (VOID*)((UINTN)(LoadOption->FilePathList) + LoadOption->FilePathListLength);
LoadOption->OptionalDataSize = EfiLoadOptionSize - ((UINTN)LoadOption->OptionalData - (UINTN)EfiLoadOption);
}
if (*BdsLoadOption == NULL) {
*BdsLoadOption = LoadOption;
}
return EFI_SUCCESS;
}
EFI_STATUS
BootOptionFromLoadOptionVariable (
IN CHAR16* BootVariableName,
OUT BDS_LOAD_OPTION** BdsLoadOption
)
{
EFI_STATUS Status;
EFI_LOAD_OPTION EfiLoadOption;
UINTN EfiLoadOptionSize;
Status = GetEnvironmentVariable (BootVariableName, NULL, &EfiLoadOptionSize, (VOID**)&EfiLoadOption);
if (!EFI_ERROR(Status)) {
*BdsLoadOption = NULL;
Status = BootOptionParseLoadOption (EfiLoadOption, EfiLoadOptionSize, BdsLoadOption);
}
return Status;
}
EFI_STATUS
BootOptionFromLoadOptionIndex (
IN UINT16 LoadOptionIndex,
OUT BDS_LOAD_OPTION **BdsLoadOption
)
{
CHAR16 BootVariableName[9];
EFI_STATUS Status;
UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", LoadOptionIndex);
Status = BootOptionFromLoadOptionVariable (BootVariableName, BdsLoadOption);
if (!EFI_ERROR(Status)) {
(*BdsLoadOption)->LoadOptionIndex = LoadOptionIndex;
}
return Status;
}
EFI_STATUS
BootOptionToLoadOptionVariable (
IN BDS_LOAD_OPTION* BdsLoadOption
)
{
EFI_STATUS Status;
UINTN DescriptionSize;
//UINT16 FilePathListLength;
EFI_DEVICE_PATH_PROTOCOL* DevicePathNode;
UINTN NodeLength;
UINT8* EfiLoadOptionPtr;
VOID* OldLoadOption;
CHAR16 BootVariableName[9];
UINTN BootOrderSize;
UINT16* BootOrder;
// If we are overwriting an existent Boot Option then we have to free previously allocated memory
if (BdsLoadOption->LoadOptionSize > 0) {
OldLoadOption = BdsLoadOption->LoadOption;
} else {
OldLoadOption = NULL;
// If this function is called at the creation of the Boot Device entry (not at the update) the
// BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry
BdsLoadOption->LoadOptionIndex = BootOptionAllocateBootIndex ();
//TODO: Add to the the Boot Entry List
}
DescriptionSize = StrSize(BdsLoadOption->Description);
// Ensure the FilePathListLength information is correct
ASSERT (GetDevicePathSize (BdsLoadOption->FilePathList) == BdsLoadOption->FilePathListLength);
// Allocate the memory for the EFI Load Option
BdsLoadOption->LoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + DescriptionSize + BdsLoadOption->FilePathListLength + BdsLoadOption->OptionalDataSize;
BdsLoadOption->LoadOption = (EFI_LOAD_OPTION)AllocateZeroPool (BdsLoadOption->LoadOptionSize);
if (BdsLoadOption->LoadOption == NULL) {
return EFI_OUT_OF_RESOURCES;
}
EfiLoadOptionPtr = BdsLoadOption->LoadOption;
//
// Populate the EFI Load Option and BDS Boot Option structures
//
// Attributes fields
*(UINT32*)EfiLoadOptionPtr = BdsLoadOption->Attributes;
EfiLoadOptionPtr += sizeof(UINT32);
// FilePath List fields
*(UINT16*)EfiLoadOptionPtr = BdsLoadOption->FilePathListLength;
EfiLoadOptionPtr += sizeof(UINT16);
// Boot description fields
CopyMem (EfiLoadOptionPtr, BdsLoadOption->Description, DescriptionSize);
EfiLoadOptionPtr += DescriptionSize;
// File path fields
DevicePathNode = BdsLoadOption->FilePathList;
while (!IsDevicePathEndType (DevicePathNode)) {
NodeLength = DevicePathNodeLength(DevicePathNode);
CopyMem (EfiLoadOptionPtr, DevicePathNode, NodeLength);
EfiLoadOptionPtr += NodeLength;
DevicePathNode = NextDevicePathNode (DevicePathNode);
}
// Set the End Device Path Type
SetDevicePathEndNode (EfiLoadOptionPtr);
EfiLoadOptionPtr += sizeof(EFI_DEVICE_PATH);
// Fill the Optional Data
if (BdsLoadOption->OptionalDataSize > 0) {
CopyMem (EfiLoadOptionPtr, BdsLoadOption->OptionalData, BdsLoadOption->OptionalDataSize);
}
// Case where the fields have been updated
if (OldLoadOption) {
// Now, the old data has been copied to the new allocated packed structure, we need to update the pointers of BdsLoadOption
BootOptionParseLoadOption (BdsLoadOption->LoadOption, BdsLoadOption->LoadOptionSize, &BdsLoadOption);
// Free the old packed structure
FreePool (OldLoadOption);
}
// Create/Update Boot#### environment variable
UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex);
Status = gRT->SetVariable (
BootVariableName,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
BdsLoadOption->LoadOptionSize,
BdsLoadOption->LoadOption
);
// When it is a new entry we must add the entry to the BootOrder
if (OldLoadOption == NULL) {
// Add the new Boot Index to the list
Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
if (!EFI_ERROR(Status)) {
BootOrder = ReallocatePool (BootOrderSize, BootOrderSize + sizeof(UINT16), BootOrder);
// Add the new index at the end
BootOrder[BootOrderSize / sizeof(UINT16)] = BdsLoadOption->LoadOptionIndex;
BootOrderSize += sizeof(UINT16);
} else {
// BootOrder does not exist. Create it
BootOrderSize = sizeof(UINT16);
BootOrder = &(BdsLoadOption->LoadOptionIndex);
}
// Update (or Create) the BootOrder environment variable
gRT->SetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
BootOrderSize,
BootOrder
);
DEBUG((EFI_D_ERROR,"Create %s\n",BootVariableName));
// Free memory allocated by GetEnvironmentVariable
if (!EFI_ERROR(Status)) {
FreePool (BootOrder);
}
} else {
DEBUG((EFI_D_ERROR,"Update %s\n",BootVariableName));
}
return EFI_SUCCESS;
}
UINT16
BootOptionAllocateBootIndex (
VOID
)
{
EFI_STATUS Status;
UINTN Index;
UINT32 BootIndex;
UINT16 *BootOrder;
UINTN BootOrderSize;
BOOLEAN Found;
// Get the Boot Option Order from the environment variable
Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);
if (!EFI_ERROR(Status)) {
for (BootIndex = 0; BootIndex <= 0xFFFF; BootIndex++) {
Found = FALSE;
for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) {
if (BootOrder[Index] == BootIndex) {
Found = TRUE;
break;
}
}
if (!Found) {
return BootIndex;
}
}
FreePool (BootOrder);
}
// Return the first index
return 0;
}