summaryrefslogtreecommitdiff
path: root/board/cm5200/fwupdate.c
diff options
context:
space:
mode:
Diffstat (limited to 'board/cm5200/fwupdate.c')
-rw-r--r--board/cm5200/fwupdate.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/board/cm5200/fwupdate.c b/board/cm5200/fwupdate.c
new file mode 100644
index 0000000000..19aa94a5a0
--- /dev/null
+++ b/board/cm5200/fwupdate.c
@@ -0,0 +1,200 @@
+/*
+ * (C) Copyright 2007 Schindler Lift Inc.
+ * (C) Copyright 2007 DENX Software Engineering
+ *
+ * Author: Michel Marti <mma@objectxp.com>
+ * Adapted for U-Boot 1.2 by Piotr Kruszynski <ppk@semihalf.com>:
+ * - code clean-up
+ * - bugfix for overwriting bootargs by user
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <image.h>
+#include <usb.h>
+#include <fat.h>
+
+#include "fwupdate.h"
+
+extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
+extern long do_fat_read(const char *, void *, unsigned long, int);
+extern int do_fat_fsload(cmd_tbl_t *, int, int, char *[]);
+
+static int load_rescue_image(ulong);
+
+void cm5200_fwupdate(void)
+{
+ cmd_tbl_t *bcmd;
+ char *rsargs;
+ char *tmp = NULL;
+ char ka[16];
+ char *argv[3] = { "bootm", ka, NULL };
+
+ /* Check if rescue system is disabled... */
+ if (getenv("norescue")) {
+ printf(LOG_PREFIX "Rescue System disabled.\n");
+ return;
+ }
+
+ /* Check if we have a USB storage device and load image */
+ if (load_rescue_image(LOAD_ADDR))
+ return;
+
+ bcmd = find_cmd("bootm");
+ if (!bcmd)
+ return;
+
+ sprintf(ka, "%lx", LOAD_ADDR);
+
+ /* prepare our bootargs */
+ rsargs = getenv("rs-args");
+ if (!rsargs)
+ rsargs = RS_BOOTARGS;
+ else {
+ tmp = malloc(strlen(rsargs+1));
+ if (!tmp) {
+ printf(LOG_PREFIX "Memory allocation failed\n");
+ return;
+ }
+ strcpy(tmp, rsargs);
+ rsargs = tmp;
+ }
+
+ setenv("bootargs", rsargs);
+
+ if (rsargs == tmp)
+ free(rsargs);
+
+ printf(LOG_PREFIX "Starting update system (bootargs=%s)...\n", rsargs);
+ do_bootm(bcmd, 0, 2, argv);
+}
+
+static int load_rescue_image(ulong addr)
+{
+ disk_partition_t info;
+ int devno;
+ int partno;
+ int i;
+ char fwdir[64];
+ char nxri[128];
+ char *tmp;
+ char dev[7];
+ char addr_str[16];
+ char *argv[6] = { "fatload", "usb", dev, addr_str, nxri, NULL };
+ block_dev_desc_t *stor_dev = NULL;
+ cmd_tbl_t *bcmd;
+
+ /* Get name of firmware directory */
+ tmp = getenv("fw-dir");
+
+ /* Copy it into fwdir */
+ strncpy(fwdir, tmp ? tmp : FW_DIR, sizeof(fwdir));
+ fwdir[sizeof(fwdir) - 1] = 0; /* Terminate string */
+
+ printf(LOG_PREFIX "Checking for firmware image directory '%s' on USB"
+ " storage...\n", fwdir);
+ usb_stop();
+ if (usb_init() != 0)
+ return 1;
+
+ /* Check for storage device */
+ if (usb_stor_scan(1) != 0) {
+ usb_stop();
+ return 1;
+ }
+
+ /* Detect storage device */
+ for (devno = 0; devno < USB_MAX_STOR_DEV; devno++) {
+ stor_dev = usb_stor_get_dev(devno);
+ if (stor_dev->type != DEV_TYPE_UNKNOWN)
+ break;
+ }
+ if (!stor_dev || stor_dev->type == DEV_TYPE_UNKNOWN) {
+ printf(LOG_PREFIX "No valid storage device found...\n");
+ usb_stop();
+ return 1;
+ }
+
+ /* Detect partition */
+ for (partno = -1, i = 0; i < 6; i++) {
+ if (get_partition_info(stor_dev, i, &info) == 0) {
+ if (fat_register_device(stor_dev, i) == 0) {
+ /* Check if rescue image is present */
+ FW_DEBUG("Looking for firmware directory '%s'"
+ " on partition %d\n", fwdir, i);
+ if (do_fat_read(fwdir, NULL, 0, LS_NO) == -1) {
+ FW_DEBUG("No NX rescue image on "
+ "partition %d.\n", i);
+ partno = -2;
+ } else {
+ partno = i;
+ FW_DEBUG("Partition %d contains "
+ "firmware directory\n", partno);
+ break;
+ }
+ }
+ }
+ }
+
+ if (partno < 0) {
+ switch (partno) {
+ case -1:
+ printf(LOG_PREFIX "Error: No valid (FAT) partition "
+ "detected\n");
+ break;
+ case -2:
+ printf(LOG_PREFIX "Error: No NX rescue image on FAT "
+ "partition\n");
+ break;
+ default:
+ printf(LOG_PREFIX "Error: Failed with code %d\n",
+ partno);
+ }
+ usb_stop();
+ return 1;
+ }
+
+ /* Load the rescue image */
+ bcmd = find_cmd("fatload");
+ if (!bcmd) {
+ printf(LOG_PREFIX "Error - 'fatload' command not present.\n");
+ usb_stop();
+ return 1;
+ }
+
+ tmp = getenv("nx-rescue-image");
+ sprintf(nxri, "%s/%s", fwdir, tmp ? tmp : RESCUE_IMAGE);
+ sprintf(dev, "%d:%d", devno, partno);
+ sprintf(addr_str, "%lx", addr);
+
+ FW_DEBUG("fat_fsload device='%s', addr='%s', file: %s\n",
+ dev, addr_str, nxri);
+
+ if (do_fat_fsload(bcmd, 0, 5, argv) != 0) {
+ usb_stop();
+ return 1;
+ }
+
+ /* Stop USB */
+ usb_stop();
+ return 0;
+}