Skip to main content

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.
4//!
5//! # Platform Support
6//!
7//! - Linux
8//! - Windows
9//! - MacOS
10//!
11//! # Features
12//!
13//! - `udev`: Dynamic permissions on Linux. Mostly useful for GUI and flatpaks
14//! - `macos_authopen`: Dynamic permissions on MacOS.
15//!
16//! # Usage
17//!
18//! ```no_run
19//! use std::path::PathBuf;
20//! use std::fs::File;
21//!
22//! #[tokio::main]
23//! async fn main() {
24//!     let dst = PathBuf::from("/tmp/dummy").into();
25//!     let img = async move {
26//!         let f = tokio::fs::File::open("/tmp/image").await?.into_std().await;
27//!         let size = f.metadata().unwrap().len();
28//!         Ok((f, size))
29//!     };
30//!     let (tx, mut rx) = tokio::sync::mpsc::channel(20);
31//!
32//!     let flash_thread = tokio::spawn(async move { bb_flasher_sd::flash(img, None::<std::future::Ready<std::io::Result<Box<str>>>>, dst, Some(tx), Vec::new(), None).await });
33//!
34//!     while let Some(m) = rx.recv().await {
35//!         println!("{:?}", m);
36//!     }
37//!
38//!     flash_thread.await.unwrap().unwrap()
39//! }
40//! ```
41//!
42//! [BeagleBoard Imager]: https://openbeagle.org/ayush1325/bb-imager-rs
43
44use std::{io, path::PathBuf};
45
46use thiserror::Error;
47
48pub(crate) mod customization;
49mod flashing;
50mod helpers;
51pub(crate) mod pal;
52
53pub use customization::{Customization, ParitionType};
54pub use flashing::flash;
55
56pub(crate) type Result<T, E = Error> = std::result::Result<T, E>;
57
58#[derive(Error, Debug)]
59/// Errors for this crate
60pub enum Error {
61    /// The partition table of image invalid.
62    #[error("Partition table of image not valid.")]
63    InvalidPartitionTable,
64    #[error("Only FAT BOOT partitions are supported.")]
65    InvalidBootPartition,
66    #[error("Failed to create customization {file}")]
67    CustomizationFileCreateFail {
68        #[source]
69        source: io::Error,
70        file: Box<str>,
71    },
72    /// Unknown error occured during IO.
73    #[error("Unknown Error during IO. Please check logs for more information.")]
74    IoError {
75        #[from]
76        #[source]
77        source: io::Error,
78    },
79    /// Aborted before completing
80    #[error("Aborted before completing.")]
81    Aborted,
82    #[error("Failed to format SD Card.")]
83    FailedToFormat {
84        #[source]
85        source: io::Error,
86    },
87    #[error("Failed to open SD Card.")]
88    FailedToOpenDestination {
89        #[source]
90        source: anyhow::Error,
91    },
92    #[error("Invalid bmap for the image.")]
93    InvalidBmap,
94    #[error("Writer thread has been closed.")]
95    WriterClosed,
96
97    #[cfg(windows)]
98    #[error("Failed to clear SD Card.")]
99    WindowsCleanError(std::process::Output),
100}
101
102/// Enumerate all SD Cards in system
103pub fn devices(filter: bool) -> std::collections::HashSet<Device> {
104    bb_drivelist::drive_list()
105        .expect("Unsupported OS for Sd Card")
106        .into_iter()
107        .filter(|x| {
108            if filter {
109                x.is_removable && !x.is_virtual
110            } else {
111                true
112            }
113        })
114        .map(|x| Device::new(x.description, x.raw.into(), x.size.unwrap_or_default()))
115        .collect()
116}
117
118#[derive(Hash, Debug, PartialEq, Eq, Clone)]
119/// SD Card
120pub struct Device {
121    pub name: String,
122    pub path: PathBuf,
123    pub size: u64,
124}
125
126impl Device {
127    const fn new(name: String, path: PathBuf, size: u64) -> Self {
128        Self { name, path, size }
129    }
130}
131
132/// Format SD card to fat32
133pub async fn format(dst: &std::path::Path) -> Result<()> {
134    crate::pal::format(dst).await
135}