STATIC EFI_STATUS PrepareFirmwareImage ( IN LIST_ENTRY *CheckPackage, IN OUT SHELL_FILE_HANDLE *FileHandle, IN OUT UINTN **FileBuffer, IN OUT UINT64 *FileSize ) { CONST CHAR16 *FileStr; EFI_STATUS Status; UINT64 OpenMode; UINTN *Buffer; // Parse string from commandline FileStr = ShellCommandLineGetRawValue (CheckPackage, 1); if (FileStr == NULL) { Print (L"%s: No image specified\n", CMD_NAME_STRING); return EFI_INVALID_PARAMETER; } else { Status = ShellIsFile (FileStr); if (EFI_ERROR(Status)) { Print (L"%s: File not found\n", CMD_NAME_STRING); return EFI_INVALID_PARAMETER; } } // Obtain file size OpenMode = EFI_FILE_MODE_READ; Status = ShellOpenFileByName (FileStr, FileHandle, OpenMode, 0); if (EFI_ERROR (Status)) { Print (L"%s: Cannot open Image file\n", CMD_NAME_STRING); return EFI_DEVICE_ERROR; } Status = FileHandleGetSize (*FileHandle, FileSize); if (EFI_ERROR (Status)) { Print (L"%s: Cannot get Image file size\n", CMD_NAME_STRING); } // Read Image header into buffer Buffer = AllocateZeroPool (*FileSize); Status = FileHandleRead (*FileHandle, (UINTN *)FileSize, Buffer); if (EFI_ERROR (Status)) { Print (L"%s: Cannot read Image file header\n", CMD_NAME_STRING); ShellCloseFile (FileHandle); FreePool (Buffer); return EFI_DEVICE_ERROR; } *FileBuffer = Buffer; return EFI_SUCCESS; }
EFI_STATUS UtilReadFileToMemory ( EFI_FILE_PROTOCOL *File, VOID **OutBuffer, UINTN *OutSize ) { EFI_STATUS Status; UINT64 FileSize = 0; VOID *Buffer = NULL; UINTN ReadSize; if(!File) return EFI_INVALID_PARAMETER; // get size Status = FileHandleGetSize(File, &FileSize); if (EFI_ERROR (Status)) { return Status; } // allocate buffer Buffer = AllocatePool(FileSize); if (Buffer==NULL) return EFI_OUT_OF_RESOURCES; // read data ReadSize = (UINTN) FileSize; Status = FileHandleRead(File, &ReadSize, Buffer); if (EFI_ERROR (Status)) { FreePool (Buffer); return Status; } *OutBuffer = Buffer; *OutSize = ReadSize; return EFI_SUCCESS; }
/** Function to read a single line (up to but not including the \n) from a file. If the position upon start is 0, then the Ascii Boolean will be set. This should be maintained and not changed for all operations with the same file. The function will not return the \r and \n character in buffer. When an empty line is read a CHAR_NULL character will be returned in buffer. @param[in] Handle FileHandle to read from. @param[in, out] Buffer The pointer to buffer to read into. @param[in, out] Size The pointer to number of bytes in Buffer. @param[in] Truncate If the buffer is large enough, this has no effect. If the buffer is is too small and Truncate is TRUE, the line will be truncated. If the buffer is is too small and Truncate is FALSE, then no read will occur. @param[in, out] Ascii Boolean value for indicating whether the file is Ascii (TRUE) or UCS2 (FALSE). @retval EFI_SUCCESS The operation was successful. The line is stored in Buffer. @retval EFI_INVALID_PARAMETER Handle was NULL. @retval EFI_INVALID_PARAMETER Size was NULL. @retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line. Size was updated to the minimum space required. @sa FileHandleRead **/ EFI_STATUS EFIAPI FileHandleReadLine( IN EFI_FILE_HANDLE Handle, IN OUT CHAR16 *Buffer, IN OUT UINTN *Size, IN BOOLEAN Truncate, IN OUT BOOLEAN *Ascii ) { EFI_STATUS Status; CHAR16 CharBuffer; UINT64 FileSize; UINTN CharSize; UINTN CountSoFar; UINTN CrCount; UINT64 OriginalFilePosition; if (Handle == NULL ||Size == NULL ||(Buffer==NULL&&*Size!=0) ){ return (EFI_INVALID_PARAMETER); } if (Buffer != NULL && *Size != 0) { *Buffer = CHAR_NULL; } Status = FileHandleGetSize (Handle, &FileSize); if (EFI_ERROR (Status)) { return Status; } else if (FileSize == 0) { *Ascii = TRUE; return EFI_SUCCESS; } FileHandleGetPosition(Handle, &OriginalFilePosition); if (OriginalFilePosition == 0) { CharSize = sizeof(CHAR16); Status = FileHandleRead(Handle, &CharSize, &CharBuffer); ASSERT_EFI_ERROR(Status); if (CharBuffer == gUnicodeFileTag) { *Ascii = FALSE; } else { *Ascii = TRUE; FileHandleSetPosition(Handle, OriginalFilePosition); } } CrCount = 0; for (CountSoFar = 0;;CountSoFar++){ CharBuffer = 0; if (*Ascii) { CharSize = sizeof(CHAR8); } else { CharSize = sizeof(CHAR16); } Status = FileHandleRead(Handle, &CharSize, &CharBuffer); if ( EFI_ERROR(Status) || CharSize == 0 || (CharBuffer == L'\n' && !(*Ascii)) || (CharBuffer == '\n' && *Ascii) ){ break; } else if ( (CharBuffer == L'\r' && !(*Ascii)) || (CharBuffer == '\r' && *Ascii) ) { CrCount++; continue; } // // if we have space save it... // if ((CountSoFar+1-CrCount)*sizeof(CHAR16) < *Size){ ASSERT(Buffer != NULL); ((CHAR16*)Buffer)[CountSoFar-CrCount] = CharBuffer; ((CHAR16*)Buffer)[CountSoFar+1-CrCount] = CHAR_NULL; } } // // if we ran out of space tell when... // if ((CountSoFar+1-CrCount)*sizeof(CHAR16) > *Size){ *Size = (CountSoFar+1-CrCount)*sizeof(CHAR16); if (!Truncate) { if (Buffer != NULL && *Size != 0) { ZeroMem(Buffer, *Size); } FileHandleSetPosition(Handle, OriginalFilePosition); return (EFI_BUFFER_TOO_SMALL); } else { DEBUG((DEBUG_WARN, "The line was truncated in FileHandleReadLine")); return (EFI_SUCCESS); } } return (Status); }
/** Function to write a line of text to a file. If the file is a Unicode file (with UNICODE file tag) then write the unicode text. If the file is an ASCII file then write the ASCII text. If the size of file is zero (without file tag at the beginning) then write ASCII text as default. @param[in] Handle FileHandle to write to. @param[in] Buffer Buffer to write, if NULL the function will take no action and return EFI_SUCCESS. @retval EFI_SUCCESS The data was written. Buffer is NULL. @retval EFI_INVALID_PARAMETER Handle is NULL. @retval EFI_OUT_OF_RESOURCES Unable to allocate temporary space for ASCII string due to out of resources. @sa FileHandleWrite **/ EFI_STATUS EFIAPI FileHandleWriteLine( IN EFI_FILE_HANDLE Handle, IN CHAR16 *Buffer ) { EFI_STATUS Status; CHAR16 CharBuffer; UINTN Size; UINTN Index; UINTN CharSize; UINT64 FileSize; UINT64 OriginalFilePosition; BOOLEAN Ascii; CHAR8 *AsciiBuffer; if (Buffer == NULL) { return (EFI_SUCCESS); } if (Handle == NULL) { return (EFI_INVALID_PARAMETER); } Ascii = FALSE; AsciiBuffer = NULL; Status = FileHandleGetPosition(Handle, &OriginalFilePosition); if (EFI_ERROR(Status)) { return Status; } Status = FileHandleSetPosition(Handle, 0); if (EFI_ERROR(Status)) { return Status; } Status = FileHandleGetSize(Handle, &FileSize); if (EFI_ERROR(Status)) { return Status; } if (FileSize == 0) { Ascii = TRUE; } else { CharSize = sizeof (CHAR16); Status = FileHandleRead (Handle, &CharSize, &CharBuffer); ASSERT_EFI_ERROR (Status); if (CharBuffer == gUnicodeFileTag) { Ascii = FALSE; } else { Ascii = TRUE; } } Status = FileHandleSetPosition(Handle, OriginalFilePosition); if (EFI_ERROR(Status)) { return Status; } if (Ascii) { Size = ( StrSize(Buffer) / sizeof(CHAR16) ) * sizeof(CHAR8); AsciiBuffer = (CHAR8 *)AllocateZeroPool(Size); if (AsciiBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } UnicodeStrToAsciiStrS (Buffer, AsciiBuffer, Size); for (Index = 0; Index < Size; Index++) { if (!((AsciiBuffer[Index] >= 0) && (AsciiBuffer[Index] < 128))){ FreePool(AsciiBuffer); return EFI_INVALID_PARAMETER; } } Size = AsciiStrSize(AsciiBuffer) - sizeof(CHAR8); Status = FileHandleWrite(Handle, &Size, AsciiBuffer); if (EFI_ERROR(Status)) { FreePool (AsciiBuffer); return (Status); } Size = AsciiStrSize("\r\n") - sizeof(CHAR8); Status = FileHandleWrite(Handle, &Size, "\r\n"); } else { if (OriginalFilePosition == 0) { Status = FileHandleSetPosition (Handle, sizeof(CHAR16)); if (EFI_ERROR(Status)) { return Status; } } Size = StrSize(Buffer) - sizeof(CHAR16); Status = FileHandleWrite(Handle, &Size, Buffer); if (EFI_ERROR(Status)) { return (Status); } Size = StrSize(L"\r\n") - sizeof(CHAR16); Status = FileHandleWrite(Handle, &Size, L"\r\n"); } if (AsciiBuffer != NULL) { FreePool (AsciiBuffer); } return Status; }
/** Function for 'decompress' command. @param[in] ImageHandle Handle to the Image (NULL if Internal). @param[in] SystemTable Pointer to the System Table (NULL if Internal). **/ SHELL_STATUS EFIAPI ShellCommandRunEfiDecompress ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; LIST_ENTRY *Package; CHAR16 *ProblemParam; SHELL_STATUS ShellStatus; SHELL_FILE_HANDLE InFileHandle; SHELL_FILE_HANDLE OutFileHandle; UINT32 OutSize; UINTN OutSizeTemp; VOID *OutBuffer; UINTN InSize; VOID *InBuffer; CHAR16 *InFileName; CONST CHAR16 *OutFileName; UINT64 Temp64Bit; UINT32 ScratchSize; VOID *ScratchBuffer; EFI_DECOMPRESS_PROTOCOL *Decompress; CONST CHAR16 *TempParam; InFileName = NULL; OutFileName = NULL; OutSize = 0; ShellStatus = SHELL_SUCCESS; Status = EFI_SUCCESS; OutBuffer = NULL; InBuffer = NULL; ScratchBuffer = NULL; InFileHandle = NULL; OutFileHandle = NULL; // // initialize the shell lib (we must be in non-auto-init...) // Status = ShellInitialize(); ASSERT_EFI_ERROR(Status); Status = CommandInit(); ASSERT_EFI_ERROR(Status); // // parse the command line // Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE); if (EFI_ERROR(Status)) { if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam); FreePool(ProblemParam); ShellStatus = SHELL_INVALID_PARAMETER; } else { ASSERT(FALSE); } } else { if (ShellCommandLineGetCount(Package) > 3) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; } else if (ShellCommandLineGetCount(Package) < 3) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle); ShellStatus = SHELL_INVALID_PARAMETER; } else { TempParam = ShellCommandLineGetRawValue(Package, 1); ASSERT(TempParam != NULL); InFileName = ShellFindFilePath(TempParam); OutFileName = ShellCommandLineGetRawValue(Package, 2); if (InFileName == NULL) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, TempParam); ShellStatus = SHELL_NOT_FOUND; } else { if (ShellIsDirectory(InFileName) == EFI_SUCCESS){ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, InFileName); ShellStatus = SHELL_INVALID_PARAMETER; } if (ShellIsDirectory(OutFileName) == EFI_SUCCESS){ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, OutFileName); ShellStatus = SHELL_INVALID_PARAMETER; } if (ShellStatus == SHELL_SUCCESS) { Status = ShellOpenFileByName(InFileName, &InFileHandle, EFI_FILE_MODE_READ, 0); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_OPEN_FAIL), gShellDebug1HiiHandle, ShellCommandLineGetRawValue(Package, 1), Status); ShellStatus = SHELL_NOT_FOUND; } Status = ShellOpenFileByName(OutFileName, &OutFileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_OPEN_FAIL), gShellDebug1HiiHandle, ShellCommandLineGetRawValue(Package, 2), Status); ShellStatus = SHELL_NOT_FOUND; } } if (ShellStatus == SHELL_SUCCESS) { Status = FileHandleGetSize(InFileHandle, &Temp64Bit); ASSERT(Temp64Bit <= (UINT32)(-1)); InSize = (UINTN)Temp64Bit; ASSERT_EFI_ERROR(Status); InBuffer = AllocateZeroPool(InSize); ASSERT(InBuffer != NULL); Status = gEfiShellProtocol->ReadFile(InFileHandle, &InSize, InBuffer); ASSERT_EFI_ERROR(Status); Status = gBS->LocateProtocol(&gEfiDecompressProtocolGuid, NULL, (VOID**)&Decompress); ASSERT_EFI_ERROR(Status); Status = Decompress->GetInfo(Decompress, InBuffer, (UINT32)InSize, &OutSize, &ScratchSize); ASSERT_EFI_ERROR(Status); OutBuffer = AllocateZeroPool(OutSize); ScratchBuffer = AllocateZeroPool(ScratchSize); ASSERT(OutBuffer != NULL); ASSERT(ScratchBuffer != NULL); Status = Decompress->Decompress(Decompress, InBuffer, (UINT32)InSize, OutBuffer, OutSize, ScratchBuffer, ScratchSize); ASSERT_EFI_ERROR(Status); if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_EFI_DECOMPRESS_FAIL), gShellDebug1HiiHandle, Status); ShellStatus = SHELL_DEVICE_ERROR; } else { OutSizeTemp = OutSize; Status = gEfiShellProtocol->WriteFile(OutFileHandle, &OutSizeTemp, OutBuffer); OutSize = (UINT32)OutSizeTemp; if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_WRITE_FAIL), gShellDebug1HiiHandle, OutFileName, Status); ShellStatus = SHELL_DEVICE_ERROR; } } } } } ShellCommandLineFreeVarList (Package); } if (InFileHandle != NULL) { gEfiShellProtocol->CloseFile(InFileHandle); } if (OutFileHandle != NULL) { gEfiShellProtocol->CloseFile(OutFileHandle); } SHELL_FREE_NON_NULL(InFileName); SHELL_FREE_NON_NULL(InBuffer); SHELL_FREE_NON_NULL(OutBuffer); SHELL_FREE_NON_NULL(ScratchBuffer); return (ShellStatus); }
/** Dump capsule information from disk. @param[in] Fs The device path of disk. @param[in] DumpCapsuleInfo The flag to indicate whether to dump the capsule inforomation. @retval EFI_SUCCESS The capsule information is dumped. **/ EFI_STATUS DumpCapsuleFromDisk ( IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs, IN BOOLEAN DumpCapsuleInfo ) { EFI_STATUS Status; EFI_FILE *Root; EFI_FILE *DirHandle; EFI_FILE *FileHandle; UINTN Index; UINTN FileSize; VOID *FileBuffer; EFI_FILE_INFO **FileInfoBuffer; EFI_FILE_INFO *FileInfo; UINTN FileCount; BOOLEAN NoFile; DirHandle = NULL; FileHandle = NULL; Index = 0; FileInfoBuffer = NULL; FileInfo = NULL; FileCount = 0; NoFile = FALSE; Status = Fs->OpenVolume (Fs, &Root); if (EFI_ERROR (Status)) { Print (L"Cannot open volume. Status = %r\n", Status); goto Done; } Status = Root->Open (Root, &DirHandle, EFI_CAPSULE_FILE_DIRECTORY, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE , 0); if (EFI_ERROR (Status)) { Print (L"Cannot open %s. Status = %r\n", EFI_CAPSULE_FILE_DIRECTORY, Status); goto Done; } // // Get file count first // do { Status = FileHandleFindFirstFile (DirHandle, &FileInfo); if (EFI_ERROR (Status) || FileInfo == NULL) { Print (L"Get File Info Fail. Status = %r\n", Status); goto Done; } if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) != 0) { FileCount++; } Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile); if (EFI_ERROR (Status)) { Print (L"Get Next File Fail. Status = %r\n", Status); goto Done; } } while (!NoFile); if (FileCount == 0) { Print (L"Error: No capsule file found!\n"); Status = EFI_NOT_FOUND; goto Done; } FileInfoBuffer = AllocateZeroPool (sizeof (FileInfo) * FileCount); if (FileInfoBuffer == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } NoFile = FALSE; // // Get all file info // do { Status = FileHandleFindFirstFile (DirHandle, &FileInfo); if (EFI_ERROR (Status) || FileInfo == NULL) { Print (L"Get File Info Fail. Status = %r\n", Status); goto Done; } if ((FileInfo->Attribute & (EFI_FILE_SYSTEM | EFI_FILE_ARCHIVE)) != 0) { FileInfoBuffer[Index++] = AllocateCopyPool ((UINTN)FileInfo->Size, FileInfo); } Status = FileHandleFindNextFile (DirHandle, FileInfo, &NoFile); if (EFI_ERROR (Status)) { Print (L"Get Next File Fail. Status = %r\n", Status); goto Done; } } while (!NoFile); // // Sort FileInfoBuffer by alphabet order // PerformQuickSort ( FileInfoBuffer, FileCount, sizeof (FileInfo), (SORT_COMPARE) CompareFileNameInAlphabet ); Print (L"The capsules will be performed by following order:\n"); for (Index = 0; Index < FileCount; Index++) { Print (L" %d.%s\n", Index + 1, FileInfoBuffer[Index]->FileName); } if (!DumpCapsuleInfo) { Status = EFI_SUCCESS; goto Done; } Print(L"The infomation of the capsules:\n"); for (Index = 0; Index < FileCount; Index++) { FileHandle = NULL; Status = DirHandle->Open (DirHandle, &FileHandle, FileInfoBuffer[Index]->FileName, EFI_FILE_MODE_READ, 0); if (EFI_ERROR (Status)) { goto Done; } Status = FileHandleGetSize (FileHandle, (UINT64 *) &FileSize); if (EFI_ERROR (Status)) { Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status); FileHandleClose (FileHandle); goto Done; } FileBuffer = AllocatePool (FileSize); if (FileBuffer == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } Status = FileHandleRead (FileHandle, &FileSize, FileBuffer); if (EFI_ERROR (Status)) { Print (L"Cannot read file %s. Status = %r\n", FileInfoBuffer[Index]->FileName, Status); FileHandleClose (FileHandle); FreePool (FileBuffer); goto Done; } Print (L"**************************\n"); Print (L" %d.%s:\n", Index + 1, FileInfoBuffer[Index]->FileName); Print (L"**************************\n"); DumpCapsuleFromBuffer ((EFI_CAPSULE_HEADER *) FileBuffer); FileHandleClose (FileHandle); FreePool (FileBuffer); } Done: if (FileInfoBuffer != NULL) { for (Index = 0; Index < FileCount; Index++) { if (FileInfoBuffer[Index] != NULL) { FreePool (FileInfoBuffer[Index]); } } FreePool (FileInfoBuffer); } return Status; }
STATIC EFI_STATUS ReadFileData ( IN CHAR16 *FileName, OUT UINT8 **Buffer, OUT UINT32 *BufferSize ) { EFI_STATUS Status; SHELL_FILE_HANDLE FileHandle; UINT64 Size; VOID *NewBuffer; UINTN ReadSize; FileHandle = NULL; NewBuffer = NULL; Size = 0; Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0); if (EFI_ERROR (Status)) { goto Done; } Status = FileHandleIsDirectory (FileHandle); if (!EFI_ERROR (Status)) { Status = EFI_NOT_FOUND; goto Done; } Status = FileHandleGetSize (FileHandle, &Size); if (EFI_ERROR (Status)) { goto Done; } NewBuffer = AllocatePool ((UINTN) Size); ReadSize = (UINTN) Size; Status = FileHandleRead (FileHandle, &ReadSize, NewBuffer); if (EFI_ERROR (Status)) { goto Done; } else if (ReadSize != (UINTN) Size) { Status = EFI_INVALID_PARAMETER; goto Done; } Done: if (FileHandle != NULL) { ShellCloseFile (&FileHandle); } if (EFI_ERROR (Status)) { if (NewBuffer != NULL) { FreePool (NewBuffer); } } else { *Buffer = NewBuffer; *BufferSize = (UINT32) Size; } return Status; }