1Firmware Configuration Framework 2================================ 3 4This document provides an overview of the |FCONF| framework. 5 6Introduction 7~~~~~~~~~~~~ 8 9The Firmware CONfiguration Framework (|FCONF|) is an abstraction layer for 10platform specific data, allowing a "property" to be queried and a value 11retrieved without the requesting entity knowing what backing store is being used 12to hold the data. 13 14It is used to bridge new and old ways of providing platform-specific data. 15Today, information like the Chain of Trust is held within several, nested 16platform-defined tables. In the future, it may be provided as part of a device 17blob, along with the rest of the information about images to load. 18Introducing this abstraction layer will make migration easier and will preserve 19functionality for platforms that cannot / don't want to use device tree. 20 21Accessing properties 22~~~~~~~~~~~~~~~~~~~~ 23 24Properties defined in the |FCONF| are grouped around namespaces and 25sub-namespaces: a.b.property. 26Examples namespace can be: 27 28- (|TBBR|) Chain of Trust data: tbbr.cot.trusted_boot_fw_cert 29- (|TBBR|) dynamic configuration info: tbbr.dyn_config.disable_auth 30- Arm io policies: arm.io_policies.bl2_image 31- GICv3 properties: hw_config.gicv3_config.gicr_base 32 33Properties can be accessed with the ``FCONF_GET_PROPERTY(a,b,property)`` macro. 34 35Defining properties 36~~~~~~~~~~~~~~~~~~~ 37 38Properties composing the |FCONF| have to be stored in C structures. If 39properties originate from a different backend source such as a device tree, 40then the platform has to provide a ``populate()`` function which essentially 41captures the property and stores them into a corresponding |FCONF| based C 42structure. 43 44Such a ``populate()`` function is usually platform specific and is associated 45with a specific backend source. For example, a populator function which 46captures the hardware topology of the platform from the HW_CONFIG device tree. 47Hence each ``populate()`` function must be registered with a specific 48``config_type`` identifier. It broadly represents a logical grouping of 49configuration properties which is usually a device tree file. 50 51Example: 52 - TB_FW: properties related to trusted firmware such as IO policies, 53 base address of other DTBs, mbedtls heap info etc. 54 - HW_CONFIG: properties related to hardware configuration of the SoC 55 such as topology, GIC controller, PSCI hooks, CPU ID etc. 56 57Hence the ``populate()`` callback must be registered to the (|FCONF|) framework 58with the ``FCONF_REGISTER_POPULATOR()`` macro. This ensures that the function 59would be called inside the generic ``fconf_populate()`` function during 60initialization. 61 62:: 63 64 int fconf_populate_topology(uintptr_t config) 65 { 66 /* read hw config dtb and fill soc_topology struct */ 67 } 68 69 FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology); 70 71Then, a wrapper has to be provided to match the ``FCONF_GET_PROPERTY()`` macro: 72 73:: 74 75 /* generic getter */ 76 #define FCONF_GET_PROPERTY(a,b,property) a##__##b##_getter(property) 77 78 /* my specific getter */ 79 #define hw_config__topology_getter(prop) soc_topology.prop 80 81This second level wrapper can be used to remap the ``FCONF_GET_PROPERTY()`` to 82anything appropriate: structure, array, function, etc.. 83 84To ensure a good interpretation of the properties, this documentation must 85explain how the properties are described for a specific backend. Refer to the 86:ref:`binding-document` section for more information and example. 87 88Loading the property device tree 89~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 90 91The ``fconf_load_config()`` must be called to load the device tree containing 92the properties' values. This must be done after the io layer is initialized, as 93the |DTB| is stored on an external device (FIP). 94 95.. uml:: ../../resources/diagrams/plantuml/fconf_bl1_load_config.puml 96 97Populating the properties 98~~~~~~~~~~~~~~~~~~~~~~~~~ 99 100Once a valid device tree is available, the ``fconf_populate(config)`` function 101can be used to fill the C data structure with the data from the config |DTB|. 102This function will call all the ``populate()`` callbacks which have been 103registered with ``FCONF_REGISTER_POPULATOR()`` as described above. 104 105.. uml:: ../../resources/diagrams/plantuml/fconf_bl2_populate.puml 106 107Namespace guidance 108~~~~~~~~~~~~~~~~~~ 109 110As mentioned above, properties are logically grouped around namespaces and 111sub-namespaces. The following concepts should be considered when adding new 112properties/namespaces. 113The framework differentiates two types of properties: 114 115 - Properties used inside common code. 116 - Properties used inside platform specific code. 117 118The first category applies to properties being part of the firmware and shared 119across multiple platforms. They should be globally accessible and defined 120inside the ``lib/fconf`` directory. The namespace must be chosen to reflect the 121feature/data abstracted. 122 123Example: 124 - |TBBR| related properties: tbbr.cot.bl2_id 125 - Dynamic configuration information: dyn_cfg.dtb_info.hw_config_id 126 127The second category should represent the majority of the properties defined 128within the framework: Platform specific properties. They must be accessed only 129within the platform API and are defined only inside the platform scope. The 130namespace must contain the platform name under which the properties defined 131belong. 132 133Example: 134 - Arm io framework: arm.io_policies.bl31_id 135 136.. _binding-document: 137 138Properties binding information 139~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 140 141.. toctree:: 142 :maxdepth: 1 143 144 fconf_properties 145