Skip to content

Commit

Permalink
Bail out on multiple matching bootloaders
Browse files Browse the repository at this point in the history
Currently, lpc55-host connects to the first bootloader that matches the
vid, pid and uuid filters.  With this patch, we make sure that there is
only a single bootloader that matches the filter to avoid accidentally
accessing the wrong device.
  • Loading branch information
robin-nitrokey authored and nickray committed Jun 3, 2021
1 parent c33560c commit b32ce0c
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/bin/lpc55/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use core::convert::TryFrom;
use std::io::{self, Write as _};
use std::fs;

use anyhow::{anyhow};
use anyhow::{Context as _, anyhow};
use delog::hex_str;
use log::{info, warn, trace};
use uuid::Uuid;
Expand Down Expand Up @@ -54,7 +54,7 @@ fn try_main(args: clap::ArgMatches<'_>) -> anyhow::Result<()> {

let uuid = args.value_of("UUID").map(Uuid::parse_str).transpose()?;

let bootloader = || Bootloader::try_find(vid, pid, uuid).ok_or(anyhow!("Could not attach to a bootloader"));
let bootloader = || Bootloader::try_find(vid, pid, uuid).context("Could not attach to a bootloader");

if let Some(command) = args.subcommand_matches("http") {
let bootloader = bootloader()?;
Expand Down
24 changes: 16 additions & 8 deletions src/bootloader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! Construct a `Bootloader` from a VID/PID pair (optionally a UUID to disambiguate),
//! then call its methods.
use anyhow::anyhow;
use enum_iterator::IntoEnumIterator;
use hidapi::HidApi;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -59,22 +60,29 @@ pub type Result<T> = std::result::Result<T, Error>;


impl Bootloader {
/// Select first available ROM bootloader with the given VID and PID.
///
/// TODO: Open question is whether this is a good idea.
/// For instance, `write-flash` on the wrong device could wreak havoc.
pub fn try_new(vid: Option<u16>, pid: Option<u16>) -> Option<Self> {
/// Select a unique ROM bootloader with the given VID and PID.
pub fn try_new(vid: Option<u16>, pid: Option<u16>) -> anyhow::Result<Self> {
Self::try_find(vid, pid, None)
}

/// Attempt to find a ROM bootloader with the given VID, PID and UUID.
pub fn try_find(vid: Option<u16>, pid: Option<u16>, uuid: Option<Uuid>) -> Option<Self> {
/// Attempt to find a unique ROM bootloader with the given VID, PID and UUID.
pub fn try_find(vid: Option<u16>, pid: Option<u16>, uuid: Option<Uuid>) -> anyhow::Result<Self> {
let mut bootloaders = Self::find(vid, pid, uuid);
if bootloaders.len() > 1 {
Err(anyhow!("Muliple matching bootloaders found"))
} else {
bootloaders.pop().ok_or_else(|| anyhow!("No matching bootloader found"))
}
}

/// Finds all ROM bootloader with the given VID, PID and UUID.
pub fn find(vid: Option<u16>, pid: Option<u16>, uuid: Option<Uuid>) -> Vec<Self> {
Self::list()
.into_iter()
.filter(|bootloader| vid.map_or(true, |vid| vid == bootloader.vid))
.filter(|bootloader| pid.map_or(true, |pid| pid == bootloader.pid))
.filter(|bootloader| uuid.map_or(true, |uuid| uuid.as_u128() == bootloader.uuid))
.next()
.collect()
}

/// Returns a vector of all HID devices that appear to be ROM bootloaders
Expand Down

0 comments on commit b32ce0c

Please sign in to comment.