| ... | @@ -1,4 +1,6 @@ | ... | @@ -1,4 +1,6 @@ |
| 1 | const uefi = @import("std").os.uefi; | 1 | const std = @import("std"); |
| | 2 | const uefi = std.os.uefi; |
| | 3 | const io = std.io; |
| 2 | const Guid = uefi.Guid; | 4 | const Guid = uefi.Guid; |
| 3 | const Time = uefi.Time; | 5 | const Time = uefi.Time; |
| 4 | const Status = uefi.Status; | 6 | const Status = uefi.Status; |
| ... | @@ -16,6 +18,27 @@ pub const FileProtocol = extern struct { | ... | @@ -16,6 +18,27 @@ pub const FileProtocol = extern struct { |
| 16 | _set_info: fn (*const FileProtocol, *align(8) const Guid, usize, [*]const u8) callconv(.C) Status, | 18 | _set_info: fn (*const FileProtocol, *align(8) const Guid, usize, [*]const u8) callconv(.C) Status, |
| 17 | _flush: fn (*const FileProtocol) callconv(.C) Status, | 19 | _flush: fn (*const FileProtocol) callconv(.C) Status, |
| 18 | | 20 | |
| | 21 | pub const SeekError = error{SeekError}; |
| | 22 | pub const GetSeekPosError = error{GetSeekPosError}; |
| | 23 | pub const ReadError = error{ReadError}; |
| | 24 | pub const WriteError = error{WriteError}; |
| | 25 | |
| | 26 | pub const SeekableStream = io.SeekableStream(*const FileProtocol, SeekError, GetSeekPosError, seekTo, seekBy, getPos, getEndPos); |
| | 27 | pub const Reader = io.Reader(*const FileProtocol, ReadError, readFn); |
| | 28 | pub const Writer = io.Writer(*const FileProtocol, WriteError, writeFn); |
| | 29 | |
| | 30 | pub fn seekableStream(self: *FileProtocol) SeekableStream { |
| | 31 | return .{ .context = self }; |
| | 32 | } |
| | 33 | |
| | 34 | pub fn reader(self: *FileProtocol) Reader { |
| | 35 | return .{ .context = self }; |
| | 36 | } |
| | 37 | |
| | 38 | pub fn writer(self: *FileProtocol) Writer { |
| | 39 | return .{ .context = self }; |
| | 40 | } |
| | 41 | |
| 19 | pub fn open(self: *const FileProtocol, new_handle: **const FileProtocol, file_name: [*:0]const u16, open_mode: u64, attributes: u64) Status { | 42 | pub fn open(self: *const FileProtocol, new_handle: **const FileProtocol, file_name: [*:0]const u16, open_mode: u64, attributes: u64) Status { |
| 20 | return self._open(self, new_handle, file_name, open_mode, attributes); | 43 | return self._open(self, new_handle, file_name, open_mode, attributes); |
| 21 | } | 44 | } |
| ... | @@ -32,18 +55,66 @@ pub const FileProtocol = extern struct { | ... | @@ -32,18 +55,66 @@ pub const FileProtocol = extern struct { |
| 32 | return self._read(self, buffer_size, buffer); | 55 | return self._read(self, buffer_size, buffer); |
| 33 | } | 56 | } |
| 34 | | 57 | |
| | 58 | fn readFn(self: *const FileProtocol, buffer: []u8) ReadError!usize { |
| | 59 | var size: usize = buffer.len; |
| | 60 | if (.Success != self.read(&size, buffer.ptr)) return ReadError.ReadError; |
| | 61 | return size; |
| | 62 | } |
| | 63 | |
| 35 | pub fn write(self: *const FileProtocol, buffer_size: *usize, buffer: [*]const u8) Status { | 64 | pub fn write(self: *const FileProtocol, buffer_size: *usize, buffer: [*]const u8) Status { |
| 36 | return self._write(self, buffer_size, buffer); | 65 | return self._write(self, buffer_size, buffer); |
| 37 | } | 66 | } |
| 38 | | 67 | |
| | 68 | fn writeFn(self: *const FileProtocol, bytes: []const u8) WriteError!usize { |
| | 69 | var size: usize = bytes.len; |
| | 70 | if (.Success != self.write(&size, bytes.ptr)) return WriteError.WriteError; |
| | 71 | return size; |
| | 72 | } |
| | 73 | |
| 39 | pub fn getPosition(self: *const FileProtocol, position: *u64) Status { | 74 | pub fn getPosition(self: *const FileProtocol, position: *u64) Status { |
| 40 | return self._get_position(self, position); | 75 | return self._get_position(self, position); |
| 41 | } | 76 | } |
| 42 | | 77 | |
| | 78 | fn getPos(self: *const FileProtocol) GetSeekPosError!u64 { |
| | 79 | var pos: u64 = undefined; |
| | 80 | if (.Success != self.getPosition(&pos)) return GetSeekPosError.GetSeekPosError; |
| | 81 | return pos; |
| | 82 | } |
| | 83 | |
| | 84 | fn getEndPos(self: *const FileProtocol) GetSeekPosError!u64 { |
| | 85 | // preserve the old file position |
| | 86 | var pos: u64 = undefined; |
| | 87 | if (.Success != self.getPosition(&pos)) return GetSeekPosError.GetSeekPosError; |
| | 88 | // seek to end of file to get position = file size |
| | 89 | if (.Success != self.setPosition(efi_file_position_end_of_file)) return GetSeekPosError.GetSeekPosError; |
| | 90 | // restore the old position |
| | 91 | if (.Success != self.setPosition(pos)) return GetSeekPosError.GetSeekPosError; |
| | 92 | // return the file size = position |
| | 93 | return pos; |
| | 94 | } |
| | 95 | |
| 43 | pub fn setPosition(self: *const FileProtocol, position: u64) Status { | 96 | pub fn setPosition(self: *const FileProtocol, position: u64) Status { |
| 44 | return self._set_position(self, position); | 97 | return self._set_position(self, position); |
| 45 | } | 98 | } |
| 46 | | 99 | |
| | 100 | fn seekTo(self: *const FileProtocol, pos: u64) SeekError!void { |
| | 101 | if (.Success != self.setPosition(pos)) return SeekError.SeekError; |
| | 102 | } |
| | 103 | |
| | 104 | fn seekBy(self: *const FileProtocol, offset: i64) SeekError!void { |
| | 105 | // save the old position and calculate the delta |
| | 106 | var pos: u64 = undefined; |
| | 107 | if (.Success != self.getPosition(&pos)) return SeekError.SeekError; |
| | 108 | const seek_back = offset < 0; |
| | 109 | const amt = std.math.absCast(offset); |
| | 110 | if (seek_back) { |
| | 111 | pos += amt; |
| | 112 | } else { |
| | 113 | pos -= amt; |
| | 114 | } |
| | 115 | if (.Success != self.setPosition(pos)) return SeekError.SeekError; |
| | 116 | } |
| | 117 | |
| 47 | pub fn getInfo(self: *const FileProtocol, information_type: *align(8) const Guid, buffer_size: *usize, buffer: [*]u8) Status { | 118 | pub fn getInfo(self: *const FileProtocol, information_type: *align(8) const Guid, buffer_size: *usize, buffer: [*]u8) Status { |
| 48 | return self._get_info(self, information_type, buffer_size, buffer); | 119 | return self._get_info(self, information_type, buffer_size, buffer); |
| 49 | } | 120 | } |