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