effie/protocols/
file.rs

1use core::{
2    alloc::Layout,
3    ffi::c_void,
4    mem::{size_of, MaybeUninit},
5};
6
7use alloc::vec;
8use alloc::{
9    alloc::{alloc, dealloc},
10    boxed::Box,
11    vec::Vec,
12};
13use itoa::Integer;
14
15use crate::{system_table, util::u16_slice_from_ptr, Guid, Result, Status, Time};
16
17#[repr(C)]
18pub struct File {
19    revision: u64,
20    open: unsafe extern "efiapi" fn(
21        this: &Self,
22        new_handle: *mut *mut File,
23        file_name: *const u16,
24        open_mode: FileMode,
25        attributes: u64,
26    ) -> Status, // FIXME: type open_mode and attributes
27    close: unsafe extern "efiapi" fn() -> Status,
28    delete: unsafe extern "efiapi" fn() -> Status,
29    read: unsafe extern "efiapi" fn(
30        this: &Self,
31        buffer_size: *mut usize,
32        buffer: *mut c_void,
33    ) -> Status,
34    get_position: unsafe extern "efiapi" fn() -> Status,
35    set_position: unsafe extern "efiapi" fn(this: &Self, position: u64) -> Status,
36    get_info: unsafe extern "efiapi" fn(
37        this: &Self,
38        information_type: *const Guid,
39        buffer_size: *mut usize,
40        buffer: *mut c_void,
41    ) -> Status,
42    set_info: unsafe extern "efiapi" fn() -> Status,
43    flush: unsafe extern "efiapi" fn() -> Status,
44    open_ex: unsafe extern "efiapi" fn() -> Status,
45    read_ex: unsafe extern "efiapi" fn() -> Status,
46    write_ex: unsafe extern "efiapi" fn() -> Status,
47    flush_ex: unsafe extern "efiapi" fn() -> Status,
48}
49
50#[repr(transparent)]
51pub struct FileMode(u64);
52
53// TODO: modes combinations
54impl FileMode {
55    pub const READ: Self = Self(1);
56    pub const WRITE: Self = Self(2);
57    pub const CREATE: Self = Self(0x8000000000000000);
58}
59
60#[repr(C)]
61pub struct FileInfo {
62    pub size: u64,
63    pub file_size: u64,
64    pub physical_size: u64,
65    pub create_time: Time,
66    pub last_access_time: Time,
67    pub modification_time: Time,
68    pub attribute: u64,
69    pub file_name: [u16],
70}
71
72impl FileInfo {
73    const GUID: Guid = Guid::new(
74        0x09576e92_u32.to_ne_bytes(),
75        0x6d3f_u16.to_ne_bytes(),
76        0x11d2_u16.to_ne_bytes(),
77        0x8e,
78        0x39,
79        [0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b],
80    );
81
82    pub fn file_name(&self) -> &[u16] {
83        unsafe { u16_slice_from_ptr(self.file_name.as_ptr()) }
84    }
85}
86
87impl File {
88    pub fn open(&self, file_name: &[u16], open_mode: FileMode) -> Result<&File> {
89        let mut file = MaybeUninit::<*mut File>::uninit();
90
91        unsafe { (self.open)(self, file.as_mut_ptr(), file_name.as_ptr(), open_mode, 0) }
92            .as_result_with(unsafe { &*file.assume_init() })
93    }
94
95    pub fn set_position(&self, position: u64) -> Result {
96        unsafe { (self.set_position)(self, position) }.as_result()
97    }
98
99    pub fn read(&self, buf: &mut [u8]) -> Result {
100        unsafe { (self.read)(self, &mut buf.len(), buf.as_mut_ptr().cast()) }.as_result()
101    }
102
103    // pub fn get_info(&self) -> Result<Box<[u8]>> {
104    //     let mut buffer: Box<[u8]> = unsafe { Box::try_new([0; 1024]).unwrap_unchecked() };
105
106    //     let info = unsafe {
107    //         (self.get_info)(
108    //             self,
109    //             &FileInfo::GUID,
110    //             &mut buffer.len(),
111    //             buffer.as_mut_ptr().cast(),
112    //         )
113    //     };
114
115    //     info.as_result_with(buffer)
116    // }
117
118    pub fn get_info(&self) -> Result<&mut FileInfo> {
119        let mut buf = vec![0u8; 1];
120
121        let mut len = buf.len();
122
123        let status =
124            unsafe { (self.get_info)(self, &FileInfo::GUID, &mut 0, buf.as_mut_ptr().cast()) };
125
126        system_table().con_out().output_line(status.description())?;
127        _print_num(len)?;
128
129        unsafe {
130            let ptr = buf.as_mut_ptr();
131            let offset_of_str = 80usize;
132            let name_ptr = ptr.add(offset_of_str).cast::<u16>();
133
134            let name_len = u16_slice_from_ptr(name_ptr).len();
135            Ok(&mut *core::ptr::from_raw_parts_mut(
136                ptr.cast::<()>(),
137                name_len,
138            ))
139        }
140    }
141}
142
143fn _print_num<I: Integer>(i: I) -> Result {
144    let mut buffer = itoa::Buffer::new();
145    let printed = buffer.format(i);
146
147    _print_utf8(printed)?;
148
149    Ok(())
150}
151
152fn _print_utf8(string: &str) -> Result {
153    let system_table = system_table();
154
155    for c in string.encode_utf16() {
156        system_table.con_out().output_string(&[c, 0])?;
157    }
158
159    // system_table.con_out().output_string(w!("\r\n"))?;
160
161    Ok(())
162}