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 <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;
/* 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
};
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;
}
/* Open a connection to the FIP device */
static int fip_dev_open(const uintptr_t dev_spec __unused,
/* 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;
}
/* 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;