[PATCH v8 06/13] binman: Support new op-tee binary format

Jerome Forissier jerome.forissier at linaro.org
Sat Jan 7 22:51:34 CET 2023



On 1/7/23 19:55, Simon Glass wrote:
> Hi Quentin,
> 
> On Mon, 2 Jan 2023 at 10:54, Quentin Schulz
> <quentin.schulz at theobroma-systems.com> wrote:
>>
>> Hi Simon,
>>
>> On 12/22/22 00:07, Simon Glass wrote:
>>> OP-TEE has a format with a binary header that can be used instead of the
>>> ELF file. With newer versions of OP-TEE this may be required on some
>>> platforms.
>>>
>>> Add support for this in binman. First, add a method to obtain the ELF
>>> sections from an entry, then use that in the FIT support. We then end up
>>> with the ability to support both types of OP-TEE files, depending on which
>>> one is passed in with the entry argument (TEE=xxx in the U-Boot build).
>>>
>>> Signed-off-by: Simon Glass <sjg at chromium.org>
>>> ---
>>>
>>> (no changes since v7)
>>>
>>> Changes in v7:
>>> - Correct missing test coverage
>>>
>>> Changes in v6:
>>> - Update op-tee to support new v1 binary header
>>>
>>>   tools/binman/entries.rst                     | 35 ++++++++-
>>>   tools/binman/entry.py                        | 13 +++
>>>   tools/binman/etype/fit.py                    | 69 +++++++++-------
>>>   tools/binman/etype/section.py                |  9 +++
>>>   tools/binman/etype/tee_os.py                 | 68 +++++++++++++++-
>>>   tools/binman/ftest.py                        | 83 ++++++++++++++++++++
>>>   tools/binman/test/263_tee_os_opt.dts         | 22 ++++++
>>>   tools/binman/test/264_tee_os_opt_fit.dts     | 33 ++++++++
>>>   tools/binman/test/265_tee_os_opt_fit_bad.dts | 40 ++++++++++
>>>   9 files changed, 340 insertions(+), 32 deletions(-)
>>>   create mode 100644 tools/binman/test/263_tee_os_opt.dts
>>>   create mode 100644 tools/binman/test/264_tee_os_opt_fit.dts
>>>   create mode 100644 tools/binman/test/265_tee_os_opt_fit_bad.dts
>>>
>>> diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
>>> index b2ce7960d3b..a3e4493a44f 100644
>>> --- a/tools/binman/entries.rst
>>> +++ b/tools/binman/entries.rst
>>> @@ -1508,12 +1508,45 @@ Entry: tee-os: Entry containing an OP-TEE Trusted OS (TEE) blob
>>>
>>>   Properties / Entry arguments:
>>>       - tee-os-path: Filename of file to read into entry. This is typically
>>> -        called tee-pager.bin
>>> +        called tee.bin or tee.elf
>>>
>>>   This entry holds the run-time firmware, typically started by U-Boot SPL.
>>>   See the U-Boot README for your architecture or board for how to use it. See
>>>   https://urldefense.com/v3/__https://github.com/OP-TEE/optee_os__;!!OOPJP91ZZw!kx6SLv4sPusmg1TyYMw-Ho5G9jxeVMf9HOYx_4yq3ZNl_TpoGJoUyICZMgEiv0Zd6l_Bl8f5OAFYyJxm8wDUevhARIs$  for more information about OP-TEE.
>>>
>>> +Note that if the file is in ELF format, it must go in a FIT. In that case,
>>> +this entry will mark itself as absent, providing the data only through the
>>> +read_elf_segments() method.
>>> +
>>> +Marking this entry as absent means that it if is used in the wrong context
>>> +it can be automatically dropped. Thus it is possible to add anb OP-TEE entry
>>
>> s/anb/an/
>>
>>> +like this::
>>> +
>>> +    binman {
>>> +        tee-os {
>>> +        };
>>> +    };
>>> +
>>> +and pass either an ELF or plain binary in with -a tee-os-path <filename>
>>> +and have binman do the right thing:
>>> +
>>> +   - include the entry if tee.bin is provided and it doesn't have the v1
>>> +     header
>>> +   - drop it otherwise
>>> +
>>
>> Is there an actual usecase for this? (sorry if this was mentioned in the
>> earlier versions of the patch) Are we expecting to be able to append the
>> content of tee-os to some raw binary instead of putting OP-TEE OS in a
>> u-boot.itb image?
> 
> Yes, that is my understanding. Perhaps it is for some archs or some
> old versions. But in any case, we can always drop it later if not
> needed, refine the warnings, etc. etc. But please let's land this mess
> and move on. If I had pushed a little harder a year ago we would have
> be talking about how to do this properly in binman rather than me
> trying to retrofit everything.
> 
> [..]
> 
>>
>> You can use a reference here since we have a _etype_fit target for "Flat
>> Image Tree / FIT".
>>
>>> +the binary v1 format is provided.
>>> +
>>>
>>
>> I'm a bit worried this is OP-TEE OS specific? We could also point to the
>> documentation here:
>> https://optee.readthedocs.io/en/latest/architecture/core.html#partitioning-of-the-binary?
> 
> Yes it is...I believe there will be other use cases for absent
> entries....in a way it is quite a big hold in binman's functionality.
> Will link to the docs.
> 
>>
>>>
>>>   .. _etype_text:
>>> diff --git a/tools/binman/entry.py b/tools/binman/entry.py
>>> index 637aece3705..de51d295891 100644
>>> --- a/tools/binman/entry.py
>>> +++ b/tools/binman/entry.py
>>> @@ -1290,3 +1290,16 @@ features to produce new behaviours.
>>>       def mark_absent(self, msg):
>>>           tout.info("Entry '%s' marked absent: %s" % (self._node.path, msg))
>>>           self.absent = True
>>> +
>>> +    def read_elf_segments(self):
>>> +        """Read segments from an entry that can generate an ELF file
>>> +
>>> +        Returns:
>>> +            tuple:
>>> +                list of segments, each:
>>> +                    int: Segment number (0 = first)
>>> +                    int: Start address of segment in memory
>>> +                    bytes: Contents of segment
>>> +                int: entry address of ELF file
>>> +        """
>>> +        return None
>>
>> Does it really make sense to have this function available to all Entry
>> objects?
> 
> Yes we must define functions in the base class to avoid confusion.
> Also it does actually get called from the FIT implementation, to see
> if this function can provide the segments...failing that it tries to
> parse an ELF blob.
> 
> [..]
> 
>>> +    @staticmethod
>>> +    def is_optee_bin(data):
>>
>> Here you are checking it's a binary with v1 header, so please explicit
>> in the function name. (there's already a v2 header available FWIW).
> 
> OMG
> 
>>
>>> +        return len(data) >= 8 and data[0:5] == b'OPTE\x01'
>>> +
>>> +    def ObtainContents(self, fake_size=0):
>>> +        super().ObtainContents(fake_size)
>>
>> Do not silence the return code of the parent class here? I know it's
>> only returning True ATM but nothing guarantees it'll stay this way.
>>
>>> +        if not self.missing:
>>> +            if elf.is_valid(self.data):
>>> +                self.mark_absent('uses Elf format which must be in a FIT')
>>> +            elif self.is_optee_bin(self.data):
>>> +                self.mark_absent('uses v1 format which must be in a FIT')
>>
>> What should this support then if neither ELF not binary with v1 header
>> are supported? I don't see support for binary with v2 header anywhere so
>> I'm quite confused by what this piece of code is supposed to handle?
>>
>> I'm also very much against displaying a warning if the user has TEE set
>> in their environment and the file exists but it won't be used in the
>> final image. If it's not compatible based on the binman DT node, error
>> out. If it's the wrong file or it's missing, error out. Is there some
>> scenario where displaying a warning (and/or removing the entry with
>> mark_absent like you did here) make sense?
> 
> We need to deal with this later, sorry. I have come to the end of the
> time I can bear to spend dealing with the strangeness of OP-TEE. If
> you are able to tidy this up after it lands, or have ideas on how to
> do better, please let me know.

There is nothing strange in OP-TEE. There is a tee.bin file, it needs to
be loaded into memory at a specific address that you can find by reading
a header (yes those things exist in OS binaries, which are not all pure
ELF files). As shown in make_atf_fit.py, it takes only a couple of lines
of Python to get this address.

Since you are calling OP-TEE strange let me say I don't understand a thing
about all the U-Boot specific tooling that you are putting in place (this
whole binman thing in particular), so as a newbie in this project I should
probably be allowed to call that weird, too ;-) But that's not the point.

The point is, with the current patch set I can't build a working FIT image
for RockPi4 that includes OP-TEE. Note I have not tried v9 but I see nothing
significant changed regarding the handling of tee.bin (please correct me
if I'm wrong). Therefore merging this patch set in its current state would
clearly be a regression and prevent us from upgrading U-Boot in the
projects I'm working on...

>> In any case, thanks Simon and Jerome for looking into this, it's a
>> bigger task than I had anticipated but am looking forward to this
>> Rockchip-specific behavior to be dropped from mainline :)
> 
> Thanks. This has been beyond painful. We have to stop all these
> scripts and strange workflows...it is making firmware impossible to
> understand.

Refactoring is certainly good from time to time. But you have to make sure
the feature set is the same, and ideally the usage is unchanged (or only
marginally). Otherwise you're transferring the pain to your users...

Thanks,
-- 
Jerome

> 
> Regards,
> Simon


More information about the U-Boot mailing list