smbios: Allow writing to the coreboot version string
When U-Boot is booted from coreboot the SMBIOS tables are written by coreboot, not U-Boot. The existing method of updating the BIOS version string does not work in that case, since gd->smbios_version is only set when U-Boot writes the tables. Add a new function which allows the version to be updated by parsing the tables and writing the string in the correct place. Since coreboot provides a pointer to the SMBIOS tables in its sysinfo structure, this makes it easy to do the update. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
		
							parent
							
								
									11a38a2573
								
							
						
					
					
						commit
						272e62cb83
					
				|  | @ -14,6 +14,10 @@ | ||||||
| #define SMBIOS_MAJOR_VER	3 | #define SMBIOS_MAJOR_VER	3 | ||||||
| #define SMBIOS_MINOR_VER	0 | #define SMBIOS_MINOR_VER	0 | ||||||
| 
 | 
 | ||||||
|  | enum { | ||||||
|  | 	SMBIOS_STR_MAX	= 64,	/* Maximum length allowed for a string */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /* SMBIOS structure types */ | /* SMBIOS structure types */ | ||||||
| enum { | enum { | ||||||
| 	SMBIOS_BIOS_INFORMATION = 0, | 	SMBIOS_BIOS_INFORMATION = 0, | ||||||
|  | @ -269,4 +273,20 @@ const char *smbios_string(const struct smbios_header *header, int index); | ||||||
|  */ |  */ | ||||||
| int smbios_update_version(const char *version); | int smbios_update_version(const char *version); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * smbios_update_version_full() - 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). | ||||||
|  |  * It scans for the correct place to put the version, so does not need U-Boot | ||||||
|  |  * to have actually written the tables itself (e.g. if a previous bootloader | ||||||
|  |  * did it). | ||||||
|  |  * | ||||||
|  |  * @smbios_tab: Start of SMBIOS tables | ||||||
|  |  * @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_full(void *smbios_tab, const char *version); | ||||||
|  | 
 | ||||||
| #endif /* _SMBIOS_H_ */ | #endif /* _SMBIOS_H_ */ | ||||||
|  |  | ||||||
|  | @ -3,6 +3,8 @@ | ||||||
|  * Copyright (C) 2020, Bachmann electronic GmbH |  * Copyright (C) 2020, Bachmann electronic GmbH | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #define LOG_CATEGORY	LOGC_BOOT | ||||||
|  | 
 | ||||||
| #include <common.h> | #include <common.h> | ||||||
| #include <smbios.h> | #include <smbios.h> | ||||||
| 
 | 
 | ||||||
|  | @ -94,3 +96,39 @@ const char *smbios_string(const struct smbios_header *header, int index) | ||||||
| 
 | 
 | ||||||
| 	return string_from_smbios_table(header, index); | 	return string_from_smbios_table(header, index); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | int smbios_update_version_full(void *smbios_tab, const char *version) | ||||||
|  | { | ||||||
|  | 	const struct smbios_header *hdr; | ||||||
|  | 	struct smbios_type0 *bios; | ||||||
|  | 	uint old_len, len; | ||||||
|  | 	char *ptr; | ||||||
|  | 
 | ||||||
|  | 	log_info("Updating SMBIOS table at %p\n", smbios_tab); | ||||||
|  | 	hdr = smbios_header(smbios_tab, SMBIOS_BIOS_INFORMATION); | ||||||
|  | 	if (!hdr) | ||||||
|  | 		return log_msg_ret("tab", -ENOENT); | ||||||
|  | 	bios = (struct smbios_type0 *)hdr; | ||||||
|  | 	ptr = (char *)smbios_string(hdr, bios->bios_ver); | ||||||
|  | 	if (!ptr) | ||||||
|  | 		return log_msg_ret("str", -ENOMEDIUM); | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * 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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -20,10 +20,6 @@ | ||||||
| 
 | 
 | ||||||
| DECLARE_GLOBAL_DATA_PTR; | DECLARE_GLOBAL_DATA_PTR; | ||||||
| 
 | 
 | ||||||
| enum { |  | ||||||
| 	SMBIOS_STR_MAX	= 64,	/* Maximum length allowed for a string */ |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /**
 | /**
 | ||||||
|  * struct smbios_ctx - context for writing SMBIOS tables |  * struct smbios_ctx - context for writing SMBIOS tables | ||||||
|  * |  * | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue