GCC4.6: Squash warnings in 4xx_pcie.c
[platform/kernel/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 long do_fat_read(const char *, void *, unsigned long, int);
39 extern int do_fat_fsload(cmd_tbl_t *, int, int, char * const []);
40
41 static int load_rescue_image(ulong);
42
43 void 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
90 static 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 }