1/* 2 * lib/mask.c 3 * 4 * This file is subject to the terms and conditions of the GNU General Public 5 * License. See the file "COPYING" in the main directory of this archive 6 * for more details. 7 * 8 * Copyright (C) 2003 Silicon Graphics, Inc. All Rights Reserved. 9 */ 10 11/* 12 * Routines to manipulate multi-word bit masks, such as cpumasks. 13 * 14 * The ascii representation of multi-word bit masks displays each 15 * 32bit word in hex (not zero filled), and for masks longer than 16 * one word, uses a comma separator between words. Words are 17 * displayed in big-endian order most significant first. And hex 18 * digits within a word are also in big-endian order, of course. 19 * 20 * Examples: 21 * A mask with just bit 0 set displays as "1". 22 * A mask with just bit 127 set displays as "80000000,0,0,0". 23 * A mask with just bit 64 set displays as "1,0,0". 24 * A mask with bits 0, 1, 2, 4, 8, 16, 32 and 64 set displays 25 * as "1,1,10117". The first "1" is for bit 64, the second 26 * for bit 32, the third for bit 16, and so forth, to the 27 * "7", which is for bits 2, 1 and 0. 28 * A mask with bits 32 through 39 set displays as "ff,0". 29 * 30 * The internal binary representation of masks is as one or 31 * an array of unsigned longs, perhaps wrapped in a struct for 32 * convenient use as an lvalue. The following code doesn't know 33 * about any such struct details, relying on inline macros in 34 * files such as cpumask.h to pass in an unsigned long pointer 35 * and a length (in bytes), describing the mask contents. 36 * The 32bit words in the array are in little-endian order, 37 * low order word first. Beware that this is the reverse order 38 * of the ascii representation. 39 * 40 * Even though the size of the input mask is provided in bytes, 41 * the following code may assume that the mask is a multiple of 42 * 32 or 64 bit words long, and ignore any fractional portion 43 * of a word at the end. The main reason the size is passed in 44 * bytes is because it is so easy to write 'sizeof(somemask_t)' 45 * in the macros. 46 * 47 * Masks are not a single,simple type, like classic 'C' 48 * nul-term strings. Rather they are a family of types, one 49 * for each different length. Inline macros are used to pick 50 * up the actual length, where it is known to the compiler, and 51 * pass it down to these routines, which work on any specified 52 * length array of unsigned longs. Poor man's templates. 53 * 54 * Many of the inline macros don't call into the following 55 * routines. Some of them call into other kernel routines, 56 * such as memset(), set_bit() or ffs(). Some of them can 57 * accomplish their task right inline, such as returning the 58 * size or address of the unsigned long array, or optimized 59 * versions of the macros for the most common case of an array 60 * of a single unsigned long. 61 */ 62 63#include <linux/kernel.h> 64#include <linux/string.h> 65#include <linux/ctype.h> 66#include <linux/slab.h> 67#include <linux/errno.h> 68#include <linux/gfp.h> 69#include <asm/uaccess.h> 70 71#define MAX_HEX_PER_BYTE 4 /* dont need > 4 hex chars to encode byte */ 72#define BASE 16 /* masks are input in hex (base 16) */ 73#define NUL ((char)'\0') /* nul-terminator */ 74 75/** 76 * __mask_snprintf_len - represent multi-word bit mask as string. 77 * @buf: The buffer to place the result into 78 * @buflen: The size of the buffer, including the trailing null space 79 * @maskp: Points to beginning of multi-word bit mask. 80 * @maskbytes: Number of bytes in bit mask at maskp. 81 * 82 * This routine is expected to be called from a macro such as: 83 * 84 * #define cpumask_snprintf(buf, buflen, mask) \ 85 * __mask_snprintf_len(buf, buflen, cpus_addr(mask), sizeof(mask)) 86 */ 87 88int __mask_snprintf_len(char *buf, unsigned int buflen, 89 const unsigned long *maskp, unsigned int maskbytes) 90{ 91 u32 *wordp = (u32 *)maskp; 92 int i = maskbytes/sizeof(u32) - 1; 93 int len = 0; 94 char *sep = ""; 95 96 while (i >= 1 && wordp[i] == 0) 97 i--; 98 while (i >= 0) { 99 len += snprintf(buf+len, buflen-len, "%s%x", sep, wordp[i]); 100 sep = ","; 101 i--; 102 } 103 return len; 104} 105 106/** 107 * __mask_parse_len - parse user string into maskbytes mask at maskp 108 * @ubuf: The user buffer from which to take the string 109 * @ubuflen: The size of this buffer, including the terminating char 110 * @maskp: Place resulting mask (array of unsigned longs) here 111 * @masklen: Construct mask at @maskp to have exactly @masklen bytes 112 * 113 * @masklen is a multiple of sizeof(unsigned long). A mask of 114 * @masklen bytes is constructed starting at location @maskp. 115 * The value of this mask is specified by the user provided 116 * string starting at address @ubuf. Only bytes in the range 117 * [@ubuf, @ubuf+@ubuflen) can be read from user space, and 118 * reading will stop after the first byte that is not a comma 119 * or valid hex digit in the characters [,0-9a-fA-F], or at 120 * the point @ubuf+@ubuflen, whichever comes first. 121 * 122 * Since the user only needs about 2.25 chars per byte to encode 123 * a mask (one char per nibble plus one comma separator or nul 124 * terminator per byte), we blow them off with -EINVAL if they 125 * claim a @ubuflen more than 4 (MAX_HEX_PER_BYTE) times maskbytes. 126 * An empty word (delimited by two consecutive commas, for example) 127 * is taken as zero. If @buflen is zero, the entire @maskp is set 128 * to zero. 129 * 130 * If the user provides fewer comma-separated ascii words 131 * than there are 32 bit words in maskbytes, we zero fill the 132 * remaining high order words. If they provide more, they fail 133 * with -EINVAL. Each comma-separate ascii word is taken as 134 * a hex representation; leading zeros are ignored, and do not 135 * imply octal. '00e1', 'e1', '00E1', 'E1' are all the same. 136 * If user passes a word that is larger than fits in a u32, 137 * they fail with -EOVERFLOW. 138 */ 139 140int __mask_parse_len(const char __user *ubuf, unsigned int ubuflen, 141 unsigned long *maskp, unsigned int maskbytes) 142{ 143 char buf[maskbytes * MAX_HEX_PER_BYTE + sizeof(NUL)]; 144 char *bp = buf; 145 u32 *wordp = (u32 *)maskp; 146 char *p; 147 int i, j; 148 149 if (ubuflen > maskbytes * MAX_HEX_PER_BYTE) 150 return -EINVAL; 151 if (copy_from_user(buf, ubuf, ubuflen)) 152 return -EFAULT; 153 buf[ubuflen] = NUL; 154 155 /* 156 * Put the words into wordp[] in big-endian order, 157 * then go back and reverse them. 158 */ 159 memset(wordp, 0, maskbytes); 160 i = j = 0; 161 while ((p = strsep(&bp, ",")) != NULL) { 162 unsigned long long t; 163 if (j == maskbytes/sizeof(u32)) 164 return -EINVAL; 165 t = simple_strtoull(p, 0, BASE); 166 if (t != (u32)t) 167 return -EOVERFLOW; 168 wordp[j++] = t; 169 } 170 --j; 171 while (i < j) { 172 u32 t = wordp[i]; 173 wordp[i] = wordp[j]; 174 wordp[j] = t; 175 i++, --j; 176 } 177 return 0; 178} 179

