All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/2] smbios: add parsing API
@ 2019-04-16 11:38 Christian Gmeiner
  2019-04-16 11:38 ` [U-Boot] [PATCH 2/2] coreboot: make use of smbios parser Christian Gmeiner
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Christian Gmeiner @ 2019-04-16 11:38 UTC (permalink / raw)
  To: u-boot

Add an very simple API to be able to access SMBIOS strings
like vendor, model and bios version.

Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
---
 include/smbios.h    |  37 ++++++++++
 lib/Kconfig         |   6 ++
 lib/Makefile        |   1 +
 lib/smbios-parser.c | 162 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 206 insertions(+)
 create mode 100644 lib/smbios-parser.c

diff --git a/include/smbios.h b/include/smbios.h
index 97b9ddce23..ad44e54245 100644
--- a/include/smbios.h
+++ b/include/smbios.h
@@ -237,4 +237,41 @@ typedef int (*smbios_write_type)(ulong *addr, int handle);
  */
 ulong write_smbios_table(ulong addr);
 
+
+struct smbios_parser;
+
+/**
+ * smbios_parser_create() - Create smbios parser
+ *
+ * @addr:	start address to search for SMBIOS structure
+ * @len:	size of search area
+ * @return:	NULL or valid pointer to a struct smbios_parser
+ */
+struct smbios_parser *smbios_parser_create(unsigned int addr, unsigned int len);
+
+/**
+ * smbios_parser_destroy() - Destroy smbios parser
+ *
+ * @p:	pointer to a struct smbios_parser
+ */
+void smbios_parser_destroy(struct smbios_parser *p);
+
+/**
+ * smbios_header() - Search for SMBIOS header type
+ *
+ * @p:	pointer to a struct smbios_parser
+ * @type:	SMBIOS type
+ * @return:	NULL or a valid pointer to a struct smbios_header
+ */
+struct smbios_header *smbios_header(const struct smbios_parser *p, int type);
+
+/**
+ * smbios_string() - Return string from SMBIOS
+ *
+ * @header:	pointer to struct smbios_header
+ * @index:	string index
+ * @return:	NULL or a valid const char pointer
+ */
+const char *smbios_string(const struct smbios_header *header, int index);
+
 #endif /* _SMBIOS_H_ */
diff --git a/lib/Kconfig b/lib/Kconfig
index 2120216593..59aafc63a7 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -432,6 +432,12 @@ config SMBIOS_PRODUCT_NAME
 
 endmenu
 
+config SMBIOS_PARSER
+	bool "SMBIOS parser"
+	default n
+	help
+	  A simple parser for SMBIOS data.
+
 source lib/efi/Kconfig
 source lib/efi_loader/Kconfig
 source lib/optee/Kconfig
diff --git a/lib/Makefile b/lib/Makefile
index 47829bfed5..f095bd420a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_FIT) += fdtdec_common.o
 obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
 obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o
 obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
+obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o
 obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
 obj-y += ldiv.o
 obj-$(CONFIG_MD5) += md5.o
diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
new file mode 100644
index 0000000000..b24fd7210c
--- /dev/null
+++ b/lib/smbios-parser.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019, Bachmann electronic GmbH
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <smbios.h>
+
+struct smbios_parser {
+	void *search_area;
+	unsigned int search_area_len;
+	struct smbios_entry *entry;
+	void *data;
+};
+
+static inline int verify_checksum(const struct smbios_entry *e)
+{
+	/*
+	 * Checksums for SMBIOS tables are calculated to have a value, so that
+	 * the sum over all bytes yields zero (using unsigned 8 bit arithmetic).
+	 */
+	u8 *byte = (u8 *)e;
+	u8 sum = 0;
+
+	for (int i = 0; i < e->length; i++)
+		sum += byte[i];
+
+	return sum;
+}
+
+static struct smbios_entry *find_smbios_entry(const struct smbios_parser *p)
+{
+	static const char sm_sig[] = "_SM_";
+	u8 *buf = (u8 *)p->search_area;
+	const u8 *end = (u8 *)p->search_area + p->search_area_len;
+	struct smbios_entry *entry = NULL;
+
+	/* look for smbios entry */
+	while (buf < end) {
+		if (memcmp(sm_sig, buf, 4) == 0) {
+			entry = (struct smbios_entry *)buf;
+
+			if (verify_checksum(entry)) {
+				entry = NULL;
+				buf++;
+				continue;
+			}
+
+			break;
+		}
+
+		buf++;
+	}
+
+	return entry;
+}
+
+void smbios_parser_destroy(struct smbios_parser *p)
+{
+	if (!p)
+		return;
+
+	unmap_sysmem(p->data);
+	unmap_sysmem(p->search_area);
+
+	free(p);
+}
+
+struct smbios_parser *smbios_parser_create(unsigned int addr, unsigned int len)
+{
+	struct smbios_parser *p = malloc(sizeof(struct smbios_parser));
+
+	if (!p)
+		return NULL;
+
+	p->search_area_len = len;
+	p->search_area = map_sysmem(addr, len);
+
+	if (!p->search_area)
+		goto fail;
+
+	/* find main entry smbios table */
+	p->entry = find_smbios_entry(p);
+
+	if (!p->entry)
+		goto fail;
+
+	/* map smbios data area */
+	p->data = map_sysmem(p->entry->struct_table_address,
+			     p->entry->struct_table_length);
+
+	if (!p->data)
+		goto fail;
+
+	return p;
+
+fail:
+	smbios_parser_destroy(p);
+
+	return NULL;
+}
+
+static struct smbios_header *next_header(const struct smbios_header *curr)
+{
+	u8 *pos = ((u8 *)curr) + curr->length;
+
+	/* search for _double_ NULL bytes */
+	while (!((*pos == 0) && (*(pos + 1) == 0)))
+		pos++;
+
+	/* step behind the double NULL bytes */
+	pos += 2;
+
+	return (struct smbios_header *)pos;
+}
+
+struct smbios_header *smbios_header(const struct smbios_parser *p, int type)
+{
+	const struct smbios_entry *entry = p->entry;
+	const unsigned int num_header = entry->struct_count;
+	struct smbios_header *header = (struct smbios_header *)p->data;
+
+	for (unsigned int i = 0; i < num_header; i++) {
+		if (header->type == type)
+			return header;
+
+		header = next_header(header);
+	}
+
+	return NULL;
+}
+
+static const char *string_from_smbios_table(const struct smbios_header *header,
+					    int idx)
+{
+	unsigned int i = 1;
+	u8 *pos;
+
+	if (!header)
+		return NULL;
+
+	pos = ((u8 *)header) + header->length;
+
+	while (i < idx) {
+		if (*pos == 0x0)
+			i++;
+
+		pos++;
+	}
+
+	return (const char *)pos;
+}
+
+const char *smbios_string(const struct smbios_header *header, int index)
+{
+	if (!header)
+		return NULL;
+
+	return string_from_smbios_table(header, index);
+}
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 2/2] coreboot: make use of smbios parser
  2019-04-16 11:38 [U-Boot] [PATCH 1/2] smbios: add parsing API Christian Gmeiner
@ 2019-04-16 11:38 ` Christian Gmeiner
  2019-04-25  6:27 ` [U-Boot] [PATCH 1/2] smbios: add parsing API Christian Gmeiner
  2019-04-25 10:09 ` Alexander Graf
  2 siblings, 0 replies; 10+ messages in thread
From: Christian Gmeiner @ 2019-04-16 11:38 UTC (permalink / raw)
  To: u-boot

If u-boot gets used as coreboot payload it might be nice to get
vendor, model and bios version from smbios. I am not sure about
the output of all the read information.

With qemu target for coreboot this could look this:

CBFS: 'Master Header Locator' located CBFS at [7a0200:800000)
CBFS: Locating 'fallback/payload'
CBFS: Found @ offset 13000 size 36ae4
Checking segment from ROM address 0xfffb3238
Checking segment from ROM address 0xfffb3254
Loading segment from ROM address 0xfffb3238
  code (compression=1)
  New segment dstaddr 0x01110000 memsize 0x7c7bb srcaddr 0xfffb3270 filesize 0x36aac
Loading Segment: addr: 0x01110000 memsz: 0x000000000007c7bb filesz: 0x0000000000036aac
using LZMA
Loading segment from ROM address 0xfffb3254
  Entry Point 0x01110015
Jumping to boot code at 01110015(07fa8000)

U-Boot 2019.04-00337-ga602a0489f-dirty (Apr 16 2019 - 13:30:50 +0200)

CPU: x86, vendor Intel, device 663h
DRAM:  127.4 MiB
MMC:
Video: No video mode configured in coreboot!
Video: No video mode configured in coreboot!
Vendor: QEMU
Model: Standard PC (i440FX + PIIX, 1996)
Bios Version: 4.9-1324-ge2f0a5f76c-dirty
Net:   e1000: 52:54:00:12:34:56

Warning: e1000#0 using MAC address from ROM
eth0: e1000#0
No working controllers found
Finalizing coreboot
Hit any key to stop autoboot:  0

Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
---
 board/coreboot/coreboot/coreboot.c | 47 ++++++++++++++++++++++++++++++
 configs/coreboot_defconfig         |  1 +
 2 files changed, 48 insertions(+)

diff --git a/board/coreboot/coreboot/coreboot.c b/board/coreboot/coreboot/coreboot.c
index ed5606d4a4..12b3eef52f 100644
--- a/board/coreboot/coreboot/coreboot.c
+++ b/board/coreboot/coreboot/coreboot.c
@@ -4,6 +4,53 @@
  */
 
 #include <common.h>
+#include <smbios.h>
+
+int show_board_info(void)
+{
+	struct smbios_parser *p = smbios_parser_create(0xF0000, 0x10000);
+
+	if (!p)
+		goto fallback;
+
+	const struct smbios_header *bios = smbios_header(p, SMBIOS_BIOS_INFORMATION);
+	const struct smbios_header *system = smbios_header(p, SMBIOS_SYSTEM_INFORMATION);
+	const struct smbios_type0 *t0 = (struct smbios_type0 *)bios;
+	const struct smbios_type1 *t1 = (struct smbios_type1 *)system;
+
+	if (!t0 || !t1)
+		goto fallback;
+
+	const char *bios_ver = smbios_string(bios, t0->bios_ver);
+	const char *model = smbios_string(system, t1->product_name);
+	const char *manufacturer = smbios_string(system, t1->manufacturer);
+
+	if (!model || !manufacturer || !bios_ver)
+		goto fallback;
+
+	printf("Vendor: %s\n", manufacturer);
+	printf("Model: %s\n", model);
+	printf("Bios Version: %s\n", bios_ver);
+
+	smbios_parser_destroy(p);
+
+	return 0;
+
+fallback:
+
+	smbios_parser_destroy(p);
+
+#ifdef CONFIG_OF_CONTROL
+	DECLARE_GLOBAL_DATA_PTR;
+
+	model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
+
+	if (model)
+		printf("Model: %s\n", model);
+#endif
+
+	return checkboard();
+}
 
 int board_early_init_r(void)
 {
diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig
index 2795fe97ca..9f4a1473fa 100644
--- a/configs/coreboot_defconfig
+++ b/configs/coreboot_defconfig
@@ -39,3 +39,4 @@ CONFIG_SYSCON=y
 CONFIG_SOUND=y
 CONFIG_SOUND_I8254=y
 CONFIG_CONSOLE_SCROLL_LINES=5
+CONFIG_SMBIOS_PARSER=y
-- 
2.20.1

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/2] smbios: add parsing API
  2019-04-16 11:38 [U-Boot] [PATCH 1/2] smbios: add parsing API Christian Gmeiner
  2019-04-16 11:38 ` [U-Boot] [PATCH 2/2] coreboot: make use of smbios parser Christian Gmeiner
@ 2019-04-25  6:27 ` Christian Gmeiner
  2019-04-25 10:09 ` Alexander Graf
  2 siblings, 0 replies; 10+ messages in thread
From: Christian Gmeiner @ 2019-04-25  6:27 UTC (permalink / raw)
  To: u-boot

Am Di., 16. Apr. 2019 um 13:38 Uhr schrieb Christian Gmeiner
<christian.gmeiner@gmail.com>:
>
> Add an very simple API to be able to access SMBIOS strings
> like vendor, model and bios version.
>

ping

> Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
> ---
>  include/smbios.h    |  37 ++++++++++
>  lib/Kconfig         |   6 ++
>  lib/Makefile        |   1 +
>  lib/smbios-parser.c | 162 ++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 206 insertions(+)
>  create mode 100644 lib/smbios-parser.c
>
> diff --git a/include/smbios.h b/include/smbios.h
> index 97b9ddce23..ad44e54245 100644
> --- a/include/smbios.h
> +++ b/include/smbios.h
> @@ -237,4 +237,41 @@ typedef int (*smbios_write_type)(ulong *addr, int handle);
>   */
>  ulong write_smbios_table(ulong addr);
>
> +
> +struct smbios_parser;
> +
> +/**
> + * smbios_parser_create() - Create smbios parser
> + *
> + * @addr:      start address to search for SMBIOS structure
> + * @len:       size of search area
> + * @return:    NULL or valid pointer to a struct smbios_parser
> + */
> +struct smbios_parser *smbios_parser_create(unsigned int addr, unsigned int len);
> +
> +/**
> + * smbios_parser_destroy() - Destroy smbios parser
> + *
> + * @p: pointer to a struct smbios_parser
> + */
> +void smbios_parser_destroy(struct smbios_parser *p);
> +
> +/**
> + * smbios_header() - Search for SMBIOS header type
> + *
> + * @p: pointer to a struct smbios_parser
> + * @type:      SMBIOS type
> + * @return:    NULL or a valid pointer to a struct smbios_header
> + */
> +struct smbios_header *smbios_header(const struct smbios_parser *p, int type);
> +
> +/**
> + * smbios_string() - Return string from SMBIOS
> + *
> + * @header:    pointer to struct smbios_header
> + * @index:     string index
> + * @return:    NULL or a valid const char pointer
> + */
> +const char *smbios_string(const struct smbios_header *header, int index);
> +
>  #endif /* _SMBIOS_H_ */
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 2120216593..59aafc63a7 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -432,6 +432,12 @@ config SMBIOS_PRODUCT_NAME
>
>  endmenu
>
> +config SMBIOS_PARSER
> +       bool "SMBIOS parser"
> +       default n
> +       help
> +         A simple parser for SMBIOS data.
> +
>  source lib/efi/Kconfig
>  source lib/efi_loader/Kconfig
>  source lib/optee/Kconfig
> diff --git a/lib/Makefile b/lib/Makefile
> index 47829bfed5..f095bd420a 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -34,6 +34,7 @@ obj-$(CONFIG_FIT) += fdtdec_common.o
>  obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
>  obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o
>  obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
> +obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o
>  obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
>  obj-y += ldiv.o
>  obj-$(CONFIG_MD5) += md5.o
> diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
> new file mode 100644
> index 0000000000..b24fd7210c
> --- /dev/null
> +++ b/lib/smbios-parser.c
> @@ -0,0 +1,162 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019, Bachmann electronic GmbH
> + */
> +
> +#include <common.h>
> +#include <malloc.h>
> +#include <mapmem.h>
> +#include <smbios.h>
> +
> +struct smbios_parser {
> +       void *search_area;
> +       unsigned int search_area_len;
> +       struct smbios_entry *entry;
> +       void *data;
> +};
> +
> +static inline int verify_checksum(const struct smbios_entry *e)
> +{
> +       /*
> +        * Checksums for SMBIOS tables are calculated to have a value, so that
> +        * the sum over all bytes yields zero (using unsigned 8 bit arithmetic).
> +        */
> +       u8 *byte = (u8 *)e;
> +       u8 sum = 0;
> +
> +       for (int i = 0; i < e->length; i++)
> +               sum += byte[i];
> +
> +       return sum;
> +}
> +
> +static struct smbios_entry *find_smbios_entry(const struct smbios_parser *p)
> +{
> +       static const char sm_sig[] = "_SM_";
> +       u8 *buf = (u8 *)p->search_area;
> +       const u8 *end = (u8 *)p->search_area + p->search_area_len;
> +       struct smbios_entry *entry = NULL;
> +
> +       /* look for smbios entry */
> +       while (buf < end) {
> +               if (memcmp(sm_sig, buf, 4) == 0) {
> +                       entry = (struct smbios_entry *)buf;
> +
> +                       if (verify_checksum(entry)) {
> +                               entry = NULL;
> +                               buf++;
> +                               continue;
> +                       }
> +
> +                       break;
> +               }
> +
> +               buf++;
> +       }
> +
> +       return entry;
> +}
> +
> +void smbios_parser_destroy(struct smbios_parser *p)
> +{
> +       if (!p)
> +               return;
> +
> +       unmap_sysmem(p->data);
> +       unmap_sysmem(p->search_area);
> +
> +       free(p);
> +}
> +
> +struct smbios_parser *smbios_parser_create(unsigned int addr, unsigned int len)
> +{
> +       struct smbios_parser *p = malloc(sizeof(struct smbios_parser));
> +
> +       if (!p)
> +               return NULL;
> +
> +       p->search_area_len = len;
> +       p->search_area = map_sysmem(addr, len);
> +
> +       if (!p->search_area)
> +               goto fail;
> +
> +       /* find main entry smbios table */
> +       p->entry = find_smbios_entry(p);
> +
> +       if (!p->entry)
> +               goto fail;
> +
> +       /* map smbios data area */
> +       p->data = map_sysmem(p->entry->struct_table_address,
> +                            p->entry->struct_table_length);
> +
> +       if (!p->data)
> +               goto fail;
> +
> +       return p;
> +
> +fail:
> +       smbios_parser_destroy(p);
> +
> +       return NULL;
> +}
> +
> +static struct smbios_header *next_header(const struct smbios_header *curr)
> +{
> +       u8 *pos = ((u8 *)curr) + curr->length;
> +
> +       /* search for _double_ NULL bytes */
> +       while (!((*pos == 0) && (*(pos + 1) == 0)))
> +               pos++;
> +
> +       /* step behind the double NULL bytes */
> +       pos += 2;
> +
> +       return (struct smbios_header *)pos;
> +}
> +
> +struct smbios_header *smbios_header(const struct smbios_parser *p, int type)
> +{
> +       const struct smbios_entry *entry = p->entry;
> +       const unsigned int num_header = entry->struct_count;
> +       struct smbios_header *header = (struct smbios_header *)p->data;
> +
> +       for (unsigned int i = 0; i < num_header; i++) {
> +               if (header->type == type)
> +                       return header;
> +
> +               header = next_header(header);
> +       }
> +
> +       return NULL;
> +}
> +
> +static const char *string_from_smbios_table(const struct smbios_header *header,
> +                                           int idx)
> +{
> +       unsigned int i = 1;
> +       u8 *pos;
> +
> +       if (!header)
> +               return NULL;
> +
> +       pos = ((u8 *)header) + header->length;
> +
> +       while (i < idx) {
> +               if (*pos == 0x0)
> +                       i++;
> +
> +               pos++;
> +       }
> +
> +       return (const char *)pos;
> +}
> +
> +const char *smbios_string(const struct smbios_header *header, int index)
> +{
> +       if (!header)
> +               return NULL;
> +
> +       return string_from_smbios_table(header, index);
> +}
> --
> 2.20.1
>


-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/2] smbios: add parsing API
  2019-04-16 11:38 [U-Boot] [PATCH 1/2] smbios: add parsing API Christian Gmeiner
  2019-04-16 11:38 ` [U-Boot] [PATCH 2/2] coreboot: make use of smbios parser Christian Gmeiner
  2019-04-25  6:27 ` [U-Boot] [PATCH 1/2] smbios: add parsing API Christian Gmeiner
@ 2019-04-25 10:09 ` Alexander Graf
  2019-04-29 14:29   ` Christian Gmeiner
  2019-04-29 15:41   ` Simon Glass
  2 siblings, 2 replies; 10+ messages in thread
From: Alexander Graf @ 2019-04-25 10:09 UTC (permalink / raw)
  To: u-boot


On 16.04.19 13:38, Christian Gmeiner wrote:
> Add an very simple API to be able to access SMBIOS strings
> like vendor, model and bios version.
>
> Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
> ---
>  include/smbios.h    |  37 ++++++++++
>  lib/Kconfig         |   6 ++
>  lib/Makefile        |   1 +
>  lib/smbios-parser.c | 162 ++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 206 insertions(+)
>  create mode 100644 lib/smbios-parser.c
>
> diff --git a/include/smbios.h b/include/smbios.h
> index 97b9ddce23..ad44e54245 100644
> --- a/include/smbios.h
> +++ b/include/smbios.h
> @@ -237,4 +237,41 @@ typedef int (*smbios_write_type)(ulong *addr, int handle);
>   */
>  ulong write_smbios_table(ulong addr);
>  
> +
> +struct smbios_parser;
> +
> +/**
> + * smbios_parser_create() - Create smbios parser
> + *
> + * @addr:	start address to search for SMBIOS structure
> + * @len:	size of search area
> + * @return:	NULL or valid pointer to a struct smbios_parser
> + */
> +struct smbios_parser *smbios_parser_create(unsigned int addr, unsigned int len);
> +
> +/**
> + * smbios_parser_destroy() - Destroy smbios parser
> + *
> + * @p:	pointer to a struct smbios_parser
> + */
> +void smbios_parser_destroy(struct smbios_parser *p);
> +
> +/**
> + * smbios_header() - Search for SMBIOS header type
> + *
> + * @p:	pointer to a struct smbios_parser
> + * @type:	SMBIOS type
> + * @return:	NULL or a valid pointer to a struct smbios_header
> + */
> +struct smbios_header *smbios_header(const struct smbios_parser *p, int type);
> +
> +/**
> + * smbios_string() - Return string from SMBIOS
> + *
> + * @header:	pointer to struct smbios_header
> + * @index:	string index
> + * @return:	NULL or a valid const char pointer
> + */
> +const char *smbios_string(const struct smbios_header *header, int index);
> +
>  #endif /* _SMBIOS_H_ */
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 2120216593..59aafc63a7 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -432,6 +432,12 @@ config SMBIOS_PRODUCT_NAME
>  
>  endmenu
>  
> +config SMBIOS_PARSER
> +	bool "SMBIOS parser"
> +	default n
> +	help
> +	  A simple parser for SMBIOS data.
> +
>  source lib/efi/Kconfig
>  source lib/efi_loader/Kconfig
>  source lib/optee/Kconfig
> diff --git a/lib/Makefile b/lib/Makefile
> index 47829bfed5..f095bd420a 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -34,6 +34,7 @@ obj-$(CONFIG_FIT) += fdtdec_common.o
>  obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
>  obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o
>  obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
> +obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o
>  obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
>  obj-y += ldiv.o
>  obj-$(CONFIG_MD5) += md5.o
> diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
> new file mode 100644
> index 0000000000..b24fd7210c
> --- /dev/null
> +++ b/lib/smbios-parser.c
> @@ -0,0 +1,162 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019, Bachmann electronic GmbH
> + */
> +
> +#include <common.h>
> +#include <malloc.h>
> +#include <mapmem.h>
> +#include <smbios.h>
> +
> +struct smbios_parser {
> +	void *search_area;
> +	unsigned int search_area_len;
> +	struct smbios_entry *entry;
> +	void *data;
> +};
> +
> +static inline int verify_checksum(const struct smbios_entry *e)
> +{
> +	/*
> +	 * Checksums for SMBIOS tables are calculated to have a value, so that
> +	 * the sum over all bytes yields zero (using unsigned 8 bit arithmetic).
> +	 */
> +	u8 *byte = (u8 *)e;
> +	u8 sum = 0;
> +
> +	for (int i = 0; i < e->length; i++)
> +		sum += byte[i];
> +
> +	return sum;
> +}
> +
> +static struct smbios_entry *find_smbios_entry(const struct smbios_parser *p)
> +{
> +	static const char sm_sig[] = "_SM_";
> +	u8 *buf = (u8 *)p->search_area;
> +	const u8 *end = (u8 *)p->search_area + p->search_area_len;
> +	struct smbios_entry *entry = NULL;
> +
> +	/* look for smbios entry */
> +	while (buf < end) {


Don't you have a way to pass the DMI pointer directly, maybe using cbfs?
Searching through the SMBIOS search area is so 1990s (and pretty much
only works on x86).


I also don't think we really need all the smbios_parser logic. No need
to create special pseudo objects. IMHO you should either create an
actual UCLASS for SMBIOS with genuine callbacks and expose the table as
DM object or just make all search functions in this patch stateless. I'd
opt for the latter - it's how the SMBIOS creation works too.


Alex


> +		if (memcmp(sm_sig, buf, 4) == 0) {
> +			entry = (struct smbios_entry *)buf;
> +
> +			if (verify_checksum(entry)) {
> +				entry = NULL;
> +				buf++;
> +				continue;
> +			}
> +
> +			break;
> +		}
> +
> +		buf++;
> +	}
> +
> +	return entry;
> +}
> +
> +void smbios_parser_destroy(struct smbios_parser *p)
> +{
> +	if (!p)
> +		return;
> +
> +	unmap_sysmem(p->data);
> +	unmap_sysmem(p->search_area);
> +
> +	free(p);
> +}
> +
> +struct smbios_parser *smbios_parser_create(unsigned int addr, unsigned int len)
> +{
> +	struct smbios_parser *p = malloc(sizeof(struct smbios_parser));
> +
> +	if (!p)
> +		return NULL;
> +
> +	p->search_area_len = len;
> +	p->search_area = map_sysmem(addr, len);
> +
> +	if (!p->search_area)
> +		goto fail;
> +
> +	/* find main entry smbios table */
> +	p->entry = find_smbios_entry(p);
> +
> +	if (!p->entry)
> +		goto fail;
> +
> +	/* map smbios data area */
> +	p->data = map_sysmem(p->entry->struct_table_address,
> +			     p->entry->struct_table_length);
> +
> +	if (!p->data)
> +		goto fail;
> +
> +	return p;
> +
> +fail:
> +	smbios_parser_destroy(p);
> +
> +	return NULL;
> +}
> +
> +static struct smbios_header *next_header(const struct smbios_header *curr)
> +{
> +	u8 *pos = ((u8 *)curr) + curr->length;
> +
> +	/* search for _double_ NULL bytes */
> +	while (!((*pos == 0) && (*(pos + 1) == 0)))
> +		pos++;
> +
> +	/* step behind the double NULL bytes */
> +	pos += 2;
> +
> +	return (struct smbios_header *)pos;
> +}
> +
> +struct smbios_header *smbios_header(const struct smbios_parser *p, int type)
> +{
> +	const struct smbios_entry *entry = p->entry;
> +	const unsigned int num_header = entry->struct_count;
> +	struct smbios_header *header = (struct smbios_header *)p->data;
> +
> +	for (unsigned int i = 0; i < num_header; i++) {
> +		if (header->type == type)
> +			return header;
> +
> +		header = next_header(header);
> +	}
> +
> +	return NULL;
> +}
> +
> +static const char *string_from_smbios_table(const struct smbios_header *header,
> +					    int idx)
> +{
> +	unsigned int i = 1;
> +	u8 *pos;
> +
> +	if (!header)
> +		return NULL;
> +
> +	pos = ((u8 *)header) + header->length;
> +
> +	while (i < idx) {
> +		if (*pos == 0x0)
> +			i++;
> +
> +		pos++;
> +	}
> +
> +	return (const char *)pos;
> +}
> +
> +const char *smbios_string(const struct smbios_header *header, int index)
> +{
> +	if (!header)
> +		return NULL;
> +
> +	return string_from_smbios_table(header, index);
> +}

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/2] smbios: add parsing API
  2019-04-25 10:09 ` Alexander Graf
@ 2019-04-29 14:29   ` Christian Gmeiner
  2019-04-29 15:35     ` Alexander Graf
  2019-04-29 15:41   ` Simon Glass
  1 sibling, 1 reply; 10+ messages in thread
From: Christian Gmeiner @ 2019-04-29 14:29 UTC (permalink / raw)
  To: u-boot

Hi

Am Do., 25. Apr. 2019 um 12:09 Uhr schrieb Alexander Graf <agraf@csgraf.de>:
>
>
> On 16.04.19 13:38, Christian Gmeiner wrote:
> > Add an very simple API to be able to access SMBIOS strings
> > like vendor, model and bios version.
> >
> > Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
> > ---
> >  include/smbios.h    |  37 ++++++++++
> >  lib/Kconfig         |   6 ++
> >  lib/Makefile        |   1 +
> >  lib/smbios-parser.c | 162 ++++++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 206 insertions(+)
> >  create mode 100644 lib/smbios-parser.c
> >
> > diff --git a/include/smbios.h b/include/smbios.h
> > index 97b9ddce23..ad44e54245 100644
> > --- a/include/smbios.h
> > +++ b/include/smbios.h
> > @@ -237,4 +237,41 @@ typedef int (*smbios_write_type)(ulong *addr, int handle);
> >   */
> >  ulong write_smbios_table(ulong addr);
> >
> > +
> > +struct smbios_parser;
> > +
> > +/**
> > + * smbios_parser_create() - Create smbios parser
> > + *
> > + * @addr:    start address to search for SMBIOS structure
> > + * @len:     size of search area
> > + * @return:  NULL or valid pointer to a struct smbios_parser
> > + */
> > +struct smbios_parser *smbios_parser_create(unsigned int addr, unsigned int len);
> > +
> > +/**
> > + * smbios_parser_destroy() - Destroy smbios parser
> > + *
> > + * @p:       pointer to a struct smbios_parser
> > + */
> > +void smbios_parser_destroy(struct smbios_parser *p);
> > +
> > +/**
> > + * smbios_header() - Search for SMBIOS header type
> > + *
> > + * @p:       pointer to a struct smbios_parser
> > + * @type:    SMBIOS type
> > + * @return:  NULL or a valid pointer to a struct smbios_header
> > + */
> > +struct smbios_header *smbios_header(const struct smbios_parser *p, int type);
> > +
> > +/**
> > + * smbios_string() - Return string from SMBIOS
> > + *
> > + * @header:  pointer to struct smbios_header
> > + * @index:   string index
> > + * @return:  NULL or a valid const char pointer
> > + */
> > +const char *smbios_string(const struct smbios_header *header, int index);
> > +
> >  #endif /* _SMBIOS_H_ */
> > diff --git a/lib/Kconfig b/lib/Kconfig
> > index 2120216593..59aafc63a7 100644
> > --- a/lib/Kconfig
> > +++ b/lib/Kconfig
> > @@ -432,6 +432,12 @@ config SMBIOS_PRODUCT_NAME
> >
> >  endmenu
> >
> > +config SMBIOS_PARSER
> > +     bool "SMBIOS parser"
> > +     default n
> > +     help
> > +       A simple parser for SMBIOS data.
> > +
> >  source lib/efi/Kconfig
> >  source lib/efi_loader/Kconfig
> >  source lib/optee/Kconfig
> > diff --git a/lib/Makefile b/lib/Makefile
> > index 47829bfed5..f095bd420a 100644
> > --- a/lib/Makefile
> > +++ b/lib/Makefile
> > @@ -34,6 +34,7 @@ obj-$(CONFIG_FIT) += fdtdec_common.o
> >  obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
> >  obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o
> >  obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
> > +obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o
> >  obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
> >  obj-y += ldiv.o
> >  obj-$(CONFIG_MD5) += md5.o
> > diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
> > new file mode 100644
> > index 0000000000..b24fd7210c
> > --- /dev/null
> > +++ b/lib/smbios-parser.c
> > @@ -0,0 +1,162 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * Copyright (C) 2019, Bachmann electronic GmbH
> > + */
> > +
> > +#include <common.h>
> > +#include <malloc.h>
> > +#include <mapmem.h>
> > +#include <smbios.h>
> > +
> > +struct smbios_parser {
> > +     void *search_area;
> > +     unsigned int search_area_len;
> > +     struct smbios_entry *entry;
> > +     void *data;
> > +};
> > +
> > +static inline int verify_checksum(const struct smbios_entry *e)
> > +{
> > +     /*
> > +      * Checksums for SMBIOS tables are calculated to have a value, so that
> > +      * the sum over all bytes yields zero (using unsigned 8 bit arithmetic).
> > +      */
> > +     u8 *byte = (u8 *)e;
> > +     u8 sum = 0;
> > +
> > +     for (int i = 0; i < e->length; i++)
> > +             sum += byte[i];
> > +
> > +     return sum;
> > +}
> > +
> > +static struct smbios_entry *find_smbios_entry(const struct smbios_parser *p)
> > +{
> > +     static const char sm_sig[] = "_SM_";
> > +     u8 *buf = (u8 *)p->search_area;
> > +     const u8 *end = (u8 *)p->search_area + p->search_area_len;
> > +     struct smbios_entry *entry = NULL;
> > +
> > +     /* look for smbios entry */
> > +     while (buf < end) {
>
>
> Don't you have a way to pass the DMI pointer directly, maybe using cbfs?
> Searching through the SMBIOS search area is so 1990s (and pretty much
> only works on x86).
>

Coreboot adds a smbios cbmem entry which can be used to get the base address.
Will make use of that mechanism in the next version of the patch set.

>
> I also don't think we really need all the smbios_parser logic. No need
> to create special pseudo objects. IMHO you should either create an
> actual UCLASS for SMBIOS with genuine callbacks and expose the table as
> DM object or just make all search functions in this patch stateless. I'd
> opt for the latter - it's how the SMBIOS creation works too.
>

I am not sure what you mean with 'special pseudo objects' - struct
smbios_parser?

-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/2] smbios: add parsing API
  2019-04-29 14:29   ` Christian Gmeiner
@ 2019-04-29 15:35     ` Alexander Graf
  2019-04-29 15:52       ` Christian Gmeiner
  0 siblings, 1 reply; 10+ messages in thread
From: Alexander Graf @ 2019-04-29 15:35 UTC (permalink / raw)
  To: u-boot


On 29.04.19 16:29, Christian Gmeiner wrote:
> Hi
>
> Am Do., 25. Apr. 2019 um 12:09 Uhr schrieb Alexander Graf <agraf@csgraf.de>:
>>
>> On 16.04.19 13:38, Christian Gmeiner wrote:
>>> Add an very simple API to be able to access SMBIOS strings
>>> like vendor, model and bios version.
>>>
>>> Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
>>> ---
>>>  include/smbios.h    |  37 ++++++++++
>>>  lib/Kconfig         |   6 ++
>>>  lib/Makefile        |   1 +
>>>  lib/smbios-parser.c | 162 ++++++++++++++++++++++++++++++++++++++++++++
>>>  4 files changed, 206 insertions(+)
>>>  create mode 100644 lib/smbios-parser.c
>>>
>>> diff --git a/include/smbios.h b/include/smbios.h
>>> index 97b9ddce23..ad44e54245 100644
>>> --- a/include/smbios.h
>>> +++ b/include/smbios.h
>>> @@ -237,4 +237,41 @@ typedef int (*smbios_write_type)(ulong *addr, int handle);
>>>   */
>>>  ulong write_smbios_table(ulong addr);
>>>
>>> +
>>> +struct smbios_parser;
>>> +
>>> +/**
>>> + * smbios_parser_create() - Create smbios parser
>>> + *
>>> + * @addr:    start address to search for SMBIOS structure
>>> + * @len:     size of search area
>>> + * @return:  NULL or valid pointer to a struct smbios_parser
>>> + */
>>> +struct smbios_parser *smbios_parser_create(unsigned int addr, unsigned int len);
>>> +
>>> +/**
>>> + * smbios_parser_destroy() - Destroy smbios parser
>>> + *
>>> + * @p:       pointer to a struct smbios_parser
>>> + */
>>> +void smbios_parser_destroy(struct smbios_parser *p);
>>> +
>>> +/**
>>> + * smbios_header() - Search for SMBIOS header type
>>> + *
>>> + * @p:       pointer to a struct smbios_parser
>>> + * @type:    SMBIOS type
>>> + * @return:  NULL or a valid pointer to a struct smbios_header
>>> + */
>>> +struct smbios_header *smbios_header(const struct smbios_parser *p, int type);
>>> +
>>> +/**
>>> + * smbios_string() - Return string from SMBIOS
>>> + *
>>> + * @header:  pointer to struct smbios_header
>>> + * @index:   string index
>>> + * @return:  NULL or a valid const char pointer
>>> + */
>>> +const char *smbios_string(const struct smbios_header *header, int index);
>>> +
>>>  #endif /* _SMBIOS_H_ */
>>> diff --git a/lib/Kconfig b/lib/Kconfig
>>> index 2120216593..59aafc63a7 100644
>>> --- a/lib/Kconfig
>>> +++ b/lib/Kconfig
>>> @@ -432,6 +432,12 @@ config SMBIOS_PRODUCT_NAME
>>>
>>>  endmenu
>>>
>>> +config SMBIOS_PARSER
>>> +     bool "SMBIOS parser"
>>> +     default n
>>> +     help
>>> +       A simple parser for SMBIOS data.
>>> +
>>>  source lib/efi/Kconfig
>>>  source lib/efi_loader/Kconfig
>>>  source lib/optee/Kconfig
>>> diff --git a/lib/Makefile b/lib/Makefile
>>> index 47829bfed5..f095bd420a 100644
>>> --- a/lib/Makefile
>>> +++ b/lib/Makefile
>>> @@ -34,6 +34,7 @@ obj-$(CONFIG_FIT) += fdtdec_common.o
>>>  obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
>>>  obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o
>>>  obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
>>> +obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o
>>>  obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
>>>  obj-y += ldiv.o
>>>  obj-$(CONFIG_MD5) += md5.o
>>> diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
>>> new file mode 100644
>>> index 0000000000..b24fd7210c
>>> --- /dev/null
>>> +++ b/lib/smbios-parser.c
>>> @@ -0,0 +1,162 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * Copyright (C) 2019, Bachmann electronic GmbH
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <malloc.h>
>>> +#include <mapmem.h>
>>> +#include <smbios.h>
>>> +
>>> +struct smbios_parser {
>>> +     void *search_area;
>>> +     unsigned int search_area_len;
>>> +     struct smbios_entry *entry;
>>> +     void *data;
>>> +};
>>> +
>>> +static inline int verify_checksum(const struct smbios_entry *e)
>>> +{
>>> +     /*
>>> +      * Checksums for SMBIOS tables are calculated to have a value, so that
>>> +      * the sum over all bytes yields zero (using unsigned 8 bit arithmetic).
>>> +      */
>>> +     u8 *byte = (u8 *)e;
>>> +     u8 sum = 0;
>>> +
>>> +     for (int i = 0; i < e->length; i++)
>>> +             sum += byte[i];
>>> +
>>> +     return sum;
>>> +}
>>> +
>>> +static struct smbios_entry *find_smbios_entry(const struct smbios_parser *p)
>>> +{
>>> +     static const char sm_sig[] = "_SM_";
>>> +     u8 *buf = (u8 *)p->search_area;
>>> +     const u8 *end = (u8 *)p->search_area + p->search_area_len;
>>> +     struct smbios_entry *entry = NULL;
>>> +
>>> +     /* look for smbios entry */
>>> +     while (buf < end) {
>>
>> Don't you have a way to pass the DMI pointer directly, maybe using cbfs?
>> Searching through the SMBIOS search area is so 1990s (and pretty much
>> only works on x86).
>>
> Coreboot adds a smbios cbmem entry which can be used to get the base address.
> Will make use of that mechanism in the next version of the patch set.


Thanks, that will make this code a lot more robust :).


>
>> I also don't think we really need all the smbios_parser logic. No need
>> to create special pseudo objects. IMHO you should either create an
>> actual UCLASS for SMBIOS with genuine callbacks and expose the table as
>> DM object or just make all search functions in this patch stateless. I'd
>> opt for the latter - it's how the SMBIOS creation works too.
>>
> I am not sure what you mean with 'special pseudo objects' - struct
> smbios_parser?


Yes. The parser is stateful. I would ideally like it best if it wasn't :).


Alex

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/2] smbios: add parsing API
  2019-04-25 10:09 ` Alexander Graf
  2019-04-29 14:29   ` Christian Gmeiner
@ 2019-04-29 15:41   ` Simon Glass
  2019-04-29 15:53     ` Christian Gmeiner
  1 sibling, 1 reply; 10+ messages in thread
From: Simon Glass @ 2019-04-29 15:41 UTC (permalink / raw)
  To: u-boot

Hi,

On Thu, 25 Apr 2019 at 04:09, Alexander Graf <agraf@csgraf.de> wrote:
>
>
> On 16.04.19 13:38, Christian Gmeiner wrote:
> > Add an very simple API to be able to access SMBIOS strings
> > like vendor, model and bios version.
> >
> > Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
> > ---
> >  include/smbios.h    |  37 ++++++++++
> >  lib/Kconfig         |   6 ++
> >  lib/Makefile        |   1 +
> >  lib/smbios-parser.c | 162 ++++++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 206 insertions(+)
> >  create mode 100644 lib/smbios-parser.c

Can you please also add a test for each of these functions, with sample data.

BTW here is some code to write fake tables in case it helps:

https://chromium-review.googlesource.com/c/chromiumos/platform2/+/1062212/6/chromeos-config/libcros_config/identity_x86.cc

Regards,
Simon

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/2] smbios: add parsing API
  2019-04-29 15:35     ` Alexander Graf
@ 2019-04-29 15:52       ` Christian Gmeiner
  2019-05-01  6:36         ` Alexander Graf
  0 siblings, 1 reply; 10+ messages in thread
From: Christian Gmeiner @ 2019-04-29 15:52 UTC (permalink / raw)
  To: u-boot

Am Mo., 29. Apr. 2019 um 17:35 Uhr schrieb Alexander Graf <agraf@csgraf.de>:
>
>
> On 29.04.19 16:29, Christian Gmeiner wrote:
> > Hi
> >
> > Am Do., 25. Apr. 2019 um 12:09 Uhr schrieb Alexander Graf <agraf@csgraf.de>:
> >>
> >> On 16.04.19 13:38, Christian Gmeiner wrote:
> >>> Add an very simple API to be able to access SMBIOS strings
> >>> like vendor, model and bios version.
> >>>
> >>> Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
> >>> ---
> >>>  include/smbios.h    |  37 ++++++++++
> >>>  lib/Kconfig         |   6 ++
> >>>  lib/Makefile        |   1 +
> >>>  lib/smbios-parser.c | 162 ++++++++++++++++++++++++++++++++++++++++++++
> >>>  4 files changed, 206 insertions(+)
> >>>  create mode 100644 lib/smbios-parser.c
> >>>
> >>> diff --git a/include/smbios.h b/include/smbios.h
> >>> index 97b9ddce23..ad44e54245 100644
> >>> --- a/include/smbios.h
> >>> +++ b/include/smbios.h
> >>> @@ -237,4 +237,41 @@ typedef int (*smbios_write_type)(ulong *addr, int handle);
> >>>   */
> >>>  ulong write_smbios_table(ulong addr);
> >>>
> >>> +
> >>> +struct smbios_parser;
> >>> +
> >>> +/**
> >>> + * smbios_parser_create() - Create smbios parser
> >>> + *
> >>> + * @addr:    start address to search for SMBIOS structure
> >>> + * @len:     size of search area
> >>> + * @return:  NULL or valid pointer to a struct smbios_parser
> >>> + */
> >>> +struct smbios_parser *smbios_parser_create(unsigned int addr, unsigned int len);
> >>> +
> >>> +/**
> >>> + * smbios_parser_destroy() - Destroy smbios parser
> >>> + *
> >>> + * @p:       pointer to a struct smbios_parser
> >>> + */
> >>> +void smbios_parser_destroy(struct smbios_parser *p);
> >>> +
> >>> +/**
> >>> + * smbios_header() - Search for SMBIOS header type
> >>> + *
> >>> + * @p:       pointer to a struct smbios_parser
> >>> + * @type:    SMBIOS type
> >>> + * @return:  NULL or a valid pointer to a struct smbios_header
> >>> + */
> >>> +struct smbios_header *smbios_header(const struct smbios_parser *p, int type);
> >>> +
> >>> +/**
> >>> + * smbios_string() - Return string from SMBIOS
> >>> + *
> >>> + * @header:  pointer to struct smbios_header
> >>> + * @index:   string index
> >>> + * @return:  NULL or a valid const char pointer
> >>> + */
> >>> +const char *smbios_string(const struct smbios_header *header, int index);
> >>> +
> >>>  #endif /* _SMBIOS_H_ */
> >>> diff --git a/lib/Kconfig b/lib/Kconfig
> >>> index 2120216593..59aafc63a7 100644
> >>> --- a/lib/Kconfig
> >>> +++ b/lib/Kconfig
> >>> @@ -432,6 +432,12 @@ config SMBIOS_PRODUCT_NAME
> >>>
> >>>  endmenu
> >>>
> >>> +config SMBIOS_PARSER
> >>> +     bool "SMBIOS parser"
> >>> +     default n
> >>> +     help
> >>> +       A simple parser for SMBIOS data.
> >>> +
> >>>  source lib/efi/Kconfig
> >>>  source lib/efi_loader/Kconfig
> >>>  source lib/optee/Kconfig
> >>> diff --git a/lib/Makefile b/lib/Makefile
> >>> index 47829bfed5..f095bd420a 100644
> >>> --- a/lib/Makefile
> >>> +++ b/lib/Makefile
> >>> @@ -34,6 +34,7 @@ obj-$(CONFIG_FIT) += fdtdec_common.o
> >>>  obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
> >>>  obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o
> >>>  obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
> >>> +obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o
> >>>  obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
> >>>  obj-y += ldiv.o
> >>>  obj-$(CONFIG_MD5) += md5.o
> >>> diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
> >>> new file mode 100644
> >>> index 0000000000..b24fd7210c
> >>> --- /dev/null
> >>> +++ b/lib/smbios-parser.c
> >>> @@ -0,0 +1,162 @@
> >>> +// SPDX-License-Identifier: GPL-2.0+
> >>> +/*
> >>> + * Copyright (C) 2019, Bachmann electronic GmbH
> >>> + */
> >>> +
> >>> +#include <common.h>
> >>> +#include <malloc.h>
> >>> +#include <mapmem.h>
> >>> +#include <smbios.h>
> >>> +
> >>> +struct smbios_parser {
> >>> +     void *search_area;
> >>> +     unsigned int search_area_len;
> >>> +     struct smbios_entry *entry;
> >>> +     void *data;
> >>> +};
> >>> +
> >>> +static inline int verify_checksum(const struct smbios_entry *e)
> >>> +{
> >>> +     /*
> >>> +      * Checksums for SMBIOS tables are calculated to have a value, so that
> >>> +      * the sum over all bytes yields zero (using unsigned 8 bit arithmetic).
> >>> +      */
> >>> +     u8 *byte = (u8 *)e;
> >>> +     u8 sum = 0;
> >>> +
> >>> +     for (int i = 0; i < e->length; i++)
> >>> +             sum += byte[i];
> >>> +
> >>> +     return sum;
> >>> +}
> >>> +
> >>> +static struct smbios_entry *find_smbios_entry(const struct smbios_parser *p)
> >>> +{
> >>> +     static const char sm_sig[] = "_SM_";
> >>> +     u8 *buf = (u8 *)p->search_area;
> >>> +     const u8 *end = (u8 *)p->search_area + p->search_area_len;
> >>> +     struct smbios_entry *entry = NULL;
> >>> +
> >>> +     /* look for smbios entry */
> >>> +     while (buf < end) {
> >>
> >> Don't you have a way to pass the DMI pointer directly, maybe using cbfs?
> >> Searching through the SMBIOS search area is so 1990s (and pretty much
> >> only works on x86).
> >>
> > Coreboot adds a smbios cbmem entry which can be used to get the base address.
> > Will make use of that mechanism in the next version of the patch set.
>
>
> Thanks, that will make this code a lot more robust :).
>
>
> >
> >> I also don't think we really need all the smbios_parser logic. No need
> >> to create special pseudo objects. IMHO you should either create an
> >> actual UCLASS for SMBIOS with genuine callbacks and expose the table as
> >> DM object or just make all search functions in this patch stateless. I'd
> >> opt for the latter - it's how the SMBIOS creation works too.
> >>
> > I am not sure what you mean with 'special pseudo objects' - struct
> > smbios_parser?
>
>
> Yes. The parser is stateful. I would ideally like it best if it wasn't :).
>

One of the reasons I need the smbios_parser is the map_sysmem(..)
thing. Maybe I do not
need it at all - that would make the whole thing much simpler.


-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/2] smbios: add parsing API
  2019-04-29 15:41   ` Simon Glass
@ 2019-04-29 15:53     ` Christian Gmeiner
  0 siblings, 0 replies; 10+ messages in thread
From: Christian Gmeiner @ 2019-04-29 15:53 UTC (permalink / raw)
  To: u-boot

Am Mo., 29. Apr. 2019 um 17:41 Uhr schrieb Simon Glass <sjg@chromium.org>:
>
> Hi,
>
> On Thu, 25 Apr 2019 at 04:09, Alexander Graf <agraf@csgraf.de> wrote:
> >
> >
> > On 16.04.19 13:38, Christian Gmeiner wrote:
> > > Add an very simple API to be able to access SMBIOS strings
> > > like vendor, model and bios version.
> > >
> > > Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
> > > ---
> > >  include/smbios.h    |  37 ++++++++++
> > >  lib/Kconfig         |   6 ++
> > >  lib/Makefile        |   1 +
> > >  lib/smbios-parser.c | 162 ++++++++++++++++++++++++++++++++++++++++++++
> > >  4 files changed, 206 insertions(+)
> > >  create mode 100644 lib/smbios-parser.c
>
> Can you please also add a test for each of these functions, with sample data.
>
> BTW here is some code to write fake tables in case it helps:
>
> https://chromium-review.googlesource.com/c/chromiumos/platform2/+/1062212/6/chromeos-config/libcros_config/identity_x86.cc

Will try my best :)

-- 
greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [U-Boot] [PATCH 1/2] smbios: add parsing API
  2019-04-29 15:52       ` Christian Gmeiner
@ 2019-05-01  6:36         ` Alexander Graf
  0 siblings, 0 replies; 10+ messages in thread
From: Alexander Graf @ 2019-05-01  6:36 UTC (permalink / raw)
  To: u-boot



> Am 29.04.2019 um 17:52 schrieb Christian Gmeiner <christian.gmeiner@gmail.com>:
> 
>> Am Mo., 29. Apr. 2019 um 17:35 Uhr schrieb Alexander Graf <agraf@csgraf.de>:
>> 
>> 
>>> On 29.04.19 16:29, Christian Gmeiner wrote:
>>> Hi
>>> 
>>>> Am Do., 25. Apr. 2019 um 12:09 Uhr schrieb Alexander Graf <agraf@csgraf.de>:
>>>> 
>>>>> On 16.04.19 13:38, Christian Gmeiner wrote:
>>>>> Add an very simple API to be able to access SMBIOS strings
>>>>> like vendor, model and bios version.
>>>>> 
>>>>> Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com>
>>>>> ---
>>>>> include/smbios.h    |  37 ++++++++++
>>>>> lib/Kconfig         |   6 ++
>>>>> lib/Makefile        |   1 +
>>>>> lib/smbios-parser.c | 162 ++++++++++++++++++++++++++++++++++++++++++++
>>>>> 4 files changed, 206 insertions(+)
>>>>> create mode 100644 lib/smbios-parser.c
>>>>> 
>>>>> diff --git a/include/smbios.h b/include/smbios.h
>>>>> index 97b9ddce23..ad44e54245 100644
>>>>> --- a/include/smbios.h
>>>>> +++ b/include/smbios.h
>>>>> @@ -237,4 +237,41 @@ typedef int (*smbios_write_type)(ulong *addr, int handle);
>>>>>  */
>>>>> ulong write_smbios_table(ulong addr);
>>>>> 
>>>>> +
>>>>> +struct smbios_parser;
>>>>> +
>>>>> +/**
>>>>> + * smbios_parser_create() - Create smbios parser
>>>>> + *
>>>>> + * @addr:    start address to search for SMBIOS structure
>>>>> + * @len:     size of search area
>>>>> + * @return:  NULL or valid pointer to a struct smbios_parser
>>>>> + */
>>>>> +struct smbios_parser *smbios_parser_create(unsigned int addr, unsigned int len);
>>>>> +
>>>>> +/**
>>>>> + * smbios_parser_destroy() - Destroy smbios parser
>>>>> + *
>>>>> + * @p:       pointer to a struct smbios_parser
>>>>> + */
>>>>> +void smbios_parser_destroy(struct smbios_parser *p);
>>>>> +
>>>>> +/**
>>>>> + * smbios_header() - Search for SMBIOS header type
>>>>> + *
>>>>> + * @p:       pointer to a struct smbios_parser
>>>>> + * @type:    SMBIOS type
>>>>> + * @return:  NULL or a valid pointer to a struct smbios_header
>>>>> + */
>>>>> +struct smbios_header *smbios_header(const struct smbios_parser *p, int type);
>>>>> +
>>>>> +/**
>>>>> + * smbios_string() - Return string from SMBIOS
>>>>> + *
>>>>> + * @header:  pointer to struct smbios_header
>>>>> + * @index:   string index
>>>>> + * @return:  NULL or a valid const char pointer
>>>>> + */
>>>>> +const char *smbios_string(const struct smbios_header *header, int index);
>>>>> +
>>>>> #endif /* _SMBIOS_H_ */
>>>>> diff --git a/lib/Kconfig b/lib/Kconfig
>>>>> index 2120216593..59aafc63a7 100644
>>>>> --- a/lib/Kconfig
>>>>> +++ b/lib/Kconfig
>>>>> @@ -432,6 +432,12 @@ config SMBIOS_PRODUCT_NAME
>>>>> 
>>>>> endmenu
>>>>> 
>>>>> +config SMBIOS_PARSER
>>>>> +     bool "SMBIOS parser"
>>>>> +     default n
>>>>> +     help
>>>>> +       A simple parser for SMBIOS data.
>>>>> +
>>>>> source lib/efi/Kconfig
>>>>> source lib/efi_loader/Kconfig
>>>>> source lib/optee/Kconfig
>>>>> diff --git a/lib/Makefile b/lib/Makefile
>>>>> index 47829bfed5..f095bd420a 100644
>>>>> --- a/lib/Makefile
>>>>> +++ b/lib/Makefile
>>>>> @@ -34,6 +34,7 @@ obj-$(CONFIG_FIT) += fdtdec_common.o
>>>>> obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o
>>>>> obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o
>>>>> obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o
>>>>> +obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o
>>>>> obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o
>>>>> obj-y += ldiv.o
>>>>> obj-$(CONFIG_MD5) += md5.o
>>>>> diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
>>>>> new file mode 100644
>>>>> index 0000000000..b24fd7210c
>>>>> --- /dev/null
>>>>> +++ b/lib/smbios-parser.c
>>>>> @@ -0,0 +1,162 @@
>>>>> +// SPDX-License-Identifier: GPL-2.0+
>>>>> +/*
>>>>> + * Copyright (C) 2019, Bachmann electronic GmbH
>>>>> + */
>>>>> +
>>>>> +#include <common.h>
>>>>> +#include <malloc.h>
>>>>> +#include <mapmem.h>
>>>>> +#include <smbios.h>
>>>>> +
>>>>> +struct smbios_parser {
>>>>> +     void *search_area;
>>>>> +     unsigned int search_area_len;
>>>>> +     struct smbios_entry *entry;
>>>>> +     void *data;
>>>>> +};
>>>>> +
>>>>> +static inline int verify_checksum(const struct smbios_entry *e)
>>>>> +{
>>>>> +     /*
>>>>> +      * Checksums for SMBIOS tables are calculated to have a value, so that
>>>>> +      * the sum over all bytes yields zero (using unsigned 8 bit arithmetic).
>>>>> +      */
>>>>> +     u8 *byte = (u8 *)e;
>>>>> +     u8 sum = 0;
>>>>> +
>>>>> +     for (int i = 0; i < e->length; i++)
>>>>> +             sum += byte[i];
>>>>> +
>>>>> +     return sum;
>>>>> +}
>>>>> +
>>>>> +static struct smbios_entry *find_smbios_entry(const struct smbios_parser *p)
>>>>> +{
>>>>> +     static const char sm_sig[] = "_SM_";
>>>>> +     u8 *buf = (u8 *)p->search_area;
>>>>> +     const u8 *end = (u8 *)p->search_area + p->search_area_len;
>>>>> +     struct smbios_entry *entry = NULL;
>>>>> +
>>>>> +     /* look for smbios entry */
>>>>> +     while (buf < end) {
>>>> 
>>>> Don't you have a way to pass the DMI pointer directly, maybe using cbfs?
>>>> Searching through the SMBIOS search area is so 1990s (and pretty much
>>>> only works on x86).
>>>> 
>>> Coreboot adds a smbios cbmem entry which can be used to get the base address.
>>> Will make use of that mechanism in the next version of the patch set.
>> 
>> 
>> Thanks, that will make this code a lot more robust :).
>> 
>> 
>>> 
>>>> I also don't think we really need all the smbios_parser logic. No need
>>>> to create special pseudo objects. IMHO you should either create an
>>>> actual UCLASS for SMBIOS with genuine callbacks and expose the table as
>>>> DM object or just make all search functions in this patch stateless. I'd
>>>> opt for the latter - it's how the SMBIOS creation works too.
>>>> 
>>> I am not sure what you mean with 'special pseudo objects' - struct
>>> smbios_parser?
>> 
>> 
>> Yes. The parser is stateful. I would ideally like it best if it wasn't :).
>> 
> 
> One of the reasons I need the smbios_parser is the map_sysmem(..)
> thing. Maybe I do not
> need it at all - that would make the whole thing much simpler.

I think you need it for sandbox, so it's good to have around. But I don't understand why map_sysmem() brings any statefulness requirements?

Alex

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2019-05-01  6:36 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-16 11:38 [U-Boot] [PATCH 1/2] smbios: add parsing API Christian Gmeiner
2019-04-16 11:38 ` [U-Boot] [PATCH 2/2] coreboot: make use of smbios parser Christian Gmeiner
2019-04-25  6:27 ` [U-Boot] [PATCH 1/2] smbios: add parsing API Christian Gmeiner
2019-04-25 10:09 ` Alexander Graf
2019-04-29 14:29   ` Christian Gmeiner
2019-04-29 15:35     ` Alexander Graf
2019-04-29 15:52       ` Christian Gmeiner
2019-05-01  6:36         ` Alexander Graf
2019-04-29 15:41   ` Simon Glass
2019-04-29 15:53     ` Christian Gmeiner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.