1 /* ----------------------------------------------------------------------- *
3 * Copyright 2009 Erwan Velu - All Rights Reserved
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
14 * The above copyright notice and this permission notice shall
15 * be included in all copies or substantial portions of the Software.
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.
26 * -----------------------------------------------------------------------
32 * An Hardware Detection Tool
42 #include "passwords.h"
55 #define WITH_MENU_DISPLAY 1
57 #define SECTOR 512 /* bytes/sector */
62 ATA_ID_FW_REV_LEN = 8,
66 unsigned char MAIN_MENU, CPU_MENU, MOBO_MENU, CHASSIS_MENU, BIOS_MENU, SYSTEM_MENU, PCI_MENU, KERNEL_MENU;
67 unsigned char MEMORY_MENU, MEMORY_SUBMENU[32], DISK_MENU, DISK_SUBMENU[32], PCI_SUBMENU[255],BATTERY_MENU;
68 int nb_sub_disk_menu=0;
69 bool is_dmi_valid=false;
71 #define ATTR_PACKED __attribute__((packed))
73 struct ata_identify_device {
74 unsigned short words000_009[10];
75 unsigned char serial_no[20];
76 unsigned short words020_022[3];
77 unsigned char fw_rev[8];
78 unsigned char model[40];
79 unsigned short words047_079[33];
80 unsigned short major_rev_num;
81 unsigned short minor_rev_num;
82 unsigned short command_set_1;
83 unsigned short command_set_2;
84 unsigned short command_set_extension;
85 unsigned short cfs_enable_1;
86 unsigned short word086;
87 unsigned short csf_default;
88 unsigned short words088_255[168];
93 int ebios; /* EBIOS supported on this disk */
94 int cbios; /* CHS geometry is valid */
96 int sectors_per_track;
100 struct ata_identify_device aid; /* IDENTIFY xxx DEVICE data */
101 char host_bus_type[5];
102 char interface_type[9];
107 * Get a disk block and return a malloc'd buffer.
108 * Uses the disk number and information from disk_info.
124 struct device_parameter {
129 uint32_t sectors_per_track;
131 uint16_t bytes_per_sector;
132 uint32_t dpte_pointer;
133 uint16_t device_path_information;
134 uint8_t device_path_lenght;
135 uint8_t device_path_reserved;
136 uint16_t device_path_reserved_2;
137 uint8_t host_bus_type[4];
138 uint8_t interface_type[8];
139 uint64_t interace_path;
140 uint64_t device_path[2];
146 * ata_id_string - Convert IDENTIFY DEVICE page into string
147 * @id: IDENTIFY DEVICE results we will examine
148 * @s: string into which data is output
149 * @ofs: offset into identify device page
150 * @len: length of string to return. must be an even number.
152 * The strings in the IDENTIFY DEVICE page are broken up into
153 * 16-bit chunks. Run through the string, and output each
154 * 8-bit chunk linearly, regardless of platform.
160 void ata_id_string(const uint16_t *id, unsigned char *s,
161 unsigned int ofs, unsigned int len)
180 * ata_id_c_string - Convert IDENTIFY DEVICE page into C string
181 * @id: IDENTIFY DEVICE results we will examine
182 * @s: string into which data is output
183 * @ofs: offset into identify device page
184 * @len: length of string to return. must be an odd number.
186 * This function is identical to ata_id_string except that it
187 * trims trailing spaces and terminates the resulting string with
188 * null. @len must be actual maximum length (even number) + 1.
193 void ata_id_c_string(const uint16_t *id, unsigned char *s,
194 unsigned int ofs, unsigned int len)
198 //WARN_ON(!(len & 1));
200 ata_id_string(id, s, ofs, len - 1);
202 p = s + strnlen(s, len - 1);
203 while (p > s && p[-1] == ' ')
209 static void printregs(const com32sys_t *r)
211 printf("eflags = %08x ds = %04x es = %04x fs = %04x gs = %04x\n"
212 "eax = %08x ebx = %08x ecx = %08x edx = %08x\n"
213 "ebp = %08x esi = %08x edi = %08x esp = %08x\n",
214 r->eflags.l, r->ds, r->es, r->fs, r->gs,
215 r->eax.l, r->ebx.l, r->ecx.l, r->edx.l,
216 r->ebp.l, r->esi.l, r->edi.l, r->_unused_esp.l);
221 * Call int 13h, but with retry on failure. Especially floppies need this.
223 static int int13_retry(const com32sys_t *inreg, com32sys_t *outreg)
225 int retry = 6; /* Number of retries */
228 if ( !outreg ) outreg = &tmpregs;
231 __intcall(0x13, inreg, outreg);
232 if ( !(outreg->eflags.l & EFLAGS_CF) )
233 return 0; /* CF=0, OK */
236 return -1; /* Error */
239 TIMEOUTCODE ontimeout()
245 void keys_handler(t_menusystem *ms, t_menuitem *mi,unsigned int scancode)
249 if ((scancode >> 8) == F1) { // If scancode of F1
250 runhelpsystem(mi->helpid);
252 // If user hit TAB, and item is an "executable" item
253 // and user has privileges to edit it, edit it in place.
254 if (((scancode & 0xFF) == 0x09) && (mi->action == OPT_RUN)) {
255 //(isallowed(username,"editcmd") || isallowed(username,"root"))) {
257 // User typed TAB and has permissions to edit command line
258 gotoxy(EDITPROMPT,1,ms->menupage);
259 csprint("Command line:",0x07);
260 editstring(mi->data,ACTIONLEN);
261 gotoxy(EDITPROMPT,1,ms->menupage);
262 cprint(' ',0x07,nc-1,ms->menupage);
267 static int get_disk_params(int disk, struct diskinfo *disk_info)
269 static com32sys_t getparm, parm, getebios, ebios, inreg,outreg;
271 struct device_parameter dp;
272 // struct ata_identify_device aid;
274 disk_info[disk].disk = disk;
275 disk_info[disk].ebios = disk_info[disk].cbios = 0;
277 memset(&getebios, 0, sizeof (com32sys_t));
278 memset(&ebios, 0, sizeof (com32sys_t));
279 /* Get EBIOS support */
280 getebios.eax.w[0] = 0x4100;
281 getebios.ebx.w[0] = 0x55aa;
282 getebios.edx.b[0] = disk;
283 getebios.eflags.b[0] = 0x3; /* CF set */
285 __intcall(0x13, &getebios, &ebios);
287 if ( !(ebios.eflags.l & EFLAGS_CF) &&
288 ebios.ebx.w[0] == 0xaa55 &&
289 (ebios.ecx.b[0] & 1) ) {
290 disk_info[disk].ebios = 1;
291 switch(ebios.eax.b[1]) {
292 case 32: strcpy(disk_info[disk].edd_version,"1.0"); break;
293 case 33: strcpy(disk_info[disk].edd_version,"1.1"); break;
294 case 48: strcpy(disk_info[disk].edd_version,"3.0"); break;
295 default: strcpy(disk_info[disk].edd_version,"0"); break;
299 /* Get disk parameters -- really only useful for
300 hard disks, but if we have a partitioned floppy
301 it's actually our best chance... */
302 memset(&getparm, 0, sizeof (com32sys_t));
303 memset(&parm, 0, sizeof (com32sys_t));
304 getparm.eax.b[1] = 0x08;
305 getparm.edx.b[0] = disk;
307 __intcall(0x13, &getparm, &parm);
309 if ( parm.eflags.l & EFLAGS_CF )
310 return disk_info[disk].ebios ? 0 : -1;
312 disk_info[disk].heads = parm.edx.b[1]+1;
313 disk_info[disk].sectors_per_track = parm.ecx.b[0] & 0x3f;
314 if ( disk_info[disk].sectors_per_track == 0 ) {
315 disk_info[disk].sectors_per_track = 1;
317 disk_info[disk].cbios = 1; /* Valid geometry */
320 memset(&dp, 0, sizeof(struct device_parameter));
321 //FIXME: memset to 0 make it fails
322 // memset(__com32.cs_bounce, 0, sizeof(struct device_parameter));
323 memset(&inreg, 0, sizeof(com32sys_t));
325 inreg.esi.w[0] = OFFS(__com32.cs_bounce);
326 inreg.ds = SEG(__com32.cs_bounce);
327 inreg.eax.w[0] = 0x4800;
328 inreg.edx.b[0] = disk;
330 __intcall(0x13, &inreg, &outreg);
332 memcpy(&dp, __com32.cs_bounce, sizeof (struct device_parameter));
334 if ( outreg.eflags.l & EFLAGS_CF) {
335 printf("Disk 0x%X doesn't supports EDD 3.0\n",disk);
339 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]);
340 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]);
341 disk_info[disk].sectors=dp.sectors;
342 disk_info[disk].cylinders=dp.cylinders;
343 //FIXME: we have to find a way to grab the model & fw
344 sprintf(disk_info[disk].aid.model,"0x%X",disk);
345 sprintf(disk_info[disk].aid.fw_rev,"%s","N/A");
346 sprintf(disk_info[disk].aid.serial_no,"%s","N/A");
349 memset(__com32.cs_bounce, 0, sizeof(struct device_parameter));
350 memset(&aid, 0, sizeof(struct ata_identify_device));
351 memset(&inreg, 0, sizeof inreg);
352 inreg.ebx.w[0] = OFFS(__com32.cs_bounce+1024);
353 inreg.es = SEG(__com32.cs_bounce+1024);
354 inreg.eax.w[0] = 0x2500;
355 inreg.edx.b[0] = disk;
357 __intcall(0x13,&inreg, &outreg);
359 memcpy(&aid, __com32.cs_bounce, sizeof (struct ata_identify_device));
361 if ( outreg.eflags.l & EFLAGS_CF) {
362 printf("Disk 0x%X: Failed to Identify Device\n",disk);
367 // ata_id_c_string(aid, disk_info[disk].fwrev, ATA_ID_FW_REV, sizeof(disk_info[disk].fwrev));
368 // ata_id_c_string(aid, disk_info[disk].model, ATA_ID_PROD, sizeof(disk_info[disk].model));
370 char buff[sizeof(struct ata_identify_device)];
371 memcpy(buff,&aid, sizeof (struct ata_identify_device));
372 for (int j=0;j<sizeof(struct ata_identify_device);j++)
373 printf ("model=|%c|\n",buff[j]);
374 printf ("Disk 0x%X : %s %s %s\n",disk, aid.model, aid.fw_rev,aid.serial_no);
379 int detect_dmi(s_dmi *dmi) {
380 if ( ! dmi_iterate() ) {
381 printf("No DMI Structure found\n");
389 void detect_disks(struct diskinfo *disk_info) {
390 for (int drive = 0x80; drive <= 0xff; drive++) {
391 if (get_disk_params(drive,disk_info))
393 struct diskinfo d=disk_info[drive];
394 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);
399 void compute_pci_device(unsigned char *menu,struct pci_device *pci_device,int pci_bus, int pci_slot, int pci_func) {
400 char buffer[MENULEN];
401 char infobar[STATLEN];
403 *menu = add_menu(" PCI Devices ",-1);
405 add_item(buffer,"Class Name",OPT_INACTIVE,NULL,0);
406 snprintf(buffer,59,"Class :%s",pci_device->dev_info->class_name);
407 add_item(buffer,"Class Name",OPT_INACTIVE,NULL,0);
408 snprintf(buffer,59,"Location: %02x:%02x.%01x",pci_bus, pci_slot, pci_func);
409 add_item(buffer,"Location on the PCI Bus",OPT_INACTIVE,NULL,0);
410 snprintf(buffer,59,"PCI ID : %04x:%04x[%04x:%04x]",pci_device->vendor, pci_device->product,pci_device->sub_vendor, pci_device->sub_product);
411 add_item(buffer,"PCI ID: vendor:product[sub_vendor:sub_product]",OPT_INACTIVE,NULL,0);
412 snprintf(buffer,59,"Module : %s",pci_device->dev_info->linux_kernel_module);
413 add_item(buffer,"Related kernel module",OPT_INACTIVE,NULL,0);
417 void compute_PCI(unsigned char *menu, struct pci_domain **pci_domain) {
418 char buffer[MENULEN];
419 char menuname[255][MENULEN];
420 char infobar[255][STATLEN];
422 struct pci_device *pci_device;
424 for_each_pci_func(pci_device, *pci_domain) {
425 compute_pci_device(&PCI_SUBMENU[i],pci_device,__pci_bus,__pci_slot,__pci_func);
426 snprintf(menuname[i],59,"%s|%s",pci_device->dev_info->vendor_name,pci_device->dev_info->product_name);
427 snprintf(infobar[i], STATLEN,"%02x:%02x.%01x # %s # ID:%04x:%04x[%04x:%04x] # Kmod:%s\n",
428 __pci_bus, __pci_slot, __pci_func,pci_device->dev_info->class_name,
429 pci_device->vendor, pci_device->product,
430 pci_device->sub_vendor, pci_device->sub_product,pci_device->dev_info->linux_kernel_module);
434 *menu = add_menu(" PCI Devices ",-1);
436 for (int j=0;j<i;j++) {
437 // sprintf(buffer," PCI <%d> ",j);
438 add_item(menuname[j],infobar[j],OPT_SUBMENU,NULL,PCI_SUBMENU[j]);
442 void compute_KERNEL(unsigned char *menu,struct pci_domain **pci_domain) {
443 char buffer[MENULEN];
444 char infobar[MENULEN];
446 *menu = add_menu(" Kernel Modules ",-1);
447 struct pci_device *pci_device;
448 for_each_pci_func(pci_device, *pci_domain) {
449 if (strcmp("unknown",pci_device->dev_info->linux_kernel_module)!=0) {
450 snprintf(buffer,MENULEN,"%s",pci_device->dev_info->linux_kernel_module);
451 snprintf(infobar, MENULEN,"%04x:%04x %s : %s\n",
452 pci_device->vendor, pci_device->product,
453 pci_device->dev_info->vendor_name,
454 pci_device->dev_info->product_name);
456 add_item(buffer,infobar,OPT_INACTIVE,NULL,0);
461 void compute_battery(unsigned char *menu, s_dmi *dmi) {
462 char buffer[MENULEN];
463 *menu = add_menu(" Battery ",-1);
465 snprintf(buffer,MENULEN,"Vendor : %s",dmi->battery.manufacturer);
466 add_item(buffer,"Vendor",OPT_INACTIVE,NULL,0);
467 snprintf(buffer,MENULEN,"Manufacture Date: %s",dmi->battery.manufacture_date);
468 add_item(buffer,"Manufacture Date",OPT_INACTIVE,NULL,0);
469 snprintf(buffer,MENULEN,"Serial : %s",dmi->battery.serial);
470 add_item(buffer,"Serial",OPT_INACTIVE,NULL,0);
471 snprintf(buffer,MENULEN,"Name : %s",dmi->battery.name);
472 add_item(buffer,"Name",OPT_INACTIVE,NULL,0);
473 snprintf(buffer,MENULEN,"Chemistry : %s",dmi->battery.chemistry);
474 add_item(buffer,"Chemistry",OPT_INACTIVE,NULL,0);
475 snprintf(buffer,MENULEN,"Design Capacity : %s",dmi->battery.design_capacity);
476 add_item(buffer,"Design Capacity",OPT_INACTIVE,NULL,0);
477 snprintf(buffer,MENULEN,"Design Voltage : %s",dmi->battery.design_voltage);
478 add_item(buffer,"Design Voltage",OPT_INACTIVE,NULL,0);
479 snprintf(buffer,MENULEN,"SBDS : %s",dmi->battery.sbds);
480 add_item(buffer,"SBDS",OPT_INACTIVE,NULL,0);
481 snprintf(buffer,MENULEN,"SBDS Manuf. Date: %s",dmi->battery.sbds_manufacture_date);
482 add_item(buffer,"SBDS Manufacture Date",OPT_INACTIVE,NULL,0);
483 snprintf(buffer,MENULEN,"SBDS Chemistry : %s",dmi->battery.sbds_chemistry);
484 add_item(buffer,"SBDS Chemistry",OPT_INACTIVE,NULL,0);
485 snprintf(buffer,MENULEN,"Maximum Error : %s",dmi->battery.maximum_error);
486 add_item(buffer,"Maximum Error (%)",OPT_INACTIVE,NULL,0);
487 snprintf(buffer,MENULEN,"OEM Info : %s",dmi->battery.oem_info);
488 add_item(buffer,"OEM Info",OPT_INACTIVE,NULL,0);
492 void compute_disk_module(unsigned char *menu, struct diskinfo *disk_info, int disk_number) {
493 char buffer[MENULEN];
494 struct diskinfo d = disk_info[disk_number];
495 if (strlen(d.aid.model)<=0) return;
497 sprintf(buffer," Disk <%d> ",nb_sub_disk_menu);
498 *menu = add_menu(buffer,-1);
500 sprintf(buffer,"Model : %s",d.aid.model);
501 add_item(buffer,"Model",OPT_INACTIVE,NULL,0);
503 // Compute device size
504 char previous_unit[3],unit[3]; //GB
505 int previous_size,size = d.sectors/2; // Converting to bytes
507 strcpy(previous_unit,unit);
515 strcpy(previous_unit,unit);
520 strcpy(previous_unit,unit);
526 sprintf(buffer,"Size : %d %s (%d %s)",size,unit,previous_size,previous_unit);
527 add_item(buffer,"Size",OPT_INACTIVE,NULL,0);
529 sprintf(buffer,"Firmware Rev.: %s",d.aid.fw_rev);
530 add_item(buffer,"Firmware Revision",OPT_INACTIVE,NULL,0);
532 sprintf(buffer,"Serial Number: %s",d.aid.serial_no);
533 add_item(buffer,"Serial Number",OPT_INACTIVE,NULL,0);
535 sprintf(buffer,"Interface : %s",d.interface_type);
536 add_item(buffer,"Interface Type",OPT_INACTIVE,NULL,0);
538 sprintf(buffer,"Host Bus : %s",d.host_bus_type);
539 add_item(buffer,"Host Bus Type",OPT_INACTIVE,NULL,0);
541 sprintf(buffer,"Sectors : %d",d.sectors);
542 add_item(buffer,"Sectors",OPT_INACTIVE,NULL,0);
544 sprintf(buffer,"Heads : %d",d.heads);
545 add_item(buffer,"Heads",OPT_INACTIVE,NULL,0);
547 sprintf(buffer,"Cylinders : %d",d.cylinders);
548 add_item(buffer,"Cylinders",OPT_INACTIVE,NULL,0);
550 sprintf(buffer,"Sectors/Track: %d",d.sectors_per_track);
551 add_item(buffer,"Sectors per Track",OPT_INACTIVE,NULL,0);
553 sprintf(buffer,"Port : 0x%X",disk_number);
554 add_item(buffer,"Port",OPT_INACTIVE,NULL,0);
556 sprintf(buffer,"EDD Version : %s",d.edd_version);
557 add_item(buffer,"EDD Version",OPT_INACTIVE,NULL,0);
562 void compute_memory_module(unsigned char *menu, s_dmi *dmi, int slot_number) {
564 char buffer[MENULEN];
565 sprintf(buffer," Module <%d> ",i);
566 *menu = add_menu(buffer,-1);
568 sprintf(buffer,"Form Factor : %s",dmi->memory[i].form_factor);
569 add_item(buffer,"Form Factor",OPT_INACTIVE,NULL,0);
571 sprintf(buffer,"Type : %s",dmi->memory[i].type);
572 add_item(buffer,"Memory Type",OPT_INACTIVE,NULL,0);
574 sprintf(buffer,"Type Details : %s",dmi->memory[i].type_detail);
575 add_item(buffer,"Memory Ty^e Details",OPT_INACTIVE,NULL,0);
577 sprintf(buffer,"Speed : %s",dmi->memory[i].speed);
578 add_item(buffer,"Speed (MHz)",OPT_INACTIVE,NULL,0);
580 sprintf(buffer,"Size : %s",dmi->memory[i].size);
581 add_item(buffer,"Size",OPT_INACTIVE,NULL,0);
583 sprintf(buffer,"Device Set : %s",dmi->memory[i].device_set);
584 add_item(buffer,"Device Set",OPT_INACTIVE,NULL,0);
586 sprintf(buffer,"Device Loc. : %s",dmi->memory[i].device_locator);
587 add_item(buffer,"Device Location",OPT_INACTIVE,NULL,0);
589 sprintf(buffer,"Bank Locator : %s",dmi->memory[i].bank_locator);
590 add_item(buffer,"Bank Location",OPT_INACTIVE,NULL,0);
592 sprintf(buffer,"Total Width : %s",dmi->memory[i].total_width);
593 add_item(buffer,"Total bit Width",OPT_INACTIVE,NULL,0);
595 sprintf(buffer,"Data Width : %s",dmi->memory[i].data_width);
596 add_item(buffer,"Data bit Width",OPT_INACTIVE,NULL,0);
598 sprintf(buffer,"Error : %s",dmi->memory[i].error);
599 add_item(buffer,"Error",OPT_INACTIVE,NULL,0);
601 sprintf(buffer,"Vendor : %s",dmi->memory[i].manufacturer);
602 add_item(buffer,"Vendor",OPT_INACTIVE,NULL,0);
604 sprintf(buffer,"Serial : %s",dmi->memory[i].serial);
605 add_item(buffer,"Serial Number",OPT_INACTIVE,NULL,0);
607 sprintf(buffer,"Asset Tag : %s",dmi->memory[i].asset_tag);
608 add_item(buffer,"Asset Tag",OPT_INACTIVE,NULL,0);
610 sprintf(buffer,"Part Number : %s",dmi->memory[i].part_number);
611 add_item(buffer,"Part Number",OPT_INACTIVE,NULL,0);
615 void compute_motherboard(unsigned char *menu,s_dmi *dmi) {
616 char buffer[MENULEN];
617 *menu = add_menu(" Motherboard ",-1);
618 snprintf(buffer,MENULEN,"Vendor : %s",dmi->base_board.manufacturer);
619 add_item(buffer,"Vendor",OPT_INACTIVE,NULL,0);
620 snprintf(buffer,MENULEN,"Product : %s",dmi->base_board.product_name);
621 add_item(buffer,"Product Name",OPT_INACTIVE,NULL,0);
622 snprintf(buffer,MENULEN,"Version : %s",dmi->base_board.version);
623 add_item(buffer,"Version",OPT_INACTIVE,NULL,0);
624 snprintf(buffer,MENULEN,"Serial : %s",dmi->base_board.serial);
625 add_item(buffer,"Serial Number",OPT_INACTIVE,NULL,0);
626 snprintf(buffer,MENULEN,"Asset Tag : %s",dmi->base_board.asset_tag);
627 add_item(buffer,"Asset Tag",OPT_INACTIVE,NULL,0);
628 snprintf(buffer,MENULEN,"Location : %s",dmi->base_board.location);
629 add_item(buffer,"Location",OPT_INACTIVE,NULL,0);
630 snprintf(buffer,MENULEN,"Type : %s",dmi->base_board.type);
631 add_item(buffer,"Type",OPT_INACTIVE,NULL,0);
634 void compute_system(unsigned char *menu,s_dmi *dmi) {
635 char buffer[MENULEN];
636 *menu = add_menu(" System ",-1);
637 snprintf(buffer,MENULEN,"Vendor : %s",dmi->system.manufacturer);
638 add_item(buffer,"Vendor",OPT_INACTIVE,NULL,0);
639 snprintf(buffer,MENULEN,"Product : %s",dmi->system.product_name);
640 add_item(buffer,"Product Name",OPT_INACTIVE,NULL,0);
641 snprintf(buffer,MENULEN,"Version : %s",dmi->system.version);
642 add_item(buffer,"Version",OPT_INACTIVE,NULL,0);
643 snprintf(buffer,MENULEN,"Serial : %s",dmi->system.serial);
644 add_item(buffer,"Serial Number",OPT_INACTIVE,NULL,0);
645 snprintf(buffer,MENULEN,"UUID : %s",dmi->system.uuid);
646 add_item(buffer,"UUID",OPT_INACTIVE,NULL,0);
647 snprintf(buffer,MENULEN,"Wakeup : %s",dmi->system.wakeup_type);
648 add_item(buffer,"Wakeup Type",OPT_INACTIVE,NULL,0);
649 snprintf(buffer,MENULEN,"SKU Number: %s",dmi->system.sku_number);
650 add_item(buffer,"SKU Number",OPT_INACTIVE,NULL,0);
651 snprintf(buffer,MENULEN,"Family : %s",dmi->system.family);
652 add_item(buffer,"Family",OPT_INACTIVE,NULL,0);
655 void compute_chassis(unsigned char *menu,s_dmi *dmi) {
656 char buffer[MENULEN];
657 *menu = add_menu(" Chassis ",-1);
658 snprintf(buffer,MENULEN,"Vendor : %s",dmi->chassis.manufacturer);
659 add_item(buffer,"Vendor",OPT_INACTIVE,NULL,0);
660 snprintf(buffer,MENULEN,"Type : %s",dmi->chassis.type);
661 add_item(buffer,"Type",OPT_INACTIVE,NULL,0);
662 snprintf(buffer,MENULEN,"Version : %s",dmi->chassis.version);
663 add_item(buffer,"Version",OPT_INACTIVE,NULL,0);
664 snprintf(buffer,MENULEN,"Serial : %s",dmi->chassis.serial);
665 add_item(buffer,"Serial Number",OPT_INACTIVE,NULL,0);
666 snprintf(buffer,MENULEN,"Asset Tag : %s",dmi->chassis.asset_tag);
667 add_item(buffer,"Asset Tag",OPT_INACTIVE,NULL,0);
668 snprintf(buffer,MENULEN,"Lock : %s",dmi->chassis.lock);
669 add_item(buffer,"Lock",OPT_INACTIVE,NULL,0);
672 void compute_bios(unsigned char *menu,s_dmi *dmi) {
673 char buffer[MENULEN];
674 *menu = add_menu(" BIOS ",-1);
675 snprintf(buffer,MENULEN,"Vendor : %s",dmi->bios.vendor);
676 add_item(buffer,"Vendor",OPT_INACTIVE,NULL,0);
677 snprintf(buffer,MENULEN,"Version : %s",dmi->bios.version);
678 add_item(buffer,"Version",OPT_INACTIVE,NULL,0);
679 snprintf(buffer,MENULEN,"Release : %s",dmi->bios.release_date);
680 add_item(buffer,"Release Date",OPT_INACTIVE,NULL,0);
681 snprintf(buffer,MENULEN,"Bios Rev. : %s",dmi->bios.bios_revision);
682 add_item(buffer,"Bios Revision",OPT_INACTIVE,NULL,0);
683 snprintf(buffer,MENULEN,"Fw. Rev. : %s",dmi->bios.firmware_revision);
684 add_item(buffer,"Firmware Revision",OPT_INACTIVE,NULL,0);
687 void compute_processor(unsigned char *menu,s_cpu *cpu, s_dmi *dmi) {
688 char buffer[MENULEN];
689 char buffer1[MENULEN];
690 *menu = add_menu(" Main Processor ",-1);
691 snprintf(buffer,MENULEN,"Vendor : %s",cpu->vendor);
692 add_item(buffer,"Vendor",OPT_INACTIVE,NULL,0);
693 snprintf(buffer,MENULEN,"Model : %s",cpu->model);
694 add_item(buffer,"Model",OPT_INACTIVE,NULL,0);
695 snprintf(buffer,MENULEN,"Vendor ID : %d",cpu->vendor_id);
696 add_item(buffer,"Vendor ID",OPT_INACTIVE,NULL,0);
697 snprintf(buffer,MENULEN,"Family ID : %d",cpu->family);
698 add_item(buffer,"Family ID",OPT_INACTIVE,NULL,0);
699 snprintf(buffer,MENULEN,"Model ID : %d",cpu->model_id);
700 add_item(buffer,"Model ID",OPT_INACTIVE,NULL,0);
701 snprintf(buffer,MENULEN,"Stepping : %d",cpu->stepping);
702 add_item(buffer,"Stepping",OPT_INACTIVE,NULL,0);
704 snprintf(buffer,MENULEN,"FSB : %d",dmi->processor.external_clock);
705 add_item(buffer,"Front Side Bus (MHz)",OPT_INACTIVE,NULL,0);
706 snprintf(buffer,MENULEN,"Cur. Speed: %d",dmi->processor.current_speed);
707 add_item(buffer,"Current Speed (MHz)",OPT_INACTIVE,NULL,0);
708 snprintf(buffer,MENULEN,"Max Speed : %d",dmi->processor.max_speed);
709 add_item(buffer,"Max Speed (MHz)",OPT_INACTIVE,NULL,0);
710 snprintf(buffer,MENULEN,"Upgrade : %s",dmi->processor.upgrade);
711 add_item(buffer,"Upgrade",OPT_INACTIVE,NULL,0);
714 if (cpu->flags.smp) snprintf(buffer,MENULEN,"SMP : Yes");
715 else snprintf(buffer,MENULEN,"SMP : No");
716 add_item(buffer,"SMP system",OPT_INACTIVE,NULL,0);
718 if (cpu->flags.lm) snprintf(buffer,MENULEN,"x86_64 : Yes");
719 else snprintf(buffer,MENULEN,"X86_64 : No");
720 add_item(buffer,"x86_64 compatible processor",OPT_INACTIVE,NULL,0);
723 if (cpu->flags.fpu) strcat(buffer1,"fpu ");
724 if (cpu->flags.vme) strcat(buffer1,"vme ");
725 if (cpu->flags.de) strcat(buffer1,"de ");
726 if (cpu->flags.pse) strcat(buffer1,"pse ");
727 if (cpu->flags.tsc) strcat(buffer1,"tsc ");
728 if (cpu->flags.msr) strcat(buffer1,"msr ");
729 if (cpu->flags.pae) strcat(buffer1,"pae ");
730 snprintf(buffer,MENULEN,"Flags : %s",buffer1);
731 add_item(buffer,"Flags",OPT_INACTIVE,NULL,0);
734 if (cpu->flags.mce) strcat(buffer1,"mce ");
735 if (cpu->flags.cx8) strcat(buffer1,"cx8 ");
736 if (cpu->flags.apic) strcat(buffer1,"apic ");
737 if (cpu->flags.sep) strcat(buffer1,"sep ");
738 if (cpu->flags.mtrr) strcat(buffer1,"mtrr ");
739 if (cpu->flags.pge) strcat(buffer1,"pge ");
740 if (cpu->flags.mca) strcat(buffer1,"mca ");
741 snprintf(buffer,MENULEN,"Flags : %s",buffer1);
742 add_item(buffer,"Flags",OPT_INACTIVE,NULL,0);
745 if (cpu->flags.cmov) strcat(buffer1,"cmov ");
746 if (cpu->flags.pat) strcat(buffer1,"pat ");
747 if (cpu->flags.pse_36) strcat(buffer1,"pse_36 ");
748 if (cpu->flags.psn) strcat(buffer1,"psn ");
749 if (cpu->flags.clflsh) strcat(buffer1,"clflsh ");
750 snprintf(buffer,MENULEN,"Flags : %s",buffer1);
751 add_item(buffer,"Flags",OPT_INACTIVE,NULL,0);
754 if (cpu->flags.dts) strcat(buffer1,"dts ");
755 if (cpu->flags.acpi) strcat(buffer1,"acpi ");
756 if (cpu->flags.mmx) strcat(buffer1,"mmx ");
757 if (cpu->flags.sse) strcat(buffer1,"sse ");
758 snprintf(buffer,MENULEN,"Flags : %s",buffer1);
759 add_item(buffer,"Flags",OPT_INACTIVE,NULL,0);
762 if (cpu->flags.sse2) strcat(buffer1,"sse2 ");
763 if (cpu->flags.ss) strcat(buffer1,"ss ");
764 if (cpu->flags.htt) strcat(buffer1,"ht ");
765 if (cpu->flags.acc) strcat(buffer1,"acc ");
766 if (cpu->flags.syscall) strcat(buffer1,"syscall ");
767 if (cpu->flags.mp) strcat(buffer1,"mp ");
768 snprintf(buffer,MENULEN,"Flags : %s",buffer1);
769 add_item(buffer,"Flags",OPT_INACTIVE,NULL,0);
772 if (cpu->flags.nx) strcat(buffer1,"nx ");
773 if (cpu->flags.mmxext) strcat(buffer1,"mmxext ");
774 if (cpu->flags.lm) strcat(buffer1,"lm ");
775 if (cpu->flags.nowext) strcat(buffer1,"3dnowext ");
776 if (cpu->flags.now) strcat(buffer1,"3dnow! ");
777 snprintf(buffer,MENULEN,"Flags : %s",buffer1);
778 add_item(buffer,"Flags",OPT_INACTIVE,NULL,0);
783 openconsole(&dev_stdcon_r, &dev_stdcon_w);
784 init_menusystem("Hardware Detection Tool Version 0.1.1 by Erwan Velu");
785 set_window_size(1,1,23,78); // Leave some space around
787 // Register the menusystem handler
788 // reg_handler(HDLR_SCREEN,&msys_handler);
789 reg_handler(HDLR_KEYS,&keys_handler);
791 // Register the ontimeout handler, with a time out of 10 seconds
792 reg_ontimeout(ontimeout,1000,0);
795 void detect_hardware(s_dmi *dmi, s_cpu *cpu, struct pci_domain **pci_domain, struct diskinfo *disk_info) {
796 printf("CPU: Detecting\n");
799 printf("DISKS: Detecting\n");
800 detect_disks(disk_info);
802 printf("DMI: Detecting Table\n");
803 if (detect_dmi(dmi) == 0)
807 printf("PCI: Detecting Devices\n");
808 /* Scanning to detect pci buses and devices */
809 *pci_domain = pci_scan();
812 printf("PCI: Resolving names\n");
813 /* Assigning product & vendor name for each device*/
814 get_name_from_pci_ids(*pci_domain);
816 printf("PCI: Resolving class names\n");
817 /* Assigning class name for each device*/
818 get_class_name_from_pci_ids(*pci_domain);
821 printf("PCI: Resolving module names\n");
822 /* Detecting which kernel module should match each device */
823 get_module_name_from_pci_ids(*pci_domain);
827 void compute_memory(unsigned char *menu, s_dmi *dmi) {
828 char buffer[MENULEN];
829 for (int i=0;i<dmi->memory_count;i++) {
830 compute_memory_module(&MEMORY_SUBMENU[i],dmi,i);
833 *menu = add_menu(" Modules ",-1);
835 for (int i=0;i<dmi->memory_count;i++) {
836 sprintf(buffer," Module <%d> ",i);
837 add_item(buffer,"Memory Module",OPT_SUBMENU,NULL,MEMORY_SUBMENU[i]);
839 add_item("Run Test","Run Test",OPT_RUN,"memtest",0);
842 void compute_disks(unsigned char *menu, struct diskinfo *disk_info) {
843 char buffer[MENULEN];
846 for (int i=0;i<0xff;i++) {
847 compute_disk_module(&DISK_SUBMENU[nb_sub_disk_menu],disk_info,i);
850 *menu = add_menu(" Disks ",-1);
852 for (int i=0;i<nb_sub_disk_menu;i++) {
853 sprintf(buffer," Disk <%d> ",i);
854 add_item(buffer,"Disk",OPT_SUBMENU,NULL,DISK_SUBMENU[i]);
858 void compute_submenus(s_dmi *dmi, s_cpu *cpu, struct pci_domain **pci_domain, struct diskinfo *disk_info) {
860 compute_motherboard(&MOBO_MENU,dmi);
861 compute_chassis(&CHASSIS_MENU,dmi);
862 compute_system(&SYSTEM_MENU,dmi);
863 compute_memory(&MEMORY_MENU,dmi);
864 compute_bios(&BIOS_MENU,dmi);
865 compute_battery(&BATTERY_MENU,dmi);
867 compute_processor(&CPU_MENU,cpu,dmi);
868 compute_disks(&DISK_MENU,disk_info);
870 compute_PCI(&PCI_MENU,pci_domain);
871 compute_KERNEL(&KERNEL_MENU,pci_domain);
875 void compute_main_menu() {
876 MAIN_MENU = add_menu(" Main Menu ",-1);
877 set_item_options(-1,24);
879 if (nb_sub_disk_menu>0)
881 add_item("PCI <D>evices","PCI Devices",OPT_SUBMENU,NULL,PCI_MENU);
883 add_item("<D>isks","Disks",OPT_SUBMENU,NULL,DISK_MENU);
884 add_item("<M>emory Modules","Memory Modules",OPT_SUBMENU,NULL,MEMORY_MENU);
885 add_item("<P>rocessor","Main Processor",OPT_SUBMENU,NULL,CPU_MENU);
888 add_item("<M>otherboard","Motherboard",OPT_SUBMENU,NULL,MOBO_MENU);
889 add_item("<B>ios","Bios",OPT_SUBMENU,NULL,BIOS_MENU);
890 add_item("<C>hassis","Chassis",OPT_SUBMENU,NULL,CHASSIS_MENU);
891 add_item("<S>ystem","System",OPT_SUBMENU,NULL,SYSTEM_MENU);
892 add_item("Ba<t>tery","Battery",OPT_SUBMENU,NULL,BATTERY_MENU);
895 add_item("","",OPT_SEP,"",0);
896 add_item("<K>ernel modules","Kernel Modules",OPT_SUBMENU,NULL,KERNEL_MENU);
904 struct pci_domain *pci_domain=NULL;
905 struct diskinfo disk_info[255];
909 detect_hardware(&dmi,&cpu,&pci_domain,disk_info);
911 compute_submenus(&dmi,&cpu,&pci_domain,disk_info);
915 #ifdef WITH_MENU_DISPLAY
919 printf("Starting Menu\n");
920 curr=showmenus(MAIN_MENU);
922 if (curr->action == OPT_RUN)
924 strcpy(cmd,curr->data);
928 else csprint(cmd,0x07);
929 return 1; // Should not happen when run from SYSLINUX