Index: trunk/src/VBox/Devices/PC/BIOS/ata.c
===================================================================
--- trunk/src/VBox/Devices/PC/BIOS/ata.c	(revision 100366)
+++ trunk/src/VBox/Devices/PC/BIOS/ata.c	(revision 100443)
@@ -659,4 +659,23 @@
                 sum = -sum;
                 fdpt->csum = sum;
+
+                /* Read the drive type from the CMOS. If it is one of the old
+                 * IBM compatible drive types (rather than Type 47 or so), point
+                 * INT 41h/46h at the drive table in ROM.
+                 * This is required for some old guests which look at INT 41h/46h,
+                 * but either insist that it point to a high segment (NetWare 2.x)
+                 * or wipe out all RAM (286 XENIX 2.1.3/2.2.1).
+                 */
+                i   = inb_cmos(0x12);
+                i >>= ((1 - device) * 4);
+                i  &= 0x0f;
+                if (i == 0xf)
+                    i = inb_cmos(0x19 + device);
+
+                if (i <= 23) {  // Should be in sync with DevPcBios.cpp
+                    fdpt = MK_FP(0xF000, 0xE401);
+                    fdpt += i - 1;
+                    *int_vec = fdpt;
+                }
             }
 
Index: trunk/src/VBox/Devices/PC/DevPcBios.cpp
===================================================================
--- trunk/src/VBox/Devices/PC/DevPcBios.cpp	(revision 100366)
+++ trunk/src/VBox/Devices/PC/DevPcBios.cpp	(revision 100443)
@@ -595,4 +595,88 @@
 
 
+/* Several common PC/AT BIOS drive types. Corresponds to IBM BIOS drive tables. */
+PDMMEDIAGEOMETRY aGeomPCAT[] = {
+    /*  cyls    heads   sectors */
+    {     0,     0,      0 },   /* Type  0 is not used */
+    {   306,     4,     17 },   /* Type  1,  10MB */
+    {   615,     4,     17 },   /* Type  2,  20MB */
+    {   615,     6,     17 },   /* Type  3,  30MB */
+    {   940,     8,     17 },   /* Type  4,  62MB */
+    {   940,     6,     17 },   /* Type  5,  47MB */
+    {   615,     4,     17 },   /* Type  6,  20MB (different WPCOMP from Type 2) */
+    {   462,     8,     17 },   /* Type  7,  30MB */
+    {   733,     5,     17 },   /* Type  8,  30MB */
+    {   900,    15,     17 },   /* Type  9, 117MB */
+
+    {   820,     3,     17 },   /* Type 10,  21MB */
+    {   855,     5,     17 },   /* Type 11,  37MB */
+    {   855,     7,     17 },   /* Type 12,  52MB */
+    {   306,     8,     17 },   /* Type 13,  21MB */
+    {   733,     7,     17 },   /* Type 14,  45MB */
+    {     0,     0,      0 },   /* Type 15 is not used */
+    {   612,     4,     17 },   /* Type 16,  21MB */
+    {   977,     5,     17 },   /* Type 17,  43MB */
+    {   977,     7,     17 },   /* Type 18,  60MB */
+    {  1024,     7,     17 },   /* Type 19,  62MB */
+
+    {   733,     5,     17 },   /* Type 20,  32MB */
+    {   733,     7,     17 },   /* Type 21,  45MB */
+    {   733,     5,     17 },   /* Type 22,  32MB */
+    {   306,     4,     17 },   /* Type 23,  10MB */
+};
+
+/**
+ * Attempts to initialize CMOS data for a hard disk matching one of
+ * the PC/AT BIOS types. Only applicable to the first two drives.
+ * Returns true if drive is one of the few recognized types.
+ */
+static bool pcbiosCmosTryPCATHardDisk(PPDMDEVINS pDevIns, int drive, PCPDMMEDIAGEOMETRY pLCHSGeometry)
+{
+    int     type;
+    int     typeLow;
+    bool    fCompatGeom = false;
+
+    Assert((drive == 0) || (drive == 1));
+
+    /* See if drive geometry is one of the ancient PC/AT BIOS types. */
+    for (type = 0; type < RT_ELEMENTS(aGeomPCAT); ++type) {
+        if ( (aGeomPCAT[type].cCylinders == pLCHSGeometry->cCylinders)
+          && (aGeomPCAT[type].cHeads     == pLCHSGeometry->cHeads    )
+          && (aGeomPCAT[type].cSectors   == pLCHSGeometry->cSectors  )) {
+            LogRel(("PcBios: Recognized ATA hard disk %d as PC/AT BIOS type %d\n", drive, type));
+            fCompatGeom = true;
+            break;
+        }
+    }
+
+    if (fCompatGeom) {
+        uint32_t    u32;
+
+        /* For types below 15, the type is in CMOS byte 0x12.
+         * NB: The type for drive 0 is in the high nibble, drive 1
+         * is in the low nibble.
+         * For drive types above 15, CMOS byte 0x12 is set to 15
+         * and actual drive type is in byte 0x19 (drive 0) or
+         * byte 0x1a (drive 1).
+         */
+        typeLow = type < 15 ? type : 15;
+
+        /* Always update CMOS byte 0x12. */
+        u32 = pcbiosCmosRead(pDevIns, 0x12);
+        u32 &= 0x0f << (4 * drive);
+        u32 |= typeLow << (4 - 4 * drive);
+        pcbiosCmosWrite(pDevIns, 0x12, u32);
+
+        /* For higher drive types, also update CMOS byte 0x19/0x1a. */
+        if (type > 15) {
+            u32 = type;
+            pcbiosCmosWrite(pDevIns, 0x19 + drive, u32);
+        }
+    }
+
+    return fCompatGeom;
+}
+
+
 /**
  * Initializes the CMOS data for one harddisk.
@@ -601,6 +685,20 @@
 {
     Log2(("%s: offInfo=%#x: LCHS=%d/%d/%d\n", __FUNCTION__, offInfo, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
-    if (offType)
+    if (offType) {
+        uint32_t    u32;
+        int         drive;
+
+        Assert(offType == 0x1a || offType == 0x19);
+        drive = offType == 0x19 ? 0 : 1;
+
+        /* Update CMOS byte 12h. It will always be set to type 0fh for this disk. */
+        u32 = pcbiosCmosRead(pDevIns, 0x12);
+        u32 &= 0x0f << (4 * drive);
+        u32 |= 0x0f << (4 - 4 * drive);
+        pcbiosCmosWrite(pDevIns, 0x12, u32);
+
+        /* Now write the extended drive type at offset 19h or 1Ah. */
         pcbiosCmosWrite(pDevIns, offType, 47);
+    }
     /* Cylinders low */
     pcbiosCmosWrite(pDevIns, offInfo + 0, RT_MIN(pLCHSGeometry->cCylinders, 1024) & 0xff);
@@ -951,14 +1049,11 @@
                         break;
                 }
-                pcbiosCmosInitHardDisk(pDevIns, offType, offInfo,
-                                       &LCHSGeometry);
+                pcbiosCmosInitHardDisk(pDevIns, offType, offInfo, &LCHSGeometry);
+                if (i < 2)
+                    pcbiosCmosTryPCATHardDisk(pDevIns, i, &LCHSGeometry);
             }
             LogRel(("PcBios: ATA LUN#%d LCHS=%u/%u/%u\n", i, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors));
         }
     }
-
-    /* 0Fh means extended and points to 19h, 1Ah */
-    u32 = (apHDs[0] ? 0xf0 : 0) | (apHDs[1] ? 0x0f : 0);
-    pcbiosCmosWrite(pDevIns, 0x12, u32);
 
     /*
