mt1959: separate A/B firmware upload paths
A (): single WRITE_BUFFER → verify 0x45 → unlock×2 B (): WRITE handshake → READ 0x3000 → WRITE 16B → verify → unlock×5 9/10 handlers are identical A/B. Only load_firmware has different logic. Both paths end with do_unlock() — firmware upload is a prerequisite for unlock, not a substitute. init() tries unlock first, falls back to load_firmware only on failure (cold boot).
This commit is contained in:
+103
-23
@@ -158,10 +158,18 @@ impl Platform for Mt1959 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// 1. WRITE_BUFFER mode=6 with ld_microcode (size = payload.len())
|
/// Two variants with different upload sequences:
|
||||||
/// 2. Check all bytes transferred
|
///
|
||||||
/// 3. READ_BUFFER buf=0x45 verify (4 bytes, expect response == 2)
|
/// 1. WRITE_BUFFER mode=6 with ld_microcode
|
||||||
/// 4. do_unlock() × 2
|
/// 2. READ_BUFFER buf=0x45 verify (expect response == 2)
|
||||||
|
/// 3. do_unlock() × 2
|
||||||
|
///
|
||||||
|
/// 1. WRITE_BUFFER with mode=2 buf=0x77 initial handshake (0x9C0 bytes)
|
||||||
|
/// 2. Check response == 2
|
||||||
|
/// 3. READ_BUFFER at offset 0x3000 (16 bytes, firmware metadata check)
|
||||||
|
/// 4. WRITE_BUFFER mode=6 with ld_microcode (16 bytes from payload+16)
|
||||||
|
/// 5. READ verify
|
||||||
|
/// 6. do_unlock() × 5 retries
|
||||||
fn load_firmware(&mut self, scsi: &mut dyn ScsiTransport) -> Result<()> {
|
fn load_firmware(&mut self, scsi: &mut dyn ScsiTransport) -> Result<()> {
|
||||||
let microcode = &self.profile.ld_microcode;
|
let microcode = &self.profile.ld_microcode;
|
||||||
if microcode.is_empty() {
|
if microcode.is_empty() {
|
||||||
@@ -170,25 +178,13 @@ impl Platform for Mt1959 {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// scsi_send(TO_DEVICE, ld_microcode, len)
|
if self.mode == 0x01 {
|
||||||
let len = microcode.len();
|
// ── MT1959-A path ──────────────────────────────────────────
|
||||||
let cdb = [
|
self.load_firmware_a(scsi)?;
|
||||||
0x3B, 0x06, 0x00,
|
} else {
|
||||||
0x00, 0x00, 0x00,
|
// ── MT1959-B path ──────────────────────────────────────────
|
||||||
(len >> 16) as u8, (len >> 8) as u8, len as u8,
|
self.load_firmware_b(scsi)?;
|
||||||
0x00,
|
}
|
||||||
];
|
|
||||||
let mut data = microcode.clone();
|
|
||||||
scsi.execute(&cdb, DataDirection::ToDevice, &mut data, 30_000)?;
|
|
||||||
|
|
||||||
let verify_cdb = [0x3C, 0x01, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00];
|
|
||||||
let mut verify_resp = [0u8; 4];
|
|
||||||
let _ = scsi.execute(
|
|
||||||
&verify_cdb, DataDirection::FromDevice, &mut verify_resp, 5_000,
|
|
||||||
);
|
|
||||||
|
|
||||||
self.do_unlock(scsi)?;
|
|
||||||
self.do_unlock(scsi)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -519,3 +515,87 @@ impl Platform for Mt1959 {
|
|||||||
self.unlocked
|
self.unlocked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Private firmware upload variants ───────────────────────────────────
|
||||||
|
|
||||||
|
impl Mt1959 {
|
||||||
|
///
|
||||||
|
/// Simple: WRITE all microcode → verify buf=0x45 → unlock × 2.
|
||||||
|
fn load_firmware_a(&mut self, scsi: &mut dyn ScsiTransport) -> Result<()> {
|
||||||
|
let microcode = &self.profile.ld_microcode;
|
||||||
|
let len = microcode.len();
|
||||||
|
|
||||||
|
// WRITE_BUFFER mode=6: send entire microcode payload
|
||||||
|
let cdb = [
|
||||||
|
0x3B, 0x06, 0x00,
|
||||||
|
0x00, 0x00, 0x00,
|
||||||
|
(len >> 16) as u8, (len >> 8) as u8, len as u8,
|
||||||
|
0x00,
|
||||||
|
];
|
||||||
|
let mut data = microcode.clone();
|
||||||
|
scsi.execute(&cdb, DataDirection::ToDevice, &mut data, 30_000)?;
|
||||||
|
|
||||||
|
let verify_cdb = [0x3C, 0x01, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00];
|
||||||
|
let mut verify_resp = [0u8; 4];
|
||||||
|
let _ = scsi.execute(
|
||||||
|
&verify_cdb, DataDirection::FromDevice, &mut verify_resp, 5_000,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Unlock × 2
|
||||||
|
self.do_unlock(scsi)?;
|
||||||
|
self.do_unlock(scsi)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Multi-step handshake:
|
||||||
|
/// 1. WRITE initial block via mode/buf (0x9C0 bytes from microcode)
|
||||||
|
/// 2. READ firmware metadata at offset 0x3000 (16 bytes)
|
||||||
|
/// 3. WRITE 16 bytes from microcode+16 via mode=6
|
||||||
|
/// 4. READ verify
|
||||||
|
/// 5. do_unlock() × 5 retries
|
||||||
|
fn load_firmware_b(&mut self, scsi: &mut dyn ScsiTransport) -> Result<()> {
|
||||||
|
let microcode = &self.profile.ld_microcode;
|
||||||
|
|
||||||
|
// Step 1: Initial handshake write via mode/buf_id
|
||||||
|
let handshake_len = 0x9C0usize.min(microcode.len());
|
||||||
|
let cdb = [
|
||||||
|
0x3B, self.mode, self.buffer_id,
|
||||||
|
0x00, 0x00, 0x00,
|
||||||
|
(handshake_len >> 16) as u8, (handshake_len >> 8) as u8, handshake_len as u8,
|
||||||
|
0x00,
|
||||||
|
];
|
||||||
|
let mut data = microcode[..handshake_len].to_vec();
|
||||||
|
scsi.execute(&cdb, DataDirection::ToDevice, &mut data, 30_000)?;
|
||||||
|
|
||||||
|
// Step 2: READ firmware metadata at offset 0x3000 (16 bytes)
|
||||||
|
let meta_cdb = [0x3C, 0x06, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x10, 0x00];
|
||||||
|
let mut meta_resp = [0u8; 16];
|
||||||
|
let _ = scsi.execute(&meta_cdb, DataDirection::FromDevice, &mut meta_resp, 5_000);
|
||||||
|
|
||||||
|
// Step 3: WRITE 16 bytes from microcode offset 16 via mode=6
|
||||||
|
if microcode.len() > 32 {
|
||||||
|
let write2_cdb = [
|
||||||
|
0x3B, 0x06, 0x00,
|
||||||
|
0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x10, 0x00,
|
||||||
|
];
|
||||||
|
let mut data2 = microcode[16..32].to_vec();
|
||||||
|
let _ = scsi.execute(&write2_cdb, DataDirection::ToDevice, &mut data2, 5_000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4: READ verify
|
||||||
|
let verify_cdb = [0x3C, self.mode, self.buffer_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00];
|
||||||
|
let mut verify_resp = [0u8; 4];
|
||||||
|
let _ = scsi.execute(&verify_cdb, DataDirection::FromDevice, &mut verify_resp, 5_000);
|
||||||
|
|
||||||
|
// Step 5: do_unlock() × 5 retries
|
||||||
|
for _attempt in 0..5 {
|
||||||
|
if self.do_unlock(scsi).is_ok() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.do_unlock(scsi)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user