2 * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
11 #include <firmware_image_package.h>
12 #include <io_driver.h>
14 #include <io_storage.h>
16 #include <platform_def.h>
22 #ifndef MAX_FIP_DEVICES
23 #define MAX_FIP_DEVICES 1
26 /* Useful for printing UUIDs when debugging.*/
27 #define PRINT_UUID2(x) \
28 "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", \
29 x.time_low, x.time_mid, x.time_hi_and_version, \
30 x.clock_seq_hi_and_reserved, x.clock_seq_low, \
31 x.node[0], x.node[1], x.node[2], x.node[3], \
35 unsigned int file_pos
;
36 fip_toc_entry_t entry
;
40 * Maintain dev_spec per FIP Device
41 * TODO - Add backend handles and file state
42 * per FIP device here once backends like io_memmap
43 * can support multiple open files
49 static const uuid_t uuid_null
= { {0} };
51 * Only one file can be open across all FIP device
52 * as backends like io_memmap don't support
53 * multiple open files. The file state and
54 * backend handle should be maintained per FIP device
55 * if the same support is available in the backend
57 static file_state_t current_file
= {0};
58 static uintptr_t backend_dev_handle
;
59 static uintptr_t backend_image_spec
;
61 static fip_dev_state_t state_pool
[MAX_FIP_DEVICES
];
62 static io_dev_info_t dev_info_pool
[MAX_FIP_DEVICES
];
64 /* Track number of allocated fip devices */
65 static unsigned int fip_dev_count
;
67 /* Firmware Image Package driver functions */
68 static int fip_dev_open(const uintptr_t dev_spec
, io_dev_info_t
**dev_info
);
69 static int fip_file_open(io_dev_info_t
*dev_info
, const uintptr_t spec
,
71 static int fip_file_len(io_entity_t
*entity
, size_t *length
);
72 static int fip_file_read(io_entity_t
*entity
, uintptr_t buffer
, size_t length
,
74 static int fip_file_close(io_entity_t
*entity
);
75 static int fip_dev_init(io_dev_info_t
*dev_info
, const uintptr_t init_params
);
76 static int fip_dev_close(io_dev_info_t
*dev_info
);
79 /* Return 0 for equal uuids. */
80 static inline int compare_uuids(const uuid_t
*uuid1
, const uuid_t
*uuid2
)
82 return memcmp(uuid1
, uuid2
, sizeof(uuid_t
));
86 /* TODO: We could check version numbers or do a package checksum? */
87 static inline int is_valid_header(fip_toc_header_t
*header
)
89 if ((header
->name
== TOC_HEADER_NAME
) && (header
->serial_number
!= 0)) {
97 /* Identify the device type as a virtual driver */
98 static io_type_t
device_type_fip(void)
100 return IO_TYPE_FIRMWARE_IMAGE_PACKAGE
;
104 static const io_dev_connector_t fip_dev_connector
= {
105 .dev_open
= fip_dev_open
109 static const io_dev_funcs_t fip_dev_funcs
= {
110 .type
= device_type_fip
,
111 .open
= fip_file_open
,
113 .size
= fip_file_len
,
114 .read
= fip_file_read
,
116 .close
= fip_file_close
,
117 .dev_init
= fip_dev_init
,
118 .dev_close
= fip_dev_close
,
121 /* Locate a file state in the pool, specified by address */
122 static int find_first_fip_state(const uintptr_t dev_spec
,
123 unsigned int *index_out
)
125 int result
= -ENOENT
;
128 for (index
= 0; index
< (unsigned int)MAX_FIP_DEVICES
; ++index
) {
129 /* dev_spec is used as identifier since it's unique */
130 if (state_pool
[index
].dev_spec
== dev_spec
) {
140 /* Allocate a device info from the pool and return a pointer to it */
141 static int allocate_dev_info(io_dev_info_t
**dev_info
)
143 int result
= -ENOMEM
;
145 assert(dev_info
!= NULL
);
147 if (fip_dev_count
< (unsigned int)MAX_FIP_DEVICES
) {
148 unsigned int index
= 0;
150 result
= find_first_fip_state(0, &index
);
152 /* initialize dev_info */
153 dev_info_pool
[index
].funcs
= &fip_dev_funcs
;
154 dev_info_pool
[index
].info
=
155 (uintptr_t)&state_pool
[index
];
156 *dev_info
= &dev_info_pool
[index
];
163 /* Release a device info to the pool */
164 static int free_dev_info(io_dev_info_t
*dev_info
)
167 unsigned int index
= 0;
168 fip_dev_state_t
*state
;
170 assert(dev_info
!= NULL
);
172 state
= (fip_dev_state_t
*)dev_info
->info
;
173 result
= find_first_fip_state(state
->dev_spec
, &index
);
175 /* free if device info is valid */
176 zeromem(state
, sizeof(fip_dev_state_t
));
184 * Multiple FIP devices can be opened depending on the value of
185 * MAX_FIP_DEVICES. Given that there is only one backend, only a
186 * single file can be open at a time by any FIP device.
188 static int fip_dev_open(const uintptr_t dev_spec
,
189 io_dev_info_t
**dev_info
)
193 fip_dev_state_t
*state
;
195 assert(dev_info
!= NULL
);
196 #if MAX_FIP_DEVICES > 1
197 assert(dev_spec
!= (uintptr_t)NULL
);
200 result
= allocate_dev_info(&info
);
204 state
= (fip_dev_state_t
*)info
->info
;
206 state
->dev_spec
= dev_spec
;
214 /* Do some basic package checks. */
215 static int fip_dev_init(io_dev_info_t
*dev_info
, const uintptr_t init_params
)
218 unsigned int image_id
= (unsigned int)init_params
;
219 uintptr_t backend_handle
;
220 fip_toc_header_t header
;
223 /* Obtain a reference to the image by querying the platform layer */
224 result
= plat_get_image_source(image_id
, &backend_dev_handle
,
225 &backend_image_spec
);
227 WARN("Failed to obtain reference to image id=%u (%i)\n",
230 goto fip_dev_init_exit
;
233 /* Attempt to access the FIP image */
234 result
= io_open(backend_dev_handle
, backend_image_spec
,
237 WARN("Failed to access image id=%u (%i)\n", image_id
, result
);
239 goto fip_dev_init_exit
;
242 result
= io_read(backend_handle
, (uintptr_t)&header
, sizeof(header
),
245 if (!is_valid_header(&header
)) {
246 WARN("Firmware Image Package header check failed.\n");
249 VERBOSE("FIP header looks OK.\n");
253 io_close(backend_handle
);
259 /* Close a connection to the FIP device */
260 static int fip_dev_close(io_dev_info_t
*dev_info
)
262 /* TODO: Consider tracking open files and cleaning them up here */
264 /* Clear the backend. */
265 backend_dev_handle
= (uintptr_t)NULL
;
266 backend_image_spec
= (uintptr_t)NULL
;
268 return free_dev_info(dev_info
);
272 /* Open a file for access from package. */
273 static int fip_file_open(io_dev_info_t
*dev_info
, const uintptr_t spec
,
277 uintptr_t backend_handle
;
278 const io_uuid_spec_t
*uuid_spec
= (io_uuid_spec_t
*)spec
;
282 assert(uuid_spec
!= NULL
);
283 assert(entity
!= NULL
);
285 /* Can only have one file open at a time for the moment. We need to
286 * track state like file cursor position. We know the header lives at
287 * offset zero, so this entry should never be zero for an active file.
288 * When the system supports dynamic memory allocation we can allow more
289 * than one open file at a time if needed.
291 if (current_file
.entry
.offset_address
!= 0) {
292 WARN("fip_file_open : Only one open file at a time.\n");
296 /* Attempt to access the FIP image */
297 result
= io_open(backend_dev_handle
, backend_image_spec
,
300 WARN("Failed to open Firmware Image Package (%i)\n", result
);
302 goto fip_file_open_exit
;
305 /* Seek past the FIP header into the Table of Contents */
306 result
= io_seek(backend_handle
, IO_SEEK_SET
, sizeof(fip_toc_header_t
));
308 WARN("fip_file_open: failed to seek\n");
310 goto fip_file_open_close
;
315 result
= io_read(backend_handle
,
316 (uintptr_t)¤t_file
.entry
,
317 sizeof(current_file
.entry
),
320 if (compare_uuids(¤t_file
.entry
.uuid
,
321 &uuid_spec
->uuid
) == 0) {
326 WARN("Failed to read FIP (%i)\n", result
);
327 goto fip_file_open_close
;
329 } while (compare_uuids(¤t_file
.entry
.uuid
, &uuid_null
) != 0);
331 if (found_file
== 1) {
332 /* All fine. Update entity info with file state and return. Set
333 * the file position to 0. The 'current_file.entry' holds the
334 * base and size of the file.
336 current_file
.file_pos
= 0;
337 entity
->info
= (uintptr_t)¤t_file
;
339 /* Did not find the file in the FIP. */
340 current_file
.entry
.offset_address
= 0;
345 io_close(backend_handle
);
352 /* Return the size of a file in package */
353 static int fip_file_len(io_entity_t
*entity
, size_t *length
)
355 assert(entity
!= NULL
);
356 assert(length
!= NULL
);
358 *length
= ((file_state_t
*)entity
->info
)->entry
.size
;
364 /* Read data from a file in package */
365 static int fip_file_read(io_entity_t
*entity
, uintptr_t buffer
, size_t length
,
372 uintptr_t backend_handle
;
374 assert(entity
!= NULL
);
375 assert(length_read
!= NULL
);
376 assert(entity
->info
!= (uintptr_t)NULL
);
378 /* Open the backend, attempt to access the blob image */
379 result
= io_open(backend_dev_handle
, backend_image_spec
,
382 WARN("Failed to open FIP (%i)\n", result
);
384 goto fip_file_read_exit
;
387 fp
= (file_state_t
*)entity
->info
;
389 /* Seek to the position in the FIP where the payload lives */
390 file_offset
= fp
->entry
.offset_address
+ fp
->file_pos
;
391 result
= io_seek(backend_handle
, IO_SEEK_SET
, file_offset
);
393 WARN("fip_file_read: failed to seek\n");
395 goto fip_file_read_close
;
398 result
= io_read(backend_handle
, buffer
, length
, &bytes_read
);
400 /* We cannot read our data. Fail. */
401 WARN("Failed to read payload (%i)\n", result
);
403 goto fip_file_read_close
;
405 /* Set caller length and new file position. */
406 *length_read
= bytes_read
;
407 fp
->file_pos
+= bytes_read
;
410 /* Close the backend. */
412 io_close(backend_handle
);
419 /* Close a file in package */
420 static int fip_file_close(io_entity_t
*entity
)
422 /* Clear our current file pointer.
423 * If we had malloc() we would free() here.
425 if (current_file
.entry
.offset_address
!= 0) {
426 zeromem(¤t_file
, sizeof(current_file
));
429 /* Clear the Entity info. */
435 /* Exported functions */
437 /* Register the Firmware Image Package driver with the IO abstraction */
438 int register_io_dev_fip(const io_dev_connector_t
**dev_con
)
441 assert(dev_con
!= NULL
);
444 * Since dev_info isn't really used in io_register_device, always
445 * use the same device info at here instead.
447 result
= io_register_device(&dev_info_pool
[0]);
449 *dev_con
= &fip_dev_connector
;