Author: wmb Date: Tue May 10 19:53:29 2011 New Revision: 2196 URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2196
Log: OLPC - RTC Anti-rollback security feature - initial checkin.
Added: cpu/x86/pc/olpc/guardrtc.fth Modified: cpu/arm/mmp2/sspspi.fth cpu/arm/olpc/1.75/devices.fth cpu/arm/olpc/1.75/fw.bth cpu/x86/pc/olpc/fw.bth cpu/x86/pc/olpc/security.fth cpu/x86/pc/olpc/setwp.fth cpu/x86/pc/olpc/via/fw.bth dev/olpc/kb3700/ecio.fth dev/olpc/spiflash/flashif.fth dev/olpc/spiflash/spiflash.fth
Modified: cpu/arm/mmp2/sspspi.fth ============================================================================== --- cpu/arm/mmp2/sspspi.fth Tue May 10 01:27:14 2011 (r2195) +++ cpu/arm/mmp2/sspspi.fth Tue May 10 19:53:29 2011 (r2196) @@ -24,12 +24,105 @@ : ssp-spi-cs-on ( -- ) d# 46 gpio-clr ; : ssp-spi-cs-off ( -- ) d# 46 gpio-set ;
+code ssp-spi-out-in ( bo -- bi ) + set r0,`ssp-base #` + begin + ldr r1,[r0,#8] + ands r1,r1,#4 + 0<> until + str tos,[r0,#0x10] + begin + ldr r1,[r0,#8] + ands r1,r1,#8 + 0<> until + ldr tos,[r0,#0x10] +c; +0 [if] : ssp-spi-out-in ( bo -- bi ) begin ssp-sssr l@ 4 and until \ Tx not full ssp-ssdr l! begin ssp-sssr l@ 8 and until \ Rx not empty ssp-ssdr l@ ; +[then] +code ssp-spi-in16 ( adr -- adr' ) + set r0,`ssp-base #` + set r2,#0xf04 + set r3,#0xf008 + mov r4,#0 + begin + ldr r1,[r0,#8] + and r1,r1,r2 + cmp r1,#4 + 0= until + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + str r4,[r0,#0x10] + begin + ldr r1,[r0,#8] + and r1,r1,r3 + cmp r1,r3 + 0= until + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 + ldr r4,[r0,#0x10] + strb r4,[tos],#1 +c; +: fast-spi-flash-read ( adr len offset -- ) + 3 spi-cmd spi-adr ( adr len ) + d# 16 /mod ( adr len%16 len/16 ) + swap >r ( adr len/16 r: len%16 ) + 0 ?do ( adr r: len%16 ) + ssp-spi-in16 ( adr' r: len%16 ) + loop ( adr' r: len%16 ) + r> 0 ?do ( adr ) + spi-in over c! ( adr ) + 1+ ( adr' ) + loop ( adr ) + drop ( ) + spi-cs-off ( ) +;
: ssp-spi-out ( b -- ) ssp-spi-out-in drop ; : ssp-spi-in ( -- b ) 0 ssp-spi-out-in ; @@ -48,8 +141,10 @@ ['] ssp-spi-out to spi-out ['] ssp-spi-cs-on to spi-cs-on ['] ssp-spi-cs-off to spi-cs-off - ['] ssp-spi-reprogrammed to spi-reprogrammed - use-spi-flash-read + ['] noop to spi-reprogrammed + ['] noop to spi-reprogrammed-no-reboot +\ use-spi-flash-read + ['] fast-spi-flash-read to flash-read ; use-ssp-spi
Modified: cpu/arm/olpc/1.75/devices.fth ============================================================================== --- cpu/arm/olpc/1.75/devices.fth Tue May 10 01:27:14 2011 (r2195) +++ cpu/arm/olpc/1.75/devices.fth Tue May 10 19:53:29 2011 (r2196) @@ -103,7 +103,6 @@ fload ${BP}/dev/olpc/spiflash/spiflash.fth \ SPI FLASH programming
: ignore-power-button ; \ XXX implement me -: ssp-spi-reprogrammed ;
fload ${BP}/cpu/arm/mmp2/sspspi.fth \ Synchronous Serial Port SPI interface
Modified: cpu/arm/olpc/1.75/fw.bth ============================================================================== --- cpu/arm/olpc/1.75/fw.bth Tue May 10 01:27:14 2011 (r2195) +++ cpu/arm/olpc/1.75/fw.bth Tue May 10 19:53:29 2011 (r2196) @@ -229,6 +229,7 @@ ; code halt ( -- ) wfi c; fload ${BP}/cpu/x86/pc/olpc/sound.fth +fload ${BP}/cpu/x86/pc/olpc/guardrtc.fth fload ${BP}/cpu/x86/pc/olpc/security.fth
: pre-setup-for-linux ( -- ) @@ -361,12 +362,16 @@ game-key-mask = if protect-fw try-fs-update then ;
+\ fload ${BP}/cpu/arm/mmp2/clocks.fth + +\ 0 [if] : 400mhz ( -- ) h# d428.2804 l@ 7 invert and h# 7000.0000 or 1 or h# d428.2804 l! ; : 800mhz ( -- ) h# d428.2804 l@ 7 invert and h# 7000.0000 or h# d428.2804 l! ; +\ [then]
: startup ( -- ) standalone? 0= if exit then
Modified: cpu/x86/pc/olpc/fw.bth ============================================================================== --- cpu/x86/pc/olpc/fw.bth Tue May 10 01:27:14 2011 (r2195) +++ cpu/x86/pc/olpc/fw.bth Tue May 10 19:53:29 2011 (r2196) @@ -361,6 +361,7 @@
fload ${BP}/cpu/x86/pc/olpc/setwp.fth fload ${BP}/cpu/x86/pc/olpc/sound.fth +fload ${BP}/cpu/x86/pc/olpc/guardrtc.fth fload ${BP}/cpu/x86/pc/olpc/security.fth fload ${BP}/cpu/x86/pc/olpc/xpsecure.fth fload ${BP}/ofw/gui/ofpong.fth
Added: cpu/x86/pc/olpc/guardrtc.fth ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ cpu/x86/pc/olpc/guardrtc.fth Tue May 10 19:53:29 2011 (r2196) @@ -0,0 +1,282 @@ +\ See license at end of file +purpose: Real-Time Clock Anti-rollback for security + +\ The entry points are: +\ rtcar-enabled? ( -- flag ) +\ True if an "rt" tag is present in manufacturing data, thus enabling anti-rollback +\ rtc-rollback? ( -- flag ) +\ True if either a rollback attach is detected or the timestamp area is corrupt +\ fix-rtc-timestamps ( data$ -- ) \ "count old-timestamp new-timestamp" +\ Restores valid data in the timestamp area according to data$ + +\ Layout of timestamp area: +\ Bytes 0-3 - 4-byte rewrite count - little-endian +\ Bytes 4-8 - Timestamp 0 +\ Bytes 9-13 - Timestamp 1 +\ ... +\ Bytes 32759-32763 - Timestamp 6552 +\ Each timestamp is a 4-byte little-endian "unixtime" (seconds since +\ epoch), followed by a 1-byte xor checksum of the preceding 4 bytes ^ 0x55 + +5 constant /timestamp + +\ First 4 bytes are the write counter base value +/l constant timestamp-start +d# 32768 timestamp-start - /timestamp / constant #timestamps/rewrite +#timestamps/rewrite /timestamp * constant /timestamps + +0 value timestamp-offset +0 value rtc-timestamp +0 value new-timestamp +: +tsbuf ( offset -- adr ) mfg-data-buf + ; +: timestamp-adr ( -- adr ) timestamp-offset +tsbuf timestamp-start + ; +: compute-check-byte ( timestamp -- check ) + lbsplit xor xor xor h# 55 xor +; +: count-base@ ( -- n ) 0 +tsbuf le-l@ ; +: count-base! ( n -- ) 0 +tsbuf le-l! ; +: #timestamps ( timestamp-offset -- n ) + timestamp-offset /timestamp / ( #buffered-timestamps ) + count-base@ + ( n ) +; +: timestamp-bad? ( -- timestamp error? ) + timestamp-adr le-l@ ( timestamp ) + dup compute-check-byte ( timestamp computed-check ) + timestamp-adr la1+ c@ <> ( timestamp error ) +; +: set-timestamp-offset ( -- error? ) + 0 to timestamp-offset ( ) + 0 to rtc-timestamp + begin timestamp-offset /timestamps <> while ( ) + timestamp-adr le-l@ h# ffffffff = if ( ) + \ Verify that the rest of the area is all ff too + timestamp-adr /timestamps timestamp-offset - ( adr len ) + h# ff bskip 0<> ( error? ) + exit ( -- error? ) + then ( ) + timestamp-bad? if ( timestamp ) + drop ( ) + true exit \ Bad checksum ( -- error? ) + else ( timestamp ) + to rtc-timestamp ( ) + then ( ) + + timestamp-offset /timestamp + to timestamp-offset ( ) + repeat ( ) + false ( ) +; + +: commit-timestamp-area ( -- ) + flash-open ( ) + (put-mfg-data) ( ) + flash-close ( ) +; +: flash-write-some ( adr len offset -- ) + flash-open ( adr len offset ) + flash-write ( ) + flash-close ( ) +; +: init-timestamp-area ( base -- ) + count-base! ( ) + + timestamp-start +tsbuf /timestamps h# ff bskip if ( ) + \ There is junk in the timestamp area so we must erase and rewrite + timestamp-start +tsbuf /timestamps h# ff fill ( ) + commit-timestamp-area + else + \ The timestamp area is already erased, so we can write without erasing + mfg-data-buf /l mfg-data-offset flash-write-some + then + + 0 to timestamp-offset +; +: rewrite-timestamp-area ( -- ) + \ Fill the timestamp area with ff's + timestamp-start +tsbuf /timestamps /timestamp /string h# ff fill + + \ Update the rewrite count + count-base@ #timestamps/rewrite + count-base! + + \ Perform an erase and rewrite on the mfg data area + commit-timestamp-area +; +: update-timestamp ( -- ) + timestamp-offset /timestamps = if ( ) + rewrite-timestamp-area ( ) + 0 to timestamp-offset ( ) + then + + new-timestamp dup timestamp-adr le-l! ( unixtime ) + compute-check-byte timestamp-adr la1+ c! ( ) + timestamp-adr /timestamp timestamp-offset timestamp-start + mfg-data-offset + flash-write-some ( ) +; + +: find-timestamp ( -- status ) + get-mfg-data ( ) + + count-base@ h# ffffffff = if ( ) + 0 init-timestamp-area ( ) + then ( ) + + set-timestamp-offset if ( ) + \ There is bad data after the last timestamp, if any + 2 exit ( -- 1 ) + then ( ) + + timestamp-offset 0= if ( ) + \ There is no data in the timestamp area + 1 exit ( -- 2 ) + then ( ) + 0 ( -- 0 ) +; +: ?update-timestamp ( status -- status' ) + dup 1 > if exit then ( status ) + + time&date >unix-seconds to new-timestamp ( status ) + + new-timestamp rtc-timestamp <= if ( status ) + \ Time went backwards + drop 3 exit ( -- status' ) + then ( status ) + + update-timestamp ( status ) +; + +1 buffer: byte-buf +: encode-byte ( b -- ) byte-buf c! byte-buf 1 encode-bytes ; +: +encode-bytes ( prop$ $ -- prop$' ) encode-bytes encode+ ; + +: make-timestamp-property ( -- ) + rtc-timestamp 0= if exit then + " /chosen" find-package drop push-package ( ) + rtc-timestamp unix-seconds> ( s m h d m y ) + push-decimal ( s m h d m y ) + #timestamps (.) encode-bytes ( s m h d m y prop$ ) + " ," +encode-bytes rot (.4) +encode-bytes ( s m h d m prop$ ) + " -" +encode-bytes rot (.2) +encode-bytes ( s m h d prop$' ) + " -" +encode-bytes rot (.2) +encode-bytes ( s m h prop$' ) + " @" +encode-bytes rot (.2) +encode-bytes ( s m prop$' ) + " :" +encode-bytes rot (.2) +encode-bytes ( s prop$' ) + " :" +encode-bytes rot (.2) +encode-bytes ( prop$' ) + " "(00)" +encode-bytes ( prop$' ) + pop-base ( ) + + " rtc-timestamp" (property) ( ) + pop-package +; +: make-status-property ( value$ -- ) + " /chosen" find-package drop push-package ( value$ ) + encode-string " rtc-status" (property) ( ) + pop-package +; + +: rtcar-enabled? ( -- flag ) + " rt" find-tag if ( data$ ) + 2drop true ( flag ) + else ( ) + false ( flag ) + then ( flag ) +; + +: rtc-rollback? ( -- flag ) + rtcar-enabled? 0= if exit then + + find-timestamp ( status ) + ?update-timestamp ( status' ) + make-timestamp-property ( status ) + case + 0 of " ok" make-status-property false endof + 1 of " empty" make-status-property false endof + 2 of " residue" make-status-property true endof + 3 of " rollback" make-status-property true endof + ( default ) true swap + endcase +; + +: parse-field ( val$ delimiter expected-length -- val$' field$ ) + >r left-parse-string ( val$' field$ ) + dup r> <> throw +; +\ Throws an error if either a number is unparsable or out of range +: decode-number ( field$ min max -- n ) + 2>r ( field$ r: min max ) + push-decimal $number pop-base ( n error? r: min max ) + throw ( n r: min max ) + dup 2r> between 0= throw ( n ) +; + +: decode-timestamp ( val$ -- s m h d m y ) + [char] - 4 parse-field d# 2000 d# 2099 decode-number >r ( val$' r: y ) + [char] - 2 parse-field 1 d# 12 decode-number >r ( val$' r: y m ) + [char] @ 2 parse-field 1 d# 31 decode-number >r ( val$' r: y m d ) + [char] : 2 parse-field 0 d# 23 decode-number >r ( val$' r: y m d h ) + [char] : 2 parse-field 0 d# 59 decode-number >r ( val$' r: y m d h m ) + dup 2 <> throw 0 d# 59 decode-number >r ( r: y m d h m s ) + r> r> r> r> r> r> ( s m h d m y ) +; +: fix-rtc-timestamps ( data$ -- ) \ "count old-ts new-ts" e.g. 2011-10-12,00:23:45 + bl left-parse-string ( rem$ count$ ) + + 0 h# 7fffffff ['] decode-number catch if ( rem$ x x x x ) + 4drop 2drop ." Bad count format" cr ( ) + exit ( -- ) + then ( rem$ count ) + -rot ( count rem$ ) + + find-timestamp ( count rem$ ) + + bl left-parse-string ( count rem$ old-timestamp$ ) + 2dup " no-timestamp" $= if ( count rem$ old-timestamp$ ) + 2drop ( count rem$ ) + rtc-timestamp if ( count rem$ ) + 3drop ( ) + ." Old timestamp mismatch" cr ( ) + exit ( -- ) + then + else ( count rem$ old-timestamp$ ) + ['] decode-timestamp catch if ( count rem$ x x ) + 5drop ( ) + ." Bad timestamp format" cr ( ) + exit ( -- ) + then ( count rem$ s m h d m y ) + then ( count rem$ s m h d m y ) + + >unix-seconds ( count rem$ old-timestamp ) + rtc-timestamp <> if ( count rem$ ) + 3drop ( ) + ." Old timestamp mismatch" cr ( ) + exit ( -- ) + then ( count rem$ ) + rot init-timestamp-area ( rem$ ) + + ['] decode-timestamp catch if ( x x ) + 2drop ." Bad timestamp format" cr ( ) + exit ( -- ) + then ( s m h d m y ) + >unix-seconds to new-timestamp ( ) + update-timestamp ( ) +; + +\ LICENSE_BEGIN +\ Copyright (c) 2011 FirmWorks +\ +\ Permission is hereby granted, free of charge, to any person obtaining +\ a copy of this software and associated documentation files (the +\ "Software"), to deal in the Software without restriction, including +\ without limitation the rights to use, copy, modify, merge, publish, +\ distribute, sublicense, and/or sell copies of the Software, and to +\ permit persons to whom the Software is furnished to do so, subject to +\ the following conditions: +\ +\ The above copyright notice and this permission notice shall be +\ included in all copies or substantial portions of the Software. +\ +\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +\ +\ LICENSE_END
Modified: cpu/x86/pc/olpc/security.fth ============================================================================== --- cpu/x86/pc/olpc/security.fth Tue May 10 01:27:14 2011 (r2195) +++ cpu/x86/pc/olpc/security.fth Tue May 10 19:53:29 2011 (r2196) @@ -728,7 +728,11 @@ " ak" find-tag if 2drop " run" else - lease-valid? if " run" else " act" then + rtc-rollback? if + " act" + else + lease-valid? if " run" else " act" then + then then cn-buf place ; @@ -951,6 +955,39 @@ r> to debug-security? ;
+: fix-rtc-history ( data$ -- ) \ SN UUID counter timestamp newtimestamp + \ Isolate data from first line + newline left-parse-string 2nip ( rem$ ) + + bl left-parse-string ( rem$ serial$ ) + my-sn$ $= 0= if ( rem$ ) + ." Wrong serial number" ?lease-error-cr ( rem$ ) + 2drop exit ( -- ) + then ( rem$ ) + + \ Ignore UUID for now + bl left-parse-string ( rem$ uuid$ ) + 2drop ( rem$ ) + + fix-rtc-timestamps ( ) +; + +: ?rtc-update ( -- ) + rtcar-enabled? 0= if exit then + show-dot + null$ cn-buf place + " rtcreset" bundle-present? if + " RTCRESET found - " ?lease-debug + leasekey$ to pubkey$ + img$ sig$ sha-valid? if + img$ fix-rtc-history + show-unlock + else + show-lock + then + then +; + : load-from-device ( devname$ -- done? )
show-dot @@ -972,6 +1009,8 @@ then then
+ ?rtc-update + show-dot ?leased \ Sets cn-buf
Modified: cpu/x86/pc/olpc/setwp.fth ============================================================================== --- cpu/x86/pc/olpc/setwp.fth Tue May 10 01:27:14 2011 (r2195) +++ cpu/x86/pc/olpc/setwp.fth Tue May 10 19:53:29 2011 (r2196) @@ -1,3 +1,6 @@ +\ See license at end of file +purpose: Changing manufacturing data - adding and deleting tags + \ Set the write protect tag. This is used to convert unlocked prototype \ machined to locked machines for testing the firmware security. This \ should not be necessary once mass production systems start coming from @@ -217,3 +220,27 @@ $add-tag ( data$ ) free-mem ; + +\ LICENSE_BEGIN +\ Copyright (c) 2007 FirmWorks +\ +\ Permission is hereby granted, free of charge, to any person obtaining +\ a copy of this software and associated documentation files (the +\ "Software"), to deal in the Software without restriction, including +\ without limitation the rights to use, copy, modify, merge, publish, +\ distribute, sublicense, and/or sell copies of the Software, and to +\ permit persons to whom the Software is furnished to do so, subject to +\ the following conditions: +\ +\ The above copyright notice and this permission notice shall be +\ included in all copies or substantial portions of the Software. +\ +\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +\ +\ LICENSE_END
Modified: cpu/x86/pc/olpc/via/fw.bth ============================================================================== --- cpu/x86/pc/olpc/via/fw.bth Tue May 10 01:27:14 2011 (r2195) +++ cpu/x86/pc/olpc/via/fw.bth Tue May 10 19:53:29 2011 (r2196) @@ -406,6 +406,7 @@ fload ${BP}/cpu/x86/firfilter.fth fload ${BP}/cpu/x86/pc/olpc/sound.fth fload ${BP}/cpu/x86/pc/olpc/via/sound.fth +fload ${BP}/cpu/x86/pc/olpc/guardrtc.fth fload ${BP}/cpu/x86/pc/olpc/security.fth fload ${BP}/cpu/x86/pc/olpc/xpsecure.fth fload ${BP}/ofw/gui/ofpong.fth
Modified: dev/olpc/kb3700/ecio.fth ============================================================================== --- dev/olpc/kb3700/ecio.fth Tue May 10 01:27:14 2011 (r2195) +++ dev/olpc/kb3700/ecio.fth Tue May 10 19:53:29 2011 (r2196) @@ -348,6 +348,10 @@ ." Restarting..." d# 2000 ms cr kbc-on begin again ; +: io-spi-reprogrammed-no-reboot ( -- ) + no-kbc-reboot + kbc-on +;
: io-spi-start ( -- ) ['] io-spi@ to spi@ @@ -356,6 +360,7 @@ use-ec-spi \ spi-in, spi-cs-on, spi-cs-off via EC commands
['] io-spi-reprogrammed to spi-reprogrammed + ['] io-spi-reprogrammed-no-reboot to spi-reprogrammed-no-reboot use-mem-flash-read [ifdef] uncache-flash uncache-flash [then]
Modified: dev/olpc/spiflash/flashif.fth ============================================================================== --- dev/olpc/spiflash/flashif.fth Tue May 10 01:27:14 2011 (r2195) +++ dev/olpc/spiflash/flashif.fth Tue May 10 19:53:29 2011 (r2196) @@ -2,6 +2,7 @@ purpose: Generic interface for FLASH programming operations
defer flash-open ( -- ) +defer flash-close ( -- ) defer flash-write-enable ( -- ) defer flash-write-disable ( -- ) defer flash-write ( adr len offset -- )
Modified: dev/olpc/spiflash/spiflash.fth ============================================================================== --- dev/olpc/spiflash/spiflash.fth Tue May 10 01:27:14 2011 (r2195) +++ dev/olpc/spiflash/spiflash.fth Tue May 10 19:53:29 2011 (r2196) @@ -219,6 +219,8 @@
defer spi-reprogrammed ( -- ) \ What to do when done reprogramming ' noop to spi-reprogrammed +defer spi-reprogrammed-no-reboot ( -- ) \ What to do when done reprogramming +' noop to spi-reprogrammed-no-reboot
defer write-spi-flash ( adr len offset -- )
@@ -312,6 +314,7 @@ \ Install the SPI FLASH versions as their implementations. : use-spi-flash ( -- ) ['] spi-flash-open to flash-open + ['] spi-reprogrammed-no-reboot to flash-close ['] spi-flash-write-enable to flash-write-enable ['] spi-reprogrammed to flash-write-disable ['] write-spi-flash to flash-write