EFI_STATUS EFIAPI GetVolumeHandleWithDir(CHAR16 *SearchDir, OUT EFI_HANDLE *Handle) { EFI_STATUS Status; UINTN HandlesSize; UINTN Idx; EFI_HANDLE *Handles; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FS = NULL; EFI_FILE_PROTOCOL *FP = NULL; EFI_FILE_PROTOCOL *FP2 = NULL; // get all handles with EFI_SIMPLE_FILE_SYSTEM_PROTOCOL Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandlesSize, &Handles); if (EFI_ERROR(Status)) { Print(L"LocateHandleBuffer: %r\n", Status); return Status; } Print(L"LocateHandleBuffer: %r, got %d handles\n", Status, HandlesSize); // find handle that contains SearchDir for (Idx = 0; Idx < HandlesSize; Idx++) { // get EFI_SIMPLE_FILE_SYSTEM_PROTOCOL first Print(L"Trying handle: %p\n", Handles[Idx]); Status = gBS->OpenProtocol(Handles[Idx], &gEfiSimpleFileSystemProtocolGuid, (void **)&FS, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(Status)) { Print(L"OpenProtocol(gEfiSimpleFileSystemProtocolGuid): %r\n", Status); continue; } // open volume Status = FS->OpenVolume(FS, &FP); if (EFI_ERROR(Status)) { Print(L"OpenVolume(): %r\n", Status); gBS->CloseProtocol(Handles[Idx], &gEfiSimpleFileSystemProtocolGuid, gImageHandle, NULL); continue; } // try to open injection dir Status = FP->Open(FP, &FP2, SearchDir, EFI_FILE_MODE_READ, 0); if (EFI_ERROR(Status)) { Print(L"Open(%s): %r\n", SearchDir, Status); FP->Close(FP); gBS->CloseProtocol(Handles[Idx], &gEfiSimpleFileSystemProtocolGuid, gImageHandle, NULL); continue; } // we have found it - close it and return handle FP2->Close(FP2); FP->Close(FP); *Handle = Handles[Idx]; return EFI_SUCCESS; } // not found return EFI_NOT_FOUND; }
EFI_STATUS BdsFileSystemLoadImage ( IN OUT EFI_DEVICE_PATH **DevicePath, IN EFI_HANDLE Handle, IN EFI_DEVICE_PATH *RemainingDevicePath, IN EFI_ALLOCATE_TYPE Type, IN OUT EFI_PHYSICAL_ADDRESS *Image, OUT UINTN *ImageSize ) { EFI_STATUS Status; FILEPATH_DEVICE_PATH *FilePathDevicePath; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FsProtocol; EFI_FILE_PROTOCOL *Fs; EFI_FILE_INFO *FileInfo; EFI_FILE_PROTOCOL *File; UINTN Size; ASSERT (IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP)); FilePathDevicePath = (FILEPATH_DEVICE_PATH*)RemainingDevicePath; Status = gBS->OpenProtocol ( Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID**)&FsProtocol, gImageHandle, Handle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // Try to Open the volume and get root directory Status = FsProtocol->OpenVolume (FsProtocol, &Fs); if (EFI_ERROR (Status)) { goto CLOSE_PROTOCOL; } Status = Fs->Open (Fs, &File, FilePathDevicePath->PathName, EFI_FILE_MODE_READ, 0); if (EFI_ERROR (Status)) { goto CLOSE_PROTOCOL; } Size = 0; File->GetInfo (File, &gEfiFileInfoGuid, &Size, NULL); FileInfo = AllocatePool (Size); Status = File->GetInfo (File, &gEfiFileInfoGuid, &Size, FileInfo); if (EFI_ERROR (Status)) { goto CLOSE_FILE; } // Get the file size Size = FileInfo->FileSize; if (ImageSize) { *ImageSize = Size; } FreePool (FileInfo); Status = gBS->AllocatePages (Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image); // Try to allocate in any pages if failed to allocate memory at the defined location if ((Status == EFI_OUT_OF_RESOURCES) && (Type != AllocateAnyPages)) { Status = gBS->AllocatePages (AllocateAnyPages, EfiBootServicesCode, EFI_SIZE_TO_PAGES(Size), Image); } if (!EFI_ERROR (Status)) { Status = File->Read (File, &Size, (VOID*)(UINTN)(*Image)); } CLOSE_FILE: File->Close (File); CLOSE_PROTOCOL: gBS->CloseProtocol ( Handle, &gEfiSimpleFileSystemProtocolGuid, gImageHandle, Handle); 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; }