VirtualBox

Changeset 6291 in vbox for trunk/src/VBox/Devices/PC


Ignore:
Timestamp:
Jan 9, 2008 10:57:05 AM (17 years ago)
Author:
vboxsync
Message:

Big virtual disk changeset containing several modifications

  • remove the always buggy translation setting and replace it with two sets of geometries, physical and logical
  • complete vmdk creation (fixed/dynamic variants, both split in 2G chunks and single file)
  • implemented VBoxHDD-new generic snapshot support, i.e. diff image creation and image merging (completely untested, I'm pretty sure there are bugs)
  • assorted changes which generalize the VBoxHDD-new interfaces (both externally and internally)
Location:
trunk/src/VBox/Devices/PC
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/BIOS/rombios.c

    r5757 r6291  
    9393//   - EBDA segment.
    9494//     I used memory starting at 0x121 in the segment
     95#ifndef VBOX
    9596//   - the translation policy is defined in cmos regs 0x39 & 0x3a
     97#endif /* !VBOX */
    9698//
    9799// TODO :
     
    202204#if BX_APM && BX_CPU<3
    203205#    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
    204210#endif
    205211
     
    23902396      Bit32u sectors;
    23912397      Bit16u cylinders, heads, spt, blksize;
     2398#ifdef VBOX
     2399      Bit16u lcylinders, lheads, lspt;
     2400      Bit8u chsgeo_base;
     2401#endif /* VBOX */
    23922402      Bit8u  translation, removable, mode;
    23932403
     
    24162426      if (sectors == 268435455)
    24172427        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      }
    24182457#endif /* VBOX */
    24192458
     
    24262465      write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt);
    24272466      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 */
    24282472      BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt);
    24292473
     
    24362480      switch (translation) {
    24372481        case ATA_TRANSLATION_NONE:
    2438 #ifndef VBOX
    24392482          BX_INFO("none");
    2440 #else /* VBOX */
    2441           bios_printf(BIOS_PRINTF_INFO, "none");
    2442 #endif /* VBOX */
    24432483          break;
    24442484        case ATA_TRANSLATION_LBA:
    2445 #ifndef VBOX
    24462485          BX_INFO("lba");
    2447 #else /* VBOX */
    2448           bios_printf(BIOS_PRINTF_INFO, "lba");
    2449 #endif /* VBOX */
    24502486          break;
    24512487        case ATA_TRANSLATION_LARGE:
    2452 #ifndef VBOX
    24532488          BX_INFO("large");
    2454 #else /* VBOX */
    2455           bios_printf(BIOS_PRINTF_INFO, "large");
    2456 #endif /* VBOX */
    24572489          break;
    24582490        case ATA_TRANSLATION_RECHS:
    2459 #ifndef VBOX
    24602491          BX_INFO("r-echs");
    2461 #else /* VBOX */
    2462           bios_printf(BIOS_PRINTF_INFO, "r-echs");
    2463 #endif /* VBOX */
    24642492          break;
    24652493        }
     
    24982526      // clip to 1024 cylinders in lchs
    24992527      if (cylinders > 1024) cylinders=1024;
    2500 #ifndef VBOX
    25012528      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 */
    25052529
    25062530      write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, heads);
    25072531      write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, cylinders);
    25082532      write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, spt);
     2533#endif /* VBOX */
    25092534
    25102535      // fill hdidmap
  • trunk/src/VBox/Devices/PC/DevPcBios.cpp

    r5999 r6291  
    55
    66/*
    7  * Copyright (C) 2006-2007 innotek GmbH
     7 * Copyright (C) 2006-2008 innotek GmbH
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    265265__END_DECLS
    266266
     267/* Attempt to guess the LCHS disk geometry from the MS-DOS master boot
     268 * record (partition table). */
     269static 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
    267308
    268309/**
     
    293334static void pcbiosCmosInitHardDisk(PPDMDEVINS pDevIns, int offType, int offInfo, PPDMIBLOCKBIOS pBlockBios)
    294335{
    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);
    319363}
    320364
     
    450494    switch (u32)
    451495    {
    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. */
    454497        default:u32 = 0;    break;      /* floppy not installed. */
    455498    }
     
    468511        if (VBOX_SUCCESS(rc))
    469512            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;
    485517        if (apHDs[i])
    486518        {
    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)
    490528            {
    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);
    493533                if (VBOX_FAILURE(rc))
    494534                {
    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);
    497537                }
    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)
    499545                {
    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
    502574                }
    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);
    513577            }
    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__));
    532601    return VINF_SUCCESS;
    533602}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette