bb_flasher_sd/
lib.rs

1//! Library to flash SD cards with OS images. Powers sd card flashing in [BeagleBoard Imager].
2//!
3//! Also allows optional extra [Customization] for BeagleBoard images. Currently only supports
4//! sysconf based post-install configuration.
5//!
6//! # Platform Support
7//!
8//! - Linux
9//! - Windows
10//! - MacOS
11//!
12//! # Features
13//!
14//! - `udev`: Dynamic permissions on Linux. Mostly useful for GUI and flatpaks
15//! - `macos_authopen`: Dynamic permissions on MacOS.
16//!
17//! # Usage
18//!
19//! ```no_run
20//! use std::path::Path;
21//! use std::fs::File;
22//!
23//! let dst = Path::new("/tmp/dummy");
24//! let img = || {
25//!     Ok((File::open("/tmp/image")?, 1024))
26//! };
27//! let (tx, rx) = futures::channel::mpsc::channel(20);
28//!
29//! let flash_thread = std::thread::spawn(move || {
30//!     bb_flasher_sd::flash(
31//!         img,
32//!         dst,
33//!         true,
34//!         Some(tx),
35//!         None,
36//!         None
37//!     )
38//! });
39//!
40//! let msgs = futures::executor::block_on_stream(rx);
41//! for m in msgs {
42//!     println!("{:?}", m);
43//! }
44//!
45//! flash_thread.join().unwrap().unwrap()
46//! ```
47//!
48//! [BeagleBoard Imager]: https://openbeagle.org/ayush1325/bb-imager-rs
49
50use std::{io, path::PathBuf};
51
52use thiserror::Error;
53
54pub(crate) mod customization;
55mod flashing;
56mod helpers;
57pub(crate) mod pal;
58
59pub use customization::Customization;
60pub use flashing::flash;
61
62pub(crate) type Result<T, E = Error> = std::result::Result<T, E>;
63
64#[derive(Error, Debug)]
65/// Errors for this crate
66pub enum Error {
67    #[error("Sha256 verification error")]
68    Sha256Verification,
69    #[error("Failed to customize flashed image {0}")]
70    Customization(String),
71    #[error("IO Error: {0}")]
72    IoError(io::Error),
73    /// Aborted before completing
74    #[error("Aborted before completing")]
75    Aborted,
76    #[error("Failed to format SD Card: {0}")]
77    FailedToFormat(String),
78    #[error("Failed to open {0}")]
79    FailedToOpenDestination(String),
80
81    #[error("Udisks2 Error: {0}")]
82    #[cfg(feature = "udev")]
83    Udisks(#[from] udisks2::Error),
84
85    #[cfg(windows)]
86    #[error("Drive path is not valid")]
87    InvalidDrive,
88    #[cfg(windows)]
89    #[error("Failed to find the drive {0}")]
90    DriveNotFound(String),
91    #[cfg(windows)]
92    #[error("Windows Error: {0}")]
93    WindowsError(#[from] windows::core::Error),
94}
95
96impl From<io::Error> for Error {
97    fn from(value: io::Error) -> Self {
98        Self::IoError(value)
99    }
100}
101
102/// Enumerate all SD Cards in system
103pub fn devices() -> std::collections::HashSet<Device> {
104    bb_drivelist::drive_list()
105        .expect("Unsupported OS for Sd Card")
106        .into_iter()
107        .filter(|x| x.is_removable)
108        .filter(|x| !x.is_virtual)
109        .map(|x| Device::new(x.description, x.raw.into(), x.size))
110        .collect()
111}
112
113#[derive(Hash, Debug, PartialEq, Eq, Clone)]
114/// SD Card
115pub struct Device {
116    pub name: String,
117    pub path: PathBuf,
118    pub size: u64,
119}
120
121impl Device {
122    const fn new(name: String, path: PathBuf, size: u64) -> Self {
123        Self { name, path, size }
124    }
125}
126
127/// Format SD card to fat32
128pub fn format(dst: &std::path::Path) -> Result<()> {
129    crate::pal::format(dst)
130}
131
132/// Flashing status
133#[derive(Clone, Debug)]
134pub enum Status {
135    Preparing,
136    Flashing(f32),
137    Verifying(f32),
138}