hdt: More snprintf Use statusbar to display content
[profile/ivi/syslinux.git] / sample / hdt.c
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 /*
30  * hdt.c
31  *
32  * An Hardware Detection Tool
33  */
34
35 #include <string.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <console.h>
39 #include "com32io.h"
40 #include "menu.h"
41 #include "help.h"
42 #include "passwords.h"
43 #include "cpuid.h"
44 #include "dmi/dmi.h"
45 #include "sys/pci.h"
46
47 #define PRODUCT_NAME "Hardware Detection Tool"
48 #define AUTHOR "Erwan Velu"
49 #define VERSION "0.1.3"
50
51 #define EDITPROMPT 21
52
53 #define SUBMENULEN 50
54 #define WITH_PCI 1
55 #define WITH_MENU_DISPLAY 1
56
57 unsigned char MAIN_MENU, CPU_MENU, MOBO_MENU, CHASSIS_MENU, BIOS_MENU, SYSTEM_MENU, PCI_MENU, KERNEL_MENU;
58 unsigned char MEMORY_MENU,  MEMORY_SUBMENU[32], DISK_MENU, DISK_SUBMENU[32], PCI_SUBMENU[128],BATTERY_MENU;
59 int nb_sub_disk_menu=0;
60 int nb_pci_devices=0;
61 bool is_dmi_valid=false;
62 int menu_count=0;
63
64 #define ATTR_PACKED __attribute__((packed))
65
66 /* Useless stuff until I manage how to send ata packets */
67 #ifdef ATA
68 enum {
69         ATA_ID_FW_REV           = 23,
70         ATA_ID_PROD             = 27,
71         ATA_ID_FW_REV_LEN       = 8,
72         ATA_ID_PROD_LEN         = 40,
73 };
74 #endif
75
76 struct ata_identify_device {
77   unsigned short words000_009[10];
78   unsigned char  serial_no[20];
79   unsigned short words020_022[3];
80   unsigned char  fw_rev[8];
81   unsigned char  model[40];
82   unsigned short words047_079[33];
83   unsigned short major_rev_num;
84   unsigned short minor_rev_num;
85   unsigned short command_set_1;
86   unsigned short command_set_2;
87   unsigned short command_set_extension;
88   unsigned short cfs_enable_1;
89   unsigned short word086;
90   unsigned short csf_default;
91   unsigned short words088_255[168];
92 } ATTR_PACKED;
93
94 struct diskinfo {
95   int disk;
96   int ebios;                    /* EBIOS supported on this disk */
97   int cbios;                    /* CHS geometry is valid */
98   int heads;
99   int sectors_per_track;
100   int sectors;
101   int cylinders;
102   char edd_version[4];
103   struct ata_identify_device aid; /* IDENTIFY xxx DEVICE data */
104   char host_bus_type[5];
105   char interface_type[9];
106   char interface_port;
107 } ATTR_PACKED;
108
109 /*
110  * Get a disk block and return a malloc'd buffer.
111  * Uses the disk number and information from disk_info.
112  */
113 struct ebios_dapa {
114   uint16_t len;
115   uint16_t count;
116   uint16_t off;
117   uint16_t seg;
118   uint64_t lba;
119 };
120
121
122
123 // BYTE=8
124 // WORD=16
125 // DWORD=32
126 // QWORD=64
127 struct device_parameter {
128  uint16_t len;
129  uint16_t info;
130  uint32_t cylinders;
131  uint32_t heads;
132  uint32_t sectors_per_track;
133  uint64_t sectors;
134  uint16_t bytes_per_sector;
135  uint32_t dpte_pointer;
136  uint16_t device_path_information;
137  uint8_t  device_path_lenght;
138  uint8_t  device_path_reserved;
139  uint16_t device_path_reserved_2;
140  uint8_t  host_bus_type[4];
141  uint8_t  interface_type[8];
142  uint64_t interace_path;
143  uint64_t device_path[2];
144  uint8_t  reserved;
145  uint8_t  cheksum;
146 } ATTR_PACKED;
147
148 #ifdef ATA
149 /**
150  *      ata_id_string - Convert IDENTIFY DEVICE page into string
151  *      @id: IDENTIFY DEVICE results we will examine
152  *      @s: string into which data is output
153  *      @ofs: offset into identify device page
154  *      @len: length of string to return. must be an even number.
155  *
156  *      The strings in the IDENTIFY DEVICE page are broken up into
157  *      16-bit chunks.  Run through the string, and output each
158  *      8-bit chunk linearly, regardless of platform.
159  *
160  *      LOCKING:
161  *      caller.
162  */
163
164 void ata_id_string(const uint16_t *id, unsigned char *s,
165                    unsigned int ofs, unsigned int len)
166 {
167         unsigned int c;
168
169         while (len > 0) {
170                 c = id[ofs] >> 8;
171                 *s = c;
172                 s++;
173
174                 c = id[ofs] & 0xff;
175                 *s = c;
176                 s++;
177
178                 ofs++;
179                 len -= 2;
180         }
181 }
182
183 /**
184  *      ata_id_c_string - Convert IDENTIFY DEVICE page into C string
185  *      @id: IDENTIFY DEVICE results we will examine
186  *      @s: string into which data is output
187  *      @ofs: offset into identify device page
188  *      @len: length of string to return. must be an odd number.
189  *
190  *      This function is identical to ata_id_string except that it
191  *      trims trailing spaces and terminates the resulting string with
192  *      null.  @len must be actual maximum length (even number) + 1.
193  *
194  *      LOCKING:
195  *      caller.
196  */
197 void ata_id_c_string(const uint16_t *id, unsigned char *s,
198                      unsigned int ofs, unsigned int len)
199 {
200         unsigned char *p;
201
202         //WARN_ON(!(len & 1));
203
204         ata_id_string(id, s, ofs, len - 1);
205
206         p = s + strnlen(s, len - 1);
207         while (p > s && p[-1] == ' ')
208                 p--;
209         *p = '\0';
210 }
211 #endif
212
213 /* Display CPU registers for debugging purposes */
214 static void printregs(const com32sys_t *r)
215 {
216   printf("eflags = %08x  ds = %04x  es = %04x  fs = %04x  gs = %04x\n"
217          "eax = %08x  ebx = %08x  ecx = %08x  edx = %08x\n"
218          "ebp = %08x  esi = %08x  edi = %08x  esp = %08x\n",
219          r->eflags.l, r->ds, r->es, r->fs, r->gs,
220          r->eax.l, r->ebx.l, r->ecx.l, r->edx.l,
221          r->ebp.l, r->esi.l, r->edi.l, r->_unused_esp.l);
222 }
223
224
225 /*
226  * Call int 13h, but with retry on failure.  Especially floppies need this.
227  */
228 static int int13_retry(const com32sys_t *inreg, com32sys_t *outreg)
229 {
230   int retry = 6;                /* Number of retries */
231   com32sys_t tmpregs;
232
233   if ( !outreg ) outreg = &tmpregs;
234
235   while ( retry-- ) {
236     __intcall(0x13, inreg, outreg);
237     if ( !(outreg->eflags.l & EFLAGS_CF) )
238       return 0;                 /* CF=0, OK */
239   }
240
241   return -1;                    /* Error */
242 }
243
244 /* In the menu system, what to do on keyboard timeout */
245 TIMEOUTCODE ontimeout()
246 {
247          // beep();
248             return CODE_WAIT;
249 }
250
251 /* Keyboard handler for the menu system */
252 void keys_handler(t_menusystem *ms, t_menuitem *mi,unsigned int scancode)
253 {
254    char nc;
255
256    if ((scancode >> 8) == F1) { // If scancode of F1
257       runhelpsystem(mi->helpid);
258    }
259    // If user hit TAB, and item is an "executable" item
260    // and user has privileges to edit it, edit it in place.
261    if (((scancode & 0xFF) == 0x09) && (mi->action == OPT_RUN)) {
262 //(isallowed(username,"editcmd") || isallowed(username,"root"))) {
263      nc = getnumcols();
264      // User typed TAB and has permissions to edit command line
265      gotoxy(EDITPROMPT,1,ms->menupage);
266      csprint("Command line:",0x07);
267      editstring(mi->data,ACTIONLEN);
268      gotoxy(EDITPROMPT,1,ms->menupage);
269      cprint(' ',0x07,nc-1,ms->menupage);
270    }
271 }
272
273 /* Try to get information for a given disk*/
274 static int get_disk_params(int disk, struct diskinfo *disk_info)
275 {
276   static com32sys_t getparm, parm, getebios, ebios, inreg,outreg;
277   struct device_parameter dp;
278 #ifdef ATA
279   struct ata_identify_device aid;
280 #endif
281
282   disk_info[disk].disk = disk;
283   disk_info[disk].ebios = disk_info[disk].cbios = 0;
284
285   /* Sending int 13h func 41h to query EBIOS information*/
286   memset(&getebios, 0, sizeof (com32sys_t));
287   memset(&ebios, 0, sizeof (com32sys_t));
288
289   /* Get EBIOS support */
290   getebios.eax.w[0] = 0x4100;
291   getebios.ebx.w[0] = 0x55aa;
292   getebios.edx.b[0] = disk;
293   getebios.eflags.b[0] = 0x3;   /* CF set */
294
295   __intcall(0x13, &getebios, &ebios);
296
297   /* Detecting EDD support */
298   if ( !(ebios.eflags.l & EFLAGS_CF) &&
299        ebios.ebx.w[0] == 0xaa55 &&
300        (ebios.ecx.b[0] & 1) ) {
301     disk_info[disk].ebios = 1;
302     switch(ebios.eax.b[1]) {
303             case 32:  strlcpy(disk_info[disk].edd_version,"1.0",3); break;
304             case 33:  strlcpy(disk_info[disk].edd_version,"1.1",3); break;
305             case 48:  strlcpy(disk_info[disk].edd_version,"3.0",3); break;
306             default:  strlcpy(disk_info[disk].edd_version,"0",1); break;
307     }
308   }
309
310   /* Get disk parameters -- really only useful for
311      hard disks, but if we have a partitioned floppy
312      it's actually our best chance... */
313   memset(&getparm, 0, sizeof (com32sys_t));
314   memset(&parm, 0, sizeof (com32sys_t));
315   getparm.eax.b[1] = 0x08;
316   getparm.edx.b[0] = disk;
317
318   __intcall(0x13, &getparm, &parm);
319
320   if ( parm.eflags.l & EFLAGS_CF )
321     return disk_info[disk].ebios ? 0 : -1;
322
323   disk_info[disk].heads = parm.edx.b[1]+1;
324   disk_info[disk].sectors_per_track = parm.ecx.b[0] & 0x3f;
325   if ( disk_info[disk].sectors_per_track == 0 ) {
326     disk_info[disk].sectors_per_track = 1;
327   } else {
328    disk_info[disk].cbios = 1;        /* Valid geometry */
329      }
330
331 /* FIXME: memset to 0 make it fails
332  * memset(__com32.cs_bounce, 0, sizeof(struct device_pairameter)); */
333    memset(&dp, 0, sizeof(struct device_parameter));
334    memset(&inreg, 0, sizeof(com32sys_t));
335
336    /* Requesting Extended Read Drive Parameters via int13h func 48h*/
337    inreg.esi.w[0] = OFFS(__com32.cs_bounce);
338    inreg.ds       = SEG(__com32.cs_bounce);
339    inreg.eax.w[0] = 0x4800;
340    inreg.edx.b[0] = disk;
341
342    __intcall(0x13, &inreg, &outreg);
343
344   /* Saving bounce buffer before anything corrupt it */
345   memcpy(&dp, __com32.cs_bounce, sizeof (struct device_parameter));
346
347    if ( outreg.eflags.l & EFLAGS_CF) {
348            printf("Disk 0x%X doesn't supports EDD 3.0\n",disk);
349            return -1;
350   }
351
352    /* Copying result to the disk_info structure
353     * host_bus_type, interface_type, sectors & cylinders */
354    sprintf(disk_info[disk].host_bus_type,"%c%c%c%c",dp.host_bus_type[0],dp.host_bus_type[1],dp.host_bus_type[2],dp.host_bus_type[3]);
355    sprintf(disk_info[disk].interface_type,"%c%c%c%c%c%c%c%c",dp.interface_type[0],dp.interface_type[1],dp.interface_type[2],dp.interface_type[3],dp.interface_type[4],dp.interface_type[5],dp.interface_type[6],dp.interface_type[7]);
356    disk_info[disk].sectors=dp.sectors;
357    disk_info[disk].cylinders=dp.cylinders;
358
359    /*FIXME: we have to find a way to grab the model & fw
360     * We do put dummy data until we found a solution */
361    sprintf(disk_info[disk].aid.model,"0x%X",disk);
362    sprintf(disk_info[disk].aid.fw_rev,"%s","N/A");
363    sprintf(disk_info[disk].aid.serial_no,"%s","N/A");
364
365   /* Useless stuff before I figure how to send ata packets */
366 #ifdef ATA
367    memset(__com32.cs_bounce, 0, sizeof(struct device_parameter));
368    memset(&aid, 0, sizeof(struct ata_identify_device));
369    memset(&inreg, 0, sizeof inreg);
370    inreg.ebx.w[0] = OFFS(__com32.cs_bounce+1024);
371    inreg.es       = SEG(__com32.cs_bounce+1024);
372    inreg.eax.w[0] = 0x2500;
373    inreg.edx.b[0] = disk;
374
375   __intcall(0x13,&inreg, &outreg);
376
377   memcpy(&aid, __com32.cs_bounce, sizeof (struct ata_identify_device));
378
379   if ( outreg.eflags.l & EFLAGS_CF) {
380            printf("Disk 0x%X: Failed to Identify Device\n",disk);
381            //FIXME
382            return 0;
383   }
384
385 //   ata_id_c_string(aid, disk_info[disk].fwrev, ATA_ID_FW_REV, sizeof(disk_info[disk].fwrev));
386 //   ata_id_c_string(aid, disk_info[disk].model, ATA_ID_PROD,  sizeof(disk_info[disk].model));
387
388   char buff[sizeof(struct ata_identify_device)];
389   memcpy(buff,&aid, sizeof (struct ata_identify_device));
390   for (int j=0;j<sizeof(struct ata_identify_device);j++)
391      printf ("model=|%c|\n",buff[j]);
392     printf ("Disk 0x%X : %s %s %s\n",disk, aid.model, aid.fw_rev,aid.serial_no);
393 #endif
394
395 return 0;
396 }
397
398 /* Detecting if a DMI table exist
399  * if yes, let's parse it */
400 int detect_dmi(s_dmi *dmi) {
401   if ( ! dmi_iterate() ) {
402              printf("No DMI Structure found\n");
403              return -1;
404   }
405
406   parse_dmitable(dmi);
407  return 0;
408 }
409
410 /* Try to detects disk from port 0x80 to 0xff*/
411 void detect_disks(struct diskinfo *disk_info) {
412  for (int drive = 0x80; drive <= 0xff; drive++) {
413     if (get_disk_params(drive,disk_info))
414           continue;
415     struct diskinfo d=disk_info[drive];
416     printf("  DISK 0x%X: %s %s: sectors=%d, sector/track=%d head=%d : EDD=%s\n",drive,d.host_bus_type,d.interface_type, d.sectors, d.sectors_per_track,d.heads,d.edd_version);
417  }
418 }
419
420 /* Dynamic submenu for the pci devices */
421 void compute_pci_device(unsigned char *menu,struct pci_device *pci_device,int pci_bus, int pci_slot, int pci_func) {
422   char buffer[56];
423   char statbuffer[STATLEN];
424
425   *menu = add_menu(" Details ",-1);
426    menu_count++;
427    set_menu_pos(7,17);
428
429    snprintf(buffer,sizeof buffer,"Vendor  : %s",pci_device->dev_info->vendor_name);
430    snprintf(statbuffer,sizeof statbuffer,"Vendor Name: %s",pci_device->dev_info->vendor_name);
431    add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
432
433    snprintf(buffer,sizeof buffer,"Product : %s",pci_device->dev_info->product_name);
434    snprintf(statbuffer,sizeof statbuffer,"Product Name  %s",pci_device->dev_info->product_name);
435    add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
436
437    snprintf(buffer,sizeof buffer,"Class   : %s",pci_device->dev_info->class_name);
438    snprintf(statbuffer,sizeof statbuffer,"Class Name: %s",pci_device->dev_info->class_name);
439    add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
440
441    snprintf(buffer,sizeof buffer,"Location: %02x:%02x.%01x",pci_bus, pci_slot, pci_func);
442    snprintf(statbuffer,sizeof statbuffer,"Location on the PCI Bus: %02x:%02x.%01x",pci_bus, pci_slot, pci_func);
443    add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
444
445    snprintf(buffer,sizeof buffer,"PCI ID  : %04x:%04x[%04x:%04x]",pci_device->vendor, pci_device->product,pci_device->sub_vendor, pci_device->sub_product);
446    snprintf(statbuffer,sizeof statbuffer,"vendor:product[sub_vendor:sub_product] : %04x:%04x[%04x:%04x]",pci_device->vendor, pci_device->product,pci_device->sub_vendor, pci_device->sub_product);
447    add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
448
449    snprintf(buffer,sizeof buffer,"Module  : %s",pci_device->dev_info->linux_kernel_module);
450    snprintf(statbuffer,sizeof statbuffer,"Kernel Module: %s",pci_device->dev_info->linux_kernel_module);
451    add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
452
453 }
454
455 /* Main PCI Menu*/
456 int compute_PCI(unsigned char *menu, struct pci_domain **pci_domain) {
457  int i=0;
458  char menuname[255][MENULEN+1];
459  char infobar[255][STATLEN+1];
460  struct pci_device *pci_device;
461  printf("MENU: Computing PCI menu\n");
462
463  /* For every detected pci device, compute its submenu */
464  for_each_pci_func(pci_device, *pci_domain) {
465    compute_pci_device(&PCI_SUBMENU[i],pci_device,__pci_bus,__pci_slot,__pci_func);
466    snprintf(menuname[i],59,"%s|%s",pci_device->dev_info->vendor_name,pci_device->dev_info->product_name);
467    snprintf(infobar[i], STATLEN,"%02x:%02x.%01x # %s # ID:%04x:%04x[%04x:%04x] # Kmod:%s\n",
468                __pci_bus, __pci_slot, __pci_func,pci_device->dev_info->class_name,
469                pci_device->vendor, pci_device->product,
470                pci_device->sub_vendor, pci_device->sub_product,pci_device->dev_info->linux_kernel_module);
471    i++;
472  }
473
474  *menu = add_menu(" PCI Devices ",-1);
475    menu_count++;
476
477  for (int j=0;j<i;j++) {
478   add_item(menuname[j],infobar[j],OPT_SUBMENU,NULL,PCI_SUBMENU[j]);
479  }
480 return 0;
481 }
482
483 /* Main Kernel Menu*/
484 void compute_KERNEL(unsigned char *menu,struct pci_domain **pci_domain) {
485   char buffer[SUBMENULEN+1];
486   char infobar[STATLEN+1];
487
488   *menu = add_menu(" Kernel Modules ",-1);
489   menu_count++;
490   printf("MENU: Computing Kernel menu\n");
491   set_menu_pos(4,29);
492   struct pci_device *pci_device;
493
494  /* For every detected pci device, grab its kernel module to compute this submenu */
495   for_each_pci_func(pci_device, *pci_domain) {
496         /* No need to add unknown kernel modules*/
497         if (strcmp("unknown",pci_device->dev_info->linux_kernel_module)!=0) {
498          snprintf(buffer,sizeof buffer,"%s (%s)",pci_device->dev_info->linux_kernel_module, pci_device->dev_info->class_name);
499          snprintf(infobar, sizeof infobar,"%04x:%04x %s : %s\n",
500                pci_device->vendor, pci_device->product,
501                 pci_device->dev_info->vendor_name,
502                 pci_device->dev_info->product_name);
503
504          add_item(buffer,infobar,OPT_INACTIVE,NULL,0);
505         }
506   }
507 }
508
509 /* Main Battery Menu*/
510 void compute_battery(unsigned char *menu, s_dmi *dmi) {
511   char buffer[SUBMENULEN+1];
512   char statbuffer[STATLEN+1];
513   *menu = add_menu(" Battery ",-1);
514   menu_count++;
515   printf("MENU: Computing Battery menu\n");
516   set_menu_pos(4,29);
517   snprintf(buffer, sizeof buffer,"Vendor          : %s",dmi->battery.manufacturer);
518   snprintf(statbuffer, sizeof statbuffer,"Vendor: %s",dmi->battery.manufacturer);
519   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
520
521   snprintf(buffer, sizeof buffer,"Manufacture Date: %s",dmi->battery.manufacture_date);
522   snprintf(statbuffer, sizeof statbuffer,"Manufacture Date: %s",dmi->battery.manufacture_date);
523   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
524
525   snprintf(buffer, sizeof buffer,"Serial          : %s",dmi->battery.serial);
526   snprintf(statbuffer, sizeof statbuffer,"Serial: %s",dmi->battery.serial);
527   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
528
529   snprintf(buffer, sizeof buffer,"Name            : %s",dmi->battery.name);
530   snprintf(statbuffer, sizeof statbuffer,"Name: %s",dmi->battery.name);
531   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
532
533   snprintf(buffer, sizeof buffer,"Chemistry       : %s",dmi->battery.chemistry);
534   snprintf(statbuffer, sizeof statbuffer,"Chemistry: %s",dmi->battery.chemistry);
535   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
536
537   snprintf(buffer, sizeof buffer,"Design Capacity : %s",dmi->battery.design_capacity);
538   snprintf(statbuffer, sizeof statbuffer,"Design Capacity: %s",dmi->battery.design_capacity);
539   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
540
541   snprintf(buffer, sizeof buffer,"Design Voltage  : %s",dmi->battery.design_voltage);
542   snprintf(statbuffer, sizeof statbuffer,"Design Voltage : %s",dmi->battery.design_voltage);
543   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
544
545   snprintf(buffer, sizeof buffer,"SBDS            : %s",dmi->battery.sbds);
546   snprintf(statbuffer, sizeof statbuffer,"SBDS: %s",dmi->battery.sbds);
547   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
548
549   snprintf(buffer, sizeof buffer,"SBDS Manuf. Date: %s",dmi->battery.sbds_manufacture_date);
550   snprintf(statbuffer, sizeof statbuffer,"SBDS Manufacture Date: %s",dmi->battery.sbds_manufacture_date);
551   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
552
553   snprintf(buffer, sizeof buffer,"SBDS Chemistry  : %s",dmi->battery.sbds_chemistry);
554   snprintf(statbuffer, sizeof statbuffer,"SBDS Chemistry : %s",dmi->battery.sbds_chemistry);
555   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
556
557   snprintf(buffer, sizeof buffer,"Maximum Error   : %s",dmi->battery.maximum_error);
558   snprintf(statbuffer, sizeof statbuffer,"Maximum Error (%) : %s",dmi->battery.maximum_error);
559   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
560
561   snprintf(buffer, sizeof buffer,"OEM Info        : %s",dmi->battery.oem_info);
562   snprintf(statbuffer, sizeof statbuffer,"OEM Info: %s",dmi->battery.oem_info);
563   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
564 }
565
566 /* Compute the disk submenu */
567 void compute_disk_module(unsigned char *menu, struct diskinfo *d,int disk_number) {
568   char buffer[MENULEN+1];
569   char statbuffer[STATLEN+1];
570
571   /* No need to add no existing devices*/
572   if (strlen(d->aid.model)<=0) return;
573
574   snprintf(buffer,sizeof buffer," Disk <%d> ",nb_sub_disk_menu);
575   *menu = add_menu(buffer,-1);
576   menu_count++;
577
578   snprintf(buffer,sizeof buffer,"Model        : %s",d->aid.model);
579   snprintf(statbuffer,sizeof statbuffer,"Model: %s",d->aid.model);
580   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
581
582   /* Compute device size */
583   char previous_unit[3],unit[3]; //GB
584   int previous_size,size = d->sectors/2; // Converting to bytes
585   strlcpy(unit,"KB",2);
586   strlcpy(previous_unit,unit,2);
587   previous_size=size;
588   if (size>1000) {
589      size=size/1000;
590      strlcpy(unit,"MB",2);
591      if (size>1000) {
592        previous_size=size;
593        size=size/1000;
594        strlcpy(previous_unit,unit,2);
595        strlcpy(unit,"GB",2);
596        if (size>1000) {
597         previous_size=size;
598         size=size/1000;
599         strlcpy(previous_unit,unit,2);
600         strlcpy(unit,"TB",2);
601        }
602      }
603   }
604
605   snprintf(buffer,sizeof buffer,"Size         : %d %s (%d %s)",size,unit,previous_size,previous_unit);
606   snprintf(statbuffer, sizeof statbuffer, "Size: %d %s (%d %s)",size,unit,previous_size,previous_unit);
607   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
608
609   snprintf(buffer,sizeof buffer,"Firmware Rev.: %s",d->aid.fw_rev);
610   snprintf(statbuffer,sizeof statbuffer,"Firmware Revision: %s",d->aid.fw_rev);
611   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
612
613   snprintf(buffer,sizeof buffer,"Serial Number: %s",d->aid.serial_no);
614   snprintf(statbuffer,sizeof statbuffer,"Serial Number: %s",d->aid.serial_no);
615   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
616
617   snprintf(buffer,sizeof buffer,"Interface    : %s",d->interface_type);
618   snprintf(statbuffer,sizeof statbuffer,"Interface: %s",d->interface_type);
619   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
620
621   snprintf(buffer,sizeof buffer,"Host Bus     : %s",d->host_bus_type);
622   snprintf(statbuffer,sizeof statbuffer,"Host Bus Type: %s",d->host_bus_type);
623   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
624
625   snprintf(buffer,sizeof buffer, "Sectors      : %d",d->sectors);
626   snprintf(statbuffer,sizeof statbuffer, "Sectors: %d",d->sectors);
627   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
628
629   snprintf(buffer,sizeof buffer,"Heads        : %d",d->heads);
630   snprintf(statbuffer,sizeof statbuffer,"Heads: %d",d->heads);
631   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
632
633   snprintf(buffer, sizeof buffer,"Cylinders    : %d",d->cylinders);
634   snprintf(statbuffer, sizeof statbuffer,"Cylinders: %d",d->cylinders);
635   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
636
637   snprintf(buffer,sizeof buffer, "Sectors/Track: %d",d->sectors_per_track);
638   snprintf(statbuffer,sizeof statbuffer, "Sectors per Track: %d",d->sectors_per_track);
639   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
640
641   snprintf(buffer,sizeof buffer,"Port         : 0x%X",disk_number);
642   snprintf(statbuffer,sizeof statbuffer,"Port: 0x%X",disk_number);
643   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
644
645   snprintf(buffer,sizeof buffer,"EDD Version  : %s",d->edd_version);
646   snprintf(statbuffer,sizeof statbuffer,"EDD Version: %s",d->edd_version);
647   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
648
649   nb_sub_disk_menu++;
650 }
651
652 /* Compute the memory submenu */
653 void compute_memory_module(unsigned char *menu, s_dmi *dmi, int slot_number) {
654   int i=slot_number;
655   char buffer[MENULEN+1];
656   char statbuffer[STATLEN+1];
657
658   sprintf(buffer," Module <%d> ",i);
659   *menu = add_menu(buffer,-1);
660   menu_count++;
661
662   snprintf(buffer,sizeof buffer,"Form Factor  : %s",dmi->memory[i].form_factor);
663   snprintf(statbuffer,sizeof statbuffer,"Form Factor: %s",dmi->memory[i].form_factor);
664   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
665
666   snprintf(buffer,sizeof buffer,"Type         : %s",dmi->memory[i].type);
667   snprintf(statbuffer,sizeof statbuffer,"Type: %s",dmi->memory[i].type);
668   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
669
670   snprintf(buffer,sizeof buffer,"Type Details : %s",dmi->memory[i].type_detail);
671   snprintf(statbuffer,sizeof statbuffer,"Type Details: %s",dmi->memory[i].type_detail);
672   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
673
674   snprintf(buffer,sizeof buffer,"Speed        : %s",dmi->memory[i].speed);
675   snprintf(statbuffer,sizeof statbuffer,"Speed (Mhz): %s",dmi->memory[i].speed);
676   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
677
678   snprintf(buffer,sizeof buffer,"Size         : %s",dmi->memory[i].size);
679   snprintf(statbuffer,sizeof statbuffer,"Size: %s",dmi->memory[i].size);
680   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
681
682   snprintf(buffer,sizeof buffer,"Device Set   : %s",dmi->memory[i].device_set);
683   snprintf(statbuffer,sizeof statbuffer,"Device Set: %s",dmi->memory[i].device_set);
684   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
685
686   snprintf(buffer,sizeof buffer,"Device Loc.  : %s",dmi->memory[i].device_locator);
687   snprintf(statbuffer,sizeof statbuffer,"Device Location: %s",dmi->memory[i].device_locator);
688   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
689
690   snprintf(buffer,sizeof buffer,"Bank Locator : %s",dmi->memory[i].bank_locator);
691   snprintf(statbuffer,sizeof statbuffer,"Bank Locator: %s",dmi->memory[i].bank_locator);
692   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
693
694   snprintf(buffer,sizeof buffer,"Total Width  : %s",dmi->memory[i].total_width);
695   snprintf(statbuffer,sizeof statbuffer,"Total bit Width: %s",dmi->memory[i].total_width);
696   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
697
698   snprintf(buffer,sizeof buffer,"Data Width   : %s",dmi->memory[i].data_width);
699   snprintf(statbuffer,sizeof statbuffer,"Data bit Width: %s",dmi->memory[i].data_width);
700   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
701
702   snprintf(buffer,sizeof buffer,"Error        : %s",dmi->memory[i].error);
703   snprintf(statbuffer,sizeof statbuffer,"Error: %s",dmi->memory[i].error);
704   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
705
706   snprintf(buffer,sizeof buffer,"Vendor       : %s",dmi->memory[i].manufacturer);
707   snprintf(statbuffer,sizeof statbuffer,"Vendor: %s",dmi->memory[i].manufacturer);
708   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
709
710   snprintf(buffer,sizeof buffer,"Serial       : %s",dmi->memory[i].serial);
711   snprintf(statbuffer,sizeof statbuffer,"Serial: %s",dmi->memory[i].serial);
712   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
713
714   snprintf(buffer,sizeof buffer,"Asset Tag    : %s",dmi->memory[i].asset_tag);
715   snprintf(statbuffer,sizeof statbuffer,"Asset Tag: %s",dmi->memory[i].asset_tag);
716   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
717
718   snprintf(buffer,sizeof buffer,"Part Number  : %s",dmi->memory[i].part_number);
719   snprintf(buffer,sizeof statbuffer,"Part Number: %s",dmi->memory[i].part_number);
720   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
721
722 }
723
724 /* Compute Motherboard main menu */
725 void compute_motherboard(unsigned char *menu,s_dmi *dmi) {
726   char buffer[SUBMENULEN+1];
727   char statbuffer[STATLEN+1];
728   printf("MENU: Computing motherboard menu\n");
729   *menu = add_menu(" Motherboard ",-1);
730   menu_count++;
731   set_menu_pos(4,29);
732
733   snprintf(buffer,sizeof buffer,"Vendor    : %s",dmi->base_board.manufacturer);
734   snprintf(statbuffer,sizeof statbuffer,"Vendor: %s",dmi->base_board.manufacturer);
735   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
736
737   snprintf(buffer,sizeof buffer,"Product   : %s",dmi->base_board.product_name);
738   snprintf(statbuffer,sizeof statbuffer,"Product Name: %s",dmi->base_board.product_name);
739   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
740
741   snprintf(buffer,sizeof buffer,"Version   : %s",dmi->base_board.version);
742   snprintf(statbuffer,sizeof statbuffer,"Version: %s",dmi->base_board.version);
743   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
744
745   snprintf(buffer,sizeof buffer,"Serial    : %s",dmi->base_board.serial);
746   snprintf(statbuffer,sizeof statbuffer,"Serial Number: %s",dmi->base_board.serial);
747   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
748
749   snprintf(buffer,sizeof buffer,"Asset Tag : %s",dmi->base_board.asset_tag);
750   snprintf(statbuffer,sizeof statbuffer,"Asset Tag: %s",dmi->base_board.asset_tag);
751   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
752
753   snprintf(buffer,sizeof buffer,"Location  : %s",dmi->base_board.location);
754   snprintf(statbuffer,sizeof statbuffer,"Location: %s",dmi->base_board.location);
755   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
756
757   snprintf(buffer,sizeof buffer,"Type      : %s",dmi->base_board.type);
758   snprintf(statbuffer,sizeof statbuffer,"Type: %s",dmi->base_board.type);
759   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
760 }
761
762 /* Compute System main menu */
763 void compute_system(unsigned char *menu,s_dmi *dmi) {
764   char buffer[SUBMENULEN+1];
765   char statbuffer[STATLEN+1];
766   printf("MENU: Computing system menu\n");
767   *menu = add_menu(" System ",-1);
768   menu_count++;
769   set_menu_pos(4,29);
770
771   snprintf(buffer,sizeof buffer,"Vendor    : %s",dmi->system.manufacturer);
772   snprintf(statbuffer,sizeof statbuffer,"Vendor: %s",dmi->system.manufacturer);
773   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
774
775   snprintf(buffer,sizeof buffer,"Product   : %s",dmi->system.product_name);
776   snprintf(statbuffer,sizeof statbuffer,"Product Name: %s",dmi->system.product_name);
777   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
778
779   snprintf(buffer,sizeof buffer,"Version   : %s",dmi->system.version);
780   snprintf(statbuffer,sizeof statbuffer,"Version: %s",dmi->system.version);
781   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
782
783   snprintf(buffer,sizeof buffer,"Serial    : %s",dmi->system.serial);
784   snprintf(statbuffer,sizeof statbuffer,"Serial Number: %s",dmi->system.serial);
785   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
786
787   snprintf(buffer,sizeof buffer,"UUID      : %s",dmi->system.uuid);
788   snprintf(statbuffer,sizeof statbuffer,"UUID: %s",dmi->system.uuid);
789   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
790
791   snprintf(buffer,sizeof buffer,"Wakeup    : %s",dmi->system.wakeup_type);
792   snprintf(statbuffer,sizeof statbuffer,"Wakeup Type: %s",dmi->system.wakeup_type);
793   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
794
795   snprintf(buffer,sizeof buffer,"SKU Number: %s",dmi->system.sku_number);
796   snprintf(statbuffer,sizeof statbuffer,"SKU Number: %s",dmi->system.sku_number);
797   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
798
799   snprintf(buffer,sizeof buffer,"Family    : %s",dmi->system.family);
800   snprintf(statbuffer,sizeof statbuffer,"Family: %s",dmi->system.family);
801   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
802 }
803
804 /* Compute Chassis menu */
805 void compute_chassis(unsigned char *menu,s_dmi *dmi) {
806   char buffer[SUBMENULEN+1];
807   char statbuffer[STATLEN+1];
808   printf("MENU: Computing chassis menu\n");
809   *menu = add_menu(" Chassis ",-1);
810   menu_count++;
811   set_menu_pos(4,29);
812   snprintf(buffer,sizeof buffer,"Vendor    : %s",dmi->chassis.manufacturer);
813   snprintf(statbuffer,sizeof statbuffer,"Vendor: %s",dmi->chassis.manufacturer);
814   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
815
816   snprintf(buffer,sizeof buffer,"Type      : %s",dmi->chassis.type);
817   snprintf(statbuffer,sizeof statbuffer,"Type: %s",dmi->chassis.type);
818   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
819
820   snprintf(buffer,sizeof buffer,"Version   : %s",dmi->chassis.version);
821   snprintf(statbuffer,sizeof statbuffer,"Version: %s",dmi->chassis.version);
822   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
823
824   snprintf(buffer,sizeof buffer,"Serial    : %s",dmi->chassis.serial);
825   snprintf(statbuffer,sizeof statbuffer,"Serial Number: %s",dmi->chassis.serial);
826   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
827
828   snprintf(buffer,sizeof buffer,"Asset Tag : %s",dmi->chassis.asset_tag);
829   snprintf(statbuffer,sizeof statbuffer,"Asset Tag: %s",dmi->chassis.asset_tag);
830   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
831
832   snprintf(buffer,sizeof buffer,"Lock      : %s",dmi->chassis.lock);
833   snprintf(statbuffer,sizeof statbuffer,"Lock: %s",dmi->chassis.lock);
834   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
835 }
836
837 /* Compute BIOS menu */
838 void compute_bios(unsigned char *menu,s_dmi *dmi) {
839   char buffer[SUBMENULEN+1];
840   char statbuffer[STATLEN+1];
841   *menu = add_menu(" BIOS ",-1);
842   menu_count++;
843   printf("MENU: Computing BIOS menu\n");
844   set_menu_pos(4,29);
845
846   snprintf(buffer,sizeof buffer,"Vendor    : %s",dmi->bios.vendor);
847   snprintf(statbuffer,sizeof statbuffer,"Vendor: %s",dmi->bios.vendor);
848   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
849
850   snprintf(buffer,sizeof buffer,"Version   : %s",dmi->bios.version);
851   snprintf(statbuffer,sizeof statbuffer,"Version: %s",dmi->bios.version);
852   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
853
854   snprintf(buffer,sizeof buffer,"Release   : %s",dmi->bios.release_date);
855   snprintf(statbuffer,sizeof statbuffer,"Release Date: %s",dmi->bios.release_date);
856   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
857
858   snprintf(buffer,sizeof buffer,"Bios Rev. : %s",dmi->bios.bios_revision);
859   snprintf(statbuffer,sizeof statbuffer,"Bios Revision: %s",dmi->bios.bios_revision);
860   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
861
862   snprintf(buffer,sizeof buffer,"Fw.  Rev. : %s",dmi->bios.firmware_revision);
863   snprintf(statbuffer,sizeof statbuffer,"Firmware Revision : %s",dmi->bios.firmware_revision);
864   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
865 }
866
867 /* Compute Processor menu */
868 void compute_processor(unsigned char *menu,s_cpu *cpu, s_dmi *dmi) {
869   char buffer[MENULEN+1];
870   char buffer1[MENULEN+1];
871   char statbuffer[STATLEN+1];
872
873   printf("MENU: Computing Processor menu\n");
874   *menu = add_menu(" Main Processor ",-1);
875   menu_count++;
876
877   snprintf(buffer,sizeof buffer,"Vendor    : %s",cpu->vendor);
878   snprintf(statbuffer,sizeof statbuffer,"Vendor: %s",cpu->vendor);
879   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
880
881   snprintf(buffer,sizeof buffer,"Model     : %s",cpu->model);
882   snprintf(statbuffer,sizeof statbuffer,"Model: %s",cpu->model);
883   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
884
885   snprintf(buffer,sizeof buffer,"Vendor ID : %d",cpu->vendor_id);
886   snprintf(statbuffer,sizeof statbuffer,"Vendor ID: %d",cpu->vendor_id);
887   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
888
889   snprintf(buffer,sizeof buffer,"Family ID : %d",cpu->family);
890   snprintf(statbuffer,sizeof statbuffer,"Family ID: %d",cpu->family);
891   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
892
893   snprintf(buffer,sizeof buffer,"Model  ID : %d",cpu->model_id);
894   snprintf(statbuffer,sizeof statbuffer,"Model  ID: %d",cpu->model_id);
895   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
896
897   snprintf(buffer,sizeof buffer,"Stepping  : %d",cpu->stepping);
898   snprintf(statbuffer,sizeof statbuffer,"Stepping: %d",cpu->stepping);
899   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
900
901   if (is_dmi_valid) {
902    snprintf(buffer,sizeof buffer,"FSB       : %d",dmi->processor.external_clock);
903    snprintf(statbuffer,sizeof statbuffer,"Front Side Bus (MHz): %d",dmi->processor.external_clock);
904    add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
905
906    snprintf(buffer,sizeof buffer,"Cur. Speed: %d",dmi->processor.current_speed);
907    snprintf(statbuffer,sizeof statbuffer,"Current Speed (MHz): %d",dmi->processor.current_speed);
908    add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
909
910    snprintf(buffer,sizeof buffer,"Max Speed : %d",dmi->processor.max_speed);
911    snprintf(statbuffer,sizeof statbuffer,"Max Speed (MHz): %d",dmi->processor.max_speed);
912    add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
913
914    snprintf(buffer,sizeof buffer,"Upgrade   : %s",dmi->processor.upgrade);
915    snprintf(statbuffer,sizeof statbuffer,"Upgrade: %s",dmi->processor.upgrade);
916    add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
917   }
918
919   if (cpu->flags.smp) {
920           snprintf(buffer,sizeof buffer,"SMP       : Yes");
921           snprintf(statbuffer,sizeof statbuffer,"SMP: Yes");
922   }
923   else {
924           snprintf(buffer,sizeof buffer,"SMP       : No");
925           snprintf(statbuffer,sizeof statbuffer,"SMP: No");
926   }
927   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
928
929   if (cpu->flags.lm) {
930           snprintf(buffer,sizeof buffer,"x86_64    : Yes");
931           snprintf(statbuffer,sizeof statbuffer,"x86_64 compatible processor: Yes");
932   }
933   else {
934           snprintf(buffer,sizeof buffer,"X86_64    : No");
935           snprintf(statbuffer,sizeof statbuffer,"X86_64 compatible processor: No");
936   }
937   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
938
939   buffer1[0]='\0';
940   if (cpu->flags.fpu) strcat(buffer1,"fpu ");
941   if (cpu->flags.vme) strcat(buffer1,"vme ");
942   if (cpu->flags.de)  strcat(buffer1,"de ");
943   if (cpu->flags.pse) strcat(buffer1,"pse ");
944   if (cpu->flags.tsc) strcat(buffer1,"tsc ");
945   if (cpu->flags.msr) strcat(buffer1,"msr ");
946   if (cpu->flags.pae) strcat(buffer1,"pae ");
947   snprintf(buffer,sizeof buffer,"Flags     : %s",buffer1);
948   snprintf(statbuffer,sizeof statbuffer,"Flags: %s",buffer1);
949   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
950
951   buffer1[0]='\0';
952   if (cpu->flags.mce) strcat(buffer1,"mce ");
953   if (cpu->flags.cx8) strcat(buffer1,"cx8 ");
954   if (cpu->flags.apic) strcat(buffer1,"apic ");
955   if (cpu->flags.sep) strcat(buffer1,"sep ");
956   if (cpu->flags.mtrr) strcat(buffer1,"mtrr ");
957   if (cpu->flags.pge) strcat(buffer1,"pge ");
958   if (cpu->flags.mca) strcat(buffer1,"mca ");
959   snprintf(buffer,sizeof buffer,"Flags     : %s",buffer1);
960   snprintf(statbuffer,sizeof statbuffer,"Flags: %s",buffer1);
961   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
962
963   buffer1[0]='\0';
964   if (cpu->flags.cmov) strcat(buffer1,"cmov ");
965   if (cpu->flags.pat)  strcat(buffer1,"pat ");
966   if (cpu->flags.pse_36) strcat(buffer1,"pse_36 ");
967   if (cpu->flags.psn)  strcat(buffer1,"psn ");
968   if (cpu->flags.clflsh) strcat(buffer1,"clflsh ");
969   snprintf(buffer,sizeof buffer,"Flags     : %s",buffer1);
970   snprintf(statbuffer,sizeof statbuffer,"Flags: %s",buffer1);
971   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
972
973   buffer1[0]='\0';
974   if (cpu->flags.dts)  strcat(buffer1,"dts ");
975   if (cpu->flags.acpi) strcat(buffer1,"acpi ");
976   if (cpu->flags.mmx)  strcat(buffer1,"mmx ");
977   if (cpu->flags.sse)  strcat(buffer1,"sse ");
978   snprintf(buffer,sizeof buffer,"Flags     : %s",buffer1);
979   snprintf(statbuffer,sizeof statbuffer,"Flags: %s",buffer1);
980   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
981
982   buffer1[0]='\0';
983   if (cpu->flags.sse2) strcat(buffer1,"sse2 ");
984   if (cpu->flags.ss)   strcat(buffer1,"ss ");
985   if (cpu->flags.htt)  strcat(buffer1,"ht ");
986   if (cpu->flags.acc)  strcat(buffer1,"acc ");
987   if (cpu->flags.syscall) strcat(buffer1,"syscall ");
988   if (cpu->flags.mp)   strcat(buffer1,"mp ");
989   snprintf(buffer,sizeof buffer,"Flags     : %s",buffer1);
990   snprintf(statbuffer,sizeof statbuffer,"Flags: %s",buffer1);
991   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
992
993   buffer1[0]='\0';
994   if (cpu->flags.nx)    strcat(buffer1,"nx ");
995   if (cpu->flags.mmxext) strcat(buffer1,"mmxext ");
996   if (cpu->flags.lm)     strcat(buffer1,"lm ");
997   if (cpu->flags.nowext) strcat(buffer1,"3dnowext ");
998   if (cpu->flags.now)    strcat(buffer1,"3dnow! ");
999   snprintf(buffer,sizeof buffer,"Flags     : %s",buffer1);
1000   snprintf(statbuffer,sizeof statbuffer,"Flags: %s",buffer1);
1001   add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
1002
1003 }
1004
1005 /* Setup our environement */
1006 void setup_env() {
1007   char version[255];
1008
1009   /* Opening the syslinux console */
1010   openconsole(&dev_stdcon_r, &dev_stdcon_w);
1011
1012   sprintf(version,"%s %s by %s",PRODUCT_NAME,VERSION,AUTHOR);
1013   printf("%s\n",version);
1014
1015   /* Creating the menu */
1016   init_menusystem(version);
1017   set_window_size(1,1,23,78); // Leave some space around
1018
1019  // Register the menusystem handler
1020  // reg_handler(HDLR_SCREEN,&msys_handler);
1021   reg_handler(HDLR_KEYS,&keys_handler);
1022
1023   // Register the ontimeout handler, with a time out of 10 seconds
1024   reg_ontimeout(ontimeout,1000,0);
1025 }
1026
1027 /* Detect the hardware stuff */
1028 void detect_hardware(s_dmi *dmi, s_cpu *cpu, struct pci_domain **pci_domain, struct diskinfo *disk_info) {
1029   printf("CPU: Detecting\n");
1030   detect_cpu(cpu);
1031
1032   printf("DISKS: Detecting\n");
1033   detect_disks(disk_info);
1034
1035   printf("DMI: Detecting Table\n");
1036   if (detect_dmi(dmi) == 0)
1037                 is_dmi_valid=true;
1038
1039 #ifdef WITH_PCI
1040   printf("PCI: Detecting Devices\n");
1041   /* Scanning to detect pci buses and devices */
1042   *pci_domain = pci_scan();
1043
1044   struct pci_device *pci_device;
1045   for_each_pci_func(pci_device, *pci_domain) {
1046           nb_pci_devices++;
1047   }
1048
1049   printf("PCI: %d Devices Found\n",nb_pci_devices);
1050
1051   printf("PCI: Resolving names\n");
1052   /* Assigning product & vendor name for each device*/
1053   get_name_from_pci_ids(*pci_domain);
1054
1055   printf("PCI: Resolving class names\n");
1056   /* Assigning class name for each device*/
1057   get_class_name_from_pci_ids(*pci_domain);
1058
1059
1060   printf("PCI: Resolving module names\n");
1061   /* Detecting which kernel module should match each device */
1062   get_module_name_from_pci_ids(*pci_domain);
1063 #endif
1064 }
1065
1066 /* Compute the Memory Menu*/
1067 void compute_memory(unsigned char *menu, s_dmi *dmi) {
1068  char buffer[MENULEN+1];
1069  printf("MENU: Computing Memory menu\n");
1070  for (int i=0;i<dmi->memory_count;i++) {
1071    compute_memory_module(&MEMORY_SUBMENU[i],dmi,i);
1072  }
1073
1074  *menu = add_menu(" Modules ",-1);
1075   menu_count++;
1076
1077  for (int i=0;i<dmi->memory_count;i++) {
1078   sprintf(buffer," Module <%d> ",i);
1079   add_item(buffer,"Memory Module",OPT_SUBMENU,NULL,MEMORY_SUBMENU[i]);
1080  }
1081  add_item("Run Test","Run Test",OPT_RUN,"memtest",0);
1082 }
1083
1084 /* Compute the Disk Menu*/
1085 void compute_disks(unsigned char *menu, struct diskinfo *disk_info) {
1086   char buffer[MENULEN+1];
1087   nb_sub_disk_menu=0;
1088   printf("MENU: Computing Disks menu\n");
1089   for (int i=0;i<0xff;i++) {
1090      compute_disk_module(&DISK_SUBMENU[nb_sub_disk_menu],&disk_info[i],i);
1091   }
1092
1093   *menu = add_menu(" Disks ",-1);
1094   menu_count++;
1095
1096   for (int i=0;i<nb_sub_disk_menu;i++) {
1097     sprintf(buffer," Disk <%d> ",i);
1098     add_item(buffer,"Disk",OPT_SUBMENU,NULL,DISK_SUBMENU[i]);
1099   }
1100 }
1101
1102 /* Compute Main' Submenus*/
1103 void compute_submenus(s_dmi *dmi, s_cpu *cpu, struct pci_domain **pci_domain, struct diskinfo *disk_info) {
1104  /* Compute this menus if a DMI table exist */
1105   if (is_dmi_valid) {
1106     compute_motherboard(&MOBO_MENU,dmi);
1107     compute_chassis(&CHASSIS_MENU,dmi);
1108     compute_system(&SYSTEM_MENU,dmi);
1109     compute_memory(&MEMORY_MENU,dmi);
1110     compute_bios(&BIOS_MENU,dmi);
1111     compute_battery(&BATTERY_MENU,dmi);
1112   }
1113
1114   compute_processor(&CPU_MENU,cpu,dmi);
1115   compute_disks(&DISK_MENU,disk_info);
1116 #ifdef WITH_PCI
1117   compute_PCI(&PCI_MENU,pci_domain);
1118   compute_KERNEL(&KERNEL_MENU,pci_domain);
1119 #endif
1120 }
1121
1122 /* Compute Main Menu*/
1123 void compute_main_menu() {
1124   MAIN_MENU = add_menu(" Main Menu ",-1);
1125   menu_count++;
1126   set_item_options(-1,24);
1127
1128 #ifdef WITH_PCI
1129   add_item("PCI <D>evices","PCI Devices",OPT_SUBMENU,NULL,PCI_MENU);
1130 #endif
1131   if (nb_sub_disk_menu>0)
1132     add_item("<D>isks","Disks",OPT_SUBMENU,NULL,DISK_MENU);
1133   add_item("<M>emory Modules","Memory Modules",OPT_SUBMENU,NULL,MEMORY_MENU);
1134   add_item("<P>rocessor","Main Processor",OPT_SUBMENU,NULL,CPU_MENU);
1135
1136 if (is_dmi_valid) {
1137   add_item("<M>otherboard","Motherboard",OPT_SUBMENU,NULL,MOBO_MENU);
1138   add_item("<B>ios","Bios",OPT_SUBMENU,NULL,BIOS_MENU);
1139   add_item("<C>hassis","Chassis",OPT_SUBMENU,NULL,CHASSIS_MENU);
1140   add_item("<S>ystem","System",OPT_SUBMENU,NULL,SYSTEM_MENU);
1141   add_item("Ba<t>tery","Battery",OPT_SUBMENU,NULL,BATTERY_MENU);
1142 }
1143 #ifdef WITH_PCI
1144   add_item("","",OPT_SEP,"",0);
1145   add_item("<K>ernel Modules","Kernel Modules",OPT_SUBMENU,NULL,KERNEL_MENU);
1146 #endif
1147 }
1148
1149 int main(void)
1150 {
1151   s_dmi dmi; /* DMI table */
1152   s_cpu cpu; /* CPU information */
1153   struct pci_domain *pci_domain=NULL; /* PCI Devices */
1154   struct diskinfo disk_info[256];     /* Disk Information*/
1155
1156   /* Setup the environement */
1157   setup_env();
1158
1159   /* Detect every kind of hardware */
1160   detect_hardware(&dmi,&cpu,&pci_domain,disk_info);
1161
1162   /* Compute all sub menus */
1163   compute_submenus(&dmi,&cpu,&pci_domain,disk_info);
1164
1165   /* Compute main menu */
1166   compute_main_menu();
1167
1168 #ifdef WITH_MENU_DISPLAY
1169   t_menuitem * curr;
1170   char cmd[160];
1171
1172   printf("Starting Menu (%d menus)\n",menu_count);
1173   curr=showmenus(MAIN_MENU);
1174   /* When we exit the menu, do we have something to do */
1175   if (curr) {
1176         /* When want to execute something */
1177         if (curr->action == OPT_RUN)
1178         {
1179             strcpy(cmd,curr->data);
1180
1181             /* Use specific syslinux call if needed */
1182             if (issyslinux())
1183                runsyslinuxcmd(cmd);
1184             else csprint(cmd,0x07);
1185             return 1; // Should not happen when run from SYSLINUX
1186         }
1187   }
1188 #endif
1189
1190   return 0;
1191 }