env_sf.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /*
  2. * (C) Copyright 2000-2010
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  6. * Andreas Heppel <aheppel@sysgo.de>
  7. *
  8. * (C) Copyright 2008 Atmel Corporation
  9. *
  10. * SPDX-License-Identifier: GPL-2.0+
  11. */
  12. #include <common.h>
  13. #include <environment.h>
  14. #include <malloc.h>
  15. #include <spi_flash.h>
  16. #include <search.h>
  17. #include <errno.h>
  18. #ifndef CONFIG_ENV_SPI_BUS
  19. # define CONFIG_ENV_SPI_BUS 0
  20. #endif
  21. #ifndef CONFIG_ENV_SPI_CS
  22. # define CONFIG_ENV_SPI_CS 0
  23. #endif
  24. #ifndef CONFIG_ENV_SPI_MAX_HZ
  25. # define CONFIG_ENV_SPI_MAX_HZ 1000000
  26. #endif
  27. #ifndef CONFIG_ENV_SPI_MODE
  28. # define CONFIG_ENV_SPI_MODE SPI_MODE_3
  29. #endif
  30. #ifdef CONFIG_ENV_OFFSET_REDUND
  31. static ulong env_offset = CONFIG_ENV_OFFSET;
  32. static ulong env_new_offset = CONFIG_ENV_OFFSET_REDUND;
  33. #define ACTIVE_FLAG 1
  34. #define OBSOLETE_FLAG 0
  35. #endif /* CONFIG_ENV_OFFSET_REDUND */
  36. DECLARE_GLOBAL_DATA_PTR;
  37. char *env_name_spec = "SPI Flash";
  38. static struct spi_flash *env_flash;
  39. #if defined(CONFIG_ENV_OFFSET_REDUND)
  40. int saveenv(void)
  41. {
  42. env_t env_new;
  43. ssize_t len;
  44. char *res, *saved_buffer = NULL, flag = OBSOLETE_FLAG;
  45. u32 saved_size, saved_offset, sector = 1;
  46. int ret;
  47. if (!env_flash) {
  48. env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
  49. CONFIG_ENV_SPI_CS,
  50. CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
  51. if (!env_flash) {
  52. set_default_env("!spi_flash_probe() failed");
  53. return 1;
  54. }
  55. }
  56. res = (char *)&env_new.data;
  57. len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
  58. if (len < 0) {
  59. error("Cannot export environment: errno = %d\n", errno);
  60. return 1;
  61. }
  62. env_new.crc = crc32(0, env_new.data, ENV_SIZE);
  63. env_new.flags = ACTIVE_FLAG;
  64. if (gd->env_valid == 1) {
  65. env_new_offset = CONFIG_ENV_OFFSET_REDUND;
  66. env_offset = CONFIG_ENV_OFFSET;
  67. } else {
  68. env_new_offset = CONFIG_ENV_OFFSET;
  69. env_offset = CONFIG_ENV_OFFSET_REDUND;
  70. }
  71. /* Is the sector larger than the env (i.e. embedded) */
  72. if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
  73. saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE;
  74. saved_offset = env_new_offset + CONFIG_ENV_SIZE;
  75. saved_buffer = malloc(saved_size);
  76. if (!saved_buffer) {
  77. ret = 1;
  78. goto done;
  79. }
  80. ret = spi_flash_read(env_flash, saved_offset,
  81. saved_size, saved_buffer);
  82. if (ret)
  83. goto done;
  84. }
  85. if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) {
  86. sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;
  87. if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE)
  88. sector++;
  89. }
  90. puts("Erasing SPI flash...");
  91. ret = spi_flash_erase(env_flash, env_new_offset,
  92. sector * CONFIG_ENV_SECT_SIZE);
  93. if (ret)
  94. goto done;
  95. puts("Writing to SPI flash...");
  96. ret = spi_flash_write(env_flash, env_new_offset,
  97. CONFIG_ENV_SIZE, &env_new);
  98. if (ret)
  99. goto done;
  100. if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
  101. ret = spi_flash_write(env_flash, saved_offset,
  102. saved_size, saved_buffer);
  103. if (ret)
  104. goto done;
  105. }
  106. ret = spi_flash_write(env_flash, env_offset + offsetof(env_t, flags),
  107. sizeof(env_new.flags), &flag);
  108. if (ret)
  109. goto done;
  110. puts("done\n");
  111. gd->env_valid = gd->env_valid == 2 ? 1 : 2;
  112. printf("Valid environment: %d\n", (int)gd->env_valid);
  113. done:
  114. if (saved_buffer)
  115. free(saved_buffer);
  116. return ret;
  117. }
  118. void env_relocate_spec(void)
  119. {
  120. int ret;
  121. int crc1_ok = 0, crc2_ok = 0;
  122. env_t *tmp_env1 = NULL;
  123. env_t *tmp_env2 = NULL;
  124. env_t *ep = NULL;
  125. tmp_env1 = (env_t *)malloc(CONFIG_ENV_SIZE);
  126. tmp_env2 = (env_t *)malloc(CONFIG_ENV_SIZE);
  127. if (!tmp_env1 || !tmp_env2) {
  128. set_default_env("!malloc() failed");
  129. goto out;
  130. }
  131. env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
  132. CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
  133. if (!env_flash) {
  134. set_default_env("!spi_flash_probe() failed");
  135. goto out;
  136. }
  137. ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET,
  138. CONFIG_ENV_SIZE, tmp_env1);
  139. if (ret) {
  140. set_default_env("!spi_flash_read() failed");
  141. goto err_read;
  142. }
  143. if (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc)
  144. crc1_ok = 1;
  145. ret = spi_flash_read(env_flash, CONFIG_ENV_OFFSET_REDUND,
  146. CONFIG_ENV_SIZE, tmp_env2);
  147. if (!ret) {
  148. if (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc)
  149. crc2_ok = 1;
  150. }
  151. if (!crc1_ok && !crc2_ok) {
  152. set_default_env("!bad CRC");
  153. goto err_read;
  154. } else if (crc1_ok && !crc2_ok) {
  155. gd->env_valid = 1;
  156. } else if (!crc1_ok && crc2_ok) {
  157. gd->env_valid = 2;
  158. } else if (tmp_env1->flags == ACTIVE_FLAG &&
  159. tmp_env2->flags == OBSOLETE_FLAG) {
  160. gd->env_valid = 1;
  161. } else if (tmp_env1->flags == OBSOLETE_FLAG &&
  162. tmp_env2->flags == ACTIVE_FLAG) {
  163. gd->env_valid = 2;
  164. } else if (tmp_env1->flags == tmp_env2->flags) {
  165. gd->env_valid = 2;
  166. } else if (tmp_env1->flags == 0xFF) {
  167. gd->env_valid = 2;
  168. } else {
  169. /*
  170. * this differs from code in env_flash.c, but I think a sane
  171. * default path is desirable.
  172. */
  173. gd->env_valid = 2;
  174. }
  175. if (gd->env_valid == 1)
  176. ep = tmp_env1;
  177. else
  178. ep = tmp_env2;
  179. ret = env_import((char *)ep, 0);
  180. if (!ret) {
  181. error("Cannot import environment: errno = %d\n", errno);
  182. set_default_env("env_import failed");
  183. }
  184. err_read:
  185. spi_flash_free(env_flash);
  186. env_flash = NULL;
  187. out:
  188. free(tmp_env1);
  189. free(tmp_env2);
  190. }
  191. #else
  192. int saveenv(void)
  193. {
  194. u32 saved_size, saved_offset, sector = 1;
  195. char *res, *saved_buffer = NULL;
  196. int ret = 1;
  197. env_t env_new;
  198. ssize_t len;
  199. if (!env_flash) {
  200. env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
  201. CONFIG_ENV_SPI_CS,
  202. CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
  203. if (!env_flash) {
  204. set_default_env("!spi_flash_probe() failed");
  205. return 1;
  206. }
  207. }
  208. /* Is the sector larger than the env (i.e. embedded) */
  209. if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
  210. saved_size = CONFIG_ENV_SECT_SIZE - CONFIG_ENV_SIZE;
  211. saved_offset = CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE;
  212. saved_buffer = malloc(saved_size);
  213. if (!saved_buffer)
  214. goto done;
  215. ret = spi_flash_read(env_flash, saved_offset,
  216. saved_size, saved_buffer);
  217. if (ret)
  218. goto done;
  219. }
  220. if (CONFIG_ENV_SIZE > CONFIG_ENV_SECT_SIZE) {
  221. sector = CONFIG_ENV_SIZE / CONFIG_ENV_SECT_SIZE;
  222. if (CONFIG_ENV_SIZE % CONFIG_ENV_SECT_SIZE)
  223. sector++;
  224. }
  225. res = (char *)&env_new.data;
  226. len = hexport_r(&env_htab, '\0', 0, &res, ENV_SIZE, 0, NULL);
  227. if (len < 0) {
  228. error("Cannot export environment: errno = %d\n", errno);
  229. goto done;
  230. }
  231. env_new.crc = crc32(0, env_new.data, ENV_SIZE);
  232. puts("Erasing SPI flash...");
  233. ret = spi_flash_erase(env_flash, CONFIG_ENV_OFFSET,
  234. sector * CONFIG_ENV_SECT_SIZE);
  235. if (ret)
  236. goto done;
  237. puts("Writing to SPI flash...");
  238. ret = spi_flash_write(env_flash, CONFIG_ENV_OFFSET,
  239. CONFIG_ENV_SIZE, &env_new);
  240. if (ret)
  241. goto done;
  242. if (CONFIG_ENV_SECT_SIZE > CONFIG_ENV_SIZE) {
  243. ret = spi_flash_write(env_flash, saved_offset,
  244. saved_size, saved_buffer);
  245. if (ret)
  246. goto done;
  247. }
  248. ret = 0;
  249. puts("done\n");
  250. done:
  251. if (saved_buffer)
  252. free(saved_buffer);
  253. return ret;
  254. }
  255. void env_relocate_spec(void)
  256. {
  257. int ret;
  258. char *buf = NULL;
  259. buf = (char *)malloc(CONFIG_ENV_SIZE);
  260. env_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
  261. CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
  262. if (!env_flash) {
  263. set_default_env("!spi_flash_probe() failed");
  264. if (buf)
  265. free(buf);
  266. return;
  267. }
  268. ret = spi_flash_read(env_flash,
  269. CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE, buf);
  270. if (ret) {
  271. set_default_env("!spi_flash_read() failed");
  272. goto out;
  273. }
  274. ret = env_import(buf, 1);
  275. if (ret)
  276. gd->env_valid = 1;
  277. out:
  278. spi_flash_free(env_flash);
  279. if (buf)
  280. free(buf);
  281. env_flash = NULL;
  282. }
  283. #endif
  284. int env_init(void)
  285. {
  286. /* SPI flash isn't usable before relocation */
  287. gd->env_addr = (ulong)&default_environment[0];
  288. gd->env_valid = 1;
  289. return 0;
  290. }