Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

opentitantool: option for parsing BFV codes #25816

Merged
merged 1 commit into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions sw/host/opentitantool/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ package(default_visibility = ["//visibility:public"])
rust_binary(
name = "opentitantool",
srcs = [
"src/command/bfv.rs",
"src/command/bootstrap.rs",
"src/command/certificate.rs",
"src/command/clear_bitstream.rs",
Expand Down Expand Up @@ -52,6 +53,7 @@ rust_binary(
"//sw/host/opentitanlib",
"//sw/host/ot_certs",
"//sw/host/sphincsplus",
"//util:bfv_decoder",
"@crate_index//:anyhow",
"@crate_index//:clap",
"@crate_index//:directories",
Expand Down
55 changes: 55 additions & 0 deletions sw/host/opentitantool/src/command/bfv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use anyhow::{Context, Result};
use clap::Args;
use serde_annotate::Annotate;
use std::any::Any;

use opentitanlib::app::command::CommandDispatch;
use opentitanlib::app::TransportWrapper;

#[derive(Debug, Args)]
/// Decode a raw status. Optionally accepts an ELF file to recover the filename.
pub struct BfvCommand {
/// Hex BFV value as reported by device on failures.
bfv: Vec<String>,
}

extern "C" {
fn bfv_decoder(bfv: u32, buf: *mut u8, buf_size: usize) -> usize;
}

impl CommandDispatch for BfvCommand {
fn run(
&self,
_context: &dyn Any,
_transport: &TransportWrapper,
) -> Result<Option<Box<dyn Annotate>>> {
for value in &self.bfv {
// Decode status.
let string_bfv = if value.starts_with("0x") {
&value.as_str()[2..]
} else {
value.as_str()
};

let bfv = u32::from_str_radix(string_bfv, 16)
.context(format!("\"{}\" is not a valid hex value", string_bfv))?;
let mut text = [0u8; 80];
// SAFETY: the decodr function is guaranteed to size of the string
// written into text.
let size = unsafe { bfv_decoder(bfv, text.as_mut_ptr(), text.len()) };

println!(
"{:08x}: {}",
bfv,
std::str::from_utf8(&text[..size]).unwrap()
);
}
// Separate command output from the next shell prompt.
println!();
Ok(None)
}
}
1 change: 1 addition & 0 deletions sw/host/opentitantool/src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

pub mod bfv;
pub mod bootstrap;
pub mod certificate;
pub mod clear_bitstream;
Expand Down
1 change: 1 addition & 0 deletions sw/host/opentitantool/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use opentitanlib::backend;
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Parser, CommandDispatch)]
enum RootCommandHierarchy {
Bfv(command::bfv::BfvCommand),
// Not flattened because `Bootstrap` is a leaf command.
Bootstrap(command::bootstrap::BootstrapCommand),
// Not flattened because `Console` is a leaf command.
Expand Down
8 changes: 8 additions & 0 deletions util/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,11 @@ py_binary(
srcs = ["fusesoc_build.py"],
deps = all_requirements,
)

cc_library(
name = "bfv_decoder",
srcs = ["bfv_decoder.c"],
deps = [
"//sw/device/silicon_creator/lib:error",
],
)
59 changes: 59 additions & 0 deletions util/bfv_decoder.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sw/device/silicon_creator/lib/error.h"

typedef struct {
const char *text;
int value;
} error_descriptor_t;

#define ERROR_TABLE_ENTRY(name, value) \
{ #name, value }

// Add an empty element in the end to make it easier to stop iterating over the
// table.
const static error_descriptor_t error_table[] = {
DEFINE_ERRORS(ERROR_TABLE_ENTRY){}};

size_t bfv_decoder(uint32_t bfv, uint8_t *buf, size_t buf_size) {
char *str = (char *)buf;

const error_descriptor_t *edesc = error_table;

while (edesc->value) {
if (edesc->value == bfv) {
snprintf(str, buf_size, "%s", edesc->text);
break;
}
edesc++;
}
if (!edesc->value) {
// This was not an encoded BFV, must have been an exception.
unsigned char mod_high = (bfv >> 16) & 0xff;
unsigned char mod_low = (bfv >> 8) & 0xff;

if (((mod_high == 'R') && (mod_low == 'I')) ||
((mod_high == 'I') && (mod_low == 'R'))) {
// This is an interrupt/exception error, retrieve the encoded mcause.
uint32_t mcause = (bfv & (1 << 31)) | ((bfv >> 24) & 0x7f);
const char *prefix = "";

if (mod_high == 'R') {
prefix = "ROM_EXT ";
}

snprintf(str, buf_size,
"%sinterrupt/exception, mcause 0x%08x, status 0x%02x", prefix,
mcause, bfv & 0xff);
} else {
snprintf(str, buf_size, "unknown error code");
}
}
return strlen(str);
}
Loading