blob: e9ba9779618a3dba88a1039d72d9417924d3f5d2 [file] [log] [blame] [edit]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::path::PathBuf;
use log::info;
use crate::context::Context;
use crate::error::HwsecError;
use crate::gsc::extract_board_id_from_gsctool_response;
use crate::gsc::run_gsctool_cmd;
use crate::gsc::GSCTOOL_CMD_NAME;
use crate::gsc::GSC_IMAGE_BASE_NAME;
use crate::tpm2::ERASED_BOARD_ID;
pub fn gsc_get_name(
ctx: &mut impl Context,
gsctool_command_options: &[&str],
) -> Result<PathBuf, HwsecError> {
const PRE_PVT_FLAG: u32 = 0x10;
info!("updater is {}", GSCTOOL_CMD_NAME);
let exe_result = run_gsctool_cmd(ctx, [gsctool_command_options, &["--board_id"]].concat())?;
let exit_status = exe_result.status.code().unwrap();
let output = format!(
"{}{}",
std::str::from_utf8(&exe_result.stdout)
.map_err(|_| HwsecError::Tpm2ResponseBadFormatError)?,
std::str::from_utf8(&exe_result.stderr)
.map_err(|_| HwsecError::Tpm2ResponseBadFormatError)?
);
let mut ext = "prod";
let board_id = extract_board_id_from_gsctool_response(&output)?;
let board_flags = format!("0x{:02x}", board_id.flag);
if exit_status != 0 {
info!("exit status: {}", exit_status);
info!("output: {}", output);
} else if board_id == ERASED_BOARD_ID {
info!("board ID is erased using {} image", ext);
} else if board_id.flag & PRE_PVT_FLAG != 0 {
ext = "prepvt";
}
info!(
r"board_id: '{:02x}:{:02x}:{:02x}' board_flags: '{}', extension: '{}'",
board_id.part_1, board_id.part_2, board_id.flag, board_flags, ext
);
Ok(PathBuf::from(format!("{}.{}", GSC_IMAGE_BASE_NAME, ext)))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::context::mock::MockContext;
use crate::gsc::GSC_IMAGE_BASE_NAME;
#[test]
fn test_gsc_get_name() {
let mut mock_ctx = MockContext::new();
mock_ctx.cmd_runner().add_gsctool_interaction(
vec!["--any", "--board_id"],
0,
"finding_device 18d1:5014\n\
Found device.\n\
found interface 3 endpoint 4, chunk_len 64\n\
READY\n\
-------\n\
Board ID space: 43425559:bcbdaaa6:00007f80\n",
"",
);
let name = gsc_get_name(&mut mock_ctx, &["--any"]);
assert_eq!(
name,
Ok(PathBuf::from(String::from(GSC_IMAGE_BASE_NAME) + ".prod"))
);
}
#[test]
fn test_gsc_get_name_board_id_not_found() {
let mut mock_ctx = MockContext::new();
mock_ctx.cmd_runner().add_gsctool_interaction(
vec!["--any", "--board_id"],
0,
"finding_device 18d1:5014\n\
Found device.\n\
found interface 3 endpoint 4, chunk_len 64\n\
READY\n\
-------\n\
Board ID space: 43425559:bxbdaaa6:00007f80\n",
"",
);
let name = gsc_get_name(&mut mock_ctx, &["--any"]);
assert_eq!(name, Err(HwsecError::GsctoolResponseBadFormatError));
}
#[test]
fn test_gsc_get_name_different_ext() {
let mut mock_ctx = MockContext::new();
mock_ctx.cmd_runner().add_gsctool_interaction(
vec!["--any", "--board_id"],
0,
"finding_device 18d1:5014\n\
Found device.\n\
found interface 3 endpoint 4, chunk_len 64\n\
READY\n\
-------\n\
Board ID space: 43425559:bcbdaaa6:00007f10\n",
"",
);
let name = gsc_get_name(&mut mock_ctx, &["--any"]);
assert_eq!(
name,
Ok(PathBuf::from(String::from(GSC_IMAGE_BASE_NAME) + ".prepvt"))
);
}
}