-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathlib.rs
150 lines (143 loc) · 5.63 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Library for reading and writing GPT disk data structures through a
//! block IO interface.
//!
//! This crate adds a convenient interface for reading and writing the
//! GPT types defined in the [`gpt_disk_types`] crate to a [`Disk`]. The
//! [`Disk`] is represented by the [`BlockIo`] trait, which allows this
//! library to be `no_std`. The [`BlockIo`] trait is designed to be
//! compatible with very simple block APIs, such as [`EFI_BLOCK_IO_PROTOCOL`].
//!
//! The [`BlockIoAdapter`] type allows the disk to be backed by simple
//! byte-oriented storage backends, such as `&mut [u8]` and `File` (the
//! latter requires the `std` feature).
//!
//! # Features
//!
//! * `alloc`: Enables [`Vec`] implementation of [`BlockIoAdapter`].
//! * `std`: Enables [`std::io`] implementations of [`BlockIoAdapter`],
//! as well as `std::error::Error` implementations for all of the
//! error types. Off by default.
//!
//! # Examples
//!
//! Construct a GPT disk in-memory backed by a `Vec`:
//!
//! ```
//! use gpt_disk_io::{BlockIoAdapter, BlockIo, Disk, DiskError};
//! use gpt_disk_types::{
//! guid, BlockSize, Crc32, GptHeader, GptPartitionEntry,
//! GptPartitionEntryArray, GptPartitionType, LbaLe, U32Le,
//! };
//!
//! // Space for a 4MiB disk.
//! let mut disk_storage = vec![0; 4 * 1024 * 1024];
//!
//! // Standard 512-byte block size.
//! let bs = BlockSize::BS_512;
//!
//! // `BlockIoAdapter` implements the `BlockIo` trait which is used by
//! // the `Disk` type for reading and writing.
//! let block_io = BlockIoAdapter::new(disk_storage.as_mut_slice(), bs);
//!
//! let mut disk = Disk::new(block_io)?;
//!
//! // Manually construct the header and partition entries.
//! let primary_header = GptHeader {
//! header_crc32: Crc32(U32Le::from_u32(0xa4877843)),
//! my_lba: LbaLe::from_u64(1),
//! alternate_lba: LbaLe::from_u64(8191),
//! first_usable_lba: LbaLe::from_u64(34),
//! last_usable_lba: LbaLe::from_u64(8158),
//! disk_guid: guid!("57a7feb6-8cd5-4922-b7bd-c78b0914e870"),
//! partition_entry_lba: LbaLe::from_u64(2),
//! number_of_partition_entries: U32Le::from_u32(128),
//! partition_entry_array_crc32: Crc32(U32Le::from_u32(0x9206adff)),
//! ..Default::default()
//! };
//! let secondary_header = GptHeader {
//! header_crc32: Crc32(U32Le::from_u32(0xdbeb4c13)),
//! my_lba: LbaLe::from_u64(8191),
//! alternate_lba: LbaLe::from_u64(1),
//! partition_entry_lba: LbaLe::from_u64(8159),
//! ..primary_header
//! };
//! let partition_entry = GptPartitionEntry {
//! partition_type_guid: GptPartitionType(guid!(
//! "ccf0994f-f7e0-4e26-a011-843e38aa2eac"
//! )),
//! unique_partition_guid: guid!("37c75ffd-8932-467a-9c56-8cf1f0456b12"),
//! starting_lba: LbaLe::from_u64(2048),
//! ending_lba: LbaLe::from_u64(4096),
//! attributes: Default::default(),
//! name: "hello world!".parse().unwrap(),
//! };
//!
//! // Create a buffer the length of one block. A `Vec` is used here,
//! // but any mutable byte slice with the right length will do.
//! let mut block_buf = vec![0u8; bs.to_usize().unwrap()];
//!
//! // Write out the protective MBR and GPT headers. Note that without
//! // the protective MBR, some tools won't recognize the disk as GPT.
//! disk.write_protective_mbr(&mut block_buf)?;
//! disk.write_primary_gpt_header(&primary_header, &mut block_buf)?;
//! disk.write_secondary_gpt_header(&secondary_header, &mut block_buf)?;
//!
//! // Construct the partition entry array.
//! let layout = primary_header.get_partition_entry_array_layout().unwrap();
//! let mut bytes =
//! vec![0; layout.num_bytes_rounded_to_block_as_usize(bs).unwrap()];
//! let mut entry_array =
//! GptPartitionEntryArray::new(layout, bs, &mut bytes).unwrap();
//! *entry_array.get_partition_entry_mut(0).unwrap() = partition_entry;
//!
//! // Write the primary partition entry array.
//! disk.write_gpt_partition_entry_array(&entry_array)?;
//!
//! // Write the secondary partition entry array.
//! entry_array.set_start_lba(secondary_header.partition_entry_lba.into());
//! disk.write_gpt_partition_entry_array(&entry_array)?;
//!
//! // Ensure all writes are flushed. This is not needed with the slice
//! // backend, but is good practice for "real" IO. (The disk will also
//! // flush when dropped, but any errors at that point are ignored.)
//! disk.flush()?;
//!
//! # Ok::<(), gpt_disk_io::DiskError<gpt_disk_io::SliceBlockIoError>>(())
//! ```
//!
//! [`File`]: std::fs::File
//! [`Read`]: std::io::Read
//! [`Seek`]: std::io::Seek
//! [`Write`]: std::io::Write
//! [`EFI_BLOCK_IO_PROTOCOL`]: https://uefi.org/specs/UEFI/2.10/13_Protocols_Media_Access.html#block-i-o-protocol
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unreachable_pub)]
#![warn(unsafe_code)]
#![warn(clippy::pedantic)]
#![warn(clippy::as_conversions)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::missing_panics_doc)]
#[cfg(feature = "alloc")]
extern crate alloc;
mod block_io;
mod disk;
#[cfg(feature = "std")]
mod std_support;
// Re-export dependencies.
pub use gpt_disk_types;
pub use block_io::slice_block_io::SliceBlockIoError;
pub use block_io::{BlockIo, BlockIoAdapter};
pub use disk::{Disk, DiskError};
#[cfg(feature = "std")]
pub use block_io::std_block_io::ReadWriteSeek;