/** Function gets the file system information from an open file descriptor, and stores it in a buffer allocated from pool. @param FHand The file handle. @return A pointer to a buffer with file information. @retval NULL is returned if failed to get Volume Label Info. **/ EFI_FILE_SYSTEM_VOLUME_LABEL * EfiLibFileSystemVolumeLabelInfo ( IN EFI_FILE_HANDLE FHand ) { EFI_STATUS Status; EFI_FILE_SYSTEM_VOLUME_LABEL *VolumeInfo = NULL; UINTN Size = 0; Status = FHand->GetInfo (FHand, &gEfiFileSystemVolumeLabelInfoIdGuid, &Size, VolumeInfo); if (Status == EFI_BUFFER_TOO_SMALL) { // inc size by 2 because some drivers (HFSPlus.efi) do not count 0 at the end of file name Size += 2; VolumeInfo = AllocateZeroPool (Size); Status = FHand->GetInfo (FHand, &gEfiFileSystemVolumeLabelInfoIdGuid, &Size, VolumeInfo); // Check to make sure this isn't actually EFI_FILE_SYSTEM_INFO if (!EFI_ERROR(Status)) { EFI_FILE_SYSTEM_INFO *FSInfo = (EFI_FILE_SYSTEM_INFO *)VolumeInfo; if (FSInfo->Size == (UINT64)Size) { // Allocate a new volume label VolumeInfo = (EFI_FILE_SYSTEM_VOLUME_LABEL *)EfiStrDuplicate(FSInfo->VolumeLabel); FreePool(FSInfo); } } if (!EFI_ERROR(Status)) { return VolumeInfo; } FreePool(VolumeInfo); } return NULL; }
EFI_STATUS BOpt_FindFileSystem ( IN BMM_CALLBACK_DATA *CallbackData ) /*++ Routine Description Find file systems for current Extensible Firmware Including Handles that support Simple File System protocol, Load File protocol. Building up the FileSystem Menu for user selection All file system will be stored in FsOptionMenu for future use. Arguments: CallbackData - BMM context data Returns: EFI_SUCCESS - Success find the file system EFI_OUT_OF_RESOURCES - Can not create menu entry --*/ { UINTN NoBlkIoHandles; UINTN NoSimpleFsHandles; UINTN NoLoadFileHandles; EFI_HANDLE *BlkIoHandle; EFI_HANDLE *SimpleFsHandle; EFI_HANDLE *LoadFileHandle; UINT16 *VolumeLabel; EFI_BLOCK_IO_PROTOCOL *BlkIo; UINTN Index; EFI_STATUS Status; BM_MENU_ENTRY *MenuEntry; BM_FILE_CONTEXT *FileContext; UINT16 *TempStr; UINTN OptionNumber; VOID *Buffer; EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; UINT16 DeviceType; BBS_BBS_DEVICE_PATH BbsDevicePathNode; EFI_DEVICE_PATH_PROTOCOL *DevicePath; BOOLEAN RemovableMedia; NoSimpleFsHandles = 0; NoLoadFileHandles = 0; OptionNumber = 0; InitializeListHead (&FsOptionMenu.Head); // // Locate Handles that support BlockIo protocol // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &NoBlkIoHandles, &BlkIoHandle ); if (!EFI_ERROR (Status)) { for (Index = 0; Index < NoBlkIoHandles; Index++) { Status = gBS->HandleProtocol ( BlkIoHandle[Index], &gEfiBlockIoProtocolGuid, &BlkIo ); if (EFI_ERROR (Status)) { continue; } // // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media // if (BlkIo->Media->RemovableMedia) { Buffer = EfiAllocateZeroPool (BlkIo->Media->BlockSize); if (NULL == Buffer) { SafeFreePool (BlkIoHandle); return EFI_OUT_OF_RESOURCES; } BlkIo->ReadBlocks ( BlkIo, BlkIo->Media->MediaId, 0, BlkIo->Media->BlockSize, Buffer ); SafeFreePool (Buffer); } } SafeFreePool (BlkIoHandle); } // // Locate Handles that support Simple File System protocol // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &NoSimpleFsHandles, &SimpleFsHandle ); if (!EFI_ERROR (Status)) { // // Find all the instances of the File System prototocol // for (Index = 0; Index < NoSimpleFsHandles; Index++) { Status = gBS->HandleProtocol ( SimpleFsHandle[Index], &gEfiBlockIoProtocolGuid, &BlkIo ); if (EFI_ERROR (Status)) { // // If no block IO exists assume it's NOT a removable media // RemovableMedia = FALSE; } else { // // If block IO exists check to see if it's remobable media // RemovableMedia = BlkIo->Media->RemovableMedia; } // // Allocate pool for this load option // MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); if (NULL == MenuEntry) { SafeFreePool (SimpleFsHandle); return EFI_OUT_OF_RESOURCES; } FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; FileContext->Handle = SimpleFsHandle[Index]; MenuEntry->OptionNumber = Index; FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle); if (!FileContext->FHandle) { BOpt_DestroyMenuEntry (MenuEntry); continue; } MenuEntry->HelpString = DevicePathToStr (EfiDevicePathFromHandle (FileContext->Handle)); FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle); FileContext->FileName = EfiStrDuplicate (L"\\"); FileContext->DevicePath = EfiFileDevicePath ( FileContext->Handle, FileContext->FileName ); FileContext->IsDir = TRUE; FileContext->IsRoot = TRUE; FileContext->IsRemovableMedia = FALSE; FileContext->IsLoadFile = FALSE; // // Get current file system's Volume Label // if (FileContext->Info == NULL) { VolumeLabel = L"NO FILE SYSTEM INFO"; } else { if (FileContext->Info->VolumeLabel == NULL) { VolumeLabel = L"NULL VOLUME LABEL"; } else { VolumeLabel = FileContext->Info->VolumeLabel; if (*VolumeLabel == 0x0000) { VolumeLabel = L"NO VOLUME LABEL"; } } } TempStr = MenuEntry->HelpString; MenuEntry->DisplayString = EfiAllocateZeroPool (MAX_CHAR); ASSERT (MenuEntry->DisplayString != NULL); SPrint ( MenuEntry->DisplayString, MAX_CHAR, L"%s, [%s]", VolumeLabel, TempStr ); OptionNumber++; InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); } } if (NoSimpleFsHandles != 0) { SafeFreePool (SimpleFsHandle); } // // Searching for handles that support Load File protocol // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &NoLoadFileHandles, &LoadFileHandle ); if (!EFI_ERROR (Status)) { for (Index = 0; Index < NoLoadFileHandles; Index++) { MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); if (NULL == MenuEntry) { SafeFreePool (LoadFileHandle); return EFI_OUT_OF_RESOURCES; } FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; FileContext->IsRemovableMedia = FALSE; FileContext->IsLoadFile = TRUE; FileContext->Handle = LoadFileHandle[Index]; FileContext->IsRoot = TRUE; FileContext->DevicePath = EfiDevicePathFromHandle (FileContext->Handle); MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath); TempStr = MenuEntry->HelpString; MenuEntry->DisplayString = EfiAllocateZeroPool (MAX_CHAR); ASSERT (MenuEntry->DisplayString != NULL); SPrint ( MenuEntry->DisplayString, MAX_CHAR, L"Load File [%s]", TempStr ); MenuEntry->OptionNumber = OptionNumber; OptionNumber++; InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); } } if (NoLoadFileHandles != 0) { SafeFreePool (LoadFileHandle); } // // Add Legacy Boot Option Support Here // Status = gBS->LocateProtocol ( &gEfiLegacyBiosProtocolGuid, NULL, &LegacyBios ); if (!EFI_ERROR (Status)) { for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) { MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); if (NULL == MenuEntry) { return EFI_OUT_OF_RESOURCES; } FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; FileContext->IsRemovableMedia = FALSE; FileContext->IsLoadFile = TRUE; FileContext->IsBootLegacy = TRUE; DeviceType = (UINT16) Index; BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH; BbsDevicePathNode.Header.SubType = BBS_BBS_DP; SetDevicePathNodeLength ( &BbsDevicePathNode.Header, sizeof (BBS_BBS_DEVICE_PATH) ); BbsDevicePathNode.DeviceType = DeviceType; BbsDevicePathNode.StatusFlag = 0; BbsDevicePathNode.String[0] = 0; DevicePath = EfiAppendDevicePathNode ( EndDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode ); FileContext->DevicePath = DevicePath; MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath); TempStr = MenuEntry->HelpString; MenuEntry->DisplayString = EfiAllocateZeroPool (MAX_CHAR); ASSERT (MenuEntry->DisplayString != NULL); SPrint ( MenuEntry->DisplayString, MAX_CHAR, L"Boot Legacy [%s]", TempStr ); MenuEntry->OptionNumber = OptionNumber; OptionNumber++; InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); } } // // Remember how many file system options are here // FsOptionMenu.MenuNumber = OptionNumber; 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; }
/** Function gets the file system information from an open file descriptor, and stores it in a buffer allocated from pool. @param FHand The file handle. @return A pointer to a buffer with file information. @retval NULL is returned if failed to get Vaolume Label Info. **/ EFI_FILE_SYSTEM_VOLUME_LABEL * EfiLibFileSystemVolumeLabelInfo ( IN EFI_FILE_HANDLE FHand ) { #if 0 EFI_STATUS Status = EFI_SUCCESS; EFI_FILE_SYSTEM_VOLUME_LABEL *Buffer; UINTN BufferSize; // // Initialize for GrowBuffer loop // Buffer = NULL; BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200; // // Call the real function // while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { Status = FHand->GetInfo ( FHand, &gEfiFileSystemVolumeLabelInfoIdGuid, &BufferSize, Buffer ); } return Buffer; #else EFI_STATUS Status; EFI_FILE_SYSTEM_VOLUME_LABEL *VolumeInfo = NULL; UINTN Size = 0; Status = FHand->GetInfo (FHand, &gEfiFileSystemVolumeLabelInfoIdGuid, &Size, VolumeInfo); if (Status == EFI_BUFFER_TOO_SMALL) { // inc size by 2 because some drivers (HFSPlus.efi) do not count 0 at the end of file name Size += 2; VolumeInfo = AllocateZeroPool (Size); Status = FHand->GetInfo (FHand, &gEfiFileSystemVolumeLabelInfoIdGuid, &Size, VolumeInfo); // Check to make sure this isn't actually EFI_FILE_SYSTEM_INFO if (!EFI_ERROR(Status)) { EFI_FILE_SYSTEM_INFO *FSInfo = (EFI_FILE_SYSTEM_INFO *)VolumeInfo; if (FSInfo->Size == (UINT64)Size) { // Allocate a new volume label VolumeInfo = (EFI_FILE_SYSTEM_VOLUME_LABEL *)EfiStrDuplicate(FSInfo->VolumeLabel); FreePool(FSInfo); } } if (!EFI_ERROR(Status)) { return VolumeInfo; } FreePool(VolumeInfo); } return NULL; #endif }