| ... | ... | @@ -9,14 +9,14 @@ const Error = Status.Error; |
| 9 | 9 | |
| 10 | 10 | pub const File = extern struct { |
| 11 | 11 | revision: u64, |
| 12 | | _open: *const fn (*const File, **File, [*:0]const u16, u64, u64) callconv(cc) Status, |
| 12 | _open: *const fn (*const File, **File, [*:0]const u16, OpenMode, Attributes) callconv(cc) Status, |
| 13 | 13 | _close: *const fn (*File) callconv(cc) Status, |
| 14 | 14 | _delete: *const fn (*File) callconv(cc) Status, |
| 15 | 15 | _read: *const fn (*File, *usize, [*]u8) callconv(cc) Status, |
| 16 | 16 | _write: *const fn (*File, *usize, [*]const u8) callconv(cc) Status, |
| 17 | 17 | _get_position: *const fn (*const File, *u64) callconv(cc) Status, |
| 18 | 18 | _set_position: *const fn (*File, u64) callconv(cc) Status, |
| 19 | | _get_info: *const fn (*const File, *align(8) const Guid, *const usize, [*]u8) callconv(cc) Status, |
| 19 | _get_info: *const fn (*const File, *align(8) const Guid, *usize, ?[*]u8) callconv(cc) Status, |
| 20 | 20 | _set_info: *const fn (*File, *align(8) const Guid, usize, [*]const u8) callconv(cc) Status, |
| 21 | 21 | _flush: *const fn (*File) callconv(cc) Status, |
| 22 | 22 | |
| ... | ... | @@ -57,7 +57,6 @@ pub const File = extern struct { |
| 57 | 57 | NoMedia, |
| 58 | 58 | DeviceError, |
| 59 | 59 | VolumeCorrupted, |
| 60 | | BufferTooSmall, |
| 61 | 60 | }; |
| 62 | 61 | pub const SetInfoError = uefi.UnexpectedError || error{ |
| 63 | 62 | Unsupported, |
| ... | ... | @@ -112,8 +111,8 @@ pub const File = extern struct { |
| 112 | 111 | self, |
| 113 | 112 | &new, |
| 114 | 113 | file_name, |
| 115 | | @intFromEnum(mode), |
| 116 | | @bitCast(create_attributes), |
| 114 | mode, |
| 115 | create_attributes, |
| 117 | 116 | )) { |
| 118 | 117 | .success => return new, |
| 119 | 118 | .not_found => return Error.NotFound, |
| ... | ... | @@ -216,21 +215,29 @@ pub const File = extern struct { |
| 216 | 215 | try self.setPosition(pos); |
| 217 | 216 | } |
| 218 | 217 | |
| 218 | /// If the underlying function returns `.buffer_too_small`, then this function |
| 219 | /// returns `.{ len, null }`. Otherwise, the 2nd value of the tuple contains |
| 220 | /// the casted reference from the buffer. |
| 219 | 221 | pub fn getInfo( |
| 220 | 222 | self: *const File, |
| 221 | 223 | comptime info: std.meta.Tag(Info), |
| 222 | | ) GetInfoError!std.meta.TagPayload(Info, info) { |
| 224 | buffer: ?[]u8, |
| 225 | ) GetInfoError!struct { usize, ?*std.meta.TagPayload(Info, info) } { |
| 223 | 226 | const InfoType = std.meta.TagPayload(Info, info); |
| 224 | 227 | |
| 225 | | var val: InfoType = undefined; |
| 226 | | var len: usize = @sizeOf(InfoType); |
| 227 | | switch (self._get_info(self, &InfoType.guid, &len, @ptrCast(&val))) { |
| 228 | | .success => return val, |
| 228 | var len = if (buffer) |b| b.len else 0; |
| 229 | switch (self._get_info( |
| 230 | self, |
| 231 | &InfoType.guid, |
| 232 | &len, |
| 233 | if (buffer) |b| b else null, |
| 234 | )) { |
| 235 | .success => return .{ len, @as(*InfoType, @ptrCast(buffer.ptr)) }, |
| 236 | .buffer_too_small => return .{ len, null }, |
| 229 | 237 | .unsupported => return Error.Unsupported, |
| 230 | 238 | .no_media => return Error.NoMedia, |
| 231 | 239 | .device_error => return Error.DeviceError, |
| 232 | 240 | .volume_corrupted => return Error.VolumeCorrupted, |
| 233 | | .buffer_too_small => return Error.BufferTooSmall, |
| 234 | 241 | else => |status| return uefi.unexpectedStatus(status), |
| 235 | 242 | } |
| 236 | 243 | } |
| ... | ... | @@ -240,8 +247,21 @@ pub const File = extern struct { |
| 240 | 247 | comptime info: std.meta.Tag(Info), |
| 241 | 248 | data: *const std.meta.TagPayload(Info, info), |
| 242 | 249 | ) SetInfoError!void { |
| 243 | | const InfoType = @TypeOf(data); |
| 244 | | switch (self._set_info(self, &InfoType.guid, @sizeOf(InfoType), @ptrCast(data))) { |
| 250 | const InfoType = std.meta.TagPayload(Info, info); |
| 251 | |
| 252 | var attached_str_len: usize = 0; |
| 253 | const attached_str: [*:0]const u16 = switch (info) { |
| 254 | .file => data.getFileName(), |
| 255 | inline .file_system, .volume_label => data.getVolumeLabel(), |
| 256 | }; |
| 257 | |
| 258 | while (attached_str[attached_str_len] != 0) : (attached_str_len += 1) {} |
| 259 | |
| 260 | // add the length (not +1 for sentinel) because `@sizeOf(InfoType)` |
| 261 | // already contains the first utf16 char |
| 262 | const len = @sizeOf(InfoType) + (attached_str_len * 2); |
| 263 | |
| 264 | switch (self._set_info(self, &InfoType.guid, len, @ptrCast(data))) { |
| 245 | 265 | .success => {}, |
| 246 | 266 | .unsupported => return Error.Unsupported, |
| 247 | 267 | .no_media => return Error.NoMedia, |
| ... | ... | @@ -268,11 +288,20 @@ pub const File = extern struct { |
| 268 | 288 | } |
| 269 | 289 | |
| 270 | 290 | pub const OpenMode = enum(u64) { |
| 271 | | read = 0x0000000000000001, |
| 272 | | // implies read |
| 273 | | write = 0x0000000000000002, |
| 274 | | // implies read+write |
| 275 | | create = 0x8000000000000000, |
| 291 | pub const Bits = packed struct(u64) { |
| 292 | // 0x0000000000000001 |
| 293 | read: bool = false, |
| 294 | // 0x0000000000000002 |
| 295 | write: bool = false, |
| 296 | _pad: u61 = 0, |
| 297 | // 0x8000000000000000 |
| 298 | create: bool = false, |
| 299 | }; |
| 300 | |
| 301 | read = @bitCast(Bits{ .read = true }), |
| 302 | read_write = @bitCast(Bits{ .read = true, .write = true }), |
| 303 | read_write_create = @bitCast(Bits{ .read = true, .write = true, .create = true }), |
| 304 | _, |
| 276 | 305 | }; |
| 277 | 306 | |
| 278 | 307 | pub const Attributes = packed struct(u64) { |