1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2011 Erwan Velu - All Rights Reserved
4 *
5 *   Permission is hereby granted, free of charge, to any person
6 *   obtaining a copy of this software and associated documentation
7 *   files (the "Software"), to deal in the Software without
8 *   restriction, including without limitation the rights to use,
9 *   copy, modify, merge, publish, distribute, sublicense, and/or
10 *   sell copies of the Software, and to permit persons to whom
11 *   the Software is furnished to do so, subject to the following
12 *   conditions:
13 *
14 *   The above copyright notice and this permission notice shall
15 *   be included in all copies or substantial portions of the Software.
16 *
17 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 *   OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * -----------------------------------------------------------------------
27 */
28
29#include "hdt-common.h"
30#include "hdt-dump.h"
31
32void dump_hardware_security(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
33	if (!hardware->dmi.hardware_security.filled) {
34			CREATE_NEW_OBJECT;
35				add_s("dmi.warning","No hardware security structure found");
36			FLUSH_OBJECT;
37			return;
38	}
39
40	CREATE_NEW_OBJECT;
41		add_s("dmi.item","hardware_security");
42		add_hs(dmi.hardware_security.power_on_passwd_status);
43		add_hs(dmi.hardware_security.keyboard_passwd_status);
44		add_hs(dmi.hardware_security.administrator_passwd_status);
45		add_hs(dmi.hardware_security.front_panel_reset_status);
46	FLUSH_OBJECT;
47}
48
49void dump_oem_strings(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
50	if (strlen(hardware->dmi.oem_strings) == 0) {
51			CREATE_NEW_OBJECT;
52				add_s("dmi.warning","No OEM structure found");
53			FLUSH_OBJECT;
54			return;
55	}
56	CREATE_NEW_OBJECT;
57		add_s("dmi.item","OEM");
58		add_hs(dmi.oem_strings);
59	FLUSH_OBJECT;
60}
61
62void dump_memory_size(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
63	CREATE_NEW_OBJECT;
64		add_s("dmi.item","memory size");
65		add_i("dmi.memory_size (KB)",hardware->detected_memory_size);
66		add_i("dmi.memory_size (MB)",(hardware->detected_memory_size + (1 << 9)) >> 10);
67	FLUSH_OBJECT;
68}
69
70void dump_memory_modules(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
71
72	if (hardware->dmi.memory_module_count == 0) {
73			CREATE_NEW_OBJECT;
74				add_s("dmi.warning","No memory module structure found");
75			FLUSH_OBJECT;
76			return;
77	}
78
79	for (int module=0; module<hardware->dmi.memory_module_count;module++) {
80		if (hardware->dmi.memory_module[module].filled == false) {
81			char msg[64]={0};
82			snprintf(msg,sizeof(msg),"Module %d doesn't contain any information", module);
83
84			CREATE_NEW_OBJECT;
85				add_s("dmi.warning",msg);
86			FLUSH_OBJECT;
87			continue;
88		}
89
90		CREATE_NEW_OBJECT;
91		add_i("Memory module", module);
92		add_s("dmi.memory_module.socket_designation", hardware->dmi.memory_module[module].socket_designation);
93		add_s("dmi.memory_module.bank_connections", hardware->dmi.memory_module[module].bank_connections);
94		add_s("dmi.memory_module.speed", hardware->dmi.memory_module[module].speed);
95		add_s("dmi.memory_module.type", hardware->dmi.memory_module[module].type);
96		add_s("dmi.memory_module.installed_size", hardware->dmi.memory_module[module].installed_size);
97		add_s("dmi.memory_module.enabled_size", hardware->dmi.memory_module[module].enabled_size);
98		add_s("dmi.memory_module.error_status", hardware->dmi.memory_module[module].error_status);
99		FLUSH_OBJECT;
100	}
101}
102
103void dump_cache(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
104
105	if (hardware->dmi.cache_count == 0) {
106			CREATE_NEW_OBJECT;
107				add_s("dmi.warning","No cache structure found");
108			FLUSH_OBJECT;
109			return;
110	}
111
112	for (int cache=0; cache<hardware->dmi.cache_count;cache++) {
113		CREATE_NEW_OBJECT;
114		add_i("Cache", cache);
115		add_s("dmi.cache.socket_designation", hardware->dmi.cache[cache].socket_designation);
116		add_s("dmi.cache.configuration", hardware->dmi.cache[cache].configuration);
117		add_s("dmi.cache.mode", hardware->dmi.cache[cache].mode);
118		add_s("dmi.cache.location", hardware->dmi.cache[cache].location);
119		add_i("dmi.cache.installed_size (KB)", hardware->dmi.cache[cache].installed_size);
120		add_i("dmi.cache.max_size (KB)", hardware->dmi.cache[cache].max_size);
121		add_s("dmi.cache.supported_sram_types", hardware->dmi.cache[cache].supported_sram_types);
122		add_s("dmi.cache.installed_sram_types", hardware->dmi.cache[cache].installed_sram_types);
123		add_i("dmi.cache.speed (ns)", hardware->dmi.cache[cache].speed);
124		add_s("dmi.cache.error_correction_type", hardware->dmi.cache[cache].error_correction_type);
125		add_s("dmi.cache.system_type", hardware->dmi.cache[cache].system_type);
126		add_s("dmi.cache.associativity", hardware->dmi.cache[cache].associativity);
127		FLUSH_OBJECT;
128	}
129}
130void dump_memory_banks(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
131
132	if (hardware->dmi.memory_count == 0) {
133			CREATE_NEW_OBJECT;
134				add_s("dmi.warning","No memory bank structure found");
135			FLUSH_OBJECT;
136			return;
137	}
138
139	for (int bank=0; bank<hardware->dmi.memory_count;bank++) {
140
141		if (hardware->dmi.memory[bank].filled == false) {
142			char msg[64]={0};
143			snprintf(msg,sizeof(msg),"Bank %d doesn't contain any information", bank);
144
145			CREATE_NEW_OBJECT;
146				add_s("dmi.warning",msg);
147			FLUSH_OBJECT;
148			continue;
149		}
150
151		CREATE_NEW_OBJECT;
152		add_i("Memory Bank", bank);
153		add_s("dmi.memory.form_factor", hardware->dmi.memory[bank].form_factor);
154		add_s("dmi.memory.type", hardware->dmi.memory[bank].type);
155		add_s("dmi.memory.type_detail", hardware->dmi.memory[bank].type_detail);
156		add_s("dmi.memory.speed", hardware->dmi.memory[bank].speed);
157		add_s("dmi.memory.size", hardware->dmi.memory[bank].size);
158		add_s("dmi.memory.device_set", hardware->dmi.memory[bank].device_set);
159		add_s("dmi.memory.device_locator", hardware->dmi.memory[bank].device_locator);
160		add_s("dmi.memory.bank_locator", hardware->dmi.memory[bank].bank_locator);
161		add_s("dmi.memory.total_width", hardware->dmi.memory[bank].total_width);
162		add_s("dmi.memory.data_width", hardware->dmi.memory[bank].data_width);
163		add_s("dmi.memory.error", hardware->dmi.memory[bank].error);
164		add_s("dmi.memory.vendor", hardware->dmi.memory[bank].manufacturer);
165		add_s("dmi.memory.serial", hardware->dmi.memory[bank].serial);
166		add_s("dmi.memory.asset_tag", hardware->dmi.memory[bank].asset_tag);
167		add_s("dmi.memory.part_number", hardware->dmi.memory[bank].part_number);
168		FLUSH_OBJECT;
169	}
170}
171
172void dump_processor(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
173	if (hardware->dmi.processor.filled == false) {
174		CREATE_NEW_OBJECT;
175			add_s("dmi.warning","no processor structure found");
176		FLUSH_OBJECT;
177		return;
178	}
179
180	char voltage[16]={0};
181	snprintf(voltage,sizeof(voltage),"%d.%02d",
182		hardware->dmi.processor.voltage_mv / 1000,
183		hardware->dmi.processor.voltage_mv - ((hardware->dmi.processor.voltage_mv / 1000) * 1000));
184
185	CREATE_NEW_OBJECT;
186	add_s("dmi.item","processor");
187	add_hs(dmi.processor.socket_designation);
188	add_hs(dmi.processor.type);
189	add_hs(dmi.processor.family);
190	add_hs(dmi.processor.manufacturer);
191	add_hs(dmi.processor.version);
192	add_hi(dmi.processor.external_clock);
193	add_hi(dmi.processor.max_speed);
194	add_hi(dmi.processor.current_speed);
195	add_hi(dmi.processor.signature.type);
196	add_hi(dmi.processor.signature.family);
197	add_hi(dmi.processor.signature.model);
198	add_hi(dmi.processor.signature.stepping);
199	add_hi(dmi.processor.signature.minor_stepping);
200	add_s("dmi.processor.voltage",voltage);
201	add_hs(dmi.processor.status);
202	add_hs(dmi.processor.upgrade);
203	add_hs(dmi.processor.cache1);
204	add_hs(dmi.processor.cache2);
205	add_hs(dmi.processor.cache3);
206	add_hs(dmi.processor.serial);
207	add_hs(dmi.processor.part_number);
208	add_hi(dmi.processor.core_count);
209	add_hi(dmi.processor.core_enabled);
210	add_hi(dmi.processor.thread_count);
211	add_hs(dmi.processor.id);
212	for (int i = 0; i < PROCESSOR_FLAGS_ELEMENTS; i++) {
213	        if (((bool *) (&hardware->dmi.processor.cpu_flags))[i] == true) {
214	            add_s("dmi.processor.flag",(char *)cpu_flags_strings[i]);
215		}
216	}
217	FLUSH_OBJECT;
218}
219
220void dump_battery(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
221	if (hardware->dmi.battery.filled == false) {
222		CREATE_NEW_OBJECT;
223			add_s("dmi.warning","no battery structure found");
224		FLUSH_OBJECT;
225		return;
226	}
227
228	CREATE_NEW_OBJECT;
229	add_s("dmi.item","battery");
230	add_hs(dmi.battery.manufacturer);
231	add_hs(dmi.battery.manufacture_date);
232	add_hs(dmi.battery.serial);
233	add_hs(dmi.battery.name);
234	add_hs(dmi.battery.chemistry);
235	add_hs(dmi.battery.design_capacity);
236	add_hs(dmi.battery.design_voltage);
237	add_hs(dmi.battery.sbds);
238	add_hs(dmi.battery.sbds_manufacture_date);
239	add_hs(dmi.battery.sbds_chemistry);
240	add_hs(dmi.battery.maximum_error);
241	add_hs(dmi.battery.oem_info);
242	FLUSH_OBJECT;
243}
244
245void dump_ipmi(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
246	if (hardware->dmi.ipmi.filled == false) {
247		CREATE_NEW_OBJECT;
248			add_s("dmi.warning","no IPMI structure found");
249		FLUSH_OBJECT;
250		return;
251	}
252
253	char spec_ver[16]={0};
254	char i2c[16]={0};
255	char base[16]={0};
256	snprintf(spec_ver,sizeof(spec_ver),"%u.%u",
257			hardware->dmi.ipmi.major_specification_version,
258			hardware->dmi.ipmi.minor_specification_version);
259
260	snprintf(i2c,sizeof(i2c),"0x%02x", hardware->dmi.ipmi.I2C_slave_address);
261	snprintf(base,sizeof(base),"%08X%08X",
262			(uint32_t)(hardware->dmi.ipmi.base_address >> 32),
263			(uint32_t)((hardware->dmi.ipmi.base_address & 0xFFFF) & ~1));
264
265	CREATE_NEW_OBJECT;
266	add_s("dmi.item","ipmi");
267	add_hs(dmi.ipmi.interface_type);
268	add_s("dmi.ipmi.spec_version",spec_ver);
269	add_hi(dmi.ipmi.I2C_slave_address);
270	add_hi(dmi.ipmi.nv_address);
271	add_s("dmi.ipmi.base_address",base);
272	add_hi(dmi.ipmi.irq);
273	FLUSH_OBJECT;
274}
275
276void dump_chassis(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
277	if (hardware->dmi.chassis.filled == false) {
278		CREATE_NEW_OBJECT;
279			add_s("dmi.warning","no chassis structure found");
280		FLUSH_OBJECT;
281		return;
282	}
283
284	CREATE_NEW_OBJECT;
285	add_s("dmi.item","bios");
286	add_hs(dmi.chassis.manufacturer);
287	add_hs(dmi.chassis.type);
288	add_hs(dmi.chassis.lock);
289	add_hs(dmi.chassis.version);
290	add_hs(dmi.chassis.serial);
291	add_s("dmi.chassis.asset_tag",del_multi_spaces(hardware->dmi.chassis.asset_tag));
292	add_hs(dmi.chassis.boot_up_state);
293	add_hs(dmi.chassis.power_supply_state);
294	add_hs(dmi.chassis.thermal_state);
295	add_hs(dmi.chassis.security_status);
296	add_hs(dmi.chassis.oem_information);
297	add_hi(dmi.chassis.height);
298	add_hi(dmi.chassis.nb_power_cords);
299	FLUSH_OBJECT;
300}
301
302void dump_bios(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
303	if (hardware->dmi.bios.filled == false) {
304		CREATE_NEW_OBJECT;
305			add_s("dmi.warning","no bios structure found");
306		FLUSH_OBJECT;
307		return;
308	}
309	char address[16]={0};
310	char runtime[16]={0};
311	char rom[16]={0};
312	snprintf(address,sizeof(address),"0x%04X0",hardware->dmi.bios.address);
313	snprintf(runtime,sizeof(runtime),"%u %s",hardware->dmi.bios.runtime_size, hardware->dmi.bios.runtime_size_unit);
314	snprintf(rom,sizeof(rom),"%u %s",hardware->dmi.bios.rom_size, hardware->dmi.bios.rom_size_unit);
315
316	CREATE_NEW_OBJECT;
317	add_s("dmi.item","bios");
318	add_hs(dmi.bios.vendor);
319	add_hs(dmi.bios.version);
320	add_hs(dmi.bios.release_date);
321	add_hs(dmi.bios.bios_revision);
322	add_hs(dmi.bios.firmware_revision);
323	add_s("dmi.bios.address",address);
324	add_s("dmi.bios.runtime_size",runtime);
325	add_s("dmi.bios.rom_size",rom);
326	for (int i = 0; i < BIOS_CHAR_NB_ELEMENTS; i++) {
327	        if (((bool *) (&hardware->dmi.bios.characteristics))[i] == true) {
328			add_s("dmi.bios.characteristics",(char *)bios_charac_strings[i]);
329		}
330	}
331
332	for (int i = 0; i < BIOS_CHAR_X1_NB_ELEMENTS; i++) {
333	        if (((bool *) (&hardware->dmi.bios.characteristics_x1))[i] == true) {
334			add_s("dmi.bios.characteristics",(char *)bios_charac_x1_strings[i]);
335		}
336	}
337
338	for (int i = 0; i < BIOS_CHAR_X2_NB_ELEMENTS; i++) {
339	        if (((bool *) (&hardware->dmi.bios.characteristics_x2))[i] == true) {
340			add_s("dmi.bios.characteristics",(char *)bios_charac_x2_strings[i]);
341		}
342	}
343	FLUSH_OBJECT;
344}
345
346void dump_system(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
347
348	if (hardware->dmi.system.filled == false) {
349		CREATE_NEW_OBJECT;
350			add_s("dmi.warning","no system structure found");
351		FLUSH_OBJECT;
352		return;
353	}
354	char system_reset_status[10]={0};
355	char watchdog_timer[15]={0};
356	snprintf(system_reset_status,sizeof(system_reset_status),"%s", (hardware->dmi.system.system_reset.status ? "Enabled" :"Disabled"));
357	snprintf(watchdog_timer,sizeof(watchdog_timer),"%s", (hardware->dmi.system.system_reset.watchdog ? "Present" :"Not Present"));
358
359	CREATE_NEW_OBJECT;
360	add_s("dmi.item","system");
361	add_hs(dmi.system.manufacturer);
362	add_hs(dmi.system.product_name);
363	add_hs(dmi.system.version);
364	add_hs(dmi.system.serial);
365	add_hs(dmi.system.uuid);
366	add_hs(dmi.system.wakeup_type);
367	add_hs(dmi.system.sku_number);
368	add_hs(dmi.system.family);
369	add_hs(dmi.system.configuration_options);
370	add_s("dmi.system.system_reset.status",system_reset_status);
371	add_s("dmi.system.system_reset.watchdog",watchdog_timer);
372	add_hs(dmi.system.system_reset.boot_option);
373	add_hs(dmi.system.system_reset.boot_option_on_limit);
374	add_hs(dmi.system.system_reset.reset_count);
375	add_hs(dmi.system.system_reset.reset_limit);
376	add_hs(dmi.system.system_reset.timer_interval);
377	add_hs(dmi.system.system_reset.timeout);
378	add_hs(dmi.system.system_boot_status);
379	FLUSH_OBJECT;
380}
381
382void dump_base_board(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
383
384	if (hardware->dmi.base_board.filled == false) {
385		CREATE_NEW_OBJECT;
386			add_s("dmi.warning","no base_board structure found");
387		FLUSH_OBJECT;
388		return;
389	}
390
391	CREATE_NEW_OBJECT;
392	add_s("dmi.item","base_board");
393	add_hs(dmi.base_board.manufacturer);
394	add_hs(dmi.base_board.product_name);
395	add_hs(dmi.base_board.version);
396	add_hs(dmi.base_board.serial);
397	add_hs(dmi.base_board.asset_tag);
398	add_hs(dmi.base_board.location);
399	add_hs(dmi.base_board.type);
400	for (int i = 0; i < BASE_BOARD_NB_ELEMENTS; i++) {
401		if (((bool *) (&hardware->dmi.base_board.features))[i] == true) {
402			add_s("dmi.base_board.features",(char *)base_board_features_strings[i]);
403		}
404	}
405
406	for (unsigned int i = 0; i < sizeof hardware->dmi.base_board.devices_information /
407		         sizeof *hardware->dmi.base_board.devices_information; i++) {
408	        if (strlen(hardware->dmi.base_board.devices_information[i].type)) {
409			add_s("dmi.base_board.devices_information.type", hardware->dmi.base_board.devices_information[i].type);
410			add_i("dmi.base_board.devices_information.status", hardware->dmi.base_board.devices_information[i].status);
411			add_s("dmi.base_board.devices_information.description", hardware->dmi.base_board.devices_information[i].description);
412		}
413	}
414	FLUSH_OBJECT;
415}
416
417void dump_dmi(struct s_hardware *hardware, ZZJSON_CONFIG *config, ZZJSON **item) {
418
419	CREATE_NEW_OBJECT;
420	add_hb(is_dmi_valid);
421
422	if (hardware->is_dmi_valid == false) {
423		FLUSH_OBJECT;
424		goto exit;
425	} else {
426		char buffer[8]={0};
427		snprintf(buffer,sizeof(buffer),"%d.%d",hardware->dmi.dmitable.major_version, hardware->dmi.dmitable.minor_version);
428		add_s("dmi.version",buffer);
429		FLUSH_OBJECT;
430	}
431
432	dump_base_board(hardware,config,item);
433	dump_system(hardware,config,item);
434	dump_bios(hardware,config,item);
435	dump_chassis(hardware,config,item);
436	dump_ipmi(hardware,config,item);
437	dump_battery(hardware,config,item);
438	dump_processor(hardware,config,item);
439	dump_cache(hardware,config,item);
440	dump_memory_banks(hardware,config,item);
441	dump_memory_modules(hardware,config,item);
442	dump_memory_size(hardware,config,item);
443	dump_oem_strings(hardware,config,item);
444	dump_hardware_security(hardware,config,item);
445exit:
446	to_cpio("dmi");
447}
448