[openfirmware] r1525 - cpu/x86/pc/olpc

svn at openfirmware.info svn at openfirmware.info
Sun Nov 29 20:58:20 CET 2009


Author: wmb
Date: 2009-11-29 20:58:20 +0100 (Sun, 29 Nov 2009)
New Revision: 1525

Added:
   cpu/x86/pc/olpc/xmodem-reflash.fth
Log:
Checked in xmodem-reflash.fth .  It can be downloaded serially to
provide a reflash-over-serial capability.


Added: cpu/x86/pc/olpc/xmodem-reflash.fth
===================================================================
--- cpu/x86/pc/olpc/xmodem-reflash.fth	                        (rev 0)
+++ cpu/x86/pc/olpc/xmodem-reflash.fth	2009-11-29 19:58:20 UTC (rev 1525)
@@ -0,0 +1,470 @@
+\ See license at end of file
+purpose: Reflash OLPC Open Firmware using XMODEM serial download for the image
+
+\ Interface definitions to splice xmodem into Open Firmware
+
+true value serial-on?
+: serial-off  ( -- )
+   serial-on?  if
+      fallback-in-ih remove-input
+      fallback-out-ih remove-output
+      false to serial-on?
+   then
+;
+: serial-on  ( -- )
+   serial-on?  0=  if
+      fallback-in-ih add-input
+      fallback-out-ih add-output
+      true to serial-on?
+   then
+;
+
+\ alias m-key? ukey?
+alias m-key  ukey
+alias m-emit uemit
+
+: m-init  ( -- )
+   h# 07  h# 3fa  pc!   \ Clear and enable FIFOs
+   h# 80  h# 3fb  pc!   \ Select baud divisor port
+   h# 00  h# 3f9  pc!   \ High divisor for 115200 baud
+   h# 01  h# 3f8  pc!   \ Low divisor for 115200 baud
+   h#  3  h# 3fb  pc!   \ 8n1
+;
+
+\ : panel-button?  ( -- flag )  key?  ;
+: panel-button?  ( -- flag )  false  ;  \ We don't want to abort
+: panel-d.  ( n -- )
+   #out @ >r
+   push-decimal
+   <#  u# u# u#  ( bs hold bs hold bs hold ) u#> type
+   pop-base
+   r> #out !
+;
+
+: panel-msg:  create ",  does> count type  ;
+
+" Abort"   panel-msg: abrt-msg     \ Abrt
+" Cancel"  panel-msg: can-msg      \ CAn
+: crc-msg ;  \ " Xmodem-CRC" panel-msg: crc-msg      \ crc
+: done-msg ; \ " Done"    panel-msg: done-msg     \ donE
+" Timeout" panel-msg: timeout-msg  \ tout
+" "rr " panel-msg: r0-msg    \ Start of packet
+" "rR " panel-msg: r1-msg    \ Start of packet big
+" "     panel-msg: r2-msg    \ Inside try-receive
+
+" Error"  panel-msg: giveup-msg   \ Err
+" Loading diags    " panel-msg: upld-msg    \ UPLd
+" OF"   panel-msg: of-msg         \ OF
+
+: bogus-char  ( c -- )  ." Bogus: " .x  ;
+: ignore-char  ( c -- )  ." Ignoring: " .x  ;
+
+: ms>ticks  ( ms -- ticks )   ;
+
+variable timer-init
+
+: timed-in  ( -- true | char false ) \ get a character unless timeout
+   get-msecs  timer-init @  +   ( time-limit )
+   begin                        ( time-limit )
+      ukey?  if  drop ukey false  exit   then  ( time-limit )
+   dup get-msecs - 0<  until
+   drop true
+;
+
+
+\ ---
+
+\ CRC-16 table
+base @ hex
+create crc16tab
+    0000 w,  1021 w,  2042 w,  3063 w,  4084 w,  50a5 w,  60c6 w,  70e7 w,
+    8108 w,  9129 w,  a14a w,  b16b w,  c18c w,  d1ad w,  e1ce w,  f1ef w,
+    1231 w,  0210 w,  3273 w,  2252 w,  52b5 w,  4294 w,  72f7 w,  62d6 w,
+    9339 w,  8318 w,  b37b w,  a35a w,  d3bd w,  c39c w,  f3ff w,  e3de w,
+    2462 w,  3443 w,  0420 w,  1401 w,  64e6 w,  74c7 w,  44a4 w,  5485 w,
+    a56a w,  b54b w,  8528 w,  9509 w,  e5ee w,  f5cf w,  c5ac w,  d58d w,
+    3653 w,  2672 w,  1611 w,  0630 w,  76d7 w,  66f6 w,  5695 w,  46b4 w,
+    b75b w,  a77a w,  9719 w,  8738 w,  f7df w,  e7fe w,  d79d w,  c7bc w,
+    48c4 w,  58e5 w,  6886 w,  78a7 w,  0840 w,  1861 w,  2802 w,  3823 w,
+    c9cc w,  d9ed w,  e98e w,  f9af w,  8948 w,  9969 w,  a90a w,  b92b w,
+    5af5 w,  4ad4 w,  7ab7 w,  6a96 w,  1a71 w,  0a50 w,  3a33 w,  2a12 w,
+    dbfd w,  cbdc w,  fbbf w,  eb9e w,  9b79 w,  8b58 w,  bb3b w,  ab1a w,
+    6ca6 w,  7c87 w,  4ce4 w,  5cc5 w,  2c22 w,  3c03 w,  0c60 w,  1c41 w,
+    edae w,  fd8f w,  cdec w,  ddcd w,  ad2a w,  bd0b w,  8d68 w,  9d49 w,
+    7e97 w,  6eb6 w,  5ed5 w,  4ef4 w,  3e13 w,  2e32 w,  1e51 w,  0e70 w,
+    ff9f w,  efbe w,  dfdd w,  cffc w,  bf1b w,  af3a w,  9f59 w,  8f78 w,
+    9188 w,  81a9 w,  b1ca w,  a1eb w,  d10c w,  c12d w,  f14e w,  e16f w,
+    1080 w,  00a1 w,  30c2 w,  20e3 w,  5004 w,  4025 w,  7046 w,  6067 w,
+    83b9 w,  9398 w,  a3fb w,  b3da w,  c33d w,  d31c w,  e37f w,  f35e w,
+    02b1 w,  1290 w,  22f3 w,  32d2 w,  4235 w,  5214 w,  6277 w,  7256 w,
+    b5ea w,  a5cb w,  95a8 w,  8589 w,  f56e w,  e54f w,  d52c w,  c50d w,
+    34e2 w,  24c3 w,  14a0 w,  0481 w,  7466 w,  6447 w,  5424 w,  4405 w,
+    a7db w,  b7fa w,  8799 w,  97b8 w,  e75f w,  f77e w,  c71d w,  d73c w,
+    26d3 w,  36f2 w,  0691 w,  16b0 w,  6657 w,  7676 w,  4615 w,  5634 w,
+    d94c w,  c96d w,  f90e w,  e92f w,  99c8 w,  89e9 w,  b98a w,  a9ab w,
+    5844 w,  4865 w,  7806 w,  6827 w,  18c0 w,  08e1 w,  3882 w,  28a3 w,
+    cb7d w,  db5c w,  eb3f w,  fb1e w,  8bf9 w,  9bd8 w,  abbb w,  bb9a w,
+    4a75 w,  5a54 w,  6a37 w,  7a16 w,  0af1 w,  1ad0 w,  2ab3 w,  3a92 w,
+    fd2e w,  ed0f w,  dd6c w,  cd4d w,  bdaa w,  ad8b w,  9de8 w,  8dc9 w,
+    7c26 w,  6c07 w,  5c64 w,  4c45 w,  3ca2 w,  2c83 w,  1ce0 w,  0cc1 w,
+    ef1f w,  ff3e w,  cf5d w,  df7c w,  af9b w,  bfba w,  8fd9 w,  9ff8 w,
+    6e17 w,  7e36 w,  4e55 w,  5e74 w,  2e93 w,  3eb2 w,  0ed1 w,  1ef0 w,
+base !
+
+: updcrc  ( crc c -- crc' c )
+   dup rot              ( c c crc )
+   wbsplit  >r          ( c c low r: high )
+   bwjoin               ( c low|c r: high )
+   crc16tab  r> wa+ w@  ( c low|c table-entry )
+   xor swap             ( crc' c )
+;
+
+: crc-send  ( crc adr len -- crc' )
+   bounds  ?do  i c@ updcrc m-emit  loop
+;
+
+\ Assumes 0<len<64K
+: crc-receive  ( crc adr len timeout -- true | crc' false )
+   timer-init !
+   bounds  ?do  timed-in  if  drop true unloop  exit  then  i c!  loop
+;
+
+: checksum-send  ( sum adr len -- sum' )
+   bounds ?do  i c@ dup m-emit  +  loop
+;
+
+
+
+\ ---
+
+purpose: X/YMODEM protocol for serial uploads and downloads
+
+\ Xmodem protocol file transfer to and from memory
+\ Commands:
+\   send  ( adr len -- )
+\   receive  ( adr maxlen -- adr len )
+
+\ Interface to the serial line:
+\
+\ m-key?     -- flag
+\       Flag is true if a character is available on the serial line
+\ m-key      -- char
+\       Gets a character from the serial line
+\ m-emit        char --
+\       Puts the character out on the serial line.
+
+variable buf-start
+variable buf-end
+variable mem-start
+variable mem-end
+
+: putc  ( char -- )  buf-start @ c!  1 buf-start +!  ;
+
+: end-delay  ( -- )  d# 200 ms  ;
+
+
+vocabulary modem
+only forth also modem also   modem definitions
+base @ decimal
+
+\ Common to both sending and receiving
+0 value crc?   0 value big?   \ 0 value streaming?
+variable #control-z's
+d# 128 constant 128by
+d# 1024 constant 1k
+variable sector#
+variable checksum
+variable #errors    4 constant max#errors  variable #naks
+: /sector  ( -- n )  big?  if  1k  else  128by  then  ;
+
+\ ASCII control characters
+    0 constant nul
+    1 constant soh  \ Start of header; 128-byte packets
+    2 constant stx  \ Start of header; 1024-byte packets
+    4 constant eot
+    6 constant ack
+d# 21 constant nak
+d# 24 constant can
+
+: timeout!  ( ms -- )  ms>ticks   timer-init !  ;
+: timeout:  \ name  ( milliseconds -- )
+   create ,
+   does>  @ timeout!
+;
+d# 3000 timeout: short-timeout  d# 6000 timeout: long-timeout
+d# 60,000 timeout: initial-timeout
+short-timeout
+
+: gobble  ( -- ) \ eat characters until they stop coming
+   d# 100 timeout!   begin  timed-in  0=  while  drop  repeat   long-timeout
+;
+
+variable done?
+: rx-abort  ( -- )  end-delay  2 done? !  ;
+: tx-abort  ( -- )  end-delay  2 done? !  true abort" aborted"  ;
+
+\ It would be nice to use control C, but some operating systems don't pass it
+: ?interrupt  ( -- )  \ aborts if user types control Z
+   panel-button? if  can m-emit  abrt-msg tx-abort   then
+;
+
+\ Receiving
+
+: receive-setup  ( adr maxlen -- )
+   1 sector# !   #naks off   #control-z's off
+;
+: receive-error ( -- ) \ eat rest of packet and send a nak
+   gobble
+   1 #naks +!   #naks @ max#errors >  if
+      can m-emit   giveup-msg rx-abort
+   then
+   nak m-emit
+;
+
+: receive-data  ( adr len -- error? )
+   0 -rot bounds                               ( chk endadr startadr )
+   crc?  if                                    ( crc endadr startadr )
+      ?do  timed-in throw  updcrc  i c!  loop  ( crc )
+      timed-in throw  timed-in throw           ( crc high low )
+      swap bwjoin  <>                          ( error? )
+   else                                        ( sum endadr startadr )
+      ?do  timed-in throw  dup i c!  +  loop   ( sum )
+      h# ff and  timed-in throw  <>            ( error? )
+   then                                        ( error? )
+;
+variable got-sector#
+: try-receive  ( adr maxlen -- adr maxlen actual-len )
+   ( packet OK return:  none )
+   ( retry return: throws -1 )
+   ( done  return: throws 1 )
+   ( abort return: throws 2 )
+\   begin
+      timed-in  throw
+      case
+         soh of  false to big?     r0-msg       endof  \ expected...
+         stx of  true to big?      r1-msg       endof  \ expected...
+         -1  of  timeout-msg -1 throw           endof
+         nul of  1 throw                        endof  \ XXX check this
+         can of  can-msg 2 throw                endof
+         eot of  done-msg ack m-emit  1 throw   endof
+        ( default) bogus-char -1 throw
+      endcase                        ( adr maxlen )
+\   again
+
+   /sector <  if  2 throw  then      ( adr )
+   timed-in                throw     ( adr sec# )
+   timed-in                throw     ( adr sec# ~sec# )
+   h# ff xor over <>       throw     ( adr sec# )
+   got-sector# !                     ( adr )
+   /sector  receive-data   throw     ( )
+
+   ack m-emit
+   sector# @ panel-d.
+   1 sector# +!   \ Expected sector#
+
+   #naks off
+   /sector                           ( actual )
+;
+: !receive-packet  ( adr maxlen -- adr maxlen actual-len )
+   r2-msg
+   begin        ( adr maxlen )
+      2dup ['] try-receive catch  case   ( adr maxlen [ actual 0 | x x n ] )
+         \ The usual case: successful packet reception
+         0  of  ( adr maxlen actual-len ) exit  endof
+
+         ?interrupt
+
+         \ Retryable error
+         -1 of  ( adr maxlen x x ) 2drop receive-error             endof
+
+         \ Handle termination conditions at a higher level
+         ( default: adr maxlen x x n ) throw
+      endcase   ( adr maxlen )
+   again
+;
+: (receive)  ( adr0 maxlen -- adr0 len )
+   receive-setup                      ( adr0 maxlen )
+   gobble  nak m-emit                 ( adr0 maxlen )
+   2dup                               ( adr0 maxlen adr0 maxlen )
+   begin  dup 0>  while               ( adr0 maxlen adr remlen )
+      ['] !receive-packet catch  case
+         0 of            ( adr0 maxlen adr remlen actual-len )   \ Packet ok
+            /string      ( adr0 maxlen adr' remlen' )
+         endof
+         1 of            ( adr0 maxlen adr remlen )   \ Normal end of transmission
+            nip - exit   ( adr0 len )
+         endof
+         ( default ) can m-emit abrt-msg   throw
+      endcase
+   repeat                              ( adr0 maxlen adr remlen )
+   can m-emit  of-msg  end-delay       ( adr0 maxlen adr remlen )
+   nip -                               ( adr0 len )
+;
+
+\ Sending
+modem definitions
+
+: bail-out  ( -- )  can m-emit  giveup-msg tx-abort  ;
+: wait-ack  ( -- proceed? )  \ wait for ack or can
+[ifdef] streaming?  \ YMODEM-g
+   streaming?  if
+      m-key?  if  m-key can =  if  bail-out  then  then
+      true exit
+   then
+[then]
+   
+   #errors off
+   begin
+      ?interrupt
+      timed-in  if
+         1 #errors +!  #errors @  max#errors >  if  bail-out  then
+         timeout-msg false  exit
+      then
+      case
+         ack of   #naks off  true exit  endof
+         can of   can-msg tx-abort       endof
+         nak of
+            1 #naks +!  #naks @  max#errors >  if  bail-out  then
+            false exit
+         endof
+
+         \ If we get a C, restart
+         [char] C  of  sector# @ 1 <>  if  [char] C bogus-char  then  endof
+
+         ( default) dup bogus-char
+      endcase
+   again
+;
+: start-receiver  ( -- )  \ wait for nak
+   gobble
+   upld-msg
+   sector# off
+   #naks off  false to crc?
+   initial-timeout
+   begin
+      timed-in  if  timeout-msg tx-abort exit  then
+      case
+         can of   can-msg  tx-abort      endof
+         nak of   true          endof
+         [char] C  of  true to crc?  crc-msg  true  endof
+[ifdef] streaming?
+         [char] G  of  true to streaming?  true to crc?  true  endof
+[then]
+         nul of   false   endof   \ Startup transients generate nulls
+         ( default)  dup ignore-char  false swap
+      endcase
+   until
+   gobble long-timeout
+;
+
+: pad  ( -- b )  control Z  sector# @  0<>  and  ;
+\ Send without confirmation
+: send-packet  ( adr len big? -- )
+   if  1k  stx  else  128by soh  then  ( adr len /sec start ) 
+   m-emit                                       ( adr len /sec ) 
+
+   \ Sector number
+   sector# @  dup m-emit  h# ff xor m-emit      ( adr len /sec )
+
+   over - 0  2swap                              ( #pad 0 adr len )
+   crc?  if                                     ( #pad 0 adr len )
+      crc-send                                  ( #pad crc )
+      swap 0  ?do  pad updcrc m-emit  loop      ( crc' )
+      0 updcrc updcrc drop                      ( crc' )
+      wbsplit m-emit m-emit                     ( )
+   else                                         ( #pad 0 adr len )
+      checksum-send                             ( #pad sum )
+      swap 0  ?do  pad  dup m-emit  +  loop     ( sum' )
+      m-emit                                    ( )
+   then                                         ( )
+; 
+
+\ Send until delivery confirmed
+: deliver-packet  ( adr len big? -- )
+   sector# @ panel-d.
+   begin  3dup send-packet  wait-ack until
+   3drop
+;
+
+: end-data  ( -- )
+   begin  eot m-emit  wait-ack  until  \ End the protocol
+   done-msg  end-delay
+;
+
+: sx  ( adr len -- )
+   m-init
+   start-receiver                    ( adr len )
+   begin  dup 0>  while              ( adr len )
+      1 sector# +!                   ( adr len )
+      2dup  /sector min              ( adr len adr /this )
+      tuck  big?  deliver-packet     ( adr len /this )
+      /string                        ( adr' len' )
+   repeat                            ( adr len )
+   2drop                             ( )
+
+   end-data
+;
+
+\ Info format:
+\ <filename>NUL<decimal_size>[[ <decimal_modtime>] <octal_permsissions.]NUL...
+: send-file  ( adr len name$ -- )
+   m-init
+   start-receiver
+   here place                     ( adr len )
+   " "(00)" here $cat             ( adr len )
+   push-decimal dup (.) pop-base  ( adr len len$ )
+   here $cat  here count          ( adr len batch$ )
+   false deliver-packet           ( adr len )
+   sx
+;
+
+: sb-end  ( -- )  start-receiver  " "(00)" false deliver-packet  end-delay  ;
+
+: sb  ( adr len name$ -- )  send-file sb-end  ;
+
+forth definitions
+
+alias sx sx
+: xmodem-receive  ( adr maxlen -- adr len )
+   serial-off  cursor-off
+   ['] (receive) catch    ( adr maxlen throw-code )
+   serial-on   cursor-on  ( adr maxlen throw-code )
+   abort" XMODEM reception aborted"
+;
+
+: xmodem-reflash  ( -- )
+   ?enough-power
+   ." Send the firmware image using the XMODEM (Checksum) protocol" cr
+   flash-buf /flash xmodem-receive  nip   ( actual-len )
+   ?image-valid  true to file-loaded?
+   reflash
+;
+.( Type 'xmodem-reflash' to begin XMODEM reception) cr
+
+only forth also definitions
+
+base !
+
+\ LICENSE_BEGIN
+\ Copyright (c) 2009 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




More information about the openfirmware mailing list