Blob Lists - bloblist

Introduction

A bloblist provides a way to store collections of binary information (blobs) in a central structure. Each record of information is assigned a tag so that its owner can find it and update it. Each record is generally described by a C structure defined by the code that owns it.

For the design goals of bloblist, please see the comments at the top of the bloblist.h header file.

Bloblist is an implementation with the Firmware Handoff protocol.

Passing state through the boot process

The bloblist is created when the first U-Boot component runs (often SPL, sometimes TPL). It is passed through to each successive part of the boot and can be accessed as needed. This provides a way to transfer state from one part to the next. For example, TPL may determine that a watchdog reset occurred by reading an SoC register. Reading the register may reset the value, so that it cannot be read a second time. So TPL can store that in a bloblist record which can be passed through to SPL and U-Boot proper, which can print a message indicating that something went wrong and the watchdog fired.

Blobs

While each blob in the bloblist can be of any length, bloblists are designed to hold small amounts of data, typically a few KB at most. It is not possible to change the length of a blob once it has been written. Each blob is normally created from a C structure which can be used to access its fields.

Blob tags

Each blob has a tag which is a 32-bit number. This uniquely identifies the owner of the blob. Blob tags are listed in enum blob_tag_t and are named with a BLOBT_ prefix.

Single structure

There is normally only one bloblist in U-Boot. Since a bloblist can store multiple blobs it does not seem useful to allow multiple bloblists. Of course there could be reasons for this, such as needing to spread the blobs around in different memory areas due to fragmented memory, but it is simpler to just have a single bloblist.

API

Bloblist provides a fairly simple API which allows blobs to be created and found. All access is via the blob’s tag. Blob records are zeroed when added.

Placing the bloblist

The bloblist is typically positioned at a fixed address by TPL, or SPL. This is controlled by CONFIG_BLOBLIST_ADDR. But in some cases it is preferable to allocate the bloblist in the malloc() space. Use the CONFIG_BLOBLIST_ALLOC option to enable this.

The bloblist is automatically relocated as part of U-Boot relocation. Sometimes it is useful to expand the bloblist in U-Boot proper, since it may want to add information for use by Linux. Note that this does not mean that Linux needs to know anything about the bloblist format, just that it is convenient to use bloblist to place things contiguously in memory. Set CONFIG_BLOBLIST_SIZE_RELOC to define the expanded size, if needed.

Finishing the bloblist

When a part of U-Boot is about to jump to the next part, it can ‘finish’ the bloblist in preparation for the next stage. This involves adding a checksum so that the next stage can make sure that the data arrived safely. While the bloblist is in use, changes can be made which will affect the checksum, so it is easier to calculate the checksum at the end after all changes are made.

Future work

Bootstage has a mechanism to ‘stash’ its records for passing to the next part. This should move to using bloblist, to avoid having its own mechanism for passing information between U-Boot parts.

API documentation

struct bloblist_hdr

header for the bloblist

Definition

struct bloblist_hdr {
  u32 magic;
  u8 chksum;
  u8 version;
  u8 hdr_size;
  u8 align_log2;
  u32 used_size;
  u32 total_size;
  u32 flags;
  u32 spare;
};

Members

magic

BLOBLIST_MAGIC

chksum

checksum for the entire bloblist allocated area. Since any of the blobs can be altered after being created, this checksum is only valid when the bloblist is finalized before jumping to the next stage of boot. This is the value needed to make all checksummed bytes sum to 0

version

BLOBLIST_VERSION

hdr_size

Size of this header, normally sizeof(struct bloblist_hdr). The first bloblist_rec starts at this offset from the start of the header

align_log2

Power of two of the maximum alignment required by this list

used_size

Size allocated so far for this bloblist. This starts out as sizeof(bloblist_hdr) since we need at least that much space to store a valid bloblist

total_size

The number of total bytes that the bloblist can occupy. Any blob producer must check if there is sufficient space before adding a record to the bloblist.

flags

Space for BLOBLISTF… flags (none yet)

spare

Spare space (for future use)

Description

This is stored at the start of the bloblist which is always on a 16-byte boundary. Records follow this header. The bloblist normally stays in the same place in memory as SPL and U-Boot execute, but it can be safely moved around.

None of the bloblist headers themselves contain pointers but it is possible to put pointers inside a bloblist record if desired. This is not encouraged, since it can make part of the bloblist inaccessible if the pointer is no-longer valid. It is better to just store all the data inside a bloblist record.

Each bloblist record is aligned to a 16-byte boundary and follows immediately from the last.

struct bloblist_rec

record for the bloblist

Definition

struct bloblist_rec {
  u32 tag_and_hdr_size;
  u32 size;
};

Members

tag_and_hdr_size

Tag indicating what the record contains (bottom 24 bits), and size of this header (top 8 bits), normally sizeof(struct bloblist_rec). The record’s data starts at this offset from the start of the record

size

Size of record in bytes, excluding the header size. This does not need to be aligned (e.g. 3 is OK).

Description

The bloblist contains a number of records each consisting of this record structure followed by the data contained. Each records is 16-byte aligned.

NOTE

Only exported for testing purposes. Do not use this struct.

void *bloblist_check_magic(ulong addr)

return a bloblist if the magic matches

Parameters

ulong addr

Address to check

Return

pointer to bloblist, if the magic matches, else NULL

void *bloblist_find(uint tag, int size)

Find a blob

Parameters

uint tag

Tag to search for (enum bloblist_tag_t)

int size

Expected size of the blob, or 0 for any size

Description

Searches the bloblist and returns the blob with the matching tag

Return

pointer to blob if found, or NULL if not found, or a blob was found but it is the wrong size

void *bloblist_add(uint tag, int size, int align_log2)

Add a new blob

Parameters

uint tag

Tag to add (enum bloblist_tag_t)

int size

Size of the blob

int align_log2

Alignment of the blob (in bytes log2), 0 for default

Description

Add a new blob to the bloblist

This should only be called if you konw there is no existing blob for a particular tag. It is typically safe to call in the first phase of U-Boot (e.g. TPL or SPL). After that, bloblist_ensure() should be used instead.

Return

pointer to the newly added block, or NULL if there is not enough space for the blob

int bloblist_ensure_size(uint tag, int size, int align_log2, void **blobp)

Find or add a blob

Parameters

uint tag

Tag to add (enum bloblist_tag_t)

int size

Size of the blob

int align_log2

Alignment of the blob (in bytes log2), 0 for default

void **blobp

Returns a pointer to blob on success

Description

Find an existing blob, or add a new one if not found

Return

0 if OK, -ENOSPC if it is missing and could not be added due to lack of space, or -ESPIPE it exists but has the wrong size

void *bloblist_ensure(uint tag, int size)

Find or add a blob

Parameters

uint tag

Tag to add (enum bloblist_tag_t)

int size

Size of the blob

Description

Find an existing blob, or add a new one if not found

Return

pointer to blob, or NULL if it is missing and could not be added due to lack of space, or it exists but has the wrong size

int bloblist_ensure_size_ret(uint tag, int *sizep, void **blobp)

Find or add a blob

Parameters

uint tag

Tag to add (enum bloblist_tag_t)

int *sizep

Size of the blob to create; returns size of actual blob

void **blobp

Returns a pointer to blob on success

Description

Find an existing blob, or add a new one if not found

Return

0 if OK, -ENOSPC if it is missing and could not be added due to lack of space

int bloblist_resize(uint tag, int new_size)

resize a blob

Parameters

uint tag

Tag to add (enum bloblist_tag_t)

int new_size

New size of the blob (>0 to expand, <0 to contract)

Description

Any blobs above this one are relocated up or down. The resized blob remains in the same place.

Return

0 if OK, -ENOSPC if the bloblist does not have enough space, -ENOENT if the tag is not found

int bloblist_new(ulong addr, uint size, uint flags, uint align_log2)

Create a new, empty bloblist of a given size

Parameters

ulong addr

Address of bloblist

uint size

Initial size for bloblist

uint flags

Flags to use for bloblist

uint align_log2

Log base 2 of maximum alignment provided by this bloblist

Return

0 if OK, -EFAULT if addr is not aligned correctly, -ENOSPC is the area is not large enough

int bloblist_check(ulong addr, uint size)

Check if a bloblist exists

Parameters

ulong addr

Address of bloblist

uint size

Reserved space size for blobsize, or 0 to use the total size

Return

0 if OK, -ENOENT if the magic number doesn’t match (indicating that there problem is no bloblist at the given address) or any fields for header size, used size and total size do not match, -EPROTONOSUPPORT if the version does not match, -EIO if the checksum does not match, -EFBIG if the reserved space size is small than the total size or total size is 0

int bloblist_finish(void)

Set up the bloblist for the next U-Boot part

Parameters

void

no arguments

Description

This sets the correct checksum for the bloblist. This ensures that the bloblist will be detected correctly by the next phase of U-Boot.

Return

0

void bloblist_get_stats(ulong *basep, ulong *tsizep, ulong *usizep)

Get information about the bloblist

Parameters

ulong *basep

Returns base address of bloblist

ulong *tsizep

Returns the total number of bytes of the bloblist

ulong *usizep

Returns the number of used bytes of the bloblist

Description

This returns useful information about the bloblist

ulong bloblist_get_base(void)

Get the base address of the bloblist

Parameters

void

no arguments

Return

base address of bloblist

ulong bloblist_get_size(void)

Get the size of the bloblist

Parameters

void

no arguments

Return

the size in bytes

ulong bloblist_get_total_size(void)

Get the total size of the bloblist

Parameters

void

no arguments

Return

the size in bytes

void bloblist_show_stats(void)

Show information about the bloblist

Parameters

void

no arguments

Description

This shows useful information about the bloblist on the console

void bloblist_show_list(void)

Show a list of blobs in the bloblist

Parameters

void

no arguments

Description

This shows a list of blobs, showing their address, size and tag.

const char *bloblist_tag_name(enum bloblist_tag_t tag)

Get the name for a tag

Parameters

enum bloblist_tag_t tag

Tag to check

Return

name of tag, or “invalid” if an invalid tag is provided

int bloblist_reloc(void *to, uint to_size)

Relocate the bloblist and optionally resize it

Parameters

void *to

Pointer to new bloblist location (must not overlap old location)

uint to_size

New size for bloblist

Return

0 if OK, -ENOSPC if the new size is small than the bloblist total

size.

int bloblist_init(void)

Init the bloblist system with a single bloblist

Parameters

void

no arguments

Description

This locates and sets up the blocklist for use.

If CONFIG_BLOBLIST_FIXED is selected, it uses CONFIG_BLOBLIST_ADDR and CONFIG_BLOBLIST_SIZE to set up a bloblist for use by U-Boot.

If CONFIG_BLOBLIST_ALLOC is selected, it allocates memory for a bloblist of size CONFIG_BLOBLIST_SIZE.

If CONFIG_BLOBLIST_PASSAGE is selected, it uses the bloblist in the incoming standard passage. The size is detected automatically so CONFIG_BLOBLIST_SIZE can be 0.

Sets GD_FLG_BLOBLIST_READY in global_data flags on success

Return

0 if OK, -ve on error

int bloblist_maybe_init(void)

Init the bloblist system if not already done

Parameters

void

no arguments

Description

Calls bloblist_init() if the GD_FLG_BLOBLIST_READY flag is not et

Return

0 if OK, -ve on error

int bloblist_check_reg_conv(ulong rfdt, ulong rzero, ulong rsig)

Check whether the bloblist is compliant to the register conventions according to the Firmware Handoff spec.

Parameters

ulong rfdt

Register that holds the FDT base address.

ulong rzero

Register that must be zero.

ulong rsig

Register that holds signature and register conventions version.

Return

0 if OK, -EIO if the bloblist is not compliant to the register

conventions.

int xferlist_from_boot_arg(ulong addr, ulong size)

Get bloblist from the boot args and relocate it to the specified address.

Parameters

ulong addr

Address for the bloblist

ulong size

Size of space reserved for the bloblist

Return

0 if OK, else on error

Simon Glass sjg@chromium.org 12-Aug-2018