Skip to content

Commit

Permalink
added "usb_boot" operation
Browse files Browse the repository at this point in the history
* split the usbboot pin functionality from the usb configuration and
  gave it its separate routine call.
* usb_boot pin is now exposed over the API via opt=set&type=usb_boot
  • Loading branch information
svenrademakers committed Sep 19, 2023
1 parent ad360f3 commit b5f5579
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 55 deletions.
27 changes: 15 additions & 12 deletions bmcd/src/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::str::FromStr;
use tokio::sync::{mpsc, Mutex};
use tpi_rs::app::bmc_application::{BmcApplication, UsbConfig};
use tpi_rs::middleware::{NodeId, UsbMode, UsbRoute};
use tpi_rs::utils::logging_sink;
type Query = web::Query<std::collections::HashMap<String, String>>;

/// version 1:
Expand Down Expand Up @@ -67,6 +68,7 @@ async fn api_entry(bmc: web::Data<BmcApplication>, query: Query) -> impl Respond

let bmc = bmc.as_ref();
match (ty.as_ref(), is_set) {
("usb_boot", true) => usb_boot(bmc, query).await.into(),
("clear_usb_boot", true) => clear_usb_boot(bmc).into(),
("network", true) => reset_network(bmc).await.into(),
("nodeinfo", true) => set_node_info().into(),
Expand Down Expand Up @@ -95,6 +97,11 @@ async fn reset_node(bmc: &BmcApplication, query: Query) -> LegacyResult<()> {
Ok(bmc.reset_node(node).await?)
}

async fn usb_boot(bmc: &BmcApplication, query: Query) -> LegacyResult<()> {
let node = get_node_param(&query)?;
bmc.usb_boot(node, true).await.map_err(Into::into)
}

fn clear_usb_boot(bmc: &BmcApplication) -> impl Into<LegacyResponse> {
bmc.clear_usb_boot().context("clear USB boot mode")
}
Expand Down Expand Up @@ -125,15 +132,10 @@ fn get_node_info(_bmc: &BmcApplication) -> impl Into<LegacyResponse> {
async fn set_node_to_msd(bmc: &BmcApplication, query: Query) -> LegacyResult<()> {
let node = get_node_param(&query)?;

let (tx, mut rx) = mpsc::channel(64);
let logger = async move {
while let Some(msg) = rx.recv().await {
log::info!("{}", msg);
}
Ok(())
};

tokio::try_join!(bmc.set_node_in_msd(node, UsbRoute::Bmc, tx), logger)
let (tx, rx) = mpsc::channel(64);
logging_sink(rx);
bmc.set_node_in_msd(node, UsbRoute::Bmc, tx)
.await
.map(|_| ())
.map_err(Into::into)
}
Expand Down Expand Up @@ -322,8 +324,9 @@ async fn set_usb_mode(bmc: &BmcApplication, query: Query) -> LegacyResult<()> {
.try_into()
.map_err(|_| LegacyResponse::bad_request("Parameter `mode` can be either 0 or 1"))?;

bmc.usb_boot(node, true).await?;
let cfg = match mode {
UsbMode::Device => UsbConfig::UsbA(node, true),
UsbMode::Device => UsbConfig::UsbA(node),
UsbMode::Host => UsbConfig::Node(node, UsbRoute::UsbA),
};

Expand All @@ -337,7 +340,7 @@ async fn get_usb_mode(bmc: &BmcApplication) -> impl Into<LegacyResponse> {
let config = bmc.get_usb_mode().await;

let (node, mode) = match config {
UsbConfig::UsbA(node, _) | UsbConfig::Bmc(node, _) => (node, UsbMode::Device),
UsbConfig::UsbA(node) | UsbConfig::Bmc(node) => (node, UsbMode::Device),
UsbConfig::Node(node, _) => (node, UsbMode::Host),
};

Expand Down Expand Up @@ -368,7 +371,7 @@ async fn handle_flash_request(
))?;

let size = u64::from_str(size)
.map_err(|_| LegacyResponse::bad_request("`lenght` parameter not a number"))?;
.map_err(|_| LegacyResponse::bad_request("`length` parameter not a number"))?;

let peer: String = request
.connection_info()
Expand Down
43 changes: 22 additions & 21 deletions tpi_rs/src/app/bmc_application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ const REBOOT_DELAY: Duration = Duration::from_millis(500);
/// Describes the different configuration the USB bus can be setup
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
pub enum UsbConfig {
/// USB-A port is host, NodeId is the device. 2nd argument specifies if the
/// usbboot pin should be set.
UsbA(NodeId, bool),
/// BMC is host, NodeId is the device. 2nd argument specifies if the
/// usbboot pin should be set.
Bmc(NodeId, bool),
/// USB-A port is host, NodeId is the device.
UsbA(NodeId),
/// BMC is host, NodeId is the device.
Bmc(NodeId),
/// NodeId is host, [UsbRoute] is configured for device
Node(NodeId, UsbRoute),
}
Expand All @@ -50,7 +48,7 @@ impl BmcApplication {
let power_controller = PowerController::new().context("power_controller")?;
let app_db = PersistencyBuilder::default()
.register_key(ACTIVATED_NODES_KEY, &0u8)
.register_key(USB_CONFIG, &UsbConfig::UsbA(NodeId::Node1, false))
.register_key(USB_CONFIG, &UsbConfig::UsbA(NodeId::Node1))
.build()
.await?;

Expand Down Expand Up @@ -166,26 +164,28 @@ impl BmcApplication {
}

pub async fn configure_usb(&self, config: UsbConfig) -> anyhow::Result<()> {
let (mode, dest, route, usbboot) = match config {
UsbConfig::UsbA(device, rpiboot) => {
(UsbMode::Device, device, UsbRoute::UsbA, Some(rpiboot))
}
UsbConfig::Bmc(device, rpiboot) => {
(UsbMode::Device, device, UsbRoute::Bmc, Some(rpiboot))
}
UsbConfig::Node(host, route) => (UsbMode::Host, host, route, None),
let (mode, dest, route) = match config {
UsbConfig::UsbA(device) => (UsbMode::Device, device, UsbRoute::UsbA),
UsbConfig::Bmc(device) => (UsbMode::Device, device, UsbRoute::Bmc),
UsbConfig::Node(host, route) => (UsbMode::Host, host, route),
};

self.pin_controller.clear_usb_boot()?;
self.pin_controller.set_usb_route(route).await?;
self.pin_controller.select_usb(dest, mode)?;
if let Some(true) = usbboot {
self.pin_controller.set_usb_boot(dest)?;
}
self.app_db.set(USB_CONFIG, config).await;
Ok(())
}

pub async fn usb_boot(&self, node: NodeId, on: bool) -> anyhow::Result<()> {
let result = if on {
self.pin_controller.set_usb_boot(node)
} else {
self.pin_controller.clear_usb_boot()
};

Ok(result?)
}

pub async fn rtl_reset(&self) -> anyhow::Result<()> {
self.pin_controller.rtl_reset().await.context("rtl error")
}
Expand Down Expand Up @@ -242,9 +242,10 @@ impl BmcApplication {
sleep(REBOOT_DELAY).await;

let config = match router {
UsbRoute::Bmc => UsbConfig::Bmc(node, true),
UsbRoute::UsbA => UsbConfig::UsbA(node, true),
UsbRoute::Bmc => UsbConfig::Bmc(node),
UsbRoute::UsbA => UsbConfig::UsbA(node),
};
self.usb_boot(node, true).await?;
self.configure_usb(config).await?;

progress_state.message = String::from("Prerequisite settings toggled, powering on...");
Expand Down
35 changes: 15 additions & 20 deletions tpi_rs/src/app/flash_application.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
use super::bmc_application::UsbConfig;
use crate::app::bmc_application::BmcApplication;
use crate::middleware::firmware_update::FlashProgress;
use crate::middleware::firmware_update::FlashStatus;
use crate::middleware::firmware_update::FlashingError;
use crate::middleware::firmware_update::SUPPORTED_DEVICES;
use crate::middleware::NodeId;
use crate::middleware::UsbRoute;
use anyhow::bail;
use anyhow::Context;
use crate::middleware::{
firmware_update::{FlashProgress, FlashStatus, FlashingError, SUPPORTED_DEVICES},
NodeId, UsbRoute,
};
use anyhow::{bail, Context};
use crc::{Crc, CRC_64_REDIS};
use futures::TryFutureExt;
use std::sync::Arc;
use std::time::Duration;
use tokio::fs;
use tokio::io::AsyncSeekExt;
use tokio::io::{self, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tokio::sync::mpsc::channel;
use tokio::sync::mpsc::Receiver;
use tokio::sync::mpsc::Sender;
use tokio::time::sleep;
use tokio::time::Instant;
use std::{sync::Arc, time::Duration};
use tokio::{
fs,
io::{self, AsyncRead, AsyncReadExt, AsyncSeekExt, AsyncWrite, AsyncWriteExt},
sync::mpsc::{channel, Receiver, Sender},
time::{sleep, Instant},
};
use tokio_util::sync::CancellationToken;

const REBOOT_DELAY: Duration = Duration::from_millis(500);
Expand Down Expand Up @@ -91,7 +85,8 @@ pub async fn flash_node<R: AsyncRead + Unpin>(context: FlashContext<R>) -> anyho
.await?;

//TODO: we probably want to restore the state prior flashing
bmc.configure_usb(UsbConfig::UsbA(node, false)).await?;
bmc.usb_boot(node, false).await?;
bmc.configure_usb(UsbConfig::UsbA(node)).await?;

sleep(REBOOT_DELAY).await;

Expand Down Expand Up @@ -143,7 +138,7 @@ where

total_read += buf_len as u64;

// we accept sporadic lost progress updates or in worst case an error
// we accept sporadic lost progress updates or in worst case an error
// inside the channel. It should never prevent the writing process from
// completing.
// Updates to the progress printer are throttled with an arbitrary
Expand Down
10 changes: 8 additions & 2 deletions tpi_rs/src/c_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,16 @@ pub extern "C" fn tpi_usb_mode_v2(mode: c_int, node: c_int, boot_pin: c_int) ->
);

let config = match mode {
UsbMode::Device => UsbConfig::UsbA(node_id, boot),
UsbMode::Device => UsbConfig::UsbA(node_id),
UsbMode::Host => UsbConfig::Node(node_id, UsbRoute::UsbA),
};
execute_routine(|bmc| Box::pin(bmc.configure_usb(config)));
execute_routine(|bmc| {
Box::pin(async move {
bmc.usb_boot(node_id, boot).await?;
bmc.configure_usb(config).await?;
Ok(())
})
});
0
}

Expand Down

0 comments on commit b5f5579

Please sign in to comment.