Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Mauro Carvalho Chehab and committed by
Ard Biesheuvel
a976d790 8ad2c72e

+62
+60
drivers/firmware/efi/cper.c
··· 12 12 * Specification version 2.4. 13 13 */ 14 14 15 + #include <linux/bitmap.h> 15 16 #include <linux/kernel.h> 16 17 #include <linux/module.h> 17 18 #include <linux/time.h> ··· 106 105 if (len) 107 106 printk("%s\n", buf); 108 107 } 108 + 109 + /** 110 + * cper_bits_to_str - return a string for set bits 111 + * @buf: buffer to store the output string 112 + * @buf_size: size of the output string buffer 113 + * @bits: bit mask 114 + * @strs: string array, indexed by bit position 115 + * @strs_size: size of the string array: @strs 116 + * 117 + * Add to @buf the bitmask in hexadecimal. Then, for each set bit in @bits, 118 + * add the corresponding string describing the bit in @strs to @buf. 119 + * 120 + * A typical example is:: 121 + * 122 + * const char * const bits[] = { 123 + * "bit 3 name", 124 + * "bit 4 name", 125 + * "bit 5 name", 126 + * }; 127 + * char str[120]; 128 + * unsigned int bitmask = BIT(3) | BIT(5); 129 + * #define MASK GENMASK(5,3) 130 + * 131 + * cper_bits_to_str(str, sizeof(str), FIELD_GET(MASK, bitmask), 132 + * bits, ARRAY_SIZE(bits)); 133 + * 134 + * The above code fills the string ``str`` with ``bit 3 name|bit 5 name``. 135 + * 136 + * Return: number of bytes stored or an error code if lower than zero. 137 + */ 138 + int cper_bits_to_str(char *buf, int buf_size, unsigned long bits, 139 + const char * const strs[], unsigned int strs_size) 140 + { 141 + int len = buf_size; 142 + char *str = buf; 143 + int i, size; 144 + 145 + *buf = '\0'; 146 + 147 + for_each_set_bit(i, &bits, strs_size) { 148 + if (!(bits & BIT_ULL(i))) 149 + continue; 150 + 151 + if (*buf && len > 0) { 152 + *str = '|'; 153 + len--; 154 + str++; 155 + } 156 + 157 + size = strscpy(str, strs[i], len); 158 + if (size < 0) 159 + return size; 160 + 161 + len -= size; 162 + str += size; 163 + } 164 + return len - buf_size; 165 + } 166 + EXPORT_SYMBOL_GPL(cper_bits_to_str); 109 167 110 168 static const char * const proc_type_strs[] = { 111 169 "IA32/X64",
+2
include/linux/cper.h
··· 588 588 const char *cper_mem_err_status_str(u64 status); 589 589 void cper_print_bits(const char *prefix, unsigned int bits, 590 590 const char * const strs[], unsigned int strs_size); 591 + int cper_bits_to_str(char *buf, int buf_size, unsigned long bits, 592 + const char * const strs[], unsigned int strs_size); 591 593 void cper_mem_err_pack(const struct cper_sec_mem_err *, 592 594 struct cper_mem_err_compact *); 593 595 const char *cper_mem_err_unpack(struct trace_seq *,