use io; use sector; use errors; def mbr_lba: size = 0; export type nombr = !void; export type mbr = struct { bootsector_sec: sector::sector, bootsector: *bootsector }; export type bootsector = struct { @offset(0) bootstrap: [440]u8, @offset(440) udid: u32, @offset(444) reserved: u16, @offset(446) entries: [4]entry, @offset(510) magic: u16, }; export type entry = struct { @offset(0) attributes: u8, @offset(4) part_type: u8, @offset(8) lba_begin: u32, @offset(12) length: u32, }; export fn bootsector_validate(self: *bootsector) bool = { if (self.magic != 0xaa55) { return false; }; return true; }; export fn from(fd: io::file) (*mbr | nombr | io::error) = { const bootsector_sec = sector::map(fd, 0, 1); sector::fetch(&bootsector_sec)?; const bootsector = bootsector_sec.buf: *[*]u8: *bootsector; if (!bootsector_validate(bootsector)) { sector::finish(&bootsector_sec); return nombr; }; let self = alloc(mbr { bootsector_sec = bootsector_sec, bootsector = bootsector }); return self; }; export fn partstream_reader(self: *mbr, entry: *entry) (io::limitstream | io::error) = { const fd = self.bootsector_sec.fd; const part = entry.lba_begin * sector::sector_length; const length = entry.length * sector::sector_length; io::seek(fd, part: io::off, io::whence::SET)?; return io::limitreader(fd, length); };