Message ID | 20201007123335.86983-1-christian.gmeiner@gmail.com |
---|---|
State | Superseded |
Delegated to: | Bin Meng |
Headers | show |
Series | [v2,1/2] smbios: add parsing API | expand |
ping and a short question: would it make more sense to put the parsing code into smbios.c and unconditionally compile it? Am Mi., 7. Okt. 2020 um 14:33 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. > > Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com> > --- > include/smbios.h | 27 +++++++++++++ > lib/Kconfig | 6 +++ > lib/Makefile | 1 + > lib/smbios-parser.c | 96 +++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 130 insertions(+) > create mode 100644 lib/smbios-parser.c > > diff --git a/include/smbios.h b/include/smbios.h > index 97b9ddce23..ed60c00fae 100644 > --- a/include/smbios.h > +++ b/include/smbios.h > @@ -237,4 +237,31 @@ typedef int (*smbios_write_type)(ulong *addr, int handle); > */ > ulong write_smbios_table(ulong addr); > > +/** > + * smbios_entry() - Get a vaild struct smbios_entry pointer > + * > + * @address: address where smbios tables is located > + * @size: size of smbios table > + * @return: NULL or a valid pointer to a struct smbios_entry > + */ > +const struct smbios_entry *smbios_entry(u64 address, u32 size); > + > +/** > + * smbios_header() - Search for SMBIOS header type > + * > + * @entry: pointer to a struct smbios_entry > + * @type: SMBIOS type > + * @return: NULL or a valid pointer to a struct smbios_header > + */ > +const struct smbios_header *smbios_header(const struct smbios_entry *entry, 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 8efb154f73..c92131b7bc 100644 > --- a/lib/Kconfig > +++ b/lib/Kconfig > @@ -667,6 +667,12 @@ config OID_REGISTRY > help > Enable fast lookup object identifier registry. > > +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 0cd7bea282..0383fddf2c 100644 > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -37,6 +37,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_XXHASH) += xxhash.o > diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c > new file mode 100644 > index 0000000000..b89f988ef9 > --- /dev/null > +++ b/lib/smbios-parser.c > @@ -0,0 +1,96 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright (C) 2020, Bachmann electronic GmbH > + */ > + > +#include <common.h> > +#include <smbios.h> > + > +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; > +} > + > +const struct smbios_entry *smbios_entry(u64 address, u32 size) > +{ > + const struct smbios_entry *entry = (struct smbios_entry *)(uintptr_t)address; > + > + if (!address | !size) > + return NULL; > + > + if (memcmp(entry->anchor, "_SM_", 4)) > + return NULL; > + > + if (verify_checksum(entry)) > + return NULL; > + > + return entry; > +} > + > +static const 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; > +} > + > +const struct smbios_header *smbios_header(const struct smbios_entry *entry, int type) > +{ > + const unsigned int num_header = entry->struct_count; > + const struct smbios_header *header = (struct smbios_header *)entry->struct_table_address; > + > + 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.28.0 >
On Mon, Nov 2, 2020 at 5:21 PM Christian Gmeiner <christian.gmeiner@gmail.com> wrote: > > ping and a short question: would it make more sense to put the parsing > code into smbios.c and unconditionally compile it? I think it's fine to leave this as a separte module. Reviewed-by: Bin Meng <bmeng.cn@gmail.com> But nits below: > > Am Mi., 7. Okt. 2020 um 14:33 Uhr schrieb Christian Gmeiner > <christian.gmeiner@gmail.com>: > > > > Add an very simple API to be able to access SMBIOS strings an -> a > > like vendor, model and bios version. > > > > Signed-off-by: Christian Gmeiner <christian.gmeiner@gmail.com> > > --- > > include/smbios.h | 27 +++++++++++++ > > lib/Kconfig | 6 +++ > > lib/Makefile | 1 + > > lib/smbios-parser.c | 96 +++++++++++++++++++++++++++++++++++++++++++++ > > 4 files changed, 130 insertions(+) > > create mode 100644 lib/smbios-parser.c > > > > diff --git a/include/smbios.h b/include/smbios.h > > index 97b9ddce23..ed60c00fae 100644 > > --- a/include/smbios.h > > +++ b/include/smbios.h > > @@ -237,4 +237,31 @@ typedef int (*smbios_write_type)(ulong *addr, int handle); > > */ > > ulong write_smbios_table(ulong addr); > > > > +/** > > + * smbios_entry() - Get a vaild struct smbios_entry pointer typo: valid > > + * > > + * @address: address where smbios tables is located > > + * @size: size of smbios table > > + * @return: NULL or a valid pointer to a struct smbios_entry > > + */ > > +const struct smbios_entry *smbios_entry(u64 address, u32 size); > > + > > +/** > > + * smbios_header() - Search for SMBIOS header type > > + * > > + * @entry: pointer to a struct smbios_entry > > + * @type: SMBIOS type > > + * @return: NULL or a valid pointer to a struct smbios_header > > + */ > > +const struct smbios_header *smbios_header(const struct smbios_entry *entry, 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 8efb154f73..c92131b7bc 100644 > > --- a/lib/Kconfig > > +++ b/lib/Kconfig > > @@ -667,6 +667,12 @@ config OID_REGISTRY > > help > > Enable fast lookup object identifier registry. > > > > +config SMBIOS_PARSER > > + bool "SMBIOS parser" > > + default n nits: remove default n, because it is Kconfig default > > + 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 0cd7bea282..0383fddf2c 100644 > > --- a/lib/Makefile > > +++ b/lib/Makefile > > @@ -37,6 +37,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_XXHASH) += xxhash.o > > diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c > > new file mode 100644 > > index 0000000000..b89f988ef9 > > --- /dev/null > > +++ b/lib/smbios-parser.c > > @@ -0,0 +1,96 @@ > > +// SPDX-License-Identifier: GPL-2.0+ > > +/* > > + * Copyright (C) 2020, Bachmann electronic GmbH > > + */ > > + > > +#include <common.h> > > +#include <smbios.h> > > + > > +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; > > +} > > + > > +const struct smbios_entry *smbios_entry(u64 address, u32 size) > > +{ > > + const struct smbios_entry *entry = (struct smbios_entry *)(uintptr_t)address; > > + > > + if (!address | !size) > > + return NULL; > > + > > + if (memcmp(entry->anchor, "_SM_", 4)) > > + return NULL; > > + > > + if (verify_checksum(entry)) > > + return NULL; > > + > > + return entry; > > +} > > + > > +static const 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; > > +} > > + > > +const struct smbios_header *smbios_header(const struct smbios_entry *entry, int type) > > +{ > > + const unsigned int num_header = entry->struct_count; > > + const struct smbios_header *header = (struct smbios_header *)entry->struct_table_address; > > + > > + 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.28.0 Regards, Bin
diff --git a/include/smbios.h b/include/smbios.h index 97b9ddce23..ed60c00fae 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -237,4 +237,31 @@ typedef int (*smbios_write_type)(ulong *addr, int handle); */ ulong write_smbios_table(ulong addr); +/** + * smbios_entry() - Get a vaild struct smbios_entry pointer + * + * @address: address where smbios tables is located + * @size: size of smbios table + * @return: NULL or a valid pointer to a struct smbios_entry + */ +const struct smbios_entry *smbios_entry(u64 address, u32 size); + +/** + * smbios_header() - Search for SMBIOS header type + * + * @entry: pointer to a struct smbios_entry + * @type: SMBIOS type + * @return: NULL or a valid pointer to a struct smbios_header + */ +const struct smbios_header *smbios_header(const struct smbios_entry *entry, 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 8efb154f73..c92131b7bc 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -667,6 +667,12 @@ config OID_REGISTRY help Enable fast lookup object identifier registry. +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 0cd7bea282..0383fddf2c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -37,6 +37,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_XXHASH) += xxhash.o diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c new file mode 100644 index 0000000000..b89f988ef9 --- /dev/null +++ b/lib/smbios-parser.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020, Bachmann electronic GmbH + */ + +#include <common.h> +#include <smbios.h> + +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; +} + +const struct smbios_entry *smbios_entry(u64 address, u32 size) +{ + const struct smbios_entry *entry = (struct smbios_entry *)(uintptr_t)address; + + if (!address | !size) + return NULL; + + if (memcmp(entry->anchor, "_SM_", 4)) + return NULL; + + if (verify_checksum(entry)) + return NULL; + + return entry; +} + +static const 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; +} + +const struct smbios_header *smbios_header(const struct smbios_entry *entry, int type) +{ + const unsigned int num_header = entry->struct_count; + const struct smbios_header *header = (struct smbios_header *)entry->struct_table_address; + + 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); +}
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 | 27 +++++++++++++ lib/Kconfig | 6 +++ lib/Makefile | 1 + lib/smbios-parser.c | 96 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 130 insertions(+) create mode 100644 lib/smbios-parser.c