mediatek-optical 0.7.0

MediaTek MT1959/MT1939 optical drive (BD/DVD) protocol: command encoding, identity and flash sequences over any SCSI transport, chip detection, hardware families, AES-CMAC integrity, family-gated updates and OEM image reconstruction. no_std by default.
Documentation
use super::*;
use crate::Chip;

/// A minimal buffer with a valid banner + descriptor at the right offsets,
/// everything else zeroed.
fn synthetic(banner: &str, family_tag: &str, model: &str, rev: &str) -> Vec<u8> {
    let mut img = vec![0u8; DESCRIPTOR_OFFSET + DESCRIPTOR_LEN + 0x100];
    img[BANNER_OFFSET..BANNER_OFFSET + banner.len()].copy_from_slice(banner.as_bytes());

    let desc = DESCRIPTOR_OFFSET;
    img[desc..desc + 0x40].fill(b' ');
    img[desc..desc + 8].copy_from_slice(b"HL-DT-ST");
    let m = model.as_bytes();
    img[desc + 0x08..desc + 0x08 + m.len()].copy_from_slice(m);
    let r = rev.as_bytes();
    img[desc + 0x18..desc + 0x18 + r.len()].copy_from_slice(r);
    let t = family_tag.as_bytes();
    img[desc + 0x34..desc + 0x34 + t.len()].copy_from_slice(t);
    img
}

#[test]
fn detects_mt1959() {
    let img = synthetic("MT1959 Boot BU5", "MTEKMT1959", "BD-RE BU40N", "1.00");
    let chip = detect_chip(&img).unwrap();
    assert_eq!(chip.family, Chip::Mt1959);
    assert_eq!(chip.vendor, "HL-DT-ST");
    assert_eq!(chip.model, "BD-RE BU40N");
    assert_eq!(chip.rev, "1.00");
    assert_eq!(chip.family.label(), "MT1959");
    assert_eq!(chip.identity_tag.as_deref(), Some("MTEKMT1959"));
}

#[test]
fn detects_mt1939() {
    let img = synthetic("MT1939 Boot Code", "MTEKMT1939", "SOME MODEL", "2.01");
    let chip = detect_chip(&img).unwrap();
    assert_eq!(chip.family, Chip::Mt1939);
}

/// The boot loader banner is authoritative. A JB8 build labelled `MTEKMT1939`
/// in its descriptor but carrying an `MT1959 Boot` banner is MT1959 — the stale
/// vendor tag never changes the decision; it is surfaced only for display.
#[test]
fn family_is_the_banner_not_the_identity_tag() {
    let img = synthetic("MT1959 Boot JB8", "MTEKMT1939", "BW-16D1HT", "3.10");
    let chip = detect_chip(&img).unwrap();
    assert_eq!(
        chip.family,
        Chip::Mt1959,
        "banner MT1959 must win over tag MT1939"
    );
    // The stale tag is still reported, as a curiosity.
    assert_eq!(chip.identity_tag.as_deref(), Some("MTEKMT1939"));
}

/// The identity tag drives no decision in either direction: a tag-1959 /
/// banner-1939 image is MT1939.
#[test]
fn identity_tag_never_flips_the_decision() {
    let img = synthetic("MT1939 Boot Code", "MTEKMT1959", "BH16NS40", "1.01");
    let chip = detect_chip(&img).unwrap();
    assert_eq!(chip.family, Chip::Mt1939);
    assert_eq!(chip.identity_tag.as_deref(), Some("MTEKMT1959"));
}

/// An image with no identity string at all still resolves from the banner.
#[test]
fn banner_alone_is_enough() {
    let mut img = vec![0u8; BANNER_OFFSET + 64];
    img[BANNER_OFFSET..BANNER_OFFSET + 16].copy_from_slice(b"MT1939 Boot Code");
    let chip = detect_chip(&img).unwrap();
    assert_eq!(chip.family, Chip::Mt1939);
    assert_eq!(chip.identity_tag, None);
    assert!(!chip.descriptor_present);
}

/// The descriptor marker byte at `+0x50` is a within-family variant flag,
/// never a family gate: detection succeeds regardless of its value.
#[test]
fn marker_0x50_is_not_a_family_gate() {
    let mut img = synthetic("MT1959 Boot BU5", "MTEKMT1959", "BD-RE BU40N", "1.00");
    img[DESCRIPTOR_OFFSET + 0x50] = 0x58; // not 0x78 — must not matter
    let chip = detect_chip(&img).unwrap();
    assert_eq!(chip.family, Chip::Mt1959);
    assert_eq!(chip.marker_0x50, Some(0x58));
    assert!(chip.descriptor_present);
}

/// No recognizable boot banner → clean refusal, regardless of any identity tag.
#[test]
fn no_banner_is_undetectable() {
    let img = synthetic("XX9999 Boot", "MTEKXX9999", "X", "1.00");
    let err = detect_chip(&img).unwrap_err().to_string();
    assert!(err.contains("undetectable"), "got: {err}");
}

/// A banner naming an MT19xx variant this crate does not handle is undetectable
/// — the stale tag cannot rescue it.
#[test]
fn unsupported_banner_is_undetectable() {
    let img = synthetic("MT1900 Boot", "MTEKMT1959", "X", "1.00");
    assert_eq!(detect_chip(&img), Err(ChipError::Undetectable));
}

#[test]
fn too_small_image_is_refused() {
    let img = vec![0u8; 0x100];
    assert!(detect_chip(&img).is_err());
}

/// The real BU40N 1.00 stock image, if present, must resolve to MT1959.
#[test]
fn real_stock_1_00_is_mt1959() {
    let Ok(path) = std::env::var("FREEMKV_KAT_BASE") else {
        eprintln!("skipping: FREEMKV_KAT_BASE unset (OEM BU40N 1.00 image)");
        return;
    };
    let Ok(img) = std::fs::read(&path) else {
        eprintln!("skipping: stock 1.00 image not present at {path}");
        return;
    };
    let chip = detect_chip(&img).unwrap();
    assert_eq!(chip.family, Chip::Mt1959);
    assert_eq!(chip.rev, "1.00");
    assert!(chip.model.contains("BU40N"), "got model: {:?}", chip.model);
}

/// The real MK-signed BU40N 1.03 image, if present, must also resolve to MT1959.
#[test]
fn real_mk_1_03_is_mt1959() {
    let Ok(path) = std::env::var("FREEMKV_KAT_MK103") else {
        eprintln!("skipping: FREEMKV_KAT_MK103 unset (MK-signed BU40N 1.03 image)");
        return;
    };
    let Ok(img) = std::fs::read(&path) else {
        eprintln!("skipping: MK 1.03 image not present at {path}");
        return;
    };
    let chip = detect_chip(&img).unwrap();
    assert_eq!(chip.family, Chip::Mt1959);
    assert_eq!(chip.rev, "1.03");
}