Commit 5b3375ac8c36c29c87abb132fede0509eb21e5c9
Committed by
Wolfgang Denk
1 parent
ecf5f077c8
Exists in
master
and in
54 other branches
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
common/env_sf.c
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 |