From b852d229f32aa65a8f402931fe6940a4303fe9e0 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Fri, 24 May 2019 20:31:15 -0700 Subject: [PATCH] Introduce lightweight BL platform parameter library This patch adds some common helper code to support a lightweight platform parameter passing framework between BLs that has already been used on Rockchip platforms but is more widely useful to others as well. It can be used as an implementation for the SoC firmware configuration file mentioned in the docs, and is primarily intended for platforms that only require a handful of values to be passed and want to get by without a libfdt dependency. Parameters are stored in a linked list and the parameter space is split in generic and vendor-specific parameter types. Generic types will be handled by this code whereas vendor-specific types have to be handled by a vendor-specific handler function that gets passed in. Change-Id: If3413d44e86b99d417294ce8d33eb2fc77a6183f Signed-off-by: Julius Werner --- include/lib/bl_aux_params/bl_aux_params.h | 103 ++++++++++++++++++++++ lib/bl_aux_params/bl_aux_params.c | 33 +++++++ 2 files changed, 136 insertions(+) create mode 100644 include/lib/bl_aux_params/bl_aux_params.h create mode 100644 lib/bl_aux_params/bl_aux_params.c diff --git a/include/lib/bl_aux_params/bl_aux_params.h b/include/lib/bl_aux_params/bl_aux_params.h new file mode 100644 index 000000000..cfea39564 --- /dev/null +++ b/include/lib/bl_aux_params/bl_aux_params.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef LIB_BL_AUX_PARAMS_H +#define LIB_BL_AUX_PARAMS_H + +#include +#include + +/* + * This API implements a lightweight parameter passing mechanism that can be + * used to pass SoC Firmware configuration data from BL2 to BL31 by platforms or + * configurations that do not want to depend on libfdt. It is structured as a + * singly-linked list of parameter structures that all share the same common + * header but may have different (and differently-sized) structure bodies after + * that. The header contains a type field to indicate the parameter type (which + * is used to infer the structure length and how to interpret its contents) and + * a next pointer which contains the absolute physical address of the next + * parameter structure. The next pointer in the last structure block is set to + * NULL. The picture below shows how the parameters are kept in memory. + * + * head of list ---> +----------------+ --+ + * | type | | + * +----------------+ |--> struct bl_aux_param + * +----| next | | + * | +----------------+ --+ + * | | parameter data | + * | +----------------+ + * | + * +--> +----------------+ --+ + * | type | | + * +----------------+ |--> struct bl_aux_param + * NULL <---| next | | + * +----------------+ --+ + * | parameter data | + * +----------------+ + * + * Note: The SCTLR_EL3.A bit (Alignment fault check enable) is set in TF-A, so + * BL2 must ensure that each parameter struct starts on a 64-bit aligned address + * to avoid alignment faults. Parameters may be allocated in any address range + * accessible at the time of BL31 handoff (e.g. SRAM, DRAM, SoC-internal scratch + * registers, etc.), in particular address ranges that may not be mapped in + * BL31's page tables, so the parameter list must be parsed before the MMU is + * enabled and any information that is required at a later point should be + * deep-copied out into BL31-internal data structures. + */ + +enum bl_aux_param_type { + BL_AUX_PARAM_NONE = 0, + BL_AUX_PARAM_VENDOR_SPECIFIC_FIRST = 0x1, + /* 0x1 - 0x7fffffff can be used by vendor-specific handlers. */ + BL_AUX_PARAM_VENDOR_SPECIFIC_LAST = 0x7fffffff, + BL_AUX_PARAM_GENERIC_FIRST = 0x80000001, + BL_AUX_PARAM_COREBOOT_TABLE = BL_AUX_PARAM_GENERIC_FIRST, + /* 0x80000001 - 0xffffffff are reserved for the generic handler. */ + BL_AUX_PARAM_GENERIC_LAST = 0xffffffff, + /* Top 32 bits of the type field are reserved for future use. */ +}; + +/* common header for all BL aux parameters */ +struct bl_aux_param_header { + uint64_t type; + uint64_t next; +}; + +/* commonly useful parameter structures that can be shared by multiple types */ +struct bl_aux_param_uint64 { + struct bl_aux_param_header h; + uint64_t value; +}; + +struct bl_aux_gpio_info { + uint8_t polarity; + uint8_t direction; + uint8_t pull_mode; + uint8_t reserved; + uint32_t index; +}; + +struct bl_aux_param_gpio { + struct bl_aux_param_header h; + struct bl_aux_gpio_info gpio; +}; + +/* + * Handler function that handles an individual aux parameter. Return true if + * the parameter was handled, and flase if bl_aux_params_parse() should make its + * own attempt at handling it (for generic parameters). + */ +typedef bool (*bl_aux_param_handler_t)(struct bl_aux_param_header *param); + +/* + * Interprets head as the start of an aux parameter list, and passes the + * parameters individually to handler(). Handles generic parameters directly if + * handler() hasn't already done so. If only generic parameters are expected, + * handler() can be NULL. + */ +void bl_aux_params_parse(u_register_t head, + bl_aux_param_handler_t handler); + +#endif /* LIB_BL_AUX_PARAMS_H */ diff --git a/lib/bl_aux_params/bl_aux_params.c b/lib/bl_aux_params/bl_aux_params.c new file mode 100644 index 000000000..7a8115c61 --- /dev/null +++ b/lib/bl_aux_params/bl_aux_params.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +void bl_aux_params_parse(u_register_t head, + bl_aux_param_handler_t handler) +{ + struct bl_aux_param_header *p; + + for (p = (void *)head; p; p = (void *)(uintptr_t)p->next) { + if (handler && handler(p)) + continue; + + switch (p->type) { +#if COREBOOT + case BL_AUX_PARAM_COREBOOT_TABLE: + coreboot_table_setup((void *)(uintptr_t) + ((struct bl_aux_param_uint64 *)p)->value); + break; +#endif + default: + ERROR("Ignoring unknown BL aux parameter: 0x%llx", + p->type); + break; + } + } +}