mbr.zig (4417B)
1 const std = @import("std"); 2 3 pub const vfs = @import("./vfs.zig"); 4 5 pub const Sector = vfs.Sector; 6 pub const Disk = vfs.Disk; 7 8 pub const MasterBootRecord = packed struct(Sector) { 9 // 446 bytes 10 // Zig doesn't allow arrays in packed 11 // u8[446] 12 boot_code: u3568, 13 pte1: PartitionTableEntry, 14 pte2: PartitionTableEntry, 15 pte3: PartitionTableEntry, 16 pte4: PartitionTableEntry, 17 // 0xAA55 18 signature: u16, 19 20 const Self = @This(); 21 22 pub fn get_partition(self: *const Self, n: u2) *const PartitionTableEntry { 23 return switch (n) { 24 0 => &self.pte1, 25 1 => &self.pte2, 26 2 => &self.pte3, 27 3 => &self.pte4, 28 }; 29 } 30 31 pub fn is_valid(self: *const Self) bool { 32 return self.signature == 0xAA55; 33 } 34 35 pub fn debug_print(self: *const Self, w: *std.Io.Writer) !void { 36 var boot_code: [446]u8 = undefined; 37 std.mem.writeInt(u3568, &boot_code, self.boot_code, .little); 38 const crc32 = std.hash.Crc32.hash(&boot_code); 39 40 try w.print( 41 \\bootcode crc32 = 0x{X} 42 \\signature = 0x{X} 43 \\ 44 , .{ 45 crc32, 46 self.signature, 47 }); 48 49 // Copy to proper alignment 50 var pte = self.pte1; 51 try w.print("Partition 1:\n", .{}); 52 try pte.debug_print(w); 53 54 pte = self.pte2; 55 try w.print("Partition 2:\n", .{}); 56 try pte.debug_print(w); 57 58 pte = self.pte3; 59 try w.print("Partition 3:\n", .{}); 60 try pte.debug_print(w); 61 62 pte = self.pte4; 63 try w.print("Partition 4:\n", .{}); 64 try pte.debug_print(w); 65 } 66 }; 67 68 pub const PartitionTableEntry = packed struct(u128) { 69 pub const Status = packed struct(u8) { 70 _reserved: u7, 71 bootable: bool, 72 }; 73 74 status: Status, 75 chs_start: u24, 76 partition_type: u8, 77 chs_end: u24, 78 first_lba: u32, 79 number_sectors: u32, 80 81 const Self = @This(); 82 83 pub fn is_fat32(self: *const Self) bool { 84 return self.partition_type == 0x0B or self.partition_type == 0x0C; 85 } 86 87 pub fn is_empty(self: *const Self) bool { 88 return std.mem.allEqual(u8, @ptrCast(self), 0x00); 89 } 90 91 pub fn partition_type_str(self: *const Self) []const u8 { 92 return switch (self.partition_type) { 93 0x00 => "Empty", 94 0x01 => "FAT12 - CHS", 95 0x04 => "FAT16 - 16-32 MB - CHS", 96 0x05 => "Microsoft Extended - CHS", 97 0x06 => "FAT16 - 32 MB-2 GB - CHS", 98 0x07 => "NTFS", 99 0x0B => "FAT32 - CHS", 100 0x0C => "FAT32 - LBA", 101 0x0E => "FAT16 - 32 MB-2 GB - LBA", 102 0x0F => "Microsoft Extended - LBA", 103 0x11 => "Hidden FAT12 - CHS", 104 0x14 => "Hidden FAT16 - 16-32 MB - CHS", 105 0x16 => "Hidden FAT16 - 32 MB-2 GB - CHS", 106 0x1b => "Hidden FAT32 - CHS", 107 0x1c => "Hidden FAT32 - LBA", 108 0x1e => "Hidden FAT16 - 32 MB-2 GB - LBA", 109 0x42 => "Microsoft MBR - Dynamic Disk", 110 0x82 => "Solaris x86 OR Linux Swap", 111 0x83 => "Linux", 112 0x84 => "Hibernation", 113 0x85 => "Linux Extended", 114 0x86 => "NTFS Volume Set", 115 0x87 => "NTFS Volume Set", 116 0xa0 => "Hibernation", 117 0xa1 => "Hibernation", 118 0xa5 => "FreeBSD", 119 0xa6 => "OpenBSD", 120 0xa8 => "Mac OSX", 121 0xa9 => "NetBSD", 122 0xab => "Mac OSX Boot", 123 0xb7 => "BSDI", 124 0xb8 => "BSDI swap", 125 0xee => "EFI GPT Disk", 126 0xef => "EFI System Partition", 127 0xfb => "Vmware File System", 128 0xfc => "Vmware swap", 129 else => "Unknown", 130 }; 131 } 132 133 pub fn debug_print(self: *const Self, w: *std.Io.Writer) !void { 134 try w.print( 135 \\ bootable = {any} 136 \\ chs_start = 0x{X} 137 \\ partition_type = 0x{X} ({s}) 138 \\ chs_end = 0X{X} 139 \\ lba_start = 0x{X} 140 \\ number sectors = {d} ({B}) 141 \\ 142 , .{ 143 self.status.bootable, 144 self.chs_start, 145 self.partition_type, 146 self.partition_type_str(), 147 self.chs_end, 148 self.first_lba, 149 self.number_sectors, 150 @as(u64, self.number_sectors) * 512, 151 }); 152 } 153 };