]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/cmd_mtdparts.c
cmd_mtdparts.c: report ECC status along with the partition map
[karo-tx-uboot.git] / common / cmd_mtdparts.c
index b7c833b14992d365050b724060fb81c55f743e00..a2289df4f64c60228d76c05eb56a1956502bebbf 100644 (file)
  *   $Id: cmdlinepart.c,v 1.17 2004/11/26 11:18:47 lavinen Exp $
  *   Copyright 2002 SYSGO Real-Time Solutions GmbH
  *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 /*
 #include <onenand_uboot.h>
 #endif
 
+DECLARE_GLOBAL_DATA_PTR;
+
 /* special size referring to all the remaining space in a partition */
 #define SIZE_REMAINING         0xFFFFFFFF
 
@@ -147,10 +133,10 @@ static char last_partition[PARTITION_MAXLEN];
 extern void jffs2_free_cache(struct part_info *part);
 
 /* mtdids mapping list, filled by parse_ids() */
-struct list_head mtdids;
+static struct list_head mtdids;
 
 /* device/partition list, parse_cmdline() parses into here */
-struct list_head devices;
+static struct list_head devices;
 
 /* current active device and partition number */
 struct mtd_device *current_mtd_dev = NULL;
@@ -230,7 +216,6 @@ static void memsize_format(char *buf, u32 size)
  */
 static void index_partitions(void)
 {
-       char buf[16];
        u16 mtddevnum;
        struct part_info *part;
        struct list_head *dentry;
@@ -244,8 +229,7 @@ static void index_partitions(void)
                        dev = list_entry(dentry, struct mtd_device, link);
                        if (dev == current_mtd_dev) {
                                mtddevnum += current_mtd_partnum;
-                               sprintf(buf, "%d", mtddevnum);
-                               setenv("mtddevnum", buf);
+                               setenv_ulong("mtddevnum", mtddevnum);
                                break;
                        }
                        mtddevnum += dev->num_parts;
@@ -338,8 +322,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
                 * checking for alignment is easy here
                 */
                if ((unsigned long)part->offset % mtd->erasesize) {
-                       printf("%s%d: partition (%s) start offset"
-                              "alignment incorrect\n",
+                       printf("%s%d: partition (%s) start offset alignment incorrect\n",
                               MTD_DEV_TYPE(id->type), id->num, part->name);
                        return 1;
                }
@@ -710,7 +693,7 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
  * @param size a pointer to the size of the mtd device (output)
  * @return 0 if device is valid, 1 otherwise
  */
-int mtd_device_validate(u8 type, u8 num, u32 *size)
+static int mtd_device_validate(u8 type, u8 num, u32 *size)
 {
        struct mtd_info *mtd = NULL;
 
@@ -1042,7 +1025,8 @@ static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_
  * @param dev_num parsed device number (output)
  * @return 0 on success, 1 otherwise
  */
-int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num)
+int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type,
+                u8 *dev_num)
 {
        const char *p = id;
 
@@ -1245,6 +1229,18 @@ static uint64_t net_part_size(struct mtd_info *mtd, struct part_info *part)
 }
 #endif
 
+static void show_ecc_stats(struct mtd_device *dev)
+{
+       struct mtd_info *mtd;
+
+       if (get_mtd_info(dev->id->type, dev->id->num, &mtd))
+               return;
+
+       printf("ECC stats for device %s:\n", mtd->name);
+       printf("  corrected bit flips:\t%4u\n", mtd->ecc_stats.corrected);
+       printf("  uncorrectable errors:\t%4u\n", mtd->ecc_stats.failed);
+}
+
 static void print_partition_table(void)
 {
        struct list_head *dentry, *pentry;
@@ -1292,6 +1288,7 @@ static void print_partition_table(void)
 #endif /* defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */
                        part_num++;
                }
+               show_ecc_stats(dev);
        }
 
        if (list_empty(&devices))
@@ -1421,7 +1418,7 @@ static int delete_partition(const char *id)
                        return 1;
 
                if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
-                       printf("generated mtdparts too long, reseting to null\n");
+                       printf("generated mtdparts too long, resetting to null\n");
                        return 1;
                }
                return 0;
@@ -1519,7 +1516,7 @@ static int spread_partitions(void)
        index_partitions();
 
        if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
-               printf("generated mtdparts too long, reseting to null\n");
+               printf("generated mtdparts too long, resetting to null\n");
                return 1;
        }
        return 0;
@@ -1538,6 +1535,7 @@ static int parse_mtdparts(const char *const mtdparts)
        const char *p = mtdparts;
        struct mtd_device *dev;
        int err = 1;
+       char tmp_parts[MTDPARTS_MAXLEN];
 
        debug("\n---parse_mtdparts---\nmtdparts = %s\n\n", p);
 
@@ -1548,7 +1546,12 @@ static int parse_mtdparts(const char *const mtdparts)
        }
 
        /* re-read 'mtdparts' variable, mtd_devices_init may be updating env */
-       p = getenv("mtdparts");
+       if (gd->flags & GD_FLG_ENV_READY) {
+               p = getenv("mtdparts");
+       } else {
+               p = tmp_parts;
+               getenv_f("mtdparts", tmp_parts, MTDPARTS_MAXLEN);
+       }
 
        if (strncmp(p, "mtdparts=", 9) != 0) {
                printf("mtdparts variable doesn't start with 'mtdparts='\n");
@@ -1706,6 +1709,7 @@ int mtdparts_init(void)
        const char *current_partition;
        int ids_changed;
        char tmp_ep[PARTITION_MAXLEN];
+       char tmp_parts[MTDPARTS_MAXLEN];
 
        debug("\n---mtdparts_init---\n");
        if (!initialized) {
@@ -1719,7 +1723,17 @@ int mtdparts_init(void)
 
        /* get variables */
        ids = getenv("mtdids");
-       parts = getenv("mtdparts");
+       /*
+        * The mtdparts variable tends to be long. If we need to access it
+        * before the env is relocated, then we need to use our own stack
+        * buffer.  gd->env_buf will be too small.
+        */
+       if (gd->flags & GD_FLG_ENV_READY) {
+               parts = getenv("mtdparts");
+       } else {
+               parts = tmp_parts;
+               getenv_f("mtdparts", tmp_parts, MTDPARTS_MAXLEN);
+       }
        current_partition = getenv("partition");
 
        /* save it for later parsing, cannot rely on current partition pointer
@@ -1884,7 +1898,7 @@ static struct part_info* mtd_part_info(struct mtd_device *dev, unsigned int part
  * @param argv arguments list
  * @return 0 on success, 1 otherwise
  */
-int do_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 /* command line only */
        struct mtd_device *dev;
@@ -1922,7 +1936,8 @@ int do_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  * @param argv arguments list
  * @return 0 on success, 1 otherwise
  */
-int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc,
+                      char * const argv[])
 {
        if (argc == 2) {
                if (strcmp(argv[1], "default") == 0) {
@@ -2016,7 +2031,7 @@ int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                }
 
                if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
-                       printf("generated mtdparts too long, reseting to null\n");
+                       printf("generated mtdparts too long, resetting to null\n");
                        return 1;
                }
 
@@ -2035,7 +2050,7 @@ int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                return spread_partitions();
 #endif /* CONFIG_CMD_MTDPARTS_SPREAD */
 
-       return cmd_usage(cmdtp);
+       return CMD_RET_USAGE;
 }
 
 /***************************************************/
@@ -2046,9 +2061,8 @@ U_BOOT_CMD(
        "    - change active partition (e.g. part-id = nand0,1)"
 );
 
-U_BOOT_CMD(
-       mtdparts,       6,      0,      do_mtdparts,
-       "define flash/nand partitions",
+#ifdef CONFIG_SYS_LONGHELP
+static char mtdparts_help_text[] =
        "\n"
        "    - list partition table\n"
        "mtdparts delall\n"
@@ -2090,6 +2104,11 @@ U_BOOT_CMD(
        "<size>     := standard linux memsize OR '-' to denote all remaining space\n"
        "<offset>   := partition start offset within the device\n"
        "<name>     := '(' NAME ')'\n"
-       "<ro-flag>  := when set to 'ro' makes partition read-only (not used, passed to kernel)"
+       "<ro-flag>  := when set to 'ro' makes partition read-only (not used, passed to kernel)";
+#endif
+
+U_BOOT_CMD(
+       mtdparts,       6,      0,      do_mtdparts,
+       "define flash/nand partitions", mtdparts_help_text
 );
 /***************************************************/