Changeset 6291 in vbox for trunk/src/VBox/Devices/PC
- Timestamp:
- Jan 9, 2008 10:57:05 AM (17 years ago)
- Location:
- trunk/src/VBox/Devices/PC
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/BIOS/rombios.c
r5757 r6291 93 93 // - EBDA segment. 94 94 // I used memory starting at 0x121 in the segment 95 #ifndef VBOX 95 96 // - the translation policy is defined in cmos regs 0x39 & 0x3a 97 #endif /* !VBOX */ 96 98 // 97 99 // TODO : … … 202 204 #if BX_APM && BX_CPU<3 203 205 # error APM BIOS can only be used with 386+ cpu 206 #endif 207 208 #if defined(VBOX) && !BX_USE_ATADRV 209 # error VBOX requires enabling the ATA/ATAPI driver 204 210 #endif 205 211 … … 2390 2396 Bit32u sectors; 2391 2397 Bit16u cylinders, heads, spt, blksize; 2398 #ifdef VBOX 2399 Bit16u lcylinders, lheads, lspt; 2400 Bit8u chsgeo_base; 2401 #endif /* VBOX */ 2392 2402 Bit8u translation, removable, mode; 2393 2403 … … 2416 2426 if (sectors == 268435455) 2417 2427 sectors = read_dword(get_SS(),buffer+(100*2)); // words 100 to 103 (someday) 2428 switch (device) 2429 { 2430 case 0: 2431 chsgeo_base = 0x1e; 2432 break; 2433 case 1: 2434 chsgeo_base = 0x26; 2435 break; 2436 case 2: 2437 chsgeo_base = 0x67; 2438 break; 2439 case 3: 2440 chsgeo_base = 0x70; 2441 break; 2442 default: 2443 chsgeo_base = 0; 2444 } 2445 if (chsgeo_base != 0) 2446 { 2447 lcylinders = inb_cmos(chsgeo_base) + (inb_cmos(chsgeo_base+1) << 8); 2448 lheads = inb_cmos(chsgeo_base+2); 2449 lspt = inb_cmos(chsgeo_base+7); 2450 } 2451 else 2452 { 2453 lcylinders = 0; 2454 lheads = 0; 2455 lspt = 0; 2456 } 2418 2457 #endif /* VBOX */ 2419 2458 … … 2426 2465 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt); 2427 2466 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors, sectors); 2467 #ifdef VBOX 2468 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, lheads); 2469 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, lcylinders); 2470 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, lspt); 2471 #else /* !VBOX */ 2428 2472 BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt); 2429 2473 … … 2436 2480 switch (translation) { 2437 2481 case ATA_TRANSLATION_NONE: 2438 #ifndef VBOX2439 2482 BX_INFO("none"); 2440 #else /* VBOX */2441 bios_printf(BIOS_PRINTF_INFO, "none");2442 #endif /* VBOX */2443 2483 break; 2444 2484 case ATA_TRANSLATION_LBA: 2445 #ifndef VBOX2446 2485 BX_INFO("lba"); 2447 #else /* VBOX */2448 bios_printf(BIOS_PRINTF_INFO, "lba");2449 #endif /* VBOX */2450 2486 break; 2451 2487 case ATA_TRANSLATION_LARGE: 2452 #ifndef VBOX2453 2488 BX_INFO("large"); 2454 #else /* VBOX */2455 bios_printf(BIOS_PRINTF_INFO, "large");2456 #endif /* VBOX */2457 2489 break; 2458 2490 case ATA_TRANSLATION_RECHS: 2459 #ifndef VBOX2460 2491 BX_INFO("r-echs"); 2461 #else /* VBOX */2462 bios_printf(BIOS_PRINTF_INFO, "r-echs");2463 #endif /* VBOX */2464 2492 break; 2465 2493 } … … 2498 2526 // clip to 1024 cylinders in lchs 2499 2527 if (cylinders > 1024) cylinders=1024; 2500 #ifndef VBOX2501 2528 BX_INFO(" LCHS=%d/%d/%d\n", cylinders, heads, spt); 2502 #else /* VBOX */2503 bios_printf(BIOS_PRINTF_INFO, " LCHS=%d/%d/%d\n", cylinders, heads, spt);2504 #endif /* VBOX */2505 2529 2506 2530 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, heads); 2507 2531 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, cylinders); 2508 2532 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, spt); 2533 #endif /* VBOX */ 2509 2534 2510 2535 // fill hdidmap -
trunk/src/VBox/Devices/PC/DevPcBios.cpp
r5999 r6291 5 5 6 6 /* 7 * Copyright (C) 2006-200 7innotek GmbH7 * Copyright (C) 2006-2008 innotek GmbH 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 265 265 __END_DECLS 266 266 267 /* Attempt to guess the LCHS disk geometry from the MS-DOS master boot 268 * record (partition table). */ 269 static int biosGuessDiskLCHS(PPDMIBLOCK pBlock, PPDMMEDIAGEOMETRY pLCHSGeometry) 270 { 271 uint8_t aMBR[512], *p; 272 int rc; 273 uint32_t iEndHead, iEndSector, cLCHSCylinders, cLCHSHeads, cLCHSSectors; 274 275 if (!pBlock) 276 return VERR_INVALID_PARAMETER; 277 rc = pBlock->pfnRead(pBlock, 0, aMBR, sizeof(aMBR)); 278 if (VBOX_FAILURE(rc)) 279 return rc; 280 /* Test MBR magic number. */ 281 if (aMBR[510] != 0x55 || aMBR[511] != 0xaa) 282 return VERR_INVALID_PARAMETER; 283 for (uint32_t i = 0; i < 4; i++) 284 { 285 /* Figure out the start of a partition table entry. */ 286 p = &aMBR[0x1be + i * 16]; 287 iEndHead = p[5]; 288 iEndSector = p[6] & 63; 289 if ((p[12] | p[13] | p[14] | p[15]) && iEndSector & iEndHead) 290 { 291 /* Assumption: partition terminates on a cylinder boundary. */ 292 cLCHSHeads = iEndHead + 1; 293 cLCHSSectors = iEndSector; 294 cLCHSCylinders = pBlock->pfnGetSize(pBlock) / (512 * cLCHSHeads * cLCHSSectors); 295 if (cLCHSCylinders >= 1) 296 { 297 pLCHSGeometry->cCylinders = cLCHSCylinders; 298 pLCHSGeometry->cHeads = cLCHSHeads; 299 pLCHSGeometry->cSectors = cLCHSSectors; 300 Log(("%s: LCHS=%d %d %d\n", __FUNCTION__, cLCHSCylinders, cLCHSHeads, cLCHSSectors)); 301 return VINF_SUCCESS; 302 } 303 } 304 } 305 return VERR_INVALID_PARAMETER; 306 } 307 267 308 268 309 /** … … 293 334 static void pcbiosCmosInitHardDisk(PPDMDEVINS pDevIns, int offType, int offInfo, PPDMIBLOCKBIOS pBlockBios) 294 335 { 295 if ( pBlockBios->pfnGetType(pBlockBios) == PDMBLOCKTYPE_HARD_DISK 296 && pBlockBios->pfnIsVisible(pBlockBios)) 297 { 298 uint32_t cCylinders; 299 uint32_t cHeads; 300 uint32_t cSectors; 301 int rc = pBlockBios->pfnGetGeometry(pBlockBios, &cCylinders, &cHeads, &cSectors); 302 if (VBOX_SUCCESS(rc)) 303 { 304 Log2(("pcbiosCmosInitHardDisk: offInfo=%#x: CHS=%d/%d/%d\n", offInfo, cCylinders, cHeads, cSectors)); 305 pcbiosCmosWrite(pDevIns, offType, 47); /* 19h - First Extended Hard Disk Drive Type */ 306 pcbiosCmosWrite(pDevIns, offInfo + 0, RT_MIN(cCylinders, 16383) & 0xff); /* 1Bh - (AMI) First Hard Disk (type 47) user defined: # of Cylinders, LSB */ 307 pcbiosCmosWrite(pDevIns, offInfo + 1, RT_MIN(cCylinders, 16383) >> 8); /* 1Ch - (AMI) First Hard Disk user defined: # of Cylinders, High Byte */ 308 pcbiosCmosWrite(pDevIns, offInfo + 2, cHeads); /* 1Dh - (AMI) First Hard Disk user defined: Number of Heads */ 309 pcbiosCmosWrite(pDevIns, offInfo + 3, 0xff); /* 1Eh - (AMI) First Hard Disk user defined: Write Precompensation Cylinder, Low Byte */ 310 pcbiosCmosWrite(pDevIns, offInfo + 4, 0xff); /* 1Fh - (AMI) First Hard Disk user defined: Write Precompensation Cylinder, High Byte */ 311 pcbiosCmosWrite(pDevIns, offInfo + 5, 0xc0 | ((cHeads > 8) << 3)); /* 20h - (AMI) First Hard Disk user defined: Control Byte */ 312 pcbiosCmosWrite(pDevIns, offInfo + 6, 0xff); /* 21h - (AMI) First Hard Disk user defined: Landing Zone, Low Byte */ 313 pcbiosCmosWrite(pDevIns, offInfo + 7, 0xff); /* 22h - (AMI) First Hard Disk user defined: Landing Zone, High Byte */ 314 pcbiosCmosWrite(pDevIns, offInfo + 8, cSectors); /* 23h - (AMI) First Hard Disk user defined: # of Sectors per track */ 315 return; 316 } 317 } 318 pcbiosCmosWrite(pDevIns, offType, 0); 336 PDMMEDIAGEOMETRY LCHSGeometry; 337 int rc = pBlockBios->pfnGetLCHSGeometry(pBlockBios, &LCHSGeometry); 338 if (VBOX_SUCCESS(rc)) 339 { 340 Log2(("%s: offInfo=%#x: LCHS=%d/%d/%d\n", __FUNCTION__, offInfo, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors)); 341 if (offType) 342 pcbiosCmosWrite(pDevIns, offType, 48); 343 /* Cylinders low */ 344 pcbiosCmosWrite(pDevIns, offInfo + 0, RT_MIN(LCHSGeometry.cCylinders, 1024) & 0xff); 345 /* Cylinders high */ 346 pcbiosCmosWrite(pDevIns, offInfo + 1, RT_MIN(LCHSGeometry.cCylinders, 1024) >> 8); 347 /* Heads */ 348 pcbiosCmosWrite(pDevIns, offInfo + 2, LCHSGeometry.cHeads); 349 /* Landing zone low */ 350 pcbiosCmosWrite(pDevIns, offInfo + 3, 0xff); 351 /* Landing zone high */ 352 pcbiosCmosWrite(pDevIns, offInfo + 4, 0xff); 353 /* Write precomp low */ 354 pcbiosCmosWrite(pDevIns, offInfo + 5, 0xff); 355 /* Write precomp high */ 356 pcbiosCmosWrite(pDevIns, offInfo + 6, 0xff); 357 /* Sectors */ 358 pcbiosCmosWrite(pDevIns, offInfo + 7, LCHSGeometry.cSectors); 359 return; 360 } 361 if (offType) 362 pcbiosCmosWrite(pDevIns, offType, 0); 319 363 } 320 364 … … 450 494 switch (u32) 451 495 { 452 case 1: u32 = 0x01; break; /* floppy installed, 1 drive. */ 453 case 2: u32 = 0x41; break; /* floppy installed, 2 drives. */ 496 case 1: u32 = 0x01; break; /* floppy installed, 2 drives. */ 454 497 default:u32 = 0; break; /* floppy not installed. */ 455 498 } … … 468 511 if (VBOX_SUCCESS(rc)) 469 512 apHDs[i] = (PPDMIBLOCKBIOS)pBase->pfnQueryInterface(pBase, PDMINTERFACE_BLOCK_BIOS); 470 } 471 472 u32 = (apHDs[0] ? 0xf0 : 0) | (apHDs[1] ? 0x0f : 0); /* 0Fh means extended and points to 1Ah, 1Bh */ 473 pcbiosCmosWrite(pDevIns, 0x12, u32); /* 12h - Hard Disk Data (type) */ 474 if (apHDs[0]) 475 pcbiosCmosInitHardDisk(pDevIns, 0x19, 0x1b, apHDs[0]); /* 19h - First Extended Hard Disk Drive Type */ 476 if (apHDs[1]) 477 pcbiosCmosInitHardDisk(pDevIns, 0x1a, 0x24, apHDs[1]); /* 1Ah - Second Extended Hard Disk Drive Type */ 478 479 /* 480 * Translation type - Bochs BIOS specific. 481 */ 482 u32 = 0; 483 for (i = 0; i < 4; i++) 484 { 513 if ( apHDs[i] 514 && ( apHDs[i]->pfnGetType(apHDs[i]) != PDMBLOCKTYPE_HARD_DISK 515 || !apHDs[i]->pfnIsVisible(apHDs[i]))) 516 apHDs[i] = NULL; 485 517 if (apHDs[i]) 486 518 { 487 PDMBIOSTRANSLATION enmTranslation; 488 int rc = apHDs[i]->pfnGetTranslation(apHDs[i], &enmTranslation); 489 if (VBOX_FAILURE(rc) || enmTranslation == PDMBIOSTRANSLATION_AUTO) 519 PDMMEDIAGEOMETRY LCHSGeometry; 520 int rc = apHDs[i]->pfnGetLCHSGeometry(apHDs[i], &LCHSGeometry); 521 if ( rc == VERR_PDM_GEOMETRY_NOT_SET 522 || LCHSGeometry.cCylinders == 0 523 || LCHSGeometry.cCylinders > 1024 524 || LCHSGeometry.cHeads == 0 525 || LCHSGeometry.cHeads > 255 526 || LCHSGeometry.cSectors == 0 527 || LCHSGeometry.cSectors > 63) 490 528 { 491 uint32_t cCylinders, cHeads, cSectors; 492 rc = apHDs[i]->pfnGetGeometry(apHDs[i], &cCylinders, &cHeads, &cSectors); 529 PPDMIBLOCK pBlock; 530 pBlock = (PPDMIBLOCK)pBase->pfnQueryInterface(pBase, PDMINTERFACE_BLOCK); 531 /* No LCHS geometry, autodetect and set. */ 532 rc = biosGuessDiskLCHS(pBlock, &LCHSGeometry); 493 533 if (VBOX_FAILURE(rc)) 494 534 { 495 AssertMsg(rc == VERR_PDM_MEDIA_NOT_MOUNTED, ("This shouldn't happen! rc=%Vrc\n", rc));496 enmTranslation = PDMBIOSTRANSLATION_NONE;535 /* Try if PCHS geometry works, otherwise fall back. */ 536 rc = apHDs[i]->pfnGetPCHSGeometry(apHDs[i], &LCHSGeometry); 497 537 } 498 else if (cCylinders <= 1024 && cHeads <= 16 && cSectors <= 63) 538 if ( VBOX_FAILURE(rc) 539 || LCHSGeometry.cCylinders == 0 540 || LCHSGeometry.cCylinders > 1024 541 || LCHSGeometry.cHeads == 0 542 || LCHSGeometry.cHeads > 16 543 || LCHSGeometry.cSectors == 0 544 || LCHSGeometry.cSectors > 63) 499 545 { 500 /* Disk <= 512 MByte not needing LBA translation. */ 501 enmTranslation = PDMBIOSTRANSLATION_NONE; 546 uint64_t cSectors = pBlock->pfnGetSize(pBlock) / 512; 547 if (cSectors / 16 / 63 <= 1024) 548 { 549 LCHSGeometry.cCylinders = RT_MAX(cSectors / 16 / 63, 1); 550 LCHSGeometry.cHeads = 16; 551 } 552 else if (cSectors / 32 / 63 <= 1024) 553 { 554 LCHSGeometry.cCylinders = RT_MAX(cSectors / 32 / 63, 1); 555 LCHSGeometry.cHeads = 32; 556 } 557 else if (cSectors / 64 / 63 <= 1024) 558 { 559 LCHSGeometry.cCylinders = cSectors / 64 / 63; 560 LCHSGeometry.cHeads = 64; 561 } 562 else if (cSectors / 128 / 63 <= 1024) 563 { 564 LCHSGeometry.cCylinders = cSectors / 128 / 63; 565 LCHSGeometry.cHeads = 128; 566 } 567 else 568 { 569 LCHSGeometry.cCylinders = RT_MIN(cSectors / 255 / 63, 1024); 570 LCHSGeometry.cHeads = 255; 571 } 572 LCHSGeometry.cSectors = 63; 573 502 574 } 503 else if (cSectors != 63 || (cHeads != 16 && cHeads != 32 && cHeads != 64 && cHeads != 128 && cHeads != 255)) 504 { 505 /* Disk with strange geometry. Using LBA here can 506 * break booting of the guest OS. Especially operating 507 * systems from Microsoft are sensitive to BIOS CHS not 508 * matching what the partition table says. */ 509 enmTranslation = PDMBIOSTRANSLATION_NONE; 510 } 511 else 512 enmTranslation = PDMBIOSTRANSLATION_LBA; 575 rc = apHDs[i]->pfnSetLCHSGeometry(apHDs[i], &LCHSGeometry); 576 AssertRC(rc); 513 577 } 514 switch (enmTranslation) 515 { 516 case PDMBIOSTRANSLATION_AUTO: /* makes gcc happy */ 517 case PDMBIOSTRANSLATION_NONE: 518 /* u32 |= 0 << (i * 2) */ 519 break; 520 default: 521 AssertMsgFailed(("bad enmTranslation=%d\n", enmTranslation)); 522 case PDMBIOSTRANSLATION_LBA: 523 u32 |= 1 << (i * 2); 524 break; 525 } 526 } 527 } 528 Log2(("pcbiosInitComplete: translation byte: %#02x\n", u32)); 529 pcbiosCmosWrite(pDevIns, 0x39, u32); 530 531 LogFlow(("pcbiosInitComplete: returns VINF_SUCCESS\n")); 578 LogRel(("DevPcBios: ATA LUN#%d LCHS=%u/%u/%u\n", i, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors)); 579 pcbiosCmosWrite(pDevIns, 0x40 + i * 4, LCHSGeometry.cCylinders & 0xff); 580 pcbiosCmosWrite(pDevIns, 0x41 + i * 4, LCHSGeometry.cCylinders >> 8); 581 pcbiosCmosWrite(pDevIns, 0x42 + i * 4, LCHSGeometry.cHeads & 0xff); 582 pcbiosCmosWrite(pDevIns, 0x43 + i * 4, LCHSGeometry.cSectors & 0xff); 583 } 584 } 585 586 /* 0Fh means extended and points to 19h, 1Ah */ 587 u32 = (apHDs[0] ? 0xf0 : 0) | (apHDs[1] ? 0x0f : 0); 588 pcbiosCmosWrite(pDevIns, 0x12, u32); 589 /* Award BIOS extended drive types for first and second disk, and 590 * extended drive types for third and fourth disk. Used by the BIOS. */ 591 if (apHDs[0]) 592 pcbiosCmosInitHardDisk(pDevIns, 0x19, 0x1e, apHDs[0]); 593 if (apHDs[1]) 594 pcbiosCmosInitHardDisk(pDevIns, 0x1a, 0x26, apHDs[1]); 595 if (apHDs[2]) 596 pcbiosCmosInitHardDisk(pDevIns, 0x00, 0x67, apHDs[2]); 597 if (apHDs[3]) 598 pcbiosCmosInitHardDisk(pDevIns, 0x00, 0x70, apHDs[3]); 599 600 LogFlow(("%s: returns VINF_SUCCESS\n", __FUNCTION__)); 532 601 return VINF_SUCCESS; 533 602 }
Note:
See TracChangeset
for help on using the changeset viewer.