Skip to content

Add Windows raw disk support and image inspection#1

Merged
Fx64b merged 1 commit into
mainfrom
claude/usb-flashing-performance-8zn5m1
Jul 9, 2026
Merged

Add Windows raw disk support and image inspection#1
Fx64b merged 1 commit into
mainfrom
claude/usb-flashing-performance-8zn5m1

Conversation

@Fx64b

@Fx64b Fx64b commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Summary

This PR adds proper Windows support for raw disk writes and implements image inspection to warn users when burning non-bootable images. The changes enable Brenner to safely write to physical drives on Windows by locking and dismounting volumes, and provide early feedback when an image cannot boot from a raw byte-for-byte copy.

Key Changes

  • Windows raw disk handling (cmd/rawdisk_windows.go): Implements volume locking and dismounting via FSCTL_LOCK_VOLUME and FSCTL_DISMOUNT_VOLUME before writing to physical drives. This is essential because Windows blocks direct writes to sectors belonging to mounted volumes. The implementation:

    • Detects Windows raw device paths (\\.\PhysicalDriveN)
    • Locks all drive-lettered volumes on the target disk
    • Holds locks until verification completes
    • Checks for Administrator privileges
  • Image inspection (internal/flash/inspect.go, internal/flash/inspect_test.go): New Inspect() function analyzes image headers to detect:

    • MBR boot signature and partition entries
    • GPT headers
    • ISO9660 primary volume descriptors
    • Provides BootableRaw() and WindowsInstaller() helper methods
  • Pre-write warnings (cmd/exec.go): Added warnIfRawWriteWontBoot() to alert users before burning images that cannot boot from raw copies (e.g., Windows installer ISOs). Warnings are shown in both interactive and CLI modes.

  • Improved verification (cmd/exec.go, internal/flash/writer.go):

    • Hash the image during write (via io.TeeReader) to avoid re-reading the source
    • Compare SHA-256 digests instead of byte-for-byte comparison
    • Added dropCache() on Linux to evict pages before verification, ensuring the readback actually hits the physical medium
  • Better write coalescing (internal/flash/writer.go): Use io.ReadFull() instead of single Read() calls to handle short reads from pipes and tee chains, ensuring full-sized aligned writes required by Windows raw disk handles.

  • Linux writeback tuning (cmd/devicewriter_linux.go): Enhanced dirty page cache management by waiting on writeback windows to keep the page cache bounded and prevent stalls during final fsync.

  • Platform-specific stubs (cmd/rawdisk_other.go, cmd/dropcache_other.go, cmd/dropcache_linux.go): Build-tagged implementations for non-Windows platforms.

Notable Implementation Details

  • Volume locks are held in a deferred release function until all verification is complete, preventing the filesystem stack from accessing the drive during the critical write+verify window
  • Image inspection is best-effort and skipped in elevated child processes to avoid duplicate warnings
  • The verification flow now never requires a second pass over the source image, improving performance for large ISOs
  • Windows Administrator check uses process token elevation detection rather than relying on os.Stat() which cannot handle raw device paths

https://claude.ai/code/session_01RYHBqMpwXrHodFDVWD7FQJ

Boot fixes:
- Warn before burning images that cannot boot from a raw copy (no MBR/GPT),
  with a specific message for Windows installer ISOs - the classic case where
  a dd-style copy silently produces a non-booting stick.
- Windows: actually lock and dismount every volume on the target disk
  (FSCTL_LOCK_VOLUME + FSCTL_DISMOUNT_VOLUME) before raw writes; without the
  lock Windows rejects writes to sectors under mounted volumes and the stick
  ends up corrupt. The old code only claimed to do this in a comment.
- Windows: open \\.\PhysicalDriveN via CreateFile with OPEN_EXISTING and
  check token elevation instead of os.Stat, which cannot handle raw device
  paths.

Performance and verification:
- Hash the ISO while it streams to the device (TeeReader), removing the
  second full read pass over the source during verification.
- Evict the page cache (posix_fadvise DONTNEED) before the verify readback so
  verification reads the physical medium, not the RAM copy of the write.
- Bound dirty page cache during writes with windowed sync_file_range waits
  (32 MiB windows, two in flight) instead of only kicking async writeback -
  keeps the progress bar honest and avoids the multi-minute final fsync stall.
- Coalesce short reads into full 4 MiB blocks in flash.Copy so devices always
  see large aligned writes (also required by Windows raw-disk handles).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RYHBqMpwXrHodFDVWD7FQJ
@Fx64b Fx64b merged commit 5be7717 into main Jul 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants