diff --git a/docs/components/fconf.rst b/docs/components/fconf.rst new file mode 100644 index 0000000..cec3ceb --- /dev/null +++ b/docs/components/fconf.rst @@ -0,0 +1,85 @@ +Firmware Configuration Framework +================================ + +This document provides an overview of the |FCONF| framework. + +Introduction +~~~~~~~~~~~~ + +The Firmware CONfiguration Framework (|FCONF|) is an abstraction layer for +platform specific data, allowing a "property" to be queried and a value +retrieved without the requesting entity knowing what backing store is being used +to hold the data. + +It is used to bridge new and old ways of providing platform-specific data. +Today, information like the Chain of Trust is held within several, nested +platform-defined tables. In the future, it may be provided as part of a device +blob, along with the rest of the information about images to load. +Introducing this abstraction layer will make migration easier and will preserve +functionality for platforms that cannot / don't want to use device tree. + +Accessing properties +~~~~~~~~~~~~~~~~~~~~ + +Properties defined in the |FCONF| are grouped around namespaces and +sub-namespaces: a.b.property. +Examples namespace can be: + +- (|TBBR|) Chain of Trust data: tbbr.cot.trusted_boot_fw_cert +- (|TBBR|) dynamic configuration info: tbbr.dyn_config.disable_auth +- Arm io policies: arm.io_policies.bl2_image + +Properties can be accessed with the ``FCONF_GET_PROPERTY(a,b,property)`` macro. + +Defining properties +~~~~~~~~~~~~~~~~~~~ + +Properties composing the |FCONF| have to be stored in C structures. If another +backing store is wanted to be used, the platform has to provide a ``populate()`` +function to fill the corresponding C structure. + +The ``populate()`` function must be registered to the |FCONF| framework with +the ``FCONF_REGISTER_POPULATOR()`` macro. This ensures that the function would +be called inside the generic ``fconf_populate()`` function during +initialization. + +:: + + int fconf_populate_tbbr_dyn_config(uintptr_t config) + { + /* read dtb and fill tbbr_dyn_config struct */ + } + + FCONF_REGISTER_POPULATOR(fconf_populate_tbbr_dyn_config); + +Then, a wrapper has to be provided to match the ``FCONF_GET_PROPERTY()`` macro: + +:: + + /* generic getter */ + #define FCONF_GET_PROPERTY(a,b,property) a##__##b##_getter(property) + + /* my specific getter */ + #define tbbr__dyn_config_getter(id) tbbr_dyn_config.id + +This second level wrapper can be used to remap the ``FCONF_GET_PROPERTY()`` to +anything appropriate: structure, array, function, etc.. + +Loading the property device tree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``fconf_load_config()`` must be called to load the device tree containing +the properties' values. This must be done after the io layer is initialized, as +the |DTB| is stored on an external device (FIP). + +.. uml:: ../resources/diagrams/plantuml/fconf_bl1_load_config.puml + +Populating the properties +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once a valid device tree is available, the ``fconf_populate(config)`` function +can be used to fill the C data structure with the data from the config |DTB|. +This function will call all the ``populate()`` callbacks which have been +registered with ``FCONF_REGISTER_POPULATOR()``. + +.. uml:: ../resources/diagrams/plantuml/fconf_bl2_populate.puml diff --git a/docs/components/index.rst b/docs/components/index.rst index f1904c0..6a6b1b0 100644 --- a/docs/components/index.rst +++ b/docs/components/index.rst @@ -9,6 +9,7 @@ spd/index arm-sip-service exception-handling + fconf firmware-update platform-interrupt-controller-API ras diff --git a/docs/global_substitutions.txt b/docs/global_substitutions.txt index 491b160..4dda1dc 100644 --- a/docs/global_substitutions.txt +++ b/docs/global_substitutions.txt @@ -6,11 +6,13 @@ .. |COT| replace:: :term:`COT` .. |CSS| replace:: :term:`CSS` .. |CVE| replace:: :term:`CVE` +.. |DTB| replace:: :term:`DTB` .. |DS-5| replace:: :term:`DS-5` .. |DSU| replace:: :term:`DSU` .. |DT| replace:: :term:`DT` .. |EL| replace:: :term:`EL` .. |EHF| replace:: :term:`EHF` +.. |FCONF| replace:: :term:`FCONF` .. |FDT| replace:: :term:`FDT` .. |FIP| replace:: :term:`FIP` .. |FVP| replace:: :term:`FVP` diff --git a/docs/glossary.rst b/docs/glossary.rst index 2f19df5..3da30b0 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -42,12 +42,18 @@ DT Device Tree + DTB + Device Tree Blob + EL Exception Level EHF Exception Handling Framework + FCONF + Firmware Configuration Framework + FDT Flattened Device Tree diff --git a/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml b/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml new file mode 100644 index 0000000..c36e544 --- /dev/null +++ b/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml @@ -0,0 +1,52 @@ +@startuml + +box "BL1 common code" + participant bl1_main + participant bl_common +end box + +box "arm platform code" #LightBlue + participant fvp_bl1_setup + participant arm_bl1_setup + participant arm_io_storage +end box + +box "platform common code" + participant plat_bl1_common + participant fconf +end box + +bl1_main -> fvp_bl1_setup : bl1_platform_setup() +fvp_bl1_setup -> arm_bl1_setup : arm_bl1_platform_setup() +arm_bl1_setup -> arm_io_storage : plat_arm_io_setup() +note over arm_io_storage : register and setup fip +arm_bl1_setup -> fconf : fconf_load_config() +activate fconf + note over fconf + create and populate an + image_desc_t for TB_FW_CONFIG + end note + fconf -> bl_common : load_auth_image(TB_FW_CONFIG_ID, &image_info) + activate bl_common + note over bl_common + load and auth image from fip + with info from plat_io_policy + end note + bl_common -> arm_io_storage + arm_io_storage -> fconf: FCONF_GET_PROPERTY(arm, arm_io_policies, tb_fw_cfg) + note over fconf: use staticaly defined policies in bl1 + fconf <- bl_common : image_info + deactivate bl_common + note over fconf : get tb_fw_config_dtb from image_info + fconf -> plat_bl1_common : bl1_plat_get_image_desc(BL2_IMAGE_ID) + fconf <- plat_bl1_common : BL2_IMAGE_DESC + note over fconf + set ep_info.args.arg0 of BL2_IMAGE_DESC + to TB_FW_CONFIG base address + end note +arm_bl1_setup <- fconf +deactivate fconf + +== load & auth, prepare and jump to BL2 == + +@enduml diff --git a/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml b/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml new file mode 100644 index 0000000..98a3ff1 --- /dev/null +++ b/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml @@ -0,0 +1,41 @@ +@startuml + +box "BL2 common code" + participant bl2_entrypoint + participant bl2_main +end box + +box "platform common code" + participant fconf + participant fconf_tbbr_getter +end box + +box "arm platform code" #LightBlue + participant arm_bl2_setup + participant arm_io_storage + participant arm_fconf_io +end box + +== bl2 setup == +bl2_entrypoint -> bl2_main : bl2_setup() +bl2_main -> arm_bl2_setup : bl2_early_platform_setup2(\n\t arg0, arg1, arg2, arg3) +note over arm_bl2_setup + arg0 = tb_fw_config + arg1 = mem_layout +end note +arm_bl2_setup -> arm_bl2_setup : arm_bl2_early_platform_setup(\n\t tb_fw_config, mem_layout) +activate arm_bl2_setup + arm_bl2_setup -> fconf: fconf_polulate(tb_fw_config) + activate fconf + fconf -> fconf_tbbr_getter: fconf_populate_tbbr_dyn_config(uintptr_t dtb) + note over fconf_tbbr_getter: read tbbr propeties from dtb + fconf -> arm_fconf_io: fconf_populate_arm_io_policies(uintptr_t dtb) + note over arm_fconf_io: read arm io propeties from dtb + deactivate fconf + arm_bl2_setup -> arm_io_storage : plat_arm_io_setup() + note over arm_io_storage: use populated properties +deactivate arm_bl2_setup + +== bl2 main == + +@enduml