blob: 4740c8394c5fa699088c2316df10e11f4ea06597 [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>
Stephen Warren26f8a4a2015-08-09 11:25:00 -060015#include <fat.h>
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020016#include <malloc.h>
17#include <image.h>
18#include <usb.h>
19#include <fat.h>
20
21#include "fwupdate.h"
22
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020023static int load_rescue_image(ulong);
24
Bartlomiej Sieka86b116b2007-08-03 12:08:16 +020025void cm5200_fwupdate(void)
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020026{
27 cmd_tbl_t *bcmd;
28 char *rsargs;
29 char *tmp = NULL;
30 char ka[16];
Wolfgang Denk54841ab2010-06-28 22:00:46 +020031 char * const argv[3] = { "bootm", ka, NULL };
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020032
33 /* Check if rescue system is disabled... */
34 if (getenv("norescue")) {
35 printf(LOG_PREFIX "Rescue System disabled.\n");
36 return;
37 }
38
39 /* Check if we have a USB storage device and load image */
40 if (load_rescue_image(LOAD_ADDR))
41 return;
42
43 bcmd = find_cmd("bootm");
44 if (!bcmd)
45 return;
46
Wolfgang Denk9b55a252008-07-11 01:16:00 +020047 sprintf(ka, "%lx", (ulong)LOAD_ADDR);
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020048
49 /* prepare our bootargs */
50 rsargs = getenv("rs-args");
51 if (!rsargs)
52 rsargs = RS_BOOTARGS;
53 else {
54 tmp = malloc(strlen(rsargs+1));
55 if (!tmp) {
56 printf(LOG_PREFIX "Memory allocation failed\n");
57 return;
58 }
59 strcpy(tmp, rsargs);
60 rsargs = tmp;
61 }
62
63 setenv("bootargs", rsargs);
64
65 if (rsargs == tmp)
66 free(rsargs);
67
68 printf(LOG_PREFIX "Starting update system (bootargs=%s)...\n", rsargs);
69 do_bootm(bcmd, 0, 2, argv);
70}
71
72static int load_rescue_image(ulong addr)
73{
74 disk_partition_t info;
75 int devno;
76 int partno;
77 int i;
78 char fwdir[64];
79 char nxri[128];
80 char *tmp;
81 char dev[7];
82 char addr_str[16];
Wolfgang Denk54841ab2010-06-28 22:00:46 +020083 char * const argv[6] = { "fatload", "usb", dev, addr_str, nxri, NULL };
Simon Glass4101f682016-02-29 15:25:34 -070084 struct blk_desc *stor_dev = NULL;
Bartlomiej Siekafa1df302007-07-11 20:11:07 +020085 cmd_tbl_t *bcmd;
86
87 /* Get name of firmware directory */
88 tmp = getenv("fw-dir");
89
90 /* Copy it into fwdir */
91 strncpy(fwdir, tmp ? tmp : FW_DIR, sizeof(fwdir));
92 fwdir[sizeof(fwdir) - 1] = 0; /* Terminate string */
93
94 printf(LOG_PREFIX "Checking for firmware image directory '%s' on USB"
95 " storage...\n", fwdir);
96 usb_stop();
97 if (usb_init() != 0)
98 return 1;
99
100 /* Check for storage device */
101 if (usb_stor_scan(1) != 0) {
102 usb_stop();
103 return 1;
104 }
105
106 /* Detect storage device */
107 for (devno = 0; devno < USB_MAX_STOR_DEV; devno++) {
Simon Glass57ebf672016-05-01 11:36:13 -0600108 stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, devno);
Bartlomiej Siekafa1df302007-07-11 20:11:07 +0200109 if (stor_dev->type != DEV_TYPE_UNKNOWN)
110 break;
111 }
112 if (!stor_dev || stor_dev->type == DEV_TYPE_UNKNOWN) {
113 printf(LOG_PREFIX "No valid storage device found...\n");
114 usb_stop();
115 return 1;
116 }
117
118 /* Detect partition */
119 for (partno = -1, i = 0; i < 6; i++) {
Simon Glass3e8bd462016-02-29 15:25:48 -0700120 if (part_get_info(stor_dev, i, &info) == 0) {
Bartlomiej Siekafa1df302007-07-11 20:11:07 +0200121 if (fat_register_device(stor_dev, i) == 0) {
122 /* Check if rescue image is present */
123 FW_DEBUG("Looking for firmware directory '%s'"
124 " on partition %d\n", fwdir, i);
Stephen Warren26f8a4a2015-08-09 11:25:00 -0600125 if (!fat_exists(fwdir)) {
Bartlomiej Siekafa1df302007-07-11 20:11:07 +0200126 FW_DEBUG("No NX rescue image on "
127 "partition %d.\n", i);
Bartlomiej Sieka86b116b2007-08-03 12:08:16 +0200128 partno = -2;
Bartlomiej Siekafa1df302007-07-11 20:11:07 +0200129 } else {
130 partno = i;
131 FW_DEBUG("Partition %d contains "
132 "firmware directory\n", partno);
133 break;
134 }
135 }
136 }
137 }
138
Bartlomiej Sieka86b116b2007-08-03 12:08:16 +0200139 if (partno < 0) {
140 switch (partno) {
141 case -1:
142 printf(LOG_PREFIX "Error: No valid (FAT) partition "
143 "detected\n");
144 break;
145 case -2:
146 printf(LOG_PREFIX "Error: No NX rescue image on FAT "
147 "partition\n");
148 break;
149 default:
150 printf(LOG_PREFIX "Error: Failed with code %d\n",
151 partno);
152 }
Bartlomiej Siekafa1df302007-07-11 20:11:07 +0200153 usb_stop();
154 return 1;
155 }
156
157 /* Load the rescue image */
158 bcmd = find_cmd("fatload");
159 if (!bcmd) {
160 printf(LOG_PREFIX "Error - 'fatload' command not present.\n");
161 usb_stop();
162 return 1;
163 }
164
165 tmp = getenv("nx-rescue-image");
166 sprintf(nxri, "%s/%s", fwdir, tmp ? tmp : RESCUE_IMAGE);
167 sprintf(dev, "%d:%d", devno, partno);
168 sprintf(addr_str, "%lx", addr);
169
170 FW_DEBUG("fat_fsload device='%s', addr='%s', file: %s\n",
171 dev, addr_str, nxri);
172
173 if (do_fat_fsload(bcmd, 0, 5, argv) != 0) {
174 usb_stop();
175 return 1;
176 }
177
178 /* Stop USB */
179 usb_stop();
180 return 0;
181}