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