DT: Add ibm,firmware-versions node

Message ID 20170707090342.6167-1-hegdevasant@linux.vnet.ibm.com
State Superseded
Headers show

Commit Message

Vasant Hegde July 7, 2017, 9:03 a.m.
In P8, hostboot provides mini device tree. It contains /ibm,firmware-versions
node which has various firmware component version details.

In P9, OPAL is building device tree. This patch adds support to parse VERSION
section of PNOR and create "/ibm,firmware-versions" device tree node.

Sample output:
	/sys/firmware/devicetree/base/ibm,firmware-versions # lsprop .
	occ              "6a00709"
	skiboot          "v5.7-rc1-p344fb62"
	buildroot        "2017.02.2-7-g23118ce"
	capp-ucode       "9c73e9f"
	petitboot        "v1.4.3-p98b6d83"
	sbe              "02021c6"
	open-power       "witherspoon-v1.17-128-gf1b53c7-dirty"
	....
	....

Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Signed-off-by: Mukesh Ojha <mukesh02@linux.vnet.ibm.com>
---
 core/flash.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)

Comments

Vaidyanathan Srinivasan July 7, 2017, 9:17 a.m. | #1
* Vasant Hegde <hegdevasant@linux.vnet.ibm.com> [2017-07-07 14:33:42]:

> In P8, hostboot provides mini device tree. It contains /ibm,firmware-versions
> node which has various firmware component version details.
> 
> In P9, OPAL is building device tree. This patch adds support to parse VERSION
> section of PNOR and create "/ibm,firmware-versions" device tree node.
> 
> Sample output:
> 	/sys/firmware/devicetree/base/ibm,firmware-versions # lsprop .
> 	occ              "6a00709"
> 	skiboot          "v5.7-rc1-p344fb62"
> 	buildroot        "2017.02.2-7-g23118ce"
> 	capp-ucode       "9c73e9f"
> 	petitboot        "v1.4.3-p98b6d83"
> 	sbe              "02021c6"
> 	open-power       "witherspoon-v1.17-128-gf1b53c7-dirty"
> 	....
> 	....
> 
> Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
> Signed-off-by: Mukesh Ojha <mukesh02@linux.vnet.ibm.com>
> ---
>  core/flash.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 102 insertions(+)
> 
> diff --git a/core/flash.c b/core/flash.c
> index 8a908e5..219e6e0 100644
> --- a/core/flash.c
> +++ b/core/flash.c
> @@ -148,6 +148,107 @@ out:
>  	return rc;
>  }
>  
> +static void flash_dt_add_fw_version(struct dt_node *fw_version, char* data)
> +{
> +	char *prop;
> +	int version_len, i;
> +	int len = strlen(data);
> +	const char * version_str[] = {"open-power", "buildroot", "skiboot",
> +				      "hostboot-binaries", "hostboot", "linux",
> +				      "petitboot", "occ", "capp-ucode", "sbe"};
> +	/*
> +	 * PNOR version strings are not easily consumable. Split them into
> +	 * property, value.
> +	 *
> +	 * Example input from PNOR :
> +	 *   "open-power-firestone-v1.8"
> +	 *   "linux-4.4.6-openpower1-8420e0f"
> +	 *

How about we make a dtb and push it into VERSION partition and just
pull it out?

We should not parse strings and make a key-value pair.  The format
in VERSION partition itself could ideally change to something that is
a key-value pair or something that is consumable and does not require
string parsing.

--Vaidy
Samuel Mendoza-Jonas July 11, 2017, 5:37 a.m. | #2
On Fri, 2017-07-07 at 14:47 +0530, Vaidyanathan Srinivasan wrote:
> * Vasant Hegde <hegdevasant@linux.vnet.ibm.com> [2017-07-07 14:33:42]:
> 
> > In P8, hostboot provides mini device tree. It contains /ibm,firmware-versions
> > node which has various firmware component version details.
> > 
> > In P9, OPAL is building device tree. This patch adds support to parse VERSION
> > section of PNOR and create "/ibm,firmware-versions" device tree node.
> > 
> > Sample output:
> > 	/sys/firmware/devicetree/base/ibm,firmware-versions # lsprop .
> > 	occ              "6a00709"
> > 	skiboot          "v5.7-rc1-p344fb62"
> > 	buildroot        "2017.02.2-7-g23118ce"
> > 	capp-ucode       "9c73e9f"
> > 	petitboot        "v1.4.3-p98b6d83"
> > 	sbe              "02021c6"
> > 	open-power       "witherspoon-v1.17-128-gf1b53c7-dirty"
> > 	....
> > 	....
> > 
> > Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
> > Signed-off-by: Mukesh Ojha <mukesh02@linux.vnet.ibm.com>
> > ---
> >  core/flash.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 102 insertions(+)
> > 
> > diff --git a/core/flash.c b/core/flash.c
> > index 8a908e5..219e6e0 100644
> > --- a/core/flash.c
> > +++ b/core/flash.c
> > @@ -148,6 +148,107 @@ out:
> >  	return rc;
> >  }
> >  
> > +static void flash_dt_add_fw_version(struct dt_node *fw_version, char* data)
> > +{
> > +	char *prop;
> > +	int version_len, i;
> > +	int len = strlen(data);
> > +	const char * version_str[] = {"open-power", "buildroot", "skiboot",
> > +				      "hostboot-binaries", "hostboot", "linux",
> > +				      "petitboot", "occ", "capp-ucode", "sbe"};
> > +	/*
> > +	 * PNOR version strings are not easily consumable. Split them into
> > +	 * property, value.
> > +	 *
> > +	 * Example input from PNOR :
> > +	 *   "open-power-firestone-v1.8"
> > +	 *   "linux-4.4.6-openpower1-8420e0f"
> > +	 *
> 
> How about we make a dtb and push it into VERSION partition and just
> pull it out?

That could be a bit complicated since I'm fairly sure most BMCs read this
partition and dump it out when processing `ipmitool fru list foo`, etc.

> 
> We should not parse strings and make a key-value pair.  The format
> in VERSION partition itself could ideally change to something that is
> a key-value pair or something that is consumable and does not require
> string parsing.

I agree that a more consumable format would be great however!

> 
> --Vaidy
> 
> _______________________________________________
> Skiboot mailing list
> Skiboot@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
Samuel Mendoza-Jonas Aug. 11, 2017, 5:04 a.m. | #3
On Fri, 2017-07-07 at 14:33 +0530, Vasant Hegde wrote:
> In P8, hostboot provides mini device tree. It contains /ibm,firmware-versions
> node which has various firmware component version details.
> 
> In P9, OPAL is building device tree. This patch adds support to parse VERSION
> section of PNOR and create "/ibm,firmware-versions" device tree node.
> 
> Sample output:
> 	/sys/firmware/devicetree/base/ibm,firmware-versions # lsprop .
> 	occ              "6a00709"
> 	skiboot          "v5.7-rc1-p344fb62"
> 	buildroot        "2017.02.2-7-g23118ce"
> 	capp-ucode       "9c73e9f"
> 	petitboot        "v1.4.3-p98b6d83"
> 	sbe              "02021c6"
> 	open-power       "witherspoon-v1.17-128-gf1b53c7-dirty"
> 	....
> 	....
> 
> Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
> Signed-off-by: Mukesh Ojha <mukesh02@linux.vnet.ibm.com>

Acked-By: Samuel Mendoza-Jonas <sam@mendozajonas.com>

> ---
>  core/flash.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 102 insertions(+)
> 
> diff --git a/core/flash.c b/core/flash.c
> index 8a908e5..219e6e0 100644
> --- a/core/flash.c
> +++ b/core/flash.c
> @@ -148,6 +148,107 @@ out:
>  	return rc;
>  }
>  
> +static void flash_dt_add_fw_version(struct dt_node *fw_version, char* data)
> +{
> +	char *prop;
> +	int version_len, i;
> +	int len = strlen(data);
> +	const char * version_str[] = {"open-power", "buildroot", "skiboot",
> +				      "hostboot-binaries", "hostboot", "linux",
> +				      "petitboot", "occ", "capp-ucode", "sbe"};
> +	/*
> +	 * PNOR version strings are not easily consumable. Split them into
> +	 * property, value.
> +	 *
> +	 * Example input from PNOR :
> +	 *   "open-power-firestone-v1.8"
> +	 *   "linux-4.4.6-openpower1-8420e0f"
> +	 *
> +	 * Desired output in device tree:
> +	 *   open-power = "firestone-v1.8";
> +	 *   linux = "4.4.6-openpower1-8420e0f";
> +	 */
> +	for(i = 0; i < ARRAY_SIZE(version_str); i++)
> +	{
> +		version_len = strlen(version_str[i]);
> +		if (len < version_len)
> +			continue;
> +
> +		if (memcmp(data, version_str[i], version_len) != 0)
> +			continue;
> +
> +		/* Found a match, add property */
> +		if (dt_find_property(fw_version, version_str[i]))
> +			continue;
> +
> +		/* Increment past "key-" */
> +		prop = data + version_len + 1;
> +		dt_add_property_string(fw_version, version_str[i], prop);
> +	}
> +}
> +
> +static int flash_fw_version_probe(struct flash *flash, struct ffs_handle *ffs)
> +{
> +	bool ecc;
> +	char *buf;
> +	uint8_t version_data[80];
> +	int rc;
> +	int numbytes = 0, i = 0;
> +	uint32_t start, size, part, version_size;
> +	struct dt_node *fw_version;
> +
> +	if (proc_gen < proc_gen_p9)
> +		return 0;
> +
> +	prlog(PR_INFO, "FLASH: probing for VERSION\n");
> +
> +	rc = ffs_lookup_part(ffs, "VERSION", &part);
> +	if (rc) {
> +		prlog(PR_WARNING, "FLASH: No VERSION partition found\n");
> +		return OPAL_HARDWARE;
> +	}
> +
> +	rc = ffs_part_info(ffs, part, NULL, &start, &size, NULL, &ecc);
> +	if (rc) {
> +		prlog(PR_WARNING, "FLASH: Can't parse ffs info for VERSION\n");
> +		return OPAL_HARDWARE;
> +	}
> +
> +	buf = malloc(size);
> +	if (!buf) {
> +                prlog(PR_WARNING, "FLASH: Failed to allocate memory\n");
> +		return OPAL_RESOURCE;
> +	}
> +
> +	rc = blocklevel_read(flash->bl, start, buf, size);
> +	if (rc) {
> +		prlog(PR_WARNING, "FLASH: Couldn't read from flash at 0x%08x "
> +		      "for len 0x%08x [rc = %d]\n", start, size, rc);
> +		return rc;
> +	}
> +
> +	version_size = ecc ? ecc_buffer_size_minus_ecc(size) : size;
> +	fw_version = dt_new(dt_root, "ibm,firmware-versions");
> +	assert(fw_version);
> +
> +	for ( ; (numbytes < version_size) && buf[numbytes]; numbytes++) {
> +		if (buf[numbytes] == '\n') {
> +			version_data[i] = '\0';
> +			flash_dt_add_fw_version(fw_version, version_data);
> +			memset(version_data, 0, sizeof(version_data));
> +			i = 0;
> +			continue;
> +		} else if (buf[numbytes] == '\t') {
> +			continue; /* skip tabs */
> +		}
> +
> +		version_data[i++] = buf[numbytes];
> +	}
> +
> +	free(buf);
> +	return 0;
> +}
> +
>  static int flash_nvram_probe(struct flash *flash, struct ffs_handle *ffs)
>  {
>  	uint32_t start, size, part;
> @@ -238,6 +339,7 @@ static void setup_system_flash(struct flash *flash, struct dt_node *node,
>  
>  	prlog(PR_INFO, "FLASH: registered system flash device %s\n", name);
>  
> +	flash_fw_version_probe(flash, ffs);
>  	flash_nvram_probe(flash, ffs);
>  }
>

Patch

diff --git a/core/flash.c b/core/flash.c
index 8a908e5..219e6e0 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -148,6 +148,107 @@  out:
 	return rc;
 }
 
+static void flash_dt_add_fw_version(struct dt_node *fw_version, char* data)
+{
+	char *prop;
+	int version_len, i;
+	int len = strlen(data);
+	const char * version_str[] = {"open-power", "buildroot", "skiboot",
+				      "hostboot-binaries", "hostboot", "linux",
+				      "petitboot", "occ", "capp-ucode", "sbe"};
+	/*
+	 * PNOR version strings are not easily consumable. Split them into
+	 * property, value.
+	 *
+	 * Example input from PNOR :
+	 *   "open-power-firestone-v1.8"
+	 *   "linux-4.4.6-openpower1-8420e0f"
+	 *
+	 * Desired output in device tree:
+	 *   open-power = "firestone-v1.8";
+	 *   linux = "4.4.6-openpower1-8420e0f";
+	 */
+	for(i = 0; i < ARRAY_SIZE(version_str); i++)
+	{
+		version_len = strlen(version_str[i]);
+		if (len < version_len)
+			continue;
+
+		if (memcmp(data, version_str[i], version_len) != 0)
+			continue;
+
+		/* Found a match, add property */
+		if (dt_find_property(fw_version, version_str[i]))
+			continue;
+
+		/* Increment past "key-" */
+		prop = data + version_len + 1;
+		dt_add_property_string(fw_version, version_str[i], prop);
+	}
+}
+
+static int flash_fw_version_probe(struct flash *flash, struct ffs_handle *ffs)
+{
+	bool ecc;
+	char *buf;
+	uint8_t version_data[80];
+	int rc;
+	int numbytes = 0, i = 0;
+	uint32_t start, size, part, version_size;
+	struct dt_node *fw_version;
+
+	if (proc_gen < proc_gen_p9)
+		return 0;
+
+	prlog(PR_INFO, "FLASH: probing for VERSION\n");
+
+	rc = ffs_lookup_part(ffs, "VERSION", &part);
+	if (rc) {
+		prlog(PR_WARNING, "FLASH: No VERSION partition found\n");
+		return OPAL_HARDWARE;
+	}
+
+	rc = ffs_part_info(ffs, part, NULL, &start, &size, NULL, &ecc);
+	if (rc) {
+		prlog(PR_WARNING, "FLASH: Can't parse ffs info for VERSION\n");
+		return OPAL_HARDWARE;
+	}
+
+	buf = malloc(size);
+	if (!buf) {
+                prlog(PR_WARNING, "FLASH: Failed to allocate memory\n");
+		return OPAL_RESOURCE;
+	}
+
+	rc = blocklevel_read(flash->bl, start, buf, size);
+	if (rc) {
+		prlog(PR_WARNING, "FLASH: Couldn't read from flash at 0x%08x "
+		      "for len 0x%08x [rc = %d]\n", start, size, rc);
+		return rc;
+	}
+
+	version_size = ecc ? ecc_buffer_size_minus_ecc(size) : size;
+	fw_version = dt_new(dt_root, "ibm,firmware-versions");
+	assert(fw_version);
+
+	for ( ; (numbytes < version_size) && buf[numbytes]; numbytes++) {
+		if (buf[numbytes] == '\n') {
+			version_data[i] = '\0';
+			flash_dt_add_fw_version(fw_version, version_data);
+			memset(version_data, 0, sizeof(version_data));
+			i = 0;
+			continue;
+		} else if (buf[numbytes] == '\t') {
+			continue; /* skip tabs */
+		}
+
+		version_data[i++] = buf[numbytes];
+	}
+
+	free(buf);
+	return 0;
+}
+
 static int flash_nvram_probe(struct flash *flash, struct ffs_handle *ffs)
 {
 	uint32_t start, size, part;
@@ -238,6 +339,7 @@  static void setup_system_flash(struct flash *flash, struct dt_node *node,
 
 	prlog(PR_INFO, "FLASH: registered system flash device %s\n", name);
 
+	flash_fw_version_probe(flash, ffs);
 	flash_nvram_probe(flash, ffs);
 }