Skip to content

Commit

Permalink
Enable firmware validation
Browse files Browse the repository at this point in the history
  • Loading branch information
JaciBrunning committed Dec 26, 2023
1 parent 474661b commit 8d73603
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 31 deletions.
15 changes: 12 additions & 3 deletions grapple-hook/grapple-hook-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,13 @@ pub fn rpc(_attr: TokenStream, input: TokenStream) -> TokenStream {
_ => Err("Not a path!").unwrap(),
};

let boundless_generics = generics.params.iter().map(|x| match x {
syn::GenericParam::Lifetime(lt) => { let l = &lt.lifetime; quote!{ #l } },
syn::GenericParam::Type(t) => { let t = &t.ident; quote! { #t } },
syn::GenericParam::Const(_c) => quote!{},
});
let boundless_generics2 = boundless_generics.clone();

let items = t.items.iter();

let fns = t.items.iter().filter_map(|x| match x {
Expand Down Expand Up @@ -230,7 +237,7 @@ pub fn rpc(_attr: TokenStream, input: TokenStream) -> TokenStream {
};

// TODO: These need to eject the inner type from anyhow::Result.
quote! {
let q = quote! {
#[derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
#[serde(tag="method", content="data")]
pub enum #request_enum_ident {
Expand All @@ -251,12 +258,14 @@ pub fn rpc(_attr: TokenStream, input: TokenStream) -> TokenStream {
}

#[async_trait::async_trait]
impl RpcBase for #ty {
impl #generics RpcBase for #ty {
async fn rpc_call(&self, data: serde_json::Value) -> anyhow::Result<serde_json::Value> {
serde_json::to_value(self.rpc_process(serde_json::from_value(data).map_err(|e| anyhow::anyhow!(e))?).await?).map_err(|e| anyhow::anyhow!(e))
}
}
}.into()
};

q.into()
}

/* Helpers */
Expand Down
2 changes: 1 addition & 1 deletion grapple-hook/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "grapple-hook",
"private": true,
"version": "24.0.0",
"version": "24.0.1",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
6 changes: 3 additions & 3 deletions grapple-hook/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion grapple-hook/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "grapple-hook"
version = "24.0.0"
version = "24.0.1"
description = "Configuration Tool for Grapple Hardware"
authors = ["Jaci Brunning <[email protected]>"]
license = "GPLv3"
Expand Down
4 changes: 2 additions & 2 deletions grapple-hook/src-tauri/src/devices/device_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ impl DeviceManager {
let send = super::SendWrapper(self.send.get(domain).unwrap().clone(), self.replies_waiting.get(domain).unwrap().clone());

let device = match (&id, device_type) {
(DeviceId::Dfu(..), _) => Box::new(FirmwareUpgradeDevice::new(send, info_arc.clone())),
(_, DeviceType::Grapple(GrappleModelId::LaserCan)) => LaserCan::maybe_gate(send, info_arc.clone(), LaserCan::new).await,
(DeviceId::Dfu(..), DeviceType::Grapple(GrappleModelId::LaserCan)) => Box::new(FirmwareUpgradeDevice::<LaserCan>::new(send, info_arc.clone())),
(DeviceId::Serial(..), DeviceType::Grapple(GrappleModelId::LaserCan)) => LaserCan::maybe_gate(send, info_arc.clone(), LaserCan::new).await,
_ => unreachable!()
};

Expand Down
16 changes: 13 additions & 3 deletions grapple-hook/src-tauri/src/devices/lasercan.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use grapple_frc_msgs::{grapple::{Request, errors::{GrappleError, CowStr}, lasercan::{LaserCanStatusFrame, LaserCanMessage, LaserCanRoi}, GrappleDeviceMessage, TaggedGrappleMessage}, DEVICE_ID_BROADCAST, Message, ManufacturerMessage, request_factory};
use grapple_frc_msgs::{grapple::{Request, errors::{GrappleError, CowStr}, lasercan::{LaserCanStatusFrame, LaserCanMessage, LaserCanRoi}, GrappleDeviceMessage, TaggedGrappleMessage, device_info::GrappleModelId}, DEVICE_ID_BROADCAST, request_factory};
use grapple_hook_macros::rpc;
use tokio::sync::RwLock;

use crate::rpc::RpcBase;
use super::{SendWrapper, SharedInfo, GrappleDevice, FirmwareUpgradeDevice, Device, FirmwareUpgradeDeviceRequest, GrappleDeviceRequest, GrappleDeviceResponse, FirmwareUpgradeDeviceResponse, VersionGatedDevice, RootDevice};
use super::{SendWrapper, SharedInfo, GrappleDevice, Device, GrappleDeviceRequest, GrappleDeviceResponse, VersionGatedDevice, RootDevice, start_field_upgrade, FirmwareValidatingDevice};

#[derive(Clone, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
pub struct LaserCanStatus {
Expand Down Expand Up @@ -72,11 +72,21 @@ impl Device for LaserCan {
}
}

impl FirmwareValidatingDevice for LaserCan {
fn validate_firmware(_info: &super::DeviceInfo, buf: &[u8]) -> anyhow::Result<()> {
if &buf[0x150..0x154] == &[0xBEu8, 0xBAu8, 0xFEu8, 0xCAu8] && buf[0x15c] == (GrappleModelId::LaserCan as u8) {
Ok(())
} else {
anyhow::bail!("Invalid Firmware File. Are you sure this is the correct firmware?")
}
}
}

#[rpc]
impl LaserCan {
async fn start_field_upgrade(&self) -> anyhow::Result<()> {
let serial = self.info.read().await.require_serial()?;
FirmwareUpgradeDevice::start_field_upgrade(&self.sender, serial).await
start_field_upgrade(&self.sender, serial).await
}

async fn set_range(&self, long: bool) -> anyhow::Result<()> {
Expand Down
41 changes: 24 additions & 17 deletions grapple-hook/src-tauri/src/devices/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod provider_manager;
pub mod roborio;
pub mod lasercan;

use std::{sync::Arc, time::Duration, collections::{LinkedList, HashMap}};
use std::{sync::Arc, time::Duration, collections::{LinkedList, HashMap}, marker::PhantomData};

use grapple_frc_msgs::{Validate, grapple::{device_info::GrappleModelId, GrappleDeviceMessage, firmware::GrappleFirmwareMessage, TaggedGrappleMessage, GrappleMessageId}, Message, DEVICE_ID_BROADCAST, ManufacturerMessage, binmarshal::{LengthTaggedVec, BinMarshal}, MessageId};
use grapple_hook_macros::rpc;
Expand Down Expand Up @@ -165,16 +165,17 @@ impl Device for GrappleDevice {}

/* FIRMWARE UPGRADE DEVICE */

pub struct FirmwareUpgradeDevice {
pub struct FirmwareUpgradeDevice<T: FirmwareValidatingDevice> {
sender: SendWrapper,
info: SharedInfo,
progress: Arc<RwLock<Option<f64>>>,
ack: Arc<Notify>
ack: Arc<Notify>,
_t: PhantomData<T>
}

impl FirmwareUpgradeDevice {
impl<T: FirmwareValidatingDevice> FirmwareUpgradeDevice<T> {
pub fn new(sender: SendWrapper, info: SharedInfo) -> Self {
Self { sender, info, progress: Arc::new(RwLock::new(None)), ack: Arc::new(Notify::new()) }
Self { sender, info, progress: Arc::new(RwLock::new(None)), ack: Arc::new(Notify::new()), _t: PhantomData }
}

pub async fn field_upgrade_worker(sender: SendWrapper, id: u8, data: &[u8], progress: Arc<RwLock<Option<f64>>>, ack: Arc<Notify>) -> anyhow::Result<()> {
Expand Down Expand Up @@ -207,20 +208,22 @@ impl FirmwareUpgradeDevice {

Ok(())
}
}

pub async fn start_field_upgrade(sender: &SendWrapper, serial: u32) -> anyhow::Result<()> {
sender.send(TaggedGrappleMessage::new(
DEVICE_ID_BROADCAST,
GrappleDeviceMessage::FirmwareUpdate(
GrappleFirmwareMessage::StartFieldUpgrade { serial }
)
)).await
}
pub async fn start_field_upgrade(sender: &SendWrapper, serial: u32) -> anyhow::Result<()> {
sender.send(TaggedGrappleMessage::new(
DEVICE_ID_BROADCAST,
GrappleDeviceMessage::FirmwareUpdate(
GrappleFirmwareMessage::StartFieldUpgrade { serial }
)
)).await
}

#[rpc]
impl FirmwareUpgradeDevice {
impl<T: FirmwareValidatingDevice + Send + Sync> FirmwareUpgradeDevice<T> {
async fn do_field_upgrade(&self, data: Vec<u8>) -> anyhow::Result<()> {
<T>::validate_firmware(&*self.info.read().await, &data)?;

let sender = self.sender.clone();
let progress = self.progress.clone();
let id = self.info.read().await.require_device_id()?;
Expand All @@ -238,14 +241,14 @@ impl FirmwareUpgradeDevice {
}
}

impl RootDevice for FirmwareUpgradeDevice {
impl<T: FirmwareValidatingDevice + Send + Sync> RootDevice for FirmwareUpgradeDevice<T> {
fn device_class(&self) -> &'static str {
"GrappleFirmwareUpgrade"
}
}

#[async_trait::async_trait]
impl Device for FirmwareUpgradeDevice {
impl<T: FirmwareValidatingDevice + Send + Sync> Device for FirmwareUpgradeDevice<T> {
async fn handle(&self, msg: TaggedGrappleMessage) -> anyhow::Result<()> {
if msg.device_id == DEVICE_ID_BROADCAST || Some(msg.device_id) == self.info.read().await.device_id {
match msg.clone().msg {
Expand All @@ -262,6 +265,10 @@ impl Device for FirmwareUpgradeDevice {
}
}

pub trait FirmwareValidatingDevice {
fn validate_firmware(info: &DeviceInfo, buf: &[u8]) -> anyhow::Result<()>;
}

#[async_trait::async_trait]
pub trait VersionGatedDevice : RootDevice + Sized + Sync + 'static {
fn validate_version(version: Option<String>) -> anyhow::Result<()>;
Expand Down Expand Up @@ -319,7 +326,7 @@ impl RootDevice for OldVersionDevice {
impl OldVersionDevice {
async fn start_field_upgrade(&self) -> anyhow::Result<()> {
let serial = self.grapple_device.info.read().await.require_serial()?;
FirmwareUpgradeDevice::start_field_upgrade(&self.grapple_device.sender, serial).await
start_field_upgrade(&self.grapple_device.sender, serial).await
}

async fn get_error(&self) -> anyhow::Result<String> {
Expand Down
2 changes: 1 addition & 1 deletion grapple-hook/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"package": {
"productName": "GrappleHook",
"version": "24.0.0"
"version": "24.0.1"
},
"tauri": {
"allowlist": {
Expand Down

0 comments on commit 8d73603

Please sign in to comment.