]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/cm5200/fwupdate.c
Merge with git://www.denx.de/git/u-boot.git
[people/ms/u-boot.git] / board / cm5200 / fwupdate.c
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
38 extern int do_bootm(cmd_tbl_t *, int, int, char *[]);
39 extern long do_fat_read(const char *, void *, unsigned long, int);
40 extern int do_fat_fsload(cmd_tbl_t *, int, int, char *[]);
41
42 static int load_rescue_image(ulong);
43
44 void cm5200_fwupdate(void)
45 {
46 cmd_tbl_t *bcmd;
47 char *rsargs;
48 char *tmp = NULL;
49 char ka[16];
50 char *argv[3] = { "bootm", ka, NULL };
51
52 /* Check if rescue system is disabled... */
53 if (getenv("norescue")) {
54 printf(LOG_PREFIX "Rescue System disabled.\n");
55 return;
56 }
57
58 /* Check if we have a USB storage device and load image */
59 if (load_rescue_image(LOAD_ADDR))
60 return;
61
62 bcmd = find_cmd("bootm");
63 if (!bcmd)
64 return;
65
66 sprintf(ka, "%lx", LOAD_ADDR);
67
68 /* prepare our bootargs */
69 rsargs = getenv("rs-args");
70 if (!rsargs)
71 rsargs = RS_BOOTARGS;
72 else {
73 tmp = malloc(strlen(rsargs+1));
74 if (!tmp) {
75 printf(LOG_PREFIX "Memory allocation failed\n");
76 return;
77 }
78 strcpy(tmp, rsargs);
79 rsargs = tmp;
80 }
81
82 setenv("bootargs", rsargs);
83
84 if (rsargs == tmp)
85 free(rsargs);
86
87 printf(LOG_PREFIX "Starting update system (bootargs=%s)...\n", rsargs);
88 do_bootm(bcmd, 0, 2, argv);
89 }
90
91 static int load_rescue_image(ulong addr)
92 {
93 disk_partition_t info;
94 int devno;
95 int partno;
96 int i;
97 char fwdir[64];
98 char nxri[128];
99 char *tmp;
100 char dev[7];
101 char addr_str[16];
102 char *argv[6] = { "fatload", "usb", dev, addr_str, nxri, NULL };
103 block_dev_desc_t *stor_dev = NULL;
104 cmd_tbl_t *bcmd;
105
106 /* Get name of firmware directory */
107 tmp = getenv("fw-dir");
108
109 /* Copy it into fwdir */
110 strncpy(fwdir, tmp ? tmp : FW_DIR, sizeof(fwdir));
111 fwdir[sizeof(fwdir) - 1] = 0; /* Terminate string */
112
113 printf(LOG_PREFIX "Checking for firmware image directory '%s' on USB"
114 " storage...\n", fwdir);
115 usb_stop();
116 if (usb_init() != 0)
117 return 1;
118
119 /* Check for storage device */
120 if (usb_stor_scan(1) != 0) {
121 usb_stop();
122 return 1;
123 }
124
125 /* Detect storage device */
126 for (devno = 0; devno < USB_MAX_STOR_DEV; devno++) {
127 stor_dev = usb_stor_get_dev(devno);
128 if (stor_dev->type != DEV_TYPE_UNKNOWN)
129 break;
130 }
131 if (!stor_dev || stor_dev->type == DEV_TYPE_UNKNOWN) {
132 printf(LOG_PREFIX "No valid storage device found...\n");
133 usb_stop();
134 return 1;
135 }
136
137 /* Detect partition */
138 for (partno = -1, i = 0; i < 6; i++) {
139 if (get_partition_info(stor_dev, i, &info) == 0) {
140 if (fat_register_device(stor_dev, i) == 0) {
141 /* Check if rescue image is present */
142 FW_DEBUG("Looking for firmware directory '%s'"
143 " on partition %d\n", fwdir, i);
144 if (do_fat_read(fwdir, NULL, 0, LS_NO) == -1) {
145 FW_DEBUG("No NX rescue image on "
146 "partition %d.\n", i);
147 partno = -2;
148 } else {
149 partno = i;
150 FW_DEBUG("Partition %d contains "
151 "firmware directory\n", partno);
152 break;
153 }
154 }
155 }
156 }
157
158 if (partno < 0) {
159 switch (partno) {
160 case -1:
161 printf(LOG_PREFIX "Error: No valid (FAT) partition "
162 "detected\n");
163 break;
164 case -2:
165 printf(LOG_PREFIX "Error: No NX rescue image on FAT "
166 "partition\n");
167 break;
168 default:
169 printf(LOG_PREFIX "Error: Failed with code %d\n",
170 partno);
171 }
172 usb_stop();
173 return 1;
174 }
175
176 /* Load the rescue image */
177 bcmd = find_cmd("fatload");
178 if (!bcmd) {
179 printf(LOG_PREFIX "Error - 'fatload' command not present.\n");
180 usb_stop();
181 return 1;
182 }
183
184 tmp = getenv("nx-rescue-image");
185 sprintf(nxri, "%s/%s", fwdir, tmp ? tmp : RESCUE_IMAGE);
186 sprintf(dev, "%d:%d", devno, partno);
187 sprintf(addr_str, "%lx", addr);
188
189 FW_DEBUG("fat_fsload device='%s', addr='%s', file: %s\n",
190 dev, addr_str, nxri);
191
192 if (do_fat_fsload(bcmd, 0, 5, argv) != 0) {
193 usb_stop();
194 return 1;
195 }
196
197 /* Stop USB */
198 usb_stop();
199 return 0;
200 }