mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-31 03:58:17 +00:00 
			
		
		
		
	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:
		
						commit
						dffa6d0210
					
				| @ -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; | ||||||
| 				}; | 				}; | ||||||
| 			}; | 			}; | ||||||
| 		}; | 		}; | ||||||
|  | |||||||
| @ -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); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -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); | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
| @ -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 | ||||||
|  * |  * | ||||||
|  | |||||||
| @ -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 \
 | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
							
								
								
									
										105
									
								
								test/bloblist.c
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								test/bloblist.c
									
									
									
									
									
								
							| @ -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) - | ||||||
|  | |||||||
| @ -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""" | ||||||
|  | |||||||
| @ -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) | ||||||
|  | |||||||
							
								
								
									
										123
									
								
								tools/fdtgrep.c
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								tools/fdtgrep.c
									
									
									
									
									
								
							| @ -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, | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user