diff options
-rw-r--r-- | perl-install/c/smp-dmi.c | 264 |
1 files changed, 93 insertions, 171 deletions
diff --git a/perl-install/c/smp-dmi.c b/perl-install/c/smp-dmi.c index 672bc2c35..c3eb9ead1 100644 --- a/perl-install/c/smp-dmi.c +++ b/perl-install/c/smp-dmi.c @@ -12,43 +12,40 @@ #include <fcntl.h> #include <string.h> #include <stdlib.h> +#include <sys/mman.h> typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; -static void -dump_raw_data(void *data, unsigned int length) + +#define DEFAULT_MEM_DEV "/dev/mem" + +void *mem_chunk(u32 base, u32 len, const char *devmem) { - unsigned char buffer1[80], buffer2[80], *b1, *b2, c; - unsigned char *p = data; - unsigned long column=0; - unsigned int length_printed = 0; - const unsigned char maxcolumn = 16; - while (length_printed < length) { - b1 = buffer1; - b2 = buffer2; - for (column = 0; - column < maxcolumn && length_printed < length; - column ++) { - b1 += sprintf(b1, "%02x ",(unsigned int) *p); - if (*p < 32 || *p > 126) c = '.'; - else c = *p; - b2 += sprintf(b2, "%c", c); - p++; - length_printed++; - } - /* pad out the line */ - for (; column < maxcolumn; column++) - { - b1 += sprintf(b1, " "); - b2 += sprintf(b2, " "); - } - - printf("%s\t%s\n", buffer1, buffer2); - } -} + void *p; + int fd; + off_t mmoffset; + void *mmp; + + if ((fd = open(devmem, O_RDONLY)) < 0) + return NULL; + + if ((p = malloc(len)) == NULL) + return NULL; + + mmoffset = base % getpagesize(); + mmp = mmap(0, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset); + if (mmp == MAP_FAILED) { + free(p); + return NULL; + } + memcpy(p, (u8 *)mmp + mmoffset, len); + munmap(mmp, mmoffset + len); + close(fd); + return p; +} struct dmi_header @@ -58,156 +55,81 @@ struct dmi_header u16 handle; }; -static char *dmi_string(struct dmi_header *dm, u8 s) +typedef int (*dmi_decode)(u8 * data); + +static int decode_handle(u32 base, int len, int num, dmi_decode decode) { - u8 *bp=(u8 *)dm; - if (!s) return ""; - - bp+=dm->length; - while(s>1) - { - bp+=strlen(bp); - bp++; - s--; + u8 *buf; + u8 *data; + int i = 0; + int ret = 0; + + if ((buf = mem_chunk(base, len, DEFAULT_MEM_DEV)) == NULL) + return 0; + + data = buf; + while(i<num && data+sizeof(struct dmi_header)<=buf+len) + { + u8 *next; + struct dmi_header *dm = (struct dmi_header *)data; + + /* look for the next handle */ + next=data+dm->length; + while(next-buf+1<len && (next[0]!=0 || next[1]!=0)) + next++; + next+=2; + if(next-buf<=len) + ret += decode(data); + else { + ret = 0; /* TRUNCATED */ + break; } - return bp; -} + data=next; + i++; + } -static char *dmi_processor_type(u8 code) -{ - static char *processor_type[]={ - "", - "Other", - "Unknown", - "Central Processor", - "Math Processor", - "DSP Processor", - "Video Processor" - }; - - if(code == 0xFF) - return "Other"; - - if (code > 0xA1) - return ""; - return processor_type[code]; + free(buf); + return ret; } -static char *dmi_processor_family(u8 code) -{ - static char *processor_family[]={ - "", - "Other", - "Unknown", - "8086", - "80286", - "Intel386 processor", - "Intel486 processor", - "8087", - "80287", - "80387", - "80487", - "Pentium processor Family", - "Pentium Pro processor", - "Pentium II processor", - "Pentium processor with MMX technology", - "Celeron processor", - "Pentium II Xeon processor", - "Pentium III processor", - "M1 Family", - "M1","M1","M1","M1","M1","M1", /* 13h - 18h */ - "K5 Family", - "K5","K5","K5","K5","K5","K5", /* 1Ah - 1Fh */ - "Power PC Family", - "Power PC 601", - "Power PC 603", - "Power PC 603+", - "Power PC 604", - }; - - if(code == 0xFF) - return "Other"; - - if (code > 0x24) - return ""; - return processor_family[code]; -} +static int dmi_detect(dmi_decode decode) { + u8 *buf; + long fp; + int ret; -static int dmi_table(int fd, u32 base, int len, int num) -{ - char *buf=malloc(len); - struct dmi_header *dm; - u8 *data; - int i=0; - int processor=0; - - if(lseek(fd, (long)base, 0)==-1) - { - perror("dmi: lseek"); - return; - } - if(read(fd, buf, len)!=len) - { - perror("dmi: read"); - return; + if ((buf = mem_chunk(0xf0000, 0x10000, DEFAULT_MEM_DEV)) == NULL) { + perror("dmi_detect"); + exit(1); + } + + for (fp = 0; fp <= 0xfff0; fp += 16) { + if (memcmp(buf + fp, "_DMI_", 5) == 0) { + u8 *p = buf + fp; + u16 num = p[13]<<8|p[12]; + u16 len = p[7]<<8|p[6]; + u32 base = p[11]<<24|p[10]<<16|p[9]<<8|p[8]; + + ret = decode_handle(base, len, num, decode); + break; } - data = buf; - while(i<num) - { - u32 u; - u32 u2; - dm=(struct dmi_header *)data; - - if((dm->type == 4) && /*"Central Processor"*/(data[5] == 3)) { - if(/*Processor Manufacturer*/data[7] != 0) - processor++; - } - - data+=dm->length; - while(*data || data[1]) - data++; - data+=2; - i++; + } + + free(buf); + return ret; +} + +static int processor(u8 *data) { + struct dmi_header *dm = (struct dmi_header *)data; + + if((dm->type == 4) && /*"Central Processor"*/(data[5] == 3)) { + if(/*Processor Manufacturer*/data[7] != 0 + && /*Populated*/(data[0x18] & (1 << 6)) + && !/*Disabled {User:2h, BIOS:3}*/(data[0x18] & (1 << 1))) + return 1; } - free(buf); - return processor; + return 0; } int intelDetectSMP(void) { - unsigned char buf[20]; - int fd=open("/dev/mem", O_RDONLY); - long fp=0xE0000L; - int processor=0; - if(fd==-1) - { - perror("/dev/mem"); - exit(1); - } - if(lseek(fd,fp,0)==-1) - { - perror("seek"); - exit(1); - } - - - fp -= 16; - - while( fp < 0xFFFFF) - { - fp+=16; - if(read(fd, buf, 16)!=16) - perror("read"); - - if(memcmp(buf, "_DMI_", 5)==0) - { - u16 num=buf[13]<<8|buf[12]; - u16 len=buf[7]<<8|buf[6]; - u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; - - processor=dmi_table(fd, base,len, num); - break; - } - } - close(fd); - return (processor > 1); + return dmi_detect(processor) > 1; } |