util/cbfstool: Add optional argument ibb

* Mark files in CBFS as IBB (Initial BootBlock)
* Will be used to identify the IBB by any TEE

Change-Id: Idb4857c894b9ee1edc464c0a1216cdda29937bbd
Signed-off-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/29744
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/payloads/libpayload/include/cbfs_core.h b/payloads/libpayload/include/cbfs_core.h
index a707154..ad1e9e2 100644
--- a/payloads/libpayload/include/cbfs_core.h
+++ b/payloads/libpayload/include/cbfs_core.h
@@ -144,6 +144,7 @@
 #define CBFS_FILE_ATTR_TAG_UNUSED2 0xffffffff
 #define CBFS_FILE_ATTR_TAG_COMPRESSION 0x42435a4c
 #define CBFS_FILE_ATTR_TAG_HASH 0x68736148
+#define CBFS_FILE_ATTR_TAG_IBB 0x32494242 /* Initial BootBlock */
 
 /* The common fields of extended cbfs file attributes.
    Attributes are expected to start with tag/len, then append their
diff --git a/src/commonlib/include/commonlib/cbfs_serialized.h b/src/commonlib/include/commonlib/cbfs_serialized.h
index 6e254f6..a4708e8 100644
--- a/src/commonlib/include/commonlib/cbfs_serialized.h
+++ b/src/commonlib/include/commonlib/cbfs_serialized.h
@@ -157,6 +157,7 @@
 #define CBFS_FILE_ATTR_TAG_HASH 0x68736148
 #define CBFS_FILE_ATTR_TAG_POSITION 0x42435350  /* PSCB */
 #define CBFS_FILE_ATTR_TAG_ALIGNMENT 0x42434c41 /* ALCB */
+#define CBFS_FILE_ATTR_TAG_IBB 0x32494242 /* Initial BootBlock */
 
 struct cbfs_file_attr_compression {
 	uint32_t tag;
diff --git a/util/cbfstool/cbfs.h b/util/cbfstool/cbfs.h
index b082d8c..4bc95ab 100644
--- a/util/cbfstool/cbfs.h
+++ b/util/cbfstool/cbfs.h
@@ -106,6 +106,7 @@
 #define CBFS_FILE_ATTR_TAG_POSITION 0x42435350 /* PSCB */
 #define CBFS_FILE_ATTR_TAG_ALIGNMENT 0x42434c41 /* ALCB */
 #define CBFS_FILE_ATTR_TAG_PADDING 0x47444150 /* PDNG */
+#define CBFS_FILE_ATTR_TAG_IBB 0x32494242 /* Initial BootBlock */
 
 struct cbfs_file_attr_compression {
 	uint32_t tag;
diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c
index 5cbe1f1..452c9d9 100644
--- a/util/cbfstool/cbfs_image.c
+++ b/util/cbfstool/cbfs_image.c
@@ -3,6 +3,8 @@
  *
  * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
  * Copyright (C) 2016 Siemens AG. All rights reserved.
+ * Copyright (C) 2019 9elements Agency GmbH
+ * Copyright (C) 2019 Facebook Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -656,7 +658,8 @@
 			     struct cbfs_file *entry,
 			     const void *data,
 			     uint32_t content_offset,
-			     const struct cbfs_file *header)
+			     const struct cbfs_file *header,
+			     const size_t len_align)
 {
 	struct cbfs_file *next = cbfs_find_next_entry(image, entry);
 	uint32_t addr = cbfs_get_entry_addr(image, entry),
@@ -708,6 +711,13 @@
 	memcpy(CBFS_SUBHEADER(entry), data, ntohl(entry->len));
 	if (verbose > 1) cbfs_print_entry_info(image, entry, stderr);
 
+	// Align the length to a multiple of len_align
+	if (len_align &&
+	    ((ntohl(entry->offset) + ntohl(entry->len)) % len_align)) {
+		size_t off = (ntohl(entry->offset) + ntohl(entry->len)) % len_align;
+		entry->len = htonl(ntohl(entry->len) + len_align - off);
+	}
+
 	// Process buffer AFTER entry.
 	entry = cbfs_find_next_entry(image, entry);
 	addr = cbfs_get_entry_addr(image, entry);
@@ -738,7 +748,8 @@
 
 int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer,
 		   uint32_t content_offset,
-		   struct cbfs_file *header)
+		   struct cbfs_file *header,
+		   const size_t len_align)
 {
 	assert(image);
 	assert(buffer);
@@ -812,7 +823,7 @@
 		      addr, addr_next - addr, content_offset);
 
 		if (cbfs_add_entry_at(image, entry, buffer->data,
-				      content_offset, header) == 0) {
+				      content_offset, header, len_align) == 0) {
 			return 0;
 		}
 		break;
diff --git a/util/cbfstool/cbfs_image.h b/util/cbfstool/cbfs_image.h
index 1f8b162..1bb3c68 100644
--- a/util/cbfstool/cbfs_image.h
+++ b/util/cbfstool/cbfs_image.h
@@ -106,7 +106,8 @@
  * Never pass this function a top-aligned address: convert it to an offset.
  * Returns 0 on success, otherwise non-zero. */
 int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer,
-		   uint32_t content_offset, struct cbfs_file *header);
+		   uint32_t content_offset, struct cbfs_file *header,
+		   const size_t len_align);
 
 /* Removes an entry from CBFS image. Returns 0 on success, otherwise non-zero. */
 int cbfs_remove_entry(struct cbfs_image *image, const char *name);
diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c
index 54b5f65..65c5e08 100644
--- a/util/cbfstool/cbfstool.c
+++ b/util/cbfstool/cbfstool.c
@@ -5,6 +5,8 @@
  *                 written by Patrick Georgi <patrick.georgi@coresystems.de>
  * Copyright (C) 2012 Google, Inc.
  * Copyright (C) 2016 Siemens AG
+ * Copyright (C) 2019 9elements Agency GmbH
+ * Copyright (C) 2019 Facebook Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -83,6 +85,7 @@
 	bool autogen_attr;
 	bool machine_parseable;
 	bool unprocessed;
+	bool ibb;
 	enum comp_algo compression;
 	int precompression;
 	enum vb2_hash_algorithm hash;
@@ -249,7 +252,7 @@
 
 	header = cbfs_create_file_header(CBFS_COMPONENT_RAW,
 		buffer.size, name);
-	if (cbfs_add_entry(&image, &buffer, offset, header) != 0) {
+	if (cbfs_add_entry(&image, &buffer, offset, header, 0) != 0) {
 		ERROR("Failed to add %llu into ROM image as '%s'.\n",
 					(long long unsigned)u64val, name);
 		goto done;
@@ -364,7 +367,7 @@
 
 	header = cbfs_create_file_header(CBFS_COMPONENT_CBFSHEADER,
 		buffer_size(&buffer), name);
-	if (cbfs_add_entry(&image, &buffer, 0, header) != 0) {
+	if (cbfs_add_entry(&image, &buffer, 0, header, 0) != 0) {
 		ERROR("Failed to add cbfs master header into ROM image.\n");
 		goto done;
 	}
@@ -448,6 +451,8 @@
 			      uint32_t headeroffset,
 			      convert_buffer_t convert)
 {
+	size_t len_align = 0;
+
 	if (!filename) {
 		ERROR("You need to specify -f/--filename.\n");
 		return 1;
@@ -539,6 +544,17 @@
 		}
 	}
 
+	if (param.ibb) {
+		/* Mark as Initial Boot Block */
+		struct cbfs_file_attribute *attrs = cbfs_add_file_attr(header,
+				CBFS_FILE_ATTR_TAG_IBB,
+				sizeof(struct cbfs_file_attribute));
+		if (attrs == NULL)
+			return -1;
+		/* For Intel TXT minimum align is 16 */
+		len_align = 16;
+	}
+
 	if (param.padding) {
 		const uint32_t hs = sizeof(struct cbfs_file_attribute);
 		uint32_t size = MAX(hs, param.padding);
@@ -554,7 +570,7 @@
 	if (IS_TOP_ALIGNED_ADDRESS(offset))
 		offset = convert_to_from_top_aligned(param.image_region,
 								-offset);
-	if (cbfs_add_entry(&image, &buffer, offset, header) != 0) {
+	if (cbfs_add_entry(&image, &buffer, offset, header, len_align) != 0) {
 		ERROR("Failed to add '%s' into ROM image.\n", filename);
 		free(header);
 		buffer_delete(&buffer);
@@ -1277,6 +1293,11 @@
 	{"truncate", "r:h?", cbfs_truncate, true, true},
 };
 
+enum {
+	/* begin after ASCII characters */
+	LONGOPT_IBB = 256,
+};
+
 static struct option long_options[] = {
 	{"alignment",     required_argument, 0, 'a' },
 	{"base-address",  required_argument, 0, 'b' },
@@ -1315,6 +1336,7 @@
 	{"gen-attribute", no_argument,       0, 'g' },
 	{"mach-parseable",no_argument,       0, 'k' },
 	{"unprocessed",   no_argument,       0, 'U' },
+	{"ibb",           no_argument,       0, LONGOPT_IBB },
 	{NULL,            0,                 0,  0  }
 };
 
@@ -1388,7 +1410,7 @@
 	     " add [-r image,regions] -f FILE -n NAME -t TYPE [-A hash] \\\n"
 	     "        [-c compression] [-b base-address | -a alignment] \\\n"
 	     "        [-p padding size] [-y|--xip if TYPE is FSP]       \\\n"
-	     "        [-j topswap-size] (Intel CPUs only)                   "
+	     "        [-j topswap-size] (Intel CPUs only) [--ibb]           "
 			"Add a component\n"
 	     "                                                         "
 	     "    -j valid size: 0x10000 0x20000 0x40000 0x80000 0x100000 \n"
@@ -1398,7 +1420,7 @@
 			"Add a payload to the ROM\n"
 	     " add-stage [-r image,regions] -f FILE -n NAME [-A hash] \\\n"
 	     "        [-c compression] [-b base] [-S section-to-ignore] \\\n"
-	     "        [-a alignment] [-y|--xip] [-P page-size]             "
+	     "        [-a alignment] [-y|--xip] [-P page-size] [--ibb]     "
 			"Add a stage to the ROM\n"
 	     " add-flat-binary [-r image,regions] -f FILE -n NAME \\\n"
 	     "        [-A hash] -l load-address -e entry-point \\\n"
@@ -1709,6 +1731,9 @@
 			case 'U':
 				param.unprocessed = true;
 				break;
+			case LONGOPT_IBB:
+				param.ibb = true;
+				break;
 			case 'h':
 			case '?':
 				usage(argv[0]);