layout: Introduce flashrom_layout_new()

It initializes an empty layout. Currently the maximum number of entries
has to be specified, which will vanish once we use dynamic allocation
per entry.

We replace the two special cases `single_layout` and `ich_layout` with
dynamically allocated layouts. As a result, we have to take care to
release the `default_layout` in a flashctx once we are done with it.

Change-Id: I2ae7246493ff592e631cce924777925c7825e398
Signed-off-by: Nico Huber <nico.h@gmx.de>
Original-Reviewed-on: https://review.coreboot.org/c/flashrom/+/33543
Original-Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Original-Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/flashrom-stable/+/72214
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/layout.c b/layout.c
index e2acd77..f7f68b3 100644
--- a/layout.c
+++ b/layout.c
@@ -37,7 +37,7 @@
 	if (flashctx->layout && flashctx->layout->num_entries)
 		return flashctx->layout;
 	else
-		return &flashctx->fallback_layout.base;
+		return flashctx->default_layout;
 }
 
 static struct romentry *mutable_layout_next(
@@ -275,6 +275,32 @@
  */
 
 /**
+ * @brief Create a new, empty layout.
+ *
+ * @param layout Pointer to returned layout reference.
+ * @param count  Number of layout entries to allocate.
+ *
+ * @return 0 on success,
+ *         1 if out of memory.
+ */
+int flashrom_layout_new(struct flashrom_layout **const layout, const unsigned int count)
+{
+	*layout = malloc(sizeof(**layout) + count * sizeof(struct romentry));
+	if (!*layout) {
+		msg_gerr("Error creating layout: %s\n", strerror(errno));
+		return 1;
+	}
+
+	const struct flashrom_layout tmp = {
+		.entries	= (void *)((char *)*layout + sizeof(**layout)),
+		.capacity	= count,
+		.num_entries	= 0,
+	};
+	**layout = tmp;
+	return 0;
+}
+
+/**
  * @brief Add another region to an existing layout.
  *
  * @param layout The existing layout.