smbios: Use a struct to keep track of context

At present we pass the ofnode to each function. We also pass the 'eos'
pointer for adding new strings. We don't track the current end of the
string table, so have smbios_string_table_len() to find that.

The code can be made more efficient if it keeps information in a
context struct. This also makes it easier to add more features.

As a first step, switch the ofnode parameter to be a context pointer.
Update smbios_add_prop() at the same time to avoid changing the same
lines of code in consecutive patches.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
diff --git a/lib/smbios.c b/lib/smbios.c
index a072d9e..4d2cb0f 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -18,14 +18,26 @@
 #endif
 
 /**
+ * struct smbios_ctx - context for writing SMBIOS tables
+ *
+ * @node:	node containing the information to write (ofnode_null() if none)
+ * @dev:	sysinfo device to use (NULL if none)
+ */
+struct smbios_ctx {
+	ofnode node;
+	struct udevice *dev;
+};
+
+/**
  * Function prototype to write a specific type of SMBIOS structure
  *
  * @addr:	start address to write the structure
  * @handle:	the structure's handle, a unique 16-bit number
- * @node:	node containing the information to write (ofnode_null() if none)
+ * @ctx:	context for writing the tables
  * @return:	size of the structure
  */
-typedef int (*smbios_write_type)(ulong *addr, int handle, ofnode node);
+typedef int (*smbios_write_type)(ulong *addr, int handle,
+				 struct smbios_ctx *ctx);
 
 /**
  * struct smbios_write_method - Information about a table-writing function
@@ -78,17 +90,18 @@
  * smbios_add_prop() - Add a property from the device tree
  *
  * @start:	string area start address
- * @node:	node containing the information to write (ofnode_null() if none)
+ * @ctx:	context for writing the tables
  * @prop:	property to write
  * @return 0 if not found, else SMBIOS string number (1 or more)
  */
-static int smbios_add_prop(char *start, ofnode node, const char *prop)
+static int smbios_add_prop(char *start, struct smbios_ctx *ctx,
+			   const char *prop)
 {
 
 	if (IS_ENABLED(CONFIG_OF_CONTROL)) {
 		const char *str;
 
-		str = ofnode_read_string(node, prop);
+		str = ofnode_read_string(ctx->node, prop);
 		if (str)
 			return smbios_add_string(start, str);
 	}
@@ -118,7 +131,8 @@
 	return len + 1;
 }
 
-static int smbios_write_type0(ulong *current, int handle, ofnode node)
+static int smbios_write_type0(ulong *current, int handle,
+			      struct smbios_ctx *ctx)
 {
 	struct smbios_type0 *t;
 	int len = sizeof(struct smbios_type0);
@@ -156,7 +170,8 @@
 	return len;
 }
 
-static int smbios_write_type1(ulong *current, int handle, ofnode node)
+static int smbios_write_type1(ulong *current, int handle,
+			      struct smbios_ctx *ctx)
 {
 	struct smbios_type1 *t;
 	int len = sizeof(struct smbios_type1);
@@ -165,17 +180,17 @@
 	t = map_sysmem(*current, len);
 	memset(t, 0, sizeof(struct smbios_type1));
 	fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
-	t->manufacturer = smbios_add_prop(t->eos, node, "manufacturer");
-	t->product_name = smbios_add_prop(t->eos, node, "product");
-	t->version = smbios_add_prop(t->eos, node, "version");
+	t->manufacturer = smbios_add_prop(t->eos, ctx, "manufacturer");
+	t->product_name = smbios_add_prop(t->eos, ctx, "product");
+	t->version = smbios_add_prop(t->eos, ctx, "version");
 	if (serial_str) {
 		t->serial_number = smbios_add_string(t->eos, serial_str);
 		strncpy((char *)t->uuid, serial_str, sizeof(t->uuid));
 	} else {
-		t->serial_number = smbios_add_prop(t->eos, node, "serial");
+		t->serial_number = smbios_add_prop(t->eos, ctx, "serial");
 	}
-	t->sku_number = smbios_add_prop(t->eos, node, "sku");
-	t->family = smbios_add_prop(t->eos, node, "family");
+	t->sku_number = smbios_add_prop(t->eos, ctx, "sku");
+	t->family = smbios_add_prop(t->eos, ctx, "family");
 
 	len = t->length + smbios_string_table_len(t->eos);
 	*current += len;
@@ -184,7 +199,8 @@
 	return len;
 }
 
-static int smbios_write_type2(ulong *current, int handle, ofnode node)
+static int smbios_write_type2(ulong *current, int handle,
+			      struct smbios_ctx *ctx)
 {
 	struct smbios_type2 *t;
 	int len = sizeof(struct smbios_type2);
@@ -192,9 +208,9 @@
 	t = map_sysmem(*current, len);
 	memset(t, 0, sizeof(struct smbios_type2));
 	fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
-	t->manufacturer = smbios_add_prop(t->eos, node, "manufacturer");
-	t->product_name = smbios_add_prop(t->eos, node, "product");
-	t->asset_tag_number = smbios_add_prop(t->eos, node, "asset-tag");
+	t->manufacturer = smbios_add_prop(t->eos, ctx, "manufacturer");
+	t->product_name = smbios_add_prop(t->eos, ctx, "product");
+	t->asset_tag_number = smbios_add_prop(t->eos, ctx, "asset-tag");
 	t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING;
 	t->board_type = SMBIOS_BOARD_MOTHERBOARD;
 
@@ -205,7 +221,8 @@
 	return len;
 }
 
-static int smbios_write_type3(ulong *current, int handle, ofnode node)
+static int smbios_write_type3(ulong *current, int handle,
+			      struct smbios_ctx *ctx)
 {
 	struct smbios_type3 *t;
 	int len = sizeof(struct smbios_type3);
@@ -213,7 +230,7 @@
 	t = map_sysmem(*current, len);
 	memset(t, 0, sizeof(struct smbios_type3));
 	fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle);
-	t->manufacturer = smbios_add_prop(t->eos, node, "manufacturer");
+	t->manufacturer = smbios_add_prop(t->eos, ctx, "manufacturer");
 	t->chassis_type = SMBIOS_ENCLOSURE_DESKTOP;
 	t->bootup_state = SMBIOS_STATE_SAFE;
 	t->power_supply_state = SMBIOS_STATE_SAFE;
@@ -227,7 +244,8 @@
 	return len;
 }
 
-static void smbios_write_type4_dm(struct smbios_type4 *t, ofnode node)
+static void smbios_write_type4_dm(struct smbios_type4 *t,
+				  struct smbios_ctx *ctx)
 {
 	u16 processor_family = SMBIOS_PROCESSOR_FAMILY_UNKNOWN;
 	const char *vendor = "Unknown";
@@ -259,7 +277,8 @@
 	t->processor_version = smbios_add_string(t->eos, name);
 }
 
-static int smbios_write_type4(ulong *current, int handle, ofnode node)
+static int smbios_write_type4(ulong *current, int handle,
+			      struct smbios_ctx *ctx)
 {
 	struct smbios_type4 *t;
 	int len = sizeof(struct smbios_type4);
@@ -268,7 +287,7 @@
 	memset(t, 0, sizeof(struct smbios_type4));
 	fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle);
 	t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL;
-	smbios_write_type4_dm(t, node);
+	smbios_write_type4_dm(t, ctx);
 	t->status = SMBIOS_PROCESSOR_STATUS_ENABLED;
 	t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE;
 	t->l1_cache_handle = 0xffff;
@@ -283,7 +302,8 @@
 	return len;
 }
 
-static int smbios_write_type32(ulong *current, int handle, ofnode node)
+static int smbios_write_type32(ulong *current, int handle,
+			       struct smbios_ctx *ctx)
 {
 	struct smbios_type32 *t;
 	int len = sizeof(struct smbios_type32);
@@ -298,7 +318,8 @@
 	return len;
 }
 
-static int smbios_write_type127(ulong *current, int handle, ofnode node)
+static int smbios_write_type127(ulong *current, int handle,
+				struct smbios_ctx *ctx)
 {
 	struct smbios_type127 *t;
 	int len = sizeof(struct smbios_type127);
@@ -327,7 +348,7 @@
 {
 	ofnode parent_node = ofnode_null();
 	struct smbios_entry *se;
-	struct udevice *dev;
+	struct smbios_ctx ctx;
 	ulong table_addr;
 	ulong tables;
 	int len = 0;
@@ -337,10 +358,13 @@
 	int isize;
 	int i;
 
+	ctx.node = ofnode_null();
 	if (IS_ENABLED(CONFIG_OF_CONTROL)) {
-		uclass_first_device(UCLASS_SYSINFO, &dev);
-		if (dev)
-			parent_node = dev_read_subnode(dev, "smbios");
+		uclass_first_device(UCLASS_SYSINFO, &ctx.dev);
+		if (ctx.dev)
+			parent_node = dev_read_subnode(ctx.dev, "smbios");
+	} else {
+		ctx.dev = NULL;
 	}
 
 	/* 16 byte align the table address */
@@ -356,14 +380,13 @@
 	/* populate minimum required tables */
 	for (i = 0; i < ARRAY_SIZE(smbios_write_funcs); i++) {
 		const struct smbios_write_method *method;
-		ofnode node = ofnode_null();
 		int tmp;
 
 		method = &smbios_write_funcs[i];
 		if (IS_ENABLED(CONFIG_OF_CONTROL) && method->subnode_name)
-			node = ofnode_find_subnode(parent_node,
-						   method->subnode_name);
-		tmp = method->write((ulong *)&addr, handle++, node);
+			ctx.node = ofnode_find_subnode(parent_node,
+						       method->subnode_name);
+		tmp = method->write((ulong *)&addr, handle++, &ctx);
 
 		max_struct_size = max(max_struct_size, tmp);
 		len += tmp;