1 | /*␊ |
2 | * Copyright 2010 AsereBLN. All rights reserved. <aserebln@googlemail.com>␊ |
3 | *␊ |
4 | * mem.c - obtain system memory information␊ |
5 | */␊ |
6 | ␊ |
7 | #include "libsaio.h"␊ |
8 | #include "pci.h"␊ |
9 | #include "platform.h"␊ |
10 | //#include "cpu.h"␊ |
11 | #include "mem.h"␊ |
12 | #include "smbios_patcher.h"␊ |
13 | ␊ |
14 | #ifndef DEBUG_MEM␊ |
15 | #define DEBUG_MEM 0␊ |
16 | #endif␊ |
17 | ␊ |
18 | #if DEBUG_MEM␊ |
19 | #define DBG(x...)␉␉verbose(x)␊ |
20 | #else␊ |
21 | #define DBG(x...)␊ |
22 | #endif␊ |
23 | ␊ |
24 | #define DC(c) (c >= 0x20 && c < 0x7f ? (char) c : '.')␊ |
25 | #define STEP 16␊ |
26 | ␊ |
27 | void dumpPhysAddr(const char * title, void * a, int len)␊ |
28 | {␊ |
29 | int i,j;␊ |
30 | u_int8_t* ad = (u_int8_t*) a;␊ |
31 | char buffer[80];␊ |
32 | char str[16];␊ |
33 | ␊ |
34 | if(ad==NULL) return;␊ |
35 | ␊ |
36 | DBG("%s addr=0x%08x len=%04d\n",title ? title : "Dump of ", a, len);␊ |
37 | DBG("Ofs-00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F ASCII\n");␊ |
38 | i = (len/STEP)*STEP;␊ |
39 | for (j=0; j < i; j+=STEP)␊ |
40 | {␊ |
41 | DBG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",␊ |
42 | j, ␊ |
43 | ad[j], ad[j+1], ad[j+2], ad[j+3] , ad[j+4], ad[j+5], ad[j+6], ad[j+7],␊ |
44 | ad[j+8], ad[j+9], ad[j+10], ad[j+11] , ad[j+12], ad[j+13], ad[j+14], ad[j+15],␊ |
45 | DC(ad[j]), DC(ad[j+1]), DC(ad[j+2]), DC(ad[j+3]) , DC(ad[j+4]), DC(ad[j+5]), DC(ad[j+6]), DC(ad[j+7]),␊ |
46 | DC(ad[j+8]), DC(ad[j+9]), DC(ad[j+10]), DC(ad[j+11]) , DC(ad[j+12]), DC(ad[j+13]), DC(ad[j+14]), DC(ad[j+15])␊ |
47 | ); ␊ |
48 | }␊ |
49 | ␊ |
50 | if (len%STEP==0) return;␊ |
51 | sprintf(buffer,"%02x:", i);␊ |
52 | for (j=0; j < STEP; j++) {␊ |
53 | if (j<(len%STEP))␊ |
54 | sprintf(str, " %02x", ad[i+j]);␊ |
55 | else␊ |
56 | strcpy(str, " " ); ␊ |
57 | strncat(buffer, str, sizeof(buffer));␊ |
58 | }␊ |
59 | strncat(buffer," ", sizeof(buffer));␊ |
60 | for (j=0; j < (len%STEP); j++) {␊ |
61 | sprintf(str, "%c", DC(ad[i+j])); ␊ |
62 | strncat(buffer, str, sizeof(buffer));␊ |
63 | }␊ |
64 | DBG("%s\n",buffer);␊ |
65 | }␊ |
66 | ␊ |
67 | void dumpAllTablesOfType(int i)␊ |
68 | {␊ |
69 | char title[32];␊ |
70 | struct DMIHeader * dmihdr;␊ |
71 | for(dmihdr = FindFirstDmiTableOfType(i, 4);␊ |
72 | dmihdr;␊ |
73 | dmihdr = FindNextDmiTableOfType(i, 4)) {␊ |
74 | sprintf(title,"Table (type %d) :" , i); ␊ |
75 | dumpPhysAddr(title, dmihdr, dmihdr->length+32);␊ |
76 | }␊ |
77 | }␊ |
78 | ␊ |
79 | const char * getDMIString(struct DMIHeader * dmihdr, uint8_t strNum)␊ |
80 | {␊ |
81 | const char * ret =NULL;␊ |
82 | const char * startAddr = (const char *) dmihdr;␊ |
83 | const char * limit = NULL;␊ |
84 | ␊ |
85 | if (!dmihdr || dmihdr->length<4 || strNum==0) return NULL;␊ |
86 | startAddr += dmihdr->length;␊ |
87 | limit = startAddr + 256;␊ |
88 | for(; strNum; strNum--) {␊ |
89 | if ((*startAddr)==0 && *(startAddr+1)==0) break;␊ |
90 | if (*startAddr && strNum<=1) {␊ |
91 | ret = startAddr; // current str␊ |
92 | break;␊ |
93 | }␊ |
94 | while(*startAddr && startAddr<limit) startAddr++;␊ |
95 | if (startAddr==limit) break; // no terminator found␊ |
96 | else if((*startAddr==0) && *(startAddr+1)==0) break;␊ |
97 | else startAddr++;␊ |
98 | }␊ |
99 | ␊ |
100 | return ret;␊ |
101 | }␊ |
102 | ␊ |
103 | void scan_memory(void) //PlatformInfo_t *p)␊ |
104 | {␊ |
105 | int i=0;␊ |
106 | struct DMIHeader * dmihdr = NULL;␊ |
107 | ␊ |
108 | struct DMIMemoryModuleInfo* memInfo[MAX_RAM_SLOTS]; // 6␊ |
109 | struct DMIPhysicalMemoryArray* physMemArray; // 16␊ |
110 | struct DMIMemoryDevice* memDev[MAX_RAM_SLOTS]; //17␊ |
111 | ␊ |
112 | /* We mainly don't use obsolete tables 5,6 because most of computers don't handle it anymore */␊ |
113 | Platform->DMI.MemoryModules = 0;␊ |
114 | /* Now lets peek info rom table 16,17 as for some bios, table 5 & 6 are not used */␊ |
115 | physMemArray = (struct DMIPhysicalMemoryArray*) FindFirstDmiTableOfType(16, 4);␊ |
116 | Platform->DMI.MaxMemorySlots = physMemArray ? physMemArray->numberOfMemoryDevices : 0;␊ |
117 | ␊ |
118 | i = 0;␊ |
119 | for(dmihdr = FindFirstDmiTableOfType(17, 4);␊ |
120 | dmihdr;␊ |
121 | dmihdr = FindNextDmiTableOfType(17, 4) ) {␊ |
122 | memDev[i] = (struct DMIMemoryDevice*) dmihdr;␊ |
123 | if (memDev[i]->size !=0 ) Platform->DMI.MemoryModules++;␊ |
124 | if (memDev[i]->memorySpeed>0) Platform->RAM.DIMM[i].Frequency = memDev[i]->memorySpeed; // take it here for now but we'll check spd and dmi table 6 as well␊ |
125 | i++;␊ |
126 | }␊ |
127 | // for table 6, we only have a look at the current speed␊ |
128 | i = 0;␊ |
129 | for(dmihdr = FindFirstDmiTableOfType(6, 4);␊ |
130 | dmihdr;␊ |
131 | dmihdr = FindNextDmiTableOfType(6, 4) ) {␊ |
132 | memInfo[i] = (struct DMIMemoryModuleInfo*) dmihdr;␊ |
133 | if (memInfo[i]->currentSpeed > Platform->RAM.DIMM[i].Frequency) ␊ |
134 | Platform->RAM.DIMM[i].Frequency = memInfo[i]->currentSpeed; // favor real overclocked speed if any␊ |
135 | i++;␊ |
136 | }␊ |
137 | #if DEBUG_MEM␊ |
138 | dumpAllTablesOfType(17);␊ |
139 | // getc();␊ |
140 | #endif␊ |
141 | }␊ |
142 | |