Commit a976d790 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab Committed by Ard Biesheuvel
Browse files

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: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Acked-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent 8ad2c72e
Loading
Loading
Loading
Loading
+60 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
 * Specification version 2.4.
 */

#include <linux/bitmap.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/time.h>
@@ -106,6 +107,65 @@ void cper_print_bits(const char *pfx, unsigned int bits,
		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[] = {
	"IA32/X64",
	"IA64",
+2 −0
Original line number Diff line number Diff line
@@ -588,6 +588,8 @@ const char *cper_mem_err_type_str(unsigned int);
const char *cper_mem_err_status_str(u64 status);
void cper_print_bits(const char *prefix, unsigned int bits,
		     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 *,
		       struct cper_mem_err_compact *);
const char *cper_mem_err_unpack(struct trace_seq *,