io_fip.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /*
  2. * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <errno.h>
  8. #include <stdint.h>
  9. #include <string.h>
  10. #include <platform_def.h>
  11. #include <common/bl_common.h>
  12. #include <common/debug.h>
  13. #include <drivers/io/io_driver.h>
  14. #include <drivers/io/io_fip.h>
  15. #include <drivers/io/io_storage.h>
  16. #include <lib/utils.h>
  17. #include <plat/common/platform.h>
  18. #include <tools_share/firmware_image_package.h>
  19. #include <tools_share/uuid.h>
  20. #ifndef MAX_FIP_DEVICES
  21. #define MAX_FIP_DEVICES 1
  22. #endif
  23. /* Useful for printing UUIDs when debugging.*/
  24. #define PRINT_UUID2(x) \
  25. "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", \
  26. x.time_low, x.time_mid, x.time_hi_and_version, \
  27. x.clock_seq_hi_and_reserved, x.clock_seq_low, \
  28. x.node[0], x.node[1], x.node[2], x.node[3], \
  29. x.node[4], x.node[5]
  30. typedef struct {
  31. unsigned int file_pos;
  32. fip_toc_entry_t entry;
  33. } fip_file_state_t;
  34. /*
  35. * Maintain dev_spec per FIP Device
  36. * TODO - Add backend handles and file state
  37. * per FIP device here once backends like io_memmap
  38. * can support multiple open files
  39. */
  40. typedef struct {
  41. uintptr_t dev_spec;
  42. uint16_t plat_toc_flag;
  43. } fip_dev_state_t;
  44. /*
  45. * Only one file can be open across all FIP device
  46. * as backends like io_memmap don't support
  47. * multiple open files. The file state and
  48. * backend handle should be maintained per FIP device
  49. * if the same support is available in the backend
  50. */
  51. static fip_file_state_t current_fip_file = {0};
  52. static uintptr_t backend_dev_handle;
  53. static uintptr_t backend_image_spec;
  54. static fip_dev_state_t state_pool[MAX_FIP_DEVICES];
  55. static io_dev_info_t dev_info_pool[MAX_FIP_DEVICES];
  56. /* Track number of allocated fip devices */
  57. static unsigned int fip_dev_count;
  58. /* Firmware Image Package driver functions */
  59. static int fip_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
  60. static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
  61. io_entity_t *entity);
  62. static int fip_file_len(io_entity_t *entity, size_t *length);
  63. static int fip_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
  64. size_t *length_read);
  65. static int fip_file_close(io_entity_t *entity);
  66. static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params);
  67. static int fip_dev_close(io_dev_info_t *dev_info);
  68. /* Return 0 for equal uuids. */
  69. static inline int compare_uuids(const uuid_t *uuid1, const uuid_t *uuid2)
  70. {
  71. return memcmp(uuid1, uuid2, sizeof(uuid_t));
  72. }
  73. static inline int is_valid_header(fip_toc_header_t *header)
  74. {
  75. if ((header->name == TOC_HEADER_NAME) && (header->serial_number != 0)) {
  76. return 1;
  77. } else {
  78. return 0;
  79. }
  80. }
  81. /* Identify the device type as a virtual driver */
  82. static io_type_t device_type_fip(void)
  83. {
  84. return IO_TYPE_FIRMWARE_IMAGE_PACKAGE;
  85. }
  86. static const io_dev_connector_t fip_dev_connector = {
  87. .dev_open = fip_dev_open
  88. };
  89. static const io_dev_funcs_t fip_dev_funcs = {
  90. .type = device_type_fip,
  91. .open = fip_file_open,
  92. .seek = NULL,
  93. .size = fip_file_len,
  94. .read = fip_file_read,
  95. .write = NULL,
  96. .close = fip_file_close,
  97. .dev_init = fip_dev_init,
  98. .dev_close = fip_dev_close,
  99. };
  100. /* Locate a file state in the pool, specified by address */
  101. static int find_first_fip_state(const uintptr_t dev_spec,
  102. unsigned int *index_out)
  103. {
  104. int result = -ENOENT;
  105. unsigned int index;
  106. for (index = 0; index < (unsigned int)MAX_FIP_DEVICES; ++index) {
  107. /* dev_spec is used as identifier since it's unique */
  108. if (state_pool[index].dev_spec == dev_spec) {
  109. result = 0;
  110. *index_out = index;
  111. break;
  112. }
  113. }
  114. return result;
  115. }
  116. /* Allocate a device info from the pool and return a pointer to it */
  117. static int allocate_dev_info(io_dev_info_t **dev_info)
  118. {
  119. int result = -ENOMEM;
  120. assert(dev_info != NULL);
  121. if (fip_dev_count < (unsigned int)MAX_FIP_DEVICES) {
  122. unsigned int index = 0;
  123. result = find_first_fip_state(0, &index);
  124. assert(result == 0);
  125. /* initialize dev_info */
  126. dev_info_pool[index].funcs = &fip_dev_funcs;
  127. dev_info_pool[index].info =
  128. (uintptr_t)&state_pool[index];
  129. *dev_info = &dev_info_pool[index];
  130. ++fip_dev_count;
  131. }
  132. return result;
  133. }
  134. /* Release a device info to the pool */
  135. static int free_dev_info(io_dev_info_t *dev_info)
  136. {
  137. int result;
  138. unsigned int index = 0;
  139. fip_dev_state_t *state;
  140. assert(dev_info != NULL);
  141. state = (fip_dev_state_t *)dev_info->info;
  142. result = find_first_fip_state(state->dev_spec, &index);
  143. if (result == 0) {
  144. /* free if device info is valid */
  145. zeromem(state, sizeof(fip_dev_state_t));
  146. --fip_dev_count;
  147. }
  148. return result;
  149. }
  150. /*
  151. * Multiple FIP devices can be opened depending on the value of
  152. * MAX_FIP_DEVICES. Given that there is only one backend, only a
  153. * single file can be open at a time by any FIP device.
  154. */
  155. static int fip_dev_open(const uintptr_t dev_spec,
  156. io_dev_info_t **dev_info)
  157. {
  158. int result;
  159. io_dev_info_t *info;
  160. fip_dev_state_t *state;
  161. assert(dev_info != NULL);
  162. #if MAX_FIP_DEVICES > 1
  163. assert(dev_spec != (uintptr_t)NULL);
  164. #endif
  165. result = allocate_dev_info(&info);
  166. if (result != 0)
  167. return -ENOMEM;
  168. state = (fip_dev_state_t *)info->info;
  169. state->dev_spec = dev_spec;
  170. *dev_info = info;
  171. return 0;
  172. }
  173. /* Do some basic package checks. */
  174. static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params)
  175. {
  176. int result;
  177. unsigned int image_id = (unsigned int)init_params;
  178. uintptr_t backend_handle;
  179. fip_toc_header_t header;
  180. size_t bytes_read;
  181. fip_dev_state_t *state;
  182. assert(dev_info != NULL);
  183. state = (fip_dev_state_t *)dev_info->info;
  184. /* Obtain a reference to the image by querying the platform layer */
  185. result = plat_get_image_source(image_id, &backend_dev_handle,
  186. &backend_image_spec);
  187. if (result != 0) {
  188. WARN("Failed to obtain reference to image id=%u (%i)\n",
  189. image_id, result);
  190. result = -ENOENT;
  191. goto fip_dev_init_exit;
  192. }
  193. /* Attempt to access the FIP image */
  194. result = io_open(backend_dev_handle, backend_image_spec,
  195. &backend_handle);
  196. if (result != 0) {
  197. WARN("Failed to access image id=%u (%i)\n", image_id, result);
  198. result = -ENOENT;
  199. goto fip_dev_init_exit;
  200. }
  201. result = io_read(backend_handle, (uintptr_t)&header, sizeof(header),
  202. &bytes_read);
  203. if (result == 0) {
  204. if (!is_valid_header(&header)) {
  205. WARN("Firmware Image Package header check failed.\n");
  206. result = -ENOENT;
  207. } else {
  208. VERBOSE("FIP header looks OK.\n");
  209. /*
  210. * Store 16-bit Platform ToC flags field which occupies
  211. * bits [32-47] in fip header.
  212. */
  213. state->plat_toc_flag = (header.flags >> 32) & 0xffff;
  214. }
  215. }
  216. io_close(backend_handle);
  217. fip_dev_init_exit:
  218. return result;
  219. }
  220. /* Close a connection to the FIP device */
  221. static int fip_dev_close(io_dev_info_t *dev_info)
  222. {
  223. /* TODO: Consider tracking open files and cleaning them up here */
  224. /* Clear the backend. */
  225. backend_dev_handle = (uintptr_t)NULL;
  226. backend_image_spec = (uintptr_t)NULL;
  227. return free_dev_info(dev_info);
  228. }
  229. /* Open a file for access from package. */
  230. static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec,
  231. io_entity_t *entity)
  232. {
  233. int result;
  234. uintptr_t backend_handle;
  235. const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)spec;
  236. static const uuid_t uuid_null = { {0} }; /* Double braces for clang */
  237. size_t bytes_read;
  238. int found_file = 0;
  239. assert(uuid_spec != NULL);
  240. assert(entity != NULL);
  241. /* Can only have one file open at a time for the moment. We need to
  242. * track state like file cursor position. We know the header lives at
  243. * offset zero, so this entry should never be zero for an active file.
  244. * When the system supports dynamic memory allocation we can allow more
  245. * than one open file at a time if needed.
  246. */
  247. if (current_fip_file.entry.offset_address != 0U) {
  248. WARN("fip_file_open : Only one open file at a time.\n");
  249. return -ENFILE;
  250. }
  251. /* Attempt to access the FIP image */
  252. result = io_open(backend_dev_handle, backend_image_spec,
  253. &backend_handle);
  254. if (result != 0) {
  255. WARN("Failed to open Firmware Image Package (%i)\n", result);
  256. result = -ENOENT;
  257. goto fip_file_open_exit;
  258. }
  259. /* Seek past the FIP header into the Table of Contents */
  260. result = io_seek(backend_handle, IO_SEEK_SET,
  261. (signed long long)sizeof(fip_toc_header_t));
  262. if (result != 0) {
  263. WARN("fip_file_open: failed to seek\n");
  264. result = -ENOENT;
  265. goto fip_file_open_close;
  266. }
  267. found_file = 0;
  268. do {
  269. result = io_read(backend_handle,
  270. (uintptr_t)&current_fip_file.entry,
  271. sizeof(current_fip_file.entry),
  272. &bytes_read);
  273. if (result == 0) {
  274. if (compare_uuids(&current_fip_file.entry.uuid,
  275. &uuid_spec->uuid) == 0) {
  276. found_file = 1;
  277. }
  278. } else {
  279. WARN("Failed to read FIP (%i)\n", result);
  280. goto fip_file_open_close;
  281. }
  282. } while ((found_file == 0) &&
  283. (compare_uuids(&current_fip_file.entry.uuid,
  284. &uuid_null) != 0));
  285. if (found_file == 1) {
  286. /* All fine. Update entity info with file state and return. Set
  287. * the file position to 0. The 'current_fip_file.entry' holds
  288. * the base and size of the file.
  289. */
  290. current_fip_file.file_pos = 0;
  291. entity->info = (uintptr_t)&current_fip_file;
  292. } else {
  293. /* Did not find the file in the FIP. */
  294. current_fip_file.entry.offset_address = 0;
  295. result = -ENOENT;
  296. }
  297. fip_file_open_close:
  298. io_close(backend_handle);
  299. fip_file_open_exit:
  300. return result;
  301. }
  302. /* Return the size of a file in package */
  303. static int fip_file_len(io_entity_t *entity, size_t *length)
  304. {
  305. assert(entity != NULL);
  306. assert(length != NULL);
  307. *length = ((fip_file_state_t *)entity->info)->entry.size;
  308. return 0;
  309. }
  310. /* Read data from a file in package */
  311. static int fip_file_read(io_entity_t *entity, uintptr_t buffer, size_t length,
  312. size_t *length_read)
  313. {
  314. int result;
  315. fip_file_state_t *fp;
  316. size_t file_offset;
  317. size_t bytes_read;
  318. uintptr_t backend_handle;
  319. assert(entity != NULL);
  320. assert(length_read != NULL);
  321. assert(entity->info != (uintptr_t)NULL);
  322. /* Open the backend, attempt to access the blob image */
  323. result = io_open(backend_dev_handle, backend_image_spec,
  324. &backend_handle);
  325. if (result != 0) {
  326. WARN("Failed to open FIP (%i)\n", result);
  327. result = -ENOENT;
  328. goto fip_file_read_exit;
  329. }
  330. fp = (fip_file_state_t *)entity->info;
  331. /* Seek to the position in the FIP where the payload lives */
  332. file_offset = fp->entry.offset_address + fp->file_pos;
  333. result = io_seek(backend_handle, IO_SEEK_SET,
  334. (signed long long)file_offset);
  335. if (result != 0) {
  336. WARN("fip_file_read: failed to seek\n");
  337. result = -ENOENT;
  338. goto fip_file_read_close;
  339. }
  340. result = io_read(backend_handle, buffer, length, &bytes_read);
  341. if (result != 0) {
  342. /* We cannot read our data. Fail. */
  343. WARN("Failed to read payload (%i)\n", result);
  344. result = -ENOENT;
  345. goto fip_file_read_close;
  346. } else {
  347. /* Set caller length and new file position. */
  348. *length_read = bytes_read;
  349. fp->file_pos += bytes_read;
  350. }
  351. /* Close the backend. */
  352. fip_file_read_close:
  353. io_close(backend_handle);
  354. fip_file_read_exit:
  355. return result;
  356. }
  357. /* Close a file in package */
  358. static int fip_file_close(io_entity_t *entity)
  359. {
  360. /* Clear our current file pointer.
  361. * If we had malloc() we would free() here.
  362. */
  363. if (current_fip_file.entry.offset_address != 0U) {
  364. zeromem(&current_fip_file, sizeof(current_fip_file));
  365. }
  366. /* Clear the Entity info. */
  367. entity->info = 0;
  368. return 0;
  369. }
  370. /* Exported functions */
  371. /* Register the Firmware Image Package driver with the IO abstraction */
  372. int register_io_dev_fip(const io_dev_connector_t **dev_con)
  373. {
  374. int result;
  375. assert(dev_con != NULL);
  376. /*
  377. * Since dev_info isn't really used in io_register_device, always
  378. * use the same device info at here instead.
  379. */
  380. result = io_register_device(&dev_info_pool[0]);
  381. if (result == 0)
  382. *dev_con = &fip_dev_connector;
  383. return result;
  384. }
  385. /* Function to retrieve plat_toc_flags, previously saved in FIP dev */
  386. int fip_dev_get_plat_toc_flag(io_dev_info_t *dev_info, uint16_t *plat_toc_flag)
  387. {
  388. fip_dev_state_t *state;
  389. assert(dev_info != NULL);
  390. state = (fip_dev_state_t *)dev_info->info;
  391. *plat_toc_flag = state->plat_toc_flag;
  392. return 0;
  393. }