blob: 06d50234e9ab046b544d95f03852f704480a8aba [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 *
Wolfgang Denk3765b3e2013-10-07 13:07:26 +020010 * SPDX-License-Identifier: GPL-2.0+
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020011 */
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
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020022extern long do_fat_read(const char *, void *, unsigned long, int);
Wolfgang Denk54841ab2010-06-28 22:00:46 +020023extern int do_fat_fsload(cmd_tbl_t *, int, int, char * const []);
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020024
25static int load_rescue_image(ulong);
26
Bartlomiej Sieka86b116b2007-08-03 12:08:16 +020027void cm5200_fwupdate(void)
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020028{
29 cmd_tbl_t *bcmd;
30 char *rsargs;
31 char *tmp = NULL;
32 char ka[16];
Wolfgang Denk54841ab2010-06-28 22:00:46 +020033 char * const argv[3] = { "bootm", ka, NULL };
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020034
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
Wolfgang Denk9b55a252008-07-11 01:16:00 +020049 sprintf(ka, "%lx", (ulong)LOAD_ADDR);
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020050
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
74static 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];
Wolfgang Denk54841ab2010-06-28 22:00:46 +020085 char * const argv[6] = { "fatload", "usb", dev, addr_str, nxri, NULL };
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020086 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);
Bartlomiej Sieka86b116b2007-08-03 12:08:16 +0200130 partno = -2;
Bartlomiej Siekafa1df302007-07-11 20:11:07 +0200131 } else {
132 partno = i;
133 FW_DEBUG("Partition %d contains "
134 "firmware directory\n", partno);
135 break;
136 }
137 }
138 }
139 }
140
Bartlomiej Sieka86b116b2007-08-03 12:08:16 +0200141 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 }
Bartlomiej Siekafa1df302007-07-11 20:11:07 +0200155 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}