On Thu, Jan 21, 2021 at 10:07 AM Simon Glass <s...@chromium.org> wrote: > > At present the version string is obtained from PLAIN_VERSION. Some boards > may want to configure this using the device tree, since the build system > can more easily insert things there after U-Boot itself is built. Add this > option to the code. > > Also in some cases the version needs to be generated programmatically, > such as when it is stored elsewhere in the ROM and must be read first. > To handle this, keep a pointer around so that it can be updated later. > This works by storing the last string in the context, since it is easier > than passing out a little-used extra parameter. > > Provide a function to update the version string. > > Signed-off-by: Simon Glass <s...@chromium.org> > --- > > Changes in v2: > - Correct documentation format > > include/asm-generic/global_data.h | 6 ++++ > include/smbios.h | 12 +++++++ > lib/smbios.c | 56 +++++++++++++++++++++++++++++-- > 3 files changed, 71 insertions(+), 3 deletions(-) > > diff --git a/include/asm-generic/global_data.h > b/include/asm-generic/global_data.h > index 19f70393b45..750e998d885 100644 > --- a/include/asm-generic/global_data.h > +++ b/include/asm-generic/global_data.h > @@ -439,6 +439,12 @@ struct global_data { > */ > struct acpi_ctx *acpi_ctx; > #endif > +#if CONFIG_IS_ENABLED(GENERATE_SMBIOS_TABLE) > + /** > + * @smbios_version: Points to SMBIOS type 0 version > + */ > + char *smbios_version; > +#endif > }; > > /** > diff --git a/include/smbios.h b/include/smbios.h > index 1cbeabf9522..ecc4fd1de3b 100644 > --- a/include/smbios.h > +++ b/include/smbios.h > @@ -257,4 +257,16 @@ const struct smbios_header *smbios_header(const struct > smbios_entry *entry, int > */ > const char *smbios_string(const struct smbios_header *header, int index); > > +/** > + * smbios_update_version() - Update the version string > + * > + * This can be called after the SMBIOS tables are written (e.g. after the > U-Boot > + * main loop has started) to update the BIOS version string (SMBIOS table 0). > + * > + * @version: New version string to use > + * @return 0 if OK, -ENOENT if no version string was previously written, > + * -ENOSPC if the new string is too large to fit > + */ > +int smbios_update_version(const char *version); > + > #endif /* _SMBIOS_H_ */ > diff --git a/lib/smbios.c b/lib/smbios.c > index 7090460bc02..d46569b09f4 100644 > --- a/lib/smbios.c > +++ b/lib/smbios.c > @@ -17,6 +17,10 @@ > #include <dm/uclass-internal.h> > #endif > > +enum { > + SMBIOS_STR_MAX = 64, /* Maximum length allowed for a string */ > +}; > + > /** > * struct smbios_ctx - context for writing SMBIOS tables > * > @@ -27,12 +31,15 @@ > * @next_ptr: pointer to the start of the next string to be added. When the > * table is nopt empty, this points to the byte after the \0 of > the > * previous string. > + * @last_str: points to the last string that was written to the table, or > NULL > + * if none > */ > struct smbios_ctx { > ofnode node; > struct udevice *dev; > char *eos; > char *next_ptr; > + char *last_str; > }; > > /** > @@ -78,6 +85,7 @@ static int smbios_add_string(struct smbios_ctx *ctx, const > char *str) > > for (;;) { > if (!*p) { > + ctx->last_str = p; > strcpy(p, str); > p += strlen(str); > *p++ = '\0'; > @@ -87,8 +95,10 @@ static int smbios_add_string(struct smbios_ctx *ctx, const > char *str) > return i; > } > > - if (!strcmp(p, str)) > + if (!strcmp(p, str)) { > + ctx->last_str = p; > return i; > + } > > p += strlen(p) + 1; > i++; > @@ -120,6 +130,35 @@ static void set_eos(struct smbios_ctx *ctx, char *eos) > { > ctx->eos = eos; > ctx->next_ptr = eos; > + ctx->last_str = NULL; > +} > + > +int smbios_update_version(const char *version) > +{ > + char *ptr = gd->smbios_version;
Missing DECLARE_GLOBAL_DATA_PTR? > + uint old_len, len; > + > + if (!ptr) > + return log_ret(-ENOENT); > + > + /* > + * This string is supposed to have at least enough bytes and is > + * padded with spaces. Update it, taking care not to move the > + * \0 terminator, so that other strings in the string table > + * are not disturbed. See smbios_add_string() > + */ > + old_len = strnlen(ptr, SMBIOS_STR_MAX); > + len = strnlen(version, SMBIOS_STR_MAX); > + if (len > old_len) > + return log_ret(-ENOSPC); > + > + log_debug("Replacing SMBIOS type 0 version string '%s'\n", ptr); > + memcpy(ptr, version, len); > +#ifdef LOG_DEBUG > + print_buffer((ulong)ptr, ptr, 1, old_len + 1, 0); > +#endif > + > + return 0; > } > > /** > @@ -147,7 +186,18 @@ static int smbios_write_type0(ulong *current, int handle, > fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle); > set_eos(ctx, t->eos); > t->vendor = smbios_add_string(ctx, "U-Boot"); > - t->bios_ver = smbios_add_string(ctx, PLAIN_VERSION); > + > + t->bios_ver = smbios_add_prop(ctx, "version"); > + if (!t->bios_ver) > + t->bios_ver = smbios_add_string(ctx, PLAIN_VERSION); > + if (t->bios_ver) > + gd->smbios_version = ctx->last_str; > + log_debug("smbios_version = %p: '%s'\n", gd->smbios_version, > + gd->smbios_version); > +#ifdef LOG_DEBUG > + print_buffer((ulong)gd->smbios_version, gd->smbios_version, > + 1, strlen(gd->smbios_version) + 1, 0); > +#endif > t->bios_release_date = smbios_add_string(ctx, U_BOOT_DMI_DATE); > #ifdef CONFIG_ROM_SIZE > t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1; > @@ -346,7 +396,7 @@ static int smbios_write_type127(ulong *current, int > handle, > } > > static struct smbios_write_method smbios_write_funcs[] = { > - { smbios_write_type0, }, > + { smbios_write_type0, "bios", }, > { smbios_write_type1, "system", }, > { smbios_write_type2, "baseboard", }, > { smbios_write_type3, "chassis", }, > -- Reviewed-by: Bin Meng <bmeng...@gmail.com>