diff options
author | Ruchika Gupta <ruchika.gupta@nxp.com> | 2018-06-27 12:18:22 +0530 |
---|---|---|
committer | Ruchika Gupta <ruchika.gupta@nxp.com> | 2018-07-02 09:51:59 +0530 |
commit | d4d598e92fe88ca3e60f41ff2f621aac176a02a6 (patch) | |
tree | d51ca812bb10f050be7ce3b74c33e74481e3c5f9 /drivers/io | |
parent | f790cc0a9c492cf3615c82574e2c3f1ff8af0a3d (diff) |
Extend FIP io driver to support multiple FIP devices
Platform can define MAX_NUM_FIP_DEVICES in platform_def.h
to define the number of FIP io devices.
The FIP driver doesn't support muliple open file.
So only one single file can be open at a time across
multiple FIP devices.
For any FIP device, an image should be loaded
fully before moving on to the next image.
Signed-off-by: Ruchika Gupta <ruchika.gupta@nxp.com>
Diffstat (limited to 'drivers/io')
-rw-r--r-- | drivers/io/io_fip.c | 124 |
1 files changed, 114 insertions, 10 deletions
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c index 17543390..6e7103db 100644 --- a/drivers/io/io_fip.c +++ b/drivers/io/io_fip.c @@ -19,6 +19,10 @@ #include <utils.h> #include <uuid.h> +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 1 +#endif + /* Useful for printing UUIDs when debugging.*/ #define PRINT_UUID2(x) \ "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", \ @@ -32,11 +36,33 @@ typedef struct { fip_toc_entry_t entry; } file_state_t; +/* + * Maintain dev_spec per FIP Device + * TODO - Add backend handles and file state + * per FIP device here once backends like io_memmap + * can support multiple open files + */ +typedef struct { + uintptr_t dev_spec; +} fip_dev_state_t; + static const uuid_t uuid_null = { {0} }; +/* + * Only one file can be open across all FIP device + * as backends like io_memmap don't support + * multiple open files. The file state and + * backend handle should be maintained per FIP device + * if the same support is available in the backend + */ static file_state_t current_file = {0}; static uintptr_t backend_dev_handle; static uintptr_t backend_image_spec; +static fip_dev_state_t state_pool[MAX_FIP_DEVICES]; +static io_dev_info_t dev_info_pool[MAX_FIP_DEVICES]; + +/* Track number of allocated fip devices */ +static unsigned int fip_dev_count; /* Firmware Image Package driver functions */ static int fip_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); @@ -92,20 +118,94 @@ static const io_dev_funcs_t fip_dev_funcs = { .dev_close = fip_dev_close, }; +/* Locate a file state in the pool, specified by address */ +static int find_first_fip_state(const uintptr_t dev_spec, + unsigned int *index_out) +{ + int result = -ENOENT; + unsigned int index; + + for (index = 0; index < (unsigned int)MAX_FIP_DEVICES; ++index) { + /* dev_spec is used as identifier since it's unique */ + if (state_pool[index].dev_spec == dev_spec) { + result = 0; + *index_out = index; + break; + } + } + return result; +} + -/* No state associated with this device so structure can be const */ -static const io_dev_info_t fip_dev_info = { - .funcs = &fip_dev_funcs, - .info = (uintptr_t)NULL -}; +/* Allocate a device info from the pool and return a pointer to it */ +static int allocate_dev_info(io_dev_info_t **dev_info) +{ + int result = -ENOMEM; + assert(dev_info != NULL); + + if (fip_dev_count < (unsigned int)MAX_FIP_DEVICES) { + unsigned int index = 0; + + result = find_first_fip_state(0, &index); + assert(result == 0); + /* initialize dev_info */ + dev_info_pool[index].funcs = &fip_dev_funcs; + dev_info_pool[index].info = + (uintptr_t)&state_pool[index]; + *dev_info = &dev_info_pool[index]; + ++fip_dev_count; + } + + return result; +} -/* Open a connection to the FIP device */ -static int fip_dev_open(const uintptr_t dev_spec __unused, +/* Release a device info to the pool */ +static int free_dev_info(io_dev_info_t *dev_info) +{ + int result; + unsigned int index = 0; + fip_dev_state_t *state; + + assert(dev_info != NULL); + + state = (fip_dev_state_t *)dev_info->info; + result = find_first_fip_state(state->dev_spec, &index); + if (result == 0) { + /* free if device info is valid */ + zeromem(state, sizeof(fip_dev_state_t)); + --fip_dev_count; + } + + return result; +} + +/* + * Multiple FIP devices can be opened depending on the value of + * MAX_FIP_DEVICES. Given that there is only one backend, only a + * single file can be open at a time by any FIP device. + */ +static int fip_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) { + int result; + io_dev_info_t *info; + fip_dev_state_t *state; + assert(dev_info != NULL); - *dev_info = (io_dev_info_t *)&fip_dev_info; /* cast away const */ +#if MAX_FIP_DEVICES > 1 + assert(dev_spec != (uintptr_t)NULL); +#endif + + result = allocate_dev_info(&info); + if (result != 0) + return -ENOMEM; + + state = (fip_dev_state_t *)info->info; + + state->dev_spec = dev_spec; + + *dev_info = info; return 0; } @@ -165,7 +265,7 @@ static int fip_dev_close(io_dev_info_t *dev_info) backend_dev_handle = (uintptr_t)NULL; backend_image_spec = (uintptr_t)NULL; - return 0; + return free_dev_info(dev_info); } @@ -341,7 +441,11 @@ int register_io_dev_fip(const io_dev_connector_t **dev_con) int result; assert(dev_con != NULL); - result = io_register_device(&fip_dev_info); + /* + * Since dev_info isn't really used in io_register_device, always + * use the same device info at here instead. + */ + result = io_register_device(&dev_info_pool[0]); if (result == 0) *dev_con = &fip_dev_connector; |