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
-
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