Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
svenrademakers committed Jan 2, 2024
1 parent c72107b commit 2445d8a
Show file tree
Hide file tree
Showing 12 changed files with 553 additions and 372 deletions.
26 changes: 26 additions & 0 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,29 @@
// limitations under the License.
pub mod into_legacy_response;
pub mod legacy;
use self::into_legacy_response::{LegacyResponse, LegacyResult};
use crate::hal::NodeId;
use actix_web::web;
use std::str::FromStr;

pub fn get_node_param(
query: &web::Query<std::collections::HashMap<String, String>>,
) -> LegacyResult<NodeId> {
let Some(node_str) = query.get("node") else {
return Err(LegacyResponse::bad_request("Missing `node` parameter"));
};

let Ok(node_num) = i32::from_str(node_str) else {
return Err(LegacyResponse::bad_request(
"Parameter `node` is not a number",
));
};

let Ok(node) = node_num.try_into() else {
return Err(LegacyResponse::bad_request(
"Parameter `node` is out of range 0..3 of node IDs",
));
};

Ok(node)
}
76 changes: 3 additions & 73 deletions src/api/legacy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//! Routes for legacy API present in versions <= 2.0.0 of the firmware.
use crate::api::into_legacy_response::LegacyResponse;
use crate::api::into_legacy_response::{LegacyResult, Null};
use crate::app::bmc_application::{BmcApplication, Encoding, UsbConfig};
use crate::app::bmc_application::{BmcApplication, UsbConfig};
use crate::app::bmc_info::{
get_fs_stat, get_ipv4_address, get_mac_address, get_net_interfaces, get_storage_info,
};
Expand Down Expand Up @@ -43,6 +43,8 @@ use std::time::Duration;
use tokio::io::AsyncBufReadExt;
use tokio_stream::StreamExt;
use tokio_util::io::ReaderStream;

use super::get_node_param;
type Query = web::Query<std::collections::HashMap<String, String>>;

/// version 1:
Expand Down Expand Up @@ -168,8 +170,6 @@ async fn api_entry(bmc: web::Data<BmcApplication>, query: Query) -> impl Respond
("reset", true) => reset_node(bmc, query).await.into(),
("sdcard", true) => format_sdcard().into(),
("sdcard", false) => get_sdcard_info(),
("uart", true) => write_to_uart(bmc, query).await.into(),
("uart", false) => read_from_uart(bmc, query).await.into(),
("usb", true) => set_usb_mode(bmc, query).await.into(),
("usb", false) => get_usb_mode(bmc).await.into(),
("info", false) => get_info().await.into(),
Expand Down Expand Up @@ -343,26 +343,6 @@ async fn set_node_to_msd(bmc: &BmcApplication, query: Query) -> LegacyResult<()>
Ok(())
}

fn get_node_param(query: &Query) -> LegacyResult<NodeId> {
let Some(node_str) = query.get("node") else {
return Err(LegacyResponse::bad_request("Missing `node` parameter"));
};

let Ok(node_num) = i32::from_str(node_str) else {
return Err(LegacyResponse::bad_request(
"Parameter `node` is not a number",
));
};

let Ok(node) = node_num.try_into() else {
return Err(LegacyResponse::bad_request(
"Parameter `node` is out of range 0..3 of node IDs",
));
};

Ok(node)
}

async fn read_os_release() -> std::io::Result<HashMap<String, String>> {
let buffer = tokio::fs::read("/etc/os-release").await?;
let mut lines = buffer.lines();
Expand Down Expand Up @@ -492,56 +472,6 @@ fn get_sdcard_info() -> LegacyResponse {
}
}

async fn write_to_uart(bmc: &BmcApplication, query: Query) -> LegacyResult<()> {
let node = get_node_param(&query)?;
let Some(cmd) = query.get("cmd") else {
return Err(LegacyResponse::bad_request("Missing `cmd` parameter"));
};
let mut data = cmd.clone();

data.push_str("\r\n");

bmc.serial_write(node, data.as_bytes())
.await
.context("write over UART")
.map_err(Into::into)
}

async fn read_from_uart(bmc: &BmcApplication, query: Query) -> LegacyResult<LegacyResponse> {
let node = get_node_param(&query)?;
let enc = get_encoding_param(&query)?;
let data = bmc.serial_read(node, enc).await?;

Ok(LegacyResponse::UartData(data))
}

fn get_encoding_param(query: &Query) -> LegacyResult<Encoding> {
let Some(enc_str) = query.get("encoding") else {
return Ok(Encoding::Utf8);
};

match enc_str.as_str() {
"utf8" => Ok(Encoding::Utf8),
"utf16" | "utf16le" => Ok(Encoding::Utf16 {
little_endian: true,
}),
"utf16be" => Ok(Encoding::Utf16 {
little_endian: false,
}),
"utf32" | "utf32le" => Ok(Encoding::Utf32 {
little_endian: true,
}),
"utf32be" => Ok(Encoding::Utf32 {
little_endian: false,
}),
_ => {
let msg = "Invalid `encoding` parameter. Expected: utf8, utf16, utf16le, utf16be, \
utf32, utf32le, utf32be.";
Err(LegacyResponse::bad_request(msg))
}
}
}

/// switches the USB configuration.
/// API values are mapped to the `UsbConfig` as followed:
///
Expand Down
33 changes: 2 additions & 31 deletions src/app/bmc_application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@
use crate::api::legacy::SetNodeInfo;
use crate::hal::helpers::bit_iterator;
use crate::hal::PowerController;
use crate::hal::SerialConnections;
use crate::hal::{NodeId, PinController, UsbMode, UsbRoute};
use crate::persistency::app_persistency::ApplicationPersistency;
use crate::persistency::app_persistency::PersistencyBuilder;
use crate::usb_boot::NodeDrivers;
use crate::utils::{get_timestamp_unix, string_from_utf16, string_from_utf32};
use crate::utils::get_timestamp_unix;
use anyhow::{ensure, Context};
use log::{debug, trace};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -49,13 +48,6 @@ pub enum UsbConfig {
Flashing(NodeId, UsbRoute),
}

/// Encodings used when reading from a serial port
pub enum Encoding {
Utf8,
Utf16 { little_endian: bool },
Utf32 { little_endian: bool },
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct NodeInfos {
pub data: Vec<NodeInfo>,
Expand Down Expand Up @@ -90,7 +82,6 @@ pub struct BmcApplication {
pub(super) pin_controller: PinController,
pub(super) power_controller: PowerController,
pub(super) app_db: ApplicationPersistency,
serial: SerialConnections,
node_drivers: NodeDrivers,
}

Expand All @@ -105,14 +96,13 @@ impl BmcApplication {
.write_timeout(database_write_timeout)
.build()
.await?;
let serial = SerialConnections::new()?;

let node_drivers = NodeDrivers::new();

let instance = Self {
pin_controller,
power_controller,
app_db,
serial,
node_drivers,
};

Expand Down Expand Up @@ -304,25 +294,6 @@ impl BmcApplication {
Ok(())
}

pub async fn start_serial_workers(&self) -> anyhow::Result<()> {
Ok(self.serial.run().await?)
}

pub async fn serial_read(&self, node: NodeId, encoding: Encoding) -> anyhow::Result<String> {
let bytes = self.serial.read(node).await?;

let res = match encoding {
Encoding::Utf8 => String::from_utf8_lossy(&bytes).to_string(),
Encoding::Utf16 { little_endian } => string_from_utf16(&bytes, little_endian),
Encoding::Utf32 { little_endian } => string_from_utf32(&bytes, little_endian),
};
Ok(res)
}

pub async fn serial_write(&self, node: NodeId, data: &[u8]) -> anyhow::Result<()> {
Ok(self.serial.write(node, data).await?)
}

pub async fn set_node_info(&self, info: SetNodeInfo) -> anyhow::Result<()> {
ensure!(info.node >= 1 && info.node <= 4);

Expand Down
5 changes: 1 addition & 4 deletions src/hal.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::fmt::Display;

// Copyright 2023 Turing Machines
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -14,6 +12,7 @@ use std::fmt::Display;
// See the License for the specific language governing permissions and
// limitations under the License.
pub mod helpers;
use std::fmt::Display;

macro_rules! conditional_import {
($attribute_condition:meta, $($statement:item)+) => {
Expand All @@ -29,10 +28,8 @@ conditional_import! {
mod gpio_definitions;
mod pin_controller;
mod power_controller;
mod serial;
pub use pin_controller::*;
pub use power_controller::*;
pub use serial::*;
}

conditional_import! {
Expand Down
Loading

0 comments on commit 2445d8a

Please sign in to comment.