Merge pull request #1396 from ruchi393/multiple_fip

Extend FIP io driver to support multiple FIP devices
This commit is contained in:
Dimitris Papastamos 2018-07-04 11:46:51 +01:00 committed by GitHub
commit d22507a0b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 114 additions and 10 deletions

View File

@ -19,6 +19,10 @@
#include <utils.h> #include <utils.h>
#include <uuid.h> #include <uuid.h>
#ifndef MAX_FIP_DEVICES
#define MAX_FIP_DEVICES 1
#endif
/* Useful for printing UUIDs when debugging.*/ /* Useful for printing UUIDs when debugging.*/
#define PRINT_UUID2(x) \ #define PRINT_UUID2(x) \
"%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", \ "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", \
@ -32,11 +36,33 @@ typedef struct {
fip_toc_entry_t entry; fip_toc_entry_t entry;
} file_state_t; } 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} }; 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 file_state_t current_file = {0};
static uintptr_t backend_dev_handle; static uintptr_t backend_dev_handle;
static uintptr_t backend_image_spec; 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 */ /* Firmware Image Package driver functions */
static int fip_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); 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, .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;
/* No state associated with this device so structure can be const */ for (index = 0; index < (unsigned int)MAX_FIP_DEVICES; ++index) {
static const io_dev_info_t fip_dev_info = { /* dev_spec is used as identifier since it's unique */
.funcs = &fip_dev_funcs, if (state_pool[index].dev_spec == dev_spec) {
.info = (uintptr_t)NULL result = 0;
}; *index_out = index;
break;
}
}
return result;
}
/* Open a connection to the FIP device */ /* Allocate a device info from the pool and return a pointer to it */
static int fip_dev_open(const uintptr_t dev_spec __unused, 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;
}
/* 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) io_dev_info_t **dev_info)
{ {
int result;
io_dev_info_t *info;
fip_dev_state_t *state;
assert(dev_info != NULL); 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; return 0;
} }
@ -165,7 +265,7 @@ static int fip_dev_close(io_dev_info_t *dev_info)
backend_dev_handle = (uintptr_t)NULL; backend_dev_handle = (uintptr_t)NULL;
backend_image_spec = (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; int result;
assert(dev_con != NULL); 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) if (result == 0)
*dev_con = &fip_dev_connector; *dev_con = &fip_dev_connector;