From 2e2980e3506285dcad8dac6adf8c2c1509b23c84 Mon Sep 17 00:00:00 2001 From: Sven Rademakers Date: Mon, 23 Oct 2023 18:04:33 +0100 Subject: [PATCH] add registration of Mass storage gadget Use configfs to construct a mass storage gadget. This gadget requires the mtdblock kernel driver. company specific data is not final yet. --- Cargo.lock | 104 ++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 9 ++++ src/bin/sdcard.rs | 82 +++++++++++++-------------------- src/bin/usb_gadget.rs | 51 +++++++++++++++++++++ src/bin_shared.rs | 52 +++++++++++++++++++++ src/lib.rs | 1 + 6 files changed, 239 insertions(+), 60 deletions(-) create mode 100644 src/bin/usb_gadget.rs create mode 100644 src/bin_shared.rs diff --git a/Cargo.lock b/Cargo.lock index a198265..24fcf5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,6 +69,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "bitvec" version = "1.0.1" @@ -94,6 +100,7 @@ dependencies = [ "i2c-linux", "income", "nix 0.26.2", + "usb-gadget", ] [[package]] @@ -139,7 +146,7 @@ checksum = "c1458a1df40e1e2afebb7ab60ce55c1fa8f431146205aa5f4887e0b111c27636" dependencies = [ "anstream", "anstyle", - "bitflags", + "bitflags 1.3.2", "clap_lex", "strsim", ] @@ -379,7 +386,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0268a871aaa071221d6c2875ebedcf64710e59b0d87c68c8faf5e98b87dd2a4" dependencies = [ - "bitflags", + "bitflags 1.3.2", "i2c-linux-sys", "resize-slice", ] @@ -390,7 +397,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cd060ed0016621d3da4ed3a23b0158084de90d1f3a8e59f3d391aacd3bbcf8" dependencies = [ - "bitflags", + "bitflags 1.3.2", "byteorder", "libc", ] @@ -482,9 +489,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "linux-raw-sys" @@ -508,6 +515,12 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +[[package]] +name = "macaddr" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baee0bbc17ce759db233beb01648088061bf678383130602a298e6998eedb2d8" + [[package]] name = "memchr" version = "2.5.0" @@ -547,7 +560,7 @@ version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cc", "cfg-if", "libc", @@ -560,7 +573,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", "memoffset 0.7.1", @@ -568,6 +581,17 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.4.1", + "cfg-if", + "libc", +] + [[package]] name = "number_prefix" version = "0.4.0" @@ -603,6 +627,15 @@ dependencies = [ "windows-targets 0.48.0", ] +[[package]] +name = "partition-identity" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa925f9becb532d758b0014b472c576869910929cf4c3f8054b386f19ab9e21" +dependencies = [ + "thiserror", +] + [[package]] name = "pin-project" version = "1.1.0" @@ -654,6 +687,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-mounts" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d652f8435d0ab70bf4f3590a6a851d59604831a458086541b95238cc51ffcf2" +dependencies = [ + "partition-identity", +] + [[package]] name = "quote" version = "1.0.28" @@ -675,7 +717,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -693,7 +735,7 @@ version = "0.37.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", @@ -701,6 +743,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "scopeguard" version = "1.1.0" @@ -734,6 +782,28 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.18", +] + [[package]] name = "syn" version = "1.0.109" @@ -817,6 +887,22 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74c1aa4511c38276c548406f0b1f5f8b793f000cfb51e18f278a102abd057e81" +[[package]] +name = "usb-gadget" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b17bbcab62bef9dbf2f71bdb4243bd030ad7ae5f032b40cdf3a413e31a16e014" +dependencies = [ + "bitflags 2.4.1", + "byteorder", + "libc", + "log", + "macaddr", + "nix 0.27.1", + "proc-mounts", + "strum", +] + [[package]] name = "utf8parse" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index 1348492..c170bcb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,12 @@ howudoin = {version="0.1.*", features=["term-line"]} i2c-linux = "0.1.*" income = "0.1.*" nix = "0.26.*" +usb-gadget = "0.3.0" + +[[bin]] +name= "sdcard" +path= "src/bin/sdcard.rs" + +[[bin]] +name= "usb_gadget" +path= "src/bin/usb_gadget.rs" diff --git a/src/bin/sdcard.rs b/src/bin/sdcard.rs index 2a95197..7600067 100644 --- a/src/bin/sdcard.rs +++ b/src/bin/sdcard.rs @@ -10,19 +10,16 @@ //! 4. The filesystem starts empty. Essential mountpoints like `/proc` and `/sys` need to be //! established before any meaningful work can be done. -use nix::errno::Errno; -use nix::mount::{mount, MsFlags}; - use std::{ fs, io::{self, Read, Seek}, - path::Path, sync::{self, atomic, mpsc}, thread, time::Duration, }; use bmc_installer::{ + bin_shared::*, format, image, nand::{mtd::MtdNand, Nand}, ubi::{ @@ -32,14 +29,6 @@ use bmc_installer::{ }, }; -const BANNER: &str = r" - _____ _ _ ____ ___ _ _ ____ -|_ _| | | | _ \|_ _| \ | |/ ___| - | | | | | | |_) || || \| | | _ - | | | |_| | _ < | || |\ | |_| | - |_| \___/|_| \_\___|_| \_|\____| -"; - const INSTRUCTIONS: &str = "\ This utility will perform a fresh installation of the Turing Pi 2 BMC firmware. @@ -64,38 +53,6 @@ const BOOTLOADER_PATH: &str = "/dev/mmcblk0"; const BOOTLOADER_OFFSET: u64 = 8192; // Boot ROM expects this offset, so it will never change const BOOTLOADER_SIZE: u64 = 5 * 64 * 2048; -/// Set up the basic environment (e.g. mount points). -fn setup_initramfs() -> anyhow::Result<()> { - // Handle mounts - for (mount_dev, mount_path, mount_type) in [ - (None, "/dev", "devtmpfs"), - (None, "/proc", "proc"), - (None, "/sys", "sysfs"), - ] { - let path = Path::new(mount_path); - - if !path.is_dir() { - fs::create_dir(path)?; - } - - let result = mount( - mount_dev.or(Some(path)), - path, - Some(mount_type), - MsFlags::empty(), - None::<&str>, - ); - - match result { - // Ignore EBUSY, which indicates that the mountpoint is already mounted. - Err(errno) if errno == Errno::EBUSY => (), - r => r?, - }; - } - - Ok(()) -} - /// LED blink patterns mod led { use std::time::Duration; @@ -138,13 +95,37 @@ mod led { pub const LED_BUSY: &[LedState] = &[ Custom(Duration::from_millis(66), true, [true, false, false, false]), - Custom(Duration::from_millis(66), false, [false, true, false, false]), + Custom( + Duration::from_millis(66), + false, + [false, true, false, false], + ), Custom(Duration::from_millis(66), true, [false, false, true, false]), - Custom(Duration::from_millis(66), false, [false, false, false, true]), - Custom(Duration::from_millis(66), true, [false, false, false, false]), - Custom(Duration::from_millis(66), false, [false, false, false, false]), - Custom(Duration::from_millis(66), true, [false, false, false, false]), - Custom(Duration::from_millis(66), false, [false, false, false, false]), + Custom( + Duration::from_millis(66), + false, + [false, false, false, true], + ), + Custom( + Duration::from_millis(66), + true, + [false, false, false, false], + ), + Custom( + Duration::from_millis(66), + false, + [false, false, false, false], + ), + Custom( + Duration::from_millis(66), + true, + [false, false, false, false], + ), + Custom( + Duration::from_millis(66), + false, + [false, false, false, false], + ), ]; pub const LED_DONE: &[LedState] = &[ @@ -253,7 +234,6 @@ fn rtl8370mb_led_thread(rx: mpsc::Receiver<[bool; 4]>) { } } - /// This runs in a thread and manages the LED blinking. /// /// Send new blink patterns through the MPSC channel to change the active pattern. diff --git a/src/bin/usb_gadget.rs b/src/bin/usb_gadget.rs new file mode 100644 index 0000000..87f074b --- /dev/null +++ b/src/bin/usb_gadget.rs @@ -0,0 +1,51 @@ +use anyhow::Context; +use bmc_installer::bin_shared::*; +use std::str::from_utf8; +use usb_gadget::{ + function::msd::Lun, function::msd::Msd, udcs, Class, Config, Gadget, Id, RegGadget, Strings, +}; + +const MTD_PARTITION_0: &str = "/dev/mtdblock0"; +const MTD_PARTITION_1: &str = "/dev/mtdblock1"; + +fn setup_gadget() -> anyhow::Result { + let udcs = udcs()?; + let udc = udcs.first().context("could not find UDC")?; + + let serial_number = std::fs::read("/proc/device-tree/serial-number")?; + let product = std::fs::read("/proc/device-tree/model")?; + let manufacturer = "Turing Machine"; + + let strings = Strings::new( + manufacturer, + from_utf8(&product)?.trim(), + from_utf8(&serial_number)?.trim(), + ); + + // TODO: get turing machine's specific ID + let id = Id::new(0x18d1, 0002); + let class = Class::new(0x8, 0x1, 0x0); + + let mut builder = Msd::builder(); + builder.add_lun(Lun::new(MTD_PARTITION_0)?); + builder.add_lun(Lun::new(MTD_PARTITION_1)?); + let (_, handle) = builder.build(); + let config = Config::new("Mass storage USB config").with_function(handle); + + Ok(Gadget::new(class, id, strings) + .with_config(config) + .bind(&udc)?) +} + +fn main() -> ! { + eprintln!("{BANNER}"); + + // Do all initialization before showing the instructions and prompting for confirmation + if let Err(err) = setup_initramfs() { + eprintln!("[-] The installer could not initialize properly:\n{err}"); + wait_forever(); + } + + let _ = setup_gadget().unwrap(); + loop {} +} diff --git a/src/bin_shared.rs b/src/bin_shared.rs new file mode 100644 index 0000000..7fb5023 --- /dev/null +++ b/src/bin_shared.rs @@ -0,0 +1,52 @@ +use nix::errno::Errno; +use nix::mount::{mount, MsFlags}; +use std::thread; +use std::time::Duration; +use std::{fs, path::Path}; + +pub const BANNER: &str = r" + _____ _ _ ____ ___ _ _ ____ +|_ _| | | | _ \|_ _| \ | |/ ___| + | | | | | | |_) || || \| | | _ + | | | |_| | _ < | || |\ | |_| | + |_| \___/|_| \_\___|_| \_|\____| +"; + +/// Set up the basic environment (e.g. mount points). +pub fn setup_initramfs() -> anyhow::Result<()> { + // Handle mounts + for (mount_dev, mount_path, mount_type) in [ + (None, "/dev", "devtmpfs"), + (None, "/proc", "proc"), + (None, "/sys", "sysfs"), + ] { + let path = Path::new(mount_path); + + if !path.is_dir() { + fs::create_dir(path)?; + } + + let result = mount( + mount_dev.or(Some(path)), + path, + Some(mount_type), + MsFlags::empty(), + None::<&str>, + ); + + match result { + // Ignore EBUSY, which indicates that the mountpoint is already mounted. + Err(errno) if errno == Errno::EBUSY => (), + r => r?, + }; + } + + Ok(()) +} + +/// Sleep until the user cuts power. +pub fn wait_forever() -> ! { + loop { + thread::sleep(Duration::from_secs(3600)); + } +} diff --git a/src/lib.rs b/src/lib.rs index c17f48f..5e09f03 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +pub mod bin_shared; pub mod format; pub mod image; pub mod nand;