mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Replace the pv crate with the pv_core crate. Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
106 lines
3.5 KiB
Rust
106 lines
3.5 KiB
Rust
// SPDX-License-Identifier: MIT
|
|
//
|
|
// Copyright IBM Corp. 2023
|
|
//
|
|
//! UV related functions for pvapconfig
|
|
//
|
|
|
|
use pv_core::uv::{ListCmd, SecretList, UvDevice, UvcSuccess};
|
|
use regex::Regex;
|
|
use std::path::Path;
|
|
|
|
/// The byte size of association secret of type 2 in struct SecretEntry
|
|
pub const AP_ASSOC_SECRET_ID_SIZE: usize = 32;
|
|
|
|
const PATH_SYS_FW_UV_FACILITIES: &str = "/sys/firmware/uv/query/facilities";
|
|
|
|
const RE_UV_FACILITIES: &str = r"^(0x)?([[:xdigit:]]+)";
|
|
const RE_UV_FAC_BIT_LIST_SECRETS: u32 = 30;
|
|
|
|
/// Check UV facilities to offer the 'list secrets' call.
|
|
/// Returns a Result with Ok(()) if the 'list secrets' feature
|
|
/// is available, otherwise an Err(reasonstring) is returned where
|
|
/// the string denotes a hint which can be displayed.
|
|
/// # Panics
|
|
/// Panics if the compilation of a static regular expression fails.
|
|
/// Panics if RE_UV_FACILITIES does not match.
|
|
pub fn has_list_secrets_facility() -> Result<(), String> {
|
|
if !Path::new(PATH_SYS_FW_UV_FACILITIES).is_file() {
|
|
return Err(format!(
|
|
"UV facilities sysfs attribute not found (file {} does not exist).",
|
|
PATH_SYS_FW_UV_FACILITIES
|
|
));
|
|
}
|
|
let facstr = match crate::helper::sysfs_read_string(PATH_SYS_FW_UV_FACILITIES) {
|
|
Ok(s) => s,
|
|
Err(err) => {
|
|
return Err(format!(
|
|
"Failure reading UV facilities from {PATH_SYS_FW_UV_FACILITIES} ({:?}).",
|
|
err
|
|
))
|
|
}
|
|
};
|
|
let re_uv_facilities = Regex::new(RE_UV_FACILITIES).unwrap();
|
|
if !re_uv_facilities.is_match(&facstr) {
|
|
Err(format!("Failure parsing UV facilities entry '{facstr}'."))
|
|
} else {
|
|
let caps = re_uv_facilities.captures(&facstr).unwrap();
|
|
let fachex = caps.get(2).unwrap().as_str();
|
|
let i: usize = RE_UV_FAC_BIT_LIST_SECRETS as usize / 4;
|
|
if i >= fachex.len() {
|
|
return Err(format!("Failure parsing UV facilities entry '{fachex}'."));
|
|
}
|
|
let nibble = u32::from_str_radix(&fachex[i..i + 1], 16).unwrap();
|
|
const THEBIT: u32 = 1 << (3 - (RE_UV_FAC_BIT_LIST_SECRETS % 4));
|
|
if nibble & THEBIT == 0 {
|
|
return Err("The 'list secret' feature is missing on this UV.".to_string());
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// Fetch the list of secrets from the UV.
|
|
/// Returns Err(errorstring) on error or
|
|
/// Ok(SecretList) on success.
|
|
/// The list may be empty if the UV doesn't have any secrets stored.
|
|
pub fn gather_secrets() -> Result<SecretList, String> {
|
|
let uv = match UvDevice::open() {
|
|
Err(e) => return Err(format!("Failed to open UV device: {:?}.", e)),
|
|
Ok(u) => u,
|
|
};
|
|
let mut cmd = ListCmd::default();
|
|
match uv.send_cmd(&mut cmd).map_err(|e| format!("{e:?}"))? {
|
|
UvcSuccess::RC_SUCCESS => (),
|
|
UvcSuccess::RC_MORE_DATA => println!("Warning: There is more data available than expected"),
|
|
};
|
|
cmd.try_into().map_err(|e| format!("{e:?}"))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
// As the name says: check for list secrets feature bit in UV facilities.
|
|
#[test]
|
|
fn test_has_list_secrets_facility() {
|
|
let r = has_list_secrets_facility();
|
|
if pv_core::misc::pv_guest_bit_set() {
|
|
assert!(r.is_ok());
|
|
} else {
|
|
assert!(r.is_err());
|
|
}
|
|
}
|
|
|
|
// Simple invocation of the list_secrets function. Should not fail
|
|
#[test]
|
|
fn test_list_secrets() {
|
|
let r = gather_secrets();
|
|
if pv_core::misc::pv_guest_bit_set() {
|
|
assert!(r.is_ok());
|
|
} else {
|
|
assert!(r.is_err());
|
|
}
|
|
}
|
|
}
|