In the previous version, this command was not working: cp fs0:\zImage fs1:\ This change uses the source filename is the destination filename is not specified. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12406 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1051 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1051 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  EBL commands for EFI and PI Devices
 | 
						|
 | 
						|
  Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
 | 
						|
  Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
 | 
						|
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR16 *Str;
 | 
						|
 | 
						|
  if (File == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  AsciiPrint ("  %a: ", File->DeviceName);
 | 
						|
  if (File->FsInfo != NULL) {
 | 
						|
    for (Str = File->FsInfo->VolumeLabel; *Str != '\0'; Str++) {
 | 
						|
      if (*Str == ' ') {
 | 
						|
        // UI makes you enter _ for space, so make the printout match that
 | 
						|
        *Str = '_';
 | 
						|
      }
 | 
						|
      AsciiPrint ("%c", *Str);
 | 
						|
    }
 | 
						|
    AsciiPrint (":");
 | 
						|
    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;
 | 
						|
  UINTN                     Index;
 | 
						|
  UINTN                     Max;
 | 
						|
  EFI_OPEN_FILE             *FsFile;
 | 
						|
 | 
						|
  if (File == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  AsciiPrint ("  %a: ", File->DeviceName);
 | 
						|
 | 
						|
  // print out name of file system, if any, on this block device
 | 
						|
  Max = EfiGetDeviceCounts (EfiOpenFileSystem);
 | 
						|
  if (Max != 0) {
 | 
						|
    for (Index = 0; Index < Max; Index++) {
 | 
						|
      FsFile = EfiDeviceOpenByType (EfiOpenFileSystem, Index);
 | 
						|
      if (FsFile != NULL) {
 | 
						|
        if (FsFile->EfiHandle == File->EfiHandle) {
 | 
						|
          AsciiPrint ("fs%d: ", Index);
 | 
						|
          EfiClose (FsFile);
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        EfiClose (FsFile);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Print out useful Block IO media properties
 | 
						|
  if (File->FsBlockIoMedia->RemovableMedia) {
 | 
						|
    AsciiPrint ("Removable ");
 | 
						|
  }
 | 
						|
  if (!File->FsBlockIoMedia->MediaPresent) {
 | 
						|
    AsciiPrint ("No Media\n");
 | 
						|
  } else {
 | 
						|
    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 command 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 ();
 | 
						|
 | 
						|
  // Now we can print out the info...
 | 
						|
  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 command 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 dependencies 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 command 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);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      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
 | 
						|
  available 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 command 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 command 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 address 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 command 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 command 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 relative 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;
 | 
						|
  UINTN         FileNameLen;
 | 
						|
  CHAR8*        DestFileName;
 | 
						|
  CHAR8*        SrcFileName;
 | 
						|
  CHAR8*        SrcPtr;
 | 
						|
 | 
						|
  if (Argc < 3) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  
 | 
						|
  DestFileName = Argv[2];
 | 
						|
  FileNameLen = AsciiStrLen (DestFileName);
 | 
						|
 | 
						|
  // Check if the destination file name looks like a directory
 | 
						|
  if ((DestFileName[FileNameLen-1] == '\\') || (DestFileName[FileNameLen-1] == ':')) {
 | 
						|
    // Set the pointer after the source drive (eg: after fs1:)
 | 
						|
    SrcPtr = AsciiStrStr (Argv[1], ":");
 | 
						|
    if (SrcPtr == NULL) {
 | 
						|
      SrcPtr = Argv[1];
 | 
						|
    } else {
 | 
						|
      SrcPtr++;
 | 
						|
      if (*SrcPtr == '\\') {
 | 
						|
        SrcPtr++;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (*SrcPtr == '\0') {
 | 
						|
      AsciiPrint("Source file incorrect.\n");
 | 
						|
    }
 | 
						|
 | 
						|
    // Skip the Source Directories
 | 
						|
    while (1) {
 | 
						|
      SrcFileName = SrcPtr;
 | 
						|
      SrcPtr = AsciiStrStr (SrcPtr,"\\");
 | 
						|
      if (SrcPtr != NULL) {
 | 
						|
        SrcPtr++;
 | 
						|
      } else {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (*SrcFileName == '\0') {
 | 
						|
      AsciiPrint("Source file incorrect (Error 2).\n");
 | 
						|
    }
 | 
						|
 | 
						|
    // Construct the destination filepath
 | 
						|
    DestFileName = (CHAR8*)AllocatePool (FileNameLen + AsciiStrLen (SrcFileName) + 1);
 | 
						|
    AsciiStrCpy (DestFileName, Argv[2]);
 | 
						|
    AsciiStrCat (DestFileName, SrcFileName);
 | 
						|
  }
 | 
						|
 | 
						|
  Source = EfiOpen(Argv[1], EFI_FILE_MODE_READ, 0);
 | 
						|
  if (Source == NULL) {
 | 
						|
    AsciiPrint("Source file open error.\n");
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  
 | 
						|
  Destination = EfiOpen(DestFileName, 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 %r\n", Status);
 | 
						|
      goto Exit;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = EfiWrite(Destination, Buffer, &Chunk);
 | 
						|
    if (EFI_ERROR(Status)) {
 | 
						|
      AsciiPrint("Write file error %r\n", Status);
 | 
						|
      goto Exit;
 | 
						|
    }    
 | 
						|
  }
 | 
						|
  
 | 
						|
  // Any left over?
 | 
						|
  if (Offset < Size) {
 | 
						|
    Chunk = Size - Offset;
 | 
						|
    
 | 
						|
    Status = EfiRead(Source, Buffer, &Chunk);
 | 
						|
    if (EFI_ERROR(Status)) {
 | 
						|
      AsciiPrint("Read file error %r\n", Status);
 | 
						|
      goto Exit;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = EfiWrite(Destination, Buffer, &Chunk);
 | 
						|
    if (EFI_ERROR(Status)) {
 | 
						|
      AsciiPrint("Write file error %r\n", Status);
 | 
						|
      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);
 | 
						|
    }
 | 
						|
 | 
						|
    // Case when we have concated the filename to the destination directory
 | 
						|
    if (DestFileName != Argv[2]) {
 | 
						|
      FreePool (DestFileName);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  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 only.",
 | 
						|
    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));
 | 
						|
}
 | 
						|
 |