uefi_loader/
file_system.rs

1extern crate alloc;
2
3use alloc::vec;
4use alloc::vec::Vec;
5use uefi::proto::media::file::{File, FileAttribute, FileMode, RegularFile};
6use uefi::{CStr16, Status, boot};
7
8/// Loads a file from the EFI file system.
9///
10/// # Error
11/// Returns a [`Status`] in case of error.
12pub fn load_file(path: &CStr16) -> Result<Vec<u8>, Status> {
13    let image_handle = boot::image_handle();
14    let mut sfs = match boot::get_image_file_system(image_handle) {
15        Ok(fs) => fs,
16        Err(e) => {
17            uefi::println!("Failed to get file system: {e:?}");
18            return Err(Status::UNSUPPORTED);
19        }
20    };
21
22    let mut volume = match sfs.open_volume() {
23        Ok(dir) => dir,
24        Err(e) => {
25            uefi::println!("Failed to open root directory: {e:?}");
26            return Err(Status::UNSUPPORTED);
27        }
28    };
29
30    let handle = match volume.open(path, FileMode::Read, FileAttribute::empty()) {
31        Ok(handle) => handle,
32        Err(e) => {
33            uefi::println!("Failed to read file: {e:?}");
34            return Err(Status::UNSUPPORTED);
35        }
36    };
37
38    let Some(mut file) = handle.into_regular_file() else {
39        uefi::println!("Failed to read file: not a file");
40        return Err(Status::UNSUPPORTED);
41    };
42
43    // Get file size
44    if let Err(e) = file.set_position(RegularFile::END_OF_FILE) {
45        uefi::println!("Failed to seek to file end: {e:?}");
46        return Err(Status::UNSUPPORTED);
47    }
48
49    let size = match file.get_position() {
50        Ok(size) => size,
51        Err(e) => {
52            uefi::println!("Failed to get file size: {e:?}");
53            return Err(Status::UNSUPPORTED);
54        }
55    };
56
57    // Seek back for actual reading
58    if let Err(e) = file.set_position(0) {
59        uefi::println!("Failed to seek to file start: {e:?}");
60        return Err(Status::UNSUPPORTED);
61    }
62
63    let Ok(size) = usize::try_from(size) else {
64        uefi::println!("Failed to get file size: invalid pointer widths");
65        return Err(Status::UNSUPPORTED);
66    };
67
68    let mut buf = vec![0u8; size];
69    let read = match file.read(&mut buf) {
70        Ok(size) => size,
71        Err(e) => {
72            uefi::println!("Failed to read file contents: {e:?}");
73            return Err(Status::UNSUPPORTED);
74        }
75    };
76
77    if read != size {
78        uefi::println!("Mismatch in file size: read {read} bytes, expected {size} bytes");
79        return Err(Status::UNSUPPORTED);
80    }
81
82    Ok(buf)
83}