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
12static 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
18static 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
24typedef 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
55static 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
66void 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*/
86static 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
123static 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
161static 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
214static 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
240static 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
292static 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
319static 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
356static 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
385static 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
416static 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
431static 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
448static 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
473static 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
511static 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
524static const luaL_Reg dmilib[] = {
525  {"gettable", dmi_gettable},
526  {"supported", dmi_supported},
527  {NULL, NULL}
528};
529
530
531LUALIB_API int luaopen_dmi (lua_State *L) {
532  luaL_newlib(L, dmilib);
533  return 1;
534}
535
536