/** 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; }
/** Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo(). **/ VOID GetLegacyOptions ( VOID ) { LEGACY_MENU_ENTRY *NewMenuEntry; LEGACY_DEVICE_CONTEXT *NewLegacyDevContext; EFI_BOOT_MANAGER_LOAD_OPTION *BootOption; UINTN BootOptionCount; UINT16 Index; UINTN FDNum; UINTN HDNum; UINTN CDNum; UINTN NETNum; UINTN BEVNum; // // Initialize Bbs Table Context from BBS info data // InitializeListHead (&LegacyFDMenu.Head); InitializeListHead (&LegacyHDMenu.Head); InitializeListHead (&LegacyCDMenu.Head); InitializeListHead (&LegacyNETMenu.Head); InitializeListHead (&LegacyBEVMenu.Head); FDNum = 0; HDNum = 0; CDNum = 0; NETNum = 0; BEVNum = 0; EfiBootManagerConnectAll (); // // for better user experience // 1. User changes HD configuration (e.g.: unplug HDD), here we have a chance to remove the HDD boot option // 2. User enables/disables UEFI PXE, here we have a chance to add/remove EFI Network boot option // EfiBootManagerRefreshAllBootOption (); BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot); for (Index = 0; Index < BootOptionCount; Index++) { if ((DevicePathType (BootOption[Index].FilePath) != BBS_DEVICE_PATH) || (DevicePathSubType (BootOption[Index].FilePath) != BBS_BBS_DP) ) { continue; } ASSERT (BootOption[Index].OptionalDataSize == sizeof (LEGACY_BOOT_OPTION_BBS_DATA)); NewMenuEntry = CreateMenuEntry (); ASSERT (NewMenuEntry != NULL); NewLegacyDevContext = (LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext; NewLegacyDevContext->BbsIndex = ((LEGACY_BOOT_OPTION_BBS_DATA *) BootOption[Index].OptionalData)->BbsIndex; NewLegacyDevContext->Description = AllocateCopyPool (StrSize (BootOption[Index].Description), BootOption[Index].Description); ASSERT (NewLegacyDevContext->Description != NULL); NewMenuEntry->DisplayString = NewLegacyDevContext->Description; NewMenuEntry->HelpString = NULL; switch (((BBS_BBS_DEVICE_PATH *) BootOption[Index].FilePath)->DeviceType) { case BBS_TYPE_FLOPPY: InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link); FDNum++; break; case BBS_TYPE_HARDDRIVE: InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link); HDNum++; break; case BBS_TYPE_CDROM: InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link); CDNum++; break; case BBS_TYPE_EMBEDDED_NETWORK: InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link); NETNum++; break; case BBS_TYPE_BEV: InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link); BEVNum++; break; } } EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount); LegacyFDMenu.MenuNumber = FDNum; LegacyHDMenu.MenuNumber = HDNum; LegacyCDMenu.MenuNumber = CDNum; LegacyNETMenu.MenuNumber = NETNum; LegacyBEVMenu.MenuNumber = BEVNum; }
/** This function builds the FsOptionMenu list which records all available file system in the system. They include all instances of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM and all type of legacy boot device. @retval EFI_SUCCESS Success find the file system @retval EFI_OUT_OF_RESOURCES Can not create menu entry **/ EFI_STATUS FindFileSystem ( VOID ) { UINTN NoBlkIoHandles; UINTN NoSimpleFsHandles; EFI_HANDLE *BlkIoHandle; EFI_HANDLE *SimpleFsHandle; UINT16 *VolumeLabel; EFI_BLOCK_IO_PROTOCOL *BlkIo; UINTN Index; EFI_STATUS Status; SECUREBOOT_MENU_ENTRY *MenuEntry; SECUREBOOT_FILE_CONTEXT *FileContext; UINT16 *TempStr; UINTN OptionNumber; VOID *Buffer; BOOLEAN RemovableMedia; NoSimpleFsHandles = 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, (VOID **) &BlkIo ); if (EFI_ERROR (Status)) { continue; } // // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media // if (BlkIo->Media->RemovableMedia) { Buffer = AllocateZeroPool (BlkIo->Media->BlockSize); if (NULL == Buffer) { FreePool (BlkIoHandle); return EFI_OUT_OF_RESOURCES; } BlkIo->ReadBlocks ( BlkIo, BlkIo->Media->MediaId, 0, BlkIo->Media->BlockSize, Buffer ); FreePool (Buffer); } } FreePool (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, (VOID **) &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 instance. // MenuEntry = CreateMenuEntry (); if (NULL == MenuEntry) { FreePool (SimpleFsHandle); return EFI_OUT_OF_RESOURCES; } FileContext = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext; FileContext->Handle = SimpleFsHandle[Index]; MenuEntry->OptionNumber = Index; FileContext->FHandle = OpenRoot (FileContext->Handle); if (FileContext->FHandle == NULL) { DestroyMenuEntry (MenuEntry); continue; } MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle)); FileContext->Info = FileSystemVolumeLabelInfo (FileContext->FHandle); FileContext->FileName = StrDuplicate (L"\\"); FileContext->DevicePath = FileDevicePath ( FileContext->Handle, FileContext->FileName ); FileContext->IsDir = TRUE; FileContext->IsRoot = TRUE; FileContext->IsRemovableMedia = RemovableMedia; 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 = AllocateZeroPool (MAX_CHAR); ASSERT (MenuEntry->DisplayString != NULL); UnicodeSPrint ( MenuEntry->DisplayString, MAX_CHAR, L"%s, [%s]", VolumeLabel, TempStr ); OptionNumber++; InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); } } if (NoSimpleFsHandles != 0) { FreePool (SimpleFsHandle); } // // Remember how many file system options are here // FsOptionMenu.MenuNumber = OptionNumber; return EFI_SUCCESS; }