diff mbox

[v2,2/4] scsi: Add SCSI block write support

Message ID 1479214972-19153-3-git-send-email-thuth@redhat.com
State Accepted
Headers show

Commit Message

Thomas Huth Nov. 15, 2016, 1:02 p.m. UTC
Using the SCSI commands WRITE-10 and WRITE-16, we can implement block write
support for SCSI disks. Write access to the first 34 sectors is not allowed,
though, to avoid that the user / client program accidentially destroys the
partition table.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 slof/fs/scsi-disk.fs    | 38 ++++++++++++++++++++++++++++++++
 slof/fs/scsi-support.fs | 58 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+)

Comments

Nikunj A Dadhania Nov. 16, 2016, 7:49 a.m. UTC | #1
Thomas Huth <thuth@redhat.com> writes:

> Using the SCSI commands WRITE-10 and WRITE-16, we can implement block write
> support for SCSI disks. Write access to the first 34 sectors is not allowed,
> though, to avoid that the user / client program accidentially destroys the
> partition table.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>

Reviewed-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
diff mbox

Patch

diff --git a/slof/fs/scsi-disk.fs b/slof/fs/scsi-disk.fs
index bcaa19e..9c0a9c1 100644
--- a/slof/fs/scsi-disk.fs
+++ b/slof/fs/scsi-disk.fs
@@ -95,6 +95,40 @@  CREATE cdb 10 allot
     dup 0<> IF " read-blocks" dump-scsi-error -65 throw ELSE drop THEN
 ;
 
+: write-blocks ( addr block# #blocks -- #written )
+    scsi-disk-debug? IF
+        ." SCSI-DISK: write-blocks " .s cr
+    THEN
+
+    \ Do not allow writes to the partition table (GPT is in first 34 sectors)
+    over 22 < IF
+        ." SCSI-DISK ERROR: Write access to partition table is not allowed." cr
+        3drop 0 EXIT
+    THEN
+
+    \ Bound check
+    2dup + max-block-num > IF
+        ." SCSI-DISK: Access beyond end of device ! " cr
+        3drop 0 EXIT
+    THEN
+
+    dup block-size *                            ( addr block# #blocks len )
+    >r rot r>                                   ( block# #blocks addr len )
+    2swap                                       ( addr len block# #blocks )
+    dup >r
+    cdb                                         ( addr len block# #blocks cdb )
+    max-block-num FFFFFFFF > IF
+        scsi-build-write-16
+    ELSE
+        scsi-build-write-10
+    THEN
+    r> -rot                                     ( #blocks addr len )
+    scsi-dir-write cdb scsi-param-size 10
+    retry-scsi-command
+                                                ( #blocks [ sense-buf sense-len ] stat )
+    dup 0<> IF s" write-blocks" dump-scsi-error -65 throw ELSE drop THEN
+;
+
 : (inquiry) ( size -- buffer | NULL )
     dup cdb scsi-build-inquiry
     \ 16 retries for inquiry to flush out any UAs
@@ -342,6 +376,10 @@  CREATE cdb 10 allot
 : read ( addr len -- actual )
     s" read" deblocker @ $call-method ;
 
+: write ( addr len -- actual )
+    s" write" deblocker @ $call-method
+;
+
 \ Get rid of SCSI bits
 scsi-close
 
diff --git a/slof/fs/scsi-support.fs b/slof/fs/scsi-support.fs
index d24c8a1..608e468 100644
--- a/slof/fs/scsi-support.fs
+++ b/slof/fs/scsi-support.fs
@@ -531,6 +531,64 @@  CONSTANT scsi-length-read-16
 ;
 
 \ ***************************************************************************
+\ SCSI-Command: WRITE (10)
+\         Type: Block Command
+\ ***************************************************************************
+\ Forth Word:   scsi-build-write-10  ( block# #blocks cdb -- )
+\ ***************************************************************************
+\ command code
+2A CONSTANT scsi-cmd-write-10
+
+\ CDB structure
+STRUCT
+   /c FIELD write-10>operation-code
+   /c FIELD write-10>protect
+   /l FIELD write-10>block-address            \ logical block address (32bits)
+   /c FIELD write-10>group
+   /w FIELD write-10>length                   \ transfer length (16-bits)
+   /c FIELD write-10>control
+CONSTANT scsi-length-write-10
+
+: scsi-build-write-10                         ( block# #blocks cdb -- )
+   >r                                         ( block# #blocks )  ( R: -- cdb )
+   r@ scsi-length-write-10 erase              \ 10 bytes CDB
+   scsi-cmd-write-10 r@ write-10>operation-code c! ( block# #blocks )
+   r@ write-10>length w!                      ( block# )
+   r@ write-10>block-address l!               (  )
+   scsi-param-control r> write-10>control c!  ( R: cdb -- )
+   scsi-length-write-10 to scsi-param-size    \ update CDB length
+;
+
+\ ***************************************************************************
+\ SCSI-Command: WRITE (16)
+\         Type: Block Command
+\ ***************************************************************************
+\ Forth Word:   scsi-build-write-16  ( block# #blocks cdb -- )
+\ ***************************************************************************
+\ command code
+8A CONSTANT scsi-cmd-write-16
+
+\ CDB structure
+STRUCT
+   /c FIELD write-16>operation-code
+   /c FIELD write-16>protect                  \ RDPROTECT, DPO, FUA, FUA_NV
+   /x FIELD write-16>block-address            \ LBA
+   /l FIELD write-16>length                   \ Transfer length (32-bits)
+   /c FIELD write-16>group                    \ Group number
+   /c FIELD write-16>control
+CONSTANT scsi-length-write-16
+
+: scsi-build-write-16                         ( block# #blocks cdb -- )
+   >r                                         ( block# #blocks )  ( R: -- cdb )
+   r@ scsi-length-write-16 erase              \ 16 bytes CDB
+   scsi-cmd-write-16 r@ write-16>operation-code c! ( block# #blocks )
+   r@ write-16>length l!                      ( block# )
+   r@ write-16>block-address x!               (  )
+   scsi-param-control r> write-16>control c!  ( R: cdb -- )
+   scsi-length-write-16 to scsi-param-size    \ update CDB length
+;
+
+\ ***************************************************************************
 \ SCSI-Command: START STOP UNIT
 \         Type: Block Command (SBC-3 clause 5.19)
 \ ***************************************************************************