Commit 5b3375ac8c36c29c87abb132fede0509eb21e5c9

Authored by Mike Frysinger
Committed by Wolfgang Denk
1 parent ecf5f077c8

env_sf: support embedded environments

If both CONFIG_ENV_SECT_SIZE and CONFIG_ENV_SIZE are defined, and the sect
size is larger than the env size, then it means the env is embedded in a
block.  So we have to save/restore the part of the sector which is not the
environment.  Previously, saving the environment in SPI flash in this
setup would probably brick the board as the rest of the sector tends to
contain actual U-Boot data/code.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Acked-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com>

Showing 1 changed file with 36 additions and 5 deletions Inline Diff

1 /* 1 /*
2 * (C) Copyright 2000-2002 2 * (C) Copyright 2000-2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 * 4 *
5 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> 5 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
6 * Andreas Heppel <aheppel@sysgo.de> 6 * Andreas Heppel <aheppel@sysgo.de>
7 * 7 *
8 * (C) Copyright 2008 Atmel Corporation 8 * (C) Copyright 2008 Atmel Corporation
9 * 9 *
10 * See file CREDITS for list of people who contributed to this 10 * See file CREDITS for list of people who contributed to this
11 * project. 11 * project.
12 * 12 *
13 * This program is free software; you can redistribute it and/or 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 14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation; either version 2 of 15 * published by the Free Software Foundation; either version 2 of
16 * the License, or (at your option) any later version. 16 * the License, or (at your option) any later version.
17 * 17 *
18 * This program is distributed in the hope that it will be useful, 18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details. 21 * GNU General Public License for more details.
22 * 22 *
23 * You should have received a copy of the GNU General Public License 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 24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
26 * MA 02111-1307 USA 26 * MA 02111-1307 USA
27 */ 27 */
28 #include <common.h> 28 #include <common.h>
29 #include <environment.h> 29 #include <environment.h>
30 #include <malloc.h>
30 #include <spi_flash.h> 31 #include <spi_flash.h>
31 32
32 #ifndef CONFIG_ENV_SPI_BUS 33 #ifndef CONFIG_ENV_SPI_BUS
33 # define CONFIG_ENV_SPI_BUS 0 34 # define CONFIG_ENV_SPI_BUS 0
34 #endif 35 #endif
35 #ifndef CONFIG_ENV_SPI_CS 36 #ifndef CONFIG_ENV_SPI_CS
36 # define CONFIG_ENV_SPI_CS 0 37 # define CONFIG_ENV_SPI_CS 0
37 #endif 38 #endif
38 #ifndef CONFIG_ENV_SPI_MAX_HZ 39 #ifndef CONFIG_ENV_SPI_MAX_HZ
39 # define CONFIG_ENV_SPI_MAX_HZ 1000000 40 # define CONFIG_ENV_SPI_MAX_HZ 1000000
40 #endif 41 #endif
41 #ifndef CONFIG_ENV_SPI_MODE 42 #ifndef CONFIG_ENV_SPI_MODE
42 # define CONFIG_ENV_SPI_MODE SPI_MODE_3 43 # define CONFIG_ENV_SPI_MODE SPI_MODE_3
43 #endif 44 #endif
44 45
45 DECLARE_GLOBAL_DATA_PTR; 46 DECLARE_GLOBAL_DATA_PTR;
46 47
47 /* references to names in env_common.c */ 48 /* references to names in env_common.c */
48 extern uchar default_environment[]; 49 extern uchar default_environment[];
49 extern int default_environment_size; 50 extern int default_environment_size;
50 51
51 char * env_name_spec = "SPI Flash"; 52 char * env_name_spec = "SPI Flash";
52 env_t *env_ptr; 53 env_t *env_ptr;
53 54
54 static struct spi_flash *env_flash; 55 static struct spi_flash *env_flash;
55 56
56 uchar env_get_char_spec(int index) 57 uchar env_get_char_spec(int index)
57 { 58 {
58 return *((uchar *)(gd->env_addr + index)); 59 return *((uchar *)(gd->env_addr + index));
59 } 60 }
60 61
61 int saveenv(void) 62 int saveenv(void)
62 { 63 {
64 u32 saved_size, saved_offset;
65 char *saved_buffer = NULL;
63 u32 sector = 1; 66 u32 sector = 1;
67 int ret;
64 68
65 if (!env_flash) { 69 if (!env_flash) {
66 puts("Environment SPI flash not initialized\n"); 70 puts("Environment SPI flash not initialized\n");
67 return 1; 71 return 1;
68 } 72 }
69 73
74 /* Is the sector larger than the env (i.e. embedded) */
75 if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
76 saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE;
77 saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
78 saved_buffer = malloc(saved_size);
79 if (!saved_buffer) {
80 ret = 1;
81 goto done;
82 }
83 ret = spi_flash_read(env_flash, saved_offset, saved_size, saved_buffer);
84 if (ret)
85 goto done;
86 }
87
70 if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) { 88 if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) {
71 sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE; 89 sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;
72 if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE) 90 if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE)
73 sector++; 91 sector++;
74 } 92 }
75 93
76 puts("Erasing SPI flash..."); 94 puts("Erasing SPI flash...");
77 if (spi_flash_erase(env_flash, CONFIG_ENV_OFFSET, sector * CONFIG_ENV_SECT_SIZE)) 95 ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET, sector * CONFIG_ENV_SECT_SIZE);
78 return 1; 96 if (ret)
97 goto done;
79 98
80 puts("Writing to SPI flash..."); 99 puts("Writing to SPI flash...");
81 if (spi_flash_write(env_flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, env_ptr)) 100 ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, env_ptr);
82 return 1; 101 if (ret)
102 goto done;
83 103
104 if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
105 ret = spi_flash_write(env_flash, saved_offset, saved_size, saved_buffer);
106 if (ret)
107 goto done;
108 }
109
110 ret = 0;
84 puts("done\n"); 111 puts("done\n");
85 return 0; 112
113 done:
114 if (saved_buffer)
115 free(saved_buffer);
116 return ret;
86 } 117 }
87 118
88 void env_relocate_spec(void) 119 void env_relocate_spec(void)
89 { 120 {
90 int ret; 121 int ret;
91 122
92 env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS, 123 env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
93 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE); 124 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
94 if (!env_flash) 125 if (!env_flash)
95 goto err_probe; 126 goto err_probe;
96 127
97 ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, env_ptr); 128 ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, env_ptr);
98 if (ret) 129 if (ret)
99 goto err_read; 130 goto err_read;
100 131
101 if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) 132 if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)
102 goto err_crc; 133 goto err_crc;
103 134
104 gd->env_valid = 1; 135 gd->env_valid = 1;
105 136
106 return; 137 return;
107 138
108 err_read: 139 err_read:
109 spi_flash_free(env_flash); 140 spi_flash_free(env_flash);
110 env_flash = NULL; 141 env_flash = NULL;
111 err_probe: 142 err_probe:
112 err_crc: 143 err_crc:
113 puts("*** Warning - bad CRC, using default environment\n\n"); 144 puts("*** Warning - bad CRC, using default environment\n\n");
114 145
115 if (default_environment_size > CONFIG_ENV_SIZE) { 146 if (default_environment_size > CONFIG_ENV_SIZE) {
116 gd->env_valid = 0; 147 gd->env_valid = 0;
117 puts("*** Error - default environment is too large\n\n"); 148 puts("*** Error - default environment is too large\n\n");
118 return; 149 return;
119 } 150 }
120 151
121 memset(env_ptr, 0, sizeof(env_t)); 152 memset(env_ptr, 0, sizeof(env_t));
122 memcpy(env_ptr->data, default_environment, default_environment_size); 153 memcpy(env_ptr->data, default_environment, default_environment_size);
123 env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE); 154 env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE);
124 gd->env_valid = 1; 155 gd->env_valid = 1;
125 } 156 }
126 157
127 int env_init(void) 158 int env_init(void)
128 { 159 {
129 /* SPI flash isn't usable before relocation */ 160 /* SPI flash isn't usable before relocation */
130 gd->env_addr = (ulong)&default_environment[0]; 161 gd->env_addr = (ulong)&default_environment[0];
131 gd->env_valid = 1; 162 gd->env_valid = 1;
132 163
133 return 0; 164 return 0;
134 } 165 }
135 166