/** Create a new file or folder in current directory. @param FileName Point to the fileNmae or folder name. @param CreateFile CreateFile== TRUE means create a new file. CreateFile== FALSE means create a new Folder. **/ EFI_STATUS LibCreateNewFile ( IN CHAR16 *FileName, IN BOOLEAN CreateFile ) { EFI_FILE_HANDLE FileHandle; EFI_FILE_HANDLE NewHandle; EFI_HANDLE DeviceHandle; EFI_STATUS Status; CHAR16 *ParentName; CHAR16 *FullFileName; NewHandle = NULL; FullFileName = NULL; LibGetFileHandleFromDevicePath(gFileExplorerPrivate.RetDevicePath, &FileHandle, &ParentName, &DeviceHandle); FullFileName = LibAppendFileName (ParentName, FileName); if (FullFileName == NULL) { return EFI_OUT_OF_RESOURCES; } if (CreateFile) { Status = FileHandle->Open( FileHandle, &NewHandle, FullFileName, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE, 0 ); if (EFI_ERROR (Status)) { FileHandle->Close (FileHandle); return Status; } } else { Status = FileHandle->Open( FileHandle, &NewHandle, FullFileName, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE, EFI_FILE_DIRECTORY ); if (EFI_ERROR (Status)) { FileHandle->Close (FileHandle); return Status; } } FileHandle->Close (FileHandle); // // Return the DevicePath of the new created file or folder. // gFileExplorerPrivate.RetDevicePath = FileDevicePath (DeviceHandle, FullFileName); return EFI_SUCCESS; }
/** Open the NvVars file for reading or writing @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance @param[in] ReadingFile - TRUE: open the file for reading. FALSE: writing @param[out] NvVarsFile - If EFI_SUCCESS is returned, then this is updated with the opened NvVars file. @return EFI_SUCCESS if the file was opened **/ EFI_STATUS GetNvVarsFile ( IN EFI_HANDLE FsHandle, IN BOOLEAN ReadingFile, OUT EFI_FILE_HANDLE *NvVarsFile ) { EFI_STATUS Status; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; EFI_FILE_HANDLE Root; // // Get the FileSystem protocol on that handle // Status = gBS->HandleProtocol ( FsHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs ); if (EFI_ERROR (Status)) { return Status; } // // Get the volume (the root directory) // Status = Fs->OpenVolume (Fs, &Root); if (EFI_ERROR (Status)) { return Status; } // // Attempt to open the NvVars file in the root directory // Status = Root->Open ( Root, NvVarsFile, L"NvVars", ReadingFile ? EFI_FILE_MODE_READ : ( EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE ), 0 ); if (EFI_ERROR (Status)) { return Status; } return Status; }
/** Find the file handle from the input menu info. @param MenuEntry Input Menu info. @param RetFileHandle Return the file handle for the input device path. @retval EFI_SUCESS Find the file handle success. @retval Other Find the file handle failure. **/ EFI_STATUS LibGetFileHandleFromMenu ( IN MENU_ENTRY *MenuEntry, OUT EFI_FILE_HANDLE *RetFileHandle ) { EFI_FILE_HANDLE Dir; EFI_FILE_HANDLE NewDir; FILE_CONTEXT *FileContext; EFI_STATUS Status; FileContext = (FILE_CONTEXT *) MenuEntry->VariableContext; Dir = FileContext->FileHandle; // // Open current directory to get files from it // Status = Dir->Open ( Dir, &NewDir, FileContext->FileName, EFI_FILE_READ_ONLY, 0 ); if (EFI_ERROR (Status)) { return Status; } if (!FileContext->IsRoot) { Dir->Close (Dir); } *RetFileHandle = NewDir; return EFI_SUCCESS; }
/** Write a file. @param[in] FileName The file to be written. @param[in] BufferSize The file buffer size @param[in] Buffer The file buffer @retval EFI_SUCCESS Write file successfully **/ EFI_STATUS WriteFileFromBuffer ( IN CHAR16 *FileName, IN UINTN BufferSize, IN VOID *Buffer ) { EFI_STATUS Status; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; UINTN TempBufferSize; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; Vol = GetMyVol(); if (Vol == NULL) { return EFI_NOT_FOUND; } // // Open the root directory // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { return Status; } // // Open the file // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE, 0 ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } // // Delete file // Status = Handle->Delete(Handle); if (EFI_ERROR(Status)) { return Status; } // // Open the file again // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE| EFI_FILE_MODE_CREATE, 0 ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } RootDir->Close (RootDir); // // Write the file data from the buffer // TempBufferSize = BufferSize; Status = Handle->Write ( Handle, &TempBufferSize, Buffer ); if (EFI_ERROR (Status)) { Handle->Close (Handle); return Status; } Handle->Close (Handle); return EFI_SUCCESS; }
EFI_STATUS GetProtocolAssertion ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *FilePath, OUT UINT32 *PassNumber, OUT UINT32 *WarnNumber, OUT UINT32 *FailNumber ) /*++ Routine Description: Get the assertion number of a protocol or service. Arguments: DevicePath - Device path of the key files. FilePath - Path of the key files. PassNumber - The number of passed assertions. WarnNumber - The number of warning assertions. FailNumber - The number of failed assertions. Returns: EFI_SUCCESS - Get instance assertion number successfully. --*/ { EFI_STATUS Status; EFI_HANDLE DeviceHandle; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE LogDir; UINTN FileInfoSize; EFI_FILE_INFO *FileInfo; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; UINTN BufferSize; CHAR16 *Buffer; CHAR16 *FileName; CHAR16 *LogName; CHAR16 *TempName; CHAR16 *CaseIndexStr; CHAR16 *CaseIterationStr; // // Check parameters // if ((DevicePath == NULL) || (FilePath == NULL) || (PassNumber == NULL) || (WarnNumber == NULL) || (FailNumber == NULL)) { return EFI_INVALID_PARAMETER; } // // Locate the device handle // RemainingDevicePath = DevicePath; Status = BS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &RemainingDevicePath, &DeviceHandle ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Locate device path - %r", Status)); return Status; } // // Locate the simple file system // Status = BS->HandleProtocol ( DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, &Vol ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Handle protocol - %r", Status)); return Status; } // // Open the root directory // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Open volume - %r", Status)); return Status; } // // Open the log directory // Status = RootDir->Open ( RootDir, &LogDir, FilePath, EFI_FILE_MODE_READ, EFI_FILE_DIRECTORY ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Open directory - %r", Status)); RootDir->Close (RootDir); return Status; } RootDir->Close (RootDir); // // Allocate memory for the entries in the directory // FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; Status = BS->AllocatePool ( EfiBootServicesData, FileInfoSize, &FileInfo ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Allocate pool - %r", Status)); LogDir->Close (LogDir); return Status; } // // Walk through each file in the directory // while (TRUE) { // // Read a file entry // FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; Status = LogDir->Read ( LogDir, &FileInfoSize, FileInfo ); if (EFI_ERROR (Status) || (FileInfoSize == 0)) { break; } if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { // // This is a file // // // Only deal with the EFI key file // if (!SctStrEndWith (FileInfo->FileName, L".ekl")) { continue; } // // Read the file to a buffer // FileName = PoolPrint (L"%s\\%s", FilePath, FileInfo->FileName); if (FileName == NULL) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"PoolPrint: Out of resources")); return EFI_OUT_OF_RESOURCES; } Status = ReadFileToBuffer ( DevicePath, FileName, &BufferSize, &Buffer ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_DEBUG, L"Read file to buffer - %r", Status)); BS->FreePool (FileName); continue; } BS->FreePool (FileName); // // Get the index and iteration from the file name // TempName = StrDuplicate (FileInfo->FileName); // // The following function didn't allocate memory for CaseIndexStr and // CaseIterationStr. So DON'T free the TempName before these two strings // are still used. // Status = GetIndexFromFileName ( TempName, &CaseIndexStr, &CaseIterationStr ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_DEBUG, L"Get index from file name - %r", Status)); BS->FreePool (TempName); continue; } // // Load the buffer to the report information structure // LogName = SctStrEndReplace (FileInfo->FileName, L"log"); Status = LoadReportInfor ( CaseIndexStr, CaseIterationStr, Buffer, LogName ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_DEBUG, L"Load report infor - %r", Status)); BS->FreePool (TempName); BS->FreePool (LogName); BS->FreePool (Buffer); continue; } BS->FreePool (TempName); BS->FreePool (LogName); BS->FreePool (Buffer); // // Get the assertion number (free the GUID assertion table) // Status = GetAssertionNumber (PassNumber, WarnNumber, FailNumber); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_DEBUG, L"Get assertion number - %r", Status)); continue; } } else { // // This is a directory // // // Skip the '.' and '..' dir // if ((StrCmp (FileInfo->FileName, L".") == 0) || (StrCmp (FileInfo->FileName, L"..") == 0)) { continue; } // // Get the report information from the sub directories // FileName = PoolPrint (L"%s\\%s", FilePath, FileInfo->FileName); if (FileName == NULL) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"PoolPrint: Out of resources")); return EFI_OUT_OF_RESOURCES; } Status = GetProtocolAssertion ( DevicePath, FileName, PassNumber, WarnNumber, FailNumber ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_DEBUG, L"Get protocol assertion - %r", Status)); BS->FreePool (FileName); continue; } BS->FreePool (FileName); } } // // Free resources // BS->FreePool (FileInfo); LogDir->Close (LogDir); // // Done // return EFI_SUCCESS; }
EFI_STATUS ReadFileFromVol ( IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol, IN CHAR16 *FileName, OUT UINTN *BufferSize, OUT VOID **Buffer ) /*++ Routine Description: Read a file. Arguments: Vol - File System Volume FileName - The file to be read. BufferSize - The file buffer size Buffer - The file buffer Returns: EFI_SUCCESS - read file successfully EFI_NOT_FOUND - file not found --*/ { EFI_STATUS Status; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; UINTN FileInfoSize; EFI_FILE_INFO *FileInfo; UINTN TempBufferSize; VOID *TempBuffer; // // Open the root directory // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { return Status; } // // Open the file // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } RootDir->Close (RootDir); // // Get the file information // FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; FileInfo = EfiLibAllocateZeroPool (FileInfoSize); if (FileInfo == NULL) { Handle->Close (Handle); return Status; } Status = Handle->GetInfo ( Handle, &gEfiFileInfoGuid, &FileInfoSize, FileInfo ); if (EFI_ERROR (Status)) { Handle->Close (Handle); gBS->FreePool (FileInfo); return Status; } // // Allocate buffer for the file data. The last CHAR16 is for L'\0' // TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16); TempBuffer = EfiLibAllocateZeroPool (TempBufferSize); if (TempBuffer == NULL) { Handle->Close (Handle); gBS->FreePool (FileInfo); return Status; } gBS->FreePool (FileInfo); // // Read the file data to the buffer // Status = Handle->Read ( Handle, &TempBufferSize, TempBuffer ); if (EFI_ERROR (Status)) { Handle->Close (Handle); gBS->FreePool (TempBuffer); return Status; } Handle->Close (Handle); *BufferSize = TempBufferSize; *Buffer = TempBuffer; return EFI_SUCCESS; }
VOID EFIAPI PlatformBdsPolicyBehavior ( IN OUT LIST_ENTRY *DriverOptionList, IN OUT LIST_ENTRY *BootOptionList, IN PROCESS_CAPSULES ProcessCapsules, IN BASEM_MEMORY_TEST BaseMemoryTest ) /*++ Routine Description: The function will excute with as the platform policy, current policy is driven by boot mode. IBV/OEM can customize this code for their specific policy action. Arguments: DriverOptionList - The header of the driver option link list BootOptionList - The header of the boot option link list ProcessCapsules - A pointer to ProcessCapsules() BaseMemoryTest - A pointer to BaseMemoryTest() Returns: None. --*/ { EFI_STATUS Status; UINT16 Timeout; EFI_EVENT UserInputDurationTime; LIST_ENTRY *Link; BDS_COMMON_OPTION *BootOption; UINTN Index; EFI_INPUT_KEY Key; EFI_TPL OldTpl; EFI_BOOT_MODE BootMode; VBoxLogFlowFuncEnter(); ConnectRootBridge (); if (PcdGetBool (PcdOvmfFlashVariablesEnable)) { DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars " "from disk since flash variables appear to be supported.\n")); } else { // // Try to restore variables from the hard disk early so // they can be used for the other BDS connect operations. // PlatformBdsRestoreNvVarsFromHardDisk (); } // // Init the time out value // Timeout = PcdGet16 (PcdPlatformBootTimeOut); // // Load the driver option as the driver option list // PlatformBdsGetDriverOption (DriverOptionList); // // Get current Boot Mode // Status = BdsLibGetBootMode (&BootMode); DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode)); // // Go the different platform policy with different boot mode // Notes: this part code can be change with the table policy // ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION); // // Connect platform console // Status = PlatformBdsConnectConsole (gPlatformConsole); if (EFI_ERROR (Status)) { // // Here OEM/IBV can customize with defined action // PlatformBdsNoConsoleAction (); } // // Create a 300ms duration event to ensure user has enough input time to enter Setup // Status = gBS->CreateEvent ( EVT_TIMER, 0, NULL, NULL, &UserInputDurationTime ); ASSERT (Status == EFI_SUCCESS); Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000); ASSERT (Status == EFI_SUCCESS); // // Memory test and Logo show // PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest); // // Perform some platform specific connect sequence // PlatformBdsConnectSequence (); // // Process QEMU's -kernel command line option // TryRunningQemuKernel (); // // Give one chance to enter the setup if we // have the time out // if (Timeout != 0) { //PlatformBdsEnterFrontPage (Timeout, FALSE); } DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n")); BdsLibConnectAll (); #ifdef VBOX { UINTN cFileSystem = 0; EFI_HANDLE *phFileSystem = NULL; BDS_COMMON_OPTION *BootOption0080 = NULL; EFI_STATUS rc = EFI_SUCCESS; DEBUG ((EFI_D_INFO, "------------------ VBox Platform Specific Initialization Start -----------------------\n")); BootOption0080 = BdsLibVariableToOption(BootOptionList, L"Boot0080"); if (!BootOption0080) { rc = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &cFileSystem, &phFileSystem); VBoxLogFlowFuncMarkRC(rc); VBoxLogFlowFuncMarkVar(cFileSystem, "%d"); if ( rc == EFI_SUCCESS && cFileSystem > 0) { EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *pFSVolume; EFI_FILE_HANDLE hFSRoot; EFI_FILE_HANDLE hBootEfiFile; UINTN iFileSystem = 0; /* Ok, we've found several simple file system handles * 1. we should find if '\\System\\Library\\CoreServices\\boot.efi' present * 2. Alter 'BootOrder' to include this file in boot sequence. */ for (iFileSystem = 0; iFileSystem < cFileSystem; ++iFileSystem) { EFI_DEVICE_PATH_PROTOCOL *pDevicePath = NULL; /* mount and look up the boot.efi */ rc = gBS->HandleProtocol (phFileSystem[iFileSystem], &gEfiSimpleFileSystemProtocolGuid, (VOID *) &pFSVolume); VBoxLogFlowFuncMarkVar(iFileSystem, "%d"); VBoxLogFlowFuncMarkRC(rc); if (EFI_ERROR(rc)) continue; rc = pFSVolume->OpenVolume(pFSVolume, &hFSRoot); VBoxLogFlowFuncMarkRC(rc); if (EFI_ERROR(rc)) continue; rc = hFSRoot->Open(hFSRoot, &hBootEfiFile, L"\\System\\Library\\CoreServices\\boot.efi", EFI_FILE_MODE_READ, 0); VBoxLogFlowFuncMarkRC(rc); if (EFI_ERROR(rc)) continue; /* nice file is found and we have to register it */ pDevicePath = FileDevicePath(phFileSystem[iFileSystem], L"\\System\\Library\\CoreServices\\boot.efi"); VBoxLogFlowFuncMarkVar(pDevicePath,"%p"); if (!pDevicePath) continue; rc = BdsLibRegisterNewOption (BootOptionList, pDevicePath, L"Mac Boot", L"BootOrder"); VBoxLogFlowFuncMarkRC(rc); } } } else { VBoxLogFlowFuncMarkVar(BootOption0080->LoadOptionsSize, "%d"); if (BootOption0080->LoadOptionsSize) VBoxLogFlowFuncMarkVar(BootOption0080->LoadOptions, "%s"); #if 0 /* Boot0080 option is found */ UINT16 *BootOrder; UINTN BootOrderSize; UINTN Index = 0; CHAR16 *BootOptionName; ASSERT(BootOption0080->Signature == BDS_LOAD_OPTION_SIGNATURE); BootOrder = BdsLibGetVariableAndSize ( L"BootOrder", &gEfiGlobalVariableGuid, &BootOrderSize); ASSERT(BootOrder); BootOptionName = AllocateRuntimePool(256 * sizeof(UINT16)); UnicodeSPrint(BootOptionName, 256 * sizeof(UINT16), L"Boot%04x", BootOrder[Index]); BootOption0080->OptionName = BootOptionName; rc = gRT->SetVariable(BootOptionName, &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof(BDS_COMMON_OPTION), BootOption0080); LogFlowFuncMarkRC(rc); #if 0 rc = BdsLibRegisterNewOption (BootOptionList, BootOption0080->DevicePath, L"Mac Boot Temp", L"BootOrder"); #endif LogFlowFuncMarkRC(rc); #endif } DEBUG ((EFI_D_INFO, "------------------ VBox Platform Specific Initialization End -----------------------\n")); } #endif BdsLibEnumerateAllBootOption (BootOptionList); SetBootOrderFromQemu (BootOptionList); // // The BootOrder variable may have changed, reload the in-memory list with // it. // BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); // // To give the User a chance to enter Setup here, if user set TimeOut is 0. // BDS should still give user a chance to enter Setup // // Connect first boot option, and then check user input before exit // for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) { BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) { // // skip the header of the link list, becuase it has no boot option // continue; } else { // // Make sure the boot option device path connected, but ignore the BBS device path // if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) { BdsLibConnectDevicePath (BootOption->DevicePath); } break; } } // // Check whether the user input after the duration time has expired // OldTpl = EfiGetCurrentTpl(); gBS->RestoreTPL (TPL_APPLICATION); gBS->WaitForEvent (1, &UserInputDurationTime, &Index); gBS->CloseEvent (UserInputDurationTime); Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); gBS->RaiseTPL (OldTpl); if (!EFI_ERROR (Status)) { // // Enter Setup if user input // Timeout = 0xffff; PlatformBdsEnterFrontPage (Timeout, FALSE); } VBoxLogFlowFuncLeave(); return ; }
EFI_STATUS ReadFileToBuffer ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *FileName, OUT UINTN *BufferSize, OUT VOID **Buffer ) /*++ Routine Description: Read a file. --*/ { EFI_STATUS Status; EFI_HANDLE DeviceHandle; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; UINTN FileInfoSize; EFI_FILE_INFO *FileInfo; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; UINTN TempBufferSize; VOID *TempBuffer; // // Check parameters // if ((DevicePath == NULL) || (FileName == NULL) || (Buffer == NULL)) { return EFI_INVALID_PARAMETER; } // // Locate the device handle // RemainingDevicePath = DevicePath; Status = BS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &RemainingDevicePath, &DeviceHandle ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Locate device path - %r", Status)); return Status; } // // Locate the simple file system // Status = BS->HandleProtocol ( DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, &Vol ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Handle protocol - %r", Status)); return Status; } // // Open the root directory // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Open volume - %r", Status)); return Status; } // // Open the file // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Open file - %r", Status)); RootDir->Close (RootDir); return Status; } RootDir->Close (RootDir); // // Get the file information // FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; Status = BS->AllocatePool ( EfiBootServicesData, FileInfoSize, &FileInfo ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Allocate pool - %r", Status)); Handle->Close (Handle); return Status; } ZeroMem (FileInfo, FileInfoSize); Status = Handle->GetInfo ( Handle, &gEfiFileInfoGuid, &FileInfoSize, FileInfo ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Get file info - %r", Status)); Handle->Close (Handle); BS->FreePool (FileInfo); return Status; } // // Allocate buffer for the file data. The last CHAR16 is for L'\0' // TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16); Status = BS->AllocatePool ( EfiBootServicesData, TempBufferSize, &TempBuffer ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Allocate pool - %r", Status)); Handle->Close (Handle); BS->FreePool (FileInfo); return Status; } ZeroMem (TempBuffer, TempBufferSize); BS->FreePool (FileInfo); // // Read the file data to the buffer // Status = Handle->Read ( Handle, &TempBufferSize, TempBuffer ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Read file - %r", Status)); Handle->Close (Handle); BS->FreePool (TempBuffer); return Status; } Handle->Close (Handle); *BufferSize = TempBufferSize; *Buffer = TempBuffer; return EFI_SUCCESS; }
EFIAPI GetFileBufferByFilePath ( IN BOOLEAN BootPolicy, IN CONST EFI_DEVICE_PATH_PROTOCOL *FilePath, OUT UINTN *FileSize, OUT UINT32 *AuthenticationStatus ) { EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; EFI_DEVICE_PATH_PROTOCOL *OrigDevicePathNode; EFI_DEVICE_PATH_PROTOCOL *TempDevicePathNode; EFI_HANDLE Handle; EFI_GUID *FvNameGuid; EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol; EFI_SECTION_TYPE SectionType; UINT8 *ImageBuffer; UINTN ImageBufferSize; EFI_FV_FILETYPE Type; EFI_FV_FILE_ATTRIBUTES Attrib; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; EFI_FILE_HANDLE FileHandle; EFI_FILE_HANDLE LastHandle; EFI_FILE_INFO *FileInfo; UINTN FileInfoSize; EFI_LOAD_FILE_PROTOCOL *LoadFile; EFI_LOAD_FILE2_PROTOCOL *LoadFile2; EFI_STATUS Status; // // Check input File device path. // if (FilePath == NULL || FileSize == NULL || AuthenticationStatus == NULL) { return NULL; } // // Init local variable // TempDevicePathNode = NULL; FvNameGuid = NULL; FileInfo = NULL; FileHandle = NULL; ImageBuffer = NULL; ImageBufferSize = 0; *AuthenticationStatus = 0; // // Copy File Device Path // OrigDevicePathNode = DuplicateDevicePath (FilePath); if (OrigDevicePathNode == NULL) { return NULL; } // // Check whether this device path support FV2 protocol. // Is so, this device path may contain a Image. // DevicePathNode = OrigDevicePathNode; Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePathNode, &Handle); if (!EFI_ERROR (Status)) { // // For FwVol File system there is only a single file name that is a GUID. // FvNameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePathNode); if (FvNameGuid == NULL) { Status = EFI_INVALID_PARAMETER; } else { // // Read image from the firmware file // Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol); if (!EFI_ERROR (Status)) { SectionType = EFI_SECTION_PE32; ImageBuffer = NULL; Status = FwVol->ReadSection ( FwVol, FvNameGuid, SectionType, 0, (VOID **)&ImageBuffer, &ImageBufferSize, AuthenticationStatus ); if (EFI_ERROR (Status)) { // // Try a raw file, since a PE32 SECTION does not exist // if (ImageBuffer != NULL) { FreePool (ImageBuffer); *AuthenticationStatus = 0; } ImageBuffer = NULL; Status = FwVol->ReadFile ( FwVol, FvNameGuid, (VOID **)&ImageBuffer, &ImageBufferSize, &Type, &Attrib, AuthenticationStatus ); } } } if (!EFI_ERROR (Status)) { goto Finish; } } // // Attempt to access the file via a file system interface // DevicePathNode = OrigDevicePathNode; Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &DevicePathNode, &Handle); if (!EFI_ERROR (Status)) { Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID**)&Volume); if (!EFI_ERROR (Status)) { // // Open the Volume to get the File System handle // Status = Volume->OpenVolume (Volume, &FileHandle); if (!EFI_ERROR (Status)) { // // Duplicate the device path to avoid the access to unaligned device path node. // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH // nodes, It assures the fields in device path nodes are 2 byte aligned. // TempDevicePathNode = DuplicateDevicePath (DevicePathNode); if (TempDevicePathNode == NULL) { FileHandle->Close (FileHandle); // // Setting Status to an EFI_ERROR value will cause the rest of // the file system support below to be skipped. // Status = EFI_OUT_OF_RESOURCES; } // // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the // directory information and filename can be seperate. The goal is to inch // our way down each device path node and close the previous node // DevicePathNode = TempDevicePathNode; while (!EFI_ERROR (Status) && !IsDevicePathEnd (DevicePathNode)) { if (DevicePathType (DevicePathNode) != MEDIA_DEVICE_PATH || DevicePathSubType (DevicePathNode) != MEDIA_FILEPATH_DP) { Status = EFI_UNSUPPORTED; break; } LastHandle = FileHandle; FileHandle = NULL; Status = LastHandle->Open ( LastHandle, &FileHandle, ((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName, EFI_FILE_MODE_READ, 0 ); // // Close the previous node // LastHandle->Close (LastHandle); DevicePathNode = NextDevicePathNode (DevicePathNode); } if (!EFI_ERROR (Status)) { // // We have found the file. Now we need to read it. Before we can read the file we need to // figure out how big the file is. // FileInfo = NULL; FileInfoSize = 0; Status = FileHandle->GetInfo ( FileHandle, &gEfiFileInfoGuid, &FileInfoSize, FileInfo ); if (Status == EFI_BUFFER_TOO_SMALL) { FileInfo = AllocatePool (FileInfoSize); if (FileInfo == NULL) { Status = EFI_OUT_OF_RESOURCES; } else { Status = FileHandle->GetInfo ( FileHandle, &gEfiFileInfoGuid, &FileInfoSize, FileInfo ); } } if (!EFI_ERROR (Status) && (FileInfo != NULL)) { // // Allocate space for the file // ImageBuffer = AllocatePool ((UINTN)FileInfo->FileSize); if (ImageBuffer == NULL) { Status = EFI_OUT_OF_RESOURCES; } else { // // Read the file into the buffer we allocated // ImageBufferSize = (UINTN)FileInfo->FileSize; Status = FileHandle->Read (FileHandle, &ImageBufferSize, ImageBuffer); } } } // // Close the file and Free FileInfo and TempDevicePathNode since we are done // if (FileInfo != NULL) { FreePool (FileInfo); } if (FileHandle != NULL) { FileHandle->Close (FileHandle); } if (TempDevicePathNode != NULL) { FreePool (TempDevicePathNode); } } } if (!EFI_ERROR (Status)) { goto Finish; } } // // Attempt to access the file via LoadFile2 interface // if (!BootPolicy) { DevicePathNode = OrigDevicePathNode; Status = gBS->LocateDevicePath (&gEfiLoadFile2ProtocolGuid, &DevicePathNode, &Handle); if (!EFI_ERROR (Status)) { Status = gBS->HandleProtocol (Handle, &gEfiLoadFile2ProtocolGuid, (VOID**)&LoadFile2); if (!EFI_ERROR (Status)) { // // Call LoadFile2 with the correct buffer size // ImageBufferSize = 0; ImageBuffer = NULL; Status = LoadFile2->LoadFile ( LoadFile2, DevicePathNode, FALSE, &ImageBufferSize, ImageBuffer ); if (Status == EFI_BUFFER_TOO_SMALL) { ImageBuffer = AllocatePool (ImageBufferSize); if (ImageBuffer == NULL) { Status = EFI_OUT_OF_RESOURCES; } else { Status = LoadFile2->LoadFile ( LoadFile2, DevicePathNode, FALSE, &ImageBufferSize, ImageBuffer ); } } } if (!EFI_ERROR (Status)) { goto Finish; } } } // // Attempt to access the file via LoadFile interface // DevicePathNode = OrigDevicePathNode; Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &DevicePathNode, &Handle); if (!EFI_ERROR (Status)) { Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID**)&LoadFile); if (!EFI_ERROR (Status)) { // // Call LoadFile with the correct buffer size // ImageBufferSize = 0; ImageBuffer = NULL; Status = LoadFile->LoadFile ( LoadFile, DevicePathNode, BootPolicy, &ImageBufferSize, ImageBuffer ); if (Status == EFI_BUFFER_TOO_SMALL) { ImageBuffer = AllocatePool (ImageBufferSize); if (ImageBuffer == NULL) { Status = EFI_OUT_OF_RESOURCES; } else { Status = LoadFile->LoadFile ( LoadFile, DevicePathNode, BootPolicy, &ImageBufferSize, ImageBuffer ); } } } } Finish: if (EFI_ERROR (Status)) { if (ImageBuffer != NULL) { FreePool (ImageBuffer); ImageBuffer = NULL; } *FileSize = 0; } else { *FileSize = ImageBufferSize; } FreePool (OrigDevicePathNode); return ImageBuffer; }
EFI_STATUS LoadSupportFiles ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *FilePath, IN BOOLEAN Recursive, OUT EFI_LIST_ENTRY *SupportFileList ) /*++ Routine Description: Load all test support files. Arguments: DevicePath - Device path of the files. FilePath - Path of the files. Recursive - Recursively. SupportFileList - Pointer to the support file list. Returns: EFI_SUCCESS - Successfully. Other value - Something failed. --*/ { EFI_STATUS Status; EFI_HANDLE DeviceHandle; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE SupportDir; CHAR16 *SubDir; CHAR16 *FileName; UINTN FileInfoSize; EFI_FILE_INFO *FileInfo; EFI_SCT_TEST_FILE *SupportFile; EFI_DEVICE_PATH_PROTOCOL *RemainderPath; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; // // Check parameters // if ((DevicePath == NULL) || (FilePath == NULL) || (SupportFileList == NULL)) { return EFI_INVALID_PARAMETER; } // // Debug information // EFI_SCT_DEBUG ((EFI_SCT_D_TRACE, L"Load support files from <%s>", FilePath)); // // Locate the device handle from the device path // RemainderPath = DevicePath; Status = BS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &RemainderPath, &DeviceHandle ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Locate device handle - %r", Status)); return Status; } // // Locate the volume of the file system // Status = BS->HandleProtocol ( DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, &Vol ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Locate file system - %r", Status)); return Status; } // // Open the root volume // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Open root volume - %r", Status)); return Status; } // // Open the support directory // Status = RootDir->Open ( RootDir, &SupportDir, FilePath, EFI_FILE_MODE_READ, EFI_FILE_DIRECTORY ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Open support directory - %r", Status)); RootDir->Close (RootDir); return Status; } RootDir->Close (RootDir); // // Allocate memory for the entries in the directory // FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; Status = BS->AllocatePool ( EfiBootServicesData, FileInfoSize, &FileInfo ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Allocate pool - %r", Status)); SupportDir->Close (SupportDir); return Status; } // // Walk through each file in the directory // while (TRUE) { // // Read a file entry // FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; Status = SupportDir->Read ( SupportDir, &FileInfoSize, FileInfo ); if (EFI_ERROR (Status) || (FileInfoSize == 0)) { break; } if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { // // This is a file // if (SctStrEndWith (FileInfo->FileName, L".efi")) { // // Load the support file // FileName = PoolPrint (L"%s\\%s", FilePath, FileInfo->FileName); if (FileName == NULL) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"PoolPrint: Out of resources")); break; } Status = LoadSingleSupportFile ( DevicePath, FileName, &SupportFile ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Load a support file - %r", Status)); BS->FreePool (FileName); continue; } BS->FreePool (FileName); // // Add the support file to the support file list // InsertTailList (SupportFileList, &SupportFile->Link); } } else { // // This is a directory // if (Recursive) { // // Skip the '.' and '..' dir // if ((StrCmp (FileInfo->FileName, L".") == 0) || (StrCmp (FileInfo->FileName, L"..") == 0)) { continue; } // // Load the support files under the sub directory // SubDir = PoolPrint (L"%s\\%s", FilePath, FileInfo->FileName); if (SubDir == NULL) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"PoolPrint: Out of resources")); break; } Status = LoadSupportFiles ( DevicePath, SubDir, Recursive, SupportFileList ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Load support files - %r", Status)); BS->FreePool (SubDir); continue; } BS->FreePool (SubDir); } } } // // Free resources // BS->FreePool (FileInfo); SupportDir->Close (SupportDir); // // Done // return EFI_SUCCESS; }
EFI_STATUS BOpt_FindFiles ( IN BMM_CALLBACK_DATA *CallbackData, IN BM_MENU_ENTRY *MenuEntry ) /*++ Routine Description Find files under current directory All files and sub-directories in current directory will be stored in DirectoryMenu for future use. Arguments: FileOption -- Pointer for Dir to explore Returns: TRUE -- Get files from current dir successfully FALSE -- Can't get files from current dir --*/ { EFI_FILE_HANDLE NewDir; EFI_FILE_HANDLE Dir; EFI_FILE_INFO *DirInfo; UINTN BufferSize; UINTN DirBufferSize; BM_MENU_ENTRY *NewMenuEntry; BM_FILE_CONTEXT *FileContext; BM_FILE_CONTEXT *NewFileContext; UINTN Pass; EFI_STATUS Status; UINTN OptionNumber; FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; Dir = FileContext->FHandle; OptionNumber = 0; // // Open current directory to get files from it // Status = Dir->Open ( Dir, &NewDir, FileContext->FileName, EFI_FILE_READ_ONLY, 0 ); if (!FileContext->IsRoot) { Dir->Close (Dir); } if (EFI_ERROR (Status)) { return Status; } DirInfo = EfiLibFileInfo (NewDir); if (!DirInfo) { return EFI_NOT_FOUND; } if (!(DirInfo->Attribute & EFI_FILE_DIRECTORY)) { return EFI_INVALID_PARAMETER; } FileContext->DevicePath = EfiFileDevicePath ( FileContext->Handle, FileContext->FileName ); DirBufferSize = sizeof (EFI_FILE_INFO) + 1024; DirInfo = EfiAllocateZeroPool (DirBufferSize); if (!DirInfo) { return EFI_OUT_OF_RESOURCES; } // // Get all files in current directory // Pass 1 to get Directories // Pass 2 to get files that are EFI images // for (Pass = 1; Pass <= 2; Pass++) { NewDir->SetPosition (NewDir, 0); for (;;) { BufferSize = DirBufferSize; Status = NewDir->Read (NewDir, &BufferSize, DirInfo); if (EFI_ERROR (Status) || BufferSize == 0) { break; } if ((DirInfo->Attribute & EFI_FILE_DIRECTORY && Pass == 2) || (!(DirInfo->Attribute & EFI_FILE_DIRECTORY) && Pass == 1) ) { // // Pass 1 is for Directories // Pass 2 is for file names // continue; } if (!(BOpt_IsEfiImageName (DirInfo->FileName) || DirInfo->Attribute & EFI_FILE_DIRECTORY)) { // // Slip file unless it is a directory entry or a .EFI file // continue; } NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); if (NULL == NewMenuEntry) { return EFI_OUT_OF_RESOURCES; } NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; NewFileContext->Handle = FileContext->Handle; NewFileContext->FileName = BOpt_AppendFileName ( FileContext->FileName, DirInfo->FileName ); NewFileContext->FHandle = NewDir; NewFileContext->DevicePath = EfiFileDevicePath ( NewFileContext->Handle, NewFileContext->FileName ); NewMenuEntry->HelpString = NULL; MenuEntry->DisplayStringToken = GetStringTokenFromDepository ( CallbackData, FileOptionStrDepository ); NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY); if (NewFileContext->IsDir) { BufferSize = EfiStrLen (DirInfo->FileName) * 2 + 6; NewMenuEntry->DisplayString = EfiAllocateZeroPool (BufferSize); SPrint ( NewMenuEntry->DisplayString, BufferSize, L"<%s>", DirInfo->FileName ); } else { NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName); } NewFileContext->IsRoot = FALSE; NewFileContext->IsLoadFile = FALSE; NewFileContext->IsRemovableMedia = FALSE; NewMenuEntry->OptionNumber = OptionNumber; OptionNumber++; InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link); } } DirectoryMenu.MenuNumber = OptionNumber; SafeFreePool (DirInfo); return EFI_SUCCESS; }
/** Find files under the current directory. All files and sub-directories in current directory will be stored in DirectoryMenu for future use. @param[in] MenuEntry The Menu Entry. @retval EFI_SUCCESS Get files from current dir successfully. @return Other Can't get files from current dir. **/ EFI_STATUS FindFiles ( IN SECUREBOOT_MENU_ENTRY *MenuEntry ) { EFI_FILE_HANDLE NewDir; EFI_FILE_HANDLE Dir; EFI_FILE_INFO *DirInfo; UINTN BufferSize; UINTN DirBufferSize; SECUREBOOT_MENU_ENTRY *NewMenuEntry; SECUREBOOT_FILE_CONTEXT *FileContext; SECUREBOOT_FILE_CONTEXT *NewFileContext; UINTN Pass; EFI_STATUS Status; UINTN OptionNumber; FileContext = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext; Dir = FileContext->FHandle; OptionNumber = 0; // // Open current directory to get files from it // Status = Dir->Open ( Dir, &NewDir, FileContext->FileName, EFI_FILE_READ_ONLY, 0 ); if (!FileContext->IsRoot) { Dir->Close (Dir); } if (EFI_ERROR (Status)) { return Status; } DirInfo = FileInfo (NewDir); if (DirInfo == NULL) { return EFI_NOT_FOUND; } if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { return EFI_INVALID_PARAMETER; } FileContext->DevicePath = FileDevicePath ( FileContext->Handle, FileContext->FileName ); DirBufferSize = sizeof (EFI_FILE_INFO) + 1024; DirInfo = AllocateZeroPool (DirBufferSize); if (DirInfo == NULL) { return EFI_OUT_OF_RESOURCES; } // // Get all files in current directory // Pass 1 to get Directories // Pass 2 to get files that are EFI images // for (Pass = 1; Pass <= 2; Pass++) { NewDir->SetPosition (NewDir, 0); for (;;) { BufferSize = DirBufferSize; Status = NewDir->Read (NewDir, &BufferSize, DirInfo); if (EFI_ERROR (Status) || BufferSize == 0) { break; } if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) || ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1) ) { // // Pass 1 is for Directories // Pass 2 is for file names // continue; } NewMenuEntry = CreateMenuEntry (); if (NULL == NewMenuEntry) { return EFI_OUT_OF_RESOURCES; } NewFileContext = (SECUREBOOT_FILE_CONTEXT *) NewMenuEntry->FileContext; NewFileContext->Handle = FileContext->Handle; NewFileContext->FileName = AppendFileName ( FileContext->FileName, DirInfo->FileName ); NewFileContext->FHandle = NewDir; NewFileContext->DevicePath = FileDevicePath ( NewFileContext->Handle, NewFileContext->FileName ); NewMenuEntry->HelpString = NULL; NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY); if (NewFileContext->IsDir) { BufferSize = StrLen (DirInfo->FileName) * 2 + 6; NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize); UnicodeSPrint ( NewMenuEntry->DisplayString, BufferSize, L"<%s>", DirInfo->FileName ); } else { NewMenuEntry->DisplayString = StrDuplicate (DirInfo->FileName); } NewFileContext->IsRoot = FALSE; NewFileContext->IsLoadFile = FALSE; NewFileContext->IsRemovableMedia = FALSE; NewMenuEntry->OptionNumber = OptionNumber; OptionNumber++; InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link); } } DirectoryMenu.MenuNumber = OptionNumber; FreePool (DirInfo); return EFI_SUCCESS; }
/** * Write a file to floppy disk. */ EFI_STATUS WriteFloppyFile ( IN CHAR16 *FileName, IN OUT UINT32 Length, IN VOID *Buffer ) { EFI_STATUS Status; EFI_HANDLE DeviceHandle; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; EFI_DEVICE_PATH_PROTOCOL *DevicePath; UINTN BufLen; // // Get floppy device path // Status = GetFloppyDevicePath (&DevicePath); if (EFI_ERROR(Status)) { return Status; } // // Determine device handle for fs protocol on floppy device path // Status = gtBS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &DevicePath, &DeviceHandle ); if (EFI_ERROR(Status) ) { return Status; } // // Determine volume for file system on device handle // Status = gtBS->HandleProtocol ( DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID*)&Vol ); if (EFI_ERROR(Status) ) { return Status; } // // Open volume for file system on device path // Status = Vol->OpenVolume (Vol, &RootDir); if (Status == EFI_MEDIA_CHANGED) { // // Reopen the volume // Status = gtBS->HandleProtocol ( DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID*)&Vol ); if (EFI_ERROR(Status) ) { return Status; } Status = Vol->OpenVolume (Vol, &RootDir); } if (EFI_ERROR(Status) ) { return Status; } // // Determine the existence of the file // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0 ); if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_FOUND)) { RootDir->Close (RootDir); return Status; } if (Status == EFI_SUCCESS) { // // Delete the existent file // Status = Handle->Delete (Handle); if (Status != EFI_SUCCESS) { Handle->Close (Handle); RootDir->Close (RootDir); return Status; } } // // Create the file // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR(Status)) { RootDir->Close (RootDir); return Status; } // // Write the file // BufLen = Length; Status = Handle->Write (Handle, &BufLen, Buffer); Handle->Close (Handle); RootDir->Close (RootDir); return Status; }
/** * Read a file from floppy disk. */ EFI_STATUS ReadFloppyFile ( IN CHAR16 *FileName, OUT UINT32 *Length, OUT VOID **Buffer ) { EFI_STATUS Status; EFI_HANDLE DeviceHandle; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; EFI_FILE_INFO *FileInfo; UINTN FileInfoSize; VOID* FileBuffer; UINTN FileSize; EFI_DEVICE_PATH_PROTOCOL *DevicePath; // // Get floppy device path // Status = GetFloppyDevicePath (&DevicePath); if (EFI_ERROR(Status)) { return Status; } // // Determine device handle for fs protocol on floppy device path // Status = gtBS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &DevicePath, &DeviceHandle ); if (EFI_ERROR(Status) ) { return Status; } // // Determine volume for file system on device handle // Status = gtBS->HandleProtocol ( DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID*)&Vol ); if (EFI_ERROR(Status) ) { return Status; } // // Open volume for file system on device path // Status = Vol->OpenVolume (Vol, &RootDir); if (Status == EFI_MEDIA_CHANGED) { // // Reopen the volume // Status = gtBS->HandleProtocol ( DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID*)&Vol ); if (EFI_ERROR(Status) ) { return Status; } Status = Vol->OpenVolume (Vol, &RootDir); } if (EFI_ERROR(Status) ) { return Status; } // // Open file for read // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR(Status) ) { RootDir->Close (RootDir); return Status; } // // Get file size // FileInfoSize = 1; Status = gtBS->AllocatePool ( EfiBootServicesData, FileInfoSize, &FileInfo ); if (EFI_ERROR(Status) ) { Handle->Close (Handle); RootDir->Close (RootDir); return Status; } // // the return code should be EFI_BUFFER_TOO_SMALL // Status = Handle->GetInfo ( Handle, &gEfiFileInfoGuid, &FileInfoSize, FileInfo ); gtBS->FreePool (FileInfo); Status = gtBS->AllocatePool ( EfiBootServicesData, FileInfoSize, &FileInfo ); if (EFI_ERROR(Status) ) { Handle->Close (Handle); RootDir->Close (RootDir); return Status; } Status = Handle->GetInfo ( Handle, &gEfiFileInfoGuid, &FileInfoSize, FileInfo ); FileSize = (UINTN)FileInfo->FileSize; gtBS->FreePool (FileInfo); // // Read the file // Status = gtBS->AllocatePool ( EfiBootServicesData, FileSize, &FileBuffer ); if (EFI_ERROR(Status) ) { Handle->Close (Handle); RootDir->Close (RootDir); return Status; } Status = Handle->Read ( Handle, &FileSize, FileBuffer ); if (EFI_ERROR(Status) ) { gtBS->FreePool (FileBuffer); } else { *Buffer = FileBuffer; *Length = (UINT32)FileSize; } Handle->Close (Handle); RootDir->Close (RootDir); return Status; }
/** Get the headers (dos, image, optional header) from an image @param Device SimpleFileSystem device handle @param FileName File name for the image @param DosHeader Pointer to dos header @param Hdr The buffer in which to return the PE32, PE32+, or TE header. @retval EFI_SUCCESS Successfully get the machine type. @retval EFI_NOT_FOUND The file is not found. @retval EFI_LOAD_ERROR File is not a valid image file. **/ EFI_STATUS EFIAPI BdsLibGetImageHeader ( IN EFI_HANDLE Device, IN CHAR16 *FileName, OUT EFI_IMAGE_DOS_HEADER *DosHeader, OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr, IN OUT CHAR16 **NewFileName ) { EFI_STATUS Status; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; EFI_FILE_HANDLE Root; EFI_FILE_HANDLE ThisFile; UINTN BufferSize; UINT64 FileSize; EFI_FILE_INFO *Info; CHAR16 *FileName0 = NULL; /*application's file*/ Root = NULL; ThisFile = NULL; // // Handle the file system interface to the device // Status = gBS->HandleProtocol ( Device, &gEfiSimpleFileSystemProtocolGuid, (VOID *) &Volume ); if (EFI_ERROR (Status)) { goto Done; } Status = Volume->OpenVolume ( Volume, &Root ); if (EFI_ERROR (Status)) { Root = NULL; goto Done; } Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0); DEBUG((DEBUG_INFO, "%a:%d Open FileName:'%s' - %r \n", __FILE__, __LINE__, FileName, Status)); if (EFI_ERROR (Status)) { goto Done; } // // Get file size // do { BufferSize = 0; Info = NULL; /* Get right size we need to allocate */ Status = ThisFile->GetInfo ( ThisFile, &gEfiFileInfoGuid, &BufferSize, Info ); if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) { goto Done; } Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info); if (EFI_ERROR (Status)) { goto Done; } Status = ThisFile->GetInfo ( ThisFile, &gEfiFileInfoGuid, &BufferSize, Info ); if (!EFI_ERROR (Status)) { DEBUG((DEBUG_INFO, "%a:%d Open FileName:%s from Info %r \n", __FILE__, __LINE__, Info->FileName, Status)); Status = gBS->AllocatePool (EfiBootServicesData, StrLen(Info->FileName), (VOID **) &FileName0); StrCpy(FileName0, Info->FileName); if (EFI_ERROR (Status)) { goto Done; } break; } if (Status != EFI_BUFFER_TOO_SMALL) { FreePool (Info); goto Done; } FreePool (Info); } while (TRUE); FileSize = Info->FileSize; FreePool (Info); // // Read dos header // #ifndef VBOX BufferSize = sizeof (EFI_IMAGE_DOS_HEADER); Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader); if (EFI_ERROR (Status) || BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) || FileSize <= DosHeader->e_lfanew || DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) { Status = EFI_LOAD_ERROR; goto Done; } // // Move to PE signature // Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew); if (EFI_ERROR (Status)) { Status = EFI_LOAD_ERROR; goto Done; } // // Read and check PE signature // BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION); Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32); if (EFI_ERROR (Status) || BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) || Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) { Status = EFI_LOAD_ERROR; goto Done; } // // Check PE32 or PE32+ magic // if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC && Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { Status = EFI_LOAD_ERROR; goto Done; } #endif Done: if (!EFI_ERROR(Status)) { EFI_STATUS Status0; /* We need prepare the correct file path for case sensitive loaders ... Sigh.*/ CHAR16 *dup; CHAR16 *p, *pp; dup = AllocateZeroPool(StrSize(FileName)); StrCpy(dup, FileName); pp = p = dup; while (*p != L'\0') { BufferSize = 0; Info = NULL; if (*p == L'\\' && p != dup) { *p = L'\0'; Status0 = Root->Open (Root, &ThisFile, dup, EFI_FILE_MODE_READ, 1); DEBUG((DEBUG_INFO, "%a:%d Open FileName:%s - %r \n", __FILE__, __LINE__, dup, Status)); if (EFI_ERROR (Status)) { goto Done; } /* Get right size we need to allocate */ Status0 = ThisFile->GetInfo ( ThisFile, &gEfiFileInfoGuid, &BufferSize, Info ); if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) { DEBUG((DEBUG_INFO, "%a:%d GetInfo(1) FileName:%s %r \n", __FILE__, __LINE__, FileName, Status)); goto Done; } Status0 = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info); if (EFI_ERROR (Status)) { goto Done; } Status0 = ThisFile->GetInfo ( ThisFile, &gEfiFileInfoGuid, &BufferSize, Info ); if (!EFI_ERROR (Status0)) { DEBUG((DEBUG_INFO, "%a:%d Open FileName:%s from Info %r \n", __FILE__, __LINE__, Info->FileName, Status)); StrCpy(pp + 1, Info->FileName); } * p = L'\\'; pp = p; } p++; } StrCpy(pp + 1, FileName0); DEBUG((DEBUG_INFO, "%a:%d NewFileName:'%s'\n", __FILE__, __LINE__, dup)); *NewFileName = dup; } DEBUG((DEBUG_INFO, "%a:%d %s - %r\n", __FILE__, __LINE__, FileName, Status)); if (ThisFile != NULL) { ThisFile->Close (ThisFile); } if (Root != NULL) { Root->Close (Root); } return Status; }
/** Internal work function to fill in EFI_OPEN_FILE information for the Fs and BlkIo @param File Open file handle @param FileName Name of file after device stripped off **/ EFI_STATUS EblFileDevicePath ( IN OUT EFI_OPEN_FILE *File, IN CHAR8 *FileName, IN CONST UINT64 OpenMode ) { EFI_STATUS Status; UINTN Size; FILEPATH_DEVICE_PATH *FilePath; EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; CHAR16 UnicodeFileName[MAX_PATHNAME]; EFI_BLOCK_IO_PROTOCOL *BlkIo; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; EFI_FILE_HANDLE Root; if ( *FileName != 0 ) { AsciiStrToUnicodeStr (FileName, UnicodeFileName); } else { AsciiStrToUnicodeStr ("\\", UnicodeFileName); } Size = StrSize (UnicodeFileName); FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof (EFI_DEVICE_PATH_PROTOCOL)); if (FileDevicePath != NULL) { FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath; FilePath->Header.Type = MEDIA_DEVICE_PATH; FilePath->Header.SubType = MEDIA_FILEPATH_DP; CopyMem (&FilePath->PathName, UnicodeFileName, Size); SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header)); if (File->EfiHandle != NULL) { File->DevicePath = DevicePathFromHandle (File->EfiHandle); } File->DevicePath = AppendDevicePath (File->DevicePath, FileDevicePath); FreePool (FileDevicePath); } Status = gBS->HandleProtocol (File->EfiHandle, &gEfiBlockIoProtocolGuid, (VOID **)&BlkIo); if (!EFI_ERROR (Status)) { File->FsBlockIoMedia = BlkIo->Media; File->FsBlockIo = BlkIo; // If we are not opening the device this will get over written with file info File->MaxPosition = MultU64x32 (BlkIo->Media->LastBlock + 1, BlkIo->Media->BlockSize); } if (File->Type == EfiOpenFileSystem) { Status = gBS->HandleProtocol (File->EfiHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Fs); if (!EFI_ERROR (Status)) { Status = Fs->OpenVolume (Fs, &Root); if (!EFI_ERROR (Status)) { // Get information about the volume Size = 0; Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo); if (Status == EFI_BUFFER_TOO_SMALL) { File->FsInfo = AllocatePool (Size); Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, File->FsInfo); } // Get information about the file Status = Root->Open (Root, &File->FsFileHandle, UnicodeFileName, OpenMode, 0); if (!EFI_ERROR (Status)) { Size = 0; Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, NULL); if (Status == EFI_BUFFER_TOO_SMALL) { File->FsFileInfo = AllocatePool (Size); Status = File->FsFileHandle->GetInfo (File->FsFileHandle, &gEfiFileInfoGuid, &Size, File->FsFileInfo); if (!EFI_ERROR (Status)) { File->Size = (UINTN)File->FsFileInfo->FileSize; File->MaxPosition = (UINT64)File->Size; } } } Root->Close (Root); } } } else if (File->Type == EfiOpenBlockIo) { File->Size = (UINTN)File->MaxPosition; } return Status; }
EFI_STATUS EFIAPI TOLOpen ( IN EFI_TEST_OUTPUT_LIBRARY_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *FileName, IN BOOLEAN OverwriteFile, OUT EFI_FILE **FileHandle ) /*++ Routine Description: One interface function of the TestOutputLibrary to open a file. Arguments: This - the protocol instance structure. DevicePath - the file's root device path. FileName - the file's name relative to the root. OverwriteFile - whether to overwrite the file. FileHandle - return the file's handle. Returns: EFI_SUCCESS - open the file successfully. EFI_NOT_READY - to overwrite an opened file is not allowed. EFI_OUT_OF_RESOURCES - not enough memory. --*/ { EFI_STATUS Status; TEST_OUTPUT_FILE *OutputFile; TEST_OUTPUT_PRIVATE_DATA *Private; EFI_HANDLE DeviceHandle; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; UINTN BufSize; CHAR8 Buffer[2]; EFI_DEVICE_PATH_PROTOCOL *PreDevicePath; Private = TEST_OUTPUT_PRIVATE_DATA_FROM_THIS (This); // // Search the file in OutputFileList to see whether the file has been opened // OutputFile = Private->OutputFileList; while (OutputFile != NULL) { if ((SctDevicePathCompare (DevicePath, OutputFile->DevicePath) == 0) && (StrCmp (FileName, OutputFile->FileName) == 0)) { break; } OutputFile = OutputFile->Next; } if (OutputFile == NULL) { // // Not found, open the file and add to the list // PreDevicePath = DevicePath; // // Determine device handle for fs protocol on specified device path // Status = BS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &PreDevicePath, &DeviceHandle ); if (EFI_ERROR (Status)) { return Status; } // // Determine volume for file system on device handle // Status = BS->HandleProtocol ( DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID*)&Vol ); if (EFI_ERROR (Status)) { return Status; } // // Open volume for file system on device path // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { return Status; } // // Determine the existence of the file // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, 0 ); if (Status == EFI_NOT_FOUND) { // // The file not exist, create it // Status = SctCreateFile (RootDir, FileName, &Handle); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } // // Write the head of Unicode text file // Buffer[0] = 0xff; Buffer[1] = 0xfe; BufSize = 2; Status = Handle->Write (Handle, &BufSize, Buffer); if (EFI_ERROR (Status)) { Handle->Close (Handle); return Status; } } else if (EFI_ERROR (Status)) { RootDir->Close(RootDir); return Status; } if (OverwriteFile) { // // Overwrite the file // // // Delete the file // Status = Handle->Delete (Handle); // // EFI_FILE.Delete() return a warning status // if (Status != EFI_SUCCESS) { RootDir->Close (RootDir); return EFI_UNSUPPORTED; } // // Recreate the file // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } // // Write the head of Unicode text file // Buffer[0] = 0xff; Buffer[1] = 0xfe; BufSize = 2; Status = Handle->Write (Handle, &BufSize, Buffer); if (EFI_ERROR (Status)) { Handle->Close (Handle); return Status; } } else { // // Append the file // // // Set position to the end of file // Status = Handle->SetPosition (Handle, (UINT64)-1); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } } RootDir->Close (RootDir); // // Add the opened file to the OutputFileList // Status = BS->AllocatePool ( EfiBootServicesData, sizeof(TEST_OUTPUT_FILE), (VOID **)&OutputFile ); if (EFI_ERROR (Status)) { Handle->Close (Handle); return Status; } ZeroMem (OutputFile, sizeof(TEST_OUTPUT_FILE)); OutputFile->DevicePath = DuplicateDevicePath (DevicePath); if (OutputFile->DevicePath == NULL) { Handle->Close (Handle); BS->FreePool (OutputFile); return EFI_OUT_OF_RESOURCES; } OutputFile->FileName = StrDuplicate (FileName); if (OutputFile->FileName == NULL) { Handle->Close (Handle); BS->FreePool (OutputFile->DevicePath); BS->FreePool (OutputFile); return EFI_OUT_OF_RESOURCES; } OutputFile->FileHandle = Handle; OutputFile->Next = Private->OutputFileList; Private->OutputFileList = OutputFile; } // // Add the open count and return the file handle // OutputFile->OpenCount ++; *FileHandle = OutputFile->FileHandle; return EFI_SUCCESS; }
EFI_STATUS EntryPoint ( EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable ) { EFI_STATUS Status = 0; UINTN i = 0; EFI_FILE_IO_INTERFACE *Vol = 0; EFI_FILE_HANDLE RootFs = 0; EFI_FILE_HANDLE FileHandle = 0; EFI_HANDLE* Search = 0; EFI_HANDLE DeviceHandle = 0; UINTN Size = 0; VOID* BootmgrBuffer = 0; EFI_FILE_INFO* FileInfoBuffer = 0; EFI_HANDLE BootmgrHandle = NULL; EFI_LOADED_IMAGE *BootmgrLoadedImage = 0; EFI_LOADED_IMAGE *LoadedImage = 0; CHAR16 *BOOTMGFW = L"\\EFI\\Microsoft\\BOOT\\BOOTMGFW.EFI"; CHAR16 *BOOTMGFW_BAK = L"\\EFI\\Microsoft\\BOOT\\BOOTMGFW.BAK"; EFI_DEVICE_PATH_PROTOCOL* DevPath = 0; ST = SystemTable; BS = ST->BootServices; RS = ST->RuntimeServices; Status = Main(); //=========================================================================// // get device handle for the loaded (this) image // //=========================================================================// Status = BS->HandleProtocol(ImageHandle, &gLoadedImageProtocol, (VOID **) &LoadedImage); if (EFI_ERROR (Status)) { return Status; } DeviceHandle = LoadedImage->DeviceHandle; //=========================================================================// // get file io interface for device image was loaded from // //=========================================================================// Status = BS->HandleProtocol(DeviceHandle, &gFileSystemProtocol, (VOID **) &Vol); if (EFI_ERROR (Status)) { return Status; } //=========================================================================// // open file system root for the device image was loaded from // //=========================================================================// Status = Vol->OpenVolume(Vol, &RootFs); if (EFI_ERROR (Status)) { return Status; } //=========================================================================// // try to open bootmgfw on file system that image was loaded from // //=========================================================================// //=========================================================================// // look for BOOTMGFW.BAK first to support BOOTMGFW.EFI replacement // // install method. // //=========================================================================// Status = RootFs->Open(RootFs, &FileHandle, BOOTMGFW_BAK, EFI_FILE_MODE_READ, 0); if (Status == EFI_SUCCESS) { BOOTMGFW = BOOTMGFW_BAK; } else if (Status == EFI_NOT_FOUND) { /* if BOOTMGFW.BAK not found search for BOOTMGFW.EFI */ Status = RootFs->Open(RootFs, &FileHandle, BOOTMGFW, EFI_FILE_MODE_READ, 0); if (EFI_ERROR (Status)) { RootFs->Close(RootFs); switch(Status) { case EFI_NOT_FOUND: //=========================================================================// // failed to find bootmgfw on same device, look for it on other devices. // // get array of device handle's that bootmgfw might be installed on // // first get size of array // //=========================================================================// Size = 0; Status = BS->LocateHandle(ByProtocol, &gFileSystemProtocol, NULL, &Size, 0); if(Status == EFI_BUFFER_TOO_SMALL) { /* allocate memory for array */ Search = (EFI_HANDLE *) AllocatePool(Size); } if(Search) { /* get the array */ Status = BS->LocateHandle(ByProtocol, &gFileSystemProtocol, NULL, &Size, Search); /* loop through handle's open each file system & try to open bootmgfw */ if(Status == EFI_SUCCESS) { for(i = 0; i < Size / sizeof(EFI_HANDLE); i++) { /* we already know bootmgfw is not in the same device as the loaded image, skip */ if(Search[i] == DeviceHandle) { continue; } /* get file io interface */ Status = BS->HandleProtocol(Search[i], &gFileSystemProtocol, (VOID **) &Vol); if(EFI_ERROR (Status)) { continue; } /* open file system root on the device */ Status = Vol->OpenVolume(Vol, &RootFs); if(EFI_ERROR (Status)) { continue; } /* try to open bootmgfw on the file system */ Status = RootFs->Open(RootFs, &FileHandle, BOOTMGFW, EFI_FILE_MODE_READ, 0); if(Status == EFI_SUCCESS) { /* found it, set DeviceHandle & break the loop */ DeviceHandle = Search[i]; break; } /* clean up for next pass */ RootFs->Close(RootFs); } /* free array of device handles, if EFI_SUCCESS break */ /* the switch/case else fall through to the error */ BS->FreePool(Search); if(Status == EFI_SUCCESS) { break; } } } default: return Status; } } } else { return Status; } //============================================================================// // RootFs is open, FileHandle is open, DeviceHandle is set // // get size of bootmgfw.efi by retriving an EFI_FILE_INFO // // first get the size of the STRUCT and allocate memory // //============================================================================// Size = 0; Status = FileHandle->GetInfo(FileHandle, &gFileInfo, &Size, NULL); if(Status == EFI_BUFFER_TOO_SMALL) { /* allocate memory for EFI_FILE_INFO */ FileInfoBuffer = (EFI_FILE_INFO *) AllocatePool(Size); } else { FileHandle->Close(FileHandle); RootFs->Close(RootFs); return Status; } //=========================================================================// // get EFI_FILE_INFO for bootmgfw.efi // //=========================================================================// Status = FileHandle->GetInfo(FileHandle, &gFileInfo, &Size, FileInfoBuffer); if(EFI_ERROR(Status)) { FileHandle->Close(FileHandle); RootFs->Close(RootFs); return Status; } //=========================================================================// // get size of bootmgfw.efi // //=========================================================================// Size = FileInfoBuffer->FileSize; //=========================================================================// // free EFI_FILE_INFO buffer // //=========================================================================// BS->FreePool(FileInfoBuffer); //=========================================================================// // allocate memory for bootmgfw.efi // //=========================================================================// BootmgrBuffer = AllocatePool(Size); if (!BootmgrBuffer) { BS->FreePool(BootmgrBuffer); FileHandle->Close(FileHandle); RootFs->Close(RootFs); return Status; } //=========================================================================// // read bootmgfw.efi into buffer // //=========================================================================// Status = FileHandle->Read(FileHandle, &Size, BootmgrBuffer); if (EFI_ERROR (Status)) { BS->FreePool(BootmgrBuffer); FileHandle->Close(FileHandle); RootFs->Close(RootFs); return Status; } //=========================================================================// // close handle for bootmgfw.efi // //=========================================================================// Status = FileHandle->Close(FileHandle); if (EFI_ERROR (Status)) { } //=========================================================================// // close handle for file system root // //=========================================================================// Status = RootFs->Close(RootFs); if (EFI_ERROR (Status)) { } //=========================================================================// // load bootmgfw.efi from buffer to execution space // //=========================================================================// Status = BS->LoadImage(FALSE, ImageHandle, 0, BootmgrBuffer, Size, &BootmgrHandle); if (EFI_ERROR (Status)) { BS->FreePool(BootmgrBuffer); return Status; } BS->FreePool(BootmgrBuffer); //=========================================================================// // set bootmgfw.efi start variables // //=========================================================================// Status = BS->HandleProtocol(BootmgrHandle, &gLoadedImageProtocol, (VOID **) &BootmgrLoadedImage); if (EFI_ERROR (Status)) { return Status; } BootmgrLoadedImage->DeviceHandle = DeviceHandle; BootmgrLoadedImage->ParentHandle = NULL; BootmgrLoadedImage->FilePath = FileDevicePath(DeviceHandle, BOOTMGFW); //=========================================================================// // start bootmgfw.efi execution // //=========================================================================// Status = BS->StartImage(BootmgrHandle, 0, 0); //============================================================================// // should never get here show error // //============================================================================// if (BootmgrHandle != NULL) { Status = BS->UnloadImage(BootmgrHandle); } return Status; }
BOOLEAN FileExist ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *FileName ) /*++ Routine Description: Check whether a file exists. --*/ { EFI_STATUS Status; EFI_HANDLE DeviceHandle; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; // // Check parameters // if ((DevicePath == NULL) || (FileName == NULL)) { return FALSE; } // // Locate the device handle // RemainingDevicePath = DevicePath; Status = BS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &RemainingDevicePath, &DeviceHandle ); if (EFI_ERROR (Status)) { return FALSE; } // // Locate the simple file system // Status = BS->HandleProtocol ( DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, &Vol ); if (EFI_ERROR (Status)) { return FALSE; } // // Open the root directory // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { return FALSE; } // // Open the file // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return FALSE; } RootDir->Close (RootDir); Handle->Close (Handle); return TRUE; }
EFI_STATUS FileOpen ( IN EFI_DEVICE_PATH_PROTOCOL *Device, IN CHAR16 *MappedFile, OUT EFI_FILE_PROTOCOL **File, IN UINT64 OpenMode ) { EFI_HANDLE Handle; EFI_FILE_HANDLE Root; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; EFI_STATUS Status; *File = NULL; Status = gBS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &Device, &Handle ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->HandleProtocol ( Handle, &gEfiSimpleFileSystemProtocolGuid, &Volume ); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { return Status; } // // Open the root directory of the volume // Root = NULL; Status = Volume->OpenVolume ( Volume, &Root ); ASSERT_EFI_ERROR (Status); ASSERT (Root != NULL); // // Open file // Status = Root->Open ( Root, File, MappedFile, OpenMode, 0 ); if (EFI_ERROR (Status)) { *File = NULL; } // // Close the Root directory // Root->Close (Root); return Status; }
/** Get the headers (dos, image, optional header) from an image @param Device SimpleFileSystem device handle @param FileName File name for the image @param DosHeader Pointer to dos header @param Hdr The buffer in which to return the PE32, PE32+, or TE header. @retval EFI_SUCCESS Successfully get the machine type. @retval EFI_NOT_FOUND The file is not found. @retval EFI_LOAD_ERROR File is not a valid image file. **/ EFI_STATUS EFIAPI BdsLibGetImageHeader ( IN EFI_HANDLE Device, IN CHAR16 *FileName, OUT EFI_IMAGE_DOS_HEADER *DosHeader, OUT EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr ) { EFI_STATUS Status; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; EFI_FILE_HANDLE Root; EFI_FILE_HANDLE ThisFile; UINTN BufferSize; UINT64 FileSize; EFI_FILE_INFO *Info; Root = NULL; ThisFile = NULL; // // Handle the file system interface to the device // Status = gBS->HandleProtocol ( Device, &gEfiSimpleFileSystemProtocolGuid, (VOID *) &Volume ); if (EFI_ERROR (Status)) { goto Done; } Status = Volume->OpenVolume ( Volume, &Root ); if (EFI_ERROR (Status)) { Root = NULL; goto Done; } // ASSERT (Root != NULL); Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0); if (EFI_ERROR (Status)) { goto Done; } // ASSERT (ThisFile != NULL); // // Get file size // BufferSize = SIZE_OF_EFI_FILE_INFO + 200; do { Info = NULL; Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info); if (EFI_ERROR (Status)) { goto Done; } Status = ThisFile->GetInfo ( ThisFile, &gEfiFileInfoGuid, &BufferSize, Info ); if (!EFI_ERROR (Status)) { break; } if (Status != EFI_BUFFER_TOO_SMALL) { FreePool (Info); goto Done; } FreePool (Info); } while (TRUE); FileSize = Info->FileSize; FreePool (Info); // // Read dos header // BufferSize = sizeof (EFI_IMAGE_DOS_HEADER); Status = ThisFile->Read (ThisFile, &BufferSize, DosHeader); if (EFI_ERROR (Status) || BufferSize < sizeof (EFI_IMAGE_DOS_HEADER) || FileSize <= DosHeader->e_lfanew || DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) { Status = EFI_LOAD_ERROR; goto Done; } // // Move to PE signature // Status = ThisFile->SetPosition (ThisFile, DosHeader->e_lfanew); if (EFI_ERROR (Status)) { Status = EFI_LOAD_ERROR; goto Done; } // // Read and check PE signature // BufferSize = sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION); Status = ThisFile->Read (ThisFile, &BufferSize, Hdr.Pe32); if (EFI_ERROR (Status) || BufferSize < sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION) || Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) { Status = EFI_LOAD_ERROR; goto Done; } // // Check PE32 or PE32+ magic // if (Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC && Hdr.Pe32->OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { Status = EFI_LOAD_ERROR; goto Done; } Done: if (ThisFile != NULL) { ThisFile->Close (ThisFile); } if (Root != NULL) { Root->Close (Root); } return Status; }
EFI_STATUS EFIAPI TrlReadResetRecord ( IN EFI_TEST_RECOVERY_LIBRARY_PROTOCOL *This, OUT UINTN *Size, OUT VOID *Buffer ) /*++ Routine Description: One interface function of the TestRecoveryLibrary to read reset record. Arguments: This - the protocol instance structure. Size - return the bytes been read. Buffer - buffer to store the record, it can't less than 1024Bytes. Returns: EFI_SUCCESS - read the record successfully. EFI_INVALID_PARAMETER - invalid parameters. --*/ { EFI_STATUS Status; EFI_HANDLE DeviceHandle; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; TEST_RECOVERY_PRIVATE_DATA *Private; EFI_DEVICE_PATH_PROTOCOL *PreDevicePath; Private = TEST_RECOVERY_PRIVATE_DATA_FROM_TRL (This); // // Determine device handle for fs protocol on specified device path // PreDevicePath = Private->DevicePath; Status = gBS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &PreDevicePath, &DeviceHandle ); if (EFI_ERROR (Status)) { return Status; } // // Determine volume for file system on device handle // Status = gBS->HandleProtocol ( DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID*)&Vol ); if (EFI_ERROR (Status)) { return Status; } // // Open volume for file system on device path // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { return Status; } // // Open file for read // Status = RootDir->Open ( RootDir, &Handle, Private->FileName, EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } *Size = MAX_BUFFER_SIZE; Status = Handle->Read (Handle, Size, Buffer); Handle->Close (Handle); RootDir->Close (RootDir); return Status; }
CHAR16 * GetFileNameUnderDir ( IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, IN CHAR16 *DirName, IN CHAR16 *FileName, IN OUT UINTN *Index ) /*++ Routine Description: Get file name under this dir with index Arguments: DebuggerPrivate - EBC Debugger private data structure DirName - The dir to be read. FileName - The file name pattern under this dir Index - The file index under this dir Returns: File Name which match the pattern and index. --*/ { EFI_STATUS Status; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; UINTN FileInfoSize; EFI_FILE_INFO *FileInfo; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; VOID *TempName; UINTN FileIndex; if (DebuggerPrivate->Vol == NULL) { Status = gBS->LocateProtocol ( &gEfiSimpleFileSystemProtocolGuid, NULL, &DebuggerPrivate->Vol ); if (EFI_ERROR(Status)) { return NULL; } } Vol = DebuggerPrivate->Vol; // // Open the root directory // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { return NULL; } // // Open the file // Status = RootDir->Open ( RootDir, &Handle, DirName, EFI_FILE_MODE_READ, EFI_FILE_DIRECTORY ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return NULL; } RootDir->Close (RootDir); // // Set Dir Position // Status = Handle->SetPosition (Handle, 0); if (EFI_ERROR (Status)) { Handle->Close (Handle); return NULL; } // // Get the file information // FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; FileInfo = EfiLibAllocateZeroPool (FileInfoSize); if (FileInfo == NULL) { Handle->Close (Handle); return NULL; } // // Walk through each file in the directory // FileIndex = 0; TempName = NULL; while (TRUE) { // // Read a file entry // FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; Status = Handle->Read ( Handle, &FileInfoSize, FileInfo ); if (EFI_ERROR (Status) || (FileInfoSize == 0)) { break; } if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0) { // // This is a file // // // Only deal with the EFI key file // if (!StrEndWith (FileInfo->FileName, FileName)) { continue; } if (FileIndex == *Index) { TempName = StrDuplicate (FileInfo->FileName); *Index = *Index + 1; break; } FileIndex ++; } } // // Free resources // gBS->FreePool (FileInfo); Handle->Close (Handle); return TempName; }
EFI_STATUS EFIAPI TrlWriteResetRecord ( IN EFI_TEST_RECOVERY_LIBRARY_PROTOCOL *This, IN UINTN Size, IN VOID *Buffer ) /*++ Routine Description: One interface function of the TestRecoveryLibrary to write reset record. Arguments: This - the protocol instance structure. Size - the bytes to be write, it can't bigger than 1024Bytes. Buffer - buffer contain the record to be written. Returns: EFI_SUCCESS - write the record successfully. EFI_INVALID_PARAMETER - invalid parameters. --*/ { EFI_STATUS Status; EFI_HANDLE DeviceHandle; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol; TEST_RECOVERY_PRIVATE_DATA *Private; EFI_DEVICE_PATH_PROTOCOL *PreDevicePath; Private = TEST_RECOVERY_PRIVATE_DATA_FROM_TRL (This); // // Determine device handle for fs protocol on specified device path // PreDevicePath = Private->DevicePath; Status = gBS->LocateDevicePath ( &gEfiSimpleFileSystemProtocolGuid, &PreDevicePath, &DeviceHandle ); if (EFI_ERROR (Status)) { return Status; } // // Determine volume for file system on device handle // Status = gBS->HandleProtocol ( DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID*)&Vol ); if (EFI_ERROR (Status)) { return Status; } // // Open volume for file system on device path // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { return Status; } // // Open file for read // Status = RootDir->Open ( RootDir, &Handle, Private->FileName, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0 ); if (Status == EFI_NOT_FOUND) { // // The file not exist, create it // Status = RootDir->Open ( RootDir, &Handle, Private->FileName, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } } else if (Status == EFI_SUCCESS) { // // The file exist, delete it // Status = Handle->Delete (Handle); // // EFI_FILE.Delete() return a warning status // if (Status != EFI_SUCCESS) { Handle->Close (Handle); RootDir->Close (RootDir); return EFI_UNSUPPORTED; } // // Recreate the file // Status = RootDir->Open ( RootDir, &Handle, Private->FileName, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } } else { RootDir->Close (RootDir); return Status; } // // Write buffer // Status = Handle->Write (Handle, &Size, Buffer); Handle->Close (Handle); RootDir->Close (RootDir); return Status; }
/** Function to get a full filename given a EFI_FILE_HANDLE somewhere lower on the directory 'stack'. If the file is a directory, then append the '\' char at the end of name string. If it's not a directory, then the last '\' should not be added. if Handle is NULL, return EFI_INVALID_PARAMETER @param[in] Handle Handle to the Directory or File to create path to. @param[out] FullFileName pointer to pointer to generated full file name. It is the responsibility of the caller to free this memory with a call to FreePool(). @retval EFI_SUCCESS the operation was sucessful and the FullFileName is valid. @retval EFI_INVALID_PARAMETER Handle was NULL. @retval EFI_INVALID_PARAMETER FullFileName was NULL. @retval EFI_OUT_OF_RESOURCES a memory allocation failed. **/ EFI_STATUS EFIAPI FileHandleGetFileName ( IN CONST EFI_FILE_HANDLE Handle, OUT CHAR16 **FullFileName ) { EFI_STATUS Status; UINTN Size; EFI_FILE_HANDLE CurrentHandle; EFI_FILE_HANDLE NextHigherHandle; EFI_FILE_INFO *FileInfo; Size = 0; // // Check our parameters // if (FullFileName == NULL || Handle == NULL) { return (EFI_INVALID_PARAMETER); } *FullFileName = NULL; CurrentHandle = NULL; Status = Handle->Open(Handle, &CurrentHandle, L".", EFI_FILE_MODE_READ, 0); if (!EFI_ERROR(Status)) { // // Reverse out the current directory on the device // for (;;) { FileInfo = FileHandleGetInfo(CurrentHandle); if (FileInfo == NULL) { Status = EFI_OUT_OF_RESOURCES; break; } else { // // We got info... do we have a name? if yes precede the current path with it... // if (StrLen (FileInfo->FileName) == 0) { if (*FullFileName == NULL) { ASSERT((*FullFileName == NULL && Size == 0) || (*FullFileName != NULL)); *FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0); } FreePool(FileInfo); break; } else { if (*FullFileName == NULL) { ASSERT((*FullFileName == NULL && Size == 0) || (*FullFileName != NULL)); *FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0); } ASSERT((*FullFileName == NULL && Size == 0) || (*FullFileName != NULL)); *FullFileName = StrnCatGrowLeft(FullFileName, &Size, FileInfo->FileName, 0); *FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0); FreePool(FileInfo); } } // // Move to the parent directory // Status = CurrentHandle->Open (CurrentHandle, &NextHigherHandle, L"..", EFI_FILE_MODE_READ, 0); if (EFI_ERROR (Status)) { break; } FileHandleClose(CurrentHandle); CurrentHandle = NextHigherHandle; } } else if (Status == EFI_NOT_FOUND) { Status = EFI_SUCCESS; ASSERT((*FullFileName == NULL && Size == 0) || (*FullFileName != NULL)); *FullFileName = StrnCatGrowLeft(FullFileName, &Size, L"\\", 0); } if (*FullFileName != NULL && (*FullFileName)[StrLen(*FullFileName) - 1] == L'\\' && StrLen(*FullFileName) > 1 && FileHandleIsDirectory(Handle) == EFI_NOT_FOUND ) { (*FullFileName)[StrLen(*FullFileName) - 1] = CHAR_NULL; } if (CurrentHandle != NULL) { CurrentHandle->Close (CurrentHandle); } if (EFI_ERROR(Status) && *FullFileName != NULL) { FreePool(*FullFileName); } return (Status); }
/** Read a file from this volume. @param[in] Vol File System Volume @param[in] FileName The file to be read. @param[out] BufferSize The file buffer size @param[out] Buffer The file buffer @retval EFI_SUCCESS Read file successfully @retval EFI_NOT_FOUND File not found **/ EFI_STATUS ReadFileFromVol ( IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Vol, IN CHAR16 *FileName, OUT UINTN *BufferSize, OUT VOID **Buffer ) { EFI_STATUS Status; EFI_FILE_HANDLE RootDir; EFI_FILE_HANDLE Handle; UINTN FileInfoSize; EFI_FILE_INFO *FileInfo; UINTN TempBufferSize; VOID *TempBuffer; // // Open the root directory // Status = Vol->OpenVolume (Vol, &RootDir); if (EFI_ERROR (Status)) { return Status; } // // Open the file // Status = RootDir->Open ( RootDir, &Handle, FileName, EFI_FILE_MODE_READ, 0 ); if (EFI_ERROR (Status)) { RootDir->Close (RootDir); return Status; } RootDir->Close (RootDir); // // Get the file information // FileInfoSize = sizeof(EFI_FILE_INFO) + 1024; FileInfo = AllocateZeroPool (FileInfoSize); if (FileInfo == NULL) { Handle->Close (Handle); return Status; } Status = Handle->GetInfo ( Handle, &gEfiFileInfoGuid, &FileInfoSize, FileInfo ); if (EFI_ERROR (Status)) { Handle->Close (Handle); gBS->FreePool (FileInfo); return Status; } // // Allocate buffer for the file data. The last CHAR16 is for L'\0' // TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16); TempBuffer = AllocateZeroPool (TempBufferSize); if (TempBuffer == NULL) { Handle->Close (Handle); gBS->FreePool (FileInfo); return Status; } gBS->FreePool (FileInfo); // // Read the file data to the buffer // Status = Handle->Read ( Handle, &TempBufferSize, TempBuffer ); if (EFI_ERROR (Status)) { Handle->Close (Handle); gBS->FreePool (TempBuffer); return Status; } Handle->Close (Handle); *BufferSize = TempBufferSize; *Buffer = TempBuffer; return EFI_SUCCESS; }
/** Find the file handle from the input device path info. @param RootDirectory Device path info. @param RetFileHandle Return the file handle for the input device path. @param ParentFileName Parent file name. @param DeviceHandle Driver handle for this partition. @retval EFI_SUCESS Find the file handle success. @retval Other Find the file handle failure. **/ EFI_STATUS LibGetFileHandleFromDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *RootDirectory, OUT EFI_FILE_HANDLE *RetFileHandle, OUT UINT16 **ParentFileName, OUT EFI_HANDLE *DeviceHandle ) { EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; EFI_DEVICE_PATH_PROTOCOL *TempDevicePathNode; EFI_STATUS Status; EFI_HANDLE Handle; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; EFI_FILE_HANDLE FileHandle; EFI_FILE_HANDLE LastHandle; CHAR16 *TempPath; *ParentFileName = NULL; // // Attempt to access the file via a file system interface // DevicePathNode = RootDirectory; Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &DevicePathNode, &Handle); if (EFI_ERROR (Status)) { return Status; } Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID**)&Volume); if (EFI_ERROR (Status)) { return Status; } // // Open the Volume to get the File System handle // Status = Volume->OpenVolume (Volume, &FileHandle); if (EFI_ERROR (Status)) { return Status; } *DeviceHandle = Handle; if (IsDevicePathEnd(DevicePathNode)) { *ParentFileName = AllocateCopyPool (StrSize (L"\\"), L"\\"); *RetFileHandle = FileHandle; return EFI_SUCCESS; } // // Duplicate the device path to avoid the access to unaligned device path node. // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH // nodes, It assures the fields in device path nodes are 2 byte aligned. // TempDevicePathNode = DuplicateDevicePath (DevicePathNode); if (TempDevicePathNode == NULL) { // // Setting Status to an EFI_ERROR value will cause the rest of // the file system support below to be skipped. // Status = EFI_OUT_OF_RESOURCES; goto Done; } // // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the // directory information and filename can be seperate. The goal is to inch // our way down each device path node and close the previous node // DevicePathNode = TempDevicePathNode; while (!EFI_ERROR (Status) && !IsDevicePathEnd (DevicePathNode)) { if (DevicePathType (DevicePathNode) != MEDIA_DEVICE_PATH || DevicePathSubType (DevicePathNode) != MEDIA_FILEPATH_DP) { Status = EFI_UNSUPPORTED; goto Done; } LastHandle = FileHandle; FileHandle = NULL; Status = LastHandle->Open ( LastHandle, &FileHandle, ((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName, EFI_FILE_MODE_READ, 0 ); if (*ParentFileName == NULL) { *ParentFileName = AllocateCopyPool (StrSize (((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName), ((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName); } else { TempPath = LibAppendFileName (*ParentFileName, ((FILEPATH_DEVICE_PATH *) DevicePathNode)->PathName); if (TempPath == NULL) { LastHandle->Close (LastHandle); Status = EFI_OUT_OF_RESOURCES; goto Done; } FreePool (*ParentFileName); *ParentFileName = TempPath; } // // Close the previous node // LastHandle->Close (LastHandle); DevicePathNode = NextDevicePathNode (DevicePathNode); } if (EFI_ERROR (Status)) { goto Done; } *RetFileHandle = FileHandle; Status = EFI_SUCCESS; Done: if (TempDevicePathNode != NULL) { FreePool (TempDevicePathNode); } if ((FileHandle != NULL) && (EFI_ERROR (Status))) { FileHandle->Close (FileHandle); } return Status; }
/** Entrypoint of Acpi Platform driver. @param ImageHandle @param SystemTable @return EFI_SUCCESS @return EFI_LOAD_ERROR @return EFI_OUT_OF_RESOURCES **/ EFI_STATUS EFIAPI AcpiPlatformEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_ACPI_TABLE_PROTOCOL *AcpiTable; // INTN Instance; // EFI_ACPI_COMMON_HEADER *CurrentTable; EFI_ACPI_COMMON_HEADER *oldDSDT; UINTN TableHandle; UINTN TableSize; // UINTN Size; #if READTABLES UINTN Index; CHAR16* FileName; #if LIP EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; #endif VOID *FileBuffer; // VOID** TmpHandler; UINT64 FileSize; UINTN BufferSize; // UINTN Key; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; EFI_FILE_INFO *Info; EFI_FILE_HANDLE Root = NULL; EFI_FILE_HANDLE ThisFile = NULL; #endif EFI_PHYSICAL_ADDRESS *Acpi20; EFI_PEI_HOB_POINTERS GuidHob; EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; // EFI_ACPI_DESCRIPTION_HEADER *Rsdt, *Xsdt; // EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt; EFI_ACPI_DESCRIPTION_HEADER *Table; SIGNAT Signature; // EFI_ACPI_TABLE_INSTANCE *AcpiInstance; Msg = NULL; Status = gBS->LocateProtocol(&gMsgLogProtocolGuid, NULL, (VOID **) &Msg); if (!EFI_ERROR(Status) && (Msg != NULL)) { msgCursor = Msg->Cursor; BootLog("MsgLog Protocol installed in AcpiPlatform\n"); } // // Find the AcpiTable protocol // Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable); if (EFI_ERROR (Status)) { return EFI_ABORTED; } #if DEBUG_ACPI AcpiInstance = EFI_ACPI_TABLE_INSTANCE_FROM_THIS(AcpiTable); DBG(L"Rsdp1 %x\n", AcpiInstance->Rsdp1); DBG(L"Rsdp3 %x\n", AcpiInstance->Rsdp3); DBG(L"Rsdt1 %x\n", AcpiInstance->Rsdt1); DBG(L"Rsdt3 %x\n", AcpiInstance->Rsdt3); DBG(L"Xsdt %x\n", AcpiInstance->Xsdt); DBG(L"Fadt1 %x\n", AcpiInstance->Fadt1); DBG(L"Fadt3 %x\n", AcpiInstance->Fadt3); #endif // Instance = 0; // CurrentTable = NULL; TableHandle = 0; GuidHob.Raw = GetFirstGuidHob (&gEfiAcpiTableGuid); if (GuidHob.Raw == NULL) { GuidHob.Raw = GetFirstGuidHob (&gEfiAcpi10TableGuid); if (GuidHob.Raw == NULL) { return EFI_ABORTED; } //Slice: TODO if we found only Acpi1.0 we need to convert it to Acpi2.0 // like I did in Chameleon } Acpi20 = GET_GUID_HOB_DATA (GuidHob.Guid); if (Acpi20 == NULL) { return EFI_ABORTED; } Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)*Acpi20; DBG(L"Rsdp @ %x\n", (UINTN)Rsdp); DBG(L"Rsdt @ %x\n", (UINTN)(Rsdp->RsdtAddress)); DBG(L"Xsdt @ %x\n", (UINTN)(Rsdp->XsdtAddress)); InstallLegacyTables(AcpiTable, Rsdp); // DBG(L"LegacyTables installed\n"); oldDSDT = (EFI_ACPI_COMMON_HEADER*)(UINTN)Fadt->Dsdt; DBG(L"Fadt @ %x\n", (UINTN)Fadt); DBG(L"oldDSDT @ %x\n", (UINTN)oldDSDT); #if READTABLES #if LIP // Looking for a volume from what we boot /* TODO - look for a volume we want to boot System it is possible if we fix in BdsBoot.c gRT->SetVariable ( L"BootCurrent", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof (UINT16), &Option->BootCurrent ); gRT->GetVariable ( L"BootNext", &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, 0, &BootNext ); and extract DevicePath from BootNext - first available :( In Gui.efi we can repeat this patch with DSDT.aml loaded from another place */ Status = gBS->HandleProtocol ( ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID*)&LoadedImage ); if (EFI_ERROR (Status)) { return EFI_ABORTED; } Status = gBS->HandleProtocol ( LoadedImage->DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID *) &Volume ); if (EFI_ERROR (Status)) { return EFI_ABORTED; } // DBG(L"Volume found\n"); // // Open the root directory of the volume // if (!EFI_ERROR (Status)) { Status = Volume->OpenVolume (Volume, &Root); } #else //Multiple FS protocols EFI_HANDLE *mFs = NULL; UINTN mFsCount = 0; // mFsInfo[] array entries must match mFs[] handles EFI_FILE_SYSTEM_INFO **mFsInfo = NULL; gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &mFsCount, &mFs); mFsInfo = AllocateZeroPool (mFsCount * sizeof (EFI_FILE_SYSTEM_INFO *)); if (mFsInfo == NULL) { // If we can't do this then we can't support file system entries mFsCount = 0; } else { // Loop through all the file system structures and cache the file system info data for (Index =0; Index < mFsCount; Index++) { Status = gBS->HandleProtocol (mFs[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&Volume); if (!EFI_ERROR (Status)) { Status = Volume->OpenVolume (Volume, &Root); if (!EFI_ERROR (Status)) { // Get information about the volume /* Size = 0; Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, mFsInfo[Index]); if (Status == EFI_BUFFER_TOO_SMALL) { mFsInfo[Index] = AllocatePool (Size); Status = Root->GetInfo (Root, &gEfiFileSystemInfoGuid, &Size, mFsInfo[Index]); } */ // Root->Close (Root); break; //I will stop at first volume //TODO try to find DSDT in all volumes } } } } #endif FileName = AllocateZeroPool(32); //Should be enough // // Read tables from the first volume. // for (Index=0; Index<NUM_TABLES; Index++) { StrCpyS(FileName, 32, ACPInames[Index]); // DBG(L"File probe %s\n", FileName); Status = Root->Open (Root, &ThisFile, FileName, EFI_FILE_MODE_READ, 0); if (EFI_ERROR (Status)) { continue; } /* Get right size we need to allocate */ Status = ThisFile->GetInfo ( ThisFile, &gEfiFileInfoGuid, &BufferSize, Info ); if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) { continue; } DBG(L"Buffer size %d\n", BufferSize); // DBG(L"GetInfo success!\n"); Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, (VOID **) &Info); if (EFI_ERROR (Status)) { // DBG(L"No pool!\n"); continue; } Status = ThisFile->GetInfo ( ThisFile, &gEfiFileInfoGuid, &BufferSize, Info ); FileSize = Info->FileSize; // DBG(L"FileSize = %d!\n", FileSize); gBS->FreePool (Info); //Slice - this is the problem. // FileBuffer = AllocatePool(FileSize); Status = gBS->AllocatePool (EfiBootServicesData, FileSize, (VOID **) &FileBuffer); if (EFI_ERROR (Status)) { // DBG(L"No pool for FileBuffer size %d!\n", FileSize); continue; } /* Status = gBS->AllocatePages ( AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES(FileSize), FileBuffer ); if (EFI_ERROR (Status)) { // DBG(L"No pool for FileBuffer size %d!\n", FileSize); continue; } */ //should use ACPI memory // Status=gBS->AllocatePages(AllocateMaxAddress, // EfiACPIReclaimMemory,RoundPage(FileSize)/EFI_PAGE_SIZE, FileBuffer); DBG(L"FileBuffer @ %x\n", (UINTN)FileBuffer); Status = ThisFile->Read (ThisFile, &FileSize, FileBuffer); //(VOID**)& // DBG(L"FileRead status=%x\n", Status); if (!EFI_ERROR(Status)) { // // Add the table // // TableHandle = 0; if (ThisFile != NULL) { ThisFile->Close (ThisFile); //close file before use buffer?! Flush?! } // DBG(L"FileRead success: %c%c%c%c\n", // ((CHAR8*)FileBuffer)[0], ((CHAR8*)FileBuffer)[1], ((CHAR8*)FileBuffer)[2], ((CHAR8*)FileBuffer)[3]); TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) FileBuffer)->Length; //ASSERT (BufferSize >= TableSize); DBG(L"Table size=%d\n", TableSize); if (FileSize < TableSize) { //Data incorrect. What TODO? Quick fix // ((EFI_ACPI_DESCRIPTION_HEADER *) FileBuffer)->Length = FileSize; // TableSize = FileSize; DBG(L"Table size > file size :(\n"); continue; //do nothing with broken table } // // Checksum ACPI table // AcpiPlatformChecksum ((UINT8*)FileBuffer, TableSize); if ((Index==0) && oldDSDT) { //DSDT always at index 0 if (((EFI_ACPI_DESCRIPTION_HEADER *) oldDSDT)->Length > TableSize) { CopyMem(oldDSDT, FileBuffer, TableSize); DBG(L"New DSDT copied to old place\n"); } } // // Install ACPI table // //TmpHandler = &FileBuffer; Status = AcpiTable->InstallAcpiTable ( AcpiTable, FileBuffer, TableSize, &TableHandle ); DBG(L"Table install status=%x\n", Status); if (EFI_ERROR(Status)) { continue; } // DBG(L"Table installed #%d\n", Index); // // Increment the instance // // Instance++; //for a what? FileBuffer = NULL; } else if (oldDSDT && (Index==0)) { //if new DSDT not found then install legacy one Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(Fadt->Dsdt)); TableSize = Table->Length; Signature.Sign = Table->Signature; DBG(L"Install legacy table: %c%c%c%c\n", Signature.ASign[0], Signature.ASign[1], Signature.ASign[2], Signature.ASign[3]); Status = AcpiTable->InstallAcpiTable ( AcpiTable, Table, TableSize, &TableHandle ); } } if (Root != NULL) { Root->Close (Root); } #else //just install legacy tables if (oldDSDT) { //if new DSDT not found then install legacy one Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(Fadt->Dsdt)); TableSize = Table->Length; Signature.Sign = Table->Signature; DBG(L"Install legacy table: %c%c%c%c\n", Signature.ASign[0], Signature.ASign[1], Signature.ASign[2], Signature.ASign[3]); /*Status = */AcpiTable->InstallAcpiTable ( AcpiTable, Table, TableSize, &TableHandle ); } #endif #if DEBUG_ACPI==2 gBS->Stall(5000000); #endif return EFI_SUCCESS; }