--- emulation hook for DF-4184/DF-4185 verification (guest-local only) --- Add to sys/dev/disk/nata/ata-queue.c in ata_atapicmd() after "ata_queue_request(request); error = request->result;": { extern int df_audit_emu_fixup(u_int8_t *, caddr_t, int, int); error = df_audit_emu_fixup(request->u.atapi.ccb, data, count, error); } And append to sys/dev/disk/nata/atapi-cd.c: /* * DF-AUDIT verification emulation (guest-local, NEVER for upstream): * emulates a crafted ATAPI drive: * df_audit.capfail=1 : MODE_SENSE page 0x2a (capabilities) always fails * -> acd_get_cap leaves cap zeroed at attach * (cur_write_speed == 0) * df_audit.mode=1 : MODE_SENSE page 0x05 (write parameters) returns * page_length = 0xff (DF-4184 driver) * MODE_SELECT / CLOSE_TRACK succeed and the * data-out contents beyond byte 65 are logged * (what a crafted receiver would get) */ #include static int df_emu_mode = 0; static int df_emu_capfail = 0; TUNABLE_INT("df_audit.mode", &df_emu_mode); TUNABLE_INT("df_audit.capfail", &df_emu_capfail); int df_audit_emu_fixup(u_int8_t *ccb, caddr_t data, int count, int error) { if (ccb[0] == 0x5d && (ccb[2] & 0x3f) == 0x2a && df_emu_capfail) return (EIO); if (ccb[0] == 0x5d && (ccb[2] & 0x3f) == 0x05 && df_emu_mode) { if (data && count >= 10) { bzero(data, count); data[8] = 0x05; data[9] = 0xff; } kprintf("DFAUDIT: forged MODE_SENSE(0x05) page_length=0xff\n"); return (0); } if (ccb[0] == 0x55 && df_emu_mode) { if (count > 65) { int i; kprintf("DFAUDIT: MODE_SELECT count=%d from 65-byte " "stack param, over-read bytes:\n", count); for (i = 65; i < count; i++) { if ((i - 65) % 32 == 0) kprintf("DFAUDIT: +%04x:", i - 65); kprintf("%02x", (u_char)data[i]); if ((i - 65) % 32 == 31) kprintf("\n"); } if ((count - 65) % 32) kprintf("\n"); } return (0); } if (ccb[0] == 0x53 && df_emu_mode) { kprintf("DFAUDIT: forged CLOSE_TRACK success\n"); return (0); } return (error); } --- CORRECTION (post-run): ATAPI opcodes --- MODE SENSE(10) is 0x5a (ATAPI_MODE_SENSE_BIG, sys/sys/nata.h:331) and CLOSE_TRACK/SESSION is 0x5b (sys/sys/nata.h:332) - the original draft of these notes wrongly used 0x5d/0x53. Also note the hook must inspect the CALLER's ccb argument, not request->u.atapi.ccb: the ATA layer overwrites the latter with a REQUEST SENSE (0x03) ccb when a command fails. The final working hook is reflected in run.log output.