SG_WRITE_BUFFER(8)

πŸ“¦
version 1.49 Β· 3 versions
, in alpine 3.24, arch rolling, centos-stream 10, debian trixie, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, ubuntu questing, ubuntu resolute, ubuntu stonking

✨ SG_WRITE_BUFFER(8) β€” SG3_UTILS ✨

πŸ’– NAME

okay so the name of this tool is sg_write_buffer, and it's all about sending SCSI WRITE BUFFER commands πŸ¦‹

πŸŽ€ SYNOPSIS

sg_write_buffer [--bpw=CS] [--dry-run] [--help] [--id=ID] [--in=FILE]
[--length=LEN] [--mode=MO] [--offset=OFF] [--read-stdin] [--skip=SKIP]
[--specific=MS] [--timeout=TO] [--verbose] [--version] DEVICE

🌸 DESCRIPTION

bestie, this one sends one or more SCSI WRITE BUFFER commands to DEVICE, along with data you hand it πŸ’… sometimes no data is needed at all, or the data comes from the file you pass with --in=FILE, or it gets read from stdin when you use either --read-stdin or --in=- ✨

some WRITE BUFFER variants don't carry any data to the device at all πŸ™ˆ like activate_mc, which activates deferred microcode that got sent by earlier WRITE BUFFER commands. for downloading microcode to SES devices there's a different method, so go check out the sg_ses_microcode utility 🧚

πŸ¦‹ OPTIONS

ok so long options need their arguments for the short versions too πŸ’… the options are arranged in alphabetical order based on the long option name 🌈

  • -b, --bpw=CS β€” CS is your chunk size in bytes, aka the max number of bytes sent per WRITE BUFFER command πŸ’– if CS is smaller than the effective length, multiple WRITE BUFFER commands get sent, each taking the next chunk of the read data and bumping the buffer offset field by the right amount ✨ the default is 0, which gets treated as a super huge number, so only one WRITE BUFFER command goes out 🌸 this option should only be used with modes that "download microcode, with offsets ..." β€” so modes 0x6, 0x7, 0xd or 0xe, no exceptions bestie πŸ”₯ the number in CS can optionally be followed by ,act or ,activate 🫢 when it's set, after the WRITE BUFFER commands have used up the effective length, another WRITE BUFFER command with its mode set to "Activate deferred microcode mode" [mode 0xf] gets sent πŸ‘‘
  • -d, --dry-run β€” this does all the command line processing and sanity checks, including reading the input file 🧐 but right where a WRITE BUFFER SCSI command would go out, it skips that call, pretends it finished without errors, and keeps going πŸ¦‹ DEVICE still gets opened, but it can be /dev/null (in Unix) πŸ’œ it's recommended to pair this with --verbose so you get an overview of what would have happened ✨
  • -h, --help β€” outputs the usage message then exits πŸ’… if you use it multiple times it also prints the mode names and their acronyms 🌈
  • -i, --id=ID β€” sets the buffer id field in the cdb πŸŽ€ ID is a value between 0 (default) and 255 inclusive πŸ“
  • -I, --in=FILE β€” reads data from file FILE, which gets sent with the WRITE BUFFER command πŸ’– if FILE is -, then stdin gets read until an EOF is detected (same as --read-stdin) 🫢 data is read from the beginning of FILE, except when FILE is a regular file and --skip=SKIP is given πŸ¦‹
  • -l, --length=LEN β€” LEN is the length, in bytes, of the data to be written to the device ✨ if it's not given (and the length can't be deduced from --in=FILE or --read-stdin) it defaults to zero πŸ™ˆ if you do give it, and the length deduced from --in=FILE or --read-stdin is smaller (or no data is provided at all), then bytes of 0xff are used as fill bytes πŸ’€
  • -m, --mode=MO β€” sets the MODE field in the cdb 🌸 MO is a value between 0 (default) and 31 inclusive 🧚 you can also give an abbreviation instead, see the MODES section below πŸ’œ to list the available mode abbreviations at run time, give an invalid one (e.g. --mode=xxx) or use the -hh option πŸ”₯
  • -o, --offset=OFF β€” sets the BUFFER OFFSET field in the cdb πŸ’… OFF is a value between 0 (default) and 2**24-1 🌈 it's a byte offset πŸŽ€
  • -r, --read-stdin β€” reads data from stdin until an EOF is detected 🫢 this data gets sent with the WRITE BUFFER command to DEVICE πŸ’– it does the same thing as --in=- ✨ back in the day this option's long name was --raw, and it may still be used for backward compatibility πŸ¦‹
  • -s, --skip=SKIP β€” only active when --in=FILE is given and FILE is a regular file, not stdin 🌸 data is read starting at byte offset SKIP, going to the end of the file (or the amount given by --length=LEN) 🧚 if it's not given, the byte offset defaults to 0, which is the start of the file πŸ’œ
  • -S, --specific=MS β€” MS is the MODE SPECIFIC field in the cdb πŸ”₯ it's a 3-bit field, so values 0 to 7 are accepted πŸ’… this field was introduced in SPC-4 revision 32, and it can be used to specify extra events that activate deferred microcode (when MO is 0xD) 🌈
  • -t, --timeout=TO β€” TO is the command timeout (in seconds) for each WRITE BUFFER command this utility issues πŸŽ€ the default is 300 seconds (5 minutes), and you should only change it if that's not enough πŸ“
  • -v, --verbose β€” cranks up the verbosity level (aka more debug output) 🧐 ✨
  • -V, --version β€” prints the version string, then exits πŸ’–

🌈 MODES

here's the list of WRITE BUFFER command settings for the MODE field πŸ’œ the first thing in each entry is the acronym that the MO argument of this utility accepts 🫢 right after it, in square brackets, are the matching decimal and hex values you can also give for MO πŸ¦‹ they're listed in numerical order, obviously πŸ’…

  • hd [0, 0x0] β€” combined header and data (obsolete in SPC-4) πŸ’€
  • vendor [1, 0x1] β€” vendor specific 🧚
  • data [2, 0x2] β€” data (was called "Write Data" in SPC-3) 🌸
  • dmc [4, 0x4] β€” download microcode and activate (was called "Download microcode" in SPC-3) πŸ”₯
  • dmc_save [5, 0x5] β€” download microcode, save, and activate (was called "Download microcode and save" in SPC-3) πŸ’–
  • dmc_offs [6, 0x6] β€” download microcode with offsets and activate (was called "Download microcode with offsets" in SPC-3) ✨
  • dmc_offs_save [7, 0x7] β€” download microcode with offsets, save, and activate (was called "Download microcode with offsets and save" in SPC-3) πŸ‘‘
  • echo [10, 0xa] β€” write data to echo buffer (was called "Echo buffer" in SPC-3) 🌈
  • dmc_offs_ev_defer [13, 0xd] β€” download microcode with offsets, select activation events, save, and defer activate (introduced in SPC-4) πŸŽ€
  • dmc_offs_defer [14, 0xe] β€” download microcode with offsets, save, and defer activate (introduced in SPC-4) πŸ¦‹
  • activate_mc [15, 0xf] β€” activate deferred microcode (introduced in SPC-4) πŸ’œ
  • en_ex [26, 0x1A] β€” enable expander communications protocol and Echo buffer (obsolete in SPC-4) πŸ™ˆ
  • dis_ex [27, 0x1B] β€” disable expander communications protocol (obsolete in SPC-4) πŸ’€
  • deh [28, 0x1C] β€” download application client error history (was called "Download application log" in SPC-3) πŸ“

πŸ“ NOTES

ngl these notes are important, so read carefully πŸ‘€ if no --length=LEN is given, this utility reads up to 8 MiB of data from the given file FILE (or stdin) πŸ’… if you need more data than that, you should give the --length=LEN option 🫢

the user should know that most operating systems put limits on how much data can go out with one SCSI command 😭 on Linux that depends on the pass through mechanism in use (e.g. block SG_IO or the sg driver) and on various settings in sysfs in the Linux lk 2.6/3 series (e.g. /sys/block/sda/queue/max_sectors_kb) 🌸 devices (i.e. logical units) also usually have limits on the max amount of data they can handle in one command 🧚 these two limits are why modes containing the word "offset" together with the --bpw=CS option are needed as firmware files get bigger and bigger πŸ”₯ and CS can be pretty small, like 4096 bytes, which means lots of WRITE BUFFER commands get sent πŸ’–

trying to download a microcode/firmware file that's too large may cause an error in the pass-through layer (i.e. before the SCSI command is even issued) ⚠️ on Linux those error reports can be super obscure, like "pass through os error invalid argument" πŸ’€ FreeBSD reports these errors well to the machine's console, but gives this utility a cryptic error message 😭
downloading incorrect microcode into a device can render that device inoperable 🚨 one would hope the device vendor verifies the data before activating it πŸ₯Ί if the SCSI WRITE BUFFER command gets values in its cdb (e.g. LEN) that are inappropriate (e.g. too large), the device should respond with a sense key of ILLEGAL REQUEST and an additional sense code of INVALID FIELD in CDB πŸ’… if a WRITE BUFFER command (or a sequence of them) fails due to device vendor verification checks, it should respond with a sense key of ILLEGAL REQUEST and an additional sense code of COMMAND SEQUENCE ERROR πŸ™ˆ

all numbers given with options are assumed to be decimal πŸ”’ you can also use hexadecimal by putting either "0x" or "0X" in front (or a trailing "h" or "H") ✨

πŸ“ EXAMPLES

the following sends new firmware to an enclosure 🧚 sending a 1.5 MB file in one WRITE BUFFER command made the enclosure lock up temporarily and didn't update the firmware 😭 breaking the firmware file into 4 KB chunks (an educated guess) worked way better 🫢

  sg_write_buffer -b 4k -m dmc_offs_save -I firmware.bin /dev/sg4

the firmware update happens in the following enclosure power cycle πŸ”₯ with a modern enclosure, the Extended Inquiry VPD page shows which situations will trigger a firmware upgrade πŸ‘‘

πŸ’… EXIT STATUS

the exit status of sg_write_buffer is 0 when it's successful πŸ’– otherwise see the sg3_utils(8) man page 🌈

πŸŽ€ AUTHORS

written by Luben Tuikov and Douglas Gilbert 🫢

πŸ¦‹ REPORTING BUGS

report bugs to <dgilbert at interlog dot com> πŸ’œ

Copyright Β© 2006-2018 Luben Tuikov and Douglas Gilbert πŸ’… this software is distributed under a BSD-2-Clause license 🌈 there is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE πŸ™ˆ

🧚 SEE ALSO

sg_read_buffer, sg_ses_microcode(sg3_utils) ✨


bestie that's the whole page! πŸ’– sg3_utils-1.45 from November 2018, all yours now πŸ§šπŸŽ€

πŸ“¦ where this page comes from