/* * (C) Copyright 2007 Schindler Lift Inc. * (C) Copyright 2007 DENX Software Engineering * * Author: Michel Marti * Adapted for U-Boot 1.2 by Piotr Kruszynski : * - code clean-up * - bugfix for overwriting bootargs by user * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include #include #include "fwupdate.h" static int load_rescue_image(ulong); void cm5200_fwupdate(void) { cmd_tbl_t *bcmd; char *rsargs; char *tmp = NULL; char ka[16]; char * const 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", (ulong)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 * const argv[6] = { "fatload", "usb", dev, addr_str, nxri, NULL }; struct blk_desc *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 = blk_get_devnum_by_type(IF_TYPE_USB, 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 (part_get_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 (!fat_exists(fwdir)) { 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; }