support propagating supernode properties with bootph schema

align bloblist with v0.9 of Firmware Handoff spec
 -----BEGIN PGP SIGNATURE-----
 
 iQFFBAABCgAvFiEEslwAIq+Gp8wWVbYnfxc6PpAIreYFAmWS9jwRHHNqZ0BjaHJv
 bWl1bS5vcmcACgkQfxc6PpAIreZvYggAnc11fzAPnWZK5Nz7RxqoT1vMl/xAaSMJ
 gKaL8V0vAY7I0s3+jMoEfed29OAIkxs68nfEV0Hu4RKc2ER6gIYjun5VOP8G6B9j
 B1S/IbWgMtz+Vn/TQNy72zbWcU/FeypU2ZICAEN7v1hksjZoM7jbytLa/OkPjSA1
 ONEIZTwYL+pXFSneAcXU1cugQX2RO+L5gYNlZF8yv6Jb5DQj0noOvhbvW1s9XvF3
 VognW1UVDmBr0KPaJVufMm0YGaurwsjeb7SaKzgk/9CUY+j6AqpfqqBaK6+KoPku
 MOjyc7shsxmJsBiLVflzSVE7WAvlTcRN6hLzoJd/4JVs+/fazz9P1A==
 =b5aT
 -----END PGP SIGNATURE-----

Merge tag 'dm-next-1124' of https://source.denx.de/u-boot/custodians/u-boot-dm into next

support propagating supernode properties with bootph schema
align bloblist with v0.9 of Firmware Handoff spec
This commit is contained in:
Tom Rini 2024-01-01 12:38:15 -05:00
commit dffa6d0210
11 changed files with 401 additions and 248 deletions

View File

@ -369,12 +369,14 @@
rw-mrc-cache { rw-mrc-cache {
label = "rw-mrc-cache"; label = "rw-mrc-cache";
reg = <0x008e0000 0x00010000>; reg = <0x008e0000 0x00010000>;
bootph-all; bootph-some-ram;
bootph-pre-ram;
}; };
rw-var-mrc-cache { rw-var-mrc-cache {
label = "rw-mrc-cache"; label = "rw-mrc-cache";
reg = <0x008f0000 0x0001000>; reg = <0x008f0000 0x0001000>;
bootph-all; bootph-some-ram;
bootph-pre-ram;
}; };
}; };
}; };

View File

@ -16,6 +16,7 @@
#include <asm/mpspec.h> #include <asm/mpspec.h>
#include <asm/tables.h> #include <asm/tables.h>
#include <asm/coreboot_tables.h> #include <asm/coreboot_tables.h>
#include <linux/log2.h>
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
@ -104,7 +105,7 @@ int write_tables(void)
if (!gd->arch.table_end) if (!gd->arch.table_end)
gd->arch.table_end = rom_addr; gd->arch.table_end = rom_addr;
rom_addr = (ulong)bloblist_add(table->tag, size, rom_addr = (ulong)bloblist_add(table->tag, size,
table->align); ilog2(table->align));
if (!rom_addr) if (!rom_addr)
return log_msg_ret("bloblist", -ENOBUFS); return log_msg_ret("bloblist", -ENOBUFS);

View File

@ -13,6 +13,7 @@
#include <malloc.h> #include <malloc.h>
#include <mapmem.h> #include <mapmem.h>
#include <spl.h> #include <spl.h>
#include <tables_csum.h>
#include <asm/global_data.h> #include <asm/global_data.h>
#include <u-boot/crc.h> #include <u-boot/crc.h>
@ -26,8 +27,6 @@
* start address of the data in each blob is aligned as required. Note that * start address of the data in each blob is aligned as required. Note that
* each blob's *data* is aligned to BLOBLIST_ALIGN regardless of the alignment * each blob's *data* is aligned to BLOBLIST_ALIGN regardless of the alignment
* of the bloblist itself or the blob header. * of the bloblist itself or the blob header.
*
* So far, only BLOBLIST_ALIGN alignment is supported.
*/ */
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
@ -36,16 +35,26 @@ static struct tag_name {
enum bloblist_tag_t tag; enum bloblist_tag_t tag;
const char *name; const char *name;
} tag_name[] = { } tag_name[] = {
{ BLOBLISTT_NONE, "(none)" }, { BLOBLISTT_VOID, "(void)" },
/* BLOBLISTT_AREA_FIRMWARE_TOP */ /* BLOBLISTT_AREA_FIRMWARE_TOP */
{ BLOBLISTT_CONTROL_FDT, "Control FDT" },
{ BLOBLISTT_HOB_BLOCK, "HOB block" },
{ BLOBLISTT_HOB_LIST, "HOB list" },
{ BLOBLISTT_ACPI_TABLES, "ACPI tables for x86" },
{ BLOBLISTT_TPM_EVLOG, "TPM event log defined by TCG EFI" },
{ BLOBLISTT_TPM_CRB_BASE, "TPM Command Response Buffer address" },
/* BLOBLISTT_AREA_FIRMWARE */ /* BLOBLISTT_AREA_FIRMWARE */
{ BLOBLISTT_ACPI_GNVS, "ACPI GNVS" },
{ BLOBLISTT_INTEL_VBT, "Intel Video-BIOS table" },
{ BLOBLISTT_TPM2_TCG_LOG, "TPM v2 log space" }, { BLOBLISTT_TPM2_TCG_LOG, "TPM v2 log space" },
{ BLOBLISTT_TCPA_LOG, "TPM log space" }, { BLOBLISTT_TCPA_LOG, "TPM log space" },
{ BLOBLISTT_ACPI_TABLES, "ACPI tables for x86" }, { BLOBLISTT_ACPI_GNVS, "ACPI GNVS" },
/* BLOBLISTT_AREA_TF */
{ BLOBLISTT_OPTEE_PAGABLE_PART, "OP-TEE pagable part" },
/* BLOBLISTT_AREA_OTHER */
{ BLOBLISTT_INTEL_VBT, "Intel Video-BIOS table" },
{ BLOBLISTT_SMBIOS_TABLES, "SMBIOS tables for x86" }, { BLOBLISTT_SMBIOS_TABLES, "SMBIOS tables for x86" },
{ BLOBLISTT_VBOOT_CTX, "Chrome OS vboot context" }, { BLOBLISTT_VBOOT_CTX, "Chrome OS vboot context" },
@ -71,18 +80,36 @@ const char *bloblist_tag_name(enum bloblist_tag_t tag)
static struct bloblist_rec *bloblist_first_blob(struct bloblist_hdr *hdr) static struct bloblist_rec *bloblist_first_blob(struct bloblist_hdr *hdr)
{ {
if (hdr->alloced <= hdr->hdr_size) if (hdr->used_size <= hdr->hdr_size)
return NULL; return NULL;
return (struct bloblist_rec *)((void *)hdr + hdr->hdr_size); return (struct bloblist_rec *)((void *)hdr + hdr->hdr_size);
} }
static inline uint rec_hdr_size(struct bloblist_rec *rec)
{
return (rec->tag_and_hdr_size & BLOBLISTR_HDR_SIZE_MASK) >>
BLOBLISTR_HDR_SIZE_SHIFT;
}
static inline uint rec_tag(struct bloblist_rec *rec)
{
return (rec->tag_and_hdr_size & BLOBLISTR_TAG_MASK) >>
BLOBLISTR_TAG_SHIFT;
}
static ulong bloblist_blob_end_ofs(struct bloblist_hdr *hdr, static ulong bloblist_blob_end_ofs(struct bloblist_hdr *hdr,
struct bloblist_rec *rec) struct bloblist_rec *rec)
{ {
ulong offset; ulong offset;
offset = (void *)rec - (void *)hdr; offset = (void *)rec - (void *)hdr;
offset += rec->hdr_size + ALIGN(rec->size, BLOBLIST_ALIGN); /*
* The data section of next TE should start from an address aligned
* to 1 << hdr->align_log2.
*/
offset += rec_hdr_size(rec) + rec->size;
offset = round_up(offset + rec_hdr_size(rec), 1 << hdr->align_log2);
offset -= rec_hdr_size(rec);
return offset; return offset;
} }
@ -92,7 +119,7 @@ static struct bloblist_rec *bloblist_next_blob(struct bloblist_hdr *hdr,
{ {
ulong offset = bloblist_blob_end_ofs(hdr, rec); ulong offset = bloblist_blob_end_ofs(hdr, rec);
if (offset >= hdr->alloced) if (offset >= hdr->used_size)
return NULL; return NULL;
return (struct bloblist_rec *)((void *)hdr + offset); return (struct bloblist_rec *)((void *)hdr + offset);
} }
@ -111,55 +138,69 @@ static struct bloblist_rec *bloblist_findrec(uint tag)
return NULL; return NULL;
foreach_rec(rec, hdr) { foreach_rec(rec, hdr) {
if (rec->tag == tag) if (rec_tag(rec) == tag)
return rec; return rec;
} }
return NULL; return NULL;
} }
static int bloblist_addrec(uint tag, int size, int align, static int bloblist_addrec(uint tag, int size, int align_log2,
struct bloblist_rec **recp) struct bloblist_rec **recp)
{ {
struct bloblist_hdr *hdr = gd->bloblist; struct bloblist_hdr *hdr = gd->bloblist;
struct bloblist_rec *rec; struct bloblist_rec *rec;
int data_start, new_alloced; int data_start, aligned_start, new_alloced;
if (!align) if (!align_log2)
align = BLOBLIST_ALIGN; align_log2 = BLOBLIST_BLOB_ALIGN_LOG2;
/* Figure out where the new data will start */ /* Figure out where the new data will start */
data_start = map_to_sysmem(hdr) + hdr->alloced + sizeof(*rec); data_start = map_to_sysmem(hdr) + hdr->used_size + sizeof(*rec);
/* Align the address and then calculate the offset from ->alloced */ /* Align the address and then calculate the offset from used size */
data_start = ALIGN(data_start, align) - map_to_sysmem(hdr); aligned_start = ALIGN(data_start, 1U << align_log2) - data_start;
/* If we need to create a dummy record, create it */
if (aligned_start) {
int void_size = aligned_start - sizeof(*rec);
struct bloblist_rec *vrec;
int ret;
ret = bloblist_addrec(BLOBLISTT_VOID, void_size, 0, &vrec);
if (ret)
return log_msg_ret("void", ret);
/* start the record after that */
data_start = map_to_sysmem(hdr) + hdr->used_size + sizeof(*vrec);
}
/* Calculate the new allocated total */ /* Calculate the new allocated total */
new_alloced = data_start + ALIGN(size, align); new_alloced = data_start - map_to_sysmem(hdr) +
ALIGN(size, 1U << align_log2);
if (new_alloced > hdr->size) { if (new_alloced > hdr->total_size) {
log_err("Failed to allocate %x bytes size=%x, need size=%x\n", log_err("Failed to allocate %x bytes\n", size);
size, hdr->size, new_alloced); log_err("Used size=%x, total size=%x\n",
hdr->used_size, hdr->total_size);
return log_msg_ret("bloblist add", -ENOSPC); return log_msg_ret("bloblist add", -ENOSPC);
} }
rec = (void *)hdr + hdr->alloced; rec = (void *)hdr + hdr->used_size;
rec->tag = tag; rec->tag_and_hdr_size = tag | sizeof(*rec) << BLOBLISTR_HDR_SIZE_SHIFT;
rec->hdr_size = data_start - hdr->alloced;
rec->size = size; rec->size = size;
rec->spare = 0;
/* Zero the record data */ /* Zero the record data */
memset((void *)rec + rec->hdr_size, '\0', rec->size); memset((void *)rec + rec_hdr_size(rec), '\0', rec->size);
hdr->alloced = new_alloced; hdr->used_size = new_alloced;
*recp = rec; *recp = rec;
return 0; return 0;
} }
static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size, static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size,
int align) int align_log2)
{ {
struct bloblist_rec *rec; struct bloblist_rec *rec;
@ -172,7 +213,7 @@ static int bloblist_ensurerec(uint tag, struct bloblist_rec **recp, int size,
} else { } else {
int ret; int ret;
ret = bloblist_addrec(tag, size, align, &rec); ret = bloblist_addrec(tag, size, align_log2, &rec);
if (ret) if (ret)
return ret; return ret;
} }
@ -191,28 +232,28 @@ void *bloblist_find(uint tag, int size)
if (size && size != rec->size) if (size && size != rec->size)
return NULL; return NULL;
return (void *)rec + rec->hdr_size; return (void *)rec + rec_hdr_size(rec);
} }
void *bloblist_add(uint tag, int size, int align) void *bloblist_add(uint tag, int size, int align_log2)
{ {
struct bloblist_rec *rec; struct bloblist_rec *rec;
if (bloblist_addrec(tag, size, align, &rec)) if (bloblist_addrec(tag, size, align_log2, &rec))
return NULL; return NULL;
return (void *)rec + rec->hdr_size; return (void *)rec + rec_hdr_size(rec);
} }
int bloblist_ensure_size(uint tag, int size, int align, void **blobp) int bloblist_ensure_size(uint tag, int size, int align_log2, void **blobp)
{ {
struct bloblist_rec *rec; struct bloblist_rec *rec;
int ret; int ret;
ret = bloblist_ensurerec(tag, &rec, size, align); ret = bloblist_ensurerec(tag, &rec, size, align_log2);
if (ret) if (ret)
return ret; return ret;
*blobp = (void *)rec + rec->hdr_size; *blobp = (void *)rec + rec_hdr_size(rec);
return 0; return 0;
} }
@ -224,7 +265,7 @@ void *bloblist_ensure(uint tag, int size)
if (bloblist_ensurerec(tag, &rec, size, 0)) if (bloblist_ensurerec(tag, &rec, size, 0))
return NULL; return NULL;
return (void *)rec + rec->hdr_size; return (void *)rec + rec_hdr_size(rec);
} }
int bloblist_ensure_size_ret(uint tag, int *sizep, void **blobp) int bloblist_ensure_size_ret(uint tag, int *sizep, void **blobp)
@ -237,7 +278,7 @@ int bloblist_ensure_size_ret(uint tag, int *sizep, void **blobp)
*sizep = rec->size; *sizep = rec->size;
else if (ret) else if (ret)
return ret; return ret;
*blobp = (void *)rec + rec->hdr_size; *blobp = (void *)rec + rec_hdr_size(rec);
return 0; return 0;
} }
@ -247,33 +288,34 @@ static int bloblist_resize_rec(struct bloblist_hdr *hdr,
int new_size) int new_size)
{ {
int expand_by; /* Number of bytes to expand by (-ve to contract) */ int expand_by; /* Number of bytes to expand by (-ve to contract) */
int new_alloced; /* New value for @hdr->alloced */ int new_alloced;
ulong next_ofs; /* Offset of the record after @rec */ ulong next_ofs; /* Offset of the record after @rec */
expand_by = ALIGN(new_size - rec->size, BLOBLIST_ALIGN); expand_by = ALIGN(new_size - rec->size, BLOBLIST_BLOB_ALIGN);
new_alloced = ALIGN(hdr->alloced + expand_by, BLOBLIST_ALIGN); new_alloced = ALIGN(hdr->used_size + expand_by, BLOBLIST_BLOB_ALIGN);
if (new_size < 0) { if (new_size < 0) {
log_debug("Attempt to shrink blob size below 0 (%x)\n", log_debug("Attempt to shrink blob size below 0 (%x)\n",
new_size); new_size);
return log_msg_ret("size", -EINVAL); return log_msg_ret("size", -EINVAL);
} }
if (new_alloced > hdr->size) { if (new_alloced > hdr->total_size) {
log_err("Failed to allocate %x bytes size=%x, need size=%x\n", log_err("Failed to allocate %x bytes\n", new_size);
new_size, hdr->size, new_alloced); log_err("Used size=%x, total size=%x\n",
hdr->used_size, hdr->total_size);
return log_msg_ret("alloc", -ENOSPC); return log_msg_ret("alloc", -ENOSPC);
} }
/* Move the following blobs up or down, if this is not the last */ /* Move the following blobs up or down, if this is not the last */
next_ofs = bloblist_blob_end_ofs(hdr, rec); next_ofs = bloblist_blob_end_ofs(hdr, rec);
if (next_ofs != hdr->alloced) { if (next_ofs != hdr->used_size) {
memmove((void *)hdr + next_ofs + expand_by, memmove((void *)hdr + next_ofs + expand_by,
(void *)hdr + next_ofs, new_alloced - next_ofs); (void *)hdr + next_ofs, new_alloced - next_ofs);
} }
hdr->alloced = new_alloced; hdr->used_size = new_alloced;
/* Zero the new part of the blob */ /* Zero the new part of the blob */
if (expand_by > 0) { if (expand_by > 0) {
memset((void *)rec + rec->hdr_size + rec->size, '\0', memset((void *)rec + rec_hdr_size(rec) + rec->size, '\0',
new_size - rec->size); new_size - rec->size);
} }
@ -301,20 +343,15 @@ int bloblist_resize(uint tag, int new_size)
static u32 bloblist_calc_chksum(struct bloblist_hdr *hdr) static u32 bloblist_calc_chksum(struct bloblist_hdr *hdr)
{ {
struct bloblist_rec *rec; u8 chksum;
u32 chksum;
chksum = crc32(0, (unsigned char *)hdr, chksum = table_compute_checksum(hdr, hdr->used_size);
offsetof(struct bloblist_hdr, chksum)); chksum += hdr->chksum;
foreach_rec(rec, hdr) {
chksum = crc32(chksum, (void *)rec, rec->hdr_size);
chksum = crc32(chksum, (void *)rec + rec->hdr_size, rec->size);
}
return chksum; return chksum;
} }
int bloblist_new(ulong addr, uint size, uint flags) int bloblist_new(ulong addr, uint size, uint flags, uint align_log2)
{ {
struct bloblist_hdr *hdr; struct bloblist_hdr *hdr;
@ -328,8 +365,9 @@ int bloblist_new(ulong addr, uint size, uint flags)
hdr->hdr_size = sizeof(*hdr); hdr->hdr_size = sizeof(*hdr);
hdr->flags = flags; hdr->flags = flags;
hdr->magic = BLOBLIST_MAGIC; hdr->magic = BLOBLIST_MAGIC;
hdr->size = size; hdr->used_size = hdr->hdr_size;
hdr->alloced = hdr->hdr_size; hdr->total_size = size;
hdr->align_log2 = align_log2 ? align_log2 : BLOBLIST_BLOB_ALIGN_LOG2;
hdr->chksum = 0; hdr->chksum = 0;
gd->bloblist = hdr; gd->bloblist = hdr;
@ -346,8 +384,13 @@ int bloblist_check(ulong addr, uint size)
return log_msg_ret("Bad magic", -ENOENT); return log_msg_ret("Bad magic", -ENOENT);
if (hdr->version != BLOBLIST_VERSION) if (hdr->version != BLOBLIST_VERSION)
return log_msg_ret("Bad version", -EPROTONOSUPPORT); return log_msg_ret("Bad version", -EPROTONOSUPPORT);
if (size && hdr->size != size) if (!hdr->total_size || (size && hdr->total_size != size))
return log_msg_ret("Bad size", -EFBIG); return log_msg_ret("Bad total size", -EFBIG);
if (hdr->used_size > hdr->total_size)
return log_msg_ret("Bad used size", -ENOENT);
if (hdr->hdr_size != sizeof(struct bloblist_hdr))
return log_msg_ret("Bad header size", -ENOENT);
chksum = bloblist_calc_chksum(hdr); chksum = bloblist_calc_chksum(hdr);
if (hdr->chksum != chksum) { if (hdr->chksum != chksum) {
log_err("Checksum %x != %x\n", hdr->chksum, chksum); log_err("Checksum %x != %x\n", hdr->chksum, chksum);
@ -363,7 +406,7 @@ int bloblist_finish(void)
struct bloblist_hdr *hdr = gd->bloblist; struct bloblist_hdr *hdr = gd->bloblist;
hdr->chksum = bloblist_calc_chksum(hdr); hdr->chksum = bloblist_calc_chksum(hdr);
log_debug("Finished bloblist size %lx at %lx\n", (ulong)hdr->size, log_debug("Finished bloblist size %lx at %lx\n", (ulong)hdr->used_size,
(ulong)map_to_sysmem(hdr)); (ulong)map_to_sysmem(hdr));
return 0; return 0;
@ -378,33 +421,40 @@ ulong bloblist_get_size(void)
{ {
struct bloblist_hdr *hdr = gd->bloblist; struct bloblist_hdr *hdr = gd->bloblist;
return hdr->size; return hdr->used_size;
} }
void bloblist_get_stats(ulong *basep, ulong *sizep, ulong *allocedp) ulong bloblist_get_total_size(void)
{
struct bloblist_hdr *hdr = gd->bloblist;
return hdr->total_size;
}
void bloblist_get_stats(ulong *basep, ulong *tsizep, ulong *usizep)
{ {
struct bloblist_hdr *hdr = gd->bloblist; struct bloblist_hdr *hdr = gd->bloblist;
*basep = map_to_sysmem(gd->bloblist); *basep = map_to_sysmem(gd->bloblist);
*sizep = hdr->size; *tsizep = hdr->total_size;
*allocedp = hdr->alloced; *usizep = hdr->used_size;
} }
static void show_value(const char *prompt, ulong value) static void show_value(const char *prompt, ulong value)
{ {
printf("%s:%*s %-5lx ", prompt, 8 - (int)strlen(prompt), "", value); printf("%s:%*s %-5lx ", prompt, 10 - (int)strlen(prompt), "", value);
print_size(value, "\n"); print_size(value, "\n");
} }
void bloblist_show_stats(void) void bloblist_show_stats(void)
{ {
ulong base, size, alloced; ulong base, tsize, usize;
bloblist_get_stats(&base, &size, &alloced); bloblist_get_stats(&base, &tsize, &usize);
printf("base: %lx\n", base); printf("base: %lx\n", base);
show_value("size", size); show_value("total size", tsize);
show_value("alloced", alloced); show_value("used size", usize);
show_value("free", size - alloced); show_value("free", tsize - usize);
} }
void bloblist_show_list(void) void bloblist_show_list(void)
@ -416,8 +466,9 @@ void bloblist_show_list(void)
for (rec = bloblist_first_blob(hdr); rec; for (rec = bloblist_first_blob(hdr); rec;
rec = bloblist_next_blob(hdr, rec)) { rec = bloblist_next_blob(hdr, rec)) {
printf("%08lx %8x %4x %s\n", printf("%08lx %8x %4x %s\n",
(ulong)map_to_sysmem((void *)rec + rec->hdr_size), (ulong)map_to_sysmem((void *)rec + rec_hdr_size(rec)),
rec->size, rec->tag, bloblist_tag_name(rec->tag)); rec->size, rec_tag(rec),
bloblist_tag_name(rec_tag(rec)));
} }
} }
@ -427,7 +478,7 @@ void bloblist_reloc(void *to, uint to_size, void *from, uint from_size)
memcpy(to, from, from_size); memcpy(to, from, from_size);
hdr = to; hdr = to;
hdr->size = to_size; hdr->total_size = to_size;
} }
int bloblist_init(void) int bloblist_init(void)
@ -457,7 +508,7 @@ int bloblist_init(void)
addr, ret); addr, ret);
} else { } else {
/* Get the real size, if it is not what we expected */ /* Get the real size, if it is not what we expected */
size = gd->bloblist->size; size = gd->bloblist->total_size;
} }
} }
if (ret) { if (ret) {
@ -472,7 +523,7 @@ int bloblist_init(void)
} }
log_debug("Creating new bloblist size %lx at %lx\n", size, log_debug("Creating new bloblist size %lx at %lx\n", size,
addr); addr);
ret = bloblist_new(addr, size, 0); ret = bloblist_new(addr, size, 0, 0);
} else { } else {
log_debug("Found existing bloblist size %lx at %lx\n", size, log_debug("Found existing bloblist size %lx at %lx\n", size,
addr); addr);

View File

@ -14,6 +14,8 @@ structure defined by the code that owns it.
For the design goals of bloblist, please see the comments at the top of the For the design goals of bloblist, please see the comments at the top of the
`bloblist.h` header file. `bloblist.h` header file.
Bloblist is an implementation with the `Firmware Handoff`_ protocol.
Passing state through the boot process Passing state through the boot process
-------------------------------------- --------------------------------------
@ -99,7 +101,7 @@ API documentation
----------------- -----------------
.. kernel-doc:: include/bloblist.h .. kernel-doc:: include/bloblist.h
.. _`Firmware Handoff`: https://github.com/FirmwareHandoff/firmware_handoff
Simon Glass Simon Glass
sjg@chromium.org sjg@chromium.org

View File

@ -24,11 +24,11 @@
* which would add to code size. For Thumb-2 the code size needed in SPL is * which would add to code size. For Thumb-2 the code size needed in SPL is
* approximately 940 bytes (e.g. for chromebook_bob). * approximately 940 bytes (e.g. for chromebook_bob).
* *
* 5. Bloblist uses 16-byte alignment internally and is designed to start on a * 5. Bloblist uses 8-byte alignment internally and is designed to start on a
* 16-byte boundary. Its headers are multiples of 16 bytes. This makes it easier * 8-byte boundary. Its headers are 8 bytes long. It is possible to achieve
* to deal with data structures which need this level of alignment, such as ACPI * larger alignment (e.g. 16 bytes) by adding a dummy header, For use in SPL and
* tables. For use in SPL and TPL the alignment can be relaxed, since it can be * TPL the alignment can be relaxed, since it can be relocated to an aligned
* relocated to an aligned address in U-Boot proper. * address in U-Boot proper.
* *
* 6. Bloblist is designed to be passed to Linux as reserved memory. While linux * 6. Bloblist is designed to be passed to Linux as reserved memory. While linux
* doesn't understand the bloblist header, it can be passed the indivdual blobs. * doesn't understand the bloblist header, it can be passed the indivdual blobs.
@ -66,6 +66,7 @@
* *
* Copyright 2018 Google, Inc * Copyright 2018 Google, Inc
* Written by Simon Glass <sjg@chromium.org> * Written by Simon Glass <sjg@chromium.org>
* Adjusted July 2023 to match Firmware handoff specification, Release 0.9
*/ */
#ifndef __BLOBLIST_H #ifndef __BLOBLIST_H
@ -74,14 +75,19 @@
#include <mapmem.h> #include <mapmem.h>
enum { enum {
BLOBLIST_VERSION = 0, BLOBLIST_VERSION = 1,
BLOBLIST_MAGIC = 0xb00757a3, BLOBLIST_MAGIC = 0x4a0fb10b,
BLOBLIST_ALIGN = 16,
BLOBLIST_BLOB_ALIGN_LOG2 = 3,
BLOBLIST_BLOB_ALIGN = 1 << BLOBLIST_BLOB_ALIGN_LOG2,
BLOBLIST_ALIGN_LOG2 = 3,
BLOBLIST_ALIGN = 1 << BLOBLIST_ALIGN_LOG2,
}; };
/* Supported tags - add new ones to tag_name in bloblist.c */ /* Supported tags - add new ones to tag_name in bloblist.c */
enum bloblist_tag_t { enum bloblist_tag_t {
BLOBLISTT_NONE = 0, BLOBLISTT_VOID = 0,
/* /*
* Standard area to allocate blobs used across firmware components, for * Standard area to allocate blobs used across firmware components, for
@ -89,42 +95,36 @@ enum bloblist_tag_t {
* projects. * projects.
*/ */
BLOBLISTT_AREA_FIRMWARE_TOP = 0x1, BLOBLISTT_AREA_FIRMWARE_TOP = 0x1,
/*
* Devicetree for use by firmware. On some platforms this is passed to
* the OS also
*/
BLOBLISTT_CONTROL_FDT = 1,
BLOBLISTT_HOB_BLOCK = 2,
BLOBLISTT_HOB_LIST = 3,
BLOBLISTT_ACPI_TABLES = 4,
BLOBLISTT_TPM_EVLOG = 5,
BLOBLISTT_TPM_CRB_BASE = 6,
/* Standard area to allocate blobs used across firmware components */ /* Standard area to allocate blobs used across firmware components */
BLOBLISTT_AREA_FIRMWARE = 0x100, BLOBLISTT_AREA_FIRMWARE = 0x10,
BLOBLISTT_TPM2_TCG_LOG = 0x10, /* TPM v2 log space */
BLOBLISTT_TCPA_LOG = 0x11, /* TPM log space */
/* /*
* Advanced Configuration and Power Interface Global Non-Volatile * Advanced Configuration and Power Interface Global Non-Volatile
* Sleeping table. This forms part of the ACPI tables passed to Linux. * Sleeping table. This forms part of the ACPI tables passed to Linux.
*/ */
BLOBLISTT_ACPI_GNVS = 0x100, BLOBLISTT_ACPI_GNVS = 0x12,
BLOBLISTT_INTEL_VBT = 0x101, /* Intel Video-BIOS table */
BLOBLISTT_TPM2_TCG_LOG = 0x102, /* TPM v2 log space */
BLOBLISTT_TCPA_LOG = 0x103, /* TPM log space */
BLOBLISTT_ACPI_TABLES = 0x104, /* ACPI tables for x86 */
BLOBLISTT_SMBIOS_TABLES = 0x105, /* SMBIOS tables for x86 */
BLOBLISTT_VBOOT_CTX = 0x106, /* Chromium OS verified boot context */
/* /* Standard area to allocate blobs used for Trusted Firmware */
* Project-specific tags are permitted here. Projects can be open source BLOBLISTT_AREA_TF = 0x100,
* or not, but the format of the data must be fuily documented in an BLOBLISTT_OPTEE_PAGABLE_PART = 0x100,
* open source project, including all fields, bits, etc. Naming should
* be: BLOBLISTT_<project>_<purpose_here>
*/
BLOBLISTT_PROJECT_AREA = 0x8000,
BLOBLISTT_U_BOOT_SPL_HANDOFF = 0x8000, /* Hand-off info from SPL */
BLOBLISTT_VBE = 0x8001, /* VBE per-phase state */
BLOBLISTT_U_BOOT_VIDEO = 0x8002, /* Video information from SPL */
/* /* Other standard area to allocate blobs */
* Vendor-specific tags are permitted here. Projects can be open source BLOBLISTT_AREA_OTHER = 0x200,
* or not, but the format of the data must be fuily documented in an BLOBLISTT_INTEL_VBT = 0x200, /* Intel Video-BIOS table */
* open source project, including all fields, bits, etc. Naming should BLOBLISTT_SMBIOS_TABLES = 0x201, /* SMBIOS tables for x86 */
* be BLOBLISTT_<vendor>_<purpose_here> BLOBLISTT_VBOOT_CTX = 0x202, /* Chromium OS verified boot context */
*/
BLOBLISTT_VENDOR_AREA = 0xc000,
/* Tags after this are not allocated for now */
BLOBLISTT_EXPANSION = 0x10000,
/* /*
* Tags from here are on reserved for private use within a single * Tags from here are on reserved for private use within a single
@ -133,9 +133,20 @@ enum bloblist_tag_t {
* implementation, but cannot be used in upstream code. Allocate a * implementation, but cannot be used in upstream code. Allocate a
* tag in one of the areas above if you want that. * tag in one of the areas above if you want that.
* *
* This area may move in future. * Project-specific tags are permitted here. Projects can be open source
* or not, but the format of the data must be fuily documented in an
* open source project, including all fields, bits, etc. Naming should
* be: BLOBLISTT_<project>_<purpose_here>
*
* Vendor-specific tags are also permitted. Projects can be open source
* or not, but the format of the data must be fuily documented in an
* open source project, including all fields, bits, etc. Naming should
* be BLOBLISTT_<vendor>_<purpose_here>
*/ */
BLOBLISTT_PRIVATE_AREA = 0xffff0000, BLOBLISTT_PRIVATE_AREA = 0xfff000,
BLOBLISTT_U_BOOT_SPL_HANDOFF = 0xfff000, /* Hand-off info from SPL */
BLOBLISTT_VBE = 0xfff001, /* VBE per-phase state */
BLOBLISTT_U_BOOT_VIDEO = 0xfff002, /* Video info from SPL */
}; };
/** /**
@ -156,33 +167,33 @@ enum bloblist_tag_t {
* from the last. * from the last.
* *
* @magic: BLOBLIST_MAGIC * @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 * @version: BLOBLIST_VERSION
* @hdr_size: Size of this header, normally sizeof(struct bloblist_hdr). The * @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 * first bloblist_rec starts at this offset from the start of the header
* @flags: Space for BLOBLISTF... flags (none yet) * @align_log2: Power of two of the maximum alignment required by this list
* @size: Total size of the bloblist (non-zero if valid) including this header. * @used_size: Size allocated so far for this bloblist. This starts out as
* 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 * sizeof(bloblist_hdr) since we need at least that much space to store a
* valid bloblist * 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) * @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.
*/ */
struct bloblist_hdr { struct bloblist_hdr {
u32 magic; u32 magic;
u32 version; u8 chksum;
u32 hdr_size; u8 version;
u8 hdr_size;
u8 align_log2;
u32 used_size;
u32 total_size;
u32 flags; u32 flags;
u32 size;
u32 alloced;
u32 spare; u32 spare;
u32 chksum;
}; };
/** /**
@ -193,18 +204,25 @@ struct bloblist_hdr {
* *
* NOTE: Only exported for testing purposes. Do not use this struct. * NOTE: Only exported for testing purposes. Do not use this struct.
* *
* @tag: Tag indicating what the record contains * @tag_and_hdr_size: Tag indicating what the record contains (bottom 24 bits), and
* @hdr_size: Size of this header, normally sizeof(struct bloblist_rec). The * size of this header (top 8 bits), normally sizeof(struct bloblist_rec).
* record's data starts at this offset from the start of the record * 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 * @size: Size of record in bytes, excluding the header size. This does not
* need to be aligned (e.g. 3 is OK). * need to be aligned (e.g. 3 is OK).
* @spare: Spare space for other things
*/ */
struct bloblist_rec { struct bloblist_rec {
u32 tag; u32 tag_and_hdr_size;
u32 hdr_size;
u32 size; u32 size;
u32 spare; };
enum {
BLOBLISTR_TAG_SHIFT = 0,
BLOBLISTR_TAG_MASK = 0xffffffU << BLOBLISTR_TAG_SHIFT,
BLOBLISTR_HDR_SIZE_SHIFT = 24,
BLOBLISTR_HDR_SIZE_MASK = 0xffU << BLOBLISTR_HDR_SIZE_SHIFT,
BLOBLIST_HDR_SIZE = sizeof(struct bloblist_hdr),
BLOBLIST_REC_HDR_SIZE = sizeof(struct bloblist_rec),
}; };
/** /**
@ -249,11 +267,11 @@ void *bloblist_find(uint tag, int size);
* *
* @tag: Tag to add (enum bloblist_tag_t) * @tag: Tag to add (enum bloblist_tag_t)
* @size: Size of the blob * @size: Size of the blob
* @align: Alignment of the blob (in bytes), 0 for default * @align_log2: Alignment of the blob (in bytes log2), 0 for default
* Return: pointer to the newly added block, or NULL if there is not enough * Return: pointer to the newly added block, or NULL if there is not enough
* space for the blob * space for the blob
*/ */
void *bloblist_add(uint tag, int size, int align); void *bloblist_add(uint tag, int size, int align_log2);
/** /**
* bloblist_ensure_size() - Find or add a blob * bloblist_ensure_size() - Find or add a blob
@ -263,11 +281,11 @@ void *bloblist_add(uint tag, int size, int align);
* @tag: Tag to add (enum bloblist_tag_t) * @tag: Tag to add (enum bloblist_tag_t)
* @size: Size of the blob * @size: Size of the blob
* @blobp: Returns a pointer to blob on success * @blobp: Returns a pointer to blob on success
* @align: Alignment of the blob (in bytes), 0 for default * @align_log2: Alignment of the blob (in bytes log2), 0 for default
* Return: 0 if OK, -ENOSPC if it is missing and could not be added due to lack * 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 * of space, or -ESPIPE it exists but has the wrong size
*/ */
int bloblist_ensure_size(uint tag, int size, int align, void **blobp); int bloblist_ensure_size(uint tag, int size, int align_log2, void **blobp);
/** /**
* bloblist_ensure() - Find or add a blob * bloblist_ensure() - Find or add a blob
@ -313,10 +331,11 @@ int bloblist_resize(uint tag, int new_size);
* @addr: Address of bloblist * @addr: Address of bloblist
* @size: Initial size for bloblist * @size: Initial size for bloblist
* @flags: Flags to use for bloblist * @flags: Flags to use for bloblist
* @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 * Return: 0 if OK, -EFAULT if addr is not aligned correctly, -ENOSPC is the
* area is not large enough * area is not large enough
*/ */
int bloblist_new(ulong addr, uint size, uint flags); int bloblist_new(ulong addr, uint size, uint flags, uint align_log2);
/** /**
* bloblist_check() - Check if a bloblist exists * bloblist_check() - Check if a bloblist exists
@ -347,10 +366,10 @@ int bloblist_finish(void);
* This returns useful information about the bloblist * This returns useful information about the bloblist
* *
* @basep: Returns base address of bloblist * @basep: Returns base address of bloblist
* @sizep: Returns the number of bytes used in the bloblist * @tsizep: Returns the total number of bytes of the bloblist
* @allocedp: Returns the total space allocated to the bloblist * @usizep: Returns the number of used bytes of the bloblist
*/ */
void bloblist_get_stats(ulong *basep, ulong *sizep, ulong *allocedp); void bloblist_get_stats(ulong *basep, ulong *tsizep, ulong *usizep);
/** /**
* bloblist_get_base() - Get the base address of the bloblist * bloblist_get_base() - Get the base address of the bloblist
@ -366,6 +385,13 @@ ulong bloblist_get_base(void);
*/ */
ulong bloblist_get_size(void); ulong bloblist_get_size(void);
/**
* bloblist_get_total_size() - Get the total size of the bloblist
*
* Return: the size in bytes
*/
ulong bloblist_get_total_size(void);
/** /**
* bloblist_show_stats() - Show information about the bloblist * bloblist_show_stats() - Show information about the bloblist
* *

View File

@ -635,8 +635,19 @@ else
fdtgrep_props := -b bootph-all -b bootph-pre-ram $(migrate_spl) fdtgrep_props := -b bootph-all -b bootph-pre-ram $(migrate_spl)
endif endif
endif endif
# This rule produces the .dtb for an SPL build.
#
# The first fdtgrep keeps nodes with the above properties (with -u ensuring that
# the properties are implied in all parents of a matching node). The root node
# is always included, along with /chosen and /config nodes. Referenced aliases
# (i.e. properties in /aliases which point to an incldued node) are also
# included.
#
# The second fdtgrep removes all bootph properties along with unused strings
# and any properties in CONFIG_OF_SPL_REMOVE_PROPS
quiet_cmd_fdtgrep = FDTGREP $@ quiet_cmd_fdtgrep = FDTGREP $@
cmd_fdtgrep = $(objtree)/tools/fdtgrep $(fdtgrep_props) -RT $< \ cmd_fdtgrep = $(objtree)/tools/fdtgrep $(fdtgrep_props) -u -RT $< \
-n /chosen -n /config -O dtb | \ -n /chosen -n /config -O dtb | \
$(objtree)/tools/fdtgrep -r -O dtb - -o $@ \ $(objtree)/tools/fdtgrep -r -O dtb - -o $@ \
-P bootph-all -P bootph-pre-ram -P bootph-pre-sram \ -P bootph-all -P bootph-pre-ram -P bootph-pre-sram \

View File

@ -314,7 +314,7 @@ endif
# - we have either OF_SEPARATE or OF_HOSTFILE # - we have either OF_SEPARATE or OF_HOSTFILE
build_dtb := build_dtb :=
ifneq ($(CONFIG_$(SPL_TPL_)OF_REAL),) ifneq ($(CONFIG_$(SPL_TPL_)OF_REAL),)
ifeq ($(CONFIG_OF_SEPARATE)$(CONFIG_SANDBOX),y) ifneq ($(CONFIG_OF_SEPARATE)$(CONFIG_SANDBOX),)
build_dtb := y build_dtb := y
endif endif
endif endif

View File

@ -72,15 +72,15 @@ static int bloblist_test_init(struct unit_test_state *uts)
hdr = clear_bloblist(); hdr = clear_bloblist();
ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR)); ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
ut_asserteq_ptr(hdr, bloblist_check_magic(TEST_ADDR)); ut_asserteq_ptr(hdr, bloblist_check_magic(TEST_ADDR));
hdr->version++; hdr->version++;
ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR, ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
TEST_BLOBLIST_SIZE)); TEST_BLOBLIST_SIZE));
ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0x10, 0)); ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0xc, 0, 0));
ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0)); ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0, 0));
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
ut_assertok(bloblist_finish()); ut_assertok(bloblist_finish());
@ -106,8 +106,9 @@ static int bloblist_test_blob(struct unit_test_state *uts)
/* At the start there should be no records */ /* At the start there should be no records */
hdr = clear_bloblist(); hdr = clear_bloblist();
ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE)); ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_size()); ut_asserteq(sizeof(struct bloblist_hdr), bloblist_get_size());
ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_total_size());
ut_asserteq(TEST_ADDR, bloblist_get_base()); ut_asserteq(TEST_ADDR, bloblist_get_base());
ut_asserteq(map_to_sysmem(hdr), TEST_ADDR); ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
@ -144,7 +145,7 @@ static int bloblist_test_blob_ensure(struct unit_test_state *uts)
/* At the start there should be no records */ /* At the start there should be no records */
clear_bloblist(); clear_bloblist();
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
/* Test with an empty bloblist */ /* Test with an empty bloblist */
size = TEST_SIZE; size = TEST_SIZE;
@ -176,7 +177,7 @@ static int bloblist_test_bad_blob(struct unit_test_state *uts)
void *data; void *data;
hdr = clear_bloblist(); hdr = clear_bloblist();
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
data = hdr + 1; data = hdr + 1;
data += sizeof(struct bloblist_rec); data += sizeof(struct bloblist_rec);
ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE)); ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
@ -192,7 +193,7 @@ static int bloblist_test_checksum(struct unit_test_state *uts)
char *data, *data2; char *data, *data2;
hdr = clear_bloblist(); hdr = clear_bloblist();
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
ut_assertok(bloblist_finish()); ut_assertok(bloblist_finish());
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
@ -205,9 +206,9 @@ static int bloblist_test_checksum(struct unit_test_state *uts)
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
hdr->flags++; hdr->flags++;
hdr->size--; hdr->total_size--;
ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
hdr->size++; hdr->total_size++;
hdr->spare++; hdr->spare++;
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
@ -217,6 +218,10 @@ static int bloblist_test_checksum(struct unit_test_state *uts)
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
hdr->chksum--; hdr->chksum--;
hdr->align_log2++;
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
hdr->align_log2--;
/* Make sure the checksum changes when we add blobs */ /* Make sure the checksum changes when we add blobs */
data = bloblist_add(TEST_TAG, TEST_SIZE, 0); data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
@ -237,12 +242,18 @@ static int bloblist_test_checksum(struct unit_test_state *uts)
*data2 -= 1; *data2 -= 1;
/* /*
* Changing data outside the range of valid data should not affect * Changing data outside the range of valid data should affect the
* the checksum. * checksum.
*/ */
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
data[TEST_SIZE]++; data[TEST_SIZE]++;
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
data[TEST_SIZE]--;
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
data2[TEST_SIZE2]++; data2[TEST_SIZE2]++;
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
data[TEST_SIZE]--;
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE)); ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
return 0; return 0;
@ -256,7 +267,7 @@ static int bloblist_test_cmd_info(struct unit_test_state *uts)
char *data, *data2; char *data, *data2;
hdr = clear_bloblist(); hdr = clear_bloblist();
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
data = bloblist_ensure(TEST_TAG, TEST_SIZE); data = bloblist_ensure(TEST_TAG, TEST_SIZE);
data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2); data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
@ -264,10 +275,10 @@ static int bloblist_test_cmd_info(struct unit_test_state *uts)
ut_silence_console(uts); ut_silence_console(uts);
console_record_reset(); console_record_reset();
run_command("bloblist info", 0); run_command("bloblist info", 0);
ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr)); ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
ut_assert_nextline("size: 400 1 KiB"); ut_assert_nextline("total size: 400 1 KiB");
ut_assert_nextline("alloced: 70 112 Bytes"); ut_assert_nextline("used size: 50 80 Bytes");
ut_assert_nextline("free: 390 912 Bytes"); ut_assert_nextline("free: 3b0 944 Bytes");
ut_assert_console_end(); ut_assert_console_end();
ut_unsilence_console(uts); ut_unsilence_console(uts);
@ -282,7 +293,7 @@ static int bloblist_test_cmd_list(struct unit_test_state *uts)
char *data, *data2; char *data, *data2;
hdr = clear_bloblist(); hdr = clear_bloblist();
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
data = bloblist_ensure(TEST_TAG, TEST_SIZE); data = bloblist_ensure(TEST_TAG, TEST_SIZE);
data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2); data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
@ -291,9 +302,9 @@ static int bloblist_test_cmd_list(struct unit_test_state *uts)
console_record_reset(); console_record_reset();
run_command("bloblist list", 0); run_command("bloblist list", 0);
ut_assert_nextline("Address Size Tag Name"); ut_assert_nextline("Address Size Tag Name");
ut_assert_nextline("%08lx %8x 8000 SPL hand-off", ut_assert_nextline("%08lx %8x fff000 SPL hand-off",
(ulong)map_to_sysmem(data), TEST_SIZE); (ulong)map_to_sysmem(data), TEST_SIZE);
ut_assert_nextline("%08lx %8x 106 Chrome OS vboot context", ut_assert_nextline("%08lx %8x 202 Chrome OS vboot context",
(ulong)map_to_sysmem(data2), TEST_SIZE2); (ulong)map_to_sysmem(data2), TEST_SIZE2);
ut_assert_console_end(); ut_assert_console_end();
ut_unsilence_console(uts); ut_unsilence_console(uts);
@ -312,7 +323,7 @@ static int bloblist_test_align(struct unit_test_state *uts)
/* At the start there should be no records */ /* At the start there should be no records */
hdr = clear_bloblist(); hdr = clear_bloblist();
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE)); ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
/* Check the default alignment */ /* Check the default alignment */
@ -325,18 +336,18 @@ static int bloblist_test_align(struct unit_test_state *uts)
data = bloblist_add(i, size, 0); data = bloblist_add(i, size, 0);
ut_assertnonnull(data); ut_assertnonnull(data);
addr = map_to_sysmem(data); addr = map_to_sysmem(data);
ut_asserteq(0, addr & (BLOBLIST_ALIGN - 1)); ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN - 1));
/* Only the bytes in the blob data should be zeroed */ /* Only the bytes in the blob data should be zeroed */
for (j = 0; j < size; j++) for (j = 0; j < size; j++)
ut_asserteq(0, data[j]); ut_asserteq(0, data[j]);
for (; j < BLOBLIST_ALIGN; j++) for (; j < BLOBLIST_BLOB_ALIGN; j++)
ut_asserteq(ERASE_BYTE, data[j]); ut_asserteq(ERASE_BYTE, data[j]);
} }
/* Check larger alignment */ /* Check larger alignment */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
int align = 32 << i; int align = 5 - i;
data = bloblist_add(3 + i, i * 4, align); data = bloblist_add(3 + i, i * 4, align);
ut_assertnonnull(data); ut_assertnonnull(data);
@ -345,16 +356,16 @@ static int bloblist_test_align(struct unit_test_state *uts)
} }
/* Check alignment with an bloblist starting on a smaller alignment */ /* Check alignment with an bloblist starting on a smaller alignment */
hdr = map_sysmem(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE); hdr = map_sysmem(TEST_ADDR + BLOBLIST_BLOB_ALIGN, TEST_BLOBLIST_SIZE);
memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE); memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
memset(hdr, '\0', sizeof(*hdr)); memset(hdr, '\0', sizeof(*hdr));
ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE, ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
0)); 0, 0));
data = bloblist_add(1, 5, BLOBLIST_ALIGN * 2); data = bloblist_add(1, 5, BLOBLIST_ALIGN_LOG2 + 1);
ut_assertnonnull(data); ut_assertnonnull(data);
addr = map_to_sysmem(data); addr = map_to_sysmem(data);
ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1)); ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN * 2 - 1));
return 0; return 0;
} }
@ -370,7 +381,7 @@ static int bloblist_test_reloc(struct unit_test_state *uts)
ulong new_addr; ulong new_addr;
ulong new_size; ulong new_size;
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
old_ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); old_ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
/* Add one blob and then one that won't fit */ /* Add one blob and then one that won't fit */
@ -409,7 +420,7 @@ static int bloblist_test_grow(struct unit_test_state *uts)
memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE); memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
/* Create two blobs */ /* Create two blobs */
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
blob1 = bloblist_add(TEST_TAG, small_size, 0); blob1 = bloblist_add(TEST_TAG, small_size, 0);
ut_assertnonnull(blob1); ut_assertnonnull(blob1);
ut_assertok(check_zero(blob1, small_size)); ut_assertok(check_zero(blob1, small_size));
@ -421,7 +432,7 @@ static int bloblist_test_grow(struct unit_test_state *uts)
ut_asserteq(sizeof(struct bloblist_hdr) + ut_asserteq(sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2, sizeof(struct bloblist_rec) * 2 + small_size * 2,
hdr->alloced); hdr->used_size);
/* Resize the first one */ /* Resize the first one */
ut_assertok(bloblist_resize(TEST_TAG, small_size + 4)); ut_assertok(bloblist_resize(TEST_TAG, small_size + 4));
@ -442,8 +453,8 @@ static int bloblist_test_grow(struct unit_test_state *uts)
hdr = ptr; hdr = ptr;
ut_asserteq(sizeof(struct bloblist_hdr) + ut_asserteq(sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2 + sizeof(struct bloblist_rec) * 2 + small_size * 2 +
BLOBLIST_ALIGN, BLOBLIST_BLOB_ALIGN,
hdr->alloced); hdr->used_size);
return 0; return 0;
} }
@ -461,7 +472,7 @@ static int bloblist_test_shrink(struct unit_test_state *uts)
ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
/* Create two blobs */ /* Create two blobs */
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
blob1 = bloblist_add(TEST_TAG, small_size, 0); blob1 = bloblist_add(TEST_TAG, small_size, 0);
ut_assertnonnull(blob1); ut_assertnonnull(blob1);
strcpy(blob1, test1_str); strcpy(blob1, test1_str);
@ -473,7 +484,7 @@ static int bloblist_test_shrink(struct unit_test_state *uts)
hdr = ptr; hdr = ptr;
ut_asserteq(sizeof(struct bloblist_hdr) + ut_asserteq(sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2, sizeof(struct bloblist_rec) * 2 + small_size * 2,
hdr->alloced); hdr->used_size);
/* Resize the first one */ /* Resize the first one */
new_size = small_size - BLOBLIST_ALIGN - 4; new_size = small_size - BLOBLIST_ALIGN - 4;
@ -493,7 +504,7 @@ static int bloblist_test_shrink(struct unit_test_state *uts)
ut_asserteq(sizeof(struct bloblist_hdr) + ut_asserteq(sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2 - sizeof(struct bloblist_rec) * 2 + small_size * 2 -
BLOBLIST_ALIGN, BLOBLIST_ALIGN,
hdr->alloced); hdr->used_size);
return 0; return 0;
} }
@ -511,7 +522,7 @@ static int bloblist_test_resize_fail(struct unit_test_state *uts)
ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE); ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
/* Create two blobs */ /* Create two blobs */
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
blob1 = bloblist_add(TEST_TAG, small_size, 0); blob1 = bloblist_add(TEST_TAG, small_size, 0);
ut_assertnonnull(blob1); ut_assertnonnull(blob1);
@ -521,12 +532,12 @@ static int bloblist_test_resize_fail(struct unit_test_state *uts)
hdr = ptr; hdr = ptr;
ut_asserteq(sizeof(struct bloblist_hdr) + ut_asserteq(sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2, sizeof(struct bloblist_rec) * 2 + small_size * 2,
hdr->alloced); hdr->used_size);
/* Resize the first one, to check the boundary conditions */ /* Resize the first one, to check the boundary conditions */
ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1)); ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1));
new_size = small_size + (hdr->size - hdr->alloced); new_size = small_size + (hdr->total_size - hdr->used_size);
ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1)); ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1));
ut_assertok(bloblist_resize(TEST_TAG, new_size)); ut_assertok(bloblist_resize(TEST_TAG, new_size));
@ -548,7 +559,7 @@ static int bloblist_test_resize_last(struct unit_test_state *uts)
hdr = ptr; hdr = ptr;
/* Create two blobs */ /* Create two blobs */
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
blob1 = bloblist_add(TEST_TAG, small_size, 0); blob1 = bloblist_add(TEST_TAG, small_size, 0);
ut_assertnonnull(blob1); ut_assertnonnull(blob1);
@ -558,9 +569,9 @@ static int bloblist_test_resize_last(struct unit_test_state *uts)
/* Check the byte after the last blob */ /* Check the byte after the last blob */
alloced_val = sizeof(struct bloblist_hdr) + alloced_val = sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2; sizeof(struct bloblist_rec) * 2 + small_size * 2;
ut_asserteq(alloced_val, hdr->alloced); ut_asserteq(alloced_val, hdr->used_size);
ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size); ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size);
ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced)); ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
/* Resize the second one, checking nothing changes */ /* Resize the second one, checking nothing changes */
ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4)); ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4));
@ -577,9 +588,9 @@ static int bloblist_test_resize_last(struct unit_test_state *uts)
ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4)); ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4));
/* Check that the new top of the allocated blobs has not been touched */ /* Check that the new top of the allocated blobs has not been touched */
alloced_val += BLOBLIST_ALIGN; alloced_val += BLOBLIST_BLOB_ALIGN;
ut_asserteq(alloced_val, hdr->alloced); ut_asserteq(alloced_val, hdr->used_size);
ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced)); ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
return 0; return 0;
} }
@ -593,7 +604,7 @@ static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
/* At the start there should be no records */ /* At the start there should be no records */
clear_bloblist(); clear_bloblist();
ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0)); ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
/* Add a blob that takes up all space */ /* Add a blob that takes up all space */
size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) - size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) -

View File

@ -2842,12 +2842,14 @@ class TestFunctional(unittest.TestCase):
fdt_size = entries['section'].GetEntries()['u-boot-dtb'].size fdt_size = entries['section'].GetEntries()['u-boot-dtb'].size
fdtmap_offset = entries['fdtmap'].offset fdtmap_offset = entries['fdtmap'].offset
tmpdir = None
try: try:
tmpdir, updated_fname = self._SetupImageInTmpdir() tmpdir, updated_fname = self._SetupImageInTmpdir()
with test_util.capture_sys_output() as (stdout, stderr): with test_util.capture_sys_output() as (stdout, stderr):
self._DoBinman('ls', '-i', updated_fname) self._DoBinman('ls', '-i', updated_fname)
finally: finally:
shutil.rmtree(tmpdir) if tmpdir:
shutil.rmtree(tmpdir)
lines = stdout.getvalue().splitlines() lines = stdout.getvalue().splitlines()
expected = [ expected = [
'Name Image-pos Size Entry-type Offset Uncomp-size', 'Name Image-pos Size Entry-type Offset Uncomp-size',
@ -2868,12 +2870,14 @@ class TestFunctional(unittest.TestCase):
def testListCmdFail(self): def testListCmdFail(self):
"""Test failing to list an image""" """Test failing to list an image"""
self._DoReadFile('005_simple.dts') self._DoReadFile('005_simple.dts')
tmpdir = None
try: try:
tmpdir, updated_fname = self._SetupImageInTmpdir() tmpdir, updated_fname = self._SetupImageInTmpdir()
with self.assertRaises(ValueError) as e: with self.assertRaises(ValueError) as e:
self._DoBinman('ls', '-i', updated_fname) self._DoBinman('ls', '-i', updated_fname)
finally: finally:
shutil.rmtree(tmpdir) if tmpdir:
shutil.rmtree(tmpdir)
self.assertIn("Cannot find FDT map in image", str(e.exception)) self.assertIn("Cannot find FDT map in image", str(e.exception))
def _RunListCmd(self, paths, expected): def _RunListCmd(self, paths, expected):
@ -3002,13 +3006,15 @@ class TestFunctional(unittest.TestCase):
self._CheckLz4() self._CheckLz4()
self._DoReadFileRealDtb('130_list_fdtmap.dts') self._DoReadFileRealDtb('130_list_fdtmap.dts')
fname = os.path.join(self._indir, 'output.extact') fname = os.path.join(self._indir, 'output.extact')
tmpdir = None
try: try:
tmpdir, updated_fname = self._SetupImageInTmpdir() tmpdir, updated_fname = self._SetupImageInTmpdir()
with test_util.capture_sys_output() as (stdout, stderr): with test_util.capture_sys_output() as (stdout, stderr):
self._DoBinman('extract', '-i', updated_fname, 'u-boot', self._DoBinman('extract', '-i', updated_fname, 'u-boot',
'-f', fname) '-f', fname)
finally: finally:
shutil.rmtree(tmpdir) if tmpdir:
shutil.rmtree(tmpdir)
data = tools.read_file(fname) data = tools.read_file(fname)
self.assertEqual(U_BOOT_DATA, data) self.assertEqual(U_BOOT_DATA, data)
@ -5185,12 +5191,14 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
data = self._DoReadFileRealDtb('207_fip_ls.dts') data = self._DoReadFileRealDtb('207_fip_ls.dts')
hdr, fents = fip_util.decode_fip(data) hdr, fents = fip_util.decode_fip(data)
tmpdir = None
try: try:
tmpdir, updated_fname = self._SetupImageInTmpdir() tmpdir, updated_fname = self._SetupImageInTmpdir()
with test_util.capture_sys_output() as (stdout, stderr): with test_util.capture_sys_output() as (stdout, stderr):
self._DoBinman('ls', '-i', updated_fname) self._DoBinman('ls', '-i', updated_fname)
finally: finally:
shutil.rmtree(tmpdir) if tmpdir:
shutil.rmtree(tmpdir)
lines = stdout.getvalue().splitlines() lines = stdout.getvalue().splitlines()
expected = [ expected = [
'Name Image-pos Size Entry-type Offset Uncomp-size', 'Name Image-pos Size Entry-type Offset Uncomp-size',
@ -5395,12 +5403,14 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
use_real_dtb=True, use_real_dtb=True,
extra_indirs=[os.path.join(self._indir, TEST_FDT_SUBDIR)]) extra_indirs=[os.path.join(self._indir, TEST_FDT_SUBDIR)])
tmpdir = None
try: try:
tmpdir, updated_fname = self._SetupImageInTmpdir() tmpdir, updated_fname = self._SetupImageInTmpdir()
with test_util.capture_sys_output() as (stdout, stderr): with test_util.capture_sys_output() as (stdout, stderr):
self._RunBinman('ls', '-i', updated_fname) self._RunBinman('ls', '-i', updated_fname)
finally: finally:
shutil.rmtree(tmpdir) if tmpdir:
shutil.rmtree(tmpdir)
def testFitSubentryUsesBintool(self): def testFitSubentryUsesBintool(self):
"""Test that binman FIT subentries can use bintools""" """Test that binman FIT subentries can use bintools"""

View File

@ -119,7 +119,7 @@ class Expr:
"""Set up a new Expr object. """Set up a new Expr object.
Args: Args:
expr (str): String cotaining regular expression to store expr (str): String containing regular expression to store
""" """
self._expr = expr self._expr = expr
self._re = re.compile(expr) self._re = re.compile(expr)

View File

@ -63,6 +63,7 @@ struct display_info {
int types_inc; /* Mask of types that we include (FDT_IS...) */ int types_inc; /* Mask of types that we include (FDT_IS...) */
int types_exc; /* Mask of types that we exclude (FDT_IS...) */ int types_exc; /* Mask of types that we exclude (FDT_IS...) */
int invert; /* Invert polarity of match */ int invert; /* Invert polarity of match */
int props_up; /* Imply properties up to supernodes */
struct value_node *value_head; /* List of values to match */ struct value_node *value_head; /* List of values to match */
const char *output_fname; /* Output filename */ const char *output_fname; /* Output filename */
FILE *fout; /* File to write dts/dtb output */ FILE *fout; /* File to write dts/dtb output */
@ -375,8 +376,9 @@ static int display_fdt_by_regions(struct display_info *disp, const void *blob,
const char *str; const char *str;
int str_base = fdt_off_dt_strings(blob); int str_base = fdt_off_dt_strings(blob);
for (offset = 0; offset < fdt_size_dt_strings(blob); for (offset = 0;
offset += strlen(str) + 1) { offset < (int)fdt_size_dt_strings(blob);
offset += strlen(str) + 1) {
str = fdt_string(blob, offset); str = fdt_string(blob, offset);
int len = strlen(str) + 1; int len = strlen(str) + 1;
int show; int show;
@ -431,7 +433,7 @@ static int dump_fdt_regions(struct display_info *disp, const void *blob,
{ {
struct fdt_header *fdt; struct fdt_header *fdt;
int size, struct_start; int size, struct_start;
int ptr; unsigned int ptr;
int i; int i;
/* Set up a basic header (even if we don't actually write it) */ /* Set up a basic header (even if we don't actually write it) */
@ -575,15 +577,65 @@ static int check_type_include(void *priv, int type, const char *data, int size)
} }
/** /**
* h_include() - Include handler function for fdt_find_regions() * check_props() - Check if a node has properties that we want to include
*
* Calls check_type_include() for each property in the nodn, returning 1 if
* that function returns 1 for any of them
*
* @disp: Display structure, holding info about our options
* @fdt: Devicetree blob to check
* @node: Node offset to check
* @inc: Current value of the 'include' variable (see h_include())
* Return: 0 to exclude, 1 to include, -1 if no information is available
*/
static int check_props(struct display_info *disp, const void *fdt, int node,
int inc)
{
int offset;
for (offset = fdt_first_property_offset(fdt, node);
offset > 0 && inc != 1;
offset = fdt_next_property_offset(fdt, offset)) {
const struct fdt_property *prop;
const char *str;
prop = fdt_get_property_by_offset(fdt, offset, NULL);
if (!prop)
continue;
str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
inc = check_type_include(disp, FDT_NODE_HAS_PROP, str,
strlen(str));
}
/* if requested, check all subnodes for this property too */
if (inc != 1 && disp->props_up) {
int subnode;
for (subnode = fdt_first_subnode(fdt, node);
subnode > 0 && inc != 1;
subnode = fdt_next_subnode(fdt, subnode))
inc = check_props(disp, fdt, subnode, inc);
}
return inc;
}
/**
* h_include() - Include handler function for fdt_first_region()
* *
* This function decides whether to include or exclude a node, property or * This function decides whether to include or exclude a node, property or
* compatible string. The function is defined by fdt_find_regions(). * compatible string. The function is defined by fdt_first_region().
* *
* The algorithm is documented in the code - disp->invert is 0 for normal * The algorithm is documented in the code - disp->invert is 0 for normal
* operation, and 1 to invert the sense of all matches. * operation, and 1 to invert the sense of all matches.
* *
* See * @priv: Private pointer as passed to fdtgrep_find_regions()
* @fdt: Pointer to FDT blob
* @offset: Offset of this node / property
* @type: Type of this part, FDT_IS_...
* @data: Pointer to data (node name, property name, compatible string)
* @size: Size of data, or 0 if none
* Return: 0 to exclude, 1 to include, -1 if no information is available
*/ */
static int h_include(void *priv, const void *fdt, int offset, int type, static int h_include(void *priv, const void *fdt, int offset, int type,
const char *data, int size) const char *data, int size)
@ -610,31 +662,13 @@ static int h_include(void *priv, const void *fdt, int offset, int type,
(disp->types_inc & FDT_NODE_HAS_PROP)) { (disp->types_inc & FDT_NODE_HAS_PROP)) {
debug(" - checking node '%s'\n", debug(" - checking node '%s'\n",
fdt_get_name(fdt, offset, NULL)); fdt_get_name(fdt, offset, NULL));
for (offset = fdt_first_property_offset(fdt, offset); inc = check_props(disp, fdt, offset, inc);
offset > 0 && inc != 1;
offset = fdt_next_property_offset(fdt, offset)) {
const struct fdt_property *prop;
const char *str;
prop = fdt_get_property_by_offset(fdt, offset, NULL);
if (!prop)
continue;
str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
inc = check_type_include(priv, FDT_NODE_HAS_PROP, str,
strlen(str));
}
if (inc == -1) if (inc == -1)
inc = 0; inc = 0;
} }
switch (inc) { if (inc != -1 && disp->invert)
case 1: inc = !inc;
inc = !disp->invert;
break;
case 0:
inc = disp->invert;
break;
}
debug(" - returning %d\n", inc); debug(" - returning %d\n", inc);
return inc; return inc;
@ -683,10 +717,10 @@ static int fdtgrep_find_regions(const void *fdt,
return new_count; return new_count;
} else if (new_count <= max_regions) { } else if (new_count <= max_regions) {
/* /*
* The alias regions will now be at the end of the list. * The alias regions will now be at the end of the list.
* Sort the regions by offset to get things into the * Sort the regions by offset to get things into the
* right order * right order
*/ */
count = new_count; count = new_count;
qsort(region, count, sizeof(struct fdt_region), qsort(region, count, sizeof(struct fdt_region),
h_cmp_region); h_cmp_region);
@ -821,7 +855,7 @@ static int do_fdtgrep(struct display_info *disp, const char *filename)
region, max_regions, path, sizeof(path), region, max_regions, path, sizeof(path),
disp->flags); disp->flags);
if (count < 0) { if (count < 0) {
report_error("fdt_find_regions", count); report_error("fdtgrep_find_regions", count);
free(region); free(region);
return -1; return -1;
} }
@ -880,7 +914,7 @@ static int do_fdtgrep(struct display_info *disp, const char *filename)
size = fdt_totalsize(fdt); size = fdt_totalsize(fdt);
} }
if (size != fwrite(fdt, 1, size, disp->fout)) { if ((size_t)size != fwrite(fdt, 1, size, disp->fout)) {
fprintf(stderr, "Write failure, %d bytes\n", size); fprintf(stderr, "Write failure, %d bytes\n", size);
free(fdt); free(fdt);
ret = 1; ret = 1;
@ -932,9 +966,9 @@ static const char usage_synopsis[] =
case '?': usage("unknown option"); case '?': usage("unknown option");
static const char usage_short_opts[] = static const char usage_short_opts[] =
"haAc:b:C:defg:G:HIlLmn:N:o:O:p:P:rRsStTv" "haAc:b:C:defg:G:HIlLmn:N:o:O:p:P:rRsStTuv"
USAGE_COMMON_SHORT_OPTS; USAGE_COMMON_SHORT_OPTS;
static struct option const usage_long_opts[] = { static const struct option usage_long_opts[] = {
{"show-address", no_argument, NULL, 'a'}, {"show-address", no_argument, NULL, 'a'},
{"colour", no_argument, NULL, 'A'}, {"colour", no_argument, NULL, 'A'},
{"include-node-with-prop", a_argument, NULL, 'b'}, {"include-node-with-prop", a_argument, NULL, 'b'},
@ -952,6 +986,8 @@ static struct option const usage_long_opts[] = {
{"include-mem", no_argument, NULL, 'm'}, {"include-mem", no_argument, NULL, 'm'},
{"include-node", a_argument, NULL, 'n'}, {"include-node", a_argument, NULL, 'n'},
{"exclude-node", a_argument, NULL, 'N'}, {"exclude-node", a_argument, NULL, 'N'},
{"out", a_argument, NULL, 'o'},
{"out-format", a_argument, NULL, 'O'},
{"include-prop", a_argument, NULL, 'p'}, {"include-prop", a_argument, NULL, 'p'},
{"exclude-prop", a_argument, NULL, 'P'}, {"exclude-prop", a_argument, NULL, 'P'},
{"remove-strings", no_argument, NULL, 'r'}, {"remove-strings", no_argument, NULL, 'r'},
@ -960,8 +996,7 @@ static struct option const usage_long_opts[] = {
{"skip-supernodes", no_argument, NULL, 'S'}, {"skip-supernodes", no_argument, NULL, 'S'},
{"show-stringtab", no_argument, NULL, 't'}, {"show-stringtab", no_argument, NULL, 't'},
{"show-aliases", no_argument, NULL, 'T'}, {"show-aliases", no_argument, NULL, 'T'},
{"out", a_argument, NULL, 'o'}, {"props-up-to-supernode", no_argument, NULL, 'u'},
{"out-format", a_argument, NULL, 'O'},
{"invert-match", no_argument, NULL, 'v'}, {"invert-match", no_argument, NULL, 'v'},
USAGE_COMMON_LONG_OPTS, USAGE_COMMON_LONG_OPTS,
}; };
@ -983,6 +1018,8 @@ static const char * const usage_opts_help[] = {
"Include mem_rsvmap section in binary output", "Include mem_rsvmap section in binary output",
"Node to include in grep", "Node to include in grep",
"Node to exclude in grep", "Node to exclude in grep",
"-o <output file>",
"-O <output format>",
"Property to include in grep", "Property to include in grep",
"Property to exclude in grep", "Property to exclude in grep",
"Remove unused strings from string table", "Remove unused strings from string table",
@ -991,8 +1028,7 @@ static const char * const usage_opts_help[] = {
"Don't include supernodes of matching nodes", "Don't include supernodes of matching nodes",
"Include string table in binary output", "Include string table in binary output",
"Include matching aliases in output", "Include matching aliases in output",
"-o <output file>", "Add -p properties to supernodes too",
"-O <output format>",
"Invert the sense of matching (select non-matching lines)", "Invert the sense of matching (select non-matching lines)",
USAGE_COMMON_OPTS_HELP USAGE_COMMON_OPTS_HELP
}; };
@ -1124,6 +1160,9 @@ static void scan_args(struct display_info *disp, int argc, char *argv[])
case 'H': case 'H':
disp->header = 1; disp->header = 1;
break; break;
case 'I':
disp->show_dts_version = 1;
break;
case 'l': case 'l':
disp->region_list = 1; disp->region_list = 1;
break; break;
@ -1176,12 +1215,12 @@ static void scan_args(struct display_info *disp, int argc, char *argv[])
case 'T': case 'T':
disp->add_aliases = 1; disp->add_aliases = 1;
break; break;
case 'u':
disp->props_up = 1;
break;
case 'v': case 'v':
disp->invert = 1; disp->invert = 1;
break; break;
case 'I':
disp->show_dts_version = 1;
break;
} }
if (type && value_add(disp, &disp->value_head, type, inc, if (type && value_add(disp, &disp->value_head, type, inc,