Dear all,

we have discussed that a protocol is needed to fix-up device trees
loaded by GRUB or other boot managers.

In the U-Boot code we have actually the following actions for
device-trees:

* load the device-tree to memory
* copy the device-tree to an allocated memory region which
  has 12 KiB free space for device-tree fix-ups
* do the actual fix-ups, i.e. add new nodes or change properties
* reserve memory according to the /reserved-memory node and the
  memory reservation block as EfiBootServicesData or as
  EfiReservedMemoryType for no-map regions
* install the device-tree as configuration table

So I think the usage of a DT fix-up protocol could take the following steps:

* GRUB loads the device-tree allocating sufficient memory for fix-ups
* GRUB calls the protocol a fist time to add extra nodes and properties
* GRUB applies its own device-tree fix-ups
* GRUB calls the protocol a second time which
  - reserves memory according to the /reserved-memory node
  - installs the device-tree as configuration table

One could join both service calls if GRUB applies its own fix-ups first.
But maybe GRUB wants to analyze U-Boot's fix-ups before committing its
own ones.

So lets define a bit-field to pass to the fix-up protocol:

/* Add nodes and update properties */
#define EFI_DT_APPLY_FIXUPS    0x00000001
/*
 * Reserve memory according to the /reserved-memory node
 * and the memory reservation block
 */
#define EFI_DT_RESERVE_MEMORY  0x00000002
/* Install the device-tree as configuration table */
#define EFI_DT_INSTALL_TABLE   0x00000004

Here is the rest of the proposed protocol definition:

#define EFI_DT_FIXUP_PROTOCOL_GUID \
 { 0xe617d64c, 0xfe08, 0x46da, \
 { 0xf4, 0xdc, 0xbb, 0xd5, 0x87, 0x0c, 0x73, 0x00 } }

typedef struct _EFI_DT_FIXUP_PROTOCOL {
EFI_DT_FIXUP fixup;
} EFI_DT_FIXUP_PROTOCOL;

typedef EFI_STATUS
(EFIAPI *EFI_DT_FIXUP) (
    IN EFI_DT_FIXUP_PROTOCOL *This,
    IN VOID                  *Fdt,
    IN OUT UINTN             *BufferSize,
    IN UINT32                Flags,
    );

This:       Pointer to the protocol
Fdt:        Buffer with the device-tree. This shall be memory
            of type EfiACPIReclaimMemory if Flags contains
            EFI_DT_INSTALL_TABLE.
BufferSize: Pointer to the size of the buffer including
            trailing unused bytes for fix-ups.
            If the buffer size is too small,
            the required buffer size is returned.
Flags:      Bitmap containing at least one of the values
            EFI_DT_APPLY_FIXUPS, EFI_DT_RESERVE_MEMORY,
            EFI_DT_INSTALL_TABLE. Indicates the actions
            to be applied to the device-tree.

The selected actions indicated in Flags are applied in the
sequence:

* Add nodes and update properties.
* Reserve memory according to the /reserved-memory node
  and the memory reservation block
* Install the device-tree as configuration table

Memory is reserved as EfiBootServicesData if the reservation does not
carry the no-map property and as EfiReservedMemoryType if it is marked
as no-map.

If *BufferSize exceeds the value of the totalsize field header of
device-tree header upon entry to the service, the totalsize field is set
to *BufferSize.

Return values:

EFI_INVALID_PARAMETER - This is NULL or does not point to a valid
                        EFI_DT_FIXUP_PROTOCOL implementation.
EFI_INVALID_PARAMETER - Fdt or BufferSize is NULL
EFI_INVALID_PARAMETER - *Fdt is not a valid device-tree
                        (e.g. incorrect value of magic)
EFI_INVALID_PARAMETER - Invalid value of Flags (zero or unknown bit)
EFI_BUFFER_TOO_SMALL  - The buffer is too small to apply the fix-ups.
EFI_SUCCESS           - All steps succeeded

If EFI_BUFFER_TOO_SMALL is returned, the device-tree is unmodified
and *BufferSize is updated with the required buffer size for the
provided device-tree.

The required buffer size when called with EFI_DT_APPLY_FIXUPS should
enforce at least 4 KiB unused space for additional fix-ups by the
operating system or the caller. The available space in the device-tree
shall be determined using the device-tree header fields:

    Available = header->totalsize
              - header->off_dt_strings
              - header->size_dt_strings;

(The strings block is always last in the flattened device-tree. There
might be more space between blocks but not all device-tree libraries can
use it.)

The required buffer size when called without EFI_DT_APPLY_FIXUPS shall
be the value of the totalsize field of the flattened device tree header.

If any other error code is returned, the state of the device-tree is
undefined. The caller should discard the buffer content.

The extent to which the validity of the device-tree is checked is
implementation dependent. But a buffer without the correct value of the
magic field of the flattened device tree header should always be rejected.

The protocol implementation is not required to check if the device-tree
is in memory of type EfiACPIReclaimMemory.

Looking forward to your feedback.

Best regards

Heinrich
_______________________________________________
boot-architecture mailing list
boot-architecture@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/boot-architecture

Reply via email to