mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-08 05:43:53 +00:00

The problem that this resolves is a bit involved; the following must be met at the same time for some function <to_be_wrapped>: * to_be_wrapped must be specified as part of the romlib * to_be_wrapped must _not_ be referenced by any translation unit in TF-A * to_be_wrapped must be referenced by a translation unit in a dependent library, mbedtls for example. Under these circumstances, to_be_wrapped will not be wrapped, and will instead reference its original definition while simultaneously residing in romlib. This is a side effect of two issues with romlib prior to this patch: 1 to_be_wrapped is expected to wrap by duplicating its definition. This causes any condition that links against both the base and wrapper functions to be a link error (duplicate symbol definition). 2 to_be_wrapped is in its own translation unit This causes the wrappers to be used by TF-A in an as needed. The duplicate function definitions can be worked around using the linker's `--wrap` flag, which redirects all references to a symbol to resolve to `__wrap_<symbol>` and the original symbol to be available as `__real_<symbol>`. Most of the changes handle creating this arguments and passing them to the linker. Further, once you use the linker's wrap, you will encounter another issue: if TF-A does not use a function, its wrapper is not present. This causes link issues when a library and not TF-A uses the wrapper. Note that this issue would have been resolved previously by ignoring the wrapper and using the base definition. This further issue is worked around by concatenating the assembly for all of the wrappers into a single translation unit. It's possible to work around this issue in a few other ways, including reordering the libraries passed to the linker to place libwrapper.a last or grouping the libraries so that symbols from later libraries may be resolved with prior libraries. I chose the translation unit concatenation approach as it revealed that a jumptable has duplicate symbols within it. Change-Id: Ie57b5ae69bde2fc8705bdc7a93fae3ddb5341ed9 Signed-off-by: Jimmy Brisson <jimmy.brisson@arm.com>
164 lines
6.1 KiB
ReStructuredText
164 lines
6.1 KiB
ReStructuredText
Library at ROM
|
|
==============
|
|
|
|
This document provides an overview of the "library at ROM" implementation in
|
|
Trusted Firmware-A (TF-A).
|
|
|
|
Introduction
|
|
~~~~~~~~~~~~
|
|
|
|
The "library at ROM" feature allows platforms to build a library of functions to
|
|
be placed in ROM. This reduces SRAM usage by utilising the available space in
|
|
ROM. The "library at ROM" contains a jump table with the list of functions that
|
|
are placed in ROM. The capabilities of the "library at ROM" are:
|
|
|
|
1. Functions can be from one or several libraries.
|
|
|
|
2. Functions can be patched after they have been programmed into ROM.
|
|
|
|
3. Platform-specific libraries can be placed in ROM.
|
|
|
|
4. Functions can be accessed by one or more BL images.
|
|
|
|
Index file
|
|
~~~~~~~~~~
|
|
|
|
.. image:: ../resources/diagrams/romlib_design.png
|
|
:width: 600
|
|
|
|
Library at ROM is described by an index file with the list of functions to be
|
|
placed in ROM. The index file is platform specific and its format is:
|
|
|
|
::
|
|
|
|
lib function [patch]
|
|
|
|
lib -- Name of the library the function belongs to
|
|
function -- Name of the function to be placed in library at ROM
|
|
[patch] -- Option to patch the function
|
|
|
|
It is also possible to insert reserved spaces in the list by using the keyword
|
|
"reserved" rather than the "lib" and "function" names as shown below:
|
|
|
|
::
|
|
|
|
reserved
|
|
|
|
The reserved spaces can be used to add more functions in the future without
|
|
affecting the order and location of functions already existing in the jump
|
|
table. Also, for additional flexibility and modularity, the index file can
|
|
include other index files.
|
|
|
|
For an index file example, refer to ``lib/romlib/jmptbl.i``.
|
|
|
|
Wrapper functions
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
.. image:: ../resources/diagrams/romlib_wrapper.png
|
|
:width: 600
|
|
|
|
When invoking a function of the "library at ROM", the calling sequence is as
|
|
follows:
|
|
|
|
BL image --> wrapper function --> jump table entry --> library at ROM
|
|
|
|
The index file is used to create a jump table which is placed in ROM. Then, the
|
|
wrappers refer to the jump table to call the "library at ROM" functions. The
|
|
wrappers essentially contain a branch instruction to the jump table entry
|
|
corresponding to the original function. Finally, the original function in the BL
|
|
image(s) is replaced with the wrapper function.
|
|
|
|
The "library at ROM" contains a necessary init function that initialises the
|
|
global variables defined by the functions inside "library at ROM".
|
|
|
|
Wrapper functions are specified at the link stage of compilation and cannot
|
|
interpose uppon functions within the same translation unit. For example, if
|
|
function ``fn_a`` calls ``fn_b`` within translation unit ``functions.c`` and
|
|
the romlib jump table includes an entry for ``fn_b``, ``fn_a`` will include
|
|
a reference to ``fn_b``'s original program text instead of the wrapper. Thus
|
|
the jumptable author must take care to include public entry points into
|
|
translation units to avoid paying the program text cost twice, once in the
|
|
original executable and once in romlib.
|
|
|
|
Script
|
|
~~~~~~
|
|
|
|
There is a ``romlib_generator.py`` Python script that generates the necessary
|
|
files for the "library at ROM" to work. It implements multiple functions:
|
|
|
|
1. ``romlib_generator.py gentbl [args]`` - Generates the jump table by parsing
|
|
the index file.
|
|
|
|
2. ``romlib_generator.py genvar [args]`` - Generates the jump table global
|
|
variable (**not** the jump table itself) with the absolute address in ROM.
|
|
This global variable is, basically, a pointer to the jump table.
|
|
|
|
3. ``romlib_generator.py genwrappers [args]`` - Generates a wrapper function for
|
|
each entry in the index file except for the ones that contain the keyword
|
|
``patch``. The generated wrapper file is called ``wrappers.s``.
|
|
|
|
4. ``romlib_generator.py pre [args]`` - Preprocesses the index file which means
|
|
it resolves all the include commands in the file recursively. It can also
|
|
generate a dependency file of the included index files which can be directly
|
|
used in makefiles.
|
|
|
|
Each ``romlib_generator.py`` function has its own manual which is accessible by
|
|
runing ``romlib_generator.py [function] --help``.
|
|
|
|
``romlib_generator.py`` requires Python 3 environment.
|
|
|
|
|
|
Patching of functions in library at ROM
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The ``romlib_generator.py genwrappers`` does not generate wrappers for the
|
|
entries in the index file that contain the keyword ``patch``. Thus, it allows
|
|
calling the function from the actual library by breaking the link to the
|
|
"library at ROM" version of this function.
|
|
|
|
The calling sequence for a patched function is as follows:
|
|
|
|
BL image --> function
|
|
|
|
Memory impact
|
|
~~~~~~~~~~~~~
|
|
|
|
Using library at ROM will modify the memory layout of the BL images:
|
|
|
|
- The ROM library needs a page aligned RAM section to hold the RW data. This
|
|
section is defined by the ROMLIB_RW_BASE and ROMLIB_RW_END macros.
|
|
On Arm platforms a section of 1 page (0x1000) is allocated at the top of SRAM.
|
|
This will have for effect to shift down all the BL images by 1 page.
|
|
|
|
- Depending on the functions moved to the ROM library, the size of the BL images
|
|
will be reduced.
|
|
For example: moving MbedTLS function into the ROM library reduces BL1 and
|
|
BL2, but not BL31.
|
|
|
|
- This change in BL images size can be taken into consideration to optimize the
|
|
memory layout when defining the BLx_BASE macros.
|
|
|
|
Build library at ROM
|
|
~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
The environment variable ``CROSS_COMPILE`` must be set appropriately. Refer to
|
|
:ref:`Performing an Initial Build` for more information about setting this
|
|
variable.
|
|
|
|
In the below example the usage of ROMLIB together with mbed TLS is demonstrated
|
|
to showcase the benefits of library at ROM - it's not mandatory.
|
|
|
|
.. code:: shell
|
|
|
|
make PLAT=fvp \
|
|
MBEDTLS_DIR=</path/to/mbedtls/> \
|
|
TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \
|
|
ARM_ROTPK_LOCATION=devel_rsa \
|
|
ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \
|
|
BL33=</path/to/bl33.bin> \
|
|
USE_ROMLIB=1 \
|
|
all fip
|
|
|
|
--------------
|
|
|
|
*Copyright (c) 2019, Arm Limited. All rights reserved.*
|