forked from Minki/linux
e7f01d1e3d
Several places were expecting that the value returned was the number of characters printed, not what would be printed if there was space. Fix it by using the scnprintf and vscnprintf variants we inherited from the kernel sources. Some corner cases where the number of printed characters were not accounted were fixed too. Reported-by: Anton Blanchard <anton@samba.org> Cc: Anton Blanchard <anton@samba.org> Cc: Eric B Munson <emunson@mgebm.net> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Yanmin Zhang <yanmin_zhang@linux.intel.com> Cc: stable@kernel.org Link: http://lkml.kernel.org/n/tip-kwxo2eh29cxmd8ilixi2005x@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
60 lines
1.2 KiB
C
60 lines
1.2 KiB
C
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "../../util/header.h"
|
|
|
|
static inline void
|
|
cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
|
|
unsigned int *d)
|
|
{
|
|
__asm__ __volatile__ (".byte 0x53\n\tcpuid\n\t"
|
|
"movl %%ebx, %%esi\n\t.byte 0x5b"
|
|
: "=a" (*a),
|
|
"=S" (*b),
|
|
"=c" (*c),
|
|
"=d" (*d)
|
|
: "a" (op));
|
|
}
|
|
|
|
int
|
|
get_cpuid(char *buffer, size_t sz)
|
|
{
|
|
unsigned int a, b, c, d, lvl;
|
|
int family = -1, model = -1, step = -1;
|
|
int nb;
|
|
char vendor[16];
|
|
|
|
cpuid(0, &lvl, &b, &c, &d);
|
|
strncpy(&vendor[0], (char *)(&b), 4);
|
|
strncpy(&vendor[4], (char *)(&d), 4);
|
|
strncpy(&vendor[8], (char *)(&c), 4);
|
|
vendor[12] = '\0';
|
|
|
|
if (lvl >= 1) {
|
|
cpuid(1, &a, &b, &c, &d);
|
|
|
|
family = (a >> 8) & 0xf; /* bits 11 - 8 */
|
|
model = (a >> 4) & 0xf; /* Bits 7 - 4 */
|
|
step = a & 0xf;
|
|
|
|
/* extended family */
|
|
if (family == 0xf)
|
|
family += (a >> 20) & 0xff;
|
|
|
|
/* extended model */
|
|
if (family >= 0x6)
|
|
model += ((a >> 16) & 0xf) << 4;
|
|
}
|
|
nb = scnprintf(buffer, sz, "%s,%u,%u,%u$", vendor, family, model, step);
|
|
|
|
/* look for end marker to ensure the entire data fit */
|
|
if (strchr(buffer, '$')) {
|
|
buffer[nb-1] = '\0';
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|