/** 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; }
EFI_STATUS generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName) { unsigned int pathlen; EFI_STATUS efi_status = EFI_SUCCESS; CHAR16 *devpathstr = DevicePathToStr(li->FilePath), *found = NULL; unsigned int i; for (i = 0; i < StrLen(devpathstr); i++) { if (devpathstr[i] == '/') devpathstr[i] = '\\'; if (devpathstr[i] == '\\') found = &devpathstr[i]; } if (!found) { pathlen = 0; } else { while (*(found - 1) == '\\') --found; *found = '\0'; pathlen = StrLen(devpathstr); } if (name[0] != '\\') pathlen++; *PathName = AllocatePool((pathlen + 1 + StrLen(name))*sizeof(CHAR16)); if (!*PathName) { Print(L"Failed to allocate path buffer\n"); efi_status = EFI_OUT_OF_RESOURCES; goto error; } StrCpy(*PathName, devpathstr); if (name[0] != '\\') StrCat(*PathName, L"\\"); StrCat(*PathName, name); *path = FileDevicePath(li->DeviceHandle, *PathName); error: FreePool(devpathstr); return efi_status; }
EFI_STATUS ExecElet ( IN OUT EFI_NETWORK_TEST_FILE *TestFile, IN CHAR16 *TestNodeName ) /*++ Routine Description: Execute an application. Arguments: TestFile - Pointer to the EFI_EFI_NETWORK_TEST_FILE structure. TestNodeName - Test node name string. Returns: EFI_SUCCESS - Operation succeeded. EFI_UNSUPPORTED - Unsupported test file. EFI_OUT_OF_RESOURCES - Memory allocation failed. Others - Some failure happened. --*/ { EFI_STATUS Status; UINTN ExitDataSize; CHAR16 *ExitData; EFI_HANDLE ImageHandle; EFI_DEVICE_PATH_PROTOCOL *FileNode; EFI_DEVICE_PATH_PROTOCOL *FilePath; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; UINT64 StartTick; UINT64 StopTick; if ((TestFile->Type == EFI_NETWORK_TEST_FILE_APPLICATION) && (TestNodeName == NULL)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_TRACE, L"in ExecElet:begin exe (%s)", TestFile->FileName)); // // Add the file path to the device path // FileNode = FileDevicePath (NULL, TestFile->FileName); if (FileNode == NULL) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"in ExecElet:Create file device path - %r", EFI_OUT_OF_RESOURCES)); return EFI_OUT_OF_RESOURCES; } FilePath = AppendDevicePath (gEasFT->DevicePath, FileNode); if (FilePath == NULL) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"in ExecElet:Append file device path - %r", EFI_OUT_OF_RESOURCES)); BS->FreePool (FileNode); return EFI_OUT_OF_RESOURCES; } BS->FreePool (FileNode); // // Load the test file // Status = BS->LoadImage ( FALSE, gEasFT->ImageHandle, FilePath, NULL, 0, &ImageHandle ); if (EFI_ERROR (Status)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"in ExecElet:Load image - %r", Status)); BS->FreePool (FilePath); return Status; } BS->FreePool (FilePath); EFI_ENTS_STATUS ((L"in ExecElet: Finish Loading image file <%s>", TestFile->FileName)); // // Verify the image is an application or not // Status = BS->HandleProtocol ( ImageHandle, &gEfiLoadedImageProtocolGuid, (void **)&LoadedImage ); if (EFI_ERROR (Status)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"in ExecElet: HandleProtocol - %r", Status)); BS->UnloadImage(ImageHandle); return Status; } if (LoadedImage->ImageCodeType == EfiLoaderCode) { // // It is an application // #ifdef EFIARM StartTick = 0; #else StartTick = EfiReadTsc (); #endif Status = BS->StartImage ( ImageHandle, &ExitDataSize, &ExitData ); #ifdef EFIARM StopTick = 0; #else StopTick = EfiReadTsc (); #endif RecordExecTime (StartTick, StopTick); if (EFI_ERROR (Status)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"Error in ExecElet: Start image - %r\n", Status)); } } else { EFI_ENTS_DEBUG ((EFI_ENTS_D_WARNING, L"Unsupported test file")); Status = EFI_UNSUPPORTED; } BS->UnloadImage(ImageHandle); return Status; } else if ((TestFile->Type == EFI_NETWORK_TEST_FILE_DRIVER) && (TestNodeName != NULL)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_TRACE, L"in ExecElet:begin exe (%s->%s)", TestFile->CmdName, TestNodeName)); Status = ExecDriver (TestFile, TestNodeName); if (EFI_ERROR (Status)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"Error in ExecDriver: Status - %r\n", Status)); return Status; } } return EFI_SUCCESS; }
EFI_STATUS EFIAPI EBounceMain (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { EFI_STATUS Status; EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl; EFI_CONSOLE_CONTROL_SCREEN_MODE currentMode; EFI_LOADED_IMAGE *SelfLoadedImage; EFI_FILE *RootDir; EFI_FILE *BootFile; EFI_DEVICE_PATH *DevicePath; CHAR16 *DevicePathAsString; CHAR16 DirName[256]; CHAR16 FileName[256]; UINTN i, FileNameIndex; EFI_HANDLE LoaderHandle; InitializeLib(ImageHandle, SystemTable); // switch to text mode if (BS->LocateProtocol(&gEfiConsoleControlProtocolGuid, NULL, &ConsoleControl) == EFI_SUCCESS) { ConsoleControl->GetMode(ConsoleControl, ¤tMode, NULL, NULL); if (currentMode == EfiConsoleControlScreenGraphics) ConsoleControl->SetMode(ConsoleControl, EfiConsoleControlScreenText); } /// load elilo.efi or e.efi from the same directory // get loaded image protocol for ourselves if (BS->HandleProtocol(ImageHandle, &LoadedImageProtocol, (VOID*)&SelfLoadedImage) != EFI_SUCCESS) { Print(L"Can not retrieve a LoadedImageProtocol handle for ImageHandle\n"); return EFI_NOT_FOUND; } // open volume RootDir = LibOpenRoot(SelfLoadedImage->DeviceHandle); if (RootDir == NULL) { Print(L"Can't open volume.\n"); return EFI_NOT_FOUND; } // find the current directory DevicePathAsString = DevicePathToStr(SelfLoadedImage->FilePath); if (DevicePathAsString != NULL) { StrCpy(DirName, DevicePathAsString); FreePool(DevicePathAsString); for (i = StrLen(DirName) - 1; i > 0 && DirName[i] != '\\'; i--) ; DirName[i++] = '\\'; DirName[i] = 0; } else { StrCpy(DirName, L"\\"); } for (FileNameIndex = 0; FileNames[FileNameIndex]; FileNameIndex++) { // build full absolute path name StrCpy(FileName, DirName); StrCat(FileName, FileNames[FileNameIndex]); // check for presence of the file if (RootDir->Open(RootDir, &BootFile, FileName, EFI_FILE_MODE_READ, 0) != EFI_SUCCESS) continue; BootFile->Close(BootFile); // make a full device path for the image file DevicePath = FileDevicePath(SelfLoadedImage->DeviceHandle, FileName); // load the image into memory Status = BS->LoadImage(FALSE, ImageHandle, DevicePath, NULL, 0, &LoaderHandle); FreePool(DevicePath); if (EFI_ERROR(Status)) { Print(L"Can not load the file %s\n", FileName); return Status; } // start it! BS->StartImage(LoaderHandle, NULL, NULL); // just in case we get control back... break; } return EFI_SUCCESS; }
EFI_STATUS LoadAndStartImage ( EFI_HANDLE CurrentImageHandle, CHAR16 *FileName, EFI_HANDLE *StartImage ) { EFI_STATUS Status; EFI_LOADED_IMAGE_PROTOCOL *LoadImage; EFI_DEVICE_PATH_PROTOCOL *FileDevPath; CHAR16 *EntireFileName; CHAR16 *FilePath; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_TEST_PROFILE_LIBRARY_PROTOCOL *ProfileLib; Status = gtBS->HandleProtocol ( CurrentImageHandle, &gEfiLoadedImageProtocolGuid, &LoadImage ); if (EFI_ERROR (Status)) { return Status; } // // Use profile lib at here just for less effect on the current system. It is // dependent on the implementation of test framework. So need to be updated // later. // Status = gtBS->LocateProtocol ( &gEfiTestProfileLibraryGuid, NULL, &ProfileLib ); if (EFI_ERROR (Status)) { return Status; } // // Get the system device path and file path // Status = ProfileLib->EfiGetSystemDevicePath ( ProfileLib, &DevicePath, &FilePath ); if (EFI_ERROR (Status)) { return Status; } EntireFileName = PoolPrint (L"%s\\%s\\%s", FilePath, DEPENDENCY_DIR_NAME, FileName); FreePool (FilePath); FreePool (DevicePath); FileDevPath = FileDevicePath (LoadImage->DeviceHandle, EntireFileName); FreePool (EntireFileName); if (FileDevPath == NULL) { return EFI_OUT_OF_RESOURCES; } Status = gtBS->LoadImage ( FALSE, CurrentImageHandle, FileDevPath, NULL, 0, StartImage ); gtBS->FreePool (FileDevPath); if (EFI_ERROR (Status)) { return Status; } Status = gtBS->StartImage (*StartImage,0,NULL); return Status; }
EFI_STATUS LoadFile(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* systab, CHAR16* filename, VOID** dataPtr, UINTN* size, EFI_DEVICE_PATH_PROTOCOL** dev_path) { EFI_GUID LoadedImageProtocolGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID; EFI_GUID FileInfoGuid = EFI_FILE_INFO_ID; EFI_GUID FileSystemGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; EFI_STATUS res; EFI_BOOT_SERVICES* BS = systab->BootServices; //get image info EFI_LOADED_IMAGE_PROTOCOL* img_proto; res = BS->HandleProtocol(ImageHandle, &LoadedImageProtocolGuid, (void**) &img_proto); if (res) { ErrorPrint(L"Failed to get image protocol. (Error %d)\r\n", res); return EFI_LOAD_ERROR ; } EFI_HANDLE img_device_handle = img_proto->DeviceHandle; //Get filesystem protocol from device EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* fs_proto; res = BS->HandleProtocol(img_device_handle, &FileSystemGuid, (VOID**) &fs_proto); if (res) { ErrorPrint(L"Failed to get file system protocol. (Error %d)\r\n", res); return EFI_LOAD_ERROR ; } //open volume EFI_FILE_PROTOCOL* volume; res = fs_proto->OpenVolume(fs_proto, &volume); if (res) { ErrorPrint(L"Failed to open file volume. (Error %d)\r\n", res); return EFI_LOAD_ERROR ; } //open file EFI_FILE_PROTOCOL* file; res = volume->Open(volume, &file, filename, EFI_FILE_MODE_READ, 0); if (res) { //don't print error here //ErrorPrint(L"Failed to open file '%s'. (Error %d)\r\n", filename, res); return EFI_NOT_FOUND ; } //get file info, two try process EFI_FILE_INFO* file_info = NULL; UINTN file_info_size = 0; res = file->GetInfo(file, &FileInfoGuid, &file_info_size, NULL ); if (res != EFI_BUFFER_TOO_SMALL ) { ErrorPrint(L"Failed to stat file '%s'. (Error %d)\r\n", filename, res); return EFI_NOT_FOUND ; } res = BS->AllocatePool(EfiLoaderData, file_info_size, (void**) &file_info); if (res) { ErrorPrint(L"Failed to allocate file info memory. (Error %d)\r\n", res); return EFI_OUT_OF_RESOURCES ; } res = file->GetInfo(file, &FileInfoGuid, &file_info_size, (void*) file_info); if (res) { BS->FreePool(file_info); ErrorPrint(L"Failed to stat file '%s'. (Error %d)\r\n", filename, res); return EFI_NOT_FOUND ; } if (dev_path != NULL ) { *dev_path = FileDevicePath(img_device_handle, filename); } UINT64 file_size = file_info->FileSize; BS->FreePool(file_info); file_info = NULL; void* data = NULL; res = BS->AllocatePool(EfiLoaderData, file_size, (void**) &data); if (res) { ErrorPrint(L"Failed to allocate file data memory. (Error %d)\r\n", res); return EFI_OUT_OF_RESOURCES ; } //read the file res = file->Read(file, &file_size, (void*) data); if (res) { BS->FreePool(data); ErrorPrint(L"Failed to read file '%s'. (Error %d)\r\n", filename, res); return EFI_NOT_FOUND ; } //close the file file->Close(file); volume->Close(volume); //set the pointer and data size *dataPtr = data; *size = file_size; //return success return EFI_SUCCESS; }
/** Find files under current directory. All files and sub-directories in current directory will be stored in DirectoryMenu for future use. @param FileHandle Parent file handle. @param FileName Parent file name. @param DeviceHandle Driver handle for this partition. @retval EFI_SUCCESS Get files from current dir successfully. @return Other value if can't get files from current dir. **/ EFI_STATUS LibFindFiles ( IN EFI_FILE_HANDLE FileHandle, IN UINT16 *FileName, IN EFI_HANDLE DeviceHandle ) { EFI_FILE_INFO *DirInfo; UINTN BufferSize; UINTN DirBufferSize; MENU_ENTRY *NewMenuEntry; FILE_CONTEXT *NewFileContext; UINTN Pass; EFI_STATUS Status; UINTN OptionNumber; OptionNumber = 0; 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 // Status = EFI_SUCCESS; for (Pass = 1; Pass <= 2; Pass++) { FileHandle->SetPosition (FileHandle, 0); for (;;) { BufferSize = DirBufferSize; Status = FileHandle->Read (FileHandle, &BufferSize, DirInfo); if (EFI_ERROR (Status) || BufferSize == 0) { Status = EFI_SUCCESS; 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; } if (!((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 || LibIsSupportedFileType (DirInfo->FileName))) { // // Slip file unless it is a directory entry or a .EFI file // continue; } NewMenuEntry = LibCreateMenuEntry (); if (NULL == NewMenuEntry) { Status = EFI_OUT_OF_RESOURCES; goto Done; } NewFileContext = (FILE_CONTEXT *) NewMenuEntry->VariableContext; NewFileContext->DeviceHandle = DeviceHandle; NewFileContext->FileName = LibAppendFileName (FileName, DirInfo->FileName); if (NewFileContext->FileName == NULL) { LibDestroyMenuEntry (NewMenuEntry); Status = EFI_OUT_OF_RESOURCES; goto Done; } NewFileContext->FileHandle = FileHandle; NewFileContext->DevicePath = FileDevicePath (NewFileContext->DeviceHandle, 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 = LibStrDuplicate (DirInfo->FileName); } NewMenuEntry->DisplayStringToken = HiiSetString ( gFileExplorerPrivate.FeHiiHandle, 0, NewMenuEntry->DisplayString, NULL ); NewFileContext->IsRoot = FALSE; OptionNumber++; InsertTailList (&gFileExplorerPrivate.FsOptionMenu->Head, &NewMenuEntry->Link); } } gFileExplorerPrivate.FsOptionMenu->MenuNumber = OptionNumber; Done: FreePool (DirInfo); return Status; }
EFI_STATUS add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments) { CHAR16 *fullpath = NULL; UINT64 pathlen = 0; EFI_STATUS rc = EFI_SUCCESS; rc = make_full_path(dirname, filename, &fullpath, &pathlen); if (EFI_ERROR(rc)) return rc; EFI_DEVICE_PATH *dph = NULL; EFI_DEVICE_PATH *file = NULL; EFI_DEVICE_PATH *full_device_path = NULL; EFI_DEVICE_PATH *dp = NULL; dph = DevicePathFromHandle(this_image->DeviceHandle); if (!dph) { rc = EFI_OUT_OF_RESOURCES; goto err; } file = FileDevicePath(fh, fullpath); if (!file) { rc = EFI_OUT_OF_RESOURCES; goto err; } full_device_path = AppendDevicePath(dph, file); if (!full_device_path) { rc = EFI_OUT_OF_RESOURCES; goto err; } rc = FindSubDevicePath(full_device_path, MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, &dp); if (EFI_ERROR(rc)) { if (rc == EFI_NOT_FOUND) { dp = full_device_path; } else { rc = EFI_OUT_OF_RESOURCES; goto err; } } #ifdef DEBUG_FALLBACK { UINTN s = DevicePathSize(dp); UINTN i; UINT8 *dpv = (void *)dp; for (i = 0; i < s; i++) { if (i > 0 && i % 16 == 0) Print(L"\n"); Print(L"%02x ", dpv[i]); } Print(L"\n"); CHAR16 *dps = DevicePathToStr(dp); Print(L"device path: \"%s\"\n", dps); } #endif UINT16 option; rc = find_boot_option(dp, full_device_path, fullpath, label, arguments, &option); if (EFI_ERROR(rc)) { add_boot_option(dp, full_device_path, fullpath, label, arguments); } else if (option != 0) { CHAR16 *newbootorder; newbootorder = AllocateZeroPool(sizeof (CHAR16) * nbootorder); if (!newbootorder) return EFI_OUT_OF_RESOURCES; newbootorder[0] = bootorder[option]; CopyMem(newbootorder + 1, bootorder, sizeof (CHAR16) * option); CopyMem(newbootorder + option + 1, bootorder + option + 1, sizeof (CHAR16) * (nbootorder - option - 1)); FreePool(bootorder); bootorder = newbootorder; } err: if (file) FreePool(file); if (full_device_path) FreePool(full_device_path); if (dp) FreePool(dp); if (fullpath) FreePool(fullpath); return rc; }
EFI_STATUS EfiMain(EFI_HANDLE hImage, EFI_SYSTEM_TABLE *pST) { EFI_LOADED_IMAGE *pImage; EFI_STATUS nStatus; EFI_HANDLE hDriver, *hBlkDevs; UINTN nBlkDevs; EFI_DEVICE_PATH *pBootPart, *pBootDisk = NULL; g_hImage = hImage; InitializeLib(hImage, pST); Print(L"%H\n*** UEFI:NTFS multiboot ***"); if (EFI_ERROR((nStatus = BS->OpenProtocol(hImage, &LoadedImageProtocol, &pImage, hImage, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL)))) { Print(L"%E\nUnable to convert handle to interface: %r\n", nStatus); goto end; } pBootPart = DevicePathFromHandle(pImage->DeviceHandle); pBootDisk = GetParentDevice(pBootPart); CHAR16 *pszDev = DevicePathToStr(pBootDisk); Print(L"%N\nDisk: %s\n", pszDev); FreePool(pszDev); Print(L"%H\n[ INFO ] Disconnecting problematic File System drivers\n"); DisconnectBlockingDrivers(); Print(L"%H\n[ WAIT ] Loading NTFS driver"); EFI_DEVICE_PATH *pDrvPath = FileDevicePath(pImage->DeviceHandle, DriverPath); if (pDrvPath == NULL) { Print(L"%E\r[ FAIL ] Unable to construct path to NTFS driver\n"); goto end; } nStatus = BS->LoadImage(FALSE, hImage, pDrvPath, NULL, 0, &hDriver); FreePool(pDrvPath); if (EFI_ERROR(nStatus)) { Print(L"%E\r[ FAIL ] Unable to load NTFS driver: %r\n", nStatus); goto end; } if (EFI_ERROR((nStatus = BS->StartImage(hDriver, NULL, NULL)))) { Print(L"%E\r[ FAIL ] Unable to start NTFS driver: %r\n", nStatus); goto end; } Print(L"%H\r[ OK ] NTFS driver loaded and started\n"); LINKED_LOADER_PATH_LIST_NODE *list = NULL; EFI_DEVICE_PATH *ldr; if (EFI_ERROR((nStatus = BS->LocateHandleBuffer(ByProtocol, &BlockIoProtocol, NULL, &nBlkDevs, &hBlkDevs)))) { Print(L"%E\r[ FAIL ] Unable to enumerate block devices: %r\n", nStatus); goto end; } for (UINTN i = 0; i < nBlkDevs; i++) { EFI_DEVICE_PATH *pDevice = DevicePathFromHandle(hBlkDevs[i]); pszDev = DevicePathToStr(pDevice); Print(L"%N\r[ INFO ] Probing %d devices... [%d] %s", nBlkDevs, i + 1, pszDev); FreePool(pszDev); if (CompareDevicePaths(pDevice, pBootPart) == 0) continue; if (CompareDevicePaths(pDevice, pBootDisk) == 0) continue; EFI_DEVICE_PATH *pDisk = GetParentDevice(pDevice); _Bool probe = CompareDevicePaths(pDisk, pBootDisk) == 0; FreePool(pDisk); #if !defined(_DEBUG) if (!probe) continue; #endif EFI_BLOCK_IO *blkIo; if (EFI_ERROR((nStatus = BS->OpenProtocol(hBlkDevs[i], &BlockIoProtocol, &blkIo, hImage, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL)))) { Print(L"%E\n[ WARN ] Unable to open block device, skipping: %r\n", nStatus); continue; } //No media or not a partition. if ((blkIo->Media == NULL) || (!blkIo->Media->LogicalPartition)) continue; CHAR8 *buffer = AllocatePool(blkIo->Media->BlockSize); if (buffer == NULL) { Print(L"%E\n[ WARN ] Unable to allocate buffer of size %d\n", blkIo->Media->BlockSize); continue; } nStatus = blkIo->ReadBlocks(blkIo, blkIo->Media->MediaId, 0, blkIo->Media->BlockSize, buffer); _Bool isNTFS = CompareMem(&buffer[3], NTFSMagic, sizeof(NTFSMagic)) == 0; FreePool(buffer); if (EFI_ERROR(nStatus)) { Print(L"%E\n[ WARN ] Unable to read block device, skipping: %r\n", nStatus); continue; } if (!isNTFS) continue; Print(L"%H\n[ WAIT ] Attaching NTFS driver to device"); EFI_FILE_IO_INTERFACE *fs; nStatus = BS->OpenProtocol(hBlkDevs[i], &FileSystemProtocol, NULL, hImage, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL); if (nStatus == EFI_UNSUPPORTED) { nStatus = BS->ConnectController(hBlkDevs[i], NULL, NULL, TRUE); } for (UINTN j = 0; j < NUM_RETRIES; j++) { if ((!EFI_ERROR((nStatus = BS->OpenProtocol(hBlkDevs[i], &FileSystemProtocol, &fs, hImage, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL))))) { break; } Print(L"."); BS->Stall(DELAY * 1000000); } if(EFI_ERROR(nStatus)) { Print(L"%E\r[ WARN ] Unable to attach NTFS driver, skipping: %r\n", nStatus); continue; } Print(L"%H\r[ OK ] NTFS driver attached to current device\n"); Print(L"%H\r[ WAIT ] Locating EFI boot loader"); EFI_FILE *fsRoot; if (EFI_ERROR((nStatus = fs->OpenVolume(fs, &fsRoot)))) { Print(L"%E\r[ WARN ] Unable to open root directory, skipping: %r\n", nStatus); continue; } CHAR16 *loader = StrDuplicate(LoaderPath); if (EFI_ERROR((nStatus = SetPathCase(fsRoot, loader)))) { FreePool(loader); Print(L"%E\r[ WARN ] Unable to locate EFI boot loader on this device: %r\n", nStatus); continue; } Print(L"%H\r[ OK ] EFI boot loader located at %s\n", loader); ldr = FileDevicePath(hBlkDevs[i], loader); ListAppend(&list, ldr); FreePool(loader); } UINTN nListEntries = 0, nBootEntry = 0, nPage = 0, nTotalPage = 0; EFI_INPUT_KEY key; _Bool interactive = FALSE; ListTraverse(&list, CountEntries, 0, 0, &nListEntries); switch (nListEntries) { case 0: Print(L"%E\n[ FAIL ] No bootable partition\n", nStatus); nStatus = EFI_NOT_FOUND; goto end; case 1: goto boot; default: nTotalPage = (nListEntries - 1) / PAGE_SIZE + 1; while (1) { ST->ConOut->ClearScreen(ST->ConOut); Print(L"%H*** UEFI:NTFS Multiboot ***\n"); pszDev = DevicePathToStr(pBootDisk); Print(L"%NDisk: %s\n\n%H", pszDev); FreePool(pszDev); ListTraverse(&list, DisplayEntries, nPage * PAGE_SIZE, PAGE_SIZE, NULL); Print(L"%N\nPage %hd / %hd, %hd entries\n", nPage + 1, nTotalPage, nListEntries); Print(L"%H\n[F1 - F8] [1 - 8] %N Boot corresponding entry"); Print(L"%H\n[PgUp] [<] [-] %N Previous page"); Print(L"%H\n[PgDn] [>] [+] %N Next page"); if (!interactive) { INTN nCountDown = AUTOBOOT_TIME; Print(L"%N\n\n"); while (nCountDown >= 0) { Print(L"\rWill automatically boot the first entry in %d seconds...", nCountDown); if (WaitForSingleEvent(ST->ConIn->WaitForKey, 1000 * 1000 * 10) != EFI_TIMEOUT) { interactive = TRUE; break; } nCountDown--; } if (!interactive) { goto boot; } } else { WaitForSingleEvent(ST->ConIn->WaitForKey, 0); } ST->ConIn->ReadKeyStroke(ST->ConIn, &key); switch (key.UnicodeChar) { case L'1':case L'2':case L'3':case L'4':case L'5':case L'6':case L'7':case L'8': nBootEntry = nPage * PAGE_SIZE + (key.UnicodeChar - L'1'); goto boot; case L'+':case L'=':case L'>':case L'.': if ((nPage + 1) != nTotalPage) { nPage++; } break; case L'-':case L'_': case L'<': case L',': if (nPage != 0) { nPage--; } break; default: switch (key.ScanCode) { case 0x09: if (nPage != 0) { nPage--; } break; case 0x0a: if ((nPage + 1) != nTotalPage) { nPage++; } break; case 0x0b:case 0x0c:case 0x0d:case 0x0e:case 0x0f:case 0x10:case 0x11:case 0x12: nBootEntry = nPage * PAGE_SIZE + (key.ScanCode - 0x0b); goto boot; } } } } boot: ldr = NULL; Print(L"%H"); ST->ConOut->ClearScreen(ST->ConOut); ListTraverse(&list, ReadEntry, nBootEntry, 1, &ldr); ListTraverse(&list, DisplayEntries, nBootEntry, 1, NULL); if (ldr == NULL) { Print(L"%E\n[ FAIL ] No such boot entry\n", nStatus); nStatus = EFI_NOT_FOUND; goto end; } ldr = DuplicateDevicePath(ldr); ListTraverse(&list, DestroyEntries, 0, 0, NULL); ListDestroy(&list); EFI_HANDLE hChain; nStatus = BS->LoadImage(FALSE, hImage, ldr, NULL, 0, &hChain); FreePool(ldr); if (EFI_ERROR(nStatus)) { Print(L"%E\n[ FAIL ] Unable to load boot loader: %r\n", nStatus); goto end; } Print(L"%N"); if (EFI_ERROR((nStatus = BS->StartImage(hChain, NULL, NULL)))) { Print(L"%E\n[ FAIL ] Unable to start boot loader: %r\n", nStatus); goto end; } end: if (pBootDisk) FreePool(pBootDisk); if (EFI_ERROR(nStatus)) { Print(L"Press any key to exit\n"); WaitForSingleEvent(ST->ConIn->WaitForKey, 0); ST->ConIn->ReadKeyStroke(ST->ConIn, &key); } return nStatus; }
STATIC EFI_STATUS PciRomLoadEfiDriversFromRomImage ( IN EFI_PHYSICAL_ADDRESS Rom, IN UINTN RomSize ) { CHAR16 *FileName; EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader; PCI_DATA_STRUCTURE *Pcir; UINTN ImageIndex; UINTN RomOffset; UINT32 ImageSize; UINT16 ImageOffset; EFI_HANDLE ImageHandle; EFI_STATUS Status; EFI_STATUS retStatus; EFI_DEVICE_PATH_PROTOCOL *FilePath; BOOLEAN SkipImage; UINT32 DestinationSize; UINT32 ScratchSize; UINT8 *Scratch; VOID *ImageBuffer; VOID *DecompressedImageBuffer; UINT32 ImageLength; EFI_DECOMPRESS_PROTOCOL *Decompress; UINT32 InitializationSize; VBoxLogFlowFuncEnter(); FileName = L"PciRomInMemory"; //FileName = L"PciRom Addr=0000000000000000"; //HexToString (&FileName[12], Rom, 16); ImageIndex = 0; retStatus = EFI_NOT_FOUND; RomOffset = (UINTN) Rom; do { EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomOffset; if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { return retStatus; } // // If the pointer to the PCI Data Structure is invalid, no further images can be located. // The PCI Data Structure must be DWORD aligned. // if (EfiRomHeader->PcirOffset == 0 || (EfiRomHeader->PcirOffset & 3) != 0 || RomOffset - (UINTN)Rom + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize) { break; } Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomOffset + EfiRomHeader->PcirOffset); // // If a valid signature is not present in the PCI Data Structure, no further images can be located. // if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { break; } ImageSize = Pcir->ImageLength * 512; if (RomOffset - (UINTN)Rom + ImageSize > RomSize) { break; } if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) && ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) || (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) { ImageOffset = EfiRomHeader->EfiImageHeaderOffset; InitializationSize = EfiRomHeader->InitializationSize * 512; if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) { ImageBuffer = (VOID *) (UINTN) (RomOffset + ImageOffset); ImageLength = InitializationSize - ImageOffset; DecompressedImageBuffer = NULL; // // decompress here if needed // SkipImage = FALSE; if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { SkipImage = TRUE; } if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress); if (EFI_ERROR (Status)) { SkipImage = TRUE; } else { SkipImage = TRUE; Status = Decompress->GetInfo ( Decompress, ImageBuffer, ImageLength, &DestinationSize, &ScratchSize ); if (!EFI_ERROR (Status)) { DecompressedImageBuffer = NULL; DecompressedImageBuffer = AllocatePool (DestinationSize); if (DecompressedImageBuffer != NULL) { Scratch = AllocatePool (ScratchSize); if (Scratch != NULL) { Status = Decompress->Decompress ( Decompress, ImageBuffer, ImageLength, DecompressedImageBuffer, DestinationSize, Scratch, ScratchSize ); if (!EFI_ERROR (Status)) { ImageBuffer = DecompressedImageBuffer; ImageLength = DestinationSize; SkipImage = FALSE; } gBS->FreePool (Scratch); } } } } } if (!SkipImage) { // // load image and start image // FilePath = FileDevicePath (NULL, FileName); Status = gBS->LoadImage ( FALSE, gImageHandle, FilePath, ImageBuffer, ImageLength, &ImageHandle ); if (!EFI_ERROR (Status)) { Status = gBS->StartImage (ImageHandle, NULL, NULL); if (!EFI_ERROR (Status)) { retStatus = Status; } } if (FilePath != NULL) { gBS->FreePool (FilePath); } } if (DecompressedImageBuffer != NULL) { gBS->FreePool (DecompressedImageBuffer); } } } RomOffset = RomOffset + ImageSize; ImageIndex++; } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomOffset - (UINTN) Rom) < RomSize)); VBoxLogFlowFuncLeaveRC(retStatus); return retStatus; }
EFI_STATUS LoadSingleSupportFile ( IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR16 *FileName, OUT EFI_SCT_TEST_FILE **SupportFile ) /*++ Routine Description: Load a test support file. --*/ { EFI_STATUS Status; EFI_HANDLE ImageHandle; EFI_DEVICE_PATH_PROTOCOL *FileNode; EFI_DEVICE_PATH_PROTOCOL *FilePath; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; UINTN ExitDataSize; CHAR16 *ExitData; EFI_TSL_INIT_INTERFACE *TslInit; // // Check parameters // if ((DevicePath == NULL) || (FileName == NULL) || (SupportFile == NULL)) { return EFI_INVALID_PARAMETER; } // // Debug information // EFI_SCT_DEBUG ((EFI_SCT_D_TRACE, L"Load support file <%s>", FileName)); // // Add the file path to the device path // FileNode = FileDevicePath (NULL, FileName); if (FileNode == NULL) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"FileDevicePath: Out of resources")); return EFI_OUT_OF_RESOURCES; } FilePath = AppendDevicePath (DevicePath, FileNode); if (FilePath == NULL) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"AppendDevicePath: Out of resources")); BS->FreePool (FileNode); return EFI_OUT_OF_RESOURCES; } BS->FreePool (FileNode); // // Load the support file // Status = BS->LoadImage ( FALSE, gFT->ImageHandle, FilePath, NULL, 0, &ImageHandle ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Load image - %r", Status)); BS->FreePool (FilePath); return Status; } BS->FreePool (FilePath); // // Verify the image is a driver or not // Status = BS->HandleProtocol ( ImageHandle, &gEfiLoadedImageProtocolGuid, &LoadedImage ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Locate loaded image - %r", Status)); return Status; } if ((LoadedImage->ImageCodeType == EfiBootServicesCode ) || (LoadedImage->ImageCodeType == EfiRuntimeServicesCode)) { // // It is a driver, and then verify it is a TSL (test support library) // Status = BS->StartImage ( ImageHandle, &ExitDataSize, &ExitData ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Start image - %r", Status)); return Status; } // // Is it a test support library? // Status = BS->HandleProtocol ( ImageHandle, &gEfiTslInitInterfaceGuid, &TslInit ); if (!EFI_ERROR (Status)) { Status = CreateSingleSupportFile ( DevicePath, FileName, ImageHandle, TslInit, SupportFile ); if (EFI_ERROR (Status)) { EFI_SCT_DEBUG ((EFI_SCT_D_ERROR, L"Create a support file - %r", Status)); BS->UnloadImage (ImageHandle); return Status; } return EFI_SUCCESS; } BS->UnloadImage (ImageHandle); } // // Unsupported file // EFI_SCT_DEBUG ((EFI_SCT_D_DEBUG, L"Unsupported file")); return EFI_UNSUPPORTED; }
EFI_STATUS LoadStartImage ( IN EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib, IN EFI_HANDLE CurrentImageHandle, IN CHAR16 *FileName, IN EFI_HANDLE *StartImage ) { EFI_STATUS Status; CHAR16 *EntireFileName; EFI_LOADED_IMAGE_PROTOCOL *LoadImage; EFI_DEVICE_PATH_PROTOCOL *FilePath; Status = gtBS->HandleProtocol ( CurrentImageHandle, &gEfiLoadedImageProtocolGuid, &LoadImage ); if (EFI_ERROR (Status)) { StandardLib->RecordAssertion ( StandardLib, EFI_TEST_ASSERTION_FAILED, gTestGenericFailureGuid, L"BS.HandleProtocol - build environment", L"%a:%d:Status - %r", __FILE__, (UINTN)__LINE__, Status ); return Status; } EntireFileName = NULL; EntireFileName = PoolPrint (L"%s\\%s", mFilePath, FileName); FilePath = FileDevicePath (LoadImage->DeviceHandle, EntireFileName); if (FilePath == NULL) { return EFI_OUT_OF_RESOURCES; } Status = gtBS->LoadImage ( FALSE, CurrentImageHandle, FilePath, NULL, 0, StartImage ); if (EFI_ERROR (Status)) { StandardLib->RecordAssertion ( StandardLib, EFI_TEST_ASSERTION_FAILED, gTestGenericFailureGuid, L"BS.LoadImage - build environment", L"%a:%d:Status - %r", __FILE__, (UINTN)__LINE__, Status ); gtBS->FreePool (EntireFileName); gtBS->FreePool (FilePath); return Status; } Status = gtBS->StartImage (*StartImage, 0, NULL); if (EFI_ERROR (Status)) { StandardLib->RecordAssertion ( StandardLib, EFI_TEST_ASSERTION_FAILED, gTestGenericFailureGuid, L"BS.StartImage - build environment", L"%a:%d:Status - %r", __FILE__, (UINTN)__LINE__, Status ); } gtBS->FreePool (EntireFileName); gtBS->FreePool (FilePath); return Status; }
/** 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; }
/** 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; }
/** The user Entry Point for Application. The user code starts with this function as the real entry point for the application. @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS The entry point is executed successfully. @retval other Some error occurs when executing this entry point. **/ EFI_STATUS EFIAPI UefiMain ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; LINUX_LOADER_OPTIONAL_DATA* LinuxOptionalData; EFI_DEVICE_PATH* DevicePathKernel; EFI_DEVICE_PATH* InitrdDevicePath; CHAR16* OptionalDataInitrd; CHAR8* OptionalDataArguments; CHAR16* Initrd; Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage); ASSERT_EFI_ERROR (Status); if (LoadedImage->LoadOptionsSize == 0) { Status = LinuxLoaderConfig (LoadedImage); } else { // Ensure the signature is correct LinuxOptionalData = (LINUX_LOADER_OPTIONAL_DATA*)LoadedImage->LoadOptions; if (LinuxOptionalData->Signature != LINUX_LOADER_SIGNATURE) { return EFI_UNSUPPORTED; } // Generate the File Path Node for the Linux Kernel DevicePathKernel = FileDevicePath (LoadedImage->DeviceHandle, LINUX_KERNEL_NAME); if (LinuxOptionalData->CmdLineLength > 0) { OptionalDataArguments = (CHAR8*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA); } else { OptionalDataArguments = NULL; } if (LinuxOptionalData->InitrdPathListLength > 0) { if (OptionalDataArguments != NULL) { OptionalDataInitrd = (CHAR16*)(OptionalDataArguments + LinuxOptionalData->CmdLineLength); } else { OptionalDataInitrd = (CHAR16*)LinuxOptionalData + sizeof(LINUX_LOADER_OPTIONAL_DATA); } // If pointer not aligned if ((UINTN)OptionalDataInitrd & 0x1) { Initrd = (CHAR16*)AllocateCopyPool (LinuxOptionalData->InitrdPathListLength, OptionalDataInitrd); } else { Initrd = OptionalDataInitrd; } InitrdDevicePath = FileDevicePath (LoadedImage->DeviceHandle, Initrd); } else { OptionalDataInitrd = NULL; InitrdDevicePath = NULL; Initrd = NULL; } // Load and Start the Linux Kernel (we should never return) Status = BdsBootLinuxAtag (DevicePathKernel, InitrdDevicePath, OptionalDataArguments); if ((UINTN)OptionalDataInitrd & 0x1) { FreePool (Initrd); } FreePool (DevicePathKernel); if (InitrdDevicePath) { FreePool (InitrdDevicePath); } } return Status; }
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 ; }
/** Command entry point. @param[in] RomBar The Rom Base address. @param[in] RomSize The Rom size. @param[in] FileName The file name. @retval EFI_SUCCESS The command completed successfully. @retval EFI_INVALID_PARAMETER Command usage error. @retval EFI_UNSUPPORTED Protocols unsupported. @retval EFI_OUT_OF_RESOURCES Out of memory. @retval Other value Unknown error. **/ EFI_STATUS EFIAPI LoadEfiDriversFromRomImage ( VOID *RomBar, UINTN RomSize, CONST CHAR16 *FileName ) { EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader; PCI_DATA_STRUCTURE *Pcir; UINTN ImageIndex; UINTN RomBarOffset; UINT32 ImageSize; UINT16 ImageOffset; EFI_HANDLE ImageHandle; EFI_STATUS Status; EFI_STATUS ReturnStatus; CHAR16 RomFileName[280]; EFI_DEVICE_PATH_PROTOCOL *FilePath; BOOLEAN SkipImage; UINT32 DestinationSize; UINT32 ScratchSize; UINT8 *Scratch; VOID *ImageBuffer; VOID *DecompressedImageBuffer; UINT32 ImageLength; EFI_DECOMPRESS_PROTOCOL *Decompress; UINT32 InitializationSize; ImageIndex = 0; ReturnStatus = EFI_NOT_FOUND; RomBarOffset = (UINTN) RomBar; do { EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset; if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_CORRUPT), gShellDebug1HiiHandle, FileName, ImageIndex); // PrintToken (STRING_TOKEN (STR_LOADPCIROM_IMAGE_CORRUPT), HiiHandle, ImageIndex); return ReturnStatus; } // // If the pointer to the PCI Data Structure is invalid, no further images can be located. // The PCI Data Structure must be DWORD aligned. // if (EfiRomHeader->PcirOffset == 0 || (EfiRomHeader->PcirOffset & 3) != 0 || RomBarOffset - (UINTN)RomBar + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize) { break; } Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset); // // If a valid signature is not present in the PCI Data Structure, no further images can be located. // if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { break; } ImageSize = Pcir->ImageLength * 512; if (RomBarOffset - (UINTN)RomBar + ImageSize > RomSize) { break; } if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) && ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) || (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) { ImageOffset = EfiRomHeader->EfiImageHeaderOffset; InitializationSize = EfiRomHeader->InitializationSize * 512; if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) { ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset); ImageLength = InitializationSize - ImageOffset; DecompressedImageBuffer = NULL; // // decompress here if needed // SkipImage = FALSE; if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { SkipImage = TRUE; } if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID**)&Decompress); ASSERT_EFI_ERROR(Status); if (EFI_ERROR (Status)) { SkipImage = TRUE; } else { SkipImage = TRUE; Status = Decompress->GetInfo ( Decompress, ImageBuffer, ImageLength, &DestinationSize, &ScratchSize ); if (!EFI_ERROR (Status)) { DecompressedImageBuffer = AllocateZeroPool (DestinationSize); if (ImageBuffer != NULL) { Scratch = AllocateZeroPool (ScratchSize); if (Scratch != NULL) { Status = Decompress->Decompress ( Decompress, ImageBuffer, ImageLength, DecompressedImageBuffer, DestinationSize, Scratch, ScratchSize ); if (!EFI_ERROR (Status)) { ImageBuffer = DecompressedImageBuffer; ImageLength = DestinationSize; SkipImage = FALSE; } FreePool (Scratch); } } } } } if (!SkipImage) { // // load image and start image // UnicodeSPrint (RomFileName, sizeof (RomFileName), L"%s[%d]", FileName, ImageIndex); FilePath = FileDevicePath (NULL, RomFileName); Status = gBS->LoadImage ( TRUE, gImageHandle, FilePath, ImageBuffer, ImageLength, &ImageHandle ); if (EFI_ERROR (Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_LOAD_FAIL), gShellDebug1HiiHandle, FileName, ImageIndex, Status); // PrintToken (STRING_TOKEN (STR_LOADPCIROM_LOAD_IMAGE_ERROR), HiiHandle, ImageIndex, Status); } else { Status = gBS->StartImage (ImageHandle, NULL, NULL); if (EFI_ERROR (Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_START_FAIL), gShellDebug1HiiHandle, FileName, ImageIndex, Status); // PrintToken (STRING_TOKEN (STR_LOADPCIROM_START_IMAGE), HiiHandle, ImageIndex, Status); } else { ReturnStatus = Status; } } } if (DecompressedImageBuffer != NULL) { FreePool (DecompressedImageBuffer); } } } RomBarOffset = RomBarOffset + ImageSize; ImageIndex++; } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize)); return ReturnStatus; }
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; }
EFI_STATUS PciRomLoadEfiDriversFromRomImage ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor ) /*++ Routine Description: Command entry point. Arguments: ImageHandle The image handle. SystemTable The system table. Returns: EFI_SUCCESS - The command completed successfully EFI_INVALID_PARAMETER - Command usage error EFI_UNSUPPORTED - Protocols unsupported EFI_OUT_OF_RESOURCES - Out of memory Other value - Unknown error --*/ { VOID *RomBar; UINTN RomSize; CHAR16 *FileName; EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader; PCI_DATA_STRUCTURE *Pcir; UINTN ImageIndex; UINTN RomBarOffset; UINT32 ImageSize; UINT16 ImageOffset; EFI_HANDLE ImageHandle; EFI_STATUS Status; EFI_STATUS retStatus; EFI_DEVICE_PATH_PROTOCOL *FilePath; BOOLEAN SkipImage; UINT32 DestinationSize; UINT32 ScratchSize; UINT8 *Scratch; VOID *ImageBuffer; VOID *DecompressedImageBuffer; UINT32 ImageLength; EFI_DECOMPRESS_PROTOCOL *Decompress; RomBar = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress; RomSize = (UINTN) PciOptionRomDescriptor->RomLength; FileName = L"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000"; HexToString (&FileName[11], PciOptionRomDescriptor->Seg, 8); HexToString (&FileName[24], PciOptionRomDescriptor->Bus, 2); HexToString (&FileName[31], PciOptionRomDescriptor->Dev, 2); HexToString (&FileName[39], PciOptionRomDescriptor->Func, 2); ImageIndex = 0; retStatus = EFI_NOT_FOUND; RomBarOffset = (UINTN) RomBar; do { EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset; if (EfiRomHeader->Signature != 0xaa55) { return retStatus; } Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset); ImageSize = Pcir->ImageLength * 512; if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) ) { if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) || (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ) { ImageOffset = EfiRomHeader->EfiImageHeaderOffset; ImageSize = EfiRomHeader->InitializationSize * 512; ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset); ImageLength = ImageSize - ImageOffset; DecompressedImageBuffer = NULL; // // decompress here if needed // SkipImage = FALSE; if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { SkipImage = TRUE; } if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress); if (EFI_ERROR (Status)) { SkipImage = TRUE; } else { SkipImage = TRUE; Status = Decompress->GetInfo ( Decompress, ImageBuffer, ImageLength, &DestinationSize, &ScratchSize ); if (!EFI_ERROR (Status)) { DecompressedImageBuffer = NULL; DecompressedImageBuffer = AllocatePool (DestinationSize); if (DecompressedImageBuffer != NULL) { Scratch = AllocatePool (ScratchSize); if (Scratch != NULL) { Status = Decompress->Decompress ( Decompress, ImageBuffer, ImageLength, DecompressedImageBuffer, DestinationSize, Scratch, ScratchSize ); if (!EFI_ERROR (Status)) { ImageBuffer = DecompressedImageBuffer; ImageLength = DestinationSize; SkipImage = FALSE; } gBS->FreePool (Scratch); } } } } } if (!SkipImage) { // // load image and start image // HexToString (&FileName[48], ImageIndex, 4); FilePath = FileDevicePath (NULL, FileName); Status = gBS->LoadImage ( FALSE, This->ImageHandle, FilePath, ImageBuffer, ImageLength, &ImageHandle ); if (!EFI_ERROR (Status)) { Status = gBS->StartImage (ImageHandle, NULL, NULL); if (!EFI_ERROR (Status)) { PciRomAddImageMapping ( ImageHandle, PciOptionRomDescriptor->Seg, PciOptionRomDescriptor->Bus, PciOptionRomDescriptor->Dev, PciOptionRomDescriptor->Func ); retStatus = Status; } } if (FilePath != NULL) { gBS->FreePool (FilePath); } } if (DecompressedImageBuffer != NULL) { gBS->FreePool (DecompressedImageBuffer); } } } RomBarOffset = RomBarOffset + ImageSize; ImageIndex++; } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize)); return retStatus; }
EFI_STATUS add_to_boot_list(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *arguments) { CHAR16 *fullpath = NULL; UINT64 pathlen = 0; EFI_STATUS rc = EFI_SUCCESS; rc = make_full_path(dirname, filename, &fullpath, &pathlen); if (EFI_ERROR(rc)) return rc; EFI_DEVICE_PATH *dph = NULL, *dpf = NULL, *dp = NULL; dph = DevicePathFromHandle(this_image->DeviceHandle); if (!dph) { rc = EFI_OUT_OF_RESOURCES; goto err; } dpf = FileDevicePath(fh, fullpath); if (!dpf) { rc = EFI_OUT_OF_RESOURCES; goto err; } dp = AppendDevicePath(dph, dpf); if (!dp) { rc = EFI_OUT_OF_RESOURCES; goto err; } #ifdef DEBUG_FALLBACK UINTN s = DevicePathSize(dp); int i; UINT8 *dpv = (void *)dp; for (i = 0; i < s; i++) { if (i > 0 && i % 16 == 0) Print(L"\n"); Print(L"%02x ", dpv[i]); } Print(L"\n"); CHAR16 *dps = DevicePathToStr(dp); Print(L"device path: \"%s\"\n", dps); #endif if (!first_new_option) { CHAR16 *dps = DevicePathToStr(dp); Print(L"device path: \"%s\"\n", dps); first_new_option = DuplicateDevicePath(dp); first_new_option_args = arguments; first_new_option_size = StrLen(arguments) * sizeof (CHAR16); } add_boot_option(dp, fullpath, label, arguments); err: if (dpf) FreePool(dpf); if (dp) FreePool(dp); if (fullpath) FreePool(fullpath); return rc; }
/** This function build the FsOptionMenu list which records all available file system in the system. They includes all instances of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM. @retval EFI_SUCCESS Success find the file system @retval EFI_OUT_OF_RESOURCES Can not create menu entry **/ EFI_STATUS LibFindFileSystem ( VOID ) { UINTN NoSimpleFsHandles; EFI_HANDLE *SimpleFsHandle; UINT16 *VolumeLabel; UINTN Index; EFI_STATUS Status; MENU_ENTRY *MenuEntry; FILE_CONTEXT *FileContext; UINTN OptionNumber; EFI_FILE_SYSTEM_VOLUME_LABEL *Info; NoSimpleFsHandles = 0; OptionNumber = 0; // // 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++) { // // Allocate pool for this load option // MenuEntry = LibCreateMenuEntry (); if (NULL == MenuEntry) { FreePool (SimpleFsHandle); return EFI_OUT_OF_RESOURCES; } FileContext = (FILE_CONTEXT *) MenuEntry->VariableContext; FileContext->DeviceHandle = SimpleFsHandle[Index]; FileContext->FileHandle = LibOpenRoot (FileContext->DeviceHandle); if (FileContext->FileHandle == NULL) { LibDestroyMenuEntry (MenuEntry); continue; } MenuEntry->HelpString = LibDevicePathToStr (DevicePathFromHandle (FileContext->DeviceHandle)); FileContext->FileName = LibStrDuplicate (L"\\"); FileContext->DevicePath = FileDevicePath (FileContext->DeviceHandle, FileContext->FileName); FileContext->IsDir = TRUE; FileContext->IsRoot = TRUE; // // Get current file system's Volume Label // Info = (EFI_FILE_SYSTEM_VOLUME_LABEL *) LibFileInfo (FileContext->FileHandle, &gEfiFileSystemVolumeLabelInfoIdGuid); if (Info == NULL) { VolumeLabel = L"NO FILE SYSTEM INFO"; } else { if (Info->VolumeLabel == NULL) { VolumeLabel = L"NULL VOLUME LABEL"; } else { VolumeLabel = Info->VolumeLabel; if (*VolumeLabel == 0x0000) { VolumeLabel = L"NO VOLUME LABEL"; } } } MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); ASSERT (MenuEntry->DisplayString != NULL); UnicodeSPrint ( MenuEntry->DisplayString, MAX_CHAR, L"%s, [%s]", VolumeLabel, MenuEntry->HelpString ); MenuEntry->DisplayStringToken = HiiSetString ( gFileExplorerPrivate.FeHiiHandle, 0, MenuEntry->DisplayString, NULL ); if (Info != NULL) FreePool (Info); OptionNumber++; InsertTailList (&gFileExplorerPrivate.FsOptionMenu->Head, &MenuEntry->Link); } } if (NoSimpleFsHandles != 0) { FreePool (SimpleFsHandle); } gFileExplorerPrivate.FsOptionMenu->MenuNumber = OptionNumber; return EFI_SUCCESS; }
/** This function uses policy data from the platform to determine what operating system or system utility should be loaded and invoked. This function call also optionally make the use of user input to determine the operating system or system utility to be loaded and invoked. When the DXE Core has dispatched all the drivers on the dispatch queue, this function is called. This function will attempt to connect the boot devices required to load and invoke the selected operating system or system utility. During this process, additional firmware volumes may be discovered that may contain addition DXE drivers that can be dispatched by the DXE Core. If a boot device cannot be fully connected, this function calls the DXE Service Dispatch() to allow the DXE drivers from any newly discovered firmware volumes to be dispatched. Then the boot device connection can be attempted again. If the same boot device connection operation fails twice in a row, then that boot device has failed, and should be skipped. This function should never return. @param This The EFI_BDS_ARCH_PROTOCOL instance. @return None. **/ VOID EFIAPI BdsEntry ( IN EFI_BDS_ARCH_PROTOCOL *This ) { EFI_STATUS Status; UINTN NoHandles; EFI_HANDLE *Buffer; EFI_HANDLE FvHandle; EFI_HANDLE ImageHandle; EFI_HANDLE UsbDeviceHandle; EFI_GUID NameGuid; UINTN Size; UINTN HandleCount; UINTN OldHandleCount; EFI_HANDLE *HandleBuffer; UINTN Index; EFI_DEVICE_PATH_PROTOCOL *LoadImageDevicePath; EFI_DEVICE_PATH_PROTOCOL *FileSystemDevicePath; PERF_END (NULL, "DXE", NULL, 0); PERF_START (NULL, "BDS", NULL, 0); // // Now do the EFI stuff // Size = 0x100; gST->FirmwareVendor = AllocateRuntimePool (Size); ASSERT (gST->FirmwareVendor != NULL); UnicodeSPrint (gST->FirmwareVendor, Size, L"BeagleBoard EFI %a %a", __DATE__, __TIME__); // // Now we need to setup the EFI System Table with information about the console devices. // This code is normally in the console spliter driver on platforms that support multiple // consoles at the same time // Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextOutProtocolGuid, NULL, &NoHandles, &Buffer); if (!EFI_ERROR (Status)) { // Use the first SimpleTextOut we find and update the EFI System Table gST->ConsoleOutHandle = Buffer[0]; gST->StandardErrorHandle = Buffer[0]; Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextOutProtocolGuid, (VOID **)&gST->ConOut); ASSERT_EFI_ERROR (Status); gST->StdErr = gST->ConOut; gST->ConOut->OutputString (gST->ConOut, L"BDS: Console Started!!!!\n\r"); FreePool (Buffer); gConsolePresent = TRUE; } Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleTextInProtocolGuid, NULL, &NoHandles, &Buffer); if (!EFI_ERROR (Status)) { // Use the first SimpleTextIn we find and update the EFI System Table gST->ConsoleInHandle = Buffer[0]; Status = gBS->HandleProtocol (Buffer[0], &gEfiSimpleTextInProtocolGuid, (VOID **)&gST->ConIn); ASSERT_EFI_ERROR (Status); FreePool (Buffer); } // // We now have EFI Consoles up and running. Print () will work now. DEBUG () and ASSERT () worked // prior to this point as they were configured to use a more primative output scheme. // // //Perform Connect // HandleCount = 0; while (1) { OldHandleCount = HandleCount; Status = gBS->LocateHandleBuffer ( AllHandles, NULL, NULL, &HandleCount, &HandleBuffer ); if (EFI_ERROR (Status)) { break; } if (HandleCount == OldHandleCount) { break; } for (Index = 0; Index < HandleCount; Index++) { gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); } } EfiSignalEventReadyToBoot (); //Locate handles for SimpleFileSystem protocol Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &HandleBuffer ); if (!EFI_ERROR(Status)) { for (Index = 0; Index < HandleCount; Index++) { //Get the device path FileSystemDevicePath = DevicePathFromHandle(HandleBuffer[Index]); if (FileSystemDevicePath == NULL) { continue; } //Check if UsbIo is on any handles in the device path. Status = gBS->LocateDevicePath(&gEfiUsbIoProtocolGuid, &FileSystemDevicePath, &UsbDeviceHandle); if (EFI_ERROR(Status)) { continue; } //Check if Usb stick has a magic EBL file. LoadImageDevicePath = FileDevicePath(HandleBuffer[Index], L"Ebl.efi"); Status = gBS->LoadImage (TRUE, gImageHandle, LoadImageDevicePath, NULL, 0, &ImageHandle); if (EFI_ERROR(Status)) { continue; } //Boot to Shell on USB stick. Status = gBS->StartImage (ImageHandle, NULL, NULL); if (EFI_ERROR(Status)) { continue; } } } // // Normal UEFI behavior is to process Globally Defined Variables as defined in Chapter 3 // (Boot Manager) of the UEFI specification. For this embedded system we don't do this. // // // Search all the FVs for an application with a UI Section of Ebl. A .FDF file can be used // to control the names of UI sections in an FV. // Status = FindApplicationMatchingUiSection (L"Ebl", &FvHandle, &NameGuid); if (!EFI_ERROR (Status)) { //Boot to Shell. Status = LoadPeCoffSectionFromFv (FvHandle, &NameGuid); if (EFI_ERROR(Status)) { DEBUG((EFI_D_ERROR, "Boot from Shell failed. Status: %r\n", Status)); } } // // EFI does not define the behaviour if all boot attemps fail and the last one returns. // So we make a policy choice to reset the system since this BDS does not have a UI. // gRT->ResetSystem (EfiResetShutdown, Status, 0, NULL); return ; }