Adding support for BeagleBoard.
ArmPkg - Supoprt for ARM specific things that can change as the architecture changes. Plus semihosting JTAG drivers. EmbeddedPkg - Generic support for an embeddded platform. Including a light weight command line shell. BeagleBoardPkg - Platform specifics for BeagleBoard. SD Card works, but USB has issues. Looks like a bug in the open source USB stack (Our internal stack works fine). git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9518 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
969
EmbeddedPkg/Ebl/EfiDevice.c
Normal file
969
EmbeddedPkg/Ebl/EfiDevice.c
Normal file
@@ -0,0 +1,969 @@
|
||||
/** @file
|
||||
EBL commands for EFI and PI Devices
|
||||
|
||||
Copyright (c) 2007, Intel Corporation<BR>
|
||||
Portions copyright (c) 2008-2009, Apple Inc. All rights reserved.
|
||||
|
||||
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 "Ebl.h"
|
||||
|
||||
|
||||
EFI_DXE_SERVICES *gDS = NULL;
|
||||
|
||||
|
||||
/**
|
||||
Print information about the File System device.
|
||||
|
||||
@param File Open File for the device
|
||||
|
||||
**/
|
||||
VOID
|
||||
EblPrintFsInfo (
|
||||
IN EFI_OPEN_FILE *File
|
||||
)
|
||||
{
|
||||
if (File == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
AsciiPrint (" %a: ", File->DeviceName);
|
||||
if (File->FsInfo != NULL) {
|
||||
AsciiPrint ("%s: ", File->FsInfo->VolumeLabel);
|
||||
if (File->FsInfo->ReadOnly) {
|
||||
AsciiPrint ("ReadOnly");
|
||||
}
|
||||
}
|
||||
|
||||
AsciiPrint ("\n");
|
||||
EfiClose (File);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Print information about the FV devices.
|
||||
|
||||
@param File Open File for the device
|
||||
|
||||
**/
|
||||
VOID
|
||||
EblPrintFvbInfo (
|
||||
IN EFI_OPEN_FILE *File
|
||||
)
|
||||
{
|
||||
if (File == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
AsciiPrint (" %a: 0x%08lx - 0x%08lx : 0x%08x\n", File->DeviceName, File->FvStart, File->FvStart + File->FvSize - 1, File->FvSize);
|
||||
EfiClose (File);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Print information about the Blk IO devices.
|
||||
If the device supports PXE dump out extra information
|
||||
|
||||
@param File Open File for the device
|
||||
|
||||
**/
|
||||
VOID
|
||||
EblPrintBlkIoInfo (
|
||||
IN EFI_OPEN_FILE *File
|
||||
)
|
||||
{
|
||||
UINT64 DeviceSize;
|
||||
|
||||
|
||||
if (File == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
AsciiPrint (" %a: ", File->DeviceName);
|
||||
if (File->FsBlockIoMedia.RemovableMedia) {
|
||||
AsciiPrint ("Removable ");
|
||||
}
|
||||
if (!File->FsBlockIoMedia.MediaPresent) {
|
||||
AsciiPrint ("No Media ");
|
||||
}
|
||||
if (File->FsBlockIoMedia.LogicalPartition) {
|
||||
AsciiPrint ("Partition ");
|
||||
}
|
||||
DeviceSize = MultU64x32 (File->FsBlockIoMedia.LastBlock + 1, File->FsBlockIoMedia.BlockSize);
|
||||
AsciiPrint ("Size = 0x%lX\n", DeviceSize);
|
||||
|
||||
EfiClose (File);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Print information about the Load File devices.
|
||||
If the device supports PXE dump out extra information
|
||||
|
||||
@param File Open File for the device
|
||||
|
||||
**/
|
||||
VOID
|
||||
EblPrintLoadFileInfo (
|
||||
IN EFI_OPEN_FILE *File
|
||||
)
|
||||
{
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
|
||||
MAC_ADDR_DEVICE_PATH *MacAddr;
|
||||
UINTN HwAddressSize;
|
||||
UINTN Index;
|
||||
|
||||
if (File == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
AsciiPrint (" %a: %a ", File->DeviceName, EblLoadFileBootTypeString (File->EfiHandle));
|
||||
|
||||
if (File->DevicePath != NULL) {
|
||||
// Try to print out the MAC address
|
||||
for (DevicePathNode = File->DevicePath;
|
||||
!IsDevicePathEnd (DevicePathNode);
|
||||
DevicePathNode = NextDevicePathNode (DevicePathNode)) {
|
||||
|
||||
if ((DevicePathType (DevicePathNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (DevicePathNode) == MSG_MAC_ADDR_DP)) {
|
||||
MacAddr = (MAC_ADDR_DEVICE_PATH *)DevicePathNode;
|
||||
|
||||
HwAddressSize = sizeof (EFI_MAC_ADDRESS);
|
||||
if (MacAddr->IfType == 0x01 || MacAddr->IfType == 0x00) {
|
||||
HwAddressSize = 6;
|
||||
}
|
||||
|
||||
AsciiPrint ("MAC ");
|
||||
for (Index = 0; Index < HwAddressSize; Index++) {
|
||||
AsciiPrint ("%02x", MacAddr->MacAddress.Addr[Index] & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AsciiPrint ("\n");
|
||||
EfiClose (File);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Dump information about devices in the system.
|
||||
|
||||
fv: PI Firmware Volume
|
||||
fs: EFI Simple File System
|
||||
blk: EFI Block IO
|
||||
LoadFile: EFI Load File Protocol (commonly PXE network boot)
|
||||
|
||||
Argv[0] - "device"
|
||||
|
||||
@param Argc Number of command arguments in Argv
|
||||
@param Argv Array of strings that represent the parsed command line.
|
||||
Argv[0] is the comamnd name
|
||||
|
||||
@return EFI_SUCCESS
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EblDeviceCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINTN CurrentRow;
|
||||
UINTN Max;
|
||||
|
||||
CurrentRow = 0;
|
||||
|
||||
// Need to call here to make sure Device Counts are valid
|
||||
EblUpdateDeviceLists ();
|
||||
|
||||
Max = EfiGetDeviceCounts (EfiOpenFirmwareVolume);
|
||||
if (Max != 0) {
|
||||
AsciiPrint ("Firmware Volume Devices:\n");
|
||||
for (Index = 0; Index < Max; Index++) {
|
||||
EblPrintFvbInfo (EfiDeviceOpenByType (EfiOpenFirmwareVolume, Index));
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Max = EfiGetDeviceCounts (EfiOpenFileSystem);
|
||||
if (Max != 0) {
|
||||
AsciiPrint ("File System Devices:\n");
|
||||
for (Index = 0; Index < Max; Index++) {
|
||||
EblPrintFsInfo (EfiDeviceOpenByType (EfiOpenFileSystem, Index));
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Max = EfiGetDeviceCounts (EfiOpenBlockIo);
|
||||
if (Max != 0) {
|
||||
AsciiPrint ("Block IO Devices:\n");
|
||||
for (Index = 0; Index < Max; Index++) {
|
||||
EblPrintBlkIoInfo (EfiDeviceOpenByType (EfiOpenBlockIo, Index));
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Max = EfiGetDeviceCounts (EfiOpenLoadFile);
|
||||
if (Max != 0) {
|
||||
AsciiPrint ("LoadFile Devices: (usually network)\n");
|
||||
for (Index = 0; Index < Max; Index++) {
|
||||
EblPrintLoadFileInfo (EfiDeviceOpenByType (EfiOpenLoadFile, Index));
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Start an EFI image (PE32+ with EFI defined entry point).
|
||||
|
||||
Argv[0] - "start"
|
||||
Argv[1] - device name and path
|
||||
Argv[2] - "" string to pass into image being started
|
||||
|
||||
start fs1:\Temp\Fv.Fv "arg to pass" ; load an FV from the disk and pass the
|
||||
; ascii string arg to pass to the image
|
||||
start fv0:\FV ; load an FV from an FV (not common)
|
||||
start LoadFile0: ; load an FV via a PXE boot
|
||||
|
||||
@param Argc Number of command arguments in Argv
|
||||
@param Argv Array of strings that represent the parsed command line.
|
||||
Argv[0] is the comamnd name
|
||||
|
||||
@return EFI_SUCCESS
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EblStartCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_OPEN_FILE *File;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
EFI_HANDLE ImageHandle;
|
||||
UINTN ExitDataSize;
|
||||
CHAR16 *ExitData;
|
||||
VOID *Buffer;
|
||||
UINTN BufferSize;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
|
||||
|
||||
ImageHandle = NULL;
|
||||
|
||||
if (Argc < 2) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (File == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
DevicePath = File->DevicePath;
|
||||
if (DevicePath != NULL) {
|
||||
// check for device path form: blk, fv, fs, and loadfile
|
||||
Status = gBS->LoadImage (FALSE, gImageHandle, DevicePath, NULL, 0, &ImageHandle);
|
||||
} else {
|
||||
// Check for buffer form: A0x12345678:0x1234 syntax.
|
||||
// Means load using buffer starting at 0x12345678 of size 0x1234.
|
||||
|
||||
Status = EfiReadAllocatePool (File, &Buffer, &BufferSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
EfiClose (File);
|
||||
return Status;
|
||||
}
|
||||
Status = gBS->LoadImage (FALSE, gImageHandle, DevicePath, Buffer, BufferSize, &ImageHandle);
|
||||
|
||||
FreePool (Buffer);
|
||||
}
|
||||
|
||||
EfiClose (File);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
if (Argc >= 3) {
|
||||
// Argv[2] is a "" string that we pass directly to the EFI application without the ""
|
||||
// We don't pass Argv[0] to the EFI Application (it's name) just the args
|
||||
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&ImageInfo);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
ImageInfo->LoadOptionsSize = (UINT32)AsciiStrSize (Argv[2]);
|
||||
ImageInfo->LoadOptions = AllocatePool (ImageInfo->LoadOptionsSize);
|
||||
AsciiStrCpy (ImageInfo->LoadOptions, Argv[2]);
|
||||
}
|
||||
|
||||
// Transfer control to the EFI image we loaded with LoadImage()
|
||||
Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Load a Firmware Volume (FV) into memory from a device. This causes drivers in
|
||||
the FV to be dispatched if the dependancies of the drivers are met.
|
||||
|
||||
Argv[0] - "loadfv"
|
||||
Argv[1] - device name and path
|
||||
|
||||
loadfv fs1:\Temp\Fv.Fv ; load an FV from the disk
|
||||
loadfv fv0:\FV ; load an FV from an FV (not common)
|
||||
loadfv LoadFile0: ; load an FV via a PXE boot
|
||||
|
||||
@param Argc Number of command arguments in Argv
|
||||
@param Argv Array of strings that represent the parsed command line.
|
||||
Argv[0] is the comamnd name
|
||||
|
||||
@return EFI_SUCCESS
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EblLoadFvCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_OPEN_FILE *File;
|
||||
VOID *FvStart;
|
||||
UINTN FvSize;
|
||||
EFI_HANDLE FvHandle;
|
||||
|
||||
|
||||
if (Argc < 2) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (File == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (File->Type == EfiOpenMemoryBuffer) {
|
||||
// If it is a address just use it.
|
||||
Status = gDS->ProcessFirmwareVolume (File->Buffer, File->Size, &FvHandle);
|
||||
} else {
|
||||
// If it is a file read it into memory and use it
|
||||
Status = EfiReadAllocatePool (File, &FvStart, &FvSize);
|
||||
EfiClose (File);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gDS->ProcessFirmwareVolume (FvStart, FvSize, &FvHandle);
|
||||
FreePool (FvStart);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Perform an EFI connect to connect devices that follow the EFI driver model.
|
||||
If it is a PI system also call the dispatcher in case a new FV was made
|
||||
availible by one of the connect EFI drivers (this is not a common case).
|
||||
|
||||
Argv[0] - "connect"
|
||||
|
||||
@param Argc Number of command arguments in Argv
|
||||
@param Argv Array of strings that represent the parsed command line.
|
||||
Argv[0] is the comamnd name
|
||||
|
||||
@return EFI_SUCCESS
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EblConnectCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN HandleCount;
|
||||
EFI_HANDLE *HandleBuffer;
|
||||
UINTN Index;
|
||||
BOOLEAN Dispatch;
|
||||
EFI_OPEN_FILE *File;
|
||||
|
||||
|
||||
if (Argc > 1) {
|
||||
if ((*Argv[1] == 'd') || (*Argv[1] == 'D')) {
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
AllHandles,
|
||||
NULL,
|
||||
NULL,
|
||||
&HandleCount,
|
||||
&HandleBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < HandleCount; Index++) {
|
||||
gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
|
||||
}
|
||||
|
||||
//
|
||||
// Given we disconnect our console we should go and do a connect now
|
||||
//
|
||||
} else {
|
||||
File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (File != NULL) {
|
||||
AsciiPrint ("Connecting %a\n", Argv[1]);
|
||||
gBS->ConnectController (File->EfiHandle, NULL, NULL, TRUE);
|
||||
EfiClose (File);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dispatch = FALSE;
|
||||
do {
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
AllHandles,
|
||||
NULL,
|
||||
NULL,
|
||||
&HandleCount,
|
||||
&HandleBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < HandleCount; Index++) {
|
||||
gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
|
||||
}
|
||||
|
||||
FreePool (HandleBuffer);
|
||||
|
||||
//
|
||||
// Check to see if it's possible to dispatch an more DXE drivers.
|
||||
// The BdsLibConnectAllEfi () may have made new DXE drivers show up.
|
||||
// If anything is Dispatched Status == EFI_SUCCESS and we will try
|
||||
// the connect again.
|
||||
//
|
||||
if (gDS == NULL) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
} else {
|
||||
Status = gDS->Dispatch ();
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Dispatch = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
} while (!EFI_ERROR (Status));
|
||||
|
||||
if (Dispatch) {
|
||||
AsciiPrint ("Connected and dispatched\n");
|
||||
} else {
|
||||
AsciiPrint ("Connect\n");
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CHAR8 *gMemMapType[] = {
|
||||
"reserved ",
|
||||
"LoaderCode",
|
||||
"LoaderData",
|
||||
"BS_code ",
|
||||
"BS_data ",
|
||||
"RT_code ",
|
||||
"RT_data ",
|
||||
"available ",
|
||||
"Unusable ",
|
||||
"ACPI_recl ",
|
||||
"ACPI_NVS ",
|
||||
"MemMapIO ",
|
||||
"MemPortIO ",
|
||||
"PAL_code "
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Dump out the EFI memory map
|
||||
|
||||
Argv[0] - "memmap"
|
||||
|
||||
@param Argc Number of command arguments in Argv
|
||||
@param Argv Array of strings that represent the parsed command line.
|
||||
Argv[0] is the comamnd name
|
||||
|
||||
@return EFI_SUCCESS
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EblMemMapCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_MEMORY_DESCRIPTOR *MemMap;
|
||||
EFI_MEMORY_DESCRIPTOR *OrigMemMap;
|
||||
UINTN MemMapSize;
|
||||
UINTN MapKey;
|
||||
UINTN DescriptorSize;
|
||||
UINT32 DescriptorVersion;
|
||||
UINT64 PageCount[EfiMaxMemoryType];
|
||||
UINTN Index;
|
||||
UINT64 EntrySize;
|
||||
UINTN CurrentRow;
|
||||
UINT64 TotalMemory;
|
||||
|
||||
ZeroMem (PageCount, sizeof (PageCount));
|
||||
|
||||
AsciiPrint ("EFI Memory Map\n");
|
||||
|
||||
// First call is to figure out how big the buffer needs to be
|
||||
MemMapSize = 0;
|
||||
MemMap = NULL;
|
||||
Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
// In case the AllocatPool changes the memory map we added in some extra descriptors
|
||||
MemMapSize += (DescriptorSize * 0x100);
|
||||
OrigMemMap = MemMap = AllocatePool (MemMapSize);
|
||||
if (OrigMemMap != NULL) {
|
||||
// 2nd time we get the data
|
||||
Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
for (Index = 0, CurrentRow = 0; Index < MemMapSize/DescriptorSize; Index++) {
|
||||
EntrySize = LShiftU64 (MemMap->NumberOfPages, 12);
|
||||
AsciiPrint ("\n%a %016lx - %016lx: # %08lx %016lx", gMemMapType[MemMap->Type % EfiMaxMemoryType], MemMap->PhysicalStart, MemMap->PhysicalStart + EntrySize -1, MemMap->NumberOfPages, MemMap->Attribute);
|
||||
if (EblAnyKeyToContinueQtoQuit (&CurrentRow, TRUE)) {
|
||||
break;
|
||||
}
|
||||
|
||||
PageCount[MemMap->Type % EfiMaxMemoryType] += MemMap->NumberOfPages;
|
||||
MemMap = NEXT_MEMORY_DESCRIPTOR (MemMap, DescriptorSize);
|
||||
}
|
||||
}
|
||||
|
||||
for (Index = 0, TotalMemory = 0; Index < EfiMaxMemoryType; Index++) {
|
||||
if (PageCount[Index] != 0) {
|
||||
AsciiPrint ("\n %a %,7ld Pages (%,14ld)", gMemMapType[Index], PageCount[Index], LShiftU64 (PageCount[Index], 12));
|
||||
if (Index == EfiLoaderCode ||
|
||||
Index == EfiLoaderData ||
|
||||
Index == EfiBootServicesCode ||
|
||||
Index == EfiBootServicesData ||
|
||||
Index == EfiRuntimeServicesCode ||
|
||||
Index == EfiRuntimeServicesData ||
|
||||
Index == EfiConventionalMemory ||
|
||||
Index == EfiACPIReclaimMemory ||
|
||||
Index == EfiACPIMemoryNVS ||
|
||||
Index == EfiPalCode
|
||||
) {
|
||||
// Count total memory
|
||||
TotalMemory += PageCount[Index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AsciiPrint ("\nTotal Memory: %,ld MB (%,ld bytes)\n", RShiftU64 (TotalMemory, 8), LShiftU64 (TotalMemory, 12));
|
||||
|
||||
FreePool (OrigMemMap);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Load a file into memory and optionally jump to it. A load addres can be
|
||||
specified or automatically allocated. A quoted command line can optionally
|
||||
be passed into the image.
|
||||
|
||||
Argv[0] - "go"
|
||||
Argv[1] - Device Name:path for the file to load
|
||||
Argv[2] - Address to load to or '*' if the load address will be allocated
|
||||
Argv[3] - Optional Entry point to the image. Image will be called if present
|
||||
Argv[4] - "" string that will be passed as Argc & Argv to EntryPoint. Needs
|
||||
to include the command name
|
||||
|
||||
go fv1:\EblCmdX 0x10000 0x10010 "EblCmdX Arg2 Arg3 Arg4"; - load EblCmdX
|
||||
from FV1 to location 0x10000 and call the entry point at 0x10010 passing
|
||||
in "EblCmdX Arg2 Arg3 Arg4" as the arguments.
|
||||
|
||||
go fv0:\EblCmdX * 0x10 "EblCmdX Arg2 Arg3 Arg4"; - load EblCmdX from FS0
|
||||
to location allocated by this comamnd and call the entry point at offset 0x10
|
||||
passing in "EblCmdX Arg2 Arg3 Arg4" as the arguments.
|
||||
|
||||
go fv1:\EblCmdX 0x10000; Load EblCmdX to address 0x10000 and return
|
||||
|
||||
@param Argc Number of command arguments in Argv
|
||||
@param Argv Array of strings that represent the parsed command line.
|
||||
Argv[0] is the comamnd name
|
||||
|
||||
@return EFI_SUCCESS
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EblGoCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_OPEN_FILE *File;
|
||||
VOID *Address;
|
||||
UINTN Size;
|
||||
EBL_COMMMAND EntryPoint;
|
||||
UINTN EntryPointArgc;
|
||||
CHAR8 *EntryPointArgv[MAX_ARGS];
|
||||
|
||||
|
||||
if (Argc <= 2) {
|
||||
// device name and laod address are required
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (File == NULL) {
|
||||
AsciiPrint (" %a is not a valid path\n", Argv[1]);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EntryPoint = (EBL_COMMMAND)((Argc > 3) ? (UINTN)AsciiStrHexToUintn (Argv[3]) : (UINTN)NULL);
|
||||
if (Argv[2][0] == '*') {
|
||||
// * Means allocate the buffer
|
||||
Status = EfiReadAllocatePool (File, &Address, &Size);
|
||||
|
||||
// EntryPoint is relatvie to the start of the image
|
||||
EntryPoint = (EBL_COMMMAND)((UINTN)EntryPoint + (UINTN)Address);
|
||||
|
||||
} else {
|
||||
Address = (VOID *)AsciiStrHexToUintn (Argv[2]);
|
||||
Size = File->Size;
|
||||
|
||||
// File->Size for LoadFile is lazy so we need to use the tell to figure it out
|
||||
EfiTell (File, NULL);
|
||||
Status = EfiRead (File, Address, &Size);
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
AsciiPrint ("Loaded %,d bytes to 0x%08x\n", Size, Address);
|
||||
|
||||
if (Argc > 3) {
|
||||
if (Argc > 4) {
|
||||
ParseArguments (Argv[4], &EntryPointArgc, EntryPointArgv);
|
||||
} else {
|
||||
EntryPointArgc = 1;
|
||||
EntryPointArgv[0] = File->FileName;
|
||||
}
|
||||
|
||||
Status = EntryPoint (EntryPointArgc, EntryPointArgv);
|
||||
}
|
||||
}
|
||||
|
||||
EfiClose (File);
|
||||
return Status;
|
||||
}
|
||||
|
||||
#define FILE_COPY_CHUNK 0x20000
|
||||
|
||||
EFI_STATUS
|
||||
EblFileCopyCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_OPEN_FILE *Source = NULL;
|
||||
EFI_OPEN_FILE *Destination = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
VOID *Buffer = NULL;
|
||||
UINTN Size;
|
||||
UINTN Offset;
|
||||
UINTN Chunk = FILE_COPY_CHUNK;
|
||||
|
||||
if (Argc < 3) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Source = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (Source == NULL) {
|
||||
AsciiPrint("Source file open error.\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Destination = EfiOpen(Argv[2], EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
|
||||
if (Destination == NULL) {
|
||||
AsciiPrint("Destination file open error.\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Buffer = AllocatePool(FILE_COPY_CHUNK);
|
||||
if (Buffer == NULL) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Size = EfiTell(Source, NULL);
|
||||
|
||||
for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size; Offset += Chunk) {
|
||||
Chunk = FILE_COPY_CHUNK;
|
||||
|
||||
Status = EfiRead(Source, Buffer, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("Read file error\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = EfiWrite(Destination, Buffer, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("Write file error\n");
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Any left over?
|
||||
if (Offset < Size) {
|
||||
Chunk = Size - Offset;
|
||||
|
||||
Status = EfiRead(Source, Buffer, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("Read file error\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = EfiWrite(Destination, Buffer, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("Write file error\n");
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (Source != NULL) {
|
||||
Status = EfiClose(Source);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("Source close error %r\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
if (Destination != NULL) {
|
||||
Status = EfiClose(Destination);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("Destination close error %r\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
if (Buffer != NULL) {
|
||||
FreePool(Buffer);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EblFileDiffCmd (
|
||||
IN UINTN Argc,
|
||||
IN CHAR8 **Argv
|
||||
)
|
||||
{
|
||||
EFI_OPEN_FILE *File1 = NULL;
|
||||
EFI_OPEN_FILE *File2 = NULL;
|
||||
EFI_STATUS Status = EFI_SUCCESS;
|
||||
VOID *Buffer1 = NULL;
|
||||
VOID *Buffer2 = NULL;
|
||||
UINTN Size1;
|
||||
UINTN Size2;
|
||||
UINTN Offset;
|
||||
UINTN Chunk = FILE_COPY_CHUNK;
|
||||
|
||||
if (Argc != 3) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
File1 = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0);
|
||||
if (File1 == NULL) {
|
||||
AsciiPrint("File 1 open error.\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
File2 = EfiOpen(Argv[2], EFI_FILE_MODE_READ, 0);
|
||||
if (File2 == NULL) {
|
||||
AsciiPrint("File 2 open error.\n");
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Size1 = EfiTell(File1, NULL);
|
||||
Size2 = EfiTell(File2, NULL);
|
||||
|
||||
if (Size1 != Size2) {
|
||||
AsciiPrint("Files differ.\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Buffer1 = AllocatePool(FILE_COPY_CHUNK);
|
||||
if (Buffer1 == NULL) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Buffer2 = AllocatePool(FILE_COPY_CHUNK);
|
||||
if (Buffer2 == NULL) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
for (Offset = 0; Offset + FILE_COPY_CHUNK <= Size1; Offset += Chunk) {
|
||||
Chunk = FILE_COPY_CHUNK;
|
||||
|
||||
Status = EfiRead(File1, Buffer1, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("File 1 read error\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = EfiRead(File2, Buffer2, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("File 2 read error\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (CompareMem(Buffer1, Buffer2, Chunk) != 0) {
|
||||
AsciiPrint("Files differ.\n");
|
||||
goto Exit;
|
||||
};
|
||||
}
|
||||
|
||||
// Any left over?
|
||||
if (Offset < Size1) {
|
||||
Chunk = Size1 - Offset;
|
||||
|
||||
Status = EfiRead(File1, Buffer1, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("File 1 read error\n");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
Status = EfiRead(File2, Buffer2, &Chunk);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("File 2 read error\n");
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (CompareMem(Buffer1, Buffer2, Chunk) != 0) {
|
||||
AsciiPrint("Files differ.\n");
|
||||
} else {
|
||||
AsciiPrint("Files are identical.\n");
|
||||
}
|
||||
|
||||
Exit:
|
||||
if (File1 != NULL) {
|
||||
Status = EfiClose(File1);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("File 1 close error %r\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
if (File2 != NULL) {
|
||||
Status = EfiClose(File2);
|
||||
if (EFI_ERROR(Status)) {
|
||||
AsciiPrint("File 2 close error %r\n", Status);
|
||||
}
|
||||
}
|
||||
|
||||
if (Buffer1 != NULL) {
|
||||
FreePool(Buffer1);
|
||||
}
|
||||
|
||||
if (Buffer2 != NULL) {
|
||||
FreePool(Buffer2);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDeviceTemplate[] =
|
||||
{
|
||||
{
|
||||
"connect",
|
||||
"[d]; Connect all EFI devices. d means disconnect",
|
||||
NULL,
|
||||
EblConnectCmd
|
||||
},
|
||||
{
|
||||
"device",
|
||||
"; Show information about boot devices",
|
||||
NULL,
|
||||
EblDeviceCmd
|
||||
},
|
||||
{
|
||||
"go",
|
||||
" dev:path loadaddress entrypoint args; load to given address and jump in",
|
||||
NULL,
|
||||
EblGoCmd
|
||||
},
|
||||
{
|
||||
"loadfv",
|
||||
" devname; Load PI FV from device",
|
||||
NULL,
|
||||
EblLoadFvCmd
|
||||
},
|
||||
{
|
||||
"start",
|
||||
" path; EFI Boot Device:filepath. fs1:\\EFI\\BOOT.EFI",
|
||||
NULL,
|
||||
EblStartCmd
|
||||
},
|
||||
{
|
||||
"memmap",
|
||||
"; dump EFI memory map",
|
||||
NULL,
|
||||
EblMemMapCmd
|
||||
},
|
||||
{
|
||||
"cp",
|
||||
" file1 file2; copy file",
|
||||
NULL,
|
||||
EblFileCopyCmd
|
||||
},
|
||||
{
|
||||
"diff",
|
||||
" file1 file2; compare files",
|
||||
NULL,
|
||||
EblFileDiffCmd
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Initialize the commands in this in this file
|
||||
**/
|
||||
|
||||
VOID
|
||||
EblInitializeDeviceCmd (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS);
|
||||
EblAddCommands (mCmdDeviceTemplate, sizeof (mCmdDeviceTemplate)/sizeof (EBL_COMMAND_TABLE));
|
||||
}
|
||||
|
Reference in New Issue
Block a user