diff mbox

[U-Boot] common/update.c ITB update code refactoring (no new file)

Message ID 4D786CC2.2040505@tibbo.com
State Changes Requested
Headers show

Commit Message

Dvorkin Dmitry March 10, 2011, 6:16 a.m. UTC
common/update.c used to update flash with ITB image.
With this patch it can also use any templated nash commands to load and 
save blobs.
Also it adds nand as possible target for update.

Usage example:
// to load itb from usb mass-storage device and save it into nand using 
nash commands
setenv updatefile updateimage.itb
setenv loadaddr 0x72000000
setenv upditb_load_method cmd
setenv upditb_cmd_load_pre usb start
setenv upditb_cmd_load fatload usb 0:1 {load_to} {file}
setenv upditb_save_method cmd
setenv upditb_cmd_save nand write {addr_src} {addr_dst} {img_size}

// better way to do the same task:
setenv updatefile updateimage.itb
setenv loadaddr 0x72000000
setenv upditb_load_method cmd
setenv upditb_cmd_load_pre usb start
setenv upditb_cmd_load fatload usb 0:1 {load_to} {file}
setenv upditb_save_method nand

it directly calls write_nand_skip_bad() to save blobs. Better because of 
kernel image usually is not nand-page aligned, end-of-kernel blob does 
not fit into nand page borders, "nand" method trying to fix it.
diff mbox

Patch

diff -urN a/common/main.c b/common/main.c
--- a/common/main.c     2010-09-29 01:20:55.000000000 +0400
+++ b/common/main.c     2011-03-02 23:34:12.000000000 +0300
@@ -56,9 +56,9 @@ 

  extern int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char * 
const argv[]);

-#if defined(CONFIG_UPDATE_TFTP)
-void update_tftp (void);
-#endif /* CONFIG_UPDATE_TFTP */
+#if defined(CONFIG_UPDATE)
+void update_itb (void);
+#endif /* CONFIG_UPDATE */

  #define MAX_DELAY_STOP_STR 32

@@ -365,9 +365,9 @@ 
         }
  #endif /* CONFIG_PREBOOT */

-#if defined(CONFIG_UPDATE_TFTP)
-       update_tftp ();
-#endif /* CONFIG_UPDATE_TFTP */
+#if defined(CONFIG_UPDATE)
+       update_itb ();
+#endif /* CONFIG_UPDATE */

  #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
         s = getenv ("bootdelay");
diff -urN a/common/Makefile b/common/Makefile
--- a/common/Makefile   2010-09-29 01:20:55.000000000 +0400
+++ b/common/Makefile   2011-03-10 09:12:25.546803490 +0300
@@ -164,7 +164,7 @@ 
  COBJS-$(CONFIG_LCD) += lcd.o
  COBJS-$(CONFIG_LYNXKDI) += lynxkdi.o
  COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o
-COBJS-$(CONFIG_UPDATE_TFTP) += update.o
+COBJS-$(CONFIG_UPDATE) += update.o
  COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o


diff -urN a/common/update.c b/common/update.c
--- a/common/update.c   2011-02-28 15:46:10.000000000 +0300
+++ b/common/update.c   2011-03-07 16:27:02.000000000 +0300
@@ -4,6 +4,10 @@ 
   * Written by: Rafal Czubak <rcz@semihalf.com>
   *             Bartlomiej Sieka <tur@semihalf.com>
   *
+ * (C) Copyright 2011 Tibbo Tech.
+ * Code refactoring, Cmd and Nand load/save features:
+ *     Dvorkin Dmitry <dvorkin@tibbo.com>
+ *
   * See file CREDITS for list of people who contributed to this
   * project.
   *
@@ -30,12 +34,13 @@ 
  #error "CONFIG_FIT and CONFIG_OF_LIBFDT are required for auto-update 
feature"
  #endif

-#if defined(CONFIG_SYS_NO_FLASH)
-#error "CONFIG_SYS_NO_FLASH defined, but FLASH is required for 
auto-update feature"
-#endif
-
  #include <command.h>
+#if !defined(CONFIG_SYS_NO_FLASH)
  #include <flash.h>
+#endif
+#if defined(CONFIG_CMD_NAND)
+#include <nand.h>
+#endif
  #include <net.h>
  #include <malloc.h>

@@ -43,16 +48,16 @@ 
  #define UPDATE_FILE_ENV                "updatefile"

  /* set configuration defaults if needed */
-#ifndef CONFIG_UPDATE_LOAD_ADDR
-#define CONFIG_UPDATE_LOAD_ADDR        0x100000
+#ifndef CONFIG_UPDITB_LOAD_ADDR
+#define CONFIG_UPDITB_LOAD_ADDR        0x100000
  #endif

-#ifndef CONFIG_UPDATE_TFTP_MSEC_MAX
-#define CONFIG_UPDATE_TFTP_MSEC_MAX    100
+#ifndef CONFIG_UPDITB_TFTP_MSEC_MAX
+#define CONFIG_UPDITB_TFTP_MSEC_MAX    100
  #endif

-#ifndef CONFIG_UPDATE_TFTP_CNT_MAX
-#define CONFIG_UPDATE_TFTP_CNT_MAX     0
+#ifndef CONFIG_UPDITB_TFTP_CNT_MAX
+#define CONFIG_UPDITB_TFTP_CNT_MAX     0
  #endif

  extern ulong TftpRRQTimeoutMSecs;
@@ -60,11 +65,91 @@ 
  extern flash_info_t flash_info[];
  extern ulong load_addr;

+extern int run_command (const char *cmd, int flag);
+
  static uchar *saved_prot_info;

-static int update_load(char *filename, ulong msec_max, int cnt_max, 
ulong addr)
+enum XLAT_ST {
+ XLAT_ST_D,    /* default */
+ XLAT_ST_S,    /* skip \ */
+ XLAT_ST_B,    /* begin attr name */
+ XLAT_ST_A,    /* in attr name */
+ XLAT_ST_s,    /* skip \} in attr name */
+ XLAT_ST_E,    /* end attr name */
+};
+
+enum XLAT_CT {
+ XLAT_CT_DEF,
+ XLAT_CT_BKS,
+ XLAT_CT_BEG,
+ XLAT_CT_END,
+};
+
+enum XLAT_ST xlat_st_tbl[ 6][ 4] = {
+ // def       \\         {          }
+ { XLAT_ST_D, XLAT_ST_S, XLAT_ST_B, XLAT_ST_D }, // _ST_D
+ { XLAT_ST_D, XLAT_ST_D, XLAT_ST_D, XLAT_ST_D }, // _ST_S
+ { XLAT_ST_A, XLAT_ST_A, XLAT_ST_A, XLAT_ST_E }, // _ST_B
+ { XLAT_ST_A, XLAT_ST_s, XLAT_ST_A, XLAT_ST_E }, // _ST_A
+ { XLAT_ST_A, XLAT_ST_A, XLAT_ST_A, XLAT_ST_A }, // _ST_s
+ { XLAT_ST_D, XLAT_ST_S, XLAT_ST_B, XLAT_ST_D }, // _ST_E
+};
+
+typedef char *( *xlat_cfpt)( void *_data, char *_as, ulong _al, ulong 
*_rlen);
+
+static int Xlat_R( const char *_i, ulong _il, char *_o, ulong _ol,
+    xlat_cfpt _cfp, void *_data) {
+ ulong i = -1, oi = 0;
+ ulong rlen, ret = 0;
+ char *tks;
+ ulong tkl;
+ char *repl_av = NULL;
+ unsigned char c;
+ enum XLAT_CT ctype;
+ enum XLAT_ST curst = XLAT_ST_D;
+
+ tks = NULL;  tkl = 0;
+ while ( ++i < _il && ( c = _i[ i]) != '\0') {
+//printf( "x:%d\n", i);
+   ctype = XLAT_CT_DEF;
+   if ( c == '\\') ctype = XLAT_CT_BKS;
+   if ( c == '{' ) ctype = XLAT_CT_BEG;
+   if ( c == '}' ) ctype = XLAT_CT_END;
+   curst = xlat_st_tbl[ curst][ ctype];
+   switch ( curst) {
+     case XLAT_ST_s:
+     case XLAT_ST_S:  break;
+     case XLAT_ST_D:  if ( _o) _o[ oi++] = c;  break;
+     case XLAT_ST_B:  tks = ( _i + i + 1);  tkl = 0;  break;
+     case XLAT_ST_A:  tkl++;  break;
+     case XLAT_ST_E:
+//       printf( "AVP:%s\n", tmp_attr);
+       // macro name ended
+       ret++;
+       // if output buffer == NULL - return number of potential subs
+       if ( !_o) break;
+       repl_av = NULL;  rlen = 0;
+       if ( _cfp) repl_av = _cfp( _data, tks, tkl, &rlen);
+       // actually replace
+       if ( repl_av != NULL) {  memcpy( _o + oi, repl_av, rlen);  oi += 
rlen;  }
+       // if replace to NULL
+       if ( repl_av == NULL && rlen > 0) break;
+       // if no replace found - copy {text} to output - safe for future
+       if ( repl_av == NULL && rlen < 1) {
+         _o[ oi++] = '{';
+         memcpy( _o + oi, tks, tkl);  oi += tkl;
+         _o[ oi++] = '}';  }
+       break;
+   } // end of switch
+   if ( tkl >= _ol) return( ret);
+ }
+ return( ret);  }
+
+static int update_load_tftp(char *filename, ulong addr)
  {
         int size, rv;
+       ulong msec_max = CONFIG_UPDITB_TFTP_MSEC_MAX;
+       int cnt_max = CONFIG_UPDITB_TFTP_CNT_MAX;
         ulong saved_timeout_msecs;
         int saved_timeout_count;
         char *saved_netretry, *saved_bootfile;
@@ -109,6 +194,74 @@ 
         return rv;
  }

+typedef struct Xlate_load_T {
+ char *file;
+ ulong load_to;
+} Xlate_load_t;
+
+char *Xlate_load( void *_data, char *_as, ulong _al, ulong *_rlen) {
+ Xlate_load_t *Xdp = ( Xlate_load_t *)_data;
+ char xs[ 64];
+ memset( xs, 0, 64);
+ if ( _al == 4 && memcmp( _as, "file", 4) == 0) sprintf( xs, "%s", 
Xdp->file);
+ if ( _al == 7 && memcmp( _as, "load_to", 7) == 0) sprintf( xs, 
"0x%08x", Xdp->load_to);
+ *_rlen = strlen( xs);
+ return( xs);  }
+
+static int update_load_cmd( char *_file, ulong _addr) {
+ char *cmd;
+ char cmdx[ 1024];
+ Xlate_load_t Xd = { .file = _file, .load_to = _addr };
+ if ( ( cmd = getenv( "upditb_cmd_load_pre")) != NULL) {
+   memset( cmdx, 0, 1024);
+   Xlat_R( cmd, strlen( cmd), cmdx, 1024, Xlate_load, &Xd);
+   printf( "Preload cmd template:%s\n", cmd);
+   printf( "Xlated to:%s\n", cmdx);
+   /* prepare for loading into RAM, 'usb start' for ex. */
+   if ( run_command( cmdx, 0) == -1) return( 1);
+ }
+ /* load to RAM. 'fatload usb 0:1 <address> <file>' for ex. */
+ if ( ( cmd = getenv( "upditb_cmd_load")) != NULL) {
+   memset( cmdx, 0, 1024);
+   Xlat_R( cmd, strlen( cmd), cmdx, 1024, Xlate_load, &Xd);
+   printf( "Load cmd template:%s\n", cmd);
+   printf( "Xlated to:%s\n", cmdx);
+   /* prepare for loading into RAM, 'usb start' for ex. */
+   if ( run_command( cmdx, 0) == -1) return( 1);
+ }
+ return( 0); }
+
+typedef struct Xlate_flash_T {
+ ulong a_src;
+ ulong a_dst;
+ ulong size;
+} Xlate_flash_t;
+
+char *Xlate_flash( void *_data, char *_as, ulong _al, ulong *_rlen) {
+ Xlate_flash_t *Xdp = ( Xlate_flash_t *)_data;
+ char xs[ 64];
+ memset( xs, 0, 64);
+ if ( _al == 8 && memcmp( _as, "addr_src", 8) == 0) sprintf( xs, 
"0x%08x", Xdp->a_src);
+ if ( _al == 8 && memcmp( _as, "addr_dst", 8) == 0) sprintf( xs, 
"0x%08x", Xdp->a_dst);
+ if ( _al == 8 && memcmp( _as, "img_size", 8) == 0) sprintf( xs, 
"0x%08x", Xdp->size);
+ *_rlen = strlen( xs);
+ return( xs);  }
+
+static int update_s_cmd( ulong _addr_source, ulong _addr_first, ulong 
_size) {
+ char *cmdc;
+ char cmdcx[ 1024];
+ Xlate_flash_t Xd = { .a_src = _addr_source, .a_dst = _addr_first, 
.size = _size };
+ printf( "%s()\n", __FUNCTION__);
+ if ( ( cmdc = getenv( "upditb_cmd_save")) == NULL) return( 1);
+ memset( cmdcx, 0, 1024);
+ Xlat_R( cmdc, strlen( cmdc), cmdcx, 1024, Xlate_flash, &Xd);
+ printf( "Save cmd template:%s\n", cmdc);
+ printf( "Xlated to:%s\n", cmdcx);
+ /* save to target, nand write {addr_src} {addr_dst} {img_size} for ex. */
+ if ( run_command( cmdcx, 0) == -1) return( 1);
+ return( 0); }
+
+#if !defined(CONFIG_SYS_NO_FLASH)
  static int update_flash_protect(int prot, ulong addr_first, ulong 
addr_last)
  {
         uchar *sp_info_ptr;
@@ -181,10 +334,11 @@ 
         return 0;
  }

-static int update_flash(ulong addr_source, ulong addr_first, ulong size)
+static int update_s_flash(ulong addr_source, ulong addr_first, ulong size)
  {
         ulong addr_last = addr_first + size - 1;

+       printf( "%s()\n", __FUNCTION__);
         /* round last address to the sector boundary */
         if (flash_sect_roundb(&addr_last) > 0)
                 return 1;
@@ -221,6 +375,25 @@ 

         return 0;
  }
+#endif
+
+#if defined(CONFIG_CMD_NAND)
+static int update_s_nand( ulong _a_src, ulong _a_dst, size_t _size)
+{
+ int err;
+ size_t len = _size;
+ size_t tl;
+ tl = nand_info[ 0].writesize;
+ printf( "%s()\n", __FUNCTION__);
+ if ( ( _size % tl) != 0) {
+   printf( "padding %d with %d bytes\n", _size, ( tl - ( _size % tl)));
+   len = _size += ( tl - ( _size % tl));
+   printf( "new size is %d bytes\n", _size);
+ }
+ err = nand_write_skip_bad( &nand_info[ 0], _a_dst, &len, _a_src);
+ if ( err != 0) return( 1);
+ return( 0);  }
+#endif

  static int update_fit_getparams(const void *fit, int noffset, ulong *addr,
                                                 ulong *fladdr, ulong *size)
@@ -238,15 +411,23 @@ 
         return 0;
  }

-void update_tftp(void)
+void update_itb(void)
  {
         char *filename, *env_addr;
+       char *method_load, *method_save, *ts;
         int images_noffset, ndepth, noffset;
         ulong update_addr, update_fladdr, update_size;
         ulong addr;
         void *fit;
+       int err, sl;

-       printf("Auto-update from TFTP: ");
+       /* update method: tftp or something else */
+       ts = method_load = getenv( "upditb_load_method");
+       if ( method_load == NULL) method_load = "none";
+       printf( "Auto-update ITB load method:%s\n", method_load);
+       if ( ts == NULL) return;
+       method_save = getenv( "upditb_save_method");
+       if ( method_save == NULL) method_save = "flash";

         /* get the file name of the update file */
         filename = getenv(UPDATE_FILE_ENV);
@@ -257,31 +438,68 @@ 
         }

         printf("trying update file '%s'\n", filename);
+#ifdef CONFIG_LCD
+       lcd_printf( "Loading auto-update file '%s'...", filename);
+#endif

         /* get load address of downloaded update file */
         if ((env_addr = getenv("loadaddr")) != NULL)
                 addr = simple_strtoul(env_addr, NULL, 16);
         else
-               addr = CONFIG_UPDATE_LOAD_ADDR;
-
+               addr = CONFIG_UPDITB_LOAD_ADDR;

-       if (update_load(filename, CONFIG_UPDATE_TFTP_MSEC_MAX,
-                                       CONFIG_UPDATE_TFTP_CNT_MAX, addr)) {
-               printf("Can't load update file, aborting auto-update\n");
-               return;
+       err = -1;
+       sl = strlen( method_load);
+       if ( sl == 4 && strcmp( method_load, "tftp") == 0) err = 
update_load_tftp( filename, addr);
+       if ( sl == 3 && strcmp( method_load, "cmd" ) == 0) err = 
update_load_cmd(  filename, addr);
+       switch ( err) {
+         case -1:
+#ifdef CONFIG_LCD
+           lcd_printf( "ERR-1\n");
+#endif
+           printf( "No such method '%s', aborting auto-update\n", 
method_load);
+           return;
+           break;
+         case 0:       /* it's OK */
+#ifdef CONFIG_LCD
+           lcd_printf( "OK\n");
+#endif
+           break;
+         default:
+#ifdef CONFIG_LCD
+           lcd_printf( "ERR\n");
+#endif
+           printf( "Can't load update file, aborting auto-update\n");
+           return;
+           break;
         }

+#ifdef CONFIG_LCD
+       lcd_printf( "Auto-update file is loaded, checking...");
+#endif
         fit = (void *)addr;

         if (!fit_check_format((void *)fit)) {
                 printf("Bad FIT format of the update file, aborting "
                                                         "auto-update\n");
+#ifdef CONFIG_LCD
+       lcd_printf( "ERR\n");
+#endif
                 return;
         }
+#ifdef CONFIG_LCD
+       lcd_printf( "OK\n");
+#endif

         /* process updates */
         images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);

+#ifdef CONFIG_LCD
+       err = fit_get_desc( fit, 0, &ts);
+       if ( err) ts = "(no description)";
+       lcd_printf( "Processing %s...\n", ts);
+#endif
+fit_print_contents( (void *)fit);
         ndepth = 0;
         noffset = fdt_next_node(fit, images_noffset, &ndepth);
         while (noffset >= 0 && ndepth > 0) {
@@ -303,10 +521,33 @@ 
 
"aborting\n");
                         goto next_node;
                 }
-               if (update_flash(update_addr, update_fladdr, update_size)) {
+fit_image_print( fit, noffset, "");
+#ifdef CONFIG_LCD
+               err = fit_get_desc( fit, noffset, &ts);
+               if ( err) ts = "(no description)";
+               lcd_printf( "Flashing %s...", ts);
+#endif
+               sl = strlen( method_save);
+               err = -1;
+#if !defined(CONFIG_SYS_NO_FLASH)
+               if ( sl == 5 && strcmp( method_save, "flash") == 0) err 
= update_s_flash(update_addr, update_fladdr, update_size);
+#endif
+               if ( sl == 3 && strcmp( method_save, "cmd" ) == 0) err = 
update_s_cmd( update_addr, update_fladdr, update_size);
+#if defined(CONFIG_CMD_NAND)
+               if ( sl == 4 && strcmp( method_save, "nand") == 0) err = 
update_s_nand(update_addr, update_fladdr, update_size);
+#endif
+               /* fallback if method not found */
+               if ( err == -1) err = update_s_flash(update_addr, 
update_fladdr, update_size);
+               if ( err) {
                         printf("Error: can't flash update (%ld %ld 
%ld), aborting\n", update_addr, update_fladdr, update_size);
+#ifdef CONFIG_LCD
+                       lcd_printf( "ERR\n");
+#endif
                         goto next_node;
                 }
+#ifdef CONFIG_LCD
+               lcd_printf( "OK\n");
+#endif
  next_node:
                 noffset = fdt_next_node(fit, noffset, &ndepth);
         }
diff -urN a/include/configs/at91sam9m10g45ek.h 
b/include/configs/at91sam9m10g45ek.h
--- a/include/configs/at91sam9m10g45ek.h        2011-02-28 
15:46:10.000000000 +0300
+++ b/include/configs/at91sam9m10g45ek.h        2011-03-02 
23:34:12.000000000 +0300
@@ -92,9 +92,11 @@ 
  /* update feature */
  #define CONFIG_FIT             1
  #define CONFIG_OF_LIBFDT       1
-#define CONFIG_UPDATE_TFTP     1
-//#define CONFIG_UPDATE_CNT_MAX        0
-//#define CONFIG_UPDATE_MSEC_MAX       100
+#define CONFIG_UPDITB          1
+#define CONFIG_UPDITB_TFTP     1
+//#define CONFIG_UPDITB_CNT_MAX        0
+//#define CONFIG_UPDITB_MSEC_MAX       100
+#define CONFIG_UPDITB_LOAD_ADDR        0x72000000

  /*
   * Command line configuration.
diff -urN a/README b/README
--- a/README    2010-09-29 01:20:55.000000000 +0400
+++ b/README    2011-03-02 23:34:12.000000000 +0300
@@ -2108,10 +2108,11 @@ 
   -150  common/cmd_nand.c       Incorrect FIT image format
    151  common/cmd_nand.c       FIT image format OK

-- Automatic software updates via TFTP server
-               CONFIG_UPDATE_TFTP
-               CONFIG_UPDATE_TFTP_CNT_MAX
-               CONFIG_UPDATE_TFTP_MSEC_MAX
+- Automatic software updates via ITB structure
+               CONFIG_UPDITB
+               CONFIG_UPDITB_TFTP
+               CONFIG_UPDITB_TFTP_CNT_MAX
+               CONFIG_UPDITB_TFTP_MSEC_MAX

                 These options enable and control the auto-update feature;
                 for a more detailed description refer to doc/README.update.