| ... | ... | @@ -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 | 4 | const Guid = uefi.Guid; |
| 3 | 5 | const Time = uefi.Time; |
| 4 | 6 | const Status = uefi.Status; |
| ... | ... | @@ -16,6 +18,27 @@ pub const FileProtocol = extern struct { |
| 16 | 18 | _set_info: fn (*const FileProtocol, *align(8) const Guid, usize, [*]const u8) callconv(.C) Status, |
| 17 | 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 | 42 | pub fn open(self: *const FileProtocol, new_handle: **const FileProtocol, file_name: [*:0]const u16, open_mode: u64, attributes: u64) Status { |
| 20 | 43 | return self._open(self, new_handle, file_name, open_mode, attributes); |
| 21 | 44 | } |
| ... | ... | @@ -32,18 +55,66 @@ pub const FileProtocol = extern struct { |
| 32 | 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 | 64 | pub fn write(self: *const FileProtocol, buffer_size: *usize, buffer: [*]const u8) Status { |
| 36 | 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 | 74 | pub fn getPosition(self: *const FileProtocol, position: *u64) Status { |
| 40 | 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 | 96 | pub fn setPosition(self: *const FileProtocol, position: u64) Status { |
| 44 | 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 | 118 | pub fn getInfo(self: *const FileProtocol, information_type: *align(8) const Guid, buffer_size: *usize, buffer: [*]u8) Status { |
| 48 | 119 | return self._get_info(self, information_type, buffer_size, buffer); |
| 49 | 120 | } |