use crate::command::ata::{raw::RawSatCommand, AtaProtocol, NoData, SatResult, ScsiSat, ToDevice};
const OPCODE_SECURITY_SET_PASSWORD: u8 = 0xF1;
const OPCODE_SECURITY_ERASE_PREPARE: u8 = 0xF3;
const OPCODE_SECURITY_ERASE_UNIT: u8 = 0xF4;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SecurityPassword {
User,
Master,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SecurityMode {
High,
Maximum,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum EraseMode {
Normal,
Enhanced,
}
#[derive(Clone, Debug)]
pub struct SecuritySetPasswordSatCommand<'a> {
raw: RawSatCommand<'a, ToDevice>,
data: Vec<u8>,
}
impl<'a> SecuritySetPasswordSatCommand<'a> {
fn new(sat: &'a ScsiSat<'a>) -> Self {
let mut raw = sat.raw_write();
raw.command(AtaProtocol::PioDataOut, OPCODE_SECURITY_SET_PASSWORD);
Self {
raw,
data: vec![0u8; 512],
}
}
pub fn mode(&mut self, level: SecurityMode) -> &mut Self {
self.data[1] = match level {
SecurityMode::High => 0x00,
SecurityMode::Maximum => 0x01,
};
self
}
pub fn password(&mut self, which: SecurityPassword, password: &[u8]) -> &mut Self {
assert!(password.len() <= 32);
self.data[0] = match which {
SecurityPassword::User => 0x00,
SecurityPassword::Master => 0x01,
};
self.data[2..2 + password.len()].copy_from_slice(password);
self
}
pub fn device(&mut self, device: u8) -> &mut Self {
self.raw.device(device);
self
}
pub fn issue_12(&mut self) -> SatResult<()> {
self.raw.parameter(&self.data).issue_12()
}
pub fn issue_16(&mut self) -> SatResult<()> {
self.raw.parameter(&self.data).issue_16()
}
}
#[derive(Clone, Debug)]
pub struct SecurityErasePrepareSatCommand<'a> {
raw: RawSatCommand<'a, NoData>,
}
impl<'a> SecurityErasePrepareSatCommand<'a> {
fn new(sat: &'a ScsiSat<'a>) -> Self {
let mut raw = sat.raw_nodata();
raw.command(AtaProtocol::NonData, OPCODE_SECURITY_ERASE_PREPARE)
.ck_cond(true);
Self { raw }
}
pub fn issue_12(&mut self) -> SatResult<()> {
self.raw.issue_12()
}
pub fn issue_16(&mut self) -> SatResult<()> {
self.raw.issue_16()
}
}
#[derive(Clone, Debug)]
pub struct SecurityEraseUnitSatCommand<'a> {
raw: RawSatCommand<'a, ToDevice>,
data: Vec<u8>,
}
impl<'a> SecurityEraseUnitSatCommand<'a> {
fn new(sat: &'a ScsiSat<'a>) -> Self {
let mut raw = sat.raw_write();
raw.command(AtaProtocol::PioDataOut, OPCODE_SECURITY_ERASE_UNIT);
Self {
raw,
data: vec![0u8; 512],
}
}
pub fn mode(&mut self, mode: EraseMode) -> &mut Self {
let bit = match mode {
EraseMode::Normal => 0b00,
EraseMode::Enhanced => 0b10,
};
self.data[0] = (self.data[0] & !0b10) | bit;
self
}
pub fn password(&mut self, which: SecurityPassword, password: &[u8]) -> &mut Self {
let bit = match which {
SecurityPassword::User => 0b0,
SecurityPassword::Master => 0b1,
};
self.data[0] = (self.data[0] & !0b1) | bit;
self.data[2..2 + password.len()].copy_from_slice(password);
self
}
pub fn issue_12(&mut self) -> SatResult<()> {
self.raw.parameter(&self.data).issue_12()
}
pub fn issue_16(&mut self) -> SatResult<()> {
self.raw.parameter(&self.data).issue_16()
}
}
impl ScsiSat<'_> {
pub fn security_set_password(&self) -> SecuritySetPasswordSatCommand<'_> {
SecuritySetPasswordSatCommand::new(self)
}
pub fn security_erase_prepare(&self) -> SecurityErasePrepareSatCommand<'_> {
SecurityErasePrepareSatCommand::new(self)
}
pub fn security_erase_unit(&self) -> SecurityEraseUnitSatCommand<'_> {
SecurityEraseUnitSatCommand::new(self)
}
}