env.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Copyright (C) 2017 Google, Inc
  3. * Written by Simon Glass <sjg@chromium.org>
  4. *
  5. * SPDX-License-Identifier: GPL-2.0+
  6. */
  7. #include <common.h>
  8. #include <environment.h>
  9. DECLARE_GLOBAL_DATA_PTR;
  10. static struct env_driver *_env_driver_lookup(enum env_location loc)
  11. {
  12. struct env_driver *drv;
  13. const int n_ents = ll_entry_count(struct env_driver, env_driver);
  14. struct env_driver *entry;
  15. drv = ll_entry_start(struct env_driver, env_driver);
  16. for (entry = drv; entry != drv + n_ents; entry++) {
  17. if (loc == entry->location)
  18. return entry;
  19. }
  20. /* Not found */
  21. return NULL;
  22. }
  23. /**
  24. * env_get_location() - Returns the best env location for a board
  25. * @op: operations performed on the environment
  26. * @prio: priority between the multiple environments, 0 being the
  27. * highest priority
  28. *
  29. * This will return the preferred environment for the given priority.
  30. *
  31. * All implementations are free to use the operation, the priority and
  32. * any other data relevant to their choice, but must take into account
  33. * the fact that the lowest prority (0) is the most important location
  34. * in the system. The following locations should be returned by order
  35. * of descending priorities, from the highest to the lowest priority.
  36. *
  37. * Returns:
  38. * an enum env_location value on success, a negative error code otherwise
  39. */
  40. static enum env_location env_get_location(enum env_operation op, int prio)
  41. {
  42. /*
  43. * We support a single environment, so any environment asked
  44. * with a priority that is not zero is out of our supported
  45. * bounds.
  46. */
  47. if (prio >= 1)
  48. return ENVL_UNKNOWN;
  49. if IS_ENABLED(CONFIG_ENV_IS_IN_EEPROM)
  50. return ENVL_EEPROM;
  51. else if IS_ENABLED(CONFIG_ENV_IS_IN_FAT)
  52. return ENVL_FAT;
  53. else if IS_ENABLED(CONFIG_ENV_IS_IN_EXT4)
  54. return ENVL_EXT4;
  55. else if IS_ENABLED(CONFIG_ENV_IS_IN_FLASH)
  56. return ENVL_FLASH;
  57. else if IS_ENABLED(CONFIG_ENV_IS_IN_MMC)
  58. return ENVL_MMC;
  59. else if IS_ENABLED(CONFIG_ENV_IS_IN_NAND)
  60. return ENVL_NAND;
  61. else if IS_ENABLED(CONFIG_ENV_IS_IN_NVRAM)
  62. return ENVL_NVRAM;
  63. else if IS_ENABLED(CONFIG_ENV_IS_IN_REMOTE)
  64. return ENVL_REMOTE;
  65. else if IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH)
  66. return ENVL_SPI_FLASH;
  67. else if IS_ENABLED(CONFIG_ENV_IS_IN_UBI)
  68. return ENVL_UBI;
  69. else if IS_ENABLED(CONFIG_ENV_IS_NOWHERE)
  70. return ENVL_NOWHERE;
  71. else
  72. return ENVL_UNKNOWN;
  73. }
  74. /**
  75. * env_driver_lookup() - Finds the most suited environment location
  76. * @op: operations performed on the environment
  77. * @prio: priority between the multiple environments, 0 being the
  78. * highest priority
  79. *
  80. * This will try to find the available environment with the highest
  81. * priority in the system.
  82. *
  83. * Returns:
  84. * NULL on error, a pointer to a struct env_driver otherwise
  85. */
  86. static struct env_driver *env_driver_lookup(enum env_operation op, int prio)
  87. {
  88. enum env_location loc = env_get_location(op, prio);
  89. struct env_driver *drv;
  90. if (loc == ENVL_UNKNOWN)
  91. return NULL;
  92. drv = _env_driver_lookup(loc);
  93. if (!drv) {
  94. debug("%s: No environment driver for location %d\n", __func__,
  95. loc);
  96. return NULL;
  97. }
  98. return drv;
  99. }
  100. int env_get_char(int index)
  101. {
  102. struct env_driver *drv;
  103. int prio;
  104. if (gd->env_valid == ENV_INVALID)
  105. return default_environment[index];
  106. for (prio = 0; (drv = env_driver_lookup(ENVOP_GET_CHAR, prio)); prio++) {
  107. int ret;
  108. if (!drv->get_char)
  109. continue;
  110. ret = drv->get_char(index);
  111. if (!ret)
  112. return 0;
  113. debug("%s: Environment %s failed to load (err=%d)\n", __func__,
  114. drv->name, ret);
  115. }
  116. return -ENODEV;
  117. }
  118. int env_load(void)
  119. {
  120. struct env_driver *drv;
  121. int prio;
  122. for (prio = 0; (drv = env_driver_lookup(ENVOP_LOAD, prio)); prio++) {
  123. int ret;
  124. if (!drv->load)
  125. continue;
  126. printf("Loading Environment from %s... ", drv->name);
  127. ret = drv->load();
  128. if (ret)
  129. printf("Failed (%d)\n", ret);
  130. else
  131. printf("OK\n");
  132. if (!ret)
  133. return 0;
  134. }
  135. return -ENODEV;
  136. }
  137. int env_save(void)
  138. {
  139. struct env_driver *drv;
  140. int prio;
  141. for (prio = 0; (drv = env_driver_lookup(ENVOP_SAVE, prio)); prio++) {
  142. int ret;
  143. if (!drv->save)
  144. continue;
  145. printf("Saving Environment to %s... ", drv->name);
  146. ret = drv->save();
  147. if (ret)
  148. printf("Failed (%d)\n", ret);
  149. else
  150. printf("OK\n");
  151. if (!ret)
  152. return 0;
  153. }
  154. return -ENODEV;
  155. }
  156. int env_init(void)
  157. {
  158. struct env_driver *drv;
  159. int ret = -ENOENT;
  160. int prio;
  161. for (prio = 0; (drv = env_driver_lookup(ENVOP_INIT, prio)); prio++) {
  162. if (!drv->init)
  163. continue;
  164. ret = drv->init();
  165. if (!ret)
  166. return 0;
  167. debug("%s: Environment %s failed to init (err=%d)\n", __func__,
  168. drv->name, ret);
  169. }
  170. if (!prio)
  171. return -ENODEV;
  172. if (ret == -ENOENT) {
  173. gd->env_addr = (ulong)&default_environment[0];
  174. gd->env_valid = ENV_VALID;
  175. return 0;
  176. }
  177. return ret;
  178. }