1 #include <stdlib.h>
2 #include <string.h>
3 
4 #define ldmilib_c       /* Define the library */
5 
6 /* Include the Lua API header files */
7 #include "lua.h"
8 #include "lauxlib.h"
9 #include "lualib.h"
10 #include "dmi/dmi.h"
11 
add_string_item(lua_State * L,const char * item,const char * value_str)12 static void add_string_item(lua_State *L, const char *item, const char *value_str) {
13  lua_pushstring(L,item);
14  lua_pushstring(L,value_str);
15  lua_settable(L,-3);
16 }
17 
add_int_item(lua_State * L,const char * item,int value_int)18 static void add_int_item(lua_State *L, const char *item, int value_int) {
19  lua_pushstring(L,item);
20  lua_pushnumber(L,value_int);
21  lua_settable(L,-3);
22 }
23 
24 typedef int (*table_fn)(lua_State*, s_dmi*);
25 
26 /* Add a Lua_String entry to the table on stack
27    xxx_P is the poiter version (i.e., pBase is a pointer)
28    xxx_S is the staic version (i.e., Base is the struct)
29 */
30 #define LUA_ADD_STR_P(pLua_state, pBase, Field) \
31   add_string_item(pLua_state, #Field, pBase->Field);
32 #define LUA_ADD_STR_S(pLua_state, Base, Field) \
33   add_string_item(pLua_state, #Field, Base.Field);
34 
35 /* Add a Lua_Number entry to the table on stack
36    xxx_P is the poiter version (i.e., pBase is a pointer)
37    xxx_S is the staic version (i.e., Base is the struct)
38 */
39 #define LUA_ADD_NUM_P(pLua_state, pBase, Field) \
40   add_int_item(pLua_state, #Field, pBase->Field);
41 #define LUA_ADD_NUM_S(pLua_state, Base, Field) \
42   add_int_item(pLua_state, #Field, Base.Field);
43 
44 /* Add a sub-DMI table to the table on stack
45    All (*table_fn)() have to be named as get_<tabel_name>_table() for this
46    macro to work. For example, for the bios subtable, the table_fn is
47    get_bios_table() and the subtable name is "bios".
48    All (*table_fn)() have to return 1 if a subtable is created on the stack
49    or 0 if the subtable is not created (no corresponding dim subtable found).
50 */
51 #define LUA_ADD_TABLE(pLua_state, pDmi, tb_name) \
52   add_dmi_sub_table(pLua_state, pDmi, #tb_name, get_ ## tb_name ## _table);
53 
54 
add_dmi_sub_table(lua_State * L,s_dmi * dmi_ptr,char * table_name,table_fn get_table_fn)55 static void add_dmi_sub_table(lua_State *L, s_dmi *dmi_ptr, char *table_name,
56                               table_fn get_table_fn)
57 {
58   if (get_table_fn(L, dmi_ptr)) {  /* only adding it when it is there */
59     lua_pushstring(L, table_name);
60     lua_insert(L, -2);
61     lua_settable(L,-3);
62   }
63 }
64 
65 
get_bool_table(lua_State * L,const char * str_table[],int n_elem,bool * bool_table)66 void get_bool_table(lua_State *L, const char *str_table[], int n_elem,
67                            bool *bool_table)
68 {
69   int i;
70   for (i = 0; i < n_elem; i++) {
71     if (!str_table[i] || !*str_table[i])  /* aviod NULL/empty string */
72       continue;
73 
74     lua_pushstring(L, str_table[i]);
75     lua_pushboolean(L, bool_table[i]);
76     lua_settable(L,-3);
77   }
78 }
79 
80 
81 /*
82 ** {======================================================
83 ** DMI subtables
84 ** =======================================================
85 */
get_bios_table(lua_State * L,s_dmi * dmi_ptr)86 static int get_bios_table(lua_State *L, s_dmi *dmi_ptr)
87 {
88   s_bios *bios = &dmi_ptr->bios;
89 
90   if (!bios->filled)
91     return 0;
92   /* bios */
93   lua_newtable(L);
94   LUA_ADD_STR_P(L, bios, vendor)
95   LUA_ADD_STR_P(L, bios, version)
96   LUA_ADD_STR_P(L, bios, release_date)
97   LUA_ADD_STR_P(L, bios, bios_revision)
98   LUA_ADD_STR_P(L, bios, firmware_revision)
99   LUA_ADD_NUM_P(L, bios, address)
100   LUA_ADD_NUM_P(L, bios, runtime_size)
101   LUA_ADD_STR_P(L, bios, runtime_size_unit)
102   LUA_ADD_NUM_P(L, bios, rom_size)
103   LUA_ADD_STR_P(L, bios, rom_size_unit)
104 
105   /* bios characteristics */
106   lua_pushstring(L, "chars");
107   lua_newtable(L);
108   get_bool_table(L, bios_charac_strings,
109                  sizeof(s_characteristics)/sizeof(bool),
110                  (bool *)(&bios->characteristics));
111   get_bool_table(L, bios_charac_x1_strings,
112                  sizeof(s_characteristics_x1)/sizeof(bool),
113                  (bool *)(&bios->characteristics_x1));
114   get_bool_table(L, bios_charac_x2_strings,
115                  sizeof(s_characteristics_x2)/sizeof(bool),
116                  (bool *)(&bios->characteristics_x2));
117   lua_settable(L,-3);
118 
119   return 1;
120 }
121 
122 
get_system_table(lua_State * L,s_dmi * dmi_ptr)123 static int get_system_table(lua_State *L, s_dmi *dmi_ptr)
124 {
125   s_system *system = &dmi_ptr->system;
126 
127   if (!system->filled)
128     return 0;
129   /* system */
130   lua_newtable(L);
131   LUA_ADD_STR_P(L, system, manufacturer)
132   LUA_ADD_STR_P(L, system, product_name)
133   LUA_ADD_STR_P(L, system, version)
134   LUA_ADD_STR_P(L, system, serial)
135   LUA_ADD_STR_P(L, system, uuid)
136   LUA_ADD_STR_P(L, system, wakeup_type)
137   LUA_ADD_STR_P(L, system, sku_number)
138   LUA_ADD_STR_P(L, system, family)
139   LUA_ADD_STR_P(L, system, system_boot_status)
140   LUA_ADD_STR_P(L, system, configuration_options)
141 
142   /* system reset */
143   if (system->system_reset.filled) {
144     lua_pushstring(L, "reset");
145     lua_newtable(L);
146     LUA_ADD_NUM_S(L, system->system_reset, status)
147     LUA_ADD_NUM_S(L, system->system_reset, watchdog)
148     LUA_ADD_STR_S(L, system->system_reset, boot_option)
149     LUA_ADD_STR_S(L, system->system_reset, boot_option_on_limit)
150 	  LUA_ADD_STR_S(L, system->system_reset, reset_count)
151 	  LUA_ADD_STR_S(L, system->system_reset, reset_limit)
152 	  LUA_ADD_STR_S(L, system->system_reset, timer_interval)
153 	  LUA_ADD_STR_S(L, system->system_reset, timeout)
154     lua_settable(L,-3);
155   }
156 
157   return 1;
158 }
159 
160 
get_base_board_table(lua_State * L,s_dmi * dmi_ptr)161 static int get_base_board_table(lua_State *L, s_dmi *dmi_ptr)
162 {
163   s_base_board *base_board = &dmi_ptr->base_board;
164   int n_dev = sizeof(base_board->devices_information) /
165               sizeof(base_board->devices_information[0]);
166   int i, j, has_dev;
167 
168   if (!base_board->filled)
169     return 0;
170   /* base_board */
171   lua_newtable(L);
172   LUA_ADD_STR_P(L, base_board, manufacturer)
173   LUA_ADD_STR_P(L, base_board, product_name)
174   LUA_ADD_STR_P(L, base_board, version)
175   LUA_ADD_STR_P(L, base_board, serial)
176   LUA_ADD_STR_P(L, base_board, asset_tag)
177   LUA_ADD_STR_P(L, base_board, location)
178   LUA_ADD_STR_P(L, base_board, type)
179 
180   /* base board features */
181   lua_pushstring(L, "features");
182   lua_newtable(L);
183   get_bool_table(L, base_board_features_strings,
184                  sizeof(s_base_board_features)/sizeof(bool),
185                  (bool *)(&base_board->features));
186   lua_settable(L,-3);
187 
188   /* on-board devices */
189   for (has_dev = 0, i = 0; i < n_dev; i++)
190     if (*base_board->devices_information[i].type)
191       has_dev++;
192 
193   if (has_dev) {
194     lua_pushstring(L, "devices");
195     lua_newtable(L);
196     for (i = 0, j = 1; i < n_dev; i++) {
197       if (!*base_board->devices_information[i].type)  /* empty device */
198         continue;
199 
200       lua_pushinteger(L, j++);
201       lua_newtable(L);
202       LUA_ADD_STR_S(L, base_board->devices_information[i], type)
203       LUA_ADD_STR_S(L, base_board->devices_information[i], description)
204       LUA_ADD_NUM_S(L, base_board->devices_information[i], status)
205       lua_settable(L,-3);
206     }
207     lua_settable(L,-3);
208   }
209 
210   return 1;
211 }
212 
213 
get_chassis_table(lua_State * L,s_dmi * dmi_ptr)214 static int get_chassis_table(lua_State *L, s_dmi *dmi_ptr)
215 {
216   s_chassis *chassis = &dmi_ptr->chassis;
217 
218   if (!chassis->filled)
219     return 0;
220   /* chassis */
221   lua_newtable(L);
222   LUA_ADD_STR_P(L, chassis, manufacturer)
223   LUA_ADD_STR_P(L, chassis, type)
224   LUA_ADD_STR_P(L, chassis, lock)
225   LUA_ADD_STR_P(L, chassis, version)
226   LUA_ADD_STR_P(L, chassis, serial)
227   LUA_ADD_STR_P(L, chassis, asset_tag)
228   LUA_ADD_STR_P(L, chassis, boot_up_state)
229   LUA_ADD_STR_P(L, chassis, power_supply_state)
230   LUA_ADD_STR_P(L, chassis, thermal_state)
231   LUA_ADD_STR_P(L, chassis, security_status)
232   LUA_ADD_STR_P(L, chassis, oem_information)
233   LUA_ADD_NUM_P(L, chassis, height)
234   LUA_ADD_NUM_P(L, chassis, nb_power_cords)
235 
236   return 1;
237 }
238 
239 
get_processor_table(lua_State * L,s_dmi * dmi_ptr)240 static int get_processor_table(lua_State *L, s_dmi *dmi_ptr)
241 {
242   s_processor *processor = &dmi_ptr->processor;
243   s_signature *signature = &processor->signature;
244 
245   if (!processor->filled)
246     return 0;
247   /* processor */
248   lua_newtable(L);
249   LUA_ADD_STR_P(L, processor, socket_designation)
250   LUA_ADD_STR_P(L, processor, type)
251   LUA_ADD_STR_P(L, processor, family)
252   LUA_ADD_STR_P(L, processor, manufacturer)
253   LUA_ADD_STR_P(L, processor, version)
254   LUA_ADD_NUM_P(L, processor, external_clock)
255   LUA_ADD_NUM_P(L, processor, max_speed)
256   LUA_ADD_NUM_P(L, processor, current_speed)
257   LUA_ADD_NUM_P(L, processor, voltage_mv)
258   LUA_ADD_STR_P(L, processor, status)
259   LUA_ADD_STR_P(L, processor, upgrade)
260   LUA_ADD_STR_P(L, processor, cache1)
261   LUA_ADD_STR_P(L, processor, cache2)
262   LUA_ADD_STR_P(L, processor, cache3)
263   LUA_ADD_STR_P(L, processor, serial)
264   LUA_ADD_STR_P(L, processor, part_number)
265   LUA_ADD_STR_P(L, processor, id)
266   LUA_ADD_NUM_P(L, processor, core_count)
267   LUA_ADD_NUM_P(L, processor, core_enabled)
268   LUA_ADD_NUM_P(L, processor, thread_count)
269 
270   /* processor signature */
271   lua_pushstring(L, "signature");
272   lua_newtable(L);
273   LUA_ADD_NUM_P(L, signature, type)
274   LUA_ADD_NUM_P(L, signature, family)
275   LUA_ADD_NUM_P(L, signature, model)
276   LUA_ADD_NUM_P(L, signature, stepping)
277   LUA_ADD_NUM_P(L, signature, minor_stepping)
278   lua_settable(L,-3);
279 
280   /* processor flags */
281   lua_pushstring(L, "flags");
282   lua_newtable(L);
283   get_bool_table(L, cpu_flags_strings,
284                  sizeof(s_dmi_cpu_flags)/sizeof(bool),
285                  (bool *)(&processor->cpu_flags));
286   lua_settable(L,-3);
287 
288   return 1;
289 }
290 
291 
get_battery_table(lua_State * L,s_dmi * dmi_ptr)292 static int get_battery_table(lua_State *L, s_dmi *dmi_ptr)
293 {
294   s_battery *battery = &dmi_ptr->battery;
295 
296   if (!battery->filled)
297     return 0;
298   /* battery */
299   lua_newtable(L);
300   LUA_ADD_STR_P(L, battery, location)
301   LUA_ADD_STR_P(L, battery, manufacturer)
302   LUA_ADD_STR_P(L, battery, manufacture_date)
303   LUA_ADD_STR_P(L, battery, serial)
304   LUA_ADD_STR_P(L, battery, name)
305   LUA_ADD_STR_P(L, battery, chemistry)
306   LUA_ADD_STR_P(L, battery, design_capacity)
307   LUA_ADD_STR_P(L, battery, design_voltage)
308   LUA_ADD_STR_P(L, battery, sbds)
309   LUA_ADD_STR_P(L, battery, sbds_serial)
310   LUA_ADD_STR_P(L, battery, maximum_error)
311   LUA_ADD_STR_P(L, battery, sbds_manufacture_date)
312   LUA_ADD_STR_P(L, battery, sbds_chemistry)
313   LUA_ADD_STR_P(L, battery, oem_info)
314 
315   return 1;
316 }
317 
318 
get_memory_table(lua_State * L,s_dmi * dmi_ptr)319 static int get_memory_table(lua_State *L, s_dmi *dmi_ptr)
320 {
321   s_memory *memory = dmi_ptr->memory;
322   int i, j, n_mem = dmi_ptr->memory_count;
323 
324   if (n_mem <= 0)  /*  no memory info */
325     return 0;
326 
327   /* memory */
328   lua_newtable(L);
329   for (j = 1, i = 0; i < n_mem; i++) {
330     if (!memory[i].filled)
331       continue;
332 
333     lua_pushinteger(L, j++);
334     lua_newtable(L);
335     LUA_ADD_STR_S(L, memory[i], manufacturer)
336     LUA_ADD_STR_S(L, memory[i], error)
337     LUA_ADD_STR_S(L, memory[i], total_width)
338     LUA_ADD_STR_S(L, memory[i], data_width)
339     LUA_ADD_STR_S(L, memory[i], size)
340     LUA_ADD_STR_S(L, memory[i], form_factor)
341     LUA_ADD_STR_S(L, memory[i], device_set)
342     LUA_ADD_STR_S(L, memory[i], device_locator)
343     LUA_ADD_STR_S(L, memory[i], bank_locator)
344     LUA_ADD_STR_S(L, memory[i], type)
345     LUA_ADD_STR_S(L, memory[i], type_detail)
346     LUA_ADD_STR_S(L, memory[i], speed)
347     LUA_ADD_STR_S(L, memory[i], serial)
348     LUA_ADD_STR_S(L, memory[i], asset_tag)
349     LUA_ADD_STR_S(L, memory[i], part_number)
350     lua_settable(L,-3);
351   }
352   return 1;
353 }
354 
355 
get_memory_module_table(lua_State * L,s_dmi * dmi_ptr)356 static int get_memory_module_table(lua_State *L, s_dmi *dmi_ptr)
357 {
358   s_memory_module *memory_module = dmi_ptr->memory_module;
359   int i, j, n_mem = dmi_ptr->memory_module_count;
360 
361   if (n_mem <= 0)  /*  no memory module info */
362     return 0;
363 
364   /* memory module */
365   lua_newtable(L);
366   for (j = 1, i = 0; i < n_mem; i++) {
367     if (!memory_module[i].filled)
368       continue;
369 
370     lua_pushinteger(L, j++);
371     lua_newtable(L);
372     LUA_ADD_STR_S(L, memory_module[i], socket_designation)
373     LUA_ADD_STR_S(L, memory_module[i], bank_connections)
374     LUA_ADD_STR_S(L, memory_module[i], speed)
375     LUA_ADD_STR_S(L, memory_module[i], type)
376     LUA_ADD_STR_S(L, memory_module[i], installed_size)
377     LUA_ADD_STR_S(L, memory_module[i], enabled_size)
378     LUA_ADD_STR_S(L, memory_module[i], error_status)
379     lua_settable(L,-3);
380   }
381   return 1;
382 }
383 
384 
get_cache_table(lua_State * L,s_dmi * dmi_ptr)385 static int get_cache_table(lua_State *L, s_dmi *dmi_ptr)
386 {
387   s_cache *cache = dmi_ptr->cache;
388   int i, n_cache = dmi_ptr->cache_count;
389 
390   if (n_cache <= 0)  /*  no cache info */
391     return 0;
392 
393   /* memory */
394   lua_newtable(L);
395   for (i = 0; i < n_cache; i++) {
396     lua_pushinteger(L, i + 1);
397     lua_newtable(L);
398     LUA_ADD_STR_S(L, cache[i], socket_designation)
399     LUA_ADD_STR_S(L, cache[i], configuration)
400     LUA_ADD_STR_S(L, cache[i], mode)
401     LUA_ADD_STR_S(L, cache[i], location)
402     LUA_ADD_NUM_S(L, cache[i], installed_size)
403     LUA_ADD_NUM_S(L, cache[i], max_size)
404     LUA_ADD_STR_S(L, cache[i], supported_sram_types)
405     LUA_ADD_STR_S(L, cache[i], installed_sram_types)
406     LUA_ADD_NUM_S(L, cache[i], speed)
407     LUA_ADD_STR_S(L, cache[i], error_correction_type)
408     LUA_ADD_STR_S(L, cache[i], system_type)
409     LUA_ADD_STR_S(L, cache[i], associativity)
410     lua_settable(L,-3);
411   }
412   return 1;
413 }
414 
415 
get_hardware_security_table(lua_State * L,s_dmi * dmi_ptr)416 static int get_hardware_security_table(lua_State *L, s_dmi *dmi_ptr)
417 {
418   if (!dmi_ptr->hardware_security.filled)
419     return 0;
420   /* hardware_security */
421   lua_newtable(L);
422   LUA_ADD_STR_S(L, dmi_ptr->hardware_security, power_on_passwd_status)
423 	LUA_ADD_STR_S(L, dmi_ptr->hardware_security, keyboard_passwd_status)
424 	LUA_ADD_STR_S(L, dmi_ptr->hardware_security, administrator_passwd_status)
425 	LUA_ADD_STR_S(L, dmi_ptr->hardware_security, front_panel_reset_status)
426 
427   return 1;
428 }
429 
430 
get_dmi_info_table(lua_State * L,s_dmi * dmi_ptr)431 static int get_dmi_info_table(lua_State *L, s_dmi *dmi_ptr)
432 {
433   dmi_table *dmitable = &dmi_ptr->dmitable;
434 
435   /* dmi info */
436   lua_newtable(L);
437   LUA_ADD_NUM_P(L, dmitable, num)
438   LUA_ADD_NUM_P(L, dmitable, len)
439   LUA_ADD_NUM_P(L, dmitable, ver)
440   LUA_ADD_NUM_P(L, dmitable, base)
441   LUA_ADD_NUM_P(L, dmitable, major_version)
442   LUA_ADD_NUM_P(L, dmitable, minor_version)
443 
444   return 1;
445 }
446 
447 
get_ipmi_table(lua_State * L,s_dmi * dmi_ptr)448 static int get_ipmi_table(lua_State *L, s_dmi *dmi_ptr)
449 {
450   s_ipmi *ipmi = &dmi_ptr->ipmi;
451 
452   if (!ipmi->filled)
453     return 0;
454   /* ipmi */
455   lua_newtable(L);
456   LUA_ADD_STR_P(L, ipmi, interface_type)
457   LUA_ADD_NUM_P(L, ipmi, major_specification_version)
458   LUA_ADD_NUM_P(L, ipmi, minor_specification_version)
459   LUA_ADD_NUM_P(L, ipmi, I2C_slave_address)
460   LUA_ADD_NUM_P(L, ipmi, nv_address)
461   LUA_ADD_NUM_P(L, ipmi, base_address)
462   LUA_ADD_NUM_P(L, ipmi, irq)
463 
464   return 1;
465 }
466 /*
467 ** {======================================================
468 ** End of DMI subtables
469 ** =======================================================
470 */
471 
472 
dmi_gettable(lua_State * L)473 static int dmi_gettable(lua_State *L)
474 {
475   s_dmi dmi;
476 
477   lua_newtable(L);
478 
479   if ( ! dmi_iterate(&dmi) ) {
480           printf("No DMI Structure found\n");
481           return -1;
482   }
483 
484   parse_dmitable(&dmi);
485 
486   LUA_ADD_NUM_S(L, dmi, memory_module_count)
487   LUA_ADD_NUM_S(L, dmi, memory_count)
488   LUA_ADD_NUM_S(L, dmi, cache_count)
489   LUA_ADD_STR_S(L, dmi, oem_strings)
490 
491   LUA_ADD_TABLE(L, &dmi, bios)
492   LUA_ADD_TABLE(L, &dmi, system)
493   LUA_ADD_TABLE(L, &dmi, base_board)
494   LUA_ADD_TABLE(L, &dmi, chassis)
495   LUA_ADD_TABLE(L, &dmi, processor)
496   LUA_ADD_TABLE(L, &dmi, battery)
497   LUA_ADD_TABLE(L, &dmi, memory)
498   LUA_ADD_TABLE(L, &dmi, memory_module)
499   LUA_ADD_TABLE(L, &dmi, cache)
500   LUA_ADD_TABLE(L, &dmi, ipmi)
501   LUA_ADD_TABLE(L, &dmi, hardware_security)
502   LUA_ADD_TABLE(L, &dmi, dmi_info)
503 
504   /* set global variable: lua_setglobal(L, "dmitable"); */
505 
506   /* return number of return values on stack */
507   return 1;
508 }
509 
510 
dmi_supported(lua_State * L)511 static int dmi_supported(lua_State *L)
512 {
513   s_dmi dmi;
514 
515   if ( dmi_iterate(&dmi) ) {
516     lua_pushboolean(L, 1);
517   } else {
518     lua_pushboolean(L, 0);
519   }
520   return 1;
521 }
522 
523 
524 static const luaL_Reg dmilib[] = {
525   {"gettable", dmi_gettable},
526   {"supported", dmi_supported},
527   {NULL, NULL}
528 };
529 
530 
luaopen_dmi(lua_State * L)531 LUALIB_API int luaopen_dmi (lua_State *L) {
532   luaL_newlib(L, dmilib);
533   return 1;
534 }
535 
536