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.

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;
  u32 version;
  u32 hdr_size;
  u32 flags;
  u32 size;
  u32 alloced;
  u32 spare;
  u32 chksum;
};

Members

magic

BLOBLIST_MAGIC

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

flags

Space for BLOBLISTF… flags (none yet)

size

Total size of the bloblist (non-zero if valid) including this header. The bloblist extends for this many bytes from the start of this header. When adding new records, the bloblist can grow up to this size.

alloced

Total 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

spare

Spare space (for future use)

chksum

CRC32 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 finalised before jumping to the next stage of boot. Note that chksum is last to make it easier to exclude it from the checksum calculation.

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;
  u32 hdr_size;
  u32 size;
  u32 spare;
};

Members

tag

Tag indicating what the record contains

hdr_size

Size of this header, 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).

spare

Spare space for other things

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)

Add a new blob

Parameters

uint tag

Tag to add (enum bloblist_tag_t)

int size

Size of the blob

int align

Alignment of the blob (in bytes), 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, 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

Alignment of the blob (in bytes), 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)

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

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

Expected size of blobsize, or 0 to detect the size

Return

0 if OK, -ENOENT if the magic number doesn’t match (indicating that there problem is no bloblist at the given address), -EPROTONOSUPPORT if the version does not match, -EIO if the checksum does not match, -EFBIG if the expected size does not match the detected size, -ENOSPC if the size is not large enough to hold the headers

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 *sizep, ulong *allocedp)

Get information about the bloblist

Parameters

ulong *basep

Returns base address of bloblist

ulong *sizep

Returns the number of bytes used in the bloblist

ulong *allocedp

Returns the total space allocated to 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

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

void bloblist_reloc(void *to, uint to_size, void *from, uint from_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 (must be larger than from_size)

void *from

Pointer to bloblist to relocate

uint from_size

Size of bloblist to relocate

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.

Return

0 if OK, -ve on error

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