blob: b2b24eff10798f983f739a22993359aef3685143 [file] [log] [blame]
/*
* Copyright (c) 2022-2023, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include <stdint.h>
#include <trace.h>
#include "installer.h"
#include "installer_index.h"
#ifndef INSTALLER_INDEX_LIMIT
#define INSTALLER_INDEX_LIMIT (8)
#endif
#ifndef INSTALLER_INDEX_LOCATION_ID_LIMIT
#define INSTALLER_INDEX_LOCATION_ID_LIMIT (8)
#endif
/**
* Singleton index of installers to use for different classes of image.
*/
static struct {
/* An index for registered installers to handle update installation
* for the platform. The set of registered installers will have been
* selected for compatibility with the class of update image handled
* by the installer.
*/
size_t num_registered;
struct installer *installers[INSTALLER_INDEX_LIMIT];
/* Each installer is associated with a location via the assigned
* location_id. This is used as a logical identifier for the part
* of the device firmware that the installer handles. Multiple
* installers may be associated with the same location.
*/
size_t num_location_ids;
uint32_t location_ids[INSTALLER_INDEX_LOCATION_ID_LIMIT];
} installer_index;
static void add_location_id(uint32_t location_id)
{
/* Check if location_id already added. Because 1..* installers
* may be associated with the same location_id, we can ignore
* location_ids that have already been added.
*/
for (size_t i = 0; i < installer_index.num_location_ids; i++) {
if (location_id == installer_index.location_ids[i])
return;
}
/* It's a new location_id so add it */
if (installer_index.num_location_ids < INSTALLER_INDEX_LOCATION_ID_LIMIT) {
installer_index.location_ids[installer_index.num_location_ids] = location_id;
++installer_index.num_location_ids;
} else {
EMSG("Too many FWU locations");
}
}
void installer_index_init(void)
{
installer_index_clear();
}
void installer_index_clear(void)
{
memset(&installer_index, 0, sizeof(installer_index));
}
void installer_index_register(
struct installer *installer)
{
assert(installer);
if (installer_index.num_registered < INSTALLER_INDEX_LIMIT) {
installer_index.installers[installer_index.num_registered] = installer;
++installer_index.num_registered;
add_location_id(installer->location_id);
} else {
EMSG("FWU configuration exceeds installer limit");
}
}
struct installer *installer_index_find(
enum install_type install_type,
uint32_t location_id)
{
struct installer *result = NULL;
for (size_t i = 0; i < installer_index.num_registered; i++) {
struct installer *installer = installer_index.installers[i];
if ((installer->install_type == install_type) &&
(installer->location_id == location_id)) {
result = installer;
break;
}
}
return result;
}
struct installer *installer_index_find_by_location_uuid(
const struct uuid_octets *location_uuid)
{
struct installer *result = NULL;
for (size_t i = 0; i < installer_index.num_registered; i++) {
struct installer *installer = installer_index.installers[i];
if (uuid_is_equal(location_uuid->octets,
installer->location_uuid.octets)) {
result = installer;
break;
}
}
return result;
}
struct installer *installer_index_get(
unsigned int index)
{
struct installer *result = NULL;
if (index < installer_index.num_registered)
result = installer_index.installers[index];
return result;
}
const uint32_t *installer_index_get_location_ids(size_t *num_ids)
{
*num_ids = installer_index.num_location_ids;
return installer_index.location_ids;
}