/** Display a single file to StdOut. If both Ascii and UCS2 are FALSE attempt to discover the file type. @param[in] Handle The handle to the file to display. @param[in] Ascii TRUE to force ASCII, FALSE othewise. @param[in] UCS2 TRUE to force UCS2, FALSE othewise. @retval EFI_OUT_OF_RESOURCES A memory allocation failed. @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS EFIAPI TypeFileByHandle ( IN EFI_HANDLE Handle, BOOLEAN Ascii, BOOLEAN UCS2 ) { UINTN ReadSize; VOID *Buffer; EFI_STATUS Status; UINTN LoopVar; CHAR16 AsciiChar; ReadSize = PcdGet16(PcdShellFileOperationSize); Buffer = AllocateZeroPool(ReadSize); if (Buffer == NULL) { return (EFI_OUT_OF_RESOURCES); } Status = ShellSetFilePosition(Handle, 0); ASSERT_EFI_ERROR(Status); while (ReadSize == ((UINTN)PcdGet16(PcdShellFileOperationSize))) { ZeroMem(Buffer, ReadSize); Status = ShellReadFile(Handle, &ReadSize, Buffer); if (EFI_ERROR(Status)) { break; } if (!(Ascii|UCS2)) { if (*(UINT16*)Buffer == gUnicodeFileTag) { UCS2 = TRUE; Buffer = ((UINT16*)Buffer) + 1; } else { Ascii = TRUE; } } // // We want to use plain Print function here! (no color support for files) // if (Ascii) { for (LoopVar = 0 ; LoopVar < ReadSize ; LoopVar++) { AsciiChar = CHAR_NULL; AsciiChar = ((CHAR8*)Buffer)[LoopVar]; if (AsciiChar == CHAR_NULL) { AsciiChar = '.'; } Print(L"%c", AsciiChar); } } else { Print(L"%s", Buffer); } } Print(L"\r\n", Buffer); return (Status); }
/** Display a single file to StdOut. If both Ascii and UCS2 are FALSE attempt to discover the file type. @param[in] Handle The handle to the file to display. @param[in] Ascii TRUE to force ASCII, FALSE othewise. @param[in] UCS2 TRUE to force UCS2, FALSE othewise. @retval EFI_OUT_OF_RESOURCES A memory allocation failed. @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS TypeFileByHandle ( IN SHELL_FILE_HANDLE Handle, IN BOOLEAN Ascii, IN BOOLEAN UCS2 ) { UINTN ReadSize; VOID *Buffer; VOID *AllocatedBuffer; EFI_STATUS Status; UINTN LoopVar; UINTN LoopSize; CHAR16 AsciiChar; CHAR16 Ucs2Char; ReadSize = PcdGet32(PcdShellFileOperationSize); AllocatedBuffer = AllocateZeroPool(ReadSize); if (AllocatedBuffer == NULL) { return (EFI_OUT_OF_RESOURCES); } Status = ShellSetFilePosition(Handle, 0); ASSERT_EFI_ERROR(Status); while (ReadSize == ((UINTN)PcdGet32(PcdShellFileOperationSize))) { Buffer = AllocatedBuffer; ZeroMem(Buffer, ReadSize); Status = ShellReadFile(Handle, &ReadSize, Buffer); if (EFI_ERROR(Status)){ break; } if (!(Ascii|UCS2)) { if (*(UINT16*)Buffer == gUnicodeFileTag) { UCS2 = TRUE; } else { Ascii = TRUE; } } if (Ascii) { LoopSize = ReadSize; for (LoopVar = 0 ; LoopVar < LoopSize ; LoopVar++) { // // The valid range of ASCII characters is 0x20-0x7E. // Display "." when there is an invalid character. // AsciiChar = CHAR_NULL; AsciiChar = ((CHAR8*)Buffer)[LoopVar]; if (AsciiChar == '\r' || AsciiChar == '\n') { // // Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD) // characters to be displayed as is. // if (AsciiChar == '\n' && ((CHAR8*)Buffer)[LoopVar-1] != '\r') { // // In case Line Feed (0xA) is encountered & Carriage Return (0xD) // was not the previous character, print CR and LF. This is because // Shell 2.0 requires carriage return with line feed for displaying // each new line from left. // ShellPrintEx (-1, -1, L"\r\n"); continue; } } else { // // For all other characters which are not printable, display '.' // if (AsciiChar < 0x20 || AsciiChar >= 0x7F) { AsciiChar = '.'; } } ShellPrintEx (-1, -1, L"%c", AsciiChar); } } else { if (*(UINT16*)Buffer == gUnicodeFileTag) { // // For unicode files, skip displaying the byte order marker. // Buffer = ((UINT16*)Buffer) + 1; LoopSize = (ReadSize / (sizeof (CHAR16))) - 1; } else { LoopSize = ReadSize / (sizeof (CHAR16)); } for (LoopVar = 0 ; LoopVar < LoopSize ; LoopVar++) { // // An invalid range of characters is 0x0-0x1F. // Display "." when there is an invalid character. // Ucs2Char = CHAR_NULL; Ucs2Char = ((CHAR16*)Buffer)[LoopVar]; if (Ucs2Char == '\r' || Ucs2Char == '\n') { // // Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD) // characters to be displayed as is. // if (Ucs2Char == '\n' && ((CHAR16*)Buffer)[LoopVar-1] != '\r') { // // In case Line Feed (0xA) is encountered & Carriage Return (0xD) // was not the previous character, print CR and LF. This is because // Shell 2.0 requires carriage return with line feed for displaying // each new line from left. // ShellPrintEx (-1, -1, L"\r\n"); continue; } } else if (Ucs2Char < 0x20) { // // For all other characters which are not printable, display '.' // Ucs2Char = L'.'; } ShellPrintEx (-1, -1, L"%c", Ucs2Char); } } if (ShellGetExecutionBreakFlag()) { break; } } FreePool (AllocatedBuffer); ShellPrintEx (-1, -1, L"\r\n"); return (Status); }
/** as the real entry point for the application. @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval other Some error occurs when executing this entry point. **/ EFI_STATUS EFIAPI UefiMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_FILE_HANDLE FileHandle; EFI_STATUS Status; CHAR16 FileName[100]; UINTN BufferSize; UINT64 Position; UINT8 Buffer[200]; EFI_FILE_INFO *pFileInfo; UINT64 Size; BOOLEAN NoFile; EFI_SHELL_FILE_INFO *pShellFileInfo; LIST_ENTRY *List; // CONST CHAR16 *Tester; FileHandle = NULL; StrCpy(FileName, L"testfile.txt"); // Position = 0; pFileInfo = NULL; Size = 0; NoFile = FALSE; pShellFileInfo = NULL; List = NULL; // command line param functions Status = ShellCommandLineParse(ParamList, &List, NULL, FALSE); // if you put an invalid parameter you SHOULD hit this assert. ASSERT_EFI_ERROR(Status); if (List) { ASSERT(ShellCommandLineGetFlag(List, L"/Param5") == FALSE); ASSERT(ShellCommandLineGetFlag(List, L"/Param1") != FALSE); ASSERT(StrCmp(ShellCommandLineGetValue(List, L"/Param2"), L"Val1")==0); ASSERT(StrCmp(ShellCommandLineGetRawValue(List, 0), L"SimpleApplication.efi")==0); // Tester = ShellCommandLineGetValue(List, L"/Param3"); // Tester = ShellCommandLineGetValue(List, L"/Param4"); ShellCommandLineFreeVarList(List); } else { Print(L"param checking skipped.\r\n"); } // return (EFI_SUCCESS); ASSERT(ShellGetExecutionBreakFlag() == FALSE); ASSERT(StrCmp(ShellGetCurrentDir(NULL), L"f10:\\") == 0); Print(L"execution break and get cur dir - pass\r\n"); ShellSetPageBreakMode(TRUE); Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0 ); ASSERT_EFI_ERROR(Status); BufferSize = StrSize(FileName); Status = ShellWriteFile(FileHandle, &BufferSize, FileName); ASSERT_EFI_ERROR(Status); Status = ShellGetFilePosition(FileHandle, &Position); ASSERT_EFI_ERROR(Status); ASSERT(Position == 0x1A); Status = ShellSetFilePosition(FileHandle, 0); ASSERT_EFI_ERROR(Status); BufferSize = sizeof(Buffer) * sizeof(Buffer[0]); Status = ShellReadFile(FileHandle, &BufferSize, Buffer); ASSERT_EFI_ERROR(Status); ASSERT(BufferSize == 0x1A); ASSERT(StrCmp((CHAR16*)Buffer, FileName) == 0); pFileInfo = ShellGetFileInfo(FileHandle); ASSERT(pFileInfo != NULL); ASSERT(StrCmp(pFileInfo->FileName, FileName) == 0); ASSERT(pFileInfo->FileSize == 0x1A); FreePool(pFileInfo); pFileInfo = NULL; Status = ShellCloseFile(&FileHandle); ASSERT_EFI_ERROR(Status); Print(L"read, write, create, getinfo - pass\r\n"); Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0 ); ASSERT_EFI_ERROR(Status); pFileInfo = ShellGetFileInfo(FileHandle); ASSERT(pFileInfo != NULL); pFileInfo->FileSize = 0x20; Status = ShellSetFileInfo(FileHandle, pFileInfo); FreePool(pFileInfo); pFileInfo = NULL; ASSERT_EFI_ERROR(Status); pFileInfo = ShellGetFileInfo(FileHandle); ASSERT(pFileInfo != NULL); ASSERT(StrCmp(pFileInfo->FileName, FileName) == 0); ASSERT(pFileInfo->PhysicalSize == 0x20); ASSERT(pFileInfo->FileSize == 0x20); ASSERT((pFileInfo->Attribute&EFI_FILE_DIRECTORY)==0); FreePool(pFileInfo); Status = ShellGetFileSize(FileHandle, &Size); ASSERT(Size == 0x20); ASSERT_EFI_ERROR(Status); Status = ShellCloseFile(&FileHandle); ASSERT_EFI_ERROR(Status); Print(L"setinfo and change size, getsize - pass\r\n"); Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0 ); ASSERT_EFI_ERROR(Status); pFileInfo = ShellGetFileInfo(FileHandle); ASSERT(pFileInfo != NULL); ASSERT(StrCmp(pFileInfo->FileName, FileName) == 0); ASSERT(pFileInfo->PhysicalSize == 0x20); ASSERT(pFileInfo->FileSize == 0x20); ASSERT((pFileInfo->Attribute&EFI_FILE_DIRECTORY)==0); FreePool(pFileInfo); pFileInfo = NULL; Status = ShellDeleteFile(&FileHandle); ASSERT_EFI_ERROR(Status); Print(L"reopen file - pass\r\n"); Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0 ); ASSERT_EFI_ERROR(Status); pFileInfo = ShellGetFileInfo(FileHandle); ASSERT(pFileInfo != NULL); ASSERT(StrCmp(pFileInfo->FileName, FileName) == 0); ASSERT(pFileInfo->PhysicalSize == 0x0); ASSERT(pFileInfo->FileSize == 0x0); ASSERT((pFileInfo->Attribute&EFI_FILE_DIRECTORY)==0); FreePool(pFileInfo); Status = ShellDeleteFile(&FileHandle); ASSERT_EFI_ERROR(Status); Print(L"size of empty - pass\r\n"); Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0 ); ASSERT(Status == EFI_NOT_FOUND); ASSERT(FileHandle == NULL); Status = ShellCreateDirectory(FileName, &FileHandle); ASSERT_EFI_ERROR(Status); ASSERT(FileHandle != NULL); pFileInfo = ShellGetFileInfo(FileHandle); ASSERT(pFileInfo != NULL); ASSERT(StrCmp(pFileInfo->FileName, FileName) == 0); ASSERT(pFileInfo->Attribute&EFI_FILE_DIRECTORY); Status = ShellDeleteFile(&FileHandle); ASSERT_EFI_ERROR(Status); Print(L"Directory create - pass\r\n"); // FindFirst and FindNext StrCpy(FileName, L"testDir"); Status = ShellCreateDirectory(FileName, &FileHandle); Status = ShellCloseFile(&FileHandle); StrCat(FileName, L"\\File.txt"); Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0 ); ASSERT_EFI_ERROR(Status); Status = ShellCloseFile(&FileHandle); StrCpy(FileName, L"testDir"); Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0 ); ASSERT_EFI_ERROR(Status); Status = ShellFindFirstFile(FileHandle, &pFileInfo); ASSERT_EFI_ERROR(Status); Status = ShellFindNextFile(FileHandle, pFileInfo, &NoFile); ASSERT_EFI_ERROR(Status); ASSERT(NoFile == FALSE); Status = ShellFindNextFile(FileHandle, pFileInfo, &NoFile); ASSERT_EFI_ERROR(Status); ASSERT(NoFile == FALSE); Status = ShellFindNextFile(FileHandle, pFileInfo, &NoFile); ASSERT_EFI_ERROR(Status); ///@todo - why is NoFile never set? limitation of NT32 file system? Status = ShellDeleteFile(&FileHandle); ASSERT(Status == RETURN_WARN_DELETE_FAILURE); Print(L"FindFirst - pass\r\n"); Print(L"FindNext - Verify with real EFI system. Cant verify NoFile under NT32\r\n"); // open and close meta arg Status = ShellOpenFileMetaArg(L"testDir\\*.*", EFI_FILE_MODE_READ, &pShellFileInfo); ASSERT_EFI_ERROR(Status); ASSERT(pShellFileInfo->Status == 0); ASSERT(StrCmp(pShellFileInfo->FileName, L"File.txt") == 0); ASSERT(pShellFileInfo->Handle); ASSERT(pShellFileInfo->Info); ASSERT(pShellFileInfo->Info->FileSize == 0); ASSERT(StrCmp(pShellFileInfo->Info->FileName, L"File.txt") == 0); ASSERT(pShellFileInfo->Info->Attribute == 0); Status = ShellCloseFileMetaArg(&pShellFileInfo); ASSERT_EFI_ERROR(Status); Print(L"Open/Close Meta Arg - pass\r\n"); // now delete that file and that directory StrCat(FileName, L"\\File.txt"); Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0 ); ASSERT_EFI_ERROR(Status); Status = ShellDeleteFile(&FileHandle); StrCpy(FileName, L"testDir"); ASSERT_EFI_ERROR(Status); Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0 ); Status = ShellDeleteFile(&FileHandle); ASSERT_EFI_ERROR(Status); // get environment variable // made for testing under nt32 ASSERT(StrCmp(ShellGetEnvironmentVariable(L"path"), L".;f10:\\efi\\tools;f10:\\efi\\boot;f10:\\;f9:\\efi\\tools;f9:\\efi\\boot;f9:\\") == 0); Print(L"ShellGetEnvironmentVariable - pass\r\n"); // set environment variable Status = ShellSetEnvironmentVariable(L"", L"", FALSE); ASSERT(Status == EFI_UNSUPPORTED); Print(L"ShellSetEnvironmentVariable - pass\r\n"); // ShellExecute Status = ShellExecute(&ImageHandle, L"EmptyApplication.efi", TRUE, NULL, NULL); ASSERT_EFI_ERROR(Status); // the pass printout for this is performed by EmptyApplication Print(L"\r\n"); // page break mode (done last so we can see the results) // we set this true at the begining of the program // this is enough lines to trigger the page... Print(L"1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n"); ShellSetPageBreakMode(FALSE); Print(L"1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n37\r\n38\r\n39\r\n40\r\n41\r\n42\r\n43\r\n44\r\n45\r\n46\r\n47\r\n48\r\n49\r\n50\r\n51\r\n52\r\n53\r\n54\r\n55\r\n56\r\n57\r\n58\r\n59\r\n60\r\n"); return EFI_SUCCESS; }
/** Function to Copy one file to another location If the destination exists the user will be prompted and the result put into *resp @param[in] Source pointer to source file name @param[in] Dest pointer to destination file name @param[out] Resp pointer to response from question. Pass back on looped calling @param[in] SilentMode whether to run in quiet mode or not @retval SHELL_SUCCESS The source file was copied to the destination **/ SHELL_STATUS EFIAPI CopySingleFile( IN CONST CHAR16 *Source, IN CONST CHAR16 *Dest, OUT VOID **Resp, IN BOOLEAN SilentMode ) { VOID *Response; UINTN ReadSize; SHELL_FILE_HANDLE SourceHandle; SHELL_FILE_HANDLE DestHandle; EFI_STATUS Status; VOID *Buffer; CHAR16 *TempName; UINTN Size; EFI_SHELL_FILE_INFO *List; SHELL_STATUS ShellStatus; UINT64 SourceFileSize; UINT64 DestFileSize; EFI_FILE_PROTOCOL *DestVolumeFP; EFI_FILE_SYSTEM_INFO *DestVolumeInfo; UINTN DestVolumeInfoSize; ASSERT(Resp != NULL); SourceHandle = NULL; DestHandle = NULL; Response = *Resp; List = NULL; DestVolumeInfo = NULL; ReadSize = PcdGet16(PcdShellFileOperationSize); // Why bother copying a file to itself if (StrCmp(Source, Dest) == 0) { return (SHELL_SUCCESS); } // // Open destination file without create // Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0); // // close file // if (DestHandle != NULL) { ShellCloseFile(&DestHandle); DestHandle = NULL; } // // if the destination file existed check response and possibly prompt user // if (!EFI_ERROR(Status)) { if (Response == NULL && !SilentMode) { Status = ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response); } // // possibly return based on response // if (!SilentMode) { switch (*(SHELL_PROMPT_RESPONSE*)Response) { case ShellPromptResponseNo: // // return success here so we dont stop the process // return (SHELL_SUCCESS); case ShellPromptResponseCancel: *Resp = Response; // // indicate to stop everything // return (SHELL_ABORTED); case ShellPromptResponseAll: *Resp = Response; case ShellPromptResponseYes: break; default: return SHELL_ABORTED; } } } if (ShellIsDirectory(Source) == EFI_SUCCESS) { Status = ShellCreateDirectory(Dest, &DestHandle); if (EFI_ERROR(Status)) { return (SHELL_ACCESS_DENIED); } // // Now copy all the files under the directory... // TempName = NULL; Size = 0; StrnCatGrow(&TempName, &Size, Source, 0); StrnCatGrow(&TempName, &Size, L"\\*", 0); if (TempName != NULL) { ShellOpenFileMetaArg((CHAR16*)TempName, EFI_FILE_MODE_READ, &List); *TempName = CHAR_NULL; StrnCatGrow(&TempName, &Size, Dest, 0); StrnCatGrow(&TempName, &Size, L"\\", 0); ShellStatus = ValidateAndCopyFiles(List, TempName, SilentMode, TRUE, Resp); ShellCloseFileMetaArg(&List); SHELL_FREE_NON_NULL(TempName); Size = 0; } } else { // // open file with create enabled // Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0); if (EFI_ERROR(Status)) { return (SHELL_ACCESS_DENIED); } // // open source file // Status = ShellOpenFileByName(Source, &SourceHandle, EFI_FILE_MODE_READ, 0); ASSERT_EFI_ERROR(Status); // //get file size of source file and freespace available on destination volume // ShellGetFileSize(SourceHandle, &SourceFileSize); ShellGetFileSize(DestHandle, &DestFileSize); // //if the destination file already exists then it will be replaced, meaning the sourcefile effectively needs less storage space // if(DestFileSize < SourceFileSize){ SourceFileSize -= DestFileSize; } else { SourceFileSize = 0; } // //get the system volume info to check the free space // DestVolumeFP = ConvertShellHandleToEfiFileProtocol(DestHandle); DestVolumeInfo = NULL; DestVolumeInfoSize = 0; Status = DestVolumeFP->GetInfo( DestVolumeFP, &gEfiFileSystemInfoGuid, &DestVolumeInfoSize, DestVolumeInfo ); if (Status == EFI_BUFFER_TOO_SMALL) { DestVolumeInfo = AllocateZeroPool(DestVolumeInfoSize); Status = DestVolumeFP->GetInfo( DestVolumeFP, &gEfiFileSystemInfoGuid, &DestVolumeInfoSize, DestVolumeInfo ); } // //check if enough space available on destination drive to complete copy // if (DestVolumeInfo->FreeSpace < SourceFileSize) { // //not enough space on destination directory to copy file // SHELL_FREE_NON_NULL(DestVolumeInfo); ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_FAIL), gShellLevel2HiiHandle); return(SHELL_VOLUME_FULL); } else { // // copy data between files // Buffer = AllocateZeroPool(ReadSize); ASSERT(Buffer != NULL); while (ReadSize == PcdGet16(PcdShellFileOperationSize) && !EFI_ERROR(Status)) { Status = ShellReadFile(SourceHandle, &ReadSize, Buffer); Status = ShellWriteFile(DestHandle, &ReadSize, Buffer); } } SHELL_FREE_NON_NULL(DestVolumeInfo); } // // close files // if (DestHandle != NULL) { ShellCloseFile(&DestHandle); DestHandle = NULL; } if (SourceHandle != NULL) { ShellCloseFile(&SourceHandle); SourceHandle = NULL; } // // return // return (SHELL_SUCCESS); }
/** Function to read in HII configuration information from a file. @param[in] Handle The handle to get info for. @param[in] FileName The filename to read the info from. **/ SHELL_STATUS EFIAPI ConfigFromFile( IN EFI_HANDLE Handle, IN CONST CHAR16 *FileName ) { EFI_HII_DATABASE_PROTOCOL *HiiDatabase; EFI_STATUS Status; VOID *MainBuffer; UINT64 Temp; UINTN MainBufferSize; EFI_HII_HANDLE HiiHandle; SHELL_FILE_HANDLE FileHandle; CHAR16 *TempDevPathString; EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; EFI_HII_PACKAGE_HEADER *PackageHeader; EFI_DEVICE_PATH_PROTOCOL *DevPath; UINTN HandleIndex; HiiDatabase = NULL; MainBufferSize = 0; MainBuffer = NULL; FileHandle = NULL; Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0); if (EFI_ERROR(Status)) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN(STR_GEN_FILE_OPEN), gShellDriver1HiiHandle, FileName, Status); return (SHELL_DEVICE_ERROR); } // // Locate HII Database protocol // Status = gBS->LocateProtocol ( &gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase ); if (EFI_ERROR(Status) || HiiDatabase == NULL) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN(STR_GEN_PROTOCOL_NF), gShellDriver1HiiHandle, L"EfiHiiDatabaseProtocol", &gEfiHiiDatabaseProtocolGuid); ShellCloseFile(&FileHandle); return (SHELL_NOT_FOUND); } Status = ShellGetFileSize(FileHandle, &Temp); MainBufferSize = (UINTN)Temp; if (EFI_ERROR(Status)) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN(STR_FILE_READ_FAIL), gShellDriver1HiiHandle, FileName, Status); ShellCloseFile(&FileHandle); return (SHELL_DEVICE_ERROR); } MainBuffer = AllocateZeroPool((UINTN)MainBufferSize); if (EFI_ERROR(Status)) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN(STR_GEN_OUT_MEM), gShellDriver1HiiHandle); ShellCloseFile(&FileHandle); return (SHELL_DEVICE_ERROR); } Status = ShellReadFile(FileHandle, &MainBufferSize, MainBuffer); if (EFI_ERROR(Status)) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN(STR_FILE_READ_FAIL), gShellDriver1HiiHandle, FileName, Status); ShellCloseFile(&FileHandle); SHELL_FREE_NON_NULL(MainBuffer); return (SHELL_DEVICE_ERROR); } ShellCloseFile(&FileHandle); if (Handle != NULL) { // // User override in place. Just do it. // HiiHandle = NULL; Status = ConvertHandleToHiiHandle(Handle, &HiiHandle, HiiDatabase); if (EFI_ERROR(Status)) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN(STR_GEN_HANDLE_NOT), gShellDriver1HiiHandle, ConvertHandleToHandleIndex(Handle), L"Device"); ShellCloseFile(&FileHandle); return (SHELL_DEVICE_ERROR); } Status = HiiDatabase->UpdatePackageList(HiiDatabase, HiiHandle, MainBuffer); if (EFI_ERROR(Status)) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN(STR_GEN_UEFI_FUNC_ERROR), gShellDriver1HiiHandle, L"HiiDatabase->UpdatePackageList", Status); return (SHELL_DEVICE_ERROR); } } else { // // we need to parse the buffer and try to match the device paths for each item to try to find it's device path. // for (PackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER*)MainBuffer ; PackageListHeader != NULL && ((CHAR8*)PackageListHeader) < (((CHAR8*)MainBuffer)+MainBufferSize) ; PackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER*)(((CHAR8*)(PackageListHeader)) + PackageListHeader->PackageLength )) { for (PackageHeader = (EFI_HII_PACKAGE_HEADER*)(((CHAR8*)(PackageListHeader))+sizeof(EFI_HII_PACKAGE_LIST_HEADER)) ; PackageHeader != NULL && ((CHAR8*)PackageHeader) < (((CHAR8*)MainBuffer)+MainBufferSize) && PackageHeader->Type != EFI_HII_PACKAGE_END ; PackageHeader = (EFI_HII_PACKAGE_HEADER*)(((CHAR8*)(PackageHeader))+PackageHeader->Length)) { if (PackageHeader->Type == EFI_HII_PACKAGE_DEVICE_PATH) { HiiHandle = NULL; Status = FindHiiHandleViaDevPath((EFI_DEVICE_PATH_PROTOCOL*)(((CHAR8*)PackageHeader) + sizeof(EFI_HII_PACKAGE_HEADER)), &HiiHandle, HiiDatabase); if (EFI_ERROR(Status)) { // // print out an error. // TempDevPathString = ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*)(((CHAR8*)PackageHeader) + sizeof(EFI_HII_PACKAGE_HEADER)), TRUE, TRUE); ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN(STR_DRVCFG_IN_FILE_NF), gShellDriver1HiiHandle, TempDevPathString); SHELL_FREE_NON_NULL(TempDevPathString); } else { Status = HiiDatabase->UpdatePackageList(HiiDatabase, HiiHandle, PackageListHeader); if (EFI_ERROR(Status)) { ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN(STR_GEN_UEFI_FUNC_ERROR), gShellDriver1HiiHandle, L"HiiDatabase->UpdatePackageList", Status); return (SHELL_DEVICE_ERROR); } else { DevPath = (EFI_DEVICE_PATH_PROTOCOL*)(((CHAR8*)PackageHeader) + sizeof(EFI_HII_PACKAGE_HEADER)); gBS->LocateDevicePath(&gEfiHiiConfigAccessProtocolGuid, &DevPath, &Handle); HandleIndex = ConvertHandleToHandleIndex(Handle); ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN(STR_DRVCFG_DONE_HII), gShellDriver1HiiHandle, HandleIndex); } } } } } } SHELL_FREE_NON_NULL(MainBuffer); ShellPrintHiiEx( -1, -1, NULL, STRING_TOKEN(STR_DRVCFG_COMP), gShellDriver1HiiHandle); return (SHELL_SUCCESS); }
/** Load the variable data from file and set to variable data base. @param[in] FileHandle The file to be read. @param[in] Name The name of the variables to be loaded. @param[in] Guid The guid of the variables to be loaded. @param[out] Found TRUE when at least one variable was loaded and set. @retval SHELL_DEVICE_ERROR Cannot access the file. @retval SHELL_VOLUME_CORRUPTED The file is in bad format. @retval SHELL_OUT_OF_RESOURCES There is not enough memory to perform the operation. @retval SHELL_SUCCESS Successfully load and set the variables. **/ SHELL_STATUS LoadVariablesFromFile ( IN SHELL_FILE_HANDLE FileHandle, IN CONST CHAR16 *Name, IN CONST EFI_GUID *Guid, OUT BOOLEAN *Found ) { EFI_STATUS Status; SHELL_STATUS ShellStatus; UINT32 NameSize; UINT32 DataSize; UINTN BufferSize; UINTN RemainingSize; UINT64 Position; UINT64 FileSize; LIST_ENTRY List; DMP_STORE_VARIABLE *Variable; LIST_ENTRY *Link; CHAR16 *Attributes; UINT8 *Buffer; UINT32 Crc32; Status = ShellGetFileSize (FileHandle, &FileSize); if (EFI_ERROR (Status)) { return SHELL_DEVICE_ERROR; } ShellStatus = SHELL_SUCCESS; InitializeListHead (&List); Position = 0; while (Position < FileSize) { // // NameSize // BufferSize = sizeof (NameSize); Status = ShellReadFile (FileHandle, &BufferSize, &NameSize); if (EFI_ERROR (Status) || (BufferSize != sizeof (NameSize))) { ShellStatus = SHELL_VOLUME_CORRUPTED; break; } // // DataSize // BufferSize = sizeof (DataSize); Status = ShellReadFile (FileHandle, &BufferSize, &DataSize); if (EFI_ERROR (Status) || (BufferSize != sizeof (DataSize))) { ShellStatus = SHELL_VOLUME_CORRUPTED; break; } // // Name, Guid, Attributes, Data, Crc32 // RemainingSize = NameSize + sizeof (EFI_GUID) + sizeof (UINT32) + DataSize + sizeof (Crc32); BufferSize = sizeof (NameSize) + sizeof (DataSize) + RemainingSize; Buffer = AllocatePool (BufferSize); if (Buffer == NULL) { ShellStatus = SHELL_OUT_OF_RESOURCES; break; } BufferSize = RemainingSize; Status = ShellReadFile (FileHandle, &BufferSize, (UINT32 *) Buffer + 2); if (EFI_ERROR (Status) || (BufferSize != RemainingSize)) { ShellStatus = SHELL_VOLUME_CORRUPTED; FreePool (Buffer); break; } // // Check Crc32 // * (UINT32 *) Buffer = NameSize; * ((UINT32 *) Buffer + 1) = DataSize; BufferSize = RemainingSize + sizeof (NameSize) + sizeof (DataSize) - sizeof (Crc32); gBS->CalculateCrc32 ( Buffer, BufferSize, &Crc32 ); if (Crc32 != * (UINT32 *) (Buffer + BufferSize)) { FreePool (Buffer); ShellStatus = SHELL_VOLUME_CORRUPTED; break; } Position += BufferSize + sizeof (Crc32); Variable = AllocateZeroPool (sizeof (*Variable) + NameSize + DataSize); if (Variable == NULL) { FreePool (Buffer); ShellStatus = SHELL_OUT_OF_RESOURCES; break; } Variable->Signature = DMP_STORE_VARIABLE_SIGNATURE; Variable->Name = (CHAR16 *) (Variable + 1); Variable->DataSize = DataSize; Variable->Data = (UINT8 *) Variable->Name + NameSize; CopyMem (Variable->Name, Buffer + sizeof (NameSize) + sizeof (DataSize), NameSize); CopyMem (&Variable->Guid, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize, sizeof (EFI_GUID)); CopyMem (&Variable->Attributes, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize + sizeof (EFI_GUID), sizeof (UINT32)); CopyMem (Variable->Data, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize + sizeof (EFI_GUID) + sizeof (UINT32), DataSize); InsertTailList (&List, &Variable->Link); FreePool (Buffer); } if ((Position != FileSize) || (ShellStatus != SHELL_SUCCESS)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD_BAD_FILE), gShellDebug1HiiHandle, L"dmpstore"); if (Position != FileSize) { ShellStatus = SHELL_VOLUME_CORRUPTED; } } for ( Link = GetFirstNode (&List) ; !IsNull (&List, Link) && (ShellStatus == SHELL_SUCCESS) ; Link = GetNextNode (&List, Link) ) { Variable = CR (Link, DMP_STORE_VARIABLE, Link, DMP_STORE_VARIABLE_SIGNATURE); if (((Name == NULL) || gUnicodeCollation->MetaiMatch (gUnicodeCollation, Variable->Name, (CHAR16 *) Name)) && ((Guid == NULL) || CompareGuid (&Variable->Guid, Guid)) ) { Attributes = GetAttrType (Variable->Attributes); ShellPrintHiiEx ( -1, -1, NULL, STRING_TOKEN(STR_DMPSTORE_HEADER_LINE), gShellDebug1HiiHandle, Attributes, &Variable->Guid, Variable->Name, Variable->DataSize ); SHELL_FREE_NON_NULL(Attributes); *Found = TRUE; Status = gRT->SetVariable ( Variable->Name, &Variable->Guid, Variable->Attributes, Variable->DataSize, Variable->Data ); if (EFI_ERROR (Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD_GEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", Variable->Name, Status); } } } for (Link = GetFirstNode (&List); !IsNull (&List, Link); ) { Variable = CR (Link, DMP_STORE_VARIABLE, Link, DMP_STORE_VARIABLE_SIGNATURE); Link = RemoveEntryList (&Variable->Link); FreePool (Variable); } return ShellStatus; }