ArmPkg/Application: Add new EFI application to boot Linux
This new application support ATAG and FDT Linux kernel. It uses the Device Tree from the EFI Configuration Table to boot FDT aware Linux kernel. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ronald Cron <Ronald.Cron@arm.com> Reviewed-by: Olivier Martin <Olivier.Martin@arm.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17828 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
committed by
oliviermartin
parent
e6c51eaf02
commit
23b01c83b2
192
ArmPkg/Application/LinuxLoader/LinuxLoaderHelper.c
Normal file
192
ArmPkg/Application/LinuxLoader/LinuxLoaderHelper.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2015, 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 <PiDxe.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
#include <Library/SerialPortLib.h>
|
||||
|
||||
#include "LinuxLoader.h"
|
||||
|
||||
STATIC CONST CHAR8 *mTokenList[] = {
|
||||
/*"SEC",*/
|
||||
"PEI",
|
||||
"DXE",
|
||||
"BDS",
|
||||
NULL
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
InsertSystemMemoryResources (
|
||||
LIST_ENTRY *ResourceList,
|
||||
EFI_HOB_RESOURCE_DESCRIPTOR *ResHob
|
||||
)
|
||||
{
|
||||
SYSTEM_MEMORY_RESOURCE *NewResource;
|
||||
LIST_ENTRY *Link;
|
||||
LIST_ENTRY *NextLink;
|
||||
LIST_ENTRY AttachedResources;
|
||||
SYSTEM_MEMORY_RESOURCE *Resource;
|
||||
EFI_PHYSICAL_ADDRESS NewResourceEnd;
|
||||
|
||||
if (IsListEmpty (ResourceList)) {
|
||||
NewResource = AllocateZeroPool (sizeof (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 = (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 = (SYSTEM_MEMORY_RESOURCE*)GetFirstNode (&AttachedResources);
|
||||
Link = RemoveEntryList (&NewResource->Link);
|
||||
while (!IsListEmpty (&AttachedResources)) {
|
||||
// Merge resources
|
||||
Resource = (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 (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;
|
||||
}
|
Reference in New Issue
Block a user