2021-02-21

Temporarily Removing Read-Only Attribute of Some Disposable USB Flip Cards

Many corporate conferences use(d) cheap branded, read-only flip card style USB flash drives to distribute demo software or other marketing materials.  These are set to read-only, limiting their utility as low/no cost disposable play storage.  Using undocumented vendor specific commands, this oversight can sometimes *temporarily*¹ be remedied.  

¹ Needs to be done every time device is plugged in. This method uses an undocumented SCSI command to write to ram. There's another undocumented SSCI command to write a sector to flash, currently unknown.  

tl;dr:  

eject /dev/sdX

sg_raw -v -v -v -R -s 0 /dev/sdX F1 0C F6 9B 70 00 00 00 00 00 00 00

eject /dev/sdX

Requirements

sg3_utils:

sudo apt-get install on pi   

and sometimes necessary: sudo apt-get install eject  

Source:  sg3_utils

Read-only (Flip Card) USB Flash Drive:

(Intel) Flip card

Example for sale:  usb0218gb-8gb-flip-card-printed-usb-flash-drives


The particular 2gb Intel credit card thumbdrive variant explored here contained an auto-opened link for Parallel Studio XE and used <1mb of the capacity of the drive:

      <a href="https://software.intel.com/en-us/intel-parallel-studio-xe?utm_campaign=DPD&amp;utm_source=Collateral%20Resources%20USB&amp;utm_content=Parallel%20Studio%20Buy%20Now" target="_blank"><img src="img/learn_more.jpg" alt="Learn more &rsaquo;" /></a>

Contents:                   

32K     ./img/box1.jpg
32K     ./img/box2.jpg
64K     ./img/box3.jpg
64K     ./img/box4.jpg
32K     ./img/box5.jpg
32K     ./img/box6.jpg
32K     ./img/buy_now.jpg
32K     ./img/evaluate_now.jpg
32K     ./img/intel_logo.jpg
32K     ./img/learn_more.jpg
32K     ./img/page_bg.jpg
32K     ./img/parallel_universe_magazine.jpg
32K     ./img/product_support.jpg
32K     ./img/Thumbs.db
32K     ./img/twitter_handle.jpg
576K    ./img
64K     ./OpenFile/STARTDOC.EXE
32K     ./OpenFile/STARTDOC.INF
128K    ./OpenFile
32K     ./AUTORUN.INF
64K     ./collateral.ico
32K     ./start.htm
864K

Initial mount

[ 37895007.597355] usb 1-1.4: new high-speed USB device number 4 using dwc_otg
[37895007.730866] usb 1-1.4: New USB device found, idVendor=1234, idProduct=1234, bcdDevice=11.00
[37895007.730883] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[37895007.730893] usb 1-1.4: Product: 1234567812345678
[37895007.730903] usb 1-1.4: Manufacturer: 12345678
[37895007.731764] usb-storage 1-1.4:1.0: USB Mass Storage device detected
[37895007.735346] scsi host0: usb-storage 1-1.4:1.0
[37895007.790833] usbcore: registered new interface driver uas
[37895008.868174] scsi 0:0:0:0: Direct-Access     12345678 1234567812345678 1100 PQ: 0 ANSI: 4
[37895008.894264] sd 0:0:0:0: Attached scsi generic sg0 type 0
[37895008.968555] sd 0:0:0:0: [sda] 3893248 512-byte logical blocks: (1.99 GB/1.86 GiB)
[37895008.971146] sd 0:0:0:0: [sda] Write Protect is on
[37895008.971198] sd 0:0:0:0: [sda] Mode Sense: 43 00 80 00
[37895008.971384] sd 0:0:0:0: [sda] 3893248 512-byte logical blocks: (1.99 GB/1.86 GiB)
[37895008.972061] sd 0:0:0:0: [sda] Attached SCSI removable disk
[37895008.981651]  sda: sda1

Query and Modify

Linux

Query

# sg_raw -v -v -v -R -n -r 1024 -o id.bin /dev/sda F0 04 00 00 00 00 00 00 00 00 00 02

Attempt to decode cdb name: Vendor specific [0xf0]
open /dev/sda with flags=0x800
    cdb to send: f0 04 00 00 00 00 00 00 00 00 00 02
    Command name: Vendor specific [0xf0]
sense_buffer=0x7ea5a4d4, length=32
dxfer_buffer_in=0x122e000, length=1024
SCSI Status: Good
Writing 1024 bytes of data to .bin
No errors

Check for expected SMI controller:  

# strings id.bin | grep SMI

  2013-02-26  SM3257ENLTBA   SMI32X

Or look in-situ:  

# xxd -s 32 -l 35 -u -c 32 id.bin

00000020: 2020 3230 3133 2D30 322D 3236 2020 534D 3332 3537 454E 4C54 4241 2020 2053 4D49    2013-02-26  SM3257ENLTBA   SMI
00000040: 3332 58                                                                            32X

Disable Read-only

Send a stop command:  

# eject /dev/sdb

Send vendor command:  

# sg_raw -v -v -v -R -s 0 /dev/sda F1 0C F6 9B 70 00 00 00 00 00 00 00

Attempt to decode cdb name: Vendor specific [0xf1]
open /dev/sda with flags=0x800
    cdb to send: f1 0c f6 9b 70 00 00 00 00 00 00 00
    Command name: Vendor specific [0xf1]
sense_buffer=0x7ed16514, length=32
dxfer_buffer_out=0x1a10000, length=0
SCSI Status: Good

Re-attach:  

# eject /dev/sda

[37955283.370850] sd 0:0:0:0: [sda] 3893248 512-byte logical blocks: (1.99 GB/1.86 GiB)
[37955283.371530] sd 0:0:0:0: [sda] Write Protect is off
[37955283.371544] sd 0:0:0:0: [sda] Mode Sense: 43 00 00 00
[37955283.374875]  sda: sda1

Explanation about the ejects:  

eject 1 tells the PI that it's 'gone', but it's still plugged in  

eject 2 should tell the PI, "I'm baaack!"  

Behind the scenes, SCSI actually has a 'start'/'stop' command - and it causes a 'media changed' response  - this means the kernel treats it as if you plugged an SD card into an external reader, and re-scans -- and this time, the response to the "INQUIRY" command says "I'm writable", and Linux is happy  

Testing Write

dd if=systemrescue-9.03-i686.iso of=/dev/sda bs=8M status=progress

794820608 bytes (795 MB, 758 MiB) copied, 152.078 s, 5.2 MB/s
94+1 records in
94+1 records out
794820608 bytes (795 MB, 758 MiB) copied, 180.895 s, 4.4 MB/s
du -ahd 1

2.0K    ./autorun
2.1M    ./boot
2.9M    ./EFI
162K    ./isolinux
752M    ./sysresccd
2.5K    ./sysrescue.d
757M    .

Windows 

> sg_scan

PD0     [L]     ST2000DM001-1CH164 ...
PD1     [C]     PCIe SSD  E8FM11.6 ...
PD2     [D]     Seagate   Backup+ Desk ...
PD3             Msft      Virtual Disk      1.0
PD4             12345678  1234567812345678  1100

> sg_ident PD4  

No output... 

Note: sg_stop doesn't work, need --eject:  

> sg_start --eject PD4

> sg_raw -v -v -v -R -s 0 PD4 F1 0C F6 9B 70 00 00 00 00 00 00 00

Attempt to decode cdb name: Vendor specific [0xf1]
    cdb to send: f1 0c f6 9b 70 00 00 00 00 00 00 00
    Command name: Vendor specific [0xf1]
sense_buffer=000000000065F9E0, length=32
dxfer_buffer_out=00000000001DB000, length=0
SCSI Status: Good
No errors

Re-attach:  

> sg_start --start PD4

Note: Rufus won't write drive: Alt-Z to zero it.  

Other notes:  Some systems seem to have issues booting when it's written this way, leaving this just as a way to put some small amount of information on flash and "protect" it (say, a password database).  

Unfinished Notes / Unsorted Dump

Questions

1.  What are the right parameters to 'write flash' (F1 01), does it need a block-erase first, or does it do that as part of its operation
        More concretely - what are the sequences of bytes sent to Port 19h (eg, 0 <1 byte>, 1 < 10 bytes?> 4 <2 bytes>)
2.  Why do ports 19h and 88h/89h both seem to have something to do with flash data cycles
        (Port 88/Port 89 is used to 'Read Flash ID" (command 0x90/0x00), port 19 seems to be used for just about everything else.

 Memory Map

    0000    - 2013-02-026 SM3257ENLTBA SMI32x
    8000    - Buffer (?)
    9000    - Buffer (???)
                    Max read is 8KB (10h)
    A000    - Used as code target?
    B000    - ??
    C000    - SM3257ENU 141027-SLC C00D version string
    D000    - Bank switched based on 7C.5 ?
    DBF0    - 20091116 rwcmd
    DC00    - ?
    DFF0    - 20070102 SETOP2
    E000    - 4 banks (7C.3,4) WMP ??
    F000    - 20091116 ISP1k ?

Port notes:  

    50      USB status/control
            .1 direction (0=send,1=recv)
            .0 active (set to 1, wait for clear)

    70      ? status of some sort
            .1   Code 1C87 waits on (SRC is C0_00, uses 71)
            .2   Code_1ea0 waits for clear
                    71 - used by .1 mode?  (memfill?)
    72,73,74,75,76,77  <= R4, R5, R6, R7, R2, R3
                    0xE0, 0, 0x80, 0, 2, 0
                    R6:R7 = Dest (80_00) R2:R3 = length, R4:R5 = src
                    72 = SRC HIGH   (Must be C0 for memfill?)
                    73 = SRC LOW    (should  be 00 for memfill??)
                    74 = Dest High
                    75 = Dest Low
                    76 = length high
                    77 = Length low
                    70.2 = 1
                    wait for 70.2 to be clear
    7C      ? Control
            .5      ? Bank switch for D0??
            .4      set in BA6
            .3      set in BAF
            .2,.1,.0        bank switching?

Generating a dump (without bank switching) Dump all RAM (64k?)

for ((ii=0; ii < 256;ii+=4)); do sg_raw -v -v -v -R -n -r 1024 -o $ii.bin /dev/sg7 F0 04 `printf "%02x" $ii` 00 00 00 00 00 00 00 00 02 ; done
(for ((ii=0; ii < 256;ii+=4)); do echo $ii.bin; done) | xargs cat > map.bin

This just does 1024 bytes at a time