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.
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
-
structbloblist_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
magicBLOBLIST_MAGIC
chksumchecksum 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
versionBLOBLIST_VERSION
hdr_sizeSize of this header, normally sizeof(struct bloblist_hdr). The first bloblist_rec starts at this offset from the start of the header
align_log2Power of two of the maximum alignment required by this list
used_sizeSize 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_sizeThe 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.
flagsSpace for BLOBLISTF... flags (none yet)
spareSpare 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.
-
structbloblist_rec
record for the bloblist
Definition
struct bloblist_rec {
u32 tag_and_hdr_size;
u32 size;
};
Members
tag_and_hdr_sizeTag 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
sizeSize 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(ulongaddr)
return a bloblist if the magic matches
Parameters
ulong addrAddress to check
Return
pointer to bloblist, if the magic matches, else NULL
-
void*bloblist_get_blob(uinttag, int*sizep)
Find a blob and get the size of it
Parameters
uint tagTag to search for (enum bloblist_tag_t)
int *sizepSize of the blob found
Description
Searches the bloblist and returns the blob with the matching tag
Return
pointer to bloblist if found, or NULL if not found
-
void*bloblist_find(uinttag, intsize)
Find a blob
Parameters
uint tagTag to search for (enum bloblist_tag_t)
int sizeExpected 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(uinttag, intsize, intalign_log2)
Add a new blob
Parameters
uint tagTag to add (enum bloblist_tag_t)
int sizeSize of the blob
int align_log2Alignment 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
-
intbloblist_ensure_size(uinttag, intsize, intalign_log2, void**blobp)
Find or add a blob
Parameters
uint tagTag to add (enum bloblist_tag_t)
int sizeSize of the blob
int align_log2Alignment of the blob (in bytes log2), 0 for default
void **blobpReturns 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(uinttag, intsize)
Find or add a blob
Parameters
uint tagTag to add (enum bloblist_tag_t)
int sizeSize 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
-
intbloblist_ensure_size_ret(uinttag, int*sizep, void**blobp)
Find or add a blob
Parameters
uint tagTag to add (enum bloblist_tag_t)
int *sizepSize of the blob to create; returns size of actual blob
void **blobpReturns 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
-
intbloblist_resize(uinttag, intnew_size)
resize a blob
Parameters
uint tagTag to add (enum bloblist_tag_t)
int new_sizeNew 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
-
intbloblist_new(ulongaddr, uintsize, uintflags, uintalign_log2)
Create a new, empty bloblist of a given size
Parameters
ulong addrAddress of bloblist
uint sizeInitial size for bloblist
uint flagsFlags to use for bloblist
uint align_log2Log 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
-
intbloblist_check(ulongaddr, uintsize)
Check if a bloblist exists
Parameters
ulong addrAddress of bloblist
uint sizeReserved 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
-
intbloblist_finish(void)
Set up the bloblist for the next U-Boot part
Parameters
voidno 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
-
voidbloblist_get_stats(ulong*basep, ulong*tsizep, ulong*usizep)
Get information about the bloblist
Parameters
ulong *basepReturns base address of bloblist
ulong *tsizepReturns the total number of bytes of the bloblist
ulong *usizepReturns the number of used bytes of the bloblist
Description
This returns useful information about the bloblist
-
ulongbloblist_get_base(void)
Get the base address of the bloblist
Parameters
voidno arguments
Return
base address of bloblist
-
ulongbloblist_get_size(void)
Get the size of the bloblist
Parameters
voidno arguments
Return
the size in bytes
-
ulongbloblist_get_total_size(void)
Get the total size of the bloblist
Parameters
voidno arguments
Return
the size in bytes
-
voidbloblist_show_stats(void)
Show information about the bloblist
Parameters
voidno arguments
Description
This shows useful information about the bloblist on the console
-
voidbloblist_show_list(void)
Show a list of blobs in the bloblist
Parameters
voidno arguments
Description
This shows a list of blobs, showing their address, size and tag.
-
constchar*bloblist_tag_name(enumbloblist_tag_ttag)
Get the name for a tag
Parameters
enum bloblist_tag_t tagTag to check
Return
name of tag, or "invalid" if an invalid tag is provided
-
intbloblist_reloc(void*to, uintto_size)
Relocate the bloblist and optionally resize it
Parameters
void *toPointer to new bloblist location (must not overlap old location)
uint to_sizeNew size for bloblist
Return
- 0 if OK, -ENOSPC if the new size is small than the bloblist total
size.
-
intbloblist_init(void)
Init the bloblist system with a single bloblist
Parameters
voidno 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_MANDATORY is selected, bloblist in the incoming standard passage is mandatorily required.
Sets GD_FLG_BLOBLIST_READY in global_data flags on success
Return
0 if OK, -ve on error
-
intbloblist_maybe_init(void)
Init the bloblist system if not already done
Parameters
voidno arguments
Description
Calls bloblist_init() if the GD_FLG_BLOBLIST_READY flag is not set
Return
0 if OK, -ve on error
-
intbloblist_check_reg_conv(ulongrfdt, ulongrzero, ulongrsig, ulongxlist)
Check whether the bloblist is compliant to the register conventions according to the Firmware Handoff spec.
Parameters
ulong rfdtRegister that holds the FDT base address.
ulong rzeroRegister that must be zero.
ulong rsigRegister that holds signature and register conventions version.
ulong xlistRegister that holds the transfer list.
Return
- 0 if OK, -EIO if the bloblist is not compliant to the register
conventions.
-
intxferlist_from_boot_arg(ulong*addr)
Get bloblist from the boot args.
Parameters
ulong *addrAddress of the bloblist
Return
0 if OK, else on error
Simon Glass sjg@chromium.org 12-Aug-2018