Author: wmb
Date: 2007-09-18 01:15:36 +0200 (Tue, 18 Sep 2007)
New Revision: 608
Modified:
cpu/x86/pc/olpc/copynand.fth
cpu/x86/pc/olpc/nandstat.fth
Log:
save-nand now creates a .crc file .
New "scan-nand" command.
Modified: cpu/x86/pc/olpc/copynand.fth
===================================================================
--- cpu/x86/pc/olpc/copynand.fth 2007-09-17 23:09:19 UTC (rev 607)
+++ cpu/x86/pc/olpc/copynand.fth 2007-09-17 23:15:36 UTC (rev 608)
@@ -15,12 +15,16 @@
0 value crc-buf
-: >crc ( index -- crc ) crc-buf swap la+ l@ ;
+: >crc ( index -- 'crc ) crc-buf swap la+ ;
+
: $call-nand ( ?? method$ -- ?? ) nandih $call-method ;
+: close-image-file ( -- )
+ fileih ?dup if 0 to fileih close-dev then
+;
: close-nand-ihs ( -- )
- fileih ?dup if 0 to fileih close-dev 0 to #image-eblocks then
+ close-image-file
nandih ?dup if 0 to nandih close-dev 0 to #nand-pages then
crc-ih ?dup if 0 to crc-ih close-dev then
#crc-records if
@@ -118,7 +122,7 @@
;
: check-mem-crc ( record# -- )
- >crc ( crc )
+ >crc l@ ( crc )
load-base /nand-block $crc ( crc actual-crc )
2dup <> if
cr ." CRC miscompare - expected " swap . ." got " . cr
@@ -133,6 +137,9 @@
#crc-records if check-mem-crc else drop then
;
+defer show-init ( #eblocks -- )
+' drop to show-init
+
defer show-erasing ( #blocks -- )
: (show-erasing) ( #blocks -- ) ." Erasing " . ." blocks" cr ;
' (show-erasing) to show-erasing
@@ -151,17 +158,26 @@
' drop to show-clean
defer show-cleaning ( -- )
-: (show-cleaning) ( -- ) cr ." Cleanmarkers" cr ;
+: (show-cleaning) ( -- ) cr ." Cleanmarkers" ;
' (show-cleaning) to show-cleaning
defer show-writing ( #blocks -- )
: (show-writing) ." Writing " . ." blocks" cr ;
' (show-writing) to show-writing
+defer show-pending ( block# -- )
+' drop to show-pending
+
defer show-written
: (show-written) ( block# -- ) (cr . ;
' (show-written) to show-written
+defer show-strange
+' drop to show-strange
+
+defer show-done
+' cr to show-done
+
: copy-nand ( "devspec" -- )
open-nand
get-img-filename
@@ -170,7 +186,9 @@
['] noop to show-progress
- #nand-pages nand-pages/block / show-erasing
+ #nand-pages nand-pages/block / dup show-init ( #eblocks )
+
+ show-erasing ( )
['] show-bad ['] show-erased ['] show-bbt-block " (wipe)" $call-nand
#image-eblocks show-writing
@@ -185,6 +203,7 @@
show-cleaning
['] show-clean " put-cleanmarkers" $call-nand
+ show-done
close-nand-ihs
;
@@ -243,7 +262,7 @@
load-base " read-next-block" $call-nand ( )
- load-base /nand-block $crc i >crc ( actual-crc expected-crc )
+ load-base /nand-block $crc i >crc l@ ( actual-crc expected-crc )
2dup <> if ( actual-crc expected-crc )
cr ." CRC miscompare - expected " . ." got " . ( )
." in NAND block starting at page "
@@ -264,44 +283,101 @@
;
true value dump-oob?
-: (dump-nand) ( "devspec" -- )
- open-nand
- safe-parse-word ( name$ )
+: make-new-file ( devspec$ -- fileih )
+ 2dup ['] $delete catch if 2drop then ( name$ )
+ 2dup ['] $create-file catch if ( name$ x x )
+ 2drop ( name$ )
+ " Can't open a file. Try using the raw disk?" confirm if ( name$ )
+ open-dev ( ih )
+ else ( name$ )
+ 2drop 0 ( ih=0 )
+ then ( ih )
+ else ( name$ ih )
+ nip nip ( ih )
+ then ( ih )
+;
- cr ." Dumping to " 2dup type cr
+: alloc-crc-buf ( -- )
+ #nand-pages nand-pages/block / to #crc-records
+ #crc-records /l* alloc-mem to crc-buf
+;
- 2dup ['] $delete catch if 2drop then ( name$ )
- 2dup ['] $create-file catch if
- 2drop
- " Can't open a file. Try using the raw disk?" confirm if
- open-file
- else
- 2drop 0
+: save-crcs ( -- )
+ image-name$ crc-name-buf place
+ true
+ crc-name$ nip 4 >= if
+ crc-name$ + 4 - c@ [char] . = if
+ " crc" crc-name$ + 3 - swap move
+ drop false
then
- then
- to fileih
+ then ( error? )
+ " Filename needs a 3-character extension" ?nand-abort
+ crc-name$ ( name$ )
+ ." CRC file is " 2dup type ( name$ )
+
+ make-new-file to crc-ih
+
+ crc-ih 0= " Can't open CRC output file" ?nand-abort
+
+ #image-eblocks 0 ?do
+ i >crc l@
+ push-hex
+ <# newline hold u# u# u# u# u# u# u# u# u#> ( adr len )
+ pop-base
+ " write" crc-ih $call-method 9 <> " CRC write failed" ?nand-abort
+ loop
+
+;
+: open-dump-file ( devspec$ -- )
+ cr ." Dumping to " 2dup type cr
+
+ make-new-file to fileih
+
fileih 0= " Can't open output" ?nand-abort
+;
+: (dump-nand) ( "devspec" -- )
+ open-nand
+ get-img-filename
+
+ dump-oob? 0= if alloc-crc-buf then
+ image-name$ open-dump-file
+
+ 0 to #image-eblocks
+
\ The stack is empty at the end of each line unless otherwise noted
- #nand-pages 0 do
- (cr i .
+ dump-oob? if #nand-pages else " usable-page-limit" $call-nand then
+ 0 do
+ (cr i nand-pages/block / .
load-base i nand-pages/block " read-blocks" $call-nand
nand-pages/block = if
load-base /nand-block written? if
- load-base /nand-block " write" fileih $call-method drop
+ ." w"
+ load-base /nand-block " write" fileih $call-method
+ /nand-block <> " Write to dump file failed" ?nand-abort
dump-oob? if
i nand-pages/block bounds ?do
i " read-oob" $call-nand h# 40 ( adr len )
" write" fileih $call-method drop
- i pad ! pad 4 " write" fileih $call-method drop
+ h# 40 <> " Write of OOB data failed" ?nand-abort
+ i pad ! pad 4 " write" fileih $call-method
+ 4 <> " Write of eblock number failed" ?nand-abort
loop
+ else
+ load-base /nand-block $crc #image-eblocks >crc l!
then
+ #image-eblocks 1+ to #image-eblocks
+ else
+ ." s"
then
then
nand-pages/block +loop
cr ." Done" cr
+ close-image-file
+ save-crcs
+
close-nand-ihs
;
: dump-nand ( "devspec" -- ) true to dump-oob? (dump-nand) ;
Modified: cpu/x86/pc/olpc/nandstat.fth
===================================================================
--- cpu/x86/pc/olpc/nandstat.fth 2007-09-17 23:09:19 UTC (rev 607)
+++ cpu/x86/pc/olpc/nandstat.fth 2007-09-17 23:15:36 UTC (rev 608)
@@ -12,71 +12,250 @@
9 constant grid-h
d# 128 value #cols
+: xy+ ( x1 y1 x2 y2 -- x3 y3 ) rot + -rot + swap ;
: xy* ( x y w h -- x*w y*h ) rot * >r * r> ;
+0 value nand-block-limit
+
+: do-fill ( color x y w h -- ) " fill-rectangle" $call-screen ;
+
\ States: 0:erased 1:bad 2:waiting for write 3:written
-: >loc ( eblock# -- ) #cols /mod grid-w grid-h xy* ulhc d+ ;
+: >loc ( eblock# -- x y ) #cols /mod grid-w grid-h xy* ulhc xy+ ;
-: show-state ( eblock# state -- )
- swap >loc glyph-w glyph-h " fill-rectangle" $call-screen
-;
+: show-state ( eblock# state -- ) swap >loc glyph-w glyph-h do-fill ;
dev screen : erase-screen erase-screen ; dend
-h# 80 h# 80 h# 80 rgb>565 constant bbt-color
- 0 0 0 rgb>565 constant erased-color
-h# ff 0 0 rgb>565 constant bad-color
- 0 0 h# ff rgb>565 constant clean-color
-h# ff h# ff 0 rgb>565 constant writing-color
- 0 h# ff 0 rgb>565 constant written-color
-h# ff h# ff h# ff rgb>565 constant starting-color
+h# 80 h# 80 h# 80 rgb>565 constant bbt-color \ gray
+ 0 0 0 rgb>565 constant erased-color \ black
+h# ff 0 0 rgb>565 constant bad-color \ red
+ 0 0 h# ff rgb>565 constant clean-color \ blue
+h# ff h# ff 0 rgb>565 constant pending-color \ yellow
+ 0 h# ff 0 rgb>565 constant written-color \ green
+ 0 h# ff h# ff rgb>565 constant strange-color \ cyan
+h# ff h# ff h# ff rgb>565 constant starting-color \ white
-: gshow-erasing ( #eblocks -- )
- cursor-off " erase-screen" $call-screen 0 status-line at-xy
- ." Erasing "
+: gshow-init ( #eblocks -- )
+ #nand-pages nand-pages/block / to nand-block-limit
+ cursor-off " erase-screen" $call-screen
+
" bbt0" $call-nand nand-pages/block / bbt-color show-state
" bbt1" $call-nand nand-pages/block / bbt-color show-state
starting-color ( #eblocks color )
swap 0 ?do i over show-state loop
drop
+ 0 status-line at-xy
;
+: gshow-erasing ( #eblocks -- ) drop ." Erasing " ;
+
: gshow-erased ( eblock# -- ) erased-color show-state ;
: gshow-bad ( eblock# -- ) bad-color show-state ;
: gshow-bbt-block ( eblock# -- ) bbt-color show-state ;
: gshow-clean ( eblock# -- ) clean-color show-state ;
+: gshow-strange ( eblock# -- ) strange-color show-state ;
-: gshow-cleaning ( -- ) ." Cleanmarkers" cr cursor-on ;
+: gshow-cleaning ( -- ) d# 26 status-line at-xy ." Cleanmarkers" cr ;
+: gshow-done ( -- ) cursor-on ;
+: gshow-pending ( eblock# -- ) pending-color show-state ;
+
: gshow-writing ( #eblocks -- )
." Writing "
- writing-color ( #eblocks color )
- 0 rot 0 ?do ( color eblock# )
- dup nand-pages/block * " block-bad?" $call-nand 0= if ( color eblock# )
- 2dup swap show-state ( color eblock# )
- 1 ( color eblock# increment )
- else ( color eblock# )
- 0 ( color eblock# increment )
- then ( color eblock# increment )
- swap 1+ swap ( color eblock#' increment )
- +loop ( color eblock#' )
- 2drop
+ 0 rot 0 ?do ( eblock# )
+ dup nand-pages/block * " block-bad?" $call-nand 0= if ( eblock# )
+ dup show-pending ( eblock# )
+ 1 ( eblock# increment )
+ else ( eblock# )
+ 0 ( eblock# increment )
+ then ( eblock# increment )
+ swap 1+ swap ( eblock#' increment )
+ +loop ( eblock#' )
+ drop
;
-: gshow-written ( eblock# -- ) written-color show-state ;
+: gshow-written ( eblock# -- )
+ dup written-color show-state
+ d# 20 status-line at-xy .x
+;
: gshow
+ ['] gshow-init to show-init
['] gshow-erasing to show-erasing
['] gshow-erased to show-erased
['] gshow-bad to show-bad
['] gshow-bbt-block to show-bbt-block
['] gshow-clean to show-clean
['] gshow-cleaning to show-cleaning
+ ['] gshow-pending to show-pending
['] gshow-writing to show-writing
['] gshow-written to show-written
+ ['] gshow-strange to show-strange
+ ['] gshow-done to show-done
;
gshow
+
+\ 0 - marked bad block : show-bad
+\ 1 - unreadable block : show-bad
+\ 2 - jffs2 w/ summary: show-written
+\ 3 - jffs2 w/o summary: show-pending
+\ 4 - clean : show-clean
+\ 5 - non-jffs2 data : show-strange
+\ 6 - erased : show-erased
+\ 7 - primary bad-block-table : show-bbt-block
+\ 8 - secondary bad-block-table : show-bbt-block
+: show-status ( status eblock# -- )
+ swap case
+ 0 of show-bad endof
+ 1 of show-bad endof
+ 2 of show-written endof
+ 3 of show-pending endof
+ 4 of show-clean endof
+ 5 of show-strange endof
+ 6 of show-erased endof
+ 7 of show-bbt-block endof
+ 8 of show-bbt-block endof
+ endcase
+;
+
+0 value nand-map
+0 value working-page
+: classify-block ( page# -- status )
+ to working-page
+
+ \ Check for block marked bad in bad-block table
+ working-page " block-bad?" $call-nand if 0 exit then
+
+ \ Try to read the first few bytes
+ load-base 4 working-page 0 " pio-read" $call-nand
+
+ \ Check for a JFFS2 node at the beginning
+ load-base w@ h# 1985 = if
+ \ Look for a summary node
+ load-base 4 working-page h# 3f + h# 7fc " pio-read" $call-nand
+ load-base " "(85 18 85 02)" comp if 3 else 2 then
+ exit
+ then
+
+ \ Check for non-erased, non-JFFS2 data
+ load-base l@ h# ffff.ffff <> if 5 exit then
+
+ \ Check for various signatures in the OOB area
+ working-page " read-oob" $call-nand d# 14 + ( adr )
+
+ \ .. Cleanmarker
+ dup " "(85 19 03 20 08 00 00 00)" comp 0= if drop 4 exit then
+
+ \ .. Bad block tables
+\ These can't happen because the BBT table blocks are marked "bad"
+\ so they get filtered out at the top of this routine.
+\ dup " Bbt0" comp 0= if drop 7 exit then
+\ dup " 1tbB" comp 0= if drop 8 exit then
+ drop
+
+ \ See if the whole thing is really completely erased
+ load-base working-page nand-pages/block ( adr block# #blocks )
+ " read-blocks" $call-nand nand-pages/block <> if 1 exit then
+
+ \ Not completely erased
+ load-base load-base h# 100000 + /nand-block comp if 5 exit then
+
+ \ Erased
+ 6
+;
+
+0 value current-block
+0 value examine-done?
+
+string-array status-descriptions
+ ," Marked bad in Bad Block Table" \ 0
+ ," Read error" \ 1
+ ," JFFS2 data with summary" \ 2
+ ," JFFS2 data, no summary" \ 3
+ ," Clean (erased with JFFS2 cleanmarker)" \ 4
+ ," Dirty, with non-JFFS2 data" \ 5
+ ," Erased, no cleanmarker" \ 6
+ ," Primary Bad Block Table" \ 7
+ ," Secondary Bad Block Table" \ 8
+end-string-array
+
+: show-block-status ( block# -- )
+ d# 20 status-line at-xy
+ dup .x
+ nand-map + c@ status-descriptions count type kill-line
+;
+
+: cell-border ( block# color -- )
+ swap >loc ( color x y )
+ -1 -1 xy+
+ 3dup grid-w 1 do-fill ( color x y )
+ 3dup grid-w 0 xy+ 1 grid-h do-fill ( color x y )
+ 3dup 0 1 xy+ 1 grid-h do-fill ( color x y )
+ 1 grid-h xy+ grid-w 1 do-fill
+;
+: lowlight ( block# -- ) h# ffff cell-border ;
+: highlight ( block# -- ) 0 cell-border ;
+: +block ( offset -- )
+ current-block + nand-block-limit mod ( new-block )
+ current-block lowlight
+ to current-block
+ current-block highlight
+ current-block show-block-status
+;
+
+: process-key ( char -- )
+ case
+ h# 9b of endof
+ [char] A of #cols negate +block endof \ up
+ [char] B of #cols +block endof \ down
+ [char] C of 1 +block endof \ right
+ [char] D of -1 +block endof \ left
+ [char] ? of #cols 8 * negate +block endof \ page up
+ [char] / of #cols 8 * +block endof \ page down
+ [char] K of 8 +block endof \ page right
+ [char] H of -8 +block endof \ page left
+ h# 1b of d# 20 ms key? 0= if true to examine-done? then endof
+ endcase
+;
+
+: examine-nand ( -- )
+ 0 status-line 1+ at-xy ." Arrows, fn Arrows to move, Esc to exit" cr
+ 0 to current-block
+ current-block highlight
+ false to examine-done?
+ begin key process-key examine-done? until
+ current-block lowlight
+;
+
+
+: scan-nand ( -- )
+ open-nand
+ nand-map 0= if
+ #nand-pages nand-pages/block / alloc-mem to nand-map
+ then
+
+ \ Something to compare against
+ load-base h# 100000 + /nand-block h# ff fill
+
+ " usable-page-limit" $call-nand
+ dup nand-pages/block / show-init ( page-limit )
+
+ 7 " bbt0" $call-nand nand-pages/block / nand-map + c!
+ 8 " bbt1" $call-nand nand-pages/block / nand-map + c!
+
+ 0 ?do
+ i classify-block ( status )
+ i nand-pages/block / ( status eblock# )
+ 2dup nand-map + c! ( status eblock# )
+ show-status
+ nand-pages/block +loop ( )
+
+ show-done
+ close-nand-ihs
+
+ examine-nand
+;