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, 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
53impl 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<&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 Ok(())
162}