diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst index 72865a517..b327f6ee3 100644 --- a/docs/getting_started/porting-guide.rst +++ b/docs/getting_started/porting-guide.rst @@ -2762,14 +2762,12 @@ can be obtained from http://github.com/freebsd/freebsd. Storage abstraction layer ------------------------- -In order to improve platform independence and portability an storage abstraction -layer is used to load data from non-volatile platform storage. +In order to improve platform independence and portability a storage abstraction +layer is used to load data from non-volatile platform storage. Currently +storage access is only required by BL1 and BL2 phases and performed inside the +``load_image()`` function in ``bl_common.c``. -Each platform should register devices and their drivers via the Storage layer. -These drivers then need to be initialized by bootloader phases as -required in their respective ``blx_platform_setup()`` functions. Currently -storage access is only required by BL1 and BL2 phases. The ``load_image()`` -function uses the storage layer to access non-volatile platform storage. +.. uml:: ../resources/diagrams/plantuml/io_framework_usage_overview.puml It is mandatory to implement at least one storage driver. For the Arm development platforms the Firmware Image Package (FIP) driver is provided as @@ -2779,13 +2777,25 @@ section in the `User Guide`_). The storage layer is described in the header file is in ``drivers/io/io_storage.c`` and the driver files are located in ``drivers/io/``. +.. uml:: ../resources/diagrams/plantuml/io_arm_class_diagram.puml + Each IO driver must provide ``io_dev_*`` structures, as described in ``drivers/io/io_driver.h``. These are returned via a mandatory registration function that is called on platform initialization. The semi-hosting driver implementation in ``io_semihosting.c`` can be used as an example. -The Storage layer provides mechanisms to initialize storage devices before -IO operations are called. The basic operations supported by the layer +Each platform should register devices and their drivers via the storage +abstraction layer. These drivers then need to be initialized by bootloader +phases as required in their respective ``blx_platform_setup()`` functions. + +.. uml:: ../resources/diagrams/plantuml/io_dev_registration.puml + +The storage abstraction layer provides mechanisms (``io_dev_init()``) to +initialize storage devices before IO operations are called. + +.. uml:: ../resources/diagrams/plantuml/io_dev_init_and_check.puml + +The basic operations supported by the layer include ``open()``, ``close()``, ``read()``, ``write()``, ``size()`` and ``seek()``. Drivers do not have to implement all operations, but each platform must provide at least one driver for a device capable of supporting generic diff --git a/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml b/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml new file mode 100644 index 000000000..53594c2ba --- /dev/null +++ b/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml @@ -0,0 +1,109 @@ +@startuml + +package arm_io_storage { + + class plat_io_policy { + dev_handle : uintptr_t* + image_spec : uintptr_t + {abstract} check() : fctptr + } + + class FIP_IMAGE_ID { + memmap_dev_handle + fip_block_spec + open_memmap() + } + + class BL2_IMAGE_ID{ + fip_dev_handle + bl2_uuid_spec + open_fip() + } + + class xxx_IMAGE_ID{ + fip_dev_handle + xxx_uuid_spec + open_fip() + } + + class arm_io_storage { + fip_dev_con : io_dev_connector_t* + fip_dev_handle : uintptr_t + memmap_dev_con : io_dev_connector_t* + memmap_dev_handle : uintptr_t + + fip_block_spec : io_block_spec_t + + policies : plat_io_policy[1..*] + + -open_fip() + -open_memmap() + + +arm_io_setup() + +plat_get_image_source() + } + + FIP_IMAGE_ID -up-|> plat_io_policy + BL2_IMAGE_ID -up-|> plat_io_policy + xxx_IMAGE_ID -up-|> plat_io_policy + + arm_io_storage *-"1..*" plat_io_policy +} + +package IO { + class io_storage { + io_dev_open() + io_dev_init() + io_dev_close() + + .. synchronous operations .. + io_open() + io_seek() + io_size() + io_read() + io_write() + io_close() + + io_register_device() + } + + class io_fip { + register_io_dev_fip() + .. io_dev_funcs_t interface .. + fip_dev_funcs : io_dev_funcs_t + } + + class io_memmap { + register_io_dev_memmap() + .. io_dev_funcs_t interface .. + memmap_dev_funcs : io_dev_funcs_t + } + + interface io_driver { + io_entity_t + io_dev_info_t + + .. io_dev_connector_t interface .. + dev_open() + + .. io_dev_funcs_t interface .. + type() + open() + seek() + size() + read() + write() + close() + dev_init() + dev_close() + + io_register_device() + } +} +arm_io_storage .. io_driver +arm_io_storage .. io_fip +arm_io_storage .. io_memmap +arm_io_storage .. io_storage + + +@enduml diff --git a/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml b/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml new file mode 100644 index 000000000..2752b3326 --- /dev/null +++ b/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml @@ -0,0 +1,62 @@ +@startuml + +participant arm_io_storage order 1 +participant io_storage order 2 + + -> arm_io_storage : plat_get_image_source(image_id, &dev_handle, &image_spec) + +group init and check device (image_id) + +alt image_id = BL2_IMAGE_ID +note over arm_io_storage + get BL2_IMAGE_ID policy: + - fip_dev_handle + - open_fip() +end note +opt policy->check() + arm_io_storage -> arm_io_storage : open_fip(spec) + activate arm_io_storage + arm_io_storage -> io_storage : io_dev_init(fip_dev_handle, FIP_IMAGE_ID) + ref over io_storage : dev_init() on fip device + + arm_io_storage -> io_storage : io_open(fip_dev_handle, spec, &local_image_handle) + ref over io_storage : io_open() on fip device + + arm_io_storage -> io_storage : io_close(local_image_handle) + ref over io_storage : io_close() on fip device + + hnote over arm_io_storage + fip_dev_handle ready + end note +end opt +deactivate arm_io_storage + +else image_id = FIP_IMAGE_ID +activate arm_io_storage +note over arm_io_storage + get FIP_IMAGE_ID policy: + - memmap_dev_handle + - open_memmap() +end note +opt policy->check() + arm_io_storage -> arm_io_storage : open_memmap(spec) + activate arm_io_storage + arm_io_storage -> io_storage : io_dev_init(memmap_dev_handle, NULL) + ref over io_storage : dev_init() on memmap device + + arm_io_storage -> io_storage : io_open(memmap_dev_handle, spec, &local_image_handle) + ref over io_storage : io_open() on memmap device + + arm_io_storage -> io_storage : io_close(local_image_handle) + ref over io_storage : io_close() on memmap device + + hnote over arm_io_storage + memmap_dev_handle ready + end note + deactivate arm_io_storage +end opt +deactivate arm_io_storage +end alt + +end group +@enduml diff --git a/docs/resources/diagrams/plantuml/io_dev_registration.puml b/docs/resources/diagrams/plantuml/io_dev_registration.puml new file mode 100644 index 000000000..114c3b778 --- /dev/null +++ b/docs/resources/diagrams/plantuml/io_dev_registration.puml @@ -0,0 +1,52 @@ +@startuml + +participant arm_io_storage order 1 +participant io_storage order 2 +participant io_fip order 3 +participant io_memmap order 4 + + -> arm_io_storage : arm_io_setup() + +group io dev registration + +arm_io_storage -> io_fip : register_io_dev_fip(&fip_dev_con) +io_fip -> io_storage : io_register_device(&dev_info_pool[]) +note over io_storage + devices[dev_count] = (fip_)dev_info_pool + dev_count++ +end note + +arm_io_storage -> io_memmap : register_io_dev_memmap(&memmap_dev_con) +io_memmap -> io_storage : io_register_device(&memmap_dev_info) +note over io_storage + devices[dev_count] = memmap_dev_info + dev_count++ +end note + +arm_io_storage -> io_storage : io_dev_open(fip_dev_con, NULL, fip_dev_handle) + io_storage -> io_storage : dev_open(dev_con, dev_spec, handle) +activate io_storage +opt dev_open() on fip device + io_storage -> io_fip : fip_dev_open(dev_spec, dev_info) + note over io_fip + dev_info = one of the + "fip_dev_info" from + dev_info_pool[] + end note +end opt +deactivate io_storage + + +arm_io_storage -> io_storage : io_dev_open(memmap_dev_con, NULL, memmap_dev_handle) +io_storage -> io_storage : dev_open(dev_con, dev_spec, handle) +activate io_storage +opt dev_open() on memmap device + io_storage -> io_memmap : memmap_dev_open(dev_spec, dev_info) + note over io_memmap + dev_info = memmap_dev_info + end note +end opt +deactivate io_storage + +end group +@enduml diff --git a/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml b/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml new file mode 100644 index 000000000..eb3e2b4c7 --- /dev/null +++ b/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml @@ -0,0 +1,59 @@ +@startuml + +participant bl_common order 1 +participant arm_io_storage order 2 +participant io_storage order 3 + +== Platform Setup == + +bl1_main -> xxx_bl1_setup : bl1_platform_setup() +xxx_bl1_setup -> arm_io_storage : plat_arm_io_setup() + +arm_io_storage -> arm_io_storage : arm_io_setup() +ref over arm_io_storage, io_storage : io device registration + +== Get Image == +bl1_main -> xxx_bl1_setup : bl1_plat_get_next_image_id() +bl1_main <-- xxx_bl1_setup : BL2_IMAGE_ID + +bl1_main -> bl1_main : bl1_load_bl2() +activate bl1_main +bl1_main -> plat_bl1_common : bl1_plat_get_image_desc(BL2_IMAGE_ID) +bl1_main <-- plat_bl1_common : BL2_IMAGE_DESC + +bl1_main -> plat_bl1_common : bl1_plat_handle_pre_image_load(BL2_IMAGE_ID) + +bl1_main -> bl_common : load_auth_image(BL2_IMAGE_ID, image_info) +activate bl_common +bl_common -> bl_common : load_auth_image_internal(BL2_IMAGE_ID, image_info, is_parent_image) +activate bl_common +bl_common -> bl_common : load_image(BL2_IMAGE_ID, image_info) +activate bl_common +bl_common -> arm_io_storage : plat_get_image_source(BL2_IMAGE_ID, &dev_handle, &image_spec) +ref over arm_io_storage, io_storage : init and check device (BL2_IMAGE_ID) +bl_common <-- arm_io_storage : dev_handle + +bl_common -> io_storage : io_open(dev_handle, image_spec, &image_handle) +ref over io_storage : io_open() on fip device +bl_common <-- io_storage : image_handle +bl_common -> io_storage : io_size(image_handle, &image_size) +ref over io_storage : io_size() on fip device +bl_common -> io_storage : io_read(image_handle, image_base, image_size, &bytes_read) +ref over io_storage : io_read() on fip device +bl_common -> io_storage : io_close(image_handle) +ref over io_storage : io_close() on fip device +bl_common -> io_storage : io_dev_close(dev_handle) +ref over io_storage : io_dev_close() on fip device + +deactivate bl_common +deactivate bl_common +deactivate bl_common + +== Prepare Next Image == +bl1_main -> plat_bl1_common : bl1_plat_handle_post_image_load(BL2_IMAGE_ID) + +deactivate bl1_main + +== Jump to next Image == + +@enduml