init: F3 unlock project — ESP32-C3 bridge + procedure for CLAR200 Exos X18
This commit is contained in:
@@ -0,0 +1,64 @@
|
|||||||
|
# Handoff — 2026-06-14 — clar200-unlock bootstrap
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
Started from a `tank` (pve173, 549 TB ZFS) degradation diagnosis. mirror-35 is a
|
||||||
|
3-way mirror running on effectively ONE healthy disk:
|
||||||
|
- `4450364206979169854` (ZL2PNZ99) — **UNAVAIL / dead**
|
||||||
|
- `wwn-0x5000c500c3663b1d-part1` (/dev/sde) — **healthy** (0 pending/realloc)
|
||||||
|
- `wwn-0x5000c500c37f4eff` (/dev/sdg) — **failing**: 30,536 pending sectors,
|
||||||
|
11,032 reallocated, 18 ZFS read errors
|
||||||
|
|
||||||
|
mirror-35 holds **3.68 TB** of real data (25.3% full) — it is a live stripe
|
||||||
|
member, not empty. Plus **ex-mirror-38** (`wwn-0x5000c500c382f4ac-part1`) is a
|
||||||
|
bare single-disk vdev. Both need **14.6 TB+** replacement disks, of which there
|
||||||
|
are **none free** on pve173 (all 14.6 T disks already in tank; spares are 10.9 T,
|
||||||
|
too small).
|
||||||
|
|
||||||
|
Seth re-added an EMC-locked 16 TB drive (SN **ZRS015V7**) hoping to use it. It's
|
||||||
|
the same CLAR200-locked Exos X18 that a prior session failed to unlock. This
|
||||||
|
project is the unlock attempt.
|
||||||
|
|
||||||
|
## What I confirmed this session (re: the drive)
|
||||||
|
|
||||||
|
- Drive is on **pve173**, dual-pathed: `/dev/sg121` (7:0:43:0) and `/dev/sg122`
|
||||||
|
(8:0:11:0), model `SS160520 CLAR200`, fake serial `Maxtor 5A320J0…RAMB1TV0`.
|
||||||
|
- New HBA (pve173 SAS2116, vs pve197 before) → **same lock** ⇒ not the controller.
|
||||||
|
- SCSI **target/bus reset** (`sg_reset -t`) → drive returns in same state.
|
||||||
|
- `sg_senddiag --test` → Illegal request. READ CAPACITY → Hardware Error.
|
||||||
|
- ⇒ Confirmed firmware-level lock below the SCSI layer. No host fix exists.
|
||||||
|
Prior `EMC_CLAR200_DRIVE_FIX_NOTES.md` conclusion stands; I closed the two
|
||||||
|
doors it left open (HBA + reset).
|
||||||
|
|
||||||
|
## What I built
|
||||||
|
|
||||||
|
Project `~/bin/clar200-unlock` + Gitea repo. ESP32-C3 (already on steel141
|
||||||
|
`/dev/ttyACM0`, MAC 58:8c:81:ac:f0:4c) as a 3.3 V USB-serial bridge to the F3
|
||||||
|
terminal. Firmware (`firmware/clar200_bridge.ino`, live `~N` baud menu), flash
|
||||||
|
script, full `PROCEDURE.md`, and `docs/f3-command-reference.md` (honest about
|
||||||
|
Exos-vs-7200.11 uncertainty).
|
||||||
|
|
||||||
|
## Next steps (ordered)
|
||||||
|
|
||||||
|
1. `cd ~/bin/clar200-unlock/firmware && ./flash.sh /dev/ttyACM0` — installs
|
||||||
|
arduino-cli + esp32 core (first run), builds, uploads. **Not done yet.**
|
||||||
|
2. Bench-test bridge: `screen /dev/ttyACM0 115200`, jumper GPIO4↔GPIO5, confirm echo.
|
||||||
|
3. Bench the drive (pull from pve173 JBOD, standalone power). **Needs an
|
||||||
|
SFF-8482→SATA-power adapter / SAS dock — confirm Seth has one.**
|
||||||
|
4. Multimeter the F3 pinout (PROCEDURE §3), wire, get boot banner + `F3 T>`.
|
||||||
|
5. Map format command via `?`, format to 512, verify with `sg_readcap`/`smartctl`.
|
||||||
|
6. If healthy → `zpool replace tank 4450364206979169854 <newdisk>` for mirror-35
|
||||||
|
(replace before detach), then re-mirror ex-mirror-38. Repeat for ZR511KWK.
|
||||||
|
|
||||||
|
## Open questions / decisions pending
|
||||||
|
|
||||||
|
- RMA to ServerPartDeals vs. attempt F3 first? Leaning F3 first (cable free).
|
||||||
|
- Does Seth have standalone SAS power + jumper wires + multimeter on the bench?
|
||||||
|
- tank mirror-35: the dying sdg is still attached as a (poor) 2nd copy — leave it
|
||||||
|
until a real replacement resilvers; **don't detach early.**
|
||||||
|
|
||||||
|
## Also worth doing
|
||||||
|
|
||||||
|
Minor CKSUM counts on mirror-10/18/19/20/30; no scrub since the tank migration.
|
||||||
|
Worth a `zpool scrub tank` AFTER mirror-35 is on healthy disks (not before — a
|
||||||
|
scrub hammers the dying sdg).
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
GITEA_API.md
|
||||||
|
firmware/build/
|
||||||
|
firmware/*.bin
|
||||||
|
firmware/*.elf
|
||||||
|
screenlog.0
|
||||||
|
docs/photos/
|
||||||
|
.DS_Store
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# clar200-unlock
|
||||||
|
|
||||||
|
> Unlock EMC CLAR200-locked Exos X18 SAS drives via the Seagate F3 terminal, using an ESP32-C3 bridge.
|
||||||
|
|
||||||
|
## Start Here
|
||||||
|
|
||||||
|
**Read the latest handoff first:** `.claude/handoffs/` (most recent file).
|
||||||
|
Then `PROCEDURE.md` (the runbook), `IDEA.md` (brief), `DECISIONS.md` (settled choices).
|
||||||
|
Background on why host-side tools fail: `~/bin/EMC_CLAR200_DRIVE_FIX_NOTES.md`.
|
||||||
|
|
||||||
|
## Project Identity
|
||||||
|
|
||||||
|
Two Seagate Exos X18 SAS drives (ST16000NM004J, EMC fw ES2264 — SN ZRS015V7,
|
||||||
|
ZR511KWK) are locked in the "SS160520 CLAR200" state: SCSI INQUIRY/VPD work, but
|
||||||
|
every other command (incl. READ CAPACITY) returns Hardware Error. No host tool
|
||||||
|
can format them. This project drives the drives' out-of-band **F3 service UART**
|
||||||
|
(via an ESP32-C3 as a 3.3 V USB-serial bridge) to reformat them to 512-byte
|
||||||
|
sectors and reclaim them as 14.6 TB+ spares for the `tank` pool.
|
||||||
|
|
||||||
|
## Current State
|
||||||
|
|
||||||
|
- **Phase:** building → first hardware attempt pending
|
||||||
|
- **Repo:** https://git.sethpc.xyz/Seth/clar200-unlock
|
||||||
|
- **Hardware:** ESP32-C3 on steel141 `/dev/ttyACM0` (MAC 58:8c:81:ac:f0:4c).
|
||||||
|
Drive ZRS015V7 in a pve173 JBOD (must be benched for F3 work).
|
||||||
|
- **Done:** firmware (`firmware/clar200_bridge.ino`) + flash script + full
|
||||||
|
procedure written.
|
||||||
|
- **Next:** `./firmware/flash.sh`, sanity-test bridge, bench drive, find F3
|
||||||
|
pinout, get `F3 T>`, format to 512.
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
- **Safety:** bench-only F3 work — NEVER in the pve173 JBOD next to live tank.
|
||||||
|
3.3 V only; share TX/RX/GND, never power. `screen -L` to log every session.
|
||||||
|
Escalation brake applies: silent terminal → re-check wiring/baud, never a more
|
||||||
|
aggressive format command.
|
||||||
|
- **F3 honesty:** Exos X18 dialect ≠ 7200.11. Map commands with `?` before
|
||||||
|
firing; record discovered tokens in `docs/f3-command-reference.md`.
|
||||||
|
- Conventional commits; commit + `gitea push` each meaningful change.
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# DECISIONS.md — clar200-unlock Decision Log
|
||||||
|
|
||||||
|
Project-specific decisions. For global/cross-cutting decisions, see `~/bin/DECISIONS.md`.
|
||||||
|
|
||||||
|
Format: `YYYY-MM-DD: <decision> — <why>`
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
- 2026-06-14: Use the drive's **F3 service UART**, not any SCSI path — every SCSI
|
||||||
|
command (incl. READ CAPACITY) returns Hardware Error on these EMC-locked drives;
|
||||||
|
F3 bypasses the SCSI layer. (See EMC_CLAR200_DRIVE_FIX_NOTES.md for the
|
||||||
|
exhaustive SCSI-side failure list.)
|
||||||
|
- 2026-06-14: **ESP32-C3 as the USB-serial bridge** rather than buying a USB-TTL
|
||||||
|
module — one is already attached to steel141 (`/dev/ttyACM0`) and its 3.3 V
|
||||||
|
logic is a native match for the F3 header (many FTDI cables are 5 V = unsafe).
|
||||||
|
- 2026-06-14: Bridge uses the C3's **native USB-CDC** as host side + **UART1
|
||||||
|
(GPIO4 TX / GPIO5 RX)** to the drive, with a live `~N` baud menu so baud can be
|
||||||
|
swept without reflashing.
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
- 2026-06-14: Build flag `CDCOnBoot=cdc` is **required** so `Serial` maps to
|
||||||
|
USB-CDC, not UART0; encoded in `firmware/flash.sh` FQBN.
|
||||||
|
- 2026-06-14: F3 format commands are **discovered via `?`**, not copied from
|
||||||
|
7200.11 forums — Exos X18 dialect differs and wrong `m0,...` params can worsen
|
||||||
|
a drive.
|
||||||
|
|
||||||
|
## Deferred / Rejected
|
||||||
|
<!-- Decisions NOT to do something are just as valuable -- prevents re-proposing rejected ideas -->
|
||||||
|
|
||||||
|
- 2026-06-14: **Rejected** further SCSI-level attempts (sg_format flag variants,
|
||||||
|
firmware download, sanitize) — prior session exhausted them; all return
|
||||||
|
Hardware Error because the EMC firmware refuses below the command layer.
|
||||||
|
- 2026-06-14: **Rejected** doing F3 work with the drive in the pve173 JBOD —
|
||||||
|
too risky next to live tank; bench-only.
|
||||||
|
- 2026-06-14: **Deferred** the BSY isolation/tape trick — the drive boots and
|
||||||
|
answers INQUIRY (not BSY-hung), so it's unlikely to be needed; contingency only.
|
||||||
|
- 2026-06-14: **Not yet decided** — whether to RMA to ServerPartDeals first vs.
|
||||||
|
attempt F3 first. Leaning: attempt F3 (cable is free + already here), RMA as
|
||||||
|
fallback if F3 refuses.
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# IDEA.md — Project Idea
|
||||||
|
|
||||||
|
## What is this?
|
||||||
|
|
||||||
|
A procedure + ESP32-C3 firmware to talk to the **Seagate F3 diagnostic serial
|
||||||
|
terminal** on two EMC/CLARiiON-locked Seagate Exos X18 SAS drives
|
||||||
|
(ST16000NM004J, EMC firmware ES2264), in order to reformat them out of the
|
||||||
|
locked "SS160520 CLAR200" state and back into usable 512-byte-sector drives
|
||||||
|
for the `tank` ZFS pool.
|
||||||
|
|
||||||
|
The two drives (SN **ZRS015V7**, **ZR511KWK**) were bought from ServerPartDeals
|
||||||
|
already pulled from an EMC array and never properly decommissioned. They answer
|
||||||
|
SCSI INQUIRY/VPD but return `Hardware Error / Internal target failure (44h/00h)`
|
||||||
|
to every other command — including READ CAPACITY — so **no host-side software
|
||||||
|
(sg_format, openSeaChest, SeaChest, firmware download) can touch them.** That is
|
||||||
|
fully documented in `~/bin/EMC_CLAR200_DRIVE_FIX_NOTES.md`.
|
||||||
|
|
||||||
|
The only remaining DIY lever is the drive's **F3 service terminal**, an
|
||||||
|
out-of-band UART on the PCB that bypasses the SCSI command layer entirely. This
|
||||||
|
project builds the cable (an ESP32-C3 acting as a 3.3 V USB-serial bridge) and
|
||||||
|
documents the F3 procedure to attempt the unlock.
|
||||||
|
|
||||||
|
## Problem it solves
|
||||||
|
|
||||||
|
- `tank` is short on **14.6 TB+** spare disks: mirror-35 has a dead + a dying
|
||||||
|
leg, and ex-mirror-38 is a bare single-disk vdev. Both need 14.6 TB disks.
|
||||||
|
- These two CLAR200 drives are 16 TB and would fix both holes — *if* they can be
|
||||||
|
unlocked. Otherwise they're paperweights / RMA candidates.
|
||||||
|
|
||||||
|
## Constraints / preferences
|
||||||
|
|
||||||
|
- **Cable:** ESP32-C3 already attached to steel141 at `/dev/ttyACM0`
|
||||||
|
(native USB-Serial-JTAG, MAC `58:8c:81:ac:f0:4c`). 3.3 V logic — native match
|
||||||
|
for the F3 header. No separate USB-TTL adapter needed.
|
||||||
|
- **Drive location:** ZRS015V7 currently in a JBOD on pve173. F3 work must be
|
||||||
|
done **on a bench**, not in-chassis — never risk the live 549 TB tank.
|
||||||
|
- **Honesty:** Exos-X18 F3 dialect ≠ the well-documented 7200.11 era. The
|
||||||
|
procedure discovers commands via the drive's own `?` help; it does not blindly
|
||||||
|
fire format commands copied from old forums.
|
||||||
|
- **Fallback if F3 fails:** RMA to ServerPartDeals (sold not-decommissioned),
|
||||||
|
or decommission in a real EMC VNX array, or PC-3000 SAS.
|
||||||
+179
@@ -0,0 +1,179 @@
|
|||||||
|
# F3 Unlock Procedure — EMC CLAR200 Exos X18 via ESP32-C3
|
||||||
|
|
||||||
|
Step-by-step to reach the Seagate **F3 service terminal** on a CLAR200-locked
|
||||||
|
Exos X18 (ST16000NM004J, EMC fw ES2264) and reformat it to 512-byte sectors.
|
||||||
|
|
||||||
|
> **Read first:** `~/bin/EMC_CLAR200_DRIVE_FIX_NOTES.md` (why every host-side tool
|
||||||
|
> fails) and `docs/f3-command-reference.md` (F3 dialect + honesty about what's
|
||||||
|
> uncertain on Exos). This file is the *physical + operational* runbook.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ Safety rules (non-negotiable)
|
||||||
|
|
||||||
|
1. **Bench only. Never in the pve173 JBOD.** The target drive lives one bay away
|
||||||
|
from the live 549 TB `tank`. Pull it and work on a bench so a slipped probe,
|
||||||
|
a shorted pad, or a power glitch can't touch a pool disk.
|
||||||
|
2. **3.3 V only.** The ESP32-C3 is 3.3 V native — correct for the F3 header.
|
||||||
|
Never put 5 V on the diagnostic pins. Never connect the ESP32's VCC/3V3/5V to
|
||||||
|
the drive — power the drive from its *own* SATA/SAS power. You share **only
|
||||||
|
TX, RX, GND**.
|
||||||
|
3. **Log everything.** Run the terminal under `screen -L` (or `tmux` + pipe).
|
||||||
|
F3 sessions are unrepeatable forensics; capture every byte.
|
||||||
|
4. **Escalation brake.** If the terminal is silent or garbled, the answer is
|
||||||
|
*re-check wiring / sweep baud / re-check ground* — never "try a more
|
||||||
|
aggressive format command." Destructive F3 commands are a last, deliberate
|
||||||
|
step, not a flailing one.
|
||||||
|
5. **One drive at a time.** Do ZRS015V7 end-to-end, document it, then ZR511KWK.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What you need
|
||||||
|
|
||||||
|
| Item | Have? | Notes |
|
||||||
|
|---|---|---|
|
||||||
|
| ESP32-C3 | ✅ on steel141 `/dev/ttyACM0` | native USB-CDC, 3.3 V, MAC 58:8c:81:ac:f0:4c |
|
||||||
|
| 3× jumper wires (F-F) | ? | drive header → ESP32 GPIO4/GPIO5/GND |
|
||||||
|
| Drive standalone power | ? | SFF-8482 → SATA-power adapter, a SAS dock, or PSU 5V+12V to the SAS power segment. **F3 needs only power — no SAS data link required.** |
|
||||||
|
| Multimeter | ? | to find TX/RX/GND pads (continuity + idle-voltage) |
|
||||||
|
| Insulating card / Kapton tape | ? | *contingency only* — for the BSY isolation trick if the terminal won't respond |
|
||||||
|
| Bench host running `screen` | steel141 or a laptop | wherever the ESP32 USB plugs in |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 1 — Flash the bridge (do this now, at the desk)
|
||||||
|
|
||||||
|
The ESP32-C3 is already on steel141. From the repo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/bin/clar200-unlock/firmware
|
||||||
|
./flash.sh /dev/ttyACM0 # installs arduino-cli + esp32 core on first run, then builds + uploads
|
||||||
|
```
|
||||||
|
|
||||||
|
Sanity-check the bridge before wiring to a drive: open it and loop GPIO4↔GPIO5
|
||||||
|
with a jumper — anything you type should echo back.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
screen /dev/ttyACM0 115200 # Ctrl-A k to quit screen
|
||||||
|
# jumper GPIO4<->GPIO5: typing shows characters; remove jumper: echo stops
|
||||||
|
```
|
||||||
|
|
||||||
|
USB-CDC baud is virtual (115200 is fine). You set the **drive** baud live inside
|
||||||
|
the session with the escape menu: `~1`=9600 `~2`=38400 `~3`=115200 `~4`=460800.
|
||||||
|
|
||||||
|
## Step 2 — Bench the drive
|
||||||
|
|
||||||
|
1. Power down / pull ZRS015V7 from the pve173 JBOD. Record the bay so it goes
|
||||||
|
back if this fails.
|
||||||
|
2. On the bench, give it **power only** (SATA/SAS power segment). No HBA/data
|
||||||
|
cable needed for F3.
|
||||||
|
3. Leave it powered off until the ESP32 is wired and the terminal is open
|
||||||
|
(Step 4), so you catch the boot banner.
|
||||||
|
|
||||||
|
## Step 3 — Find the F3 header pinout (multimeter)
|
||||||
|
|
||||||
|
3.5" Seagate SAS drives expose a small diagnostic UART — usually a 3- or 4-pad
|
||||||
|
group or a tiny header near the SAS connector / on the PCB edge. Pads are **not
|
||||||
|
labeled**. Identify them:
|
||||||
|
|
||||||
|
- **GND:** continuity (beep) to a drive mounting screw hole / SAS connector
|
||||||
|
shell.
|
||||||
|
- **TX (drive→host):** with the drive powered, idles **high ≈ 3.3 V** to GND and
|
||||||
|
twitches during boot. This is the pad you wire to ESP32 **GPIO5 (DRV_RX)**.
|
||||||
|
- **RX (drive→in):** the remaining signal pad, usually sits near 0 V / floating.
|
||||||
|
Wire to ESP32 **GPIO4 (DRV_TX)**.
|
||||||
|
- A 4th pad is often N/C or a 3.3 V rail — **do not** wire a power rail.
|
||||||
|
|
||||||
|
Photograph the PCB and pad group; save under `docs/photos/` for the next drive.
|
||||||
|
|
||||||
|
> If you can't disambiguate TX/RX by voltage, they're swappable safely at 3.3 V —
|
||||||
|
> if you get nothing, swap GPIO4↔GPIO5 and retry. Wrong-way TX/RX cannot damage
|
||||||
|
> anything here.
|
||||||
|
|
||||||
|
## Step 4 — Wire + open the terminal
|
||||||
|
|
||||||
|
```
|
||||||
|
drive GND ---- ESP32 GND
|
||||||
|
drive TX ---> ESP32 GPIO5 (DRV_RX)
|
||||||
|
drive RX <--- ESP32 GPIO4 (DRV_TX)
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
screen -L /dev/ttyACM0 115200 # -L logs to screenlog.0
|
||||||
|
```
|
||||||
|
|
||||||
|
Power on the drive. You should see a **boot banner** (Seagate F3 firmware spew).
|
||||||
|
- **Banner readable** → baud is right (try `~2`=38400 first; if garbage, sweep
|
||||||
|
`~1`/`~3`/`~4` until the banner is clean ASCII).
|
||||||
|
- **Nothing at any baud** → re-check GND first, then swap TX/RX (`~` won't help a
|
||||||
|
wiring fault). Only if still dead consider the BSY isolation trick
|
||||||
|
(`docs/f3-command-reference.md` §BSY).
|
||||||
|
|
||||||
|
## Step 5 — Get the `F3 T>` prompt
|
||||||
|
|
||||||
|
Once you see boot text (or a blank but live line):
|
||||||
|
|
||||||
|
- Press **Ctrl-Z**. Expect the prompt: `F3 T>` (T = top level).
|
||||||
|
- If Ctrl-Z does nothing, try Enter, then Ctrl-Z again; some firmware needs the
|
||||||
|
boot to finish first.
|
||||||
|
|
||||||
|
Capture the banner — it often states firmware rev and sometimes the current
|
||||||
|
**sector size / "format corrupt"** state, which tells you what you're fixing.
|
||||||
|
|
||||||
|
## Step 6 — Diagnose state, THEN format (drive-specific — go slow)
|
||||||
|
|
||||||
|
> This is where the Exos X18 F3 dialect diverges from old 7200.11 recipes.
|
||||||
|
> **Do not** paste `m0,6,2,...`-style commands blind. Map the drive first.
|
||||||
|
|
||||||
|
1. At `F3 T>` type `?` (and at each level you enter) to list available commands.
|
||||||
|
Record the menus. Identify the **format / translator** level and the
|
||||||
|
**read-capacity / identify** command.
|
||||||
|
2. Read current geometry/sector size. Confirm the hypothesis: locked at **520 B**
|
||||||
|
sectors (EMC T10-DIF) and/or **format-corrupt (block size 0)**.
|
||||||
|
3. Only once you've located the documented format command for *this* firmware,
|
||||||
|
issue a **format/reinitialize to 512-byte sectors**. On Seagate F3 this is the
|
||||||
|
format-unit / translator-regen at the format level; the exact token set comes
|
||||||
|
from Step 6.1's `?` output, **not** from memory.
|
||||||
|
4. Formats can run **hours** on a 16 TB drive and may print little. Don't
|
||||||
|
interrupt. Keep power stable.
|
||||||
|
|
||||||
|
See `docs/f3-command-reference.md` for the candidate command families and exactly
|
||||||
|
which ones are confirmed vs. 7200.11-era-only.
|
||||||
|
|
||||||
|
## Step 7 — Verify back on a real SAS port
|
||||||
|
|
||||||
|
After format completes and the drive is power-cycled:
|
||||||
|
|
||||||
|
1. Reinstall in the pve173 JBOD (or attach via the bench HBA).
|
||||||
|
2. `smartctl -i /dev/sgX` — identity should now be the **real** Seagate
|
||||||
|
ST16000NM004J, not "SATA-SAM SS160520 CLAR200", with the true serial.
|
||||||
|
3. `sg_readcap -l /dev/sgX` — must report **512-byte logical** sectors and full
|
||||||
|
~16 TB capacity (was Hardware Error before).
|
||||||
|
4. Short self-test: `smartctl -t short`, then check pending/reallocated sectors.
|
||||||
|
|
||||||
|
## Step 8 — Put it to work in `tank`
|
||||||
|
|
||||||
|
Healthy 14.6 TB+ disk → fix the redundancy holes (see `~/bin/CLAUDE.md` storage
|
||||||
|
notes and the tank diagnosis in this project's first handoff):
|
||||||
|
|
||||||
|
- **mirror-35** (dead ZL2PNZ99 leg + dying c37f4eff): `zpool replace tank
|
||||||
|
4450364206979169854 <newdisk>`, let it resilver, then replace/detach the dying
|
||||||
|
leg. *Replace before detach.*
|
||||||
|
- **ex-mirror-38** single-disk vdev (`wwn-0x5000c500c382f4ac-part1`): `zpool
|
||||||
|
attach` a mirror partner to restore redundancy.
|
||||||
|
|
||||||
|
Then repeat the whole procedure for **ZR511KWK**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## If F3 fails
|
||||||
|
|
||||||
|
Not every EMC-locked drive yields to the terminal (the firmware may refuse the
|
||||||
|
format at the F3 level too, or the SA modules may be EMC-proprietary). Stop and
|
||||||
|
fall back — do not escalate:
|
||||||
|
|
||||||
|
1. **RMA / refund — ServerPartDeals.** They shipped drives still in CLAR200
|
||||||
|
locked state = not decommissioned. Lead with the evidence in
|
||||||
|
`EMC_CLAR200_DRIVE_FIX_NOTES.md`. Lowest effort, arguably their fault.
|
||||||
|
2. **Decommission in a real EMC VNX/CLARiiON array** if you can borrow one.
|
||||||
|
3. **PC-3000 SAS** (professional) — overkill for $/TB drives.
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# clar200-unlock
|
||||||
|
|
||||||
|
Unlock two EMC/CLARiiON-locked Seagate **Exos X18** SAS drives
|
||||||
|
(ST16000NM004J, fw ES2264 — SN **ZRS015V7**, **ZR511KWK**) via the Seagate
|
||||||
|
**F3 service terminal**, using an **ESP32-C3** as a 3.3 V USB-serial bridge.
|
||||||
|
|
||||||
|
Goal: turn two 16 TB paperweights into healthy 512-byte-sector disks for the
|
||||||
|
`tank` ZFS pool, which is short on 14.6 TB+ spares (mirror-35 has a dead + a
|
||||||
|
dying leg; ex-mirror-38 is a bare single-disk vdev).
|
||||||
|
|
||||||
|
## Why this exists
|
||||||
|
|
||||||
|
These drives answer SCSI INQUIRY/VPD but return `Hardware Error / Internal
|
||||||
|
target failure` to **every** other command — including READ CAPACITY — so no
|
||||||
|
host-side tool (sg_format, openSeaChest, SeaChest, firmware download) can format
|
||||||
|
them. Full prior evidence: `~/bin/EMC_CLAR200_DRIVE_FIX_NOTES.md`. The F3 UART
|
||||||
|
bypasses the SCSI layer; it's the only remaining DIY lever.
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
| Path | What |
|
||||||
|
|---|---|
|
||||||
|
| `PROCEDURE.md` | **Start here** — the physical + operational runbook (bench, wiring, flash, F3 entry, format, verify) |
|
||||||
|
| `firmware/clar200_bridge.ino` | ESP32-C3 transparent USB↔UART bridge sketch (live baud menu) |
|
||||||
|
| `firmware/flash.sh` | One-command build + flash from steel141 (`/dev/ttyACM0`) |
|
||||||
|
| `docs/f3-command-reference.md` | F3 dialect — confirmed vs. 7200.11-era-only; what to verify with `?` |
|
||||||
|
| `IDEA.md` / `DECISIONS.md` / `CLAUDE.md` | project brief / decisions / Claude Code context |
|
||||||
|
|
||||||
|
## Hardware (current)
|
||||||
|
|
||||||
|
- **ESP32-C3** on steel141 `/dev/ttyACM0` (native USB-Serial-JTAG, 3.3 V, MAC
|
||||||
|
`58:8c:81:ac:f0:4c`). 3.3 V is a native match for the F3 header — no separate
|
||||||
|
USB-TTL adapter needed.
|
||||||
|
- **Target drive** ZRS015V7 currently in a pve173 JBOD → must be **benched** for
|
||||||
|
F3 work (never in-chassis next to live tank).
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd firmware && ./flash.sh /dev/ttyACM0 # build + flash the bridge
|
||||||
|
screen /dev/ttyACM0 115200 # open it; ~1/~2/~3/~4 set DRIVE baud
|
||||||
|
```
|
||||||
|
Then follow `PROCEDURE.md` from Step 2 (bench the drive).
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Bootstrapped 2026-06-14. Firmware + procedure written; **not yet flashed, drive
|
||||||
|
not yet benched.** See the latest `.claude/handoffs/` entry.
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# F3 Command Reference — confirmed vs. uncertain
|
||||||
|
|
||||||
|
The Seagate **F3 architecture** terminal is common across modern Seagate drives,
|
||||||
|
but the *command set differs by family*. The well-documented recipes are from the
|
||||||
|
**7200.11 "Moose" / Barracuda** era (circa 2009, the famous BSY/0-LBA bricking).
|
||||||
|
A 16 TB **Exos X18 (ST16000NM004J)** is many generations newer and its F3 dialect
|
||||||
|
is **not reliably documented publicly**. Treat everything below accordingly.
|
||||||
|
|
||||||
|
## Ground truth (safe to rely on)
|
||||||
|
|
||||||
|
- **Electrical:** F3 UART is **3.3 V TTL, 8N1**. Baud is one of
|
||||||
|
**9600 / 38400 / 115200** (sweep with the bridge's `~1/~2/~3` menu). 38400 is
|
||||||
|
the most common default.
|
||||||
|
- **Entering the terminal:** after the boot banner, **Ctrl-Z** → `F3 T>` prompt.
|
||||||
|
`F3 T>` = top level. `F3 2>` etc. = other diagnostic levels.
|
||||||
|
- **Level change:** `/` followed by a level id, e.g. `/2`, `/1`, `/T`, `/C`.
|
||||||
|
- **Help:** `?` at a prompt *may* dump that level's command list. **Always run
|
||||||
|
`?` and record the output before issuing anything.** This is how you learn the
|
||||||
|
*actual* command tokens for this firmware instead of guessing.
|
||||||
|
- **Logging:** every command may have side effects; keep `screen -L` running.
|
||||||
|
|
||||||
|
## CLAR200-specific expectation
|
||||||
|
|
||||||
|
This drive **boots and answers INQUIRY** (it is not BSY-hung), so you will
|
||||||
|
*probably* get an `F3 T>` prompt without the isolation trick. The lock is the EMC
|
||||||
|
firmware refusing **SCSI** FORMAT/READ-CAP — the F3 path sidesteps SCSI. The
|
||||||
|
realistic in-terminal goal is a **low-level format / translator regeneration to
|
||||||
|
512-byte logical sectors** (the drive is likely stuck at 520 B EMC-DIF and/or in
|
||||||
|
a "format corrupt / block size 0" state).
|
||||||
|
|
||||||
|
## Candidate commands — VERIFY with `?`, do NOT fire blind
|
||||||
|
|
||||||
|
These are **7200.11-era** and listed only so you recognize the *shapes* of
|
||||||
|
commands. **Confirm each against this drive's own `?` output before use.** Many
|
||||||
|
will not exist or will differ on Exos.
|
||||||
|
|
||||||
|
| Intent | 7200.11-era token | Status on Exos X18 |
|
||||||
|
|---|---|---|
|
||||||
|
| Spin down motor (level 2) | `Z` | unconfirmed |
|
||||||
|
| Spin up motor (level 2) | `U` | unconfirmed |
|
||||||
|
| Regenerate SMART (level 1) | `N1` | unconfirmed |
|
||||||
|
| Partition regenerate (level T) | `i4,1,22` | unconfirmed |
|
||||||
|
| Format / regen translator (level T) | `m0,2,2,0,0,0,0,22` | unconfirmed |
|
||||||
|
| Low-level format w/ sector size | `m0,6,2,,,,,22` (historic 512-format) | **likely different** |
|
||||||
|
|
||||||
|
⚠️ The `m0,...` translator/format commands are exactly the ones that, with wrong
|
||||||
|
parameters, can make a drive *worse*. On Exos, the safer modern route is often a
|
||||||
|
proper **Format Unit at the format level** with an explicit bytes-per-sector of
|
||||||
|
512 — but the token for that comes from `?`, not this table.
|
||||||
|
|
||||||
|
## BSY isolation trick (contingency only)
|
||||||
|
|
||||||
|
Only if the terminal is **completely unresponsive / the drive hangs BSY** at
|
||||||
|
power-on:
|
||||||
|
|
||||||
|
1. Power off. Slip a thin insulator (business card / Kapton) between the PCB and
|
||||||
|
the **head-contact block** (or motor contacts, per the drive) so firmware
|
||||||
|
boots without reading the system area.
|
||||||
|
2. Power on → you should now get `F3 T>` (firmware skipped the unreadable SA).
|
||||||
|
3. Carefully remove the insulator / re-seat contacts **without** powering down.
|
||||||
|
4. Spin up and proceed.
|
||||||
|
|
||||||
|
This is a 7200.11 technique. It is **unlikely to be needed** here (the drive
|
||||||
|
isn't BSY) and is drive-mechanically risky — last resort.
|
||||||
|
|
||||||
|
## Sources / further reading (verify, don't trust blindly)
|
||||||
|
|
||||||
|
- HDDGURU / MRT / PC-3000 community threads on "CLAR200" and "SS160520" Seagate
|
||||||
|
EMC drives — the recurring finding is: SCSI tools fail, F3 terminal or array
|
||||||
|
decommission is the path.
|
||||||
|
- Seagate 7200.11 BSY fix write-ups — for F3 terminal *mechanics* (prompt, `/`
|
||||||
|
levels, `?`), not for the exact Exos command tokens.
|
||||||
|
|
||||||
|
When you discover the real Exos X18 tokens during the session, **record them
|
||||||
|
here** so ZR511KWK (and any future EMC drive) is a known quantity.
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
// clar200_bridge.ino — ESP32-C3 transparent USB <-> UART bridge
|
||||||
|
// Purpose: talk to a Seagate F3 diagnostic terminal on an EMC CLAR200-locked
|
||||||
|
// Exos X18 SAS drive, using the C3's native USB-CDC as the host side.
|
||||||
|
//
|
||||||
|
// Target board: ESP32-C3 (native USB-Serial-JTAG), e.g. C3 SuperMini / DevKitM-1.
|
||||||
|
// Host port: /dev/ttyACM0 on steel141 (MAC 58:8c:81:ac:f0:4c).
|
||||||
|
//
|
||||||
|
// Build flag REQUIRED: "USB CDC On Boot: Enabled" (so `Serial` == USB-CDC, not UART0)
|
||||||
|
// arduino-cli: append :CDCOnBoot=cdc to the FQBN (see firmware/flash.sh)
|
||||||
|
//
|
||||||
|
// Wiring (3.3 V, common ground, TX<->RX crossover):
|
||||||
|
// ESP32-C3 GPIO4 (DRV_TX) ---> drive F3 RX
|
||||||
|
// ESP32-C3 GPIO5 (DRV_RX) <--- drive F3 TX
|
||||||
|
// ESP32-C3 GND ---- drive GND (mandatory)
|
||||||
|
// Do NOT connect any VCC/5V to the drive header. Drive is powered by its own
|
||||||
|
// SATA/SAS power. You only tap TX / RX / GND.
|
||||||
|
//
|
||||||
|
// Baud: Seagate F3 is 8N1. Family varies — this sketch boots at 38400 and lets
|
||||||
|
// you change baud live without reflashing, via a `~` escape menu (see below).
|
||||||
|
//
|
||||||
|
// Live baud menu — type these AT THE START OF A LINE in your terminal:
|
||||||
|
// ~1 -> 9600 ~2 -> 38400 (default) ~3 -> 115200 ~4 -> 460800
|
||||||
|
// ~? -> print current baud
|
||||||
|
// Anything else is passed through transparently (binary-safe).
|
||||||
|
|
||||||
|
#define DRV_TX 4 // ESP32-C3 GPIO -> drive RX
|
||||||
|
#define DRV_RX 5 // ESP32-C3 GPIO <- drive TX
|
||||||
|
#define LED_PIN 8 // most C3 boards: onboard LED on GPIO8 (active-low). Harmless if absent.
|
||||||
|
|
||||||
|
static const uint32_t BAUDS[] = {9600, 38400, 115200, 460800};
|
||||||
|
static uint32_t curBaud = 38400;
|
||||||
|
|
||||||
|
static void applyBaud(uint32_t b) {
|
||||||
|
curBaud = b;
|
||||||
|
Serial1.end();
|
||||||
|
Serial1.begin(curBaud, SERIAL_8N1, DRV_RX, DRV_TX);
|
||||||
|
Serial.printf("\r\n[bridge] drive UART = %lu 8N1\r\n", (unsigned long)curBaud);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(LED_PIN, OUTPUT);
|
||||||
|
digitalWrite(LED_PIN, LOW); // LED on = bridge alive
|
||||||
|
Serial.begin(115200); // USB-CDC; baud value is ignored over CDC
|
||||||
|
delay(200);
|
||||||
|
applyBaud(38400);
|
||||||
|
Serial.print("\r\n[bridge] ESP32-C3 F3 bridge ready. ~1/~2/~3/~4 set baud, ~? shows it.\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minimal line-start escape parser so `~N` switches baud but everything else
|
||||||
|
// (including F3 binary) flows through untouched.
|
||||||
|
static bool atLineStart = true;
|
||||||
|
static bool inEscape = false;
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// host -> drive
|
||||||
|
while (Serial.available()) {
|
||||||
|
int c = Serial.read();
|
||||||
|
if (inEscape) {
|
||||||
|
inEscape = false;
|
||||||
|
switch (c) {
|
||||||
|
case '1': applyBaud(BAUDS[0]); break;
|
||||||
|
case '2': applyBaud(BAUDS[1]); break;
|
||||||
|
case '3': applyBaud(BAUDS[2]); break;
|
||||||
|
case '4': applyBaud(BAUDS[3]); break;
|
||||||
|
case '?': Serial.printf("\r\n[bridge] current = %lu\r\n", (unsigned long)curBaud); break;
|
||||||
|
default: // not a menu key: emit the swallowed '~' then this char
|
||||||
|
Serial1.write('~'); Serial1.write((uint8_t)c);
|
||||||
|
}
|
||||||
|
atLineStart = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (atLineStart && c == '~') { inEscape = true; continue; }
|
||||||
|
Serial1.write((uint8_t)c);
|
||||||
|
atLineStart = (c == '\n' || c == '\r');
|
||||||
|
}
|
||||||
|
// drive -> host
|
||||||
|
while (Serial1.available()) Serial.write((uint8_t)Serial1.read());
|
||||||
|
}
|
||||||
Executable
+37
@@ -0,0 +1,37 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# flash.sh — build + flash the ESP32-C3 F3 bridge from steel141.
|
||||||
|
# The C3 is at /dev/ttyACM0 (native USB-Serial-JTAG). esptool is already present;
|
||||||
|
# arduino-cli + the esp32 core are installed on first run if missing.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PORT="${1:-/dev/ttyACM0}"
|
||||||
|
SKETCH="$(cd "$(dirname "$0")" && pwd)/clar200_bridge.ino"
|
||||||
|
FQBN="esp32:esp32:esp32c3:CDCOnBoot=cdc" # CDCOnBoot=cdc -> Serial == USB-CDC (required by sketch)
|
||||||
|
|
||||||
|
command -v arduino-cli >/dev/null 2>&1 || {
|
||||||
|
echo ">> installing arduino-cli to ~/.local/bin ..."
|
||||||
|
mkdir -p ~/.local/bin
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh \
|
||||||
|
| BINDIR=~/.local/bin sh
|
||||||
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ! arduino-cli core list 2>/dev/null | grep -q '^esp32:esp32'; then
|
||||||
|
echo ">> installing esp32 Arduino core (this is the big download) ..."
|
||||||
|
arduino-cli config init --overwrite >/dev/null 2>&1 || true
|
||||||
|
arduino-cli config add board_manager.additional_urls \
|
||||||
|
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
|
||||||
|
arduino-cli core update-index
|
||||||
|
arduino-cli core install esp32:esp32
|
||||||
|
fi
|
||||||
|
|
||||||
|
# arduino-cli wants the sketch in a dir named like the .ino; it already is.
|
||||||
|
SKETCH_DIR="$(dirname "$SKETCH")"
|
||||||
|
echo ">> compiling for $FQBN ..."
|
||||||
|
arduino-cli compile --fqbn "$FQBN" "$SKETCH_DIR"
|
||||||
|
|
||||||
|
echo ">> flashing to $PORT ..."
|
||||||
|
arduino-cli upload --fqbn "$FQBN" --port "$PORT" "$SKETCH_DIR"
|
||||||
|
|
||||||
|
echo ">> done. Open the terminal with: screen $PORT 115200 (Ctrl-A k to quit)"
|
||||||
|
echo " USB-CDC baud is virtual; set the DRIVE baud with ~1/~2/~3/~4 inside the session."
|
||||||
Reference in New Issue
Block a user