summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--perl-install/c/smp-dmi.c264
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;
}