blob: 9d4eadcb66d4ca7ea4f08a5bd9a11be635b228aa [file] [log] [blame]
Bartlomiej Siekafa1df302007-07-11 20:11:07 +02001/*
2 * (C) Copyright 2007 Schindler Lift Inc.
Bartlomiej Sieka86b116b2007-08-03 12:08:16 +02003 * (C) Copyright 2007 DENX Software Engineering
Bartlomiej Siekafa1df302007-07-11 20:11:07 +02004 *
5 * Author: Michel Marti <mma@objectxp.com>
6 * Adapted for U-Boot 1.2 by Piotr Kruszynski <ppk@semihalf.com>:
Bartlomiej Sieka86b116b2007-08-03 12:08:16 +02007 * - code clean-up
8 * - bugfix for overwriting bootargs by user
Bartlomiej Siekafa1df302007-07-11 20:11:07 +02009 *
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
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020038extern long do_fat_read(const char *, void *, unsigned long, int);
Wolfgang Denk54841ab2010-06-28 22:00:46 +020039extern int do_fat_fsload(cmd_tbl_t *, int, int, char * const []);
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020040
41static int load_rescue_image(ulong);
42
Bartlomiej Sieka86b116b2007-08-03 12:08:16 +020043void cm5200_fwupdate(void)
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020044{
45 cmd_tbl_t *bcmd;
46 char *rsargs;
47 char *tmp = NULL;
48 char ka[16];
Wolfgang Denk54841ab2010-06-28 22:00:46 +020049 char * const argv[3] = { "bootm", ka, NULL };
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020050
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
Wolfgang Denk9b55a252008-07-11 01:16:00 +020065 sprintf(ka, "%lx", (ulong)LOAD_ADDR);
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020066
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];
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200101 char * const argv[6] = { "fatload", "usb", dev, addr_str, nxri, NULL };
Bartlomiej Siekafa1df302007-07-11 20:11:07 +0200102 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);
Bartlomiej Sieka86b116b2007-08-03 12:08:16 +0200146 partno = -2;
Bartlomiej Siekafa1df302007-07-11 20:11:07 +0200147 } else {
148 partno = i;
149 FW_DEBUG("Partition %d contains "
150 "firmware directory\n", partno);
151 break;
152 }
153 }
154 }
155 }
156
Bartlomiej Sieka86b116b2007-08-03 12:08:16 +0200157 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 }
Bartlomiej Siekafa1df302007-07-11 20:11:07 +0200171 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}