efi/cper: Add a new helper function to print bitmasks

Add a helper function to print a string with names associated
to each bit field.

A typical example is:

	const char * const bits[] = {
		"bit 3 name",
		"bit 4 name",
		"bit 5 name",
	};
	char str[120];
        unsigned int bitmask = BIT(3) | BIT(5);

	#define MASK  GENMASK(5,3)

	cper_bits_to_str(str, sizeof(str), FIELD_GET(MASK, bitmask),
			 bits, ARRAY_SIZE(bits));

The above code fills string "str" with "bit 3 name|bit 5 name".

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Acked-by: Borislav Petkov (AMD) <bp@alien8.de>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
Mauro Carvalho Chehab 2025-08-14 09:52:54 -07:00 committed by Ard Biesheuvel
parent 8ad2c72e21
commit a976d790f4
2 changed files with 62 additions and 0 deletions

View File

@ -12,6 +12,7 @@
* Specification version 2.4. * Specification version 2.4.
*/ */
#include <linux/bitmap.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/time.h> #include <linux/time.h>
@ -106,6 +107,65 @@ void cper_print_bits(const char *pfx, unsigned int bits,
printk("%s\n", buf); printk("%s\n", buf);
} }
/**
* cper_bits_to_str - return a string for set bits
* @buf: buffer to store the output string
* @buf_size: size of the output string buffer
* @bits: bit mask
* @strs: string array, indexed by bit position
* @strs_size: size of the string array: @strs
*
* Add to @buf the bitmask in hexadecimal. Then, for each set bit in @bits,
* add the corresponding string describing the bit in @strs to @buf.
*
* A typical example is::
*
* const char * const bits[] = {
* "bit 3 name",
* "bit 4 name",
* "bit 5 name",
* };
* char str[120];
* unsigned int bitmask = BIT(3) | BIT(5);
* #define MASK GENMASK(5,3)
*
* cper_bits_to_str(str, sizeof(str), FIELD_GET(MASK, bitmask),
* bits, ARRAY_SIZE(bits));
*
* The above code fills the string ``str`` with ``bit 3 name|bit 5 name``.
*
* Return: number of bytes stored or an error code if lower than zero.
*/
int cper_bits_to_str(char *buf, int buf_size, unsigned long bits,
const char * const strs[], unsigned int strs_size)
{
int len = buf_size;
char *str = buf;
int i, size;
*buf = '\0';
for_each_set_bit(i, &bits, strs_size) {
if (!(bits & BIT_ULL(i)))
continue;
if (*buf && len > 0) {
*str = '|';
len--;
str++;
}
size = strscpy(str, strs[i], len);
if (size < 0)
return size;
len -= size;
str += size;
}
return len - buf_size;
}
EXPORT_SYMBOL_GPL(cper_bits_to_str);
static const char * const proc_type_strs[] = { static const char * const proc_type_strs[] = {
"IA32/X64", "IA32/X64",
"IA64", "IA64",

View File

@ -588,6 +588,8 @@ const char *cper_mem_err_type_str(unsigned int);
const char *cper_mem_err_status_str(u64 status); const char *cper_mem_err_status_str(u64 status);
void cper_print_bits(const char *prefix, unsigned int bits, void cper_print_bits(const char *prefix, unsigned int bits,
const char * const strs[], unsigned int strs_size); const char * const strs[], unsigned int strs_size);
int cper_bits_to_str(char *buf, int buf_size, unsigned long bits,
const char * const strs[], unsigned int strs_size);
void cper_mem_err_pack(const struct cper_sec_mem_err *, void cper_mem_err_pack(const struct cper_sec_mem_err *,
struct cper_mem_err_compact *); struct cper_mem_err_compact *);
const char *cper_mem_err_unpack(struct trace_seq *, const char *cper_mem_err_unpack(struct trace_seq *,