1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2009 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 <stdio.h>
30#include <string.h>
31#include <stdlib.h>
32#include <errno.h>
33
34#include "hdt-cli.h"
35#include "hdt-common.h"
36
37static void show_dmi_modules(int argc __unused, char **argv __unused,
38			     struct s_hardware *hardware)
39{
40    char available_dmi_commands[1024];
41    reset_more_printf();
42    memset(available_dmi_commands, 0, sizeof(available_dmi_commands));
43
44    more_printf("Available DMI modules on your system:\n");
45    if (hardware->dmi.base_board.filled == true)
46	more_printf("\t%s\n", CLI_DMI_BASE_BOARD);
47    if (hardware->dmi.battery.filled == true)
48	more_printf("\t%s\n", CLI_DMI_BATTERY);
49    if (hardware->dmi.bios.filled == true)
50	more_printf("\t%s\n", CLI_DMI_BIOS);
51    if (hardware->dmi.chassis.filled == true)
52	more_printf("\t%s\n", CLI_DMI_CHASSIS);
53    for (int i = 0; i < hardware->dmi.memory_count; i++) {
54	if (hardware->dmi.memory[i].filled == true) {
55	    more_printf("\tbank <number>\n");
56	    break;
57	}
58    }
59    for (int i = 0; i < hardware->dmi.memory_module_count; i++) {
60	if (hardware->dmi.memory_module[i].filled == true) {
61	    more_printf("\tmodule <number>\n");
62	    break;
63	}
64    }
65    if (hardware->dmi.processor.filled == true)
66	more_printf("\t%s\n", CLI_DMI_PROCESSOR);
67    if (hardware->dmi.system.filled == true)
68	more_printf("\t%s\n", CLI_DMI_SYSTEM);
69    if (hardware->dmi.ipmi.filled == true)
70	more_printf("\t%s\n", CLI_DMI_IPMI);
71    if (hardware->dmi.cache_count)
72	more_printf("\t%s\n", CLI_DMI_CACHE);
73    if (strlen(hardware->dmi.oem_strings))
74	more_printf("\t%s\n", CLI_DMI_OEM);
75    if (hardware->dmi.hardware_security.filled)
76	more_printf("\t%s\n", CLI_DMI_SECURITY);
77}
78
79static void show_dmi_base_board(int argc __unused, char **argv __unused,
80				struct s_hardware *hardware)
81{
82    if (hardware->dmi.base_board.filled == false) {
83	more_printf("base_board information not found on your system, see "
84		    "`show list' to see which module is available.\n");
85	return;
86    }
87    reset_more_printf();
88    more_printf("Base board\n");
89    more_printf(" Manufacturer : %s\n", hardware->dmi.base_board.manufacturer);
90    more_printf(" Product Name : %s\n", hardware->dmi.base_board.product_name);
91    more_printf(" Version      : %s\n", hardware->dmi.base_board.version);
92    more_printf(" Serial       : %s\n", hardware->dmi.base_board.serial);
93    more_printf(" Asset Tag    : %s\n", hardware->dmi.base_board.asset_tag);
94    more_printf(" Location     : %s\n", hardware->dmi.base_board.location);
95    more_printf(" Type         : %s\n", hardware->dmi.base_board.type);
96    for (int i = 0; i < BASE_BOARD_NB_ELEMENTS; i++) {
97	if (((bool *) (&hardware->dmi.base_board.features))[i] == true) {
98	    more_printf(" %s\n", base_board_features_strings[i]);
99	}
100    }
101
102    for (unsigned int i = 0;
103	 i <
104	 sizeof hardware->dmi.base_board.devices_information /
105	 sizeof *hardware->dmi.base_board.devices_information; i++) {
106	if (strlen(hardware->dmi.base_board.devices_information[i].type)) {
107	    more_printf("On Board Device #%u Information\n", i)
108		more_printf("  Type        : %s\n",
109			    hardware->dmi.base_board.devices_information[i].
110			    type);
111	    more_printf("  Status      : %s\n",
112			hardware->dmi.base_board.devices_information[i].
113			status ? "Enabled" : "Disabled");
114	    more_printf("  Description : %s\n",
115			hardware->dmi.base_board.devices_information[i].
116			description);
117	}
118    }
119}
120
121static void show_dmi_system(int argc __unused, char **argv __unused,
122			    struct s_hardware *hardware)
123{
124    if (hardware->dmi.system.filled == false) {
125	more_printf("system information not found on your system, see "
126		    "`show list' to see which module is available.\n");
127	return;
128    }
129    reset_more_printf();
130    more_printf("System\n");
131    more_printf(" Manufacturer : %s\n", hardware->dmi.system.manufacturer);
132    more_printf(" Product Name : %s\n", hardware->dmi.system.product_name);
133    more_printf(" Version      : %s\n", hardware->dmi.system.version);
134    more_printf(" Serial       : %s\n", hardware->dmi.system.serial);
135    more_printf(" UUID         : %s\n", hardware->dmi.system.uuid);
136    more_printf(" Wakeup Type  : %s\n", hardware->dmi.system.wakeup_type);
137    more_printf(" SKU Number   : %s\n", hardware->dmi.system.sku_number);
138    more_printf(" Family       : %s\n", hardware->dmi.system.family);
139
140    if (strlen(hardware->dmi.system.configuration_options)) {
141	more_printf("System Configuration Options\n");
142	more_printf("%s\n", hardware->dmi.system.configuration_options);
143    }
144
145    if (hardware->dmi.system.system_reset.filled) {
146	more_printf("System Reset\n");
147	more_printf("  Status               : %s\n",
148		    (hardware->dmi.system.system_reset.
149		     status ? "Enabled" : "Disabled"));
150	more_printf("  Watchdog Timer       : %s\n",
151		    (hardware->dmi.system.system_reset.
152		     watchdog ? "Present" : "Not Present"));
153	if (strlen(hardware->dmi.system.system_reset.boot_option))
154	    more_printf("  Boot Option          : %s\n",
155			hardware->dmi.system.system_reset.boot_option);
156	if (strlen(hardware->dmi.system.system_reset.boot_option_on_limit))
157	    more_printf("  Boot Option On Limit : %s\n",
158			hardware->dmi.system.system_reset.boot_option_on_limit);
159	if (strlen(hardware->dmi.system.system_reset.reset_count))
160	    more_printf("  Reset Count          : %s\n",
161			hardware->dmi.system.system_reset.reset_count);
162	if (strlen(hardware->dmi.system.system_reset.reset_limit))
163	    more_printf("  Reset Limit          : %s\n",
164			hardware->dmi.system.system_reset.reset_limit);
165	if (strlen(hardware->dmi.system.system_reset.timer_interval))
166	    more_printf("  Timer Interval       : %s\n",
167			hardware->dmi.system.system_reset.timer_interval);
168	if (strlen(hardware->dmi.system.system_reset.timeout))
169	    more_printf("  Timeout              : %s\n",
170			hardware->dmi.system.system_reset.timeout);
171    }
172
173    more_printf("System Boot Information\n");
174    more_printf(" Status       : %s\n",
175		hardware->dmi.system.system_boot_status);
176}
177
178static void show_dmi_bios(int argc __unused, char **argv __unused,
179			  struct s_hardware *hardware)
180{
181    if (hardware->dmi.bios.filled == false) {
182	more_printf("bios information not found on your system, see "
183		    "`show list' to see which module is available.\n");
184	return;
185    }
186    reset_more_printf();
187    more_printf("BIOS\n");
188    more_printf(" Vendor            : %s\n", hardware->dmi.bios.vendor);
189    more_printf(" Version           : %s\n", hardware->dmi.bios.version);
190    more_printf(" Release Date      : %s\n", hardware->dmi.bios.release_date);
191    more_printf(" Bios Revision     : %s\n", hardware->dmi.bios.bios_revision);
192    if (strlen(hardware->dmi.bios.firmware_revision))
193	more_printf(" Firmware Revision : %s\n",
194		    hardware->dmi.bios.firmware_revision);
195    more_printf(" Address           : 0x%04X0\n", hardware->dmi.bios.address);
196    more_printf(" Runtime address   : %u %s\n",
197		hardware->dmi.bios.runtime_size,
198		hardware->dmi.bios.runtime_size_unit);
199    more_printf(" Rom size          : %u %s\n", hardware->dmi.bios.rom_size,
200		hardware->dmi.bios.rom_size_unit);
201
202    for (int i = 0; i < BIOS_CHAR_NB_ELEMENTS; i++) {
203	if (((bool *) (&hardware->dmi.bios.characteristics))[i] == true) {
204	    more_printf(" %s\n", bios_charac_strings[i]);
205	}
206    }
207    for (int i = 0; i < BIOS_CHAR_X1_NB_ELEMENTS; i++) {
208	if (((bool *) (&hardware->dmi.bios.characteristics_x1))[i] == true) {
209	    more_printf(" %s\n", bios_charac_x1_strings[i]);
210	}
211    }
212
213    for (int i = 0; i < BIOS_CHAR_X2_NB_ELEMENTS; i++) {
214	if (((bool *) (&hardware->dmi.bios.characteristics_x2))[i] == true) {
215	    more_printf(" %s\n", bios_charac_x2_strings[i]);
216	}
217    }
218
219}
220
221static void show_dmi_chassis(int argc __unused, char **argv __unused,
222			     struct s_hardware *hardware)
223{
224    if (hardware->dmi.chassis.filled == false) {
225	more_printf("chassis information not found on your system, see "
226		    "`show list' to see which module is available.\n");
227	return;
228    }
229    reset_more_printf();
230    more_printf("Chassis\n");
231    more_printf(" Manufacturer       : %s\n",
232		hardware->dmi.chassis.manufacturer);
233    more_printf(" Type               : %s\n", hardware->dmi.chassis.type);
234    more_printf(" Lock               : %s\n", hardware->dmi.chassis.lock);
235    more_printf(" Version            : %s\n", hardware->dmi.chassis.version);
236    more_printf(" Serial             : %s\n", hardware->dmi.chassis.serial);
237    more_printf(" Asset Tag          : %s\n",
238		del_multi_spaces(hardware->dmi.chassis.asset_tag));
239    more_printf(" Boot up state      : %s\n",
240		hardware->dmi.chassis.boot_up_state);
241    more_printf(" Power supply state : %s\n",
242		hardware->dmi.chassis.power_supply_state);
243    more_printf(" Thermal state      : %s\n",
244		hardware->dmi.chassis.thermal_state);
245    more_printf(" Security Status    : %s\n",
246		hardware->dmi.chassis.security_status);
247    more_printf(" OEM Information    : %s\n",
248		hardware->dmi.chassis.oem_information);
249    more_printf(" Height             : %u\n", hardware->dmi.chassis.height);
250    more_printf(" NB Power Cords     : %u\n",
251		hardware->dmi.chassis.nb_power_cords);
252}
253
254static void show_dmi_ipmi(int argc __unused, char **argv __unused,
255			  struct s_hardware *hardware)
256{
257    if (hardware->dmi.ipmi.filled == false) {
258	more_printf("IPMI module not available\n");
259	return;
260    }
261    reset_more_printf();
262    more_printf("IPMI\n");
263    more_printf(" Interface Type     : %s\n",
264		hardware->dmi.ipmi.interface_type);
265    more_printf(" Specification Ver. : %u.%u\n",
266		hardware->dmi.ipmi.major_specification_version,
267		hardware->dmi.ipmi.minor_specification_version);
268    more_printf(" I2C Slave Address  : 0x%02x\n",
269		hardware->dmi.ipmi.I2C_slave_address);
270    more_printf(" Nv Storage Address : %u\n", hardware->dmi.ipmi.nv_address);
271    uint32_t high = hardware->dmi.ipmi.base_address >> 32;
272    uint32_t low = hardware->dmi.ipmi.base_address & 0xFFFF;
273    more_printf(" Base Address       : %08X%08X\n", high, (low & ~1));
274    more_printf(" IRQ                : %d\n", hardware->dmi.ipmi.irq);
275}
276
277static void show_dmi_battery(int argc __unused, char **argv __unused,
278			     struct s_hardware *hardware)
279{
280    if (hardware->dmi.battery.filled == false) {
281	more_printf("battery information not found on your system, see "
282		    "`show list' to see which module is available.\n");
283	return;
284    }
285    reset_more_printf();
286    more_printf("Battery \n");
287    more_printf(" Vendor             : %s\n",
288		hardware->dmi.battery.manufacturer);
289    more_printf(" Manufacture Date   : %s\n",
290		hardware->dmi.battery.manufacture_date);
291    more_printf(" Serial             : %s\n", hardware->dmi.battery.serial);
292    more_printf(" Name               : %s\n", hardware->dmi.battery.name);
293    more_printf(" Chemistry          : %s\n", hardware->dmi.battery.chemistry);
294    more_printf(" Design Capacity    : %s\n",
295		hardware->dmi.battery.design_capacity);
296    more_printf(" Design Voltage     : %s\n",
297		hardware->dmi.battery.design_voltage);
298    more_printf(" SBDS               : %s\n", hardware->dmi.battery.sbds);
299    more_printf(" SBDS Manuf. Date   : %s\n",
300		hardware->dmi.battery.sbds_manufacture_date);
301    more_printf(" SBDS Chemistry     : %s\n",
302		hardware->dmi.battery.sbds_chemistry);
303    more_printf(" Maximum Error      : %s\n",
304		hardware->dmi.battery.maximum_error);
305    more_printf(" OEM Info           : %s\n", hardware->dmi.battery.oem_info);
306}
307
308static void show_dmi_cpu(int argc __unused, char **argv __unused,
309			 struct s_hardware *hardware)
310{
311    if (hardware->dmi.processor.filled == false) {
312	more_printf("processor information not found on your system, see "
313		    "`show list' to see which module is available.\n");
314	return;
315    }
316    reset_more_printf();
317    more_printf("CPU\n");
318    more_printf(" Socket Designation : %s\n",
319		hardware->dmi.processor.socket_designation);
320    more_printf(" Type               : %s\n", hardware->dmi.processor.type);
321    more_printf(" Family             : %s\n", hardware->dmi.processor.family);
322    more_printf(" Manufacturer       : %s\n",
323		hardware->dmi.processor.manufacturer);
324    more_printf(" Version            : %s\n", hardware->dmi.processor.version);
325    more_printf(" External Clock     : %u\n",
326		hardware->dmi.processor.external_clock);
327    more_printf(" Max Speed          : %u\n",
328		hardware->dmi.processor.max_speed);
329    more_printf(" Current Speed      : %u\n",
330		hardware->dmi.processor.current_speed);
331    more_printf(" Cpu Type           : %u\n",
332		hardware->dmi.processor.signature.type);
333    more_printf(" Cpu Family         : %u\n",
334		hardware->dmi.processor.signature.family);
335    more_printf(" Cpu Model          : %u\n",
336		hardware->dmi.processor.signature.model);
337    more_printf(" Cpu Stepping       : %u\n",
338		hardware->dmi.processor.signature.stepping);
339    more_printf(" Cpu Minor Stepping : %u\n",
340		hardware->dmi.processor.signature.minor_stepping);
341    more_printf("Voltage             : %d.%02d\n",
342                hardware->dmi.processor.voltage_mv / 1000,
343                hardware->dmi.processor.voltage_mv -
344                ((hardware->dmi.processor.voltage_mv / 1000) * 1000));
345    more_printf(" Status             : %s\n", hardware->dmi.processor.status);
346    more_printf(" Upgrade            : %s\n", hardware->dmi.processor.upgrade);
347    more_printf(" Cache L1 Handle    : %s\n", hardware->dmi.processor.cache1);
348    more_printf(" Cache L2 Handle    : %s\n", hardware->dmi.processor.cache2);
349    more_printf(" Cache L3 Handle    : %s\n", hardware->dmi.processor.cache3);
350    more_printf(" Serial             : %s\n", hardware->dmi.processor.serial);
351    more_printf(" Part Number        : %s\n",
352		hardware->dmi.processor.part_number);
353    if (hardware->dmi.processor.core_count != 0)
354        more_printf(" Cores Count        : %d\n", hardware->dmi.processor.core_count);
355    if (hardware->dmi.processor.core_enabled != 0)
356        more_printf(" Cores Enabled      : %d\n", hardware->dmi.processor.core_enabled);
357    if (hardware->dmi.processor.thread_count != 0)
358        more_printf(" Threads Count      : %d\n", hardware->dmi.processor.thread_count);
359
360    more_printf(" ID                 : %s\n", hardware->dmi.processor.id);
361    for (int i = 0; i < PROCESSOR_FLAGS_ELEMENTS; i++) {
362	if (((bool *) (&hardware->dmi.processor.cpu_flags))[i] == true) {
363	    more_printf(" %s\n", cpu_flags_strings[i]);
364	}
365    }
366}
367
368void show_dmi_memory_bank(int argc, char **argv, struct s_hardware *hardware)
369{
370    int bank = -1;
371
372    /* Sanitize arguments */
373    if (argc > 0)
374	bank = strtol(argv[0], (char **)NULL, 10);
375
376    if (errno == ERANGE || bank < 0) {
377	more_printf("This bank number is incorrect\n");
378	return;
379    }
380
381    if ((bank >= hardware->dmi.memory_count) || (bank < 0)) {
382	more_printf("Bank %d number doesn't exist\n", bank);
383	return;
384    }
385    if (hardware->dmi.memory[bank].filled == false) {
386	more_printf("Bank %d doesn't contain any information\n", bank);
387	return;
388    }
389
390    reset_more_printf();
391    more_printf("Memory Bank %d\n", bank);
392    more_printf(" Form Factor  : %s\n", hardware->dmi.memory[bank].form_factor);
393    more_printf(" Type         : %s\n", hardware->dmi.memory[bank].type);
394    more_printf(" Type Detail  : %s\n", hardware->dmi.memory[bank].type_detail);
395    more_printf(" Speed        : %s\n", hardware->dmi.memory[bank].speed);
396    more_printf(" Size         : %s\n", hardware->dmi.memory[bank].size);
397    more_printf(" Device Set   : %s\n", hardware->dmi.memory[bank].device_set);
398    more_printf(" Device Loc.  : %s\n",
399		hardware->dmi.memory[bank].device_locator);
400    more_printf(" Bank Locator : %s\n",
401		hardware->dmi.memory[bank].bank_locator);
402    more_printf(" Total Width  : %s\n", hardware->dmi.memory[bank].total_width);
403    more_printf(" Data Width   : %s\n", hardware->dmi.memory[bank].data_width);
404    more_printf(" Error        : %s\n", hardware->dmi.memory[bank].error);
405    more_printf(" Vendor       : %s\n",
406		hardware->dmi.memory[bank].manufacturer);
407    more_printf(" Serial       : %s\n", hardware->dmi.memory[bank].serial);
408    more_printf(" Asset Tag    : %s\n", hardware->dmi.memory[bank].asset_tag);
409    more_printf(" Part Number  : %s\n", hardware->dmi.memory[bank].part_number);
410}
411
412static void show_dmi_cache(int argc, char **argv, struct s_hardware *hardware)
413{
414    if (!hardware->dmi.cache_count) {
415	more_printf("cache information not found on your system, see "
416		    "`show list' to see which module is available.\n");
417	return;
418    }
419
420    int cache = strtol(argv[0], NULL, 10);
421
422    if (argc != 1 || cache > hardware->dmi.cache_count) {
423	more_printf("show cache [0-%d]\n", hardware->dmi.cache_count - 1);
424	return;
425    }
426
427    reset_more_printf();
428
429    more_printf("Cache Information #%d\n", cache);
430    more_printf("  Socket Designation    : %s\n",
431		hardware->dmi.cache[cache].socket_designation);
432    more_printf("  Configuration         : %s\n",
433		hardware->dmi.cache[cache].configuration);
434    more_printf("  Operational Mode      : %s\n",
435		hardware->dmi.cache[cache].mode);
436    more_printf("  Location              : %s\n",
437		hardware->dmi.cache[cache].location);
438    more_printf("  Installed Size        : %u KB",
439		hardware->dmi.cache[cache].installed_size);
440    more_printf("\n");
441    more_printf("  Maximum Size          : %u KB",
442		hardware->dmi.cache[cache].max_size);
443    more_printf("\n");
444    more_printf("  Supported SRAM Types  : %s",
445		hardware->dmi.cache[cache].supported_sram_types);
446    more_printf("\n");
447    more_printf("  Installed SRAM Type   : %s",
448		hardware->dmi.cache[cache].installed_sram_types);
449    more_printf("\n");
450    more_printf("  Speed                 : %u ns",
451		hardware->dmi.cache[cache].speed);
452    more_printf("\n");
453    more_printf("  Error Correction Type : %s\n",
454		hardware->dmi.cache[cache].error_correction_type);
455    more_printf("  System Type           : %s\n",
456		hardware->dmi.cache[cache].system_type);
457    more_printf("  Associativity         : %s\n",
458		hardware->dmi.cache[cache].associativity);
459}
460
461void show_dmi_memory_module(int argc, char **argv, struct s_hardware *hardware)
462{
463    int module = -1;
464
465    /* Sanitize arguments */
466    if (argc > 0)
467	module = strtol(argv[0], (char **)NULL, 10);
468
469    if (errno == ERANGE || module < 0) {
470	more_printf("This module number is incorrect\n");
471	return;
472    }
473
474    if ((module >= hardware->dmi.memory_module_count) || (module < 0)) {
475	more_printf("Module number %d doesn't exist\n", module);
476	return;
477    }
478
479    if (hardware->dmi.memory_module[module].filled == false) {
480	more_printf("Module %d doesn't contain any information\n", module);
481	return;
482    }
483
484    reset_more_printf();
485    more_printf("Memory Module %d\n", module);
486    more_printf(" Socket Designation : %s\n",
487		hardware->dmi.memory_module[module].socket_designation);
488    more_printf(" Bank Connections   : %s\n",
489		hardware->dmi.memory_module[module].bank_connections);
490    more_printf(" Current Speed      : %s\n",
491		hardware->dmi.memory_module[module].speed);
492    more_printf(" Type               : %s\n",
493		hardware->dmi.memory_module[module].type);
494    more_printf(" Installed Size     : %s\n",
495		hardware->dmi.memory_module[module].installed_size);
496    more_printf(" Enabled Size       : %s\n",
497		hardware->dmi.memory_module[module].enabled_size);
498    more_printf(" Error Status       : %s\n",
499		hardware->dmi.memory_module[module].error_status);
500}
501
502void main_show_dmi(int argc __unused, char **argv __unused,
503		   struct s_hardware *hardware)
504{
505
506    if (hardware->is_dmi_valid == false) {
507	more_printf("No valid DMI table found, exiting.\n");
508	return;
509    }
510    reset_more_printf();
511    more_printf("DMI Table version %u.%u found\n",
512		hardware->dmi.dmitable.major_version,
513		hardware->dmi.dmitable.minor_version);
514
515    show_dmi_modules(0, NULL, hardware);
516}
517
518void show_dmi_memory_modules(int argc __unused, char **argv __unused,
519			     struct s_hardware *hardware)
520{
521    /* Do we have so display unpopulated banks ? */
522    int show_free_banks = 1;
523
524    more_printf("Memory Size   : %lu MB (%lu KB)\n",
525		(hardware->detected_memory_size + (1 << 9)) >> 10,
526		hardware->detected_memory_size);
527
528    if ((hardware->dmi.memory_count <= 0)
529	&& (hardware->dmi.memory_module_count <= 0)) {
530	more_printf("No memory bank found\n");
531	return;
532    }
533
534    /* Sanitize arguments */
535    if (argc > 0) {
536	/* When we display a summary, there is no need to show the unpopulated banks
537	 * The first argv is set to define this behavior
538	 */
539	show_free_banks = strtol(argv[0], NULL, 10);
540	if (errno == ERANGE || show_free_banks < 0 || show_free_banks > 1)
541	    goto usage;
542    }
543
544    reset_more_printf();
545    /* If type 17 is available */
546    if (hardware->dmi.memory_count > 0) {
547	char bank_number[255];
548	more_printf("Memory Banks\n");
549	for (int i = 0; i < hardware->dmi.memory_count; i++) {
550	    if (hardware->dmi.memory[i].filled == true) {
551		memset(bank_number, 0, sizeof(bank_number));
552		snprintf(bank_number, sizeof(bank_number), "%d ", i);
553		if (show_free_banks == false) {
554		    if (strncmp(hardware->dmi.memory[i].size, "Free", 4))
555			more_printf(" bank %02d      : %s %s@%s\n",
556				    i, hardware->dmi.memory[i].size,
557				    hardware->dmi.memory[i].type,
558				    hardware->dmi.memory[i].speed);
559		} else {
560		    more_printf(" bank %02d      : %s %s@%s\n", i,
561				hardware->dmi.memory[i].size,
562				hardware->dmi.memory[i].type,
563				hardware->dmi.memory[i].speed);
564		}
565	    }
566	}
567    } else if (hardware->dmi.memory_module_count > 0) {
568	/* Let's use type 6 as a fallback of type 17 */
569	more_printf("Memory Modules\n");
570	for (int i = 0; i < hardware->dmi.memory_module_count; i++) {
571	    if (hardware->dmi.memory_module[i].filled == true) {
572		more_printf(" module %02d    : %s %s@%s\n", i,
573			    hardware->dmi.memory_module[i].enabled_size,
574			    hardware->dmi.memory_module[i].type,
575			    hardware->dmi.memory_module[i].speed);
576	    }
577	}
578    }
579
580    return;
581    //printf("Type 'show bank<bank_number>' for more details.\n");
582
583usage:
584    more_printf("show memory <clear screen? <show free banks?>>\n");
585    return;
586}
587
588void show_dmi_oem_strings(int argc __unused, char **argv __unused,
589			  struct s_hardware *hardware)
590{
591    reset_more_printf();
592
593    if (strlen(hardware->dmi.oem_strings))
594	more_printf("OEM Strings\n%s", hardware->dmi.oem_strings);
595}
596
597void show_dmi_hardware_security(int argc __unused, char **argv __unused,
598				struct s_hardware *hardware)
599{
600    reset_more_printf();
601
602    if (!hardware->dmi.hardware_security.filled)
603	return;
604
605    more_printf("Hardware Security\n");
606    more_printf("  Power-On Password Status      : %s\n",
607		hardware->dmi.hardware_security.power_on_passwd_status);
608    more_printf("  Keyboard Password Status      : %s\n",
609		hardware->dmi.hardware_security.keyboard_passwd_status);
610    more_printf("  Administrator Password Status : %s\n",
611		hardware->dmi.hardware_security.administrator_passwd_status);
612    more_printf("  Front Panel Reset Status      : %s\n",
613		hardware->dmi.hardware_security.front_panel_reset_status);
614}
615
616struct cli_callback_descr list_dmi_show_modules[] = {
617    {
618     .name = CLI_DMI_BASE_BOARD,
619     .exec = show_dmi_base_board,
620     .nomodule = false,
621     },
622    {
623     .name = CLI_DMI_BIOS,
624     .exec = show_dmi_bios,
625     .nomodule = false,
626     },
627    {
628     .name = CLI_DMI_BATTERY,
629     .exec = show_dmi_battery,
630     .nomodule = false,
631     },
632    {
633     .name = CLI_DMI_CHASSIS,
634     .exec = show_dmi_chassis,
635     .nomodule = false,
636     },
637    {
638     .name = CLI_DMI_MEMORY,
639     .exec = show_dmi_memory_modules,
640     .nomodule = false,
641     },
642    {
643     .name = CLI_DMI_MEMORY_BANK,
644     .exec = show_dmi_memory_bank,
645     .nomodule = false,
646     },
647    {
648     .name = "module",
649     .exec = show_dmi_memory_module,
650     .nomodule = false,
651     },
652    {
653     .name = CLI_DMI_PROCESSOR,
654     .exec = show_dmi_cpu,
655     .nomodule = false,
656     },
657    {
658     .name = CLI_DMI_SYSTEM,
659     .exec = show_dmi_system,
660     .nomodule = false,
661     },
662    {
663     .name = CLI_DMI_OEM,
664     .exec = show_dmi_oem_strings,
665     .nomodule = false,
666     },
667    {
668     .name = CLI_DMI_SECURITY,
669     .exec = show_dmi_hardware_security,
670     .nomodule = false,
671     },
672    {
673     .name = CLI_DMI_IPMI,
674     .exec = show_dmi_ipmi,
675     .nomodule = false,
676     },
677    {
678     .name = CLI_DMI_CACHE,
679     .exec = show_dmi_cache,
680     .nomodule = false,
681     },
682    {
683     .name = CLI_DMI_LIST,
684     .exec = show_dmi_modules,
685     .nomodule = false,
686     },
687    {
688     .name = NULL,
689     .exec = NULL,
690     .nomodule = false,
691     },
692};
693
694struct cli_module_descr dmi_show_modules = {
695    .modules = list_dmi_show_modules,
696    .default_callback = main_show_dmi,
697};
698
699struct cli_mode_descr dmi_mode = {
700    .mode = DMI_MODE,
701    .name = CLI_DMI,
702    .default_modules = NULL,
703    .show_modules = &dmi_show_modules,
704    .set_modules = NULL,
705};
706