]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/hwinfo/src/hd/memory.c
Signierten GPG-Schluessel importiert.
[people/pmueller/ipfire-2.x.git] / src / hwinfo / src / hd / memory.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <sys/stat.h>
6
7 #include "hd.h"
8 #include "hd_int.h"
9 #include "memory.h"
10 #include "klog.h"
11
12 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
13 * memory stuff
14 *
15 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
16 */
17
18 uint64_t kcore_mem(hd_data_t *hd_data);
19 uint64_t klog_mem(hd_data_t *hd_data, uint64_t *alt);
20 uint64_t klog_mem2(hd_data_t *hd_data);
21 uint64_t meminfo_mem(hd_data_t *hd_data);
22
23 void hd_scan_memory(hd_data_t *hd_data)
24 {
25 hd_t *hd;
26 uint64_t kcore, klog, klog_alt, klog2, meminfo, msize0, msize1, u;
27 hd_res_t *res;
28 int i;
29 int exact;
30
31 if(!hd_probe_feature(hd_data, pr_memory)) return;
32
33 hd_data->module = mod_memory;
34
35 /* some clean-up */
36 remove_hd_entries(hd_data);
37
38 PROGRESS(1, 0, "main memory size");
39
40 kcore = kcore_mem(hd_data);
41 klog = klog_mem(hd_data, &klog_alt);
42 klog2 = klog_mem2(hd_data);
43 if(klog2 > klog) klog = klog2;
44 meminfo = meminfo_mem(hd_data);
45
46 msize0 = meminfo > klog ? meminfo : klog;
47 if(!msize0) msize0 = kcore;
48
49 exact = 0;
50 if(msize0 && kcore >= msize0 && ((kcore - msize0) << 4) / msize0 == 0) {
51 /* trust kcore value if it's approx. msize0 */
52 msize0 = kcore;
53 exact = 1;
54 }
55 msize1 = msize0;
56 if(meminfo > msize1) { msize1 = meminfo; exact = 0; }
57 if(klog_alt > msize0) msize0 = klog_alt;
58
59 hd = add_hd_entry(hd_data, __LINE__, 0);
60 hd->base_class.id = bc_internal;
61 hd->sub_class.id = sc_int_main_mem;
62
63 res = add_res_entry(&hd->res, new_mem(sizeof *res));
64 res->mem.type = res_mem;
65 res->mem.range = msize0;
66 res->mem.access = acc_rw;
67 res->mem.enabled = 1;
68
69 /* round it somewhat */
70 for(i = 0, u = msize1; u; i++) {
71 u >>= 1;
72 }
73 if(i > 10) { /* We *do* have at least 1k memory, do we? */
74 msize1 >>= i - (exact ? 8 : 5);
75 msize1++;
76 msize1 >>= 1;
77 msize1 <<= i - (exact ? 7 : 4);
78 }
79
80 res = add_res_entry(&hd->res, new_mem(sizeof *res));
81 res->phys_mem.type = res_phys_mem;
82 res->phys_mem.range = msize1;
83 }
84
85 uint64_t kcore_mem(hd_data_t *hd_data)
86 {
87 uint64_t u = 0;
88 size_t ps = getpagesize();
89 struct stat sb;
90
91 if(!stat(PROC_KCORE, &sb)) {
92 u = sb.st_size;
93 if(u > ps) u -= ps;
94
95 #if 0
96 /* we'll assume no mem modules with less than 256k */
97 u += 1 << 17;
98 u &= -1 << 18;
99 #endif
100 }
101
102 ADD2LOG(" kcore mem: 0x%"PRIx64"\n", u);
103
104 return u;
105 }
106
107
108 uint64_t klog_mem(hd_data_t *hd_data, uint64_t *alt)
109 {
110 uint64_t u = 0, u0, u1, u2, u3, mem0 = 0, mem1 = 0;
111 str_list_t *sl;
112 char *s;
113 int i;
114
115 if(!hd_data->klog) read_klog(hd_data);
116
117 for(sl = hd_data->klog; sl; sl = sl->next) {
118 if(strstr(sl->str, "<6>Memory: ") == sl->str) {
119 if(sscanf(sl->str, "<6>Memory: %"SCNu64"k/%"SCNu64"k", &u0, &u1) == 2) {
120 mem0 = u1 << 10;
121 }
122 if(
123 (i = sscanf(sl->str, "<6>Memory: %"SCNu64"k available (%"SCNu64"k kernel code, %"SCNu64"k data, %"SCNu64"k", &u0, &u1, &u2, &u3)) == 4 || i == 1
124 ) {
125 mem0 = (i == 1 ? u0 : u0 + u1 + u2 + u3) << 10;
126 }
127 if(
128 (s = strstr(sl->str, "[")) &&
129 sscanf(s, "[%"SCNx64",%"SCNx64"]", &u0, &u1) == 2 &&
130 u1 > u0
131 ) {
132 mem1 = u1 - u0;
133 }
134 break;
135 }
136 }
137
138 u = mem0 ? mem0 : mem1;
139
140 #if 0
141 /* round it somewhat */
142 for(i = 0, u0 = u; u0; i++) {
143 u0 >>= 1;
144 }
145 if(i > 10) { /* We *do* have at least 1k memory, do we? */
146 u >>= i - 6;
147 u++;
148 u >>= 1;
149 u <<= i - 5;
150 }
151 #endif
152
153 ADD2LOG(" klog mem 0: 0x%"PRIx64"\n", mem0);
154 ADD2LOG(" klog mem 1: 0x%"PRIx64"\n", mem1);
155 ADD2LOG(" klog mem: 0x%"PRIx64"\n", u);
156
157 *alt = mem1;
158
159 return u;
160 }
161
162 uint64_t klog_mem2(hd_data_t *hd_data)
163 {
164 uint64_t u0, u1, mem = 0;
165 str_list_t *sl;
166 char buf[64];
167
168 if(!hd_data->klog) read_klog(hd_data);
169
170 for(sl = hd_data->klog; sl; sl = sl->next) {
171 if(strstr(sl->str, "<6>BIOS-provided physical RAM map:") == sl->str) {
172 for(sl = sl->next ; sl; sl = sl->next) {
173 ADD2LOG(" -- %s", sl->str);
174 if(sscanf(sl->str, "<4> BIOS-e820: %"SCNx64" - %"SCNx64" (%63s", &u0, &u1, buf) != 3) break;
175 if(strcmp(buf, "usable)")) continue;
176 if(u1 < u0) break;
177 mem += u1 - u0;
178 }
179 break;
180 }
181 }
182
183 ADD2LOG(" bios mem: 0x%"PRIx64"\n", mem);
184
185 return mem;
186 }
187
188 uint64_t meminfo_mem(hd_data_t *hd_data)
189 {
190 uint64_t u = 0, u0;
191 str_list_t *sl;
192
193 sl = read_file(PROC_MEMINFO, 0, 1);
194
195 if(sl && sscanf(sl->str, "MemTotal: %"SCNu64"", &u0) == 1) {
196 u = u0 << 10;
197 }
198
199 free_str_list(sl);
200
201 ADD2LOG(" meminfo: 0x%"PRIx64"\n", u);
202
203 return u;
204 }
205
206