2
* (C) Copyright 2008 Semihalf
4
* Written by: Rafal Czubak <rcz@semihalf.com>
5
* Bartlomiej Sieka <tur@semihalf.com>
7
* See file CREDITS for list of people who contributed to this
10
* This program is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU General Public License as
12
* published by the Free Software Foundation; either version 2 of
13
* the License, or (at your option) any later version.
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29
#if !(defined(CONFIG_FIT) && defined(CONFIG_OF_LIBFDT))
30
#error "CONFIG_FIT and CONFIG_OF_LIBFDT are required for auto-update feature"
33
#if defined(CONFIG_SYS_NO_FLASH)
34
#error "CONFIG_SYS_NO_FLASH defined, but FLASH is required for auto-update feature"
42
/* env variable holding the location of the update file */
43
#define UPDATE_FILE_ENV "updatefile"
45
/* set configuration defaults if needed */
46
#ifndef CONFIG_UPDATE_LOAD_ADDR
47
#define CONFIG_UPDATE_LOAD_ADDR 0x100000
50
#ifndef CONFIG_UPDATE_TFTP_MSEC_MAX
51
#define CONFIG_UPDATE_TFTP_MSEC_MAX 100
54
#ifndef CONFIG_UPDATE_TFTP_CNT_MAX
55
#define CONFIG_UPDATE_TFTP_CNT_MAX 0
58
extern ulong TftpRRQTimeoutMSecs;
59
extern int TftpRRQTimeoutCountMax;
60
extern flash_info_t flash_info[];
61
extern ulong load_addr;
63
static uchar *saved_prot_info;
65
static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr)
68
ulong saved_timeout_msecs;
69
int saved_timeout_count;
70
char *saved_netretry, *saved_bootfile;
73
/* save used globals and env variable */
74
saved_timeout_msecs = TftpRRQTimeoutMSecs;
75
saved_timeout_count = TftpRRQTimeoutCountMax;
76
saved_netretry = strdup(getenv("netretry"));
77
saved_bootfile = strdup(BootFile);
79
/* set timeouts for auto-update */
80
TftpRRQTimeoutMSecs = msec_max;
81
TftpRRQTimeoutCountMax = cnt_max;
83
/* we don't want to retry the connection if errors occur */
84
setenv("netretry", "no");
86
/* download the update file */
88
copy_filename(BootFile, filename, sizeof(BootFile));
94
flush_cache(addr, size);
96
/* restore changed globals and env variable */
97
TftpRRQTimeoutMSecs = saved_timeout_msecs;
98
TftpRRQTimeoutCountMax = saved_timeout_count;
100
setenv("netretry", saved_netretry);
101
if (saved_netretry != NULL)
102
free(saved_netretry);
104
if (saved_bootfile != NULL) {
105
copy_filename(BootFile, saved_bootfile, sizeof(BootFile));
106
free(saved_bootfile);
112
static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
123
calloc(CONFIG_SYS_MAX_FLASH_BANKS * CONFIG_SYS_MAX_FLASH_SECT, 1);
124
if (!saved_prot_info)
128
for (bank = 0; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank) {
130
info = &flash_info[bank];
132
/* Nothing to do if the bank doesn't exist */
133
if (info->sector_count == 0)
136
/* Point to current bank protection information */
137
sp_info_ptr = saved_prot_info + (bank * CONFIG_SYS_MAX_FLASH_SECT);
140
* Adjust addr_first or addr_last if we are on bank boundary.
141
* Address space between banks must be continuous for other
142
* flash functions (like flash_sect_erase or flash_write) to
143
* succeed. Banks must also be numbered in correct order,
144
* according to increasing addresses.
146
if (addr_last > info->start[0] + info->size - 1)
147
addr_last = info->start[0] + info->size - 1;
148
if (addr_first < info->start[0])
149
addr_first = info->start[0];
151
for (i = 0; i < info->sector_count; i++) {
152
/* Save current information about protected sectors */
155
if ((s >= addr_first) && (s <= addr_last))
156
sp_info_ptr[i] = info->protect[i];
160
/* Protect/unprotect sectors */
161
if (sp_info_ptr[i] == 1) {
162
#if defined(CONFIG_SYS_FLASH_PROTECTION)
163
if (flash_real_protect(info, i, prot))
166
info->protect[i] = prot;
173
printf("%sProtected %d sectors\n",
174
prot ? "": "Un-", cnt);
178
if((prot == 1) && saved_prot_info)
179
free(saved_prot_info);
184
static int update_flash(ulong addr_source, ulong addr_first, ulong size)
186
ulong addr_last = addr_first + size - 1;
188
/* round last address to the sector boundary */
189
if (flash_sect_roundb(&addr_last) > 0)
192
if (addr_first >= addr_last) {
193
printf("Error: end address exceeds addressing space\n");
197
/* remove protection on processed sectors */
198
if (update_flash_protect(0, addr_first, addr_last) > 0) {
199
printf("Error: could not unprotect flash sectors\n");
203
printf("Erasing 0x%08lx - 0x%08lx", addr_first, addr_last);
204
if (flash_sect_erase(addr_first, addr_last) > 0) {
205
printf("Error: could not erase flash\n");
209
printf("Copying to flash...");
210
if (flash_write((char *)addr_source, addr_first, size) > 0) {
211
printf("Error: could not copy to flash\n");
216
/* enable protection on processed sectors */
217
if (update_flash_protect(1, addr_first, addr_last) > 0) {
218
printf("Error: could not protect flash sectors\n");
225
static int update_fit_getparams(const void *fit, int noffset, ulong *addr,
226
ulong *fladdr, ulong *size)
230
if (fit_image_get_data(fit, noffset, &data, (size_t *)size))
233
if (fit_image_get_load(fit, noffset, (ulong *)fladdr))
241
void update_tftp(void)
243
char *filename, *env_addr;
244
int images_noffset, ndepth, noffset;
245
ulong update_addr, update_fladdr, update_size;
249
printf("Auto-update from TFTP: ");
251
/* get the file name of the update file */
252
filename = getenv(UPDATE_FILE_ENV);
253
if (filename == NULL) {
254
printf("failed, env. variable '%s' not found\n",
259
printf("trying update file '%s'\n", filename);
261
/* get load address of downloaded update file */
262
if ((env_addr = getenv("loadaddr")) != NULL)
263
addr = simple_strtoul(env_addr, NULL, 16);
265
addr = CONFIG_UPDATE_LOAD_ADDR;
268
if (update_load(filename, CONFIG_UPDATE_TFTP_MSEC_MAX,
269
CONFIG_UPDATE_TFTP_CNT_MAX, addr)) {
270
printf("Can't load update file, aborting auto-update\n");
276
if (!fit_check_format((void *)fit)) {
277
printf("Bad FIT format of the update file, aborting "
282
/* process updates */
283
images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
286
noffset = fdt_next_node(fit, images_noffset, &ndepth);
287
while (noffset >= 0 && ndepth > 0) {
291
printf("Processing update '%s' :",
292
fit_get_name(fit, noffset, NULL));
294
if (!fit_image_check_hashes(fit, noffset)) {
295
printf("Error: invalid update hash, aborting\n");
300
if (update_fit_getparams(fit, noffset, &update_addr,
301
&update_fladdr, &update_size)) {
302
printf("Error: can't get update parameteres, "
306
if (update_flash(update_addr, update_fladdr, update_size)) {
307
printf("Error: can't flash update, aborting\n");
311
noffset = fdt_next_node(fit, noffset, &ndepth);