Author: wmb Date: 2008-08-13 12:12:48 +0200 (Wed, 13 Aug 2008) New Revision: 879
Added: dev/flashui.fth dev/flashwritepkg.fth dev/lpcflash.fth Modified: cpu/x86/pc/neptune/addrs.fth cpu/x86/pc/neptune/devices.fth cpu/x86/pc/neptune/fw.bth cpu/x86/pc/neptune/msrinit.fth cpu/x86/pc/neptune/neptune.bth Log: Neptune - FLASH writing support.
Modified: cpu/x86/pc/neptune/addrs.fth =================================================================== --- cpu/x86/pc/neptune/addrs.fth 2008-08-12 08:49:21 UTC (rev 878) +++ cpu/x86/pc/neptune/addrs.fth 2008-08-13 10:12:48 UTC (rev 879) @@ -1,67 +1,18 @@ \ See license at end of file purpose: Establish address and I/O configuration definitions
-[ifdef] use-meg0 -h# f0.0000 constant dropin-base -h# 08.0000 constant dropin-size -h# 0.4000 constant fw-pa -h# f.c000 constant /fw-ram -[then] +h# fff0.0000 constant rom-pa \ Physical address of boot ROM +h# 10.0000 constant /rom \ Size of boot ROM
-[ifdef] rom-loaded -h# fff8.0000 constant rom-pa \ Physical address of boot ROM -h# 8.0000 constant /rom \ Size of boot ROM -rom-pa constant dropin-base - +h# 8.0000 constant dropin-offset +rom-pa dropin-offset + constant dropin-base h# 8.0000 constant dropin-size
dropin-base h# 20 + constant ResetBase \ Location of "reset" dropin in ROM
h# 1c0.0000 constant fw-pa h# 20.0000 constant /fw-ram -[then]
-[ifdef] linuxbios-loaded -\ h# d8.0000 constant dropin-base -h# fff2.0000 constant dropin-base \ Location of payload in FLASH -\ h# fff8.0000 constant dropin-base \ Location of payload in FLASH -dropin-base h# 80 + h# 20 + constant ResetBase \ Location of "reset" dropin in ROM -h# 08.0000 constant dropin-size -h# 1e0.0000 constant fw-pa -h# 20.0000 constant /fw-ram -h# fff0.0000 constant rom-pa -h# 10.0000 constant /rom -[then] - -[ifdef] old-bzimage-loaded -\ h# d8.0000 constant dropin-base -h# 10.0020 constant dropin-base \ RAM address where Linux normally loads -h# 08.0000 constant dropin-size -h# 20.0000 constant fw-pa -h# 20.0000 constant /fw-ram -[then] - -[ifdef] bzimage-loaded -h# 1d8.0020 constant dropin-base \ RAM address where we want to end up -h# 08.0000 constant dropin-size -h# 1e0.0000 constant fw-pa -h# 20.0000 constant /fw-ram -[then] - -[ifdef] syslinux-loaded -h# 10.1020 constant dropin-base -h# 07.e0e0 constant dropin-size -h# 20.0000 constant fw-pa -h# 20.0000 constant /fw-ram -[then] - -[ifdef] grub-loaded -h# 1b8.0000 constant dropin-base -h# 08.0000 constant dropin-size -h# 1c0.0000 constant fw-pa -h# 20.0000 constant /fw-ram -[then] - h# 80.0000 constant def-load-base \ Convenient for initrd
\ The heap starts at RAMtop, which on this system is "fw-pa /fw-ram +" @@ -100,7 +51,7 @@
fload ${BP}/cpu/x86/pc/virtaddr.fth [ifndef] virtual-mode -h# ff80.0000 to fw-virt-base \ Override the usual setting; we use an MSR to double-map some memory up high +h# fec0.0000 to fw-virt-base \ Override the usual setting; we use an MSR to double-map some memory up high h# 40.0000 to fw-virt-size [then]
Modified: cpu/x86/pc/neptune/devices.fth =================================================================== --- cpu/x86/pc/neptune/devices.fth 2008-08-12 08:49:21 UTC (rev 878) +++ cpu/x86/pc/neptune/devices.fth 2008-08-13 10:12:48 UTC (rev 879) @@ -80,23 +80,36 @@ warning !
\ Create the top-level device node to access the entire boot FLASH device -\ 0 0 " fff00000" " /" begin-package -0 0 dropin-base <# u#s u#> " /" begin-package +0 0 " fff00000" " /" begin-package " flash" device-name
h# 10.0000 value /device h# 10.0000 constant /device-phys my-address my-space /device-phys reg + + h# 40.0000 negate constant regs-offset + h# 1.0000 value block-size + + : write-enable ( -- ) + h# 1808 rdmsr h# ff.ffff and h# 2100.0000 or h# 1808 wrmsr + ; + : write-disable ( -- ) + h# 1808 rdmsr h# ff.ffff and h# 2500.0000 or h# 1808 wrmsr + ; + fload ${BP}/dev/flashpkg.fth - fload ${BP}/dev/flashwrite.fth + fload ${BP}/dev/lpcflash.fth + fload ${BP}/dev/flashwritepkg.fth end-package
+devalias flash /flash@fff00000 + \ Create a node below the top-level FLASH node to accessing the portion \ containing the dropin modules -0 0 " 00000" " /flash" begin-package +0 0 dropin-offset <# u#s u#> " /flash" begin-package " dropins" device-name
- h# 70000 constant /device + dropin-size constant /device fload ${BP}/dev/subrange.fth end-package
@@ -108,6 +121,29 @@ \ This devalias lets us say, for example, "dir rom:" devalias rom /dropin-fs
+\ Create the top-level device node to access the entire boot FLASH device +0 0 " ffe00000" " /" begin-package + " flash" device-name + + h# 10.0000 value /device + h# 10.0000 constant /device-phys + my-address my-space /device-phys reg + h# 1.0000 value block-size + + h# 40.0000 negate constant regs-offset + + : write-enable ( -- ) + h# 1808 rdmsr h# ff.ffff and h# 2100.0000 or h# 1808 wrmsr + ; + : write-disable ( -- ) + h# 1808 rdmsr h# ff.ffff and h# 2500.0000 or h# 1808 wrmsr + ; + + fload ${BP}/dev/flashpkg.fth + fload ${BP}/dev/lpcflash.fth + fload ${BP}/dev/flashwritepkg.fth +end-package + 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 @@ -259,10 +295,6 @@ dend ;
-fload ${BP}/cpu/x86/pc/neptune/lpcflash.fth - -fload ${BP}/dev/geode/lpcflash.fth \ Reflasher for PLCC FLASH on A-test - : +i encode-int encode+ ; : 0+i 0 +i ;
[ifdef] rom-loaded
Modified: cpu/x86/pc/neptune/fw.bth =================================================================== --- cpu/x86/pc/neptune/fw.bth 2008-08-12 08:49:21 UTC (rev 878) +++ cpu/x86/pc/neptune/fw.bth 2008-08-13 10:12:48 UTC (rev 879) @@ -420,15 +420,8 @@
;
-h# ffac0000 constant lpc-flash2-phys -h# 40000 constant /lpc-flash2 \ size +fload ${BP}/dev/flashui.fth
-: neptune-flash2-map - - lpc-flash2-phys /lpc-flash2 0 mmu-claim drop \ Reserve the virtual address range - lpc-flash2-phys dup /lpc-flash2 -1 mmu-map \ Create a mapping -; - : vme ( -- ) ." Running Lattice programmer " com1 io
Modified: cpu/x86/pc/neptune/msrinit.fth =================================================================== --- cpu/x86/pc/neptune/msrinit.fth 2008-08-12 08:49:21 UTC (rev 878) +++ cpu/x86/pc/neptune/msrinit.fth 2008-08-13 10:12:48 UTC (rev 879) @@ -219,7 +219,7 @@ \ msr: 5140.0012 \ LBAR_FLSH2 \ msr: 5140.0013 \ LBAR_FLSH3 \ msr: 5140.0014 00000000.80070003. \ LEG_IO already set in romreset - msr: 5140.0015 00000000.00000f7d. \ BALL_OPTS - IDE pins are IDE, not NAND + msr: 5140.0015 00000000.00000f71. \ BALL_OPTS - IDE pins are IDE, not NAND, LPC FLASH mode \ msr: 5140.001b 00000000.07770777. \ NANDF_DATA - default \ msr: 5140.001c 00000000.00000777. \ NANDF_CTL - default msr: 5140.001f 00000000.00000011. \ KEL_CTRL
Modified: cpu/x86/pc/neptune/neptune.bth =================================================================== --- cpu/x86/pc/neptune/neptune.bth 2008-08-12 08:49:21 UTC (rev 878) +++ cpu/x86/pc/neptune/neptune.bth 2008-08-13 10:12:48 UTC (rev 879) @@ -73,22 +73,22 @@ [then] " ${BP}/dev/pci/build/pcibridg.fc" " class060400" $add-deflated-dropin
- /rom h# 400 - pad-file \ rmstart image must start 0x400 from end + dropin-size h# 400 - pad-file \ rmstart image must start 0x400 from end " rmstart.img" $add-file
\ Insert the revision signature -/rom h# 40 - ofd @ fseek +dropin-size h# 40 - ofd @ fseek " DA1 ${FW_VERSION} D1${FW_MAJOR}" expand$ ofd @ fputs
/l buffer: crcbuf -/rom buffer: filebuf +dropin-size buffer: filebuf 0 ofd @ fseek
\ Read the entire image, compute the CRC, and store it h# 30 from the end -filebuf /rom ofd @ fgets /rom <> abort" Can't read back image" -0 crctab filebuf /rom ($crc) crcbuf ! +filebuf dropin-size ofd @ fgets dropin-size <> abort" Can't read back image" +0 crctab filebuf dropin-size ($crc) crcbuf !
-/rom h# 30 - ofd @ fseek +dropin-size h# 30 - ofd @ fseek crcbuf /l ofd @ fputs
ofd @ fclose
Added: dev/flashui.fth =================================================================== --- dev/flashui.fth (rev 0) +++ dev/flashui.fth 2008-08-13 10:12:48 UTC (rev 879) @@ -0,0 +1,117 @@ +purpose: Simple FLASH write user interface, calling flash node methods +\ See license at end of file. + +[ifndef] reflash +0 value flash-buf +0 value /flash +0 value /flash-block + +\ 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"). + +0 value file-loaded? + +: ?image-valid ( len -- ) + /flash <> abort" Image file is the wrong length" +; + +0 value flash-ih + +: $call-flash ( ??? -- ??? ) flash-ih $call-method ; +: close-flash ( -- ) + flash-ih if + flash-ih close-dev + 0 to flash-ih + flash-buf /flash free-mem + then +; + +: ?open-flash ( -- ) + flash-ih if exit then + + " flash" open-dev to flash-ih + flash-ih 0= abort" Can't open FLASH device" + + " writable?" $call-flash 0= if + close-flash + true abort" FLASH device is not writable" + then + + " block-size" $call-flash to /flash-block + " size" $call-flash drop to /flash + /flash alloc-mem to flash-buf +; + +: $get-flash-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 + ?open-flash + ?file + + ." Writing" cr + + /flash 0 ?do + (cr i . + flash-buf i + /flash-block i " flash-write" $call-flash ( ) + /flash-block +loop + + close-flash +; + +\ Set this defer word to return a string naming the default +\ filename for firmware updates +defer fw-filename$ ' null$ to fw-filename$ + +: get-flash-file ( ["filename"] -- ) + ?open-flash + parse-word ( adr len ) + dup 0= if 2drop fw-filename$ then ( adr len ) + ." Reading " 2dup type cr ( adr len ) + $get-flash-file +; + +: flash ( ["filename"] -- ) get-flash-file reflash ; +[then] + + +\ 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/flashwritepkg.fth =================================================================== --- dev/flashwritepkg.fth (rev 0) +++ dev/flashwritepkg.fth 2008-08-13 10:12:48 UTC (rev 879) @@ -0,0 +1,115 @@ +purpose: Support routines for NOR FLASH writing +\ See license at end of file. + +\ This defines a "write" method for NOR FLASH than handles the +\ problems that you have to erase a block before writing and +\ the erase granularity may be larger than the write granularity. +\ This is intended to be part of the implementation of a FLASH +\ device node, where lower level erase-block and flash-write +\ routines are already defined. + +\ On NOR FLASH, you can write as many times as you want as long as +\ you keep turning 1's into 0's. You only have to erase when you +\ want to make some bits go from 0 to 1. An efficient 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. + +: left-in-block ( len offset -- #left ) + \ Determine how many bytes are left in the page containing offset + block-size swap block-size 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 block-size = 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 erase-block ( adr len ) + seek-ptr flash-write ( ) + else + \ Allocate a buffer to save the old block contents + block-size alloc-mem >r ( adr len ) + + seek-ptr block-size round-down ( adr len block-start ) + + \ Copy existing data from FLASH block to the buffer + dup device-base + r@ block-size lmove ( adr len block-start ) + + \ Merge new bytes into the buffer + -rot ( block-start adr len ) + seek-ptr block-size mod ( block-start adr len buf-offset ) + r@ + swap move ( block-start ) + + \ Erase the block and rewrite it from the buffer + dup erase-block ( block-start ) + r@ block-size rot flash-write ( ) + + \ Release the buffer + r> block-size 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 ) + writable? 0= if 2drop 0 exit then + tuck ( len adr len ) + begin dup while handle-block repeat ( len adr' remain' ) + 2drop ( len ) +; + +\ 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/lpcflash.fth =================================================================== --- dev/lpcflash.fth (rev 0) +++ dev/lpcflash.fth 2008-08-13 10:12:48 UTC (rev 879) @@ -0,0 +1,104 @@ +purpose: LPC/FWH FLASH low-level write words for use inside a device node +\ See license at end of file. + +\ write-enable and write-disable need to be defined externally +\ Typically you load flashpkg.fth before and flashwritepkg.fth after this + +0 instance value regs-adr + +: unmap-regs ( -- ) + regs-adr if + regs-adr /device " map-out" $call-parent + 0 to regs-adr + write-disable + then +; + +: writable? ( -- flag ) + regs-adr if true exit then + + my-address my-space regs-offset + /device " map-in" $call-parent to regs-adr + regs-adr h# c.0000 + c@ ( id0 ) + + dup 0<> swap h# ff <> and ( writable? ) + + dup if write-enable else unmap-regs then +; + +warning @ warning off \ Intentional chained definition +: close ( -- ) unmap-regs close ; +warning ! + +: >lpc-adr ( offset -- ) device-base + ; +: jedec! ( byte -- ) h# 5555 >lpc-adr c! ; + +\ The write enable for the block at fffx.0000 is at ffbx.0002 +: write-enable-block ( offset -- ) + h# ffff invert and 2 or ( we-offset ) + regs-adr + 0 swap c! +; + +: write-setup ( -- ) h# aa jedec! h# 55 h# 2aaa >lpc-adr c! ; + +: lpc! ( byte offset -- ) + over h# ff = if 2drop exit then + >lpc-adr ( byte lpc-adr ) + write-setup h# a0 jedec! ( byte lpc-adr ) + 2dup c! ( byte lpc-adr ) + begin 2dup c@ = until 2drop ( ) +; + +: wait-toggle ( -- ) + device-base c@ ( value ) + begin device-base c@ tuck = until ( value ) + drop +; +: erase-block ( offset -- ) + dup write-enable-block + write-setup h# 80 jedec! + write-setup h# 50 swap >lpc-adr c! + wait-toggle +; + +: flash-read ( adr len offset -- ) + device-base + -rot move +; +: flash-verify ( adr len offset -- ) + device-base + -rot comp + abort" LPC FLASH verify failed" +; + +: flash-write ( adr len offset -- ) + -rot bounds ?do ( offset ) + i c@ over lpc! 1+ ( offset' ) + loop ( offset ) + drop +; +: write-block ( adr len offset -- ) + dup erase-block ( adr len offset ) + flash-write +; + +\ 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
openfirmware@openfirmware.info