Author: wmb Date: 2008-06-25 01:14:57 +0200 (Wed, 25 Jun 2008) New Revision: 838
Added: dev/flashpkg.fth dev/flashrb.fth dev/flashwrite.fth dev/subrange.fth Modified: cpu/x86/pc/lxdevel/config.fth cpu/x86/pc/lxdevel/devices.fth cpu/x86/pc/lxdevel/fw.bth cpu/x86/pc/olpc/devices.fth dev/geode/lpcflash.fth dev/olpc/spiflash/flashec.fth dev/olpc/spiflash/spiflash.fth dev/olpc/spiflash/spiui.fth ofw/confvar/nameval.fth ofw/core/ofwcore.fth ofw/fs/dropinfs.fth Log: Big revision of the FLASH infrastructure so it's easier to integrate FLASH write drivers into the system. For OLPC, there is no functional difference at the top level, but the internal arrangement of the FLASH device node subtree has changed. It's now possible to compile an OLPC ROM that can save configuration variables in an SPI FLASH block (see config.fth:use-flash-nvram). For the lxdevel build, that option is now chosen by default.
Modified: cpu/x86/pc/lxdevel/config.fth =================================================================== --- cpu/x86/pc/lxdevel/config.fth 2008-06-20 23:37:28 UTC (rev 837) +++ cpu/x86/pc/lxdevel/config.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -39,7 +39,8 @@ create no-floppy-node create use-pci-isa
-create use-null-nvram +\ create use-null-nvram \ Don't store configuration variables +create use-flash-nvram \ Store configuration variables in SPI FLASH
fload ${BP}/cpu/x86/pc/lxdevel/addrs.fth
Modified: cpu/x86/pc/lxdevel/devices.fth =================================================================== --- cpu/x86/pc/lxdevel/devices.fth 2008-06-20 23:37:28 UTC (rev 837) +++ cpu/x86/pc/lxdevel/devices.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -76,11 +76,12 @@ 0 0 dropin-base <# u#s u#> " /" begin-package " flash" device-name
-[ifdef] addresses-assigned dropin-size [else] h# 4.0000 [then] +[ifdef] addresses-assigned dropin-size [else] h# 8.0000 [then] dup value /device constant /device-phys my-address my-space /device-phys reg - fload ${BP}/cpu/x86/pc/flashpkg.fth + fload ${BP}/dev/flashpkg.fth + fload ${BP}/dev/flashwrite.fth
: init ( comp$ /device -- ) to /device 2>r @@ -92,10 +93,29 @@ /device /device-phys <> if enable-flash-select then [then] ; +end-package
+\ Create a node below the top-level FLASH node to accessing the portion +\ containing the dropin modules. +\ The number in the line below is the offset from the beginning of the +\ FLASH to the block that contains the dropin modules. +0 0 " 0" " /flash" begin-package + " dropins" device-name + + h# 70000 constant /device \ Size of the area for dropin modules + fload ${BP}/dev/subrange.fth end-package -" rom" dropin-base <# u#s " /flash@" hold$ u#> $devalias
+devalias dropins /dropins + +\ Create a pseudo-device that presents the dropin modules as a filesystem. +0 0 " " " /" begin-package + fload ${BP}/ofw/fs/dropinfs.fth +end-package + +\ This devalias lets us say, for example, "dir rom:" +devalias rom /dropin-fs + fload ${BP}/cpu/x86/forthint.fth \ Low-level interrupt handling code fload ${BP}/dev/isa/irq.fth \ ISA interrupt dispatcher fload ${BP}/cpu/x86/pc/isatick.fth \ Use ISA timer as the alarm tick timer @@ -112,11 +132,7 @@ devalias d disk devalias n nand devalias u /usb/disk -devalias sd /sd/disk
-\ If we don't do the ctlr-selftest, the keyboard won't start on the LX devel board -\ dev /8042 patch false ctlr-selftest open device-end - 0 0 " i70" " /isa" begin-package \ Real-time clock node fload ${BP}/dev/ds1385r.fth 8 encode-int 0 encode-int encode+ " interrupts" property @@ -159,6 +175,10 @@ [then]
[ifdef] use-null-nvram +\ For not storing configuration variable changes across reboots ... +\ This is useful for "turnkey" systems where configurability would +\ increase support costs. + fload ${BP}/cpu/x86/pc/nullnv.fth stand-init: Null-NVRAM " /null-nvram" open-dev to nvram-node @@ -166,6 +186,29 @@ ; [then]
+[ifdef] use-flash-nvram +\ For configuration variables stored in a sector of the boot FLASH ... + +\ Create a node below the top-level FLASH node to access the portion +\ containing the configuration variables. + +\ The number in the line below is the offset from the beginning of the +\ FLASH to the block that contains the configuration variables. +0 0 " 70000" " /flash" begin-package + " nvram" device-name + + \ Size of configuration variable area. Typically the size of + \ a FLASH block (erase unit). + h# 10000 constant /device + fload ${BP}/dev/subrange.fth +end-package + +stand-init: NVRAM + " /nvram" open-dev to nvram-node + ['] init-config-vars catch drop +; +[then] + \ Create the alias unless it already exists : $?devalias ( alias$ value$ -- ) 2over not-alias? if $devalias exit then ( alias$ value$ alias$ ) @@ -220,7 +263,7 @@ dend ;
-\ fload ${BP}/dev/geode/lpcflash.fth \ Reflasher for PLCC FLASH on A-test +fload ${BP}/dev/geode/lpcflash.fth \ Reflasher for LPC FLASH
: +i encode-int encode+ ; : 0+i 0 +i ;
Modified: cpu/x86/pc/lxdevel/fw.bth =================================================================== --- cpu/x86/pc/lxdevel/fw.bth 2008-06-20 23:37:28 UTC (rev 837) +++ cpu/x86/pc/lxdevel/fw.bth 2008-06-24 23:14:57 UTC (rev 838) @@ -188,6 +188,8 @@ fload ${BP}/cpu/x86/pc/mmusetup.fth \ Initial values for MMU lists [then]
+: background-rgb ( -- r g b ) h# ff h# ff h# ff ; + fload ${BP}/cpu/x86/pc/lxdevel/devices.fth
[ifdef] rom-loaded
Modified: cpu/x86/pc/olpc/devices.fth =================================================================== --- cpu/x86/pc/olpc/devices.fth 2008-06-20 23:37:28 UTC (rev 837) +++ cpu/x86/pc/olpc/devices.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -79,29 +79,36 @@ ; warning !
-0 0 dropin-base <# u#s u#> " /" begin-package +\ Create the top-level device node to access the entire boot FLASH device +0 0 " fff00000" " /" begin-package " flash" device-name
- h# 10.0000 - dup value /device - constant /device-phys + h# 10.0000 value /device + h# 10.0000 constant /device-phys my-address my-space /device-phys reg - fload ${BP}/cpu/x86/pc/flashpkg.fth + fload ${BP}/dev/flashpkg.fth + fload ${BP}/dev/flashwrite.fth +end-package
- : init ( comp$ /device -- ) - to /device 2>r - 0 0 encode-bytes - 2r> encode-string encode+ - " rom" encode-string encode+ - " compatible" property -[ifdef] enable-flash-select - /device /device-phys <> if enable-flash-select then -[then] - ; +\ Create a node below the top-level FLASH node to accessing the portion +\ containing the dropin modules +0 0 " 10000" " /flash" begin-package + " dropins" device-name
+ h# c0000 constant /device + fload ${BP}/dev/subrange.fth end-package -" rom" dropin-base <# u#s " /flash@" hold$ u#> $devalias
+devalias dropins /dropins + +\ Create a pseudo-device that presents the dropin modules as a filesystem. +0 0 " " " /" begin-package + fload ${BP}/ofw/fs/dropinfs.fth +end-package + +\ This devalias lets us say, for example, "dir rom:" +devalias rom /dropin-fs + fload ${BP}/cpu/x86/forthint.fth \ Low-level interrupt handling code fload ${BP}/dev/isa/irq.fth \ ISA interrupt dispatcher fload ${BP}/cpu/x86/pc/isatick.fth \ Use ISA timer as the alarm tick timer @@ -156,22 +163,11 @@ devalias nand /nandflash devalias mtd /nandflash
-[ifdef] pseudo-nvram -fload ${BP}/cpu/x86/pc/biosload/filenv.fth -dev /file-nvram -: floppy-nv-file ( -- ) " a:\nvram.dat" ; -' floppy-nv-file to nv-file -device-end -stand-init: Pseudo-NVRAM - " /file-nvram" open-dev to nvram-node - nvram-node 0= if - ." The configuration EEPROM is not working" cr - then - ['] init-config-vars catch drop -; -[then] +[ifdef] use-null-nvram +\ For not storing configuration variable changes across reboots ... +\ This is useful for "turnkey" systems where configurability would +\ increase support costs.
-[ifdef] use-null-nvram fload ${BP}/cpu/x86/pc/nullnv.fth stand-init: Null-NVRAM " /null-nvram" open-dev to nvram-node @@ -179,6 +175,24 @@ ; [then]
+[ifdef] use-flash-nvram +\ For configuration variables stored in a sector of the boot FLASH ... + +\ Create a node below the top-level FLASH node to access the portion +\ containing the configuration variables. +0 0 " d0000" " /flash" begin-package + " nvram" device-name + + h# 10000 constant /device + fload ${BP}/dev/subrange.fth +end-package + +stand-init: NVRAM + " /nvram" open-dev to nvram-node + ['] init-config-vars catch drop +; +[then] + \ Create the alias unless it already exists : $?devalias ( alias$ value$ -- ) 2over not-alias? if $devalias exit then ( alias$ value$ alias$ )
Added: dev/flashpkg.fth =================================================================== --- dev/flashpkg.fth (rev 0) +++ dev/flashpkg.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -0,0 +1,107 @@ +purpose: Package for FLASH ROM device +\ See license at end of file + +headerless +0 value device-base +0 value open-count +0 instance value seek-ptr + +: clip-size ( adr len -- len' adr len' ) + seek-ptr + /device min seek-ptr - ( adr len' ) + tuck +; +: update-ptr ( len' -- len' ) dup seek-ptr + to seek-ptr ; + +headers +external +: seek ( d.offset -- status ) + 0<> over /device u> or if drop true exit then \ Seek offset too big + to seek-ptr + false +; + +: open ( -- flag ) + \ This lets us open the node during compilation + standalone? 0= if true exit then + + open-count dup 1+ to open-count 0= if ( ) +[ifdef] eprom-va + eprom-va +[else] + my-address my-space /device " map-in" $call-parent +[then] + to device-base + then ( ) + 0 to seek-ptr ( ) + true ( true ) +; +: close ( -- ) + \ This lets us open the node during compilation + standalone? 0= if exit then + + open-count dup 1- 0 max to open-count ( old-count ) +[ifdef] eprom-va + drop +[else] + 1 = if device-base /device " map-out" $call-parent then +[then] +; +: size ( -- d.size ) /device u>d ; +: read ( adr len -- actual ) + clip-size ( len' adr len' ) + seek-ptr device-base + -rot ( len' device-adr adr len' ) + move ( len' ) + update-ptr ( len' ) +; + +0 [if] +\ Write support is complicated by the need to erase before +\ writing and the possibly-different erase and write granularity. +\ +\ For NOR FLASH, where you can write as many times as you want +\ while turning 1's into 0's, the algorithm is: +\ +\ Break the entire write range into pieces each contained in one +\ erase unit. For each piece: +\ +\ Compare the existing and new contents to see if the unit needs erasing +\ +\ If no bits need to go from 0 to 1, erase is unnecessary, so just write. +\ (It's a little more complicated if the write granularity is >1 byte.) +\ +\ Otherwise, copy the existing contents of the erase unit to a buffer, +\ merge in the new data, erase, then write back the buffer. +[then] + +\ These permit subordinate nodes for subranges of the device, for +\ purposes like dropin driver collections, configuration variables, etc. +1 " #address-cells" integer-property + +: decode-unit ( adr len -- phys ) push-hex $number if 0 then pop-base ; +: encode-unit ( phys -- adr len ) push-hex (u.) pop-base ; +: map-in ( offset size -- virt ) drop device-base + ; +: map-out ( virt size -- virt ) 2drop ; + +\ LICENSE_BEGIN +\ Copyright (c) 2008 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
Added: dev/flashrb.fth =================================================================== --- dev/flashrb.fth (rev 0) +++ dev/flashrb.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -0,0 +1,106 @@ +purpose: Driver for storing reboot info in a FLASH sector +\ See license at end of file + +\ This device is subordinate to the "flash" device node. +\ It accesses reboot information stored in a FLASH sector. + +\ The reboot information could be updated on every system reboot. To +\ extend the lifetime of the FLASH, we use an incremental writing strategy +\ that minimizes the number of times that the sector must be rewritten. +\ It works as follows: +\ +\ The sector contains all h# ff bytes when it is completely erased. +\ If it contains all ff's, this is a normal boot, not a reboot. +\ Otherwise, the first non-ff byte is the reboot count byte. If that +\ count byte is 0, this is a normal boot, not a reboot. +\ Otherwise, this is a reboot, and the count-1 following bytes +\ are the reboot argument string. (If count is 1, this is a reboot with +\ a null argument string.) +\ When the firmware reads the reboot info during the reboot process, it sets +\ the count byte to zero (which can be done without erasing the sector), thus +\ cancelling the reboot information. +\ To initiate a new reboot, the driver places the new count and argument +\ string before the old one. The driver erases the entire sector only +\ when it fills up so there isn't enough space for the new string. + +" reboot-info" device-name + +\ Requires that /device be defined externally +my-address my-space /device reg + +: sector-buf ( -- adr ) " 'base-adr" $call-parent my-space + ; + +external +: open ( -- flag ) true ; +: close ( -- ) ; + +: reboot-byte ( -- adr byte ) + sector-buf /device 0 do ( adr ) + dup c@ h# ff <> if ( adr ) + dup c@ unloop exit ( adr byte ) + then ( adr ) + 1+ ( adr' ) + loop ( adr ) + 0 ( adr byte ) +; + +: write-byte ( byte offset -- ) + my-space + " write-byte" $call-parent + " read-mode" $call-parent +; +: write-bytes ( adr offset len -- ) + swap my-space + swap " write-bytes" $call-parent +; + +: erase-sector ( -- ) my-space " sector-erase" $call-parent ; + +: find-offset ( len -- actual offset ) + /device min ( actual ) + reboot-byte drop sector-buf - ( actual last-offset ) + over - ( actual new-offset ) + dup 0< if ( actual new-offset ) + drop erase-sector ( actual ) + /device over - ( actual offset ) + then ( actual offset ) +; + +: read ( adr len -- actual ) + reboot-byte ( adr len reboot-adr count ) + dup 0= if 4drop -1 exit then ( adr len reboot-adr count ) + 0 2 pick sector-buf - write-byte ( adr len reboot-adr count ) + 1 /string rot min ( adr reboot-adr' actual ) + >r swap r@ move r> ( reboot-adr actual ) +; + +: write ( adr len -- actual ) + 1+ find-offset ( adr actual+1 offset ) + 2dup write-byte ( adr actual+1 offset ) + swap 1 /string ( adr offset+1 actual ) + dup >r write-bytes ( r: actual ) + r> +; +: size ( -- d ) /device 0 ; + +\ LICENSE_BEGIN +\ Copyright (c) 2008 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
Added: dev/flashwrite.fth =================================================================== --- dev/flashwrite.fth (rev 0) +++ dev/flashwrite.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -0,0 +1,104 @@ +0 [if] +\ Write support is complicated by the need to erase before +\ writing and the possibly-different erase and write granularity. +\ +\ For NOR FLASH, where you can write as many times as you want +\ while turning 1's into 0's, the algorithm is: +\ +\ Break the entire write range into pieces each contained in one +\ erase unit. For each piece: +\ +\ Compare the existing and new contents to see if the unit needs erasing +\ +\ If no bits need to go from 0 to 1, erase is unnecessary, so just write. +\ (It's a little more complicated if the write granularity is >1 byte.) +\ +\ Otherwise, copy the existing contents of the erase unit to a buffer, +\ merge in the new data, erase, then write back the buffer. +[then] + +\ dev /flash + +[ifndef] flash-write-enable +also forth definitions +defer flash-write-enable ( -- ) +defer flash-write-disable ( -- ) +defer flash-erase-block ( offset -- ) +defer flash-write ( adr len offset -- ) +defer flash-read ( adr len offset -- ) +defer flash-verify ( adr len offset -- ) +h# 10.0000 value /flash +h# 10000 value /flash-block +previous definitions +[then] + + +: left-in-block ( len offset -- #left ) + \ Determine how many bytes are left in the page containing offset + /flash-block swap /flash-block 1- and - ( len left-in-page ) + min ( #left ) +; + +: must-erase? ( adr len -- flag ) + device-base seek-ptr + ( adr len dev-adr ) + swap 0 ?do ( adr dev-adr ) + over i + c@ over i + c@ ( adr dev-adr new-byte old-byte ) + \ Must erase if a bit in old-byte is 0 and that bit in new-byte is 1 + invert and if ( adr dev-adr ) + 2drop true unloop exit + then ( adr dev-adr ) + loop ( adr dev-adr ) + 2drop false +; + +: erase+write ( adr len -- ) + dup /flash-block = if + \ If we are going to overwrite the entire block, there's no need to + \ preserve the old data. This can only happen if we are already + \ aligned on an erase block boundary. + seek-ptr flash-erase-block ( adr len ) + seek-ptr flash-write ( ) + else + \ Allocate a buffer to save the old block contents + /flash-block alloc-mem >r ( adr len ) + + seek-ptr /flash-block round-down ( adr len block-start ) + + \ Copy existing data from FLASH block to the buffer + dup device-base + r@ /flash-block lmove ( adr len block-start ) + + \ Merge new bytes into the buffer + -rot ( block-start adr len ) + seek-ptr /flash-block mod ( block-start adr len buf-offset ) + r@ + swap move ( block-start ) + + \ Erase the block and rewrite it from the buffer + dup flash-erase-block ( block-start ) + r@ /flash-block rot flash-write ( ) + + \ Release the buffer + r> /flash-block free-mem + then +; + +: handle-block ( adr len -- adr' len' ) + dup seek-ptr left-in-block ( adr len #left ) + >r ( adr len r: #left ) + over r@ must-erase? if ( adr len r: #left ) + over r@ erase+write ( adr len r: #left ) + else ( adr len r: #left ) + over r@ seek-ptr flash-write ( adr len r: #left ) + then ( adr len r: #left ) + seek-ptr r@ + to seek-ptr ( adr len r: #left ) + r> /string ( adr' len' ) +; + +: write ( adr len -- #written ) + flash-write-enable + tuck ( len adr len ) + begin dup while handle-block repeat ( len adr' remain' ) + 2drop ( len ) + flash-write-disable +; + +\ dend
Modified: dev/geode/lpcflash.fth =================================================================== --- dev/geode/lpcflash.fth 2008-06-20 23:37:28 UTC (rev 837) +++ dev/geode/lpcflash.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -1,20 +1,22 @@ \ See license at end of file. -purpose: LPC/FWH FLASH writer. This assumes a 1 MiB device. +purpose: LPC/FWH FLASH writer.
: geode-lpc-write-enable ( -- ) h# 1808 rdmsr h# ff.ffff and h# 2100.0000 or h# 1808 wrmsr ; +: geode-lpc-write-disable ( -- ) + h# 1808 rdmsr h# ff.ffff and h# 2500.0000 or h# 1808 wrmsr +;
h# 1.0000 constant /lpc-block h# fff0.0000 constant lpc-flash-base
-: ?lpc ( -- ) +: lpc-flash-write-enable ( -- ) h# ffbc.0000 c@ ( id0 ) dup 0= swap h# ff = or abort" LPC FLASH not present" geode-lpc-write-enable ;
- : >lpc-adr ( offset -- ) lpc-flash-base + ; : lpc-jedec! ( byte -- ) h# 5555 >lpc-adr c! ;
@@ -45,34 +47,115 @@ lpc-wait-toggle ;
-: lpc-write-block ( adr len offset -- ) - dup lpc-erase-block ( adr len offset ) +: lpc-flash-read ( adr len offset -- ) + lpc-flash-base + -rot move +; +: lpc-flash-verify ( adr len offset -- ) + lpc-flash-base + -rot comp + abort" LPC FLASH verify failed" +; + +: lpc-flash-write ( adr len offset -- ) -rot bounds ?do ( offset ) i c@ over lpc! 1+ ( offset' ) loop ( offset ) drop ; +: lpc-write-block ( adr len offset -- ) + dup lpc-erase-block ( adr len offset ) + lpc-flash-write +;
-: lpc-reflash ( -- ) \ Flash from data already in memory - ?file +\ Create defer words for generic FLASH writing routines if necessary +[ifndef] flash-write-enable +defer flash-write-enable ( -- ) +defer flash-write-disable ( -- ) +defer flash-write ( adr len offset -- ) +defer flash-read ( adr len offset -- ) +defer flash-verify ( adr len offset -- ) +defer flash-erase-block ( offset -- ) +h# 10.0000 value /flash-block +h# 10000 value /flash-block +[then]
-[ifdef] crc2-offset - \ Insert another CRC, this time including the mfg data - flash-buf /flash crc ( crc ) - flash-buf /flash + crc2-offset - l! ( ) +\ Install the LPC FLASH versions as their implementations. + +: use-lpc-flash ( -- ) + ['] lpc-flash-write-enable to flash-write-enable + ['] geode-lpc-write-disable to flash-write-disable + ['] lpc-flash-write to flash-write + ['] lpc-flash-read to flash-read + ['] lpc-flash-verify to flash-verify + ['] lpc-erase-block to flash-erase-block + h# 8.0000 to /flash \ Should be determined dynamically + /lpc-block to /flash-block +; +use-lpc-flash + +[ifndef] reflash +\ Simple UI for reflashing, assuming that you want to overwrite +\ the entire FLASH contents. That's not always a good assumption; +\ some systems use certain FLASH blocks for persistent data like +\ configuration variables or manufacturing data ("Vital Product Data"). + +[ifdef] load-base +: flash-buf load-base ; +[else] +/flash buffer: flash-buf [then] +0 value file-loaded?
- ?lpc +: ?image-valid ( len -- ) + /flash <> abort" Image file is the wrong length" +; + +: $get-file ( "filename" -- ) + $read-open + flash-buf /flash ifd @ fgets ( len ) + ifd @ fclose + + ?image-valid + + true to file-loaded? +; + +: ?file ( -- ) + file-loaded? 0= if + ." You must first load a valid FLASH image file with" cr + ." get-file filename" cr + abort + then +; + +: reflash ( -- ) \ Flash from data already in memory + ?file + + flash-write-enable ." Writing" cr
/flash 0 ?do (cr i . - flash-buf i + /lpc-block i lpc-write-block ( ) - /lpc-block +loop + flash-buf i + /flash-block i flash-write ( ) + /flash-block +loop + + flash-write-disable ;
-: lpc-flash ( ["filename"] -- ) get-file lpc-reflash ; +\ Set this defer word to return a string naming the default +\ filename for firmware updates +defer fw-filename$ ' null$ to fw-filename$
+: get-file ( ["filename"] -- ) + parse-word ( adr len ) + dup 0= if 2drop fw-filename$ then ( adr len ) + ." Reading " 2dup type cr ( adr len ) + $get-file +; + +: flash ( ["filename"] -- ) get-file reflash ; +[then] + + \ LICENSE_BEGIN \ Copyright (c) 2006 FirmWorks \
Modified: dev/olpc/spiflash/flashec.fth =================================================================== --- dev/olpc/spiflash/flashec.fth 2008-06-20 23:37:28 UTC (rev 837) +++ dev/olpc/spiflash/flashec.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -13,8 +13,7 @@
/ec <> abort" EC image file is the wrong length"
- spi-start - spi-identify .spi-id cr + flash-write-enable
\ merge-mfg-data
Modified: dev/olpc/spiflash/spiflash.fth =================================================================== --- dev/olpc/spiflash/spiflash.fth 2008-06-20 23:37:28 UTC (rev 837) +++ dev/olpc/spiflash/spiflash.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -310,8 +310,33 @@ then ;
+: spi-flash-write-enable ( -- ) spi-start spi-identify .spi-id cr ;
+\ Create defer words for generic FLASH writing routines if necessary +[ifndef] flash-write-enable +defer flash-write-enable ( -- ) +defer flash-write-disable ( -- ) +defer flash-write ( adr len offset -- ) +defer flash-read ( adr len offset -- ) +defer flash-verify ( adr len offset -- ) +defer flash-erase-block ( offset -- ) +h# 10.0000 value /flash-block +h# 10000 value /flash-block +[then]
+\ Install the SPI FLASH versions as their implementations. +: use-spi-flash ( -- ) + ['] spi-flash-write-enable to flash-write-enable + ['] spi-reprogrammed to flash-write-disable + ['] write-spi-flash to flash-write + ['] read-spi-flash to flash-read + ['] verify-spi-flash to flash-verify + ['] erase-spi-block to flash-erase-block + h# 10.0000 to /flash + /spi-eblock to /flash-block +; +use-spi-flash + 0 [if] \ Command support by device \ Numbers are #address_bytes, #dummy_bytes, #data_bytes
Modified: dev/olpc/spiflash/spiui.fth =================================================================== --- dev/olpc/spiflash/spiui.fth 2008-06-20 23:37:28 UTC (rev 837) +++ dev/olpc/spiflash/spiui.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -7,24 +7,26 @@ \ access the FLASH device are defined elsewhere.
h# 4000 constant /chunk \ Convenient sized piece for progress reports -h# 100000 constant /flash -h# 10000 constant /flash-block \ Size of erase block
+[ifdef] use-flash-nvram +h# d.0000 constant nvram-offset +[then] + h# e.0000 constant mfg-data-offset mfg-data-offset /flash-block + constant mfg-data-end-offset
: write-flash-range ( adr end-offset start-offset -- ) ." Erasing" cr 2dup ?do - i .x (cr i erase-spi-block - /spi-eblock +loop ( adr end start ) - cr ( adr end start ) + i .x (cr i flash-erase-block + /flash-block +loop ( adr end start ) + cr ( adr end start )
." Writing" cr ?do ( adr ) - i .x (cr ( adr ) - dup /chunk i write-spi-flash ( adr ) - /chunk + ( adr' ) + i .x (cr ( adr ) + dup /chunk i flash-write ( adr ) + /chunk + ( adr' ) /chunk +loop ( adr ) cr drop ( ) ; @@ -33,7 +35,7 @@ ." Verifying" cr ?do ( adr ) i .x (cr - dup i + /chunk i verify-spi-flash + dup i + /chunk i flash-verify /chunk +loop ( adr ) cr drop ( ) ; @@ -85,6 +87,10 @@
flash-buf mfg-data-offset + /flash-block ['] ?erased catch abort" Firmware image has data in the manufacturing data block" +[ifdef] use-flash-nvram + flash-buf nvram-offset + /flash-block ['] ?erased catch + abort" Firmware image has data in the NVRAM block" +[then] ;
: $get-file ( "filename" -- ) @@ -109,7 +115,7 @@ writing /flash 0 do i .x (cr - flash-buf i + /chunk i read-spi-flash + flash-buf i + /chunk i flash-read /chunk +loop flash-buf /flash ofd @ fputs ofd @ fclose @@ -162,11 +168,11 @@ 2dup ifd @ fgets drop ( adr len ) ifd @ fclose
- spi-start spi-identify - mfg-data-offset erase-spi-block ( adr len ) + flash-write-enable + mfg-data-offset flash-erase-block ( adr len ) mfg-data-end-offset over - ( adr len offset ) - write-spi-flash ( ) - spi-reprogrammed ( ) + flash-write ( ) + flash-write-disable ( ) ;
[then] @@ -177,16 +183,16 @@ flash-base -1 = if \ Read the manufacturing data from the other FLASH \ First try the new location in the e.0000 block - flash-buf mfg-data-offset + /flash-block mfg-data-offset read-spi-flash + flash-buf mfg-data-offset + /flash-block mfg-data-offset flash-read
- \ If there is no mfg data in the e.000 block, get whatever is in the + \ If there is no mfg data in the e.0000 block, get whatever is in the \ last 2K of the 0 block, where the mfg data used to live. flash-buf mfg-data-end-offset + invalid-tag? if flash-buf mfg-data-offset + /flash-block h# ff erase
flash-buf mfg-data-end-offset + h# 800 - h# 800 ( adr len ) mfg-data-end-offset h# 800 - ( adr len offset ) - read-spi-flash ( ) + flash-read ( ) then exit then @@ -202,9 +208,9 @@ 2dup 2>r move 2r> ( ram-adr len )
\ Write from the memory buffer to the FLASH - mfg-data-offset erase-spi-block ( ram-adr len ) + mfg-data-offset flash-erase-block ( ram-adr len ) mfg-data-end-offset over - ( ram-adr len offset ) - write-spi-flash ( ) + flash-write ( ) else \ Copy the entire block containing the manufacturing data into the \ memory buffer. This make verification easier. @@ -216,7 +222,11 @@ ;
: write-firmware ( -- ) +[ifdef] use-flash-nvram + flash-buf nvram-offset 0 write-flash-range \ Write first part +[else] flash-buf mfg-data-offset 0 write-flash-range \ Write first part +[then]
\ Don't write the block containing the manufacturing data
@@ -232,10 +242,8 @@
: reflash ( -- ) \ Flash from data already in memory ?file - spi-start + flash-write-enable
- spi-identify .spi-id cr - ?move-mfg-data
write-firmware @@ -247,7 +255,7 @@ write-firmware verify then - spi-reprogrammed + flash-write-disable else .verify-msg then @@ -301,20 +309,20 @@ 0 [if] \ Erase the first block containing the EC microcode. This is dangerous...
-: erase-spi-ec ( -- ) 0 erase-spi-block ; +: erase-ec ( -- ) 0 flash-erase-block ; \ Erase everything after the first sector, thus preserving \ the EC microcode in the first sector.
-: erase-spi-firmware ( -- ) - h# 100000 /spi-eblock do (cr i .x i erase-spi-block /spi-eblock +loop cr +: erase-firmware ( -- ) + h# 100000 /flash-block do (cr i .x i flash-erase-block /flash-block +loop cr ;
: reprogram-firmware ( adr len -- ) check-firmware-image ( adr len ) - /spi-eblock /string ( adr+ len- ) \ Remove EC ucode from the beginning + /flash-block /string ( adr+ len- ) \ Remove EC ucode from the beginning ." Erasing ..." cr erase-spi-firmware ( adr len ) - ." Programming..." 2dup /spi-eblock write-spi-flash cr ( adr len ) - ." Verifying..." /spi-eblock verify-spi-flash cr ( ) + ." Programming..." 2dup /flash-block flash-write cr ( adr len ) + ." Verifying..." /flash-block flash-verify cr ( ) ;
: flash-bios ( -- )
Added: dev/subrange.fth =================================================================== --- dev/subrange.fth (rev 0) +++ dev/subrange.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -0,0 +1,64 @@ +purpose: Device that represents a subrange of its parent +\ See license at end of file + +\ This is device that accesses a subrange of its parent's address space + +\ /device must be defined externally as the length of the subrange +\ my-space is the base of the subrange +my-address my-space /device reg + +0 value offset \ seek pointer + +: clip-size ( adr len -- adr actual ) + offset + /device min offset - ( adr actual ) +; +: update-ptr ( actual -- actual ) dup offset + to offset ; + +: seek-parent ( n -- ) my-space + u>d " seek" $call-parent drop ; + +external +: open ( -- flag ) 0 to offset true ; +: close ( -- ) ; + +: seek ( d.offset -- status ) + 0<> over /device u> or if drop true exit then \ Seek offset too large + to offset + false +; +: read ( adr len -- actual ) + clip-size ( adr actual ) + offset seek-parent ( adr actual ) + " read" $call-parent ( actual ) + update-ptr +; +: write ( adr len -- actual ) + clip-size ( adr actual ) + offset seek-parent ( adr actual ) + " write" $call-parent ( actual ) + update-ptr +; +: size ( -- d ) /device 0 ; + +\ LICENSE_BEGIN +\ Copyright (c) 2008 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: ofw/confvar/nameval.fth =================================================================== --- ofw/confvar/nameval.fth 2008-06-20 23:37:28 UTC (rev 837) +++ ofw/confvar/nameval.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -20,9 +20,9 @@ \ Generic version that just looks for an obviously broken initial name : (config-checksum?) ( -- flag ) cv-area drop d# 32 bounds ?do ( ) - \ Good if we encounter an "=" or a null before an unprintable character - i c@ dup 0= swap [char] = = or if unloop true exit then - \ Bad if we encounter an unprintable character before the first = or \0 + \ Good if we encounter '=' or \0 or ff before an unprintable character + i c@ dup 0= over [char] = = or swap h# ff = or if unloop true exit then + \ Bad if we encounter an unprintable character before the first = or \0 or ff i c@ bl 1+ h# 7f within 0= if unloop false exit then loop \ Bad if the first name is too long @@ -35,6 +35,7 @@
: another-ge-var? ( adr len -- false | adr' len' value$ name$ true ) dup 0= if 2drop false exit then ( adr len ) + over c@ h# ff = if 2drop false exit then ( adr len ) 0 left-parse-string ( adr' len' var$ ) dup 0= if 4drop false exit then ( adr' len' var$ ) [char] = left-parse-string ( adr' len' value$ name$ ) @@ -76,14 +77,20 @@ \ Clear the new piece at the top (from name+(top-rem) to top) 2 pick - over + ( rem-adr name-adr name+top-rem ) -rot - ( name+top-rem rem-name ) - erase + h# ff fill ; : ?delete-ge-var ( $name -- ) find-ge-var 0= if delete-ge-var then ; : find-available ( -- adr len ) - cv-area - begin 0 left-parse-string while drop repeat ( rem$ adr ) + cv-area begin ( rem$ ) + dup if ( rem$ ) + over c@ h# ff = if ( rem$ ) + exit + then ( rem$ ) + then ( rem$ ) + 0 left-parse-string ( rem$ env$ ) + while drop repeat ( rem$ adr ) -rot + over - ( adr len ) ; : (cv-unused) ( -- len ) find-available nip ; @@ -108,7 +115,8 @@ tuck r@ swap move ( $value name-len ) r> + [char] = over c! 1+ ( $value nv-value-adr ) 2dup 2>r swap move 2r> ( value-len nv-value-adr ) - over + 0 over c! ( value-len terminator-adr ) + over + 1- ( value-len last-char-adr ) +\ over + 0 over c! ( value-len terminator-adr ) update-modified-adr ( value-len ) then ( value-len | -1 ) ; @@ -134,8 +142,10 @@ ' show-ge-var to show-extra-env-var \ Install in user interface
: clear-ge-vars ( -- ) - cv-area erase - cv-area bounds update-modified-adr update-modified-adr + cv-area h# ff fill + \ The 1- is necessary because update-modified-adr refers to + \ a byte that is touched, not the one just after it. + cv-area bounds update-modified-adr 1- update-modified-adr ; ' clear-ge-vars to erase-user-env-vars
@@ -195,7 +205,7 @@ : clear-nvram ( -- ) config-rw 0 update-modified-range drop config-size update-modified-range drop - config-mem config-size erase + config-mem config-size h# ff fill set-mfg-defaults config-ro init-modified-range
Modified: ofw/core/ofwcore.fth =================================================================== --- ofw/core/ofwcore.fth 2008-06-20 23:37:28 UTC (rev 837) +++ ofw/core/ofwcore.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -4516,7 +4516,7 @@ partial-headers : open-drop-in ( -- 0 ) di-count dup 1+ to di-count 0= if - " rom" open-dev to rom-dev + " dropins" open-dev to rom-dev else 0 seek-rom then
Modified: ofw/fs/dropinfs.fth =================================================================== --- ofw/fs/dropinfs.fth 2008-06-20 23:37:28 UTC (rev 837) +++ ofw/fs/dropinfs.fth 2008-06-24 23:14:57 UTC (rev 838) @@ -1,14 +1,19 @@ +purpose: Present dropins as a filesystem \ See license at end of file -purpose: Support package for "dropin file system"
+0 0 " " " /" begin-package +" dropin-fs" name + headerless 0 instance value base-adr 0 instance value image-size +0 value open-count +false value written? 0 instance value seek-ptr -0 instance value offset
-: clip-size ( adr len -- adr len' ) - seek-ptr + image-size umin seek-ptr - +: clip-size ( adr len -- len' adr len' ) + seek-ptr + image-size min seek-ptr - ( adr len' ) + tuck ; : update-ptr ( len' -- len' ) dup seek-ptr + to seek-ptr ;
@@ -17,98 +22,45 @@ : seek ( d.offset -- status ) 0<> over image-size u> or if drop true exit then \ Seek offset too big to seek-ptr - seek-ptr offset + 0 " seek" $call-parent + false ; -: size ( -- d.size ) image-size 0 ; -: read ( adr len -- actual ) - clip-size ( adr len' ) - " read" $call-parent ( len' ) - update-ptr ( len' ) -;
-d# 32 buffer: di-buffer +: open ( -- flag ) + \ This lets us open the node during compilation + standalone? 0= if true exit then
-\ ID of the header that's currently in the buffer --1 instance value header-id - -: difield \ name ( offset -- offset' ) - create over , + does> @ di-buffer + + 0 to base-adr + 0 to seek-ptr ( ) + my-args dup if ( adr len ) + 2dup " " $= 0= if ( adr len ) + over c@ [char] \ = if 1 /string then ( adr' len' ) + find-drop-in dup if ( di-adr di-len true ) + -rot to image-size to base-adr ( true ) + then ( flag ) + exit ( flag ) + then ( adr len ) + then ( adr len ) + 2drop ( ) + false ; +: close ( -- ) + \ This lets us open the node during compilation + standalone? 0= if exit then
-d# 16 constant max-di-name -struct - /l difield di-magic - /l difield di-size - /l difield di-sum - /l difield di-expansion -max-di-name difield di-name -constant /di-header - -: load ( adr -- len ) 0 0 seek drop image-size read ; - -: ?get-header ( id -- id ) - dup header-id <> if ( id ) - dup /di-header - 0 seek drop ( id ) - di-buffer /di-header read drop ( id ) - dup to header-id ( id ) - then ( id ) + base-adr 0<> if base-adr image-size release-dropin then ; - -: di-magic? ( -- flag ) di-magic 4 " OBMD" $= ; -: first-header ( -- id ) - d# 2000 /di-header do - i ?get-header drop - di-magic? if i unloop exit then - /di-header +loop - 0 +: size ( -- d.size ) image-size u>d ; +: read ( adr len -- actual ) + clip-size ( len' adr len' ) + seek-ptr base-adr + -rot ( len' device-adr adr len' ) + move ( len' ) + update-ptr ( len' ) ; - -: another-dropin? ( id -- false | id' true ) - ?dup if ( id ) \ Not the first call - ?get-header ( id ) \ Get the old header into the buffer - di-size be-l@ + ( id+ ) \ Skip the old dropin - 4 round-up ( id' ) \ Finish skipping - /di-header + ( id' ) \ Set ID to image offset - ?get-header ( id' ) \ Get the new header - else ( ) - first-header ( id' ) - then ( id' ) - - di-magic? dup 0= if nip then +: load ( adr -- len ) + base-adr swap image-size move image-size ; - -headerless -: find-drop-in ( name-adr,len -- false | drop-in-adr,len true ) - 0 ( name-adr,len id ) - begin another-dropin? while ( name-adr,len id ) - 2 pick 2 pick ( name-adr,len id name-adr,len ) - di-name cscount $= if ( name-adr,len id ) - nip nip ( id ) - di-size be-l@ true ( adr len true ) - exit - then ( name-adr,len id ) - repeat ( name-adr,len ) - 2drop false -; - -: open ( -- flag ) - -1 to image-size 0 to offset - my-args 2dup " " $= if ( adr len ) - 2drop ( ) - true exit ( true ) - else ( adr len ) - over c@ [char] \ = if 1 /string then ( adr' len' ) - find-drop-in dup if ( di-adr di-len true ) - -rot to image-size to offset ( true ) - 0. seek drop ( true ) - then ( flag ) - exit ( flag ) - then ( adr len ) - 2drop false ( false ) -; -: close ( -- ) ; - : next-file-info ( id -- false | id' s m h d m y len attributes name$ true ) + ?dup 0= if open-drop-in then ( id ) another-dropin? if ( id ) " built-time-int" $find if ( id s m h xt ) execute ( id s m h packed-date ) @@ -122,27 +74,29 @@ else ( id s m h adr len ) 2drop 0 0 0 ( id s m h d m y ) then ( id s m h d m y ) -\ di-expansion be-l@ ( id s m h d m y size ) -\ ?dup 0= if di-size be-l@ then ( id s m h d m y size ) - di-size be-l@ ( id s m h d m y size ) + di-expansion be-l@ ( id s m h d m y size ) + ?dup 0= if di-size be-l@ then ( id s m h d m y size ) o# 100444 ( id s m h d m y size attributes ) - di-name cscount max-di-name min ( id s m h d m y size attr name$ ) + di-name cscount ( id s m h d m y size attr name$ ) true ( id s m h d m y size attr name$ true ) else ( ) - false ( false ) + close-drop-in false ( false ) then ;
: free-bytes ( -- d.#bytes ) - 0 ( high-water ) + open-drop-in 0 ( high-water ) 0 begin another-dropin? while ( high-water id ) nip di-size be-l@ 4 round-up ( id size ) over + swap ( high-water' id ) repeat ( high-water ) - " size" $call-parent rot 0 d- ( d.#bytes ) + size rot 0 d- ( d.#bytes ) ; + +end-package + \ LICENSE_BEGIN -\ Copyright (c) 2006 FirmWorks +\ Copyright (c) 2008 FirmWorks \ \ Permission is hereby granted, free of charge, to any person obtaining \ a copy of this software and associated documentation files (the
openfirmware@openfirmware.info