diff --git a/source/transfer_list.rst b/source/transfer_list.rst index 55be5f9..63a1ad8 100644 --- a/source/transfer_list.rst +++ b/source/transfer_list.rst @@ -292,6 +292,11 @@ This section describes the valid operations that may be performed on a TL in more detail, in order to clarify how to use the various fields and to serve as a guideline for implementation. +.. note:: +This section assumes te.hdr_size is 0x8 for all TE entries. This is used consistently throughout the examples. +In the future, if entries with different header sizes are introduced, some operations may need to explicitly +take te.hdr_size as an argument. + Validating a TL header ^^^^^^^^^^^^^^^^^^^^^^ @@ -338,8 +343,7 @@ Inputs: is smaller or equal to `tl.used_size`, otherwise abort (the TL is corrupted). #. If `te.tag_id` (`te_base_addr + 0x0`) is a known tag, interpret the data - at `te_base_addr + te.hdr_size` accordingly. (Do not hardcode the value - for `te.hdr_size`, even for known tags!) Otherwise, ignore the tag and + at `te_base_addr + te.hdr_size` accordingly. Otherwise, ignore the tag and proceed with the next step. #. Add `align8(te.hdr_size + te.data_size)` to `te_base_addr`. @@ -362,14 +366,14 @@ Inputs: #. Use the `te_base_addr` of this tag for the rest of the operation. - #. If `has_checksum`, Subtract the sum of `align8(new_data_size + 0x8)` bytes + #. If `has_checksum`, Subtract the sum of `align8(new_data_size + te.hdr_size)` bytes starting at `te_base_addr` from `tl.checksum`. #. Skip the next step (step 2) with all its substeps. #. Calculate `te_base_addr` as `tl_base_addr + tl.used_size`. - #. If `tl.total_size - tl.used_size` is smaller than `align8(new_data_size + 0x8)`, + #. If `tl.total_size - tl.used_size` is smaller than `align8(new_data_size + te.hdr_size)`, abort (not enough room to add TE). #. If `has_checksum`, subtract the sum of the 4 bytes from @@ -386,29 +390,69 @@ Inputs: #. Set `te.data_size` (`te_base_addr + 0x4`) to `new_data_size`. -#. Copy or generate the TE data into `te_base_addr + 0x8`. +#. Copy or generate the TE data into `te_base_addr + te.hdr_size`. -#. If `has_checksum`, add the sum of `align8(new_data_size + 0x8)` bytes +#. If `has_checksum`, add the sum of `align8(new_data_size + te.hdr_size)` bytes starting at `te_base_addr` to `tl.checksum`. #. If an existing XFERLIST_VOID TE was chosen to be overwritten in step 1, and - `old_void_data_size - new_data_size` is greater or equal to `0x8`: + `old_void_data_size - new_data_size` is greater than or equal to `te.hdr_size`, then + create a new void TE to fill the remaining space by calling `Adding a void TE`_ + with the following arguments: + + #. `void_te.base_addr` = `te_base_addr + align8(new_data_size + te.hdr_size)` + + #. `void_te.data_size` = `old_void_data_size - align8(new_data_size + te.hdr_size)` + +Removing a TE +^^^^^^^^^^^^^ + +Inputs: + +- `te_base_addr`: Base address of the TE to be removed + +#. Invoke `Adding a void TE`_ with following arguments + + #. `void_te.base_addr` = `te_base_addr` + + #. `void_te.size` = `te.data_size` + +#. *(Optional)* Implementations may perform memory management by inspecting adjacent entries + and coalescing consecutive `XFERLIST_VOID` entries into a single larger one. This can help + reduce fragmentation and improve reuse of space in the Transfer List. + +Overwriting a TE +^^^^^^^^^^^^^^^^ + +Inputs: + +- `te_base_addr`: Base address of the Transfer Entry (TE) to be overwritten +- `new_data_size`: Size in bytes of the new data to be encapsulated in the TE +- [data]: Data to be copied into the TE + +#. If `te.data_size` is smaller than `new_data_size`, the overwrite operation must return an error. + The caller is then responsible for: - #. Use `te_base_addr + align8(new_data_size + 0x8)` as the new `te_base_addr` - for a new XFERLIST_VOID tag. + #. Reclaiming the existing space by calling `Adding a void TE`_ with `te_base_addr` and `te.data_size`. - #. If `has_checksum`, subtract the sum of the 8 bytes from `te_base_addr` to - `te_base_addr + 0x8` from `tl.checksum`. + #. Adding a new TE by invoking `Adding a new TE`_ with appropriate arguments. - #. Set `te.tag_id` (`te_base_addr + 0x0`) to `0x0` (XFERLIST_VOID). +#. If `has_checksum`, subtract the sum of `te.data_size` bytes starting at + `te_base_addr + te.hdr_size` from `tl.checksum`. - #. Set `te.hdr_size` (`te_base_addr + 0x3`) to `0x8`. +#. Set `te.data_size` (`te_base_addr + 0x4`) to `align8(new_data_size)`. - #. Set `te.data_size` (`te_base_addr + 0x4`) to - `old_void_data_size - align8(new_data_size) - 0x8`. +#. Copy or generate the new TE data into `te_base_addr + te.hdr_size`. - #. If `has_checksum`, add the sum of the 8 bytes from `te_base_addr` to - `te_base_addr + 0x8` to `tl.checksum`. +#. If `has_checksum`, add the sum of `align8(new_data_size)` bytes starting at + `te_base_addr + te.hdr_size` to `tl.checksum`. + +#. If `te.data_size - align8(new_data_size)` is greater than or equal to `te.hdr_size`, create a new + void TE to fill the remaining space by calling `Adding a void TE`_ with the following arguments: + + #. `te_base_addr` = `te_base_addr + align8(new_data_size + te.hdr_size)` + + #. `data_size` = `te.data_size - align8(new_data_size - te.hdr_size)` Adding a new TE with special data alignment requirement ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -507,6 +551,35 @@ Inputs: #. If `has_checksum`, add the sum of the 4 bytes from `new_tl_base + 0xc` to `new_tl_base + 0x10` to `tl.checksum` (`new_tl_base + 0x4`). +.. note:: + After relocating a TL, implementations should consider scrubbing the old TL memory if it contains + any secrets that might be accessible to later untrusted software. + +Helper Routines +^^^^^^^^^^^^^^^ + +Adding a void TE +~~~~~~~~~~~~~~~~ + +Inputs: + +- `te_base_addr`: Base address where void TE to be added +- `data_size`: Size in bytes of the data to be encapsulated in void TE + +#. If `has_checksum`, subtract the sum of `te.hdr_size + data_size` bytes starting at + `te_base_addr` from `tl.checksum`. + +#. Set `te.tag_id` (`te_base_addr + 0x0`) to `0x0` (XFERLIST_VOID) + +#. Set `te.hdr_size` (`te_base_addr + 0x3`) to `0x8` + +#. Set `te.data_size` (`te_base_addr + 0x4`) to `align8(data_size)` + +#. *(optional)* Set the `data_size` bytes starting at `te_base_addr + te.hdr_size` to 0x0 + +#. If `has_checksum`, add the sum of `te.hdr_size + data_size` bytes starting at + `te_base_addr` with `tl.checksum` + .. _sec_std_entries: