1 /* ----------------------------------------------------------------------- * 2 * 3 * Copyright 2009 Erwan Velu - All Rights Reserved 4 * 5 * Permission is hereby granted, free of charge, to any person 6 * obtaining a copy of this software and associated documentation 7 * files (the "Software"), to deal in the Software without 8 * restriction, including without limitation the rights to use, 9 * copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Software, and to permit persons to whom 11 * the Software is furnished to do so, subject to the following 12 * conditions: 13 * 14 * The above copyright notice and this permission notice shall 15 * be included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 * OTHER DEALINGS IN THE SOFTWARE. 25 * 26 * ----------------------------------------------------------------------- 27 */ 28 29 #include <stdlib.h> 30 #include <string.h> 31 #include <stdio.h> 32 #include <getkey.h> 33 #include "syslinux/config.h" 34 #include "../lib/sys/vesa/vesa.h" 35 #include "hdt-common.h" 36 #include <disk/util.h> 37 #include <disk/mbrs.h> 38 #include <memory.h> 39 40 /* ISOlinux requires a 8.3 format */ 41 void convert_isolinux_filename(char *filename, struct s_hardware *hardware) 42 { 43 /* Exit if we are not running ISOLINUX */ 44 if (hardware->sv->filesystem != SYSLINUX_FS_ISOLINUX) 45 return; 46 /* Searching the dot */ 47 char *dot = strchr(filename, '.'); 48 /* Exiting if no dot exists in that string */ 49 if (dot == NULL) 50 return; 51 /* Exiting if the extension is 3 char or less */ 52 if (strlen(dot) <= 4) 53 return; 54 55 /* We have an extension bigger than .blah 56 * so we have to shorten it to 3*/ 57 dot[4] = '\0'; 58 } 59 60 void detect_parameters(const int argc, const char *argv[], 61 struct s_hardware *hardware) 62 { 63 /* Quiet mode - make the output more quiet */ 64 quiet = true; 65 66 /* Silent mode - make not output at all */ 67 silent = false; 68 69 /* Vesa mode isn't set until we explictly call it */ 70 vesamode = false; 71 72 /* Automode isn't the default*/ 73 automode = false; 74 75 /* Menu mode is the default*/ 76 menumode = true; 77 78 for (int i = 1; i < argc; i++) { 79 if (!strncmp(argv[i], "quiet", 5)) { 80 quiet = true; 81 } else if (!strncmp(argv[i], "silent", 6)) { 82 silent = true; 83 } else if (!strncmp(argv[i], "verbose", 7)) { 84 quiet = false; 85 } else if (!strncmp(argv[i], "modules_pcimap=", 15)) { 86 strlcpy(hardware->modules_pcimap_path, argv[i] + 15, 87 sizeof(hardware->modules_pcimap_path)); 88 convert_isolinux_filename(hardware->modules_pcimap_path, hardware); 89 } else if (!strncmp(argv[i], "pciids=", 7)) { 90 strlcpy(hardware->pciids_path, argv[i] + 7, 91 sizeof(hardware->pciids_path)); 92 convert_isolinux_filename(hardware->pciids_path, hardware); 93 } else if (!strncmp(argv[i], "modules_alias=", 14)) { 94 strlcpy(hardware->modules_alias_path, argv[i] + 14, 95 sizeof(hardware->modules_alias_path)); 96 convert_isolinux_filename(hardware->modules_alias_path, hardware); 97 } else if (!strncmp(argv[i], "memtest=", 8)) { 98 strlcpy(hardware->memtest_label, argv[i] + 8, 99 sizeof(hardware->memtest_label)); 100 convert_isolinux_filename(hardware->memtest_label, hardware); 101 } else if (!strncmp(argv[i], "vesa", 4)) { 102 vesamode = true; 103 max_console_lines = MAX_VESA_CLI_LINES; 104 /* If the user defines a background image */ 105 if (!strncmp(argv[i], "vesa=", 5)) { 106 strlcpy(hardware->vesa_background, argv[i] + 5, 107 sizeof(hardware->vesa_background)); 108 } 109 } else if (!strncmp(argv[i], "novesa", 6)) { 110 vesamode = false; 111 max_console_lines = MAX_CLI_LINES; 112 } else if (!strncmp(argv[i], "nomenu", 6)) { 113 menumode = false; 114 } else if (!strncmp(argv[i], "dump_filename=", 14)) { 115 strlcpy(hardware->dump_filename, argv[i] + 14, 116 sizeof(hardware->dump_filename)); 117 } else if (!strncmp(argv[i], "dump_path=", 10)) { 118 strlcpy(hardware->dump_path, argv[i] + 10, 119 sizeof(hardware->dump_path)); 120 } else if (!strncmp(argv[i], "tftp_ip=", 8)) { 121 strlcpy(hardware->tftp_ip, argv[i] + 8, 122 sizeof(hardware->tftp_ip)); 123 } else if (!strncmp(argv[i], "postexec=", 9)) { 124 /* The postexec= parameter is separated in several argv[] 125 * as it can contains spaces. 126 * We use the AUTO_DELIMITER char to define the limits 127 * of this parameter. 128 * i.e postexec='linux memtest.bin' 129 */ 130 131 char *argument = (char*)argv[i]+10; 132 /* Extracting the first parameter */ 133 strcpy(hardware->postexec, argument); 134 135 /* While we can't find the other AUTO_DELIMITER, let's process the argv[] */ 136 while ((strchr(argument, AUTO_DELIMITER) == NULL) && (i+1<argc)) { 137 i++; 138 argument = (char *)argv[i]; 139 strcat(hardware->postexec, " "); 140 strcat(hardware->postexec, argument); 141 } 142 143 hardware->postexec[strlen(hardware->postexec) - 1] = 0; 144 } else if (!strncmp(argv[i], "auto=", 5)) { 145 /* The auto= parameter is separated in several argv[] 146 * as it can contains spaces. 147 * We use the AUTO_DELIMITER char to define the limits 148 * of this parameter. 149 * i.e auto='show dmi; show pci' 150 */ 151 152 automode=true; 153 char *argument = (char*)argv[i]+6; 154 /* Extracting the first parameter */ 155 strcpy(hardware->auto_label, argument); 156 157 /* While we can't find the other AUTO_DELIMITER, let's process the argv[] */ 158 while ((strchr(argument, AUTO_DELIMITER) == NULL) && (i+1<argc)) { 159 i++; 160 argument = (char *)argv[i]; 161 strcat(hardware->auto_label, " "); 162 strcat(hardware->auto_label, argument); 163 } 164 165 hardware->auto_label[strlen(hardware->auto_label) - 1] = 0; 166 } 167 } 168 } 169 170 void detect_syslinux(struct s_hardware *hardware) 171 { 172 hardware->sv = syslinux_version(); 173 switch (hardware->sv->filesystem) { 174 case SYSLINUX_FS_SYSLINUX: 175 strlcpy(hardware->syslinux_fs, "SYSlinux", 9); 176 break; 177 case SYSLINUX_FS_PXELINUX: 178 strlcpy(hardware->syslinux_fs, "PXElinux", 9); 179 break; 180 case SYSLINUX_FS_ISOLINUX: 181 strlcpy(hardware->syslinux_fs, "ISOlinux", 9); 182 break; 183 case SYSLINUX_FS_EXTLINUX: 184 strlcpy(hardware->syslinux_fs, "EXTlinux", 9); 185 break; 186 case SYSLINUX_FS_UNKNOWN: 187 default: 188 strlcpy(hardware->syslinux_fs, "Unknown Bootloader", 189 sizeof hardware->syslinux_fs); 190 break; 191 } 192 } 193 194 void init_hardware(struct s_hardware *hardware) 195 { 196 hardware->pci_ids_return_code = 0; 197 hardware->modules_pcimap_return_code = 0; 198 hardware->modules_alias_return_code = 0; 199 hardware->cpu_detection = false; 200 hardware->pci_detection = false; 201 hardware->disk_detection = false; 202 hardware->disks_count = 0; 203 hardware->dmi_detection = false; 204 hardware->pxe_detection = false; 205 hardware->vesa_detection = false; 206 hardware->vpd_detection = false; 207 hardware->memory_detection = false; 208 hardware->acpi_detection = false; 209 hardware->nb_pci_devices = 0; 210 hardware->is_dmi_valid = false; 211 hardware->is_pxe_valid = false; 212 hardware->is_vpd_valid = false; 213 hardware->is_acpi_valid = false; 214 hardware->pci_domain = NULL; 215 hardware->detected_memory_size = 0; 216 hardware->physical_cpu_count =1; /* we have at least one cpu */ 217 218 /* Cleaning structures */ 219 memset(hardware->disk_info, 0, sizeof(hardware->disk_info)); 220 memset(hardware->mbr_ids, 0, sizeof(hardware->mbr_ids)); 221 memset(&hardware->dmi, 0, sizeof(s_dmi)); 222 memset(&hardware->cpu, 0, sizeof(s_cpu)); 223 memset(&hardware->pxe, 0, sizeof(struct s_pxe)); 224 memset(&hardware->vesa, 0, sizeof(struct s_vesa)); 225 memset(&hardware->vpd, 0, sizeof(s_vpd)); 226 memset(&hardware->acpi, 0, sizeof(s_acpi)); 227 memset(hardware->syslinux_fs, 0, sizeof hardware->syslinux_fs); 228 memset(hardware->pciids_path, 0, sizeof hardware->pciids_path); 229 memset(hardware->modules_pcimap_path, 0, 230 sizeof hardware->modules_pcimap_path); 231 memset(hardware->modules_alias_path, 0, 232 sizeof hardware->modules_alias_path); 233 memset(hardware->memtest_label, 0, sizeof hardware->memtest_label); 234 memset(hardware->auto_label, 0, sizeof hardware->auto_label); 235 memset(hardware->dump_path, 0, sizeof hardware->dump_path); 236 memset(hardware->dump_filename, 0, sizeof hardware->dump_filename); 237 memset(hardware->vesa_background, 0, sizeof hardware->vesa_background); 238 memset(hardware->tftp_ip, 0, sizeof hardware->tftp_ip); 239 memset(hardware->postexec, 0, sizeof hardware->postexec); 240 strcat(hardware->dump_path, "hdt"); 241 strcat(hardware->dump_filename, "%{m}+%{p}+%{v}"); 242 strcat(hardware->pciids_path, "pci.ids"); 243 strcat(hardware->modules_pcimap_path, "modules.pcimap"); 244 strcat(hardware->modules_alias_path, "modules.alias"); 245 strcat(hardware->memtest_label, "memtest"); 246 strlcpy(hardware->vesa_background, CLI_DEFAULT_BACKGROUND, 247 sizeof(hardware->vesa_background)); 248 } 249 250 /* 251 * Detecting if a DMI table exist 252 * if yes, let's parse it 253 */ 254 int detect_dmi(struct s_hardware *hardware) 255 { 256 if (hardware->dmi_detection == true) 257 return -1; 258 hardware->dmi_detection = true; 259 if (dmi_iterate(&hardware->dmi) == -ENODMITABLE) { 260 hardware->is_dmi_valid = false; 261 return -ENODMITABLE; 262 } 263 264 parse_dmitable(&hardware->dmi); 265 hardware->is_dmi_valid = true; 266 return 0; 267 } 268 269 /* 270 * Detecting ACPI 271 * if yes, let's parse it 272 */ 273 int detect_acpi(struct s_hardware *hardware) 274 { 275 int retval; 276 if (hardware->acpi_detection == true) 277 return -1; 278 hardware->acpi_detection = true; 279 if ((retval=parse_acpi(&hardware->acpi)) != ACPI_FOUND) { 280 hardware->is_acpi_valid = false; 281 return retval; 282 } 283 284 hardware->is_acpi_valid = true; 285 return retval; 286 } 287 288 /** 289 * vpd_detection - populate the VPD structure 290 * 291 * VPD is a structure available on IBM machines. 292 * It is documented at: 293 * http://www.pc.ibm.com/qtechinfo/MIGR-45120.html 294 * (XXX the page seems to be gone) 295 **/ 296 int detect_vpd(struct s_hardware *hardware) 297 { 298 if (hardware->vpd_detection) 299 return -1; 300 else 301 hardware->vpd_detection = true; 302 303 if (vpd_decode(&hardware->vpd) == -ENOVPDTABLE) { 304 hardware->is_vpd_valid = false; 305 return -ENOVPDTABLE; 306 } else { 307 hardware->is_vpd_valid = true; 308 return 0; 309 } 310 } 311 312 /* Detection vesa stuff*/ 313 int detect_vesa(struct s_hardware *hardware) 314 { 315 static com32sys_t rm; 316 struct vesa_general_info *gi; 317 struct vesa_mode_info *mi; 318 uint16_t mode, *mode_ptr; 319 char *oem_ptr; 320 int rv = -1; 321 322 if (hardware->vesa_detection == true) 323 return -1; 324 325 hardware->vesa_detection = true; 326 hardware->is_vesa_valid = false; 327 328 gi = lmalloc(sizeof(*gi)); 329 if (!gi) 330 return -1; 331 332 mi = lmalloc(sizeof(*mi)); 333 if (!mi) 334 goto out; 335 336 gi->signature = VBE2_MAGIC; /* Get VBE2 extended data */ 337 memset(&rm, 0, sizeof rm); 338 rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ 339 rm.edi.w[0] = OFFS(gi); 340 rm.es = SEG(gi); 341 __intcall(0x10, &rm, &rm); 342 343 if (rm.eax.w[0] != 0x004F) { 344 goto out; 345 }; 346 347 mode_ptr = GET_PTR(gi->video_mode_ptr); 348 oem_ptr = GET_PTR(gi->oem_vendor_name_ptr); 349 strlcpy(hardware->vesa.vendor, oem_ptr, sizeof(hardware->vesa.vendor)); 350 oem_ptr = GET_PTR(gi->oem_product_name_ptr); 351 strlcpy(hardware->vesa.product, oem_ptr, sizeof(hardware->vesa.product)); 352 oem_ptr = GET_PTR(gi->oem_product_rev_ptr); 353 strlcpy(hardware->vesa.product_revision, oem_ptr, 354 sizeof(hardware->vesa.product_revision)); 355 356 hardware->vesa.major_version = (gi->version >> 8) & 0xff; 357 hardware->vesa.minor_version = gi->version & 0xff; 358 hardware->vesa.total_memory = gi->total_memory; 359 hardware->vesa.software_rev = gi->oem_software_rev; 360 361 hardware->vesa.vmi_count = 0; 362 363 while ((mode = *mode_ptr++) != 0xFFFF) { 364 365 memset(&rm, 0, sizeof rm); 366 rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ 367 rm.ecx.w[0] = mode; 368 rm.edi.w[0] = OFFS(mi); 369 rm.es = SEG(mi); 370 __intcall(0x10, &rm, &rm); 371 372 /* Must be a supported mode */ 373 if (rm.eax.w[0] != 0x004f) 374 continue; 375 376 /* Saving detected values */ 377 memcpy(&hardware->vesa.vmi[hardware->vesa.vmi_count].mi, mi, 378 sizeof(struct vesa_mode_info)); 379 hardware->vesa.vmi[hardware->vesa.vmi_count].mode = mode; 380 381 hardware->vesa.vmi_count++; 382 } 383 hardware->is_vesa_valid = true; 384 385 rv = 0; 386 out: 387 lfree(mi); 388 lfree(gi); 389 return rv; 390 } 391 392 /* Try to detect disks from port 0x80 to 0xff */ 393 void detect_disks(struct s_hardware *hardware) 394 { 395 int i = -1; 396 int err; 397 398 if (hardware->disk_detection) 399 return; 400 401 hardware->disk_detection = true; 402 for (int drive = 0x80; drive < 0xff; drive++) { 403 i++; 404 hardware->disk_info[i].disk = drive; 405 err = get_drive_parameters(&hardware->disk_info[i]); 406 407 /* 408 * Do not print output when drive does not exist or 409 * doesn't support int13 (cdrom, ...) 410 */ 411 if (err == -1 || !hardware->disk_info[i].cbios) 412 continue; 413 414 /* Detect MBR */ 415 hardware->mbr_ids[i] = get_mbr_id(&hardware->disk_info[i]); 416 417 hardware->disks_count++; 418 } 419 } 420 421 int detect_pxe(struct s_hardware *hardware) 422 { 423 void *dhcpdata; 424 425 size_t dhcplen; 426 t_PXENV_UNDI_GET_NIC_TYPE gnt; 427 428 if (hardware->pxe_detection == true) 429 return -1; 430 hardware->pxe_detection = true; 431 hardware->is_pxe_valid = false; 432 memset(&gnt, 0, sizeof(t_PXENV_UNDI_GET_NIC_TYPE)); 433 memset(&hardware->pxe, 0, sizeof(struct s_pxe)); 434 435 /* This code can only work if pxelinux is loaded */ 436 if (hardware->sv->filesystem != SYSLINUX_FS_PXELINUX) { 437 return -1; 438 } 439 // printf("PXE: PXElinux detected\n"); 440 if (!pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK, &dhcpdata, &dhcplen)) { 441 pxe_bootp_t *dhcp = &hardware->pxe.dhcpdata; 442 memcpy(&hardware->pxe.dhcpdata, dhcpdata, 443 sizeof(hardware->pxe.dhcpdata)); 444 snprintf(hardware->pxe.mac_addr, sizeof(hardware->pxe.mac_addr), 445 "%02x:%02x:%02x:%02x:%02x:%02x", dhcp->CAddr[0], 446 dhcp->CAddr[1], dhcp->CAddr[2], dhcp->CAddr[3], 447 dhcp->CAddr[4], dhcp->CAddr[5]); 448 449 /* Saving our IP address in a easy format */ 450 hardware->pxe.ip_addr[0] = hardware->pxe.dhcpdata.yip & 0xff; 451 hardware->pxe.ip_addr[1] = hardware->pxe.dhcpdata.yip >> 8 & 0xff; 452 hardware->pxe.ip_addr[2] = hardware->pxe.dhcpdata.yip >> 16 & 0xff; 453 hardware->pxe.ip_addr[3] = hardware->pxe.dhcpdata.yip >> 24 & 0xff; 454 455 if (!pxe_get_nic_type(&gnt)) { 456 switch (gnt.NicType) { 457 case PCI_NIC: 458 hardware->is_pxe_valid = true; 459 hardware->pxe.vendor_id = gnt.info.pci.Vendor_ID; 460 hardware->pxe.product_id = gnt.info.pci.Dev_ID; 461 hardware->pxe.subvendor_id = gnt.info.pci.SubVendor_ID; 462 hardware->pxe.subproduct_id = 463 gnt.info.pci.SubDevice_ID, 464 hardware->pxe.rev = gnt.info.pci.Rev; 465 hardware->pxe.pci_bus = (gnt.info.pci.BusDevFunc >> 8) & 0xff; 466 hardware->pxe.pci_dev = (gnt.info.pci.BusDevFunc >> 3) & 0x7; 467 hardware->pxe.pci_func = gnt.info.pci.BusDevFunc & 0x03; 468 hardware->pxe.base_class = gnt.info.pci.Base_Class; 469 hardware->pxe.sub_class = gnt.info.pci.Sub_Class; 470 hardware->pxe.prog_intf = gnt.info.pci.Prog_Intf; 471 hardware->pxe.nictype = gnt.NicType; 472 break; 473 case CardBus_NIC: 474 hardware->is_pxe_valid = true; 475 hardware->pxe.vendor_id = gnt.info.cardbus.Vendor_ID; 476 hardware->pxe.product_id = gnt.info.cardbus.Dev_ID; 477 hardware->pxe.subvendor_id = gnt.info.cardbus.SubVendor_ID; 478 hardware->pxe.subproduct_id = 479 gnt.info.cardbus.SubDevice_ID, 480 hardware->pxe.rev = gnt.info.cardbus.Rev; 481 hardware->pxe.pci_bus = 482 (gnt.info.cardbus.BusDevFunc >> 8) & 0xff; 483 hardware->pxe.pci_dev = 484 (gnt.info.cardbus.BusDevFunc >> 3) & 0x7; 485 hardware->pxe.pci_func = gnt.info.cardbus.BusDevFunc & 0x03; 486 hardware->pxe.base_class = gnt.info.cardbus.Base_Class; 487 hardware->pxe.sub_class = gnt.info.cardbus.Sub_Class; 488 hardware->pxe.prog_intf = gnt.info.cardbus.Prog_Intf; 489 hardware->pxe.nictype = gnt.NicType; 490 break; 491 case PnP_NIC: 492 default: 493 return -1; 494 break; 495 } 496 497 /* The firt pass try to find the exact pci device */ 498 hardware->pxe.pci_device = NULL; 499 hardware->pxe.pci_device_pos = 0; 500 struct pci_device *pci_device; 501 int pci_number = 0; 502 for_each_pci_func(pci_device, hardware->pci_domain) { 503 pci_number++; 504 if ((__pci_bus == hardware->pxe.pci_bus) && 505 (__pci_slot == hardware->pxe.pci_dev) && 506 (__pci_func == hardware->pxe.pci_func) && 507 (pci_device->vendor == hardware->pxe.vendor_id) 508 && (pci_device->product == hardware->pxe.product_id)) { 509 hardware->pxe.pci_device = pci_device; 510 hardware->pxe.pci_device_pos = pci_number; 511 return 0; 512 } 513 } 514 515 /* If we reach that part, it means the pci device pointed by 516 * the pxe rom wasn't found in our list. 517 * Let's try to find the device only by its pci ids. 518 * The pci device we'll match is maybe not exactly the good one 519 * as we can have the same pci id several times. 520 * At least, the pci id, the vendor/product will be right. 521 * That's clearly a workaround for some weird cases. 522 * This should happend very unlikely */ 523 hardware->pxe.pci_device = NULL; 524 hardware->pxe.pci_device_pos = 0; 525 pci_number = 0; 526 for_each_pci_func(pci_device, hardware->pci_domain) { 527 pci_number++; 528 if ((pci_device->vendor == hardware->pxe.vendor_id) 529 && (pci_device->product == hardware->pxe.product_id)) { 530 hardware->pxe.pci_device = pci_device; 531 hardware->pxe.pci_device_pos = pci_number; 532 return 0; 533 } 534 } 535 536 } 537 } 538 return 0; 539 } 540 541 void detect_memory(struct s_hardware *hardware) { 542 if (hardware->memory_detection == false) { 543 hardware->memory_detection = true; 544 hardware->detected_memory_size = detect_memsize(); 545 } 546 } 547 548 void detect_pci(struct s_hardware *hardware) 549 { 550 if (hardware->pci_detection == true) 551 return; 552 hardware->pci_detection = true; 553 554 hardware->nb_pci_devices = 0; 555 556 /* Scanning to detect pci buses and devices */ 557 hardware->pci_domain = pci_scan(); 558 559 if (!hardware->pci_domain) 560 return; 561 562 /* Gathering addtional information */ 563 gather_additional_pci_config(hardware->pci_domain); 564 565 struct pci_device *pci_device; 566 for_each_pci_func(pci_device, hardware->pci_domain) { 567 hardware->nb_pci_devices++; 568 } 569 570 if (!quiet) { 571 more_printf("PCI: %d devices detected\n", hardware->nb_pci_devices); 572 more_printf("PCI: Resolving names\n"); 573 } 574 /* Assigning product & vendor name for each device */ 575 hardware->pci_ids_return_code = 576 get_name_from_pci_ids(hardware->pci_domain, hardware->pciids_path); 577 578 if (!quiet) 579 more_printf("PCI: Resolving class names\n"); 580 /* Assigning class name for each device */ 581 hardware->pci_ids_return_code = 582 get_class_name_from_pci_ids(hardware->pci_domain, 583 hardware->pciids_path); 584 585 if (!quiet) 586 more_printf("PCI: Resolving module names\n"); 587 /* Detecting which kernel module should match each device using modules.pcimap */ 588 hardware->modules_pcimap_return_code = 589 get_module_name_from_pcimap(hardware->pci_domain, 590 hardware->modules_pcimap_path); 591 592 /* Detecting which kernel module should match each device using modules.alias */ 593 hardware->modules_alias_return_code = 594 get_module_name_from_alias(hardware->pci_domain, 595 hardware->modules_alias_path); 596 597 } 598 599 void cpu_detect(struct s_hardware *hardware) 600 { 601 if (hardware->cpu_detection == true) 602 return; 603 detect_cpu(&hardware->cpu); 604 /* Old processors doesn't manage the identify commands 605 * Let's use the dmi value in that case */ 606 if (strlen(remove_spaces(hardware->cpu.model)) == 0) 607 strlcpy(hardware->cpu.model, hardware->dmi.processor.version, 608 sizeof(hardware->cpu.model)); 609 610 /* Some CPUs like to put many spaces in the model name 611 * That makes some weird display in console/menu 612 * Let's remove that mulitple spaces */ 613 strlcpy(hardware->cpu.model,del_multi_spaces(hardware->cpu.model),sizeof(hardware->cpu.model)); 614 615 if ((hardware->is_acpi_valid) && (hardware->acpi.madt.valid)) { 616 hardware->physical_cpu_count=hardware->acpi.madt.processor_local_apic_count / hardware->cpu.num_cores; 617 } 618 hardware->cpu_detection = true; 619 } 620 621 /* 622 * Find the last instance of a particular command line argument 623 * (which should include the final =; do not use for boolean arguments) 624 */ 625 const char *find_argument(const char **argv, const char *argument) 626 { 627 int la = strlen(argument); 628 const char **arg; 629 const char *ptr = NULL; 630 631 for (arg = argv; *arg; arg++) { 632 if (!memcmp(*arg, argument, la)) 633 ptr = *arg + la; 634 } 635 636 return ptr; 637 } 638 639 void clear_screen(void) 640 { 641 move_cursor_to_next_line(); 642 disable_utf8(); 643 set_g1_special_char(); 644 set_us_g0_charset(); 645 display_cursor(false); 646 clear_entire_screen(); 647 gotoxy(0,0); 648 reset_more_printf(); 649 } 650 651 /* remove begining spaces */ 652 char *skip_spaces(char *p) 653 { 654 while (*p && *p <= ' ') { 655 p++; 656 } 657 658 return p; 659 } 660 661 /* remove trailing & begining spaces */ 662 char *remove_spaces(char *p) 663 { 664 char *save = p; 665 p += strlen(p) - 1; 666 while (*p && *p <= ' ') { 667 *p = '\0'; 668 p--; 669 } 670 p = save; 671 while (*p && *p <= ' ') { 672 p++; 673 } 674 675 return p; 676 } 677 678 /* remove trailing LF */ 679 char *remove_trailing_lf(char *p) 680 { 681 char *save = p; 682 p += strlen(p) - 1; 683 while (*p && *p == 10) { 684 *p = '\0'; 685 p--; 686 } 687 p = save; 688 689 return p; 690 } 691 692 /* delete multiple spaces, one is enough */ 693 char *del_multi_spaces(char *p) 694 { 695 /* Saving the original pointer */ 696 char *save = p; 697 698 /* Let's parse the complete string 699 * As we search for a double spacing 700 * we have to be sure then string is 701 * long enough to be processed */ 702 while (*p && *(p + 1)) { 703 704 /* If we have two consecutive spaces */ 705 if ((*p == ' ') && (*(p + 1) == ' ')) { 706 707 /* Let's copy to the current position 708 * the content from the second space*/ 709 strlcpy(p, p + 1, strlen(p + 1)); 710 711 /* Don't increment the pointer as we 712 * changed the content of the current position*/ 713 continue; 714 } 715 716 /* Nothing as been found, let's see on the next char */ 717 p++; 718 } 719 /* Returning the original pointer */ 720 return save; 721 } 722 723 /* Reset the more_printf counter */ 724 void reset_more_printf(void) 725 { 726 display_line_nb = 0; 727 } 728 729 int draw_background(const char *what) 730 { 731 if (!what) 732 return vesacon_default_background(); 733 else 734 return vesacon_load_background(what); 735 } 736 737 void init_console(struct s_hardware *hardware) 738 { 739 if (vesamode) { 740 openconsole(&dev_rawcon_r, &dev_vesaserial_w); 741 draw_background(hardware->vesa_background); 742 } else 743 console_ansi_raw(); 744 } 745 746 void detect_hardware(struct s_hardware *hardware) 747 { 748 if (!quiet) 749 more_printf("ACPI: Detecting\n"); 750 detect_acpi(hardware); 751 752 if (!quiet) 753 more_printf("MEMORY: Detecting\n"); 754 detect_memory(hardware); 755 756 if (!quiet) 757 more_printf("DMI: Detecting Table\n"); 758 if (detect_dmi(hardware) == -ENODMITABLE) { 759 more_printf("DMI: ERROR ! Table not found ! \n"); 760 more_printf("DMI: Many hardware components will not be detected ! \n"); 761 } else { 762 if (!quiet) 763 more_printf("DMI: Table found ! (version %u.%u)\n", 764 hardware->dmi.dmitable.major_version, 765 hardware->dmi.dmitable.minor_version); 766 } 767 768 if (!quiet) 769 more_printf("CPU: Detecting\n"); 770 cpu_detect(hardware); 771 772 if (!quiet) 773 more_printf("DISKS: Detecting\n"); 774 detect_disks(hardware); 775 776 if (!quiet) 777 more_printf("VPD: Detecting\n"); 778 detect_vpd(hardware); 779 780 detect_pci(hardware); 781 if (!quiet) 782 more_printf("PCI: %d Devices Found\n", hardware->nb_pci_devices); 783 784 if (!quiet) 785 more_printf("PXE: Detecting\n"); 786 detect_pxe(hardware); 787 788 if (!quiet) 789 more_printf("VESA: Detecting\n"); 790 detect_vesa(hardware); 791 } 792 793