| ... | @@ -9,14 +9,14 @@ const Error = Status.Error; | ... | @@ -9,14 +9,14 @@ const Error = Status.Error; |
| 9 | | 9 | |
| 10 | pub const File = extern struct { | 10 | pub const File = extern struct { |
| 11 | revision: u64, | 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 | _close: *const fn (*File) callconv(cc) Status, | 13 | _close: *const fn (*File) callconv(cc) Status, |
| 14 | _delete: *const fn (*File) callconv(cc) Status, | 14 | _delete: *const fn (*File) callconv(cc) Status, |
| 15 | _read: *const fn (*File, *usize, [*]u8) callconv(cc) Status, | 15 | _read: *const fn (*File, *usize, [*]u8) callconv(cc) Status, |
| 16 | _write: *const fn (*File, *usize, [*]const u8) callconv(cc) Status, | 16 | _write: *const fn (*File, *usize, [*]const u8) callconv(cc) Status, |
| 17 | _get_position: *const fn (*const File, *u64) callconv(cc) Status, | 17 | _get_position: *const fn (*const File, *u64) callconv(cc) Status, |
| 18 | _set_position: *const fn (*File, u64) callconv(cc) Status, | 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 | _set_info: *const fn (*File, *align(8) const Guid, usize, [*]const u8) callconv(cc) Status, | 20 | _set_info: *const fn (*File, *align(8) const Guid, usize, [*]const u8) callconv(cc) Status, |
| 21 | _flush: *const fn (*File) callconv(cc) Status, | 21 | _flush: *const fn (*File) callconv(cc) Status, |
| 22 | | 22 | |
| ... | @@ -57,7 +57,6 @@ pub const File = extern struct { | ... | @@ -57,7 +57,6 @@ pub const File = extern struct { |
| 57 | NoMedia, | 57 | NoMedia, |
| 58 | DeviceError, | 58 | DeviceError, |
| 59 | VolumeCorrupted, | 59 | VolumeCorrupted, |
| 60 | BufferTooSmall, | | |
| 61 | }; | 60 | }; |
| 62 | pub const SetInfoError = uefi.UnexpectedError || error{ | 61 | pub const SetInfoError = uefi.UnexpectedError || error{ |
| 63 | Unsupported, | 62 | Unsupported, |
| ... | @@ -112,8 +111,8 @@ pub const File = extern struct { | ... | @@ -112,8 +111,8 @@ pub const File = extern struct { |
| 112 | self, | 111 | self, |
| 113 | &new, | 112 | &new, |
| 114 | file_name, | 113 | file_name, |
| 115 | @intFromEnum(mode), | 114 | mode, |
| 116 | @bitCast(create_attributes), | 115 | create_attributes, |
| 117 | )) { | 116 | )) { |
| 118 | .success => return new, | 117 | .success => return new, |
| 119 | .not_found => return Error.NotFound, | 118 | .not_found => return Error.NotFound, |
| ... | @@ -216,21 +215,29 @@ pub const File = extern struct { | ... | @@ -216,21 +215,29 @@ pub const File = extern struct { |
| 216 | try self.setPosition(pos); | 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 | pub fn getInfo( | 221 | pub fn getInfo( |
| 220 | self: *const File, | 222 | self: *const File, |
| 221 | comptime info: std.meta.Tag(Info), | 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 | const InfoType = std.meta.TagPayload(Info, info); | 226 | const InfoType = std.meta.TagPayload(Info, info); |
| 224 | | 227 | |
| 225 | var val: InfoType = undefined; | 228 | var len = if (buffer) |b| b.len else 0; |
| 226 | var len: usize = @sizeOf(InfoType); | 229 | switch (self._get_info( |
| 227 | switch (self._get_info(self, &InfoType.guid, &len, @ptrCast(&val))) { | 230 | self, |
| 228 | .success => return val, | 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 | .unsupported => return Error.Unsupported, | 237 | .unsupported => return Error.Unsupported, |
| 230 | .no_media => return Error.NoMedia, | 238 | .no_media => return Error.NoMedia, |
| 231 | .device_error => return Error.DeviceError, | 239 | .device_error => return Error.DeviceError, |
| 232 | .volume_corrupted => return Error.VolumeCorrupted, | 240 | .volume_corrupted => return Error.VolumeCorrupted, |
| 233 | .buffer_too_small => return Error.BufferTooSmall, | | |
| 234 | else => |status| return uefi.unexpectedStatus(status), | 241 | else => |status| return uefi.unexpectedStatus(status), |
| 235 | } | 242 | } |
| 236 | } | 243 | } |
| ... | @@ -240,8 +247,21 @@ pub const File = extern struct { | ... | @@ -240,8 +247,21 @@ pub const File = extern struct { |
| 240 | comptime info: std.meta.Tag(Info), | 247 | comptime info: std.meta.Tag(Info), |
| 241 | data: *const std.meta.TagPayload(Info, info), | 248 | data: *const std.meta.TagPayload(Info, info), |
| 242 | ) SetInfoError!void { | 249 | ) SetInfoError!void { |
| 243 | const InfoType = @TypeOf(data); | 250 | const InfoType = std.meta.TagPayload(Info, info); |
| 244 | switch (self._set_info(self, &InfoType.guid, @sizeOf(InfoType), @ptrCast(data))) { | 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 | .success => {}, | 265 | .success => {}, |
| 246 | .unsupported => return Error.Unsupported, | 266 | .unsupported => return Error.Unsupported, |
| 247 | .no_media => return Error.NoMedia, | 267 | .no_media => return Error.NoMedia, |
| ... | @@ -268,11 +288,20 @@ pub const File = extern struct { | ... | @@ -268,11 +288,20 @@ pub const File = extern struct { |
| 268 | } | 288 | } |
| 269 | | 289 | |
| 270 | pub const OpenMode = enum(u64) { | 290 | pub const OpenMode = enum(u64) { |
| 271 | read = 0x0000000000000001, | 291 | pub const Bits = packed struct(u64) { |
| 272 | // implies read | 292 | // 0x0000000000000001 |
| 273 | write = 0x0000000000000002, | 293 | read: bool = false, |
| 274 | // implies read+write | 294 | // 0x0000000000000002 |
| 275 | create = 0x8000000000000000, | 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 | pub const Attributes = packed struct(u64) { | 307 | pub const Attributes = packed struct(u64) { |