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