sylveos

Toy Operating System
Log | Files | Refs

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 };