uboot/board/cm5200/fwupdate.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2007 Schindler Lift Inc.
   3 * (C) Copyright 2007 DENX Software Engineering
   4 *
   5 * Author: Michel Marti <mma@objectxp.com>
   6 * Adapted for U-Boot 1.2 by Piotr Kruszynski <ppk@semihalf.com>:
   7 *   - code clean-up
   8 *   - bugfix for overwriting bootargs by user
   9 *
  10 * See file CREDITS for list of people who contributed to this
  11 * project.
  12 *
  13 * This program is free software; you can redistribute it and/or
  14 * modify it under the terms of the GNU General Public License as
  15 * published by the Free Software Foundation; either version 2 of
  16 * the License, or (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 *
  23 * You should have received a copy of the GNU General Public License
  24 * along with this program; if not, write to the Free Software
  25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  26 * MA 02111-1307 USA
  27 */
  28
  29#include <common.h>
  30#include <command.h>
  31#include <malloc.h>
  32#include <image.h>
  33#include <usb.h>
  34#include <fat.h>
  35
  36#include "fwupdate.h"
  37
  38extern long do_fat_read(const char *, void *, unsigned long, int);
  39extern int do_fat_fsload(cmd_tbl_t *, int, int, char * const []);
  40
  41static int load_rescue_image(ulong);
  42
  43void cm5200_fwupdate(void)
  44{
  45        cmd_tbl_t *bcmd;
  46        char *rsargs;
  47        char *tmp = NULL;
  48        char ka[16];
  49        char * const argv[3] = { "bootm", ka, NULL };
  50
  51        /* Check if rescue system is disabled... */
  52        if (getenv("norescue")) {
  53                printf(LOG_PREFIX "Rescue System disabled.\n");
  54                return;
  55        }
  56
  57        /* Check if we have a USB storage device and load image */
  58        if (load_rescue_image(LOAD_ADDR))
  59                return;
  60
  61        bcmd = find_cmd("bootm");
  62        if (!bcmd)
  63                return;
  64
  65        sprintf(ka, "%lx", (ulong)LOAD_ADDR);
  66
  67        /* prepare our bootargs */
  68        rsargs = getenv("rs-args");
  69        if (!rsargs)
  70                rsargs = RS_BOOTARGS;
  71        else {
  72                tmp = malloc(strlen(rsargs+1));
  73                if (!tmp) {
  74                        printf(LOG_PREFIX "Memory allocation failed\n");
  75                        return;
  76                }
  77                strcpy(tmp, rsargs);
  78                rsargs = tmp;
  79        }
  80
  81        setenv("bootargs", rsargs);
  82
  83        if (rsargs == tmp)
  84                free(rsargs);
  85
  86        printf(LOG_PREFIX "Starting update system (bootargs=%s)...\n", rsargs);
  87        do_bootm(bcmd, 0, 2, argv);
  88}
  89
  90static int load_rescue_image(ulong addr)
  91{
  92        disk_partition_t info;
  93        int devno;
  94        int partno;
  95        int i;
  96        char fwdir[64];
  97        char nxri[128];
  98        char *tmp;
  99        char dev[7];
 100        char addr_str[16];
 101        char * const argv[6] = { "fatload", "usb", dev, addr_str, nxri, NULL };
 102        block_dev_desc_t *stor_dev = NULL;
 103        cmd_tbl_t *bcmd;
 104
 105        /* Get name of firmware directory */
 106        tmp = getenv("fw-dir");
 107
 108        /* Copy it into fwdir */
 109        strncpy(fwdir, tmp ? tmp : FW_DIR, sizeof(fwdir));
 110        fwdir[sizeof(fwdir) - 1] = 0; /* Terminate string */
 111
 112        printf(LOG_PREFIX "Checking for firmware image directory '%s' on USB"
 113                " storage...\n", fwdir);
 114        usb_stop();
 115        if (usb_init() != 0)
 116                return 1;
 117
 118        /* Check for storage device */
 119        if (usb_stor_scan(1) != 0) {
 120                usb_stop();
 121                return 1;
 122        }
 123
 124        /* Detect storage device */
 125        for (devno = 0; devno < USB_MAX_STOR_DEV; devno++) {
 126                stor_dev = usb_stor_get_dev(devno);
 127                if (stor_dev->type != DEV_TYPE_UNKNOWN)
 128                        break;
 129        }
 130        if (!stor_dev || stor_dev->type == DEV_TYPE_UNKNOWN) {
 131                printf(LOG_PREFIX "No valid storage device found...\n");
 132                usb_stop();
 133                return 1;
 134        }
 135
 136        /* Detect partition */
 137        for (partno = -1, i = 0; i < 6; i++) {
 138                if (get_partition_info(stor_dev, i, &info) == 0) {
 139                        if (fat_register_device(stor_dev, i) == 0) {
 140                                /* Check if rescue image is present */
 141                                FW_DEBUG("Looking for firmware directory '%s'"
 142                                        " on partition %d\n", fwdir, i);
 143                                if (do_fat_read(fwdir, NULL, 0, LS_NO) == -1) {
 144                                        FW_DEBUG("No NX rescue image on "
 145                                                "partition %d.\n", i);
 146                                        partno = -2;
 147                                } else {
 148                                        partno = i;
 149                                        FW_DEBUG("Partition %d contains "
 150                                                "firmware directory\n", partno);
 151                                        break;
 152                                }
 153                        }
 154                }
 155        }
 156
 157        if (partno < 0) {
 158                switch (partno) {
 159                case -1:
 160                        printf(LOG_PREFIX "Error: No valid (FAT) partition "
 161                                "detected\n");
 162                        break;
 163                case -2:
 164                        printf(LOG_PREFIX "Error: No NX rescue image on FAT "
 165                                "partition\n");
 166                        break;
 167                default:
 168                        printf(LOG_PREFIX "Error: Failed with code %d\n",
 169                                partno);
 170                }
 171                usb_stop();
 172                return 1;
 173        }
 174
 175        /* Load the rescue image */
 176        bcmd = find_cmd("fatload");
 177        if (!bcmd) {
 178                printf(LOG_PREFIX "Error - 'fatload' command not present.\n");
 179                usb_stop();
 180                return 1;
 181        }
 182
 183        tmp = getenv("nx-rescue-image");
 184        sprintf(nxri, "%s/%s", fwdir, tmp ? tmp : RESCUE_IMAGE);
 185        sprintf(dev, "%d:%d", devno, partno);
 186        sprintf(addr_str, "%lx", addr);
 187
 188        FW_DEBUG("fat_fsload device='%s', addr='%s', file: %s\n",
 189                dev, addr_str, nxri);
 190
 191        if (do_fat_fsload(bcmd, 0, 5, argv) != 0) {
 192                usb_stop();
 193                return 1;
 194        }
 195
 196        /* Stop USB */
 197        usb_stop();
 198        return 0;
 199}
 200