hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
pub const MBR_SIGNATURE: u16 = 0xAA55;
pub const MBR_PARTITION_TABLE_OFFSET: usize = 446;
pub const MBR_ENTRY_SIZE: usize = 16;
pub const MBR_MAX_PARTITIONS: usize = 4;

pub const GPT_SIGNATURE: u64 = 0x5452415020494645;
pub const GPT_HEADER_LBA: u64 = 1;
pub const GPT_ENTRY_SIZE: usize = 128;
pub const GPT_MAX_PARTITIONS: usize = 128;

#[derive(Clone, Copy)]
pub enum PartitionScheme {
    Mbr,
    Gpt,
    Unknown,
}

#[derive(Clone, Copy)]
pub struct MbrEntry {
    pub status: u8,
    pub partition_type: u8,
    pub start_lba: u32,
    pub sector_count: u32,
}

#[derive(Clone, Copy)]
pub struct GptEntry {
    pub type_guid: [u8; 16],
    pub unique_guid: [u8; 16],
    pub start_lba: u64,
    pub end_lba: u64,
    pub attributes: u64,
}

impl MbrEntry {
    pub fn is_active(&self) -> bool {
        self.status == 0x80
    }

    pub fn is_empty(&self) -> bool {
        self.partition_type == 0
    }

    pub fn size_bytes(&self, sector_size: u32) -> u64 {
        self.sector_count as u64 * sector_size as u64
    }
}

impl GptEntry {
    pub fn is_empty(&self) -> bool {
        let mut all_zero = true;
        let mut i = 0;
        while i < 16 {
            if self.type_guid[i] != 0 {
                all_zero = false;
            }
            i += 1;
        }
        all_zero
    }

    pub fn size_lba(&self) -> u64 {
        if self.end_lba >= self.start_lba {
            self.end_lba - self.start_lba + 1
        } else {
            0
        }
    }

    pub fn size_bytes(&self, sector_size: u64) -> u64 {
        self.size_lba() * sector_size
    }
}

pub fn detect_scheme(sector0: &[u8]) -> PartitionScheme {
    if sector0.len() < 512 {
        return PartitionScheme::Unknown;
    }
    let sig = (sector0[511] as u16) << 8 | sector0[510] as u16;
    if sig != MBR_SIGNATURE {
        return PartitionScheme::Unknown;
    }
    let off = MBR_PARTITION_TABLE_OFFSET;
    if sector0[off + 4] == 0xEE {
        return PartitionScheme::Gpt;
    }
    PartitionScheme::Mbr
}

pub fn parse_mbr_entry(sector0: &[u8], index: usize) -> Option<MbrEntry> {
    if index >= MBR_MAX_PARTITIONS || sector0.len() < 512 {
        return None;
    }
    let off = MBR_PARTITION_TABLE_OFFSET + index * MBR_ENTRY_SIZE;
    let status = sector0[off];
    let partition_type = sector0[off + 4];
    let start_lba = u32::from_le_bytes([
        sector0[off + 8],
        sector0[off + 9],
        sector0[off + 10],
        sector0[off + 11],
    ]);
    let sector_count = u32::from_le_bytes([
        sector0[off + 12],
        sector0[off + 13],
        sector0[off + 14],
        sector0[off + 15],
    ]);
    Some(MbrEntry {
        status,
        partition_type,
        start_lba,
        sector_count,
    })
}

pub fn parse_gpt_entry(entry_data: &[u8]) -> Option<GptEntry> {
    if entry_data.len() < GPT_ENTRY_SIZE {
        return None;
    }
    let mut type_guid = [0u8; 16];
    let mut unique_guid = [0u8; 16];
    let mut i = 0;
    while i < 16 {
        type_guid[i] = entry_data[i];
        unique_guid[i] = entry_data[16 + i];
        i += 1;
    }
    let start_lba = u64::from_le_bytes([
        entry_data[32],
        entry_data[33],
        entry_data[34],
        entry_data[35],
        entry_data[36],
        entry_data[37],
        entry_data[38],
        entry_data[39],
    ]);
    let end_lba = u64::from_le_bytes([
        entry_data[40],
        entry_data[41],
        entry_data[42],
        entry_data[43],
        entry_data[44],
        entry_data[45],
        entry_data[46],
        entry_data[47],
    ]);
    let attributes = u64::from_le_bytes([
        entry_data[48],
        entry_data[49],
        entry_data[50],
        entry_data[51],
        entry_data[52],
        entry_data[53],
        entry_data[54],
        entry_data[55],
    ]);
    Some(GptEntry {
        type_guid,
        unique_guid,
        start_lba,
        end_lba,
        attributes,
    })
}