Пример #1
0
/**
  Send null requests to all removable media block IO devices so the a media add/remove/change
  can be detected in real before we execute a command.

  This is mainly due to the fact that the FAT driver does not do this today so you can get stale
  dir commands after an SD Card has been removed.
**/
VOID
EblProbeRemovableMedia (
  VOID
  )
{
  UINTN         Index;
  UINTN         Max;
  EFI_OPEN_FILE *File;

  //
  // Probe for media insertion/removal in removable media devices
  //
  Max = EfiGetDeviceCounts (EfiOpenBlockIo);
  if (Max != 0) {
    for (Index = 0; Index < Max; Index++) {
      File = EfiDeviceOpenByType (EfiOpenBlockIo, Index);
      if (File != NULL) {
        if (File->FsBlockIoMedia->RemovableMedia) {
          // Probe to see if media is present (or not) or media changed
          //  this causes the ReinstallProtocolInterface() to fire in the
          //  block io driver to update the system about media change events
          File->FsBlockIo->ReadBlocks (File->FsBlockIo, File->FsBlockIo->Media->MediaId, (EFI_LBA)0, 0, NULL);
        }
        EfiClose (File);
      }
    }
  }
}
Пример #2
0
/**
  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);
}
Пример #3
0
/**
  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);
}
Пример #4
0
/**
  Execute the passed in file like a series of commands. The ; can be used on
  a single line to indicate multiple commands per line. The Ascii text file 
  can contain any number of lines. The following line termination forms are 
  supported:
    LF   : Unix, Mac OS X*, BeOS
    CR+LF: MS-DOS*, Microsoft Windows*
    CR   : Commodore, Apple II, and really Mac OS
    LF+CR: for simplicity and completeness 

  Argv[0] - "script"
  Argv[1] - Device Name:path for the file to load

  script fv1:\script.txt

  @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
EblScriptCmd (
  IN UINTN  Argc,
  IN CHAR8  **Argv
  )
{
  EFI_STATUS                    Status;
  EFI_OPEN_FILE                 *File;
  VOID                          *Address;
  UINTN                         Size;
  CHAR8                         *Ptr;
  CHAR8                         *ScanPtr;
  UINTN                         CmdLineSize;
  
  

  if (Argc < 2) {
    // file name 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;
  }

  Status = EfiReadAllocatePool (File, &Address, &Size);
  if (!EFI_ERROR (Status)) {
    // Loop through each line in the text file
    for (Ptr = (CHAR8 *)Address; (Ptr < (((CHAR8 *)Address) + Size)) && !EFI_ERROR (Status); Ptr += CmdLineSize) {
      for (CmdLineSize = 0, ScanPtr = Ptr; ; CmdLineSize++, ScanPtr++) {
        // look for the end of the line
        if ((*ScanPtr == EBL_CR) || (*ScanPtr == EBL_LF)) {
          // convert to NULL as this is what input routine would do
          *ScanPtr = 0;
          if ((*(ScanPtr + 1) == EBL_CR) || (*(ScanPtr + 1) == EBL_LF)) {
            // if its a set get the 2nd EOL char
            CmdLineSize++;
            *(ScanPtr + 1) = 0;
          }
          CmdLineSize++;
          break;
        }
        
      }

      Status = ProcessCmdLine (Ptr, CmdLineSize);
    }
  
    FreePool (Address);
  }
 
  EfiClose (File);
  return Status;
}
Пример #5
0
/**
  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);
}
Пример #6
0
 /**
  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;
}
Пример #7
0
/**
  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;
}
Пример #8
0
EFI_STATUS
EfiCopyFile (
  IN        CHAR8               *DestinationFile,
  IN        CHAR8               *SourceFile
  )
{
  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;

  Source = EfiOpen (SourceFile, EFI_FILE_MODE_READ, 0);
  if (Source == NULL) {
    AsciiPrint("Source file open error.\n");
    Status = EFI_NOT_FOUND;
    goto Exit;
  }

  Destination = EfiOpen (DestinationFile, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0);
  if (Destination == NULL) {
    AsciiPrint("Destination file open error.\n");
    Status = EFI_NOT_FOUND;
    goto Exit;
  }

  Buffer = AllocatePool(FILE_COPY_CHUNK);
  if (Buffer == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    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\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");
    }
  }

  if (Destination != NULL) {
    Status = EfiClose(Destination);
    if (EFI_ERROR(Status)) {
      AsciiPrint("Destination close error");
    }
  }

  if (Buffer != NULL) {
    FreePool(Buffer);
  }

  return Status;
}
Пример #9
0
/**
  Perform a dir on a device. The device must support Simple File System Protocol
  or the FV protocol.

  Argv[0] - "dir"
  Argv[1] - Device Name:path. Path is optional
  Argv[2] - Optional filename to match on. A leading * means match substring
  Argv[3] - Optional FV file type

  dir fs1:\efi      ; perform a dir on fs1: device in the efi directory
  dir fs1:\efi *.efi; perform a dir on fs1: device in the efi directory but
                      only print out files that contain the string *.efi
  dir fv1:\         ; perform a dir on fv1: device in the efi directory
                    NOTE: fv devices do not contain subdirs
  dir fv1:\ * PEIM  ; will match all files of type PEIM

  @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
EblDirCmd (
    IN UINTN  Argc,
    IN CHAR8  **Argv
)
{
    EFI_STATUS                    Status;
    EFI_OPEN_FILE                 *File;
    EFI_FILE_INFO                 *DirInfo;
    UINTN                         ReadSize;
    UINTN                         CurrentRow;
    CHAR16                        *MatchSubString;
    EFI_STATUS                    GetNextFileStatus;
    UINTN                         Key;
    EFI_FV_FILETYPE               SearchType;
    EFI_FV_FILETYPE               Type;
    EFI_FV_FILE_ATTRIBUTES        Attributes;
    UINTN                         Size;
    EFI_GUID                      NameGuid;
    EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
    UINT32                        AuthenticationStatus;
    VOID                          *Section;
    UINTN                         SectionSize;
    EFI_FV_FILETYPE               Index;
    UINTN                         Length;
    UINTN                         BestMatchCount;
    CHAR16                        UnicodeFileName[MAX_CMD_LINE];
    CHAR8                         *Path;
    CHAR8                         *TypeStr;
    UINTN                         TotalSize;


    if (Argc <= 1) {
        Path = EfiGetCwd ();
        if (Path == NULL) {
            return EFI_SUCCESS;
        }
    } else {
        Path = Argv[1];
    }

    File = EfiOpen (Path, EFI_FILE_MODE_READ, 0);
    if (File == NULL) {
        return EFI_SUCCESS;
    }

    if (File->Type == EfiOpenFirmwareVolume) {
        // FV Dir

        SearchType = EFI_FV_FILETYPE_ALL;
        UnicodeFileName[0] = '\0';
        MatchSubString = &UnicodeFileName[0];
        if (Argc > 2) {
            AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);
            if (UnicodeFileName[0] == '*') {
                // Handle *Name substring matching
                MatchSubString = &UnicodeFileName[1];
            }

            // Handle file type matchs
            if (Argc > 3) {
                // match a specific file type, always last argument
                Length = AsciiStrLen (Argv[3]);
                for (Index = 1, BestMatchCount = 0; Index < sizeof (gFvFileType)/sizeof (CHAR8 *); Index++) {
                    if (AsciiStriCmp (gFvFileType[Index], Argv[3]) == 0) {
                        // exact match
                        SearchType = Index;
                        break;
                    }

                    if (AsciiStrniCmp (Argv[3], gFvFileType[Index], Length) == 0) {
                        // partial match, so keep looking to make sure there is only one partial match
                        BestMatchCount++;
                        SearchType = Index;
                    }
                }

                if (BestMatchCount > 1) {
                    SearchType = EFI_FV_FILETYPE_ALL;
                }
            }
        }

        TotalSize = 0;
        Fv = File->Fv;
        Key = 0;
        CurrentRow = 0;
        do {
            Type = SearchType;
            GetNextFileStatus = Fv->GetNextFile (
                                    Fv,
                                    &Key,
                                    &Type,
                                    &NameGuid,
                                    &Attributes,
                                    &Size
                                );
            if (!EFI_ERROR (GetNextFileStatus)) {
                TotalSize += Size;
                // Calculate size of entire file
                Section = NULL;
                Size = 0;
                Status = Fv->ReadFile (
                             Fv,
                             &NameGuid,
                             Section,
                             &Size,
                             &Type,
                             &Attributes,
                             &AuthenticationStatus
                         );
                if (!((Status == EFI_BUFFER_TOO_SMALL) || !EFI_ERROR (Status))) {
                    // EFI_SUCCESS or EFI_BUFFER_TOO_SMALL mean size is valid
                    Size = 0;
                }

                TypeStr = (Type <= EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) ? gFvFileType[Type] : "UNKNOWN";

                // read the UI seciton to do a name match.
                Section = NULL;
                Status = Fv->ReadSection (
                             Fv,
                             &NameGuid,
                             EFI_SECTION_USER_INTERFACE,
                             0,
                             &Section,
                             &SectionSize,
                             &AuthenticationStatus
                         );
                if (!EFI_ERROR (Status)) {
                    if (StrStr (Section, MatchSubString) != NULL) {
                        AsciiPrint ("%,9d %7a %g %s\n", Size, TypeStr, &NameGuid, Section);
                        if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
                            break;
                        }
                    }
                    FreePool (Section);
                } else {
                    if (*MatchSubString == '\0') {
                        AsciiPrint ("%,9d %7a %g\n", Size, TypeStr, &NameGuid);
                        if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
                            break;
                        }
                    }
                }
            }
        } while (!EFI_ERROR (GetNextFileStatus));

        if (SearchType == EFI_FV_FILETYPE_ALL) {
            AsciiPrint ("%,20d bytes in files %,d bytes free\n", TotalSize, File->FvSize - File->FvHeaderSize - TotalSize);
        }


    } else if ((File->Type == EfiOpenFileSystem) || (File->Type == EfiOpenBlockIo)) {
        // Simple File System DIR

        if (File->FsFileInfo ==  NULL) {
            return EFI_SUCCESS;
        }

        if (!(File->FsFileInfo->Attribute & EFI_FILE_DIRECTORY)) {
            return EFI_SUCCESS;
        }

        // Handle *Name substring matching
        MatchSubString = NULL;
        UnicodeFileName[0] = '\0';
        if (Argc > 2) {
            AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);
            if (UnicodeFileName[0] == '*') {
                MatchSubString = &UnicodeFileName[1];
            }
        }

        File->FsFileHandle->SetPosition (File->FsFileHandle, 0);
        for (CurrentRow = 0;;) {
            // First read gets the size
            DirInfo = NULL;
            ReadSize = 0;
            Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);
            if (Status == EFI_BUFFER_TOO_SMALL) {
                // Allocate the buffer for the real read
                DirInfo = AllocatePool (ReadSize);
                if (DirInfo == NULL) {
                    goto Done;
                }

                // Read the data
                Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);
                if ((EFI_ERROR (Status)) || (ReadSize == 0)) {
                    break;
                }
            } else {
                break;
            }

            if (MatchSubString != NULL) {
                if (StrStr (&DirInfo->FileName[0], MatchSubString) == NULL) {
                    // does not match *name argument, so skip
                    continue;
                }
            } else if (UnicodeFileName[0] != '\0') {
                // is not an exact match for name argument, so skip
                if (StrCmp (&DirInfo->FileName[0], UnicodeFileName) != 0) {
                    continue;
                }
            }

            if (DirInfo->Attribute & EFI_FILE_DIRECTORY) {
                AsciiPrint ("         <DIR> %s\n", &DirInfo->FileName[0]);
            } else {
                AsciiPrint ("%,14ld %s\n", DirInfo->FileSize, &DirInfo->FileName[0]);
            }

            if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
                break;
            }

            FreePool (DirInfo);
        }

Done:
        if (DirInfo != NULL) {
            FreePool (DirInfo);
        }
    }

    EfiClose (File);

    return EFI_SUCCESS;
}
Пример #10
0
/**
  Toggle page break global. This turns on and off prompting to Quit or hit any
  key to continue when a command is about to scroll the screen with its output

  Argv[0] - "hexdump"[.#]  # is optional 1,2, or 4 for width
  Argv[1] - Device or File to dump.
  Argv[2] - Optional offset to start dumping
  Argv[3] - Optional number of bytes to dump

  @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
EFIAPI
EblHexdumpCmd (
  IN UINTN  Argc,
  IN CHAR8  **Argv
  )
{
  EFI_OPEN_FILE *File;
  VOID          *Location;
  UINTN         Size;
  UINTN         Width;
  UINTN         Offset = 0;
  EFI_STATUS    Status;
  UINTN         Chunk = HEXDUMP_CHUNK;

  if ((Argc < 2) || (Argc > 4)) {
    return EFI_INVALID_PARAMETER;
  }

  Width = WidthFromCommandName (Argv[0], 1);
  if ((Width != 1) && (Width != 2) && (Width != 4)) {
    return EFI_INVALID_PARAMETER;
  }

  File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
  if (File == NULL) {
    return EFI_NOT_FOUND;
  }

  Location = AllocatePool (Chunk);
  Size     = (Argc > 3) ? AsciiStrHexToUintn (Argv[3]) : EfiTell (File, NULL);

  Offset = 0;
  if (Argc > 2) {
    Offset = AsciiStrHexToUintn (Argv[2]);
    if (Offset > 0) {
      // Make sure size includes the part of the file we have skipped
      Size += Offset;
    }
  }

  Status = EfiSeek (File, Offset, EfiSeekStart);
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  for (; Offset + HEXDUMP_CHUNK <= Size; Offset += Chunk) {
    Chunk = HEXDUMP_CHUNK;
    Status = EfiRead (File, Location, &Chunk);
    if (EFI_ERROR(Status)) {
      AsciiPrint ("Error reading file content\n");
      goto Exit;
    }

    Status = OutputData (Location, Chunk, Width, File->BaseOffset + Offset);
    if (EFI_ERROR(Status)) {
      if (Status == EFI_END_OF_FILE) {
        Status = EFI_SUCCESS;
      }
      goto Exit;
    }
  }

  // Any left over?
  if (Offset < Size) {
    Chunk = Size - Offset;
    Status = EfiRead (File, Location, &Chunk);
    if (EFI_ERROR(Status)) {
      AsciiPrint ("Error reading file content\n");
      goto Exit;
    }

    Status = OutputData (Location, Chunk, Width, File->BaseOffset + Offset);
    if (EFI_ERROR(Status)) {
      if (Status == EFI_END_OF_FILE) {
        Status = EFI_SUCCESS;
      }
      goto Exit;
    }
  }

Exit:
  EfiClose (File);

  FreePool (Location);

  return EFI_SUCCESS;
}
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
/**
  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;
}
Пример #14
0
/**
  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;
}
Пример #15
0
/**
  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;
}