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; }
/** 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; }
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; }
/** 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; }