|
| 1 | +// SPDX-License-Identifier: MIT |
| 2 | +// Copyright (c) 2017 Quyzi |
| 3 | +// Copyright (c) 2024 Linaro Ltd. |
| 4 | + |
| 5 | +use std::error::Error; |
| 6 | +use std::fmt; |
| 7 | +use std::io::Cursor; |
| 8 | + |
| 9 | +use gpt::header::parse_uuid; |
| 10 | + |
| 11 | +/// Header describing a GPT disk. |
| 12 | +#[derive(Clone, Debug, Eq, PartialEq)] |
| 13 | +pub struct Header { |
| 14 | + /// GPT header magic signature, hardcoded to "EFI PART". |
| 15 | + pub signature: String, // Offset 0. "EFI PART", 45h 46h 49h 20h 50h 41h 52h 54h |
| 16 | + /// 00 00 01 00 |
| 17 | + pub revision: u32, // Offset 8 |
| 18 | + /// little endian |
| 19 | + pub header_size_le: u32, // Offset 12 |
| 20 | + /// CRC32 of the header with crc32 section zeroed |
| 21 | + pub crc32: u32, // Offset 16 |
| 22 | + /// must be 0 |
| 23 | + pub reserved: u32, // Offset 20 |
| 24 | + /// For main header, 1 |
| 25 | + pub current_lba: u64, // Offset 24 |
| 26 | + /// LBA for backup header |
| 27 | + pub backup_lba: u64, // Offset 32 |
| 28 | + /// First usable LBA for partitions (primary table last LBA + 1) |
| 29 | + pub first_usable: u64, // Offset 40 |
| 30 | + /// Last usable LBA (secondary partition table first LBA - 1) |
| 31 | + pub last_usable: u64, // Offset 48 |
| 32 | + /// UUID of the disk |
| 33 | + pub disk_guid: uuid::Uuid, // Offset 56 |
| 34 | + /// Starting LBA of partition entries |
| 35 | + pub part_start: u64, // Offset 72 |
| 36 | + /// Number of partition entries |
| 37 | + pub num_parts: u32, // Offset 80 |
| 38 | + /// Size of a partition entry, usually 128 |
| 39 | + pub part_size: u32, // Offset 84 |
| 40 | + /// CRC32 of the partition table |
| 41 | + pub crc32_parts: u32, // Offset 88 |
| 42 | +} |
| 43 | + |
| 44 | +impl fmt::Display for Header { |
| 45 | + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 46 | + write!( |
| 47 | + f, |
| 48 | + "Disk:\t\t{}\nCRC32:\t\t{}\nTable CRC:\t{}", |
| 49 | + self.disk_guid, self.crc32, self.crc32_parts |
| 50 | + ) |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +impl TryFrom<&[u8]> for Header { |
| 55 | + type Error = Box<dyn Error>; |
| 56 | + |
| 57 | + fn try_from(buf: &[u8]) -> Result<Self, Self::Error> { |
| 58 | + Ok(Header { |
| 59 | + signature: String::from_utf8(buf[0..8].into())?, |
| 60 | + revision: u32::from_le_bytes(buf[8..12].try_into()?), |
| 61 | + header_size_le: u32::from_le_bytes(buf[12..16].try_into()?), |
| 62 | + crc32: u32::from_le_bytes(buf[16..20].try_into()?), |
| 63 | + reserved: u32::from_le_bytes(buf[20..24].try_into()?), |
| 64 | + current_lba: u64::from_le_bytes(buf[24..32].try_into()?), |
| 65 | + backup_lba: u64::from_le_bytes(buf[32..40].try_into()?), |
| 66 | + first_usable: u64::from_le_bytes(buf[40..48].try_into()?), |
| 67 | + last_usable: u64::from_le_bytes(buf[48..56].try_into()?), |
| 68 | + disk_guid: parse_uuid(&mut Cursor::new(&buf[56..72]))?, |
| 69 | + part_start: u64::from_le_bytes(buf[72..80].try_into()?), |
| 70 | + num_parts: u32::from_le_bytes(buf[80..84].try_into()?), |
| 71 | + part_size: u32::from_le_bytes(buf[84..88].try_into()?), |
| 72 | + crc32_parts: u32::from_le_bytes(buf[88..92].try_into()?), |
| 73 | + }) |
| 74 | + } |
| 75 | +} |
0 commit comments