Index: /trunk/src/VBox/Devices/PC/BIOS-new/ahci.c
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/ahci.c	(revision 39596)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/ahci.c	(revision 39597)
@@ -83,4 +83,8 @@
     /** Current port which uses the memory to communicate with the controller. */
     uint8_t         cur_port;
+    /** Current PRD index (for pre/post skip). */
+    uint8_t         cur_prd;
+    /** Physical address of the sink buffer (for pre/post skip). */
+    uint32_t        sink_buf_phys;
     /** VDS EDDS DMA buffer descriptor structure. */
     vds_edds        edds;
@@ -235,5 +239,5 @@
  * Issues a command to the SATA controller and waits for completion.
  */
-static void ahci_port_cmd_sync(ahci_t __far *ahci, uint8_t val, uint16_t cbData)
+static void ahci_port_cmd_sync(ahci_t __far *ahci, uint8_t val)
 {
     uint16_t        io_base;
@@ -246,6 +250,6 @@
     {
         /* Prepare the command header. */
-        ahci->aCmdHdr[0] = RT_BIT_32(16) | RT_BIT_32(7) | val;
-        ahci->aCmdHdr[1] = 0; //cbData;  //@todo: Is this really an input parameter?
+        ahci->aCmdHdr[0] = ((uint32_t)ahci->cur_prd << 16) | RT_BIT_32(7) | val;
+        ahci->aCmdHdr[1] = 0;
         ahci->aCmdHdr[2] = ahci_addr_to_phys(&ahci->abCmd[0]);
 
@@ -286,4 +290,5 @@
     uint16_t        n_sect = bios_dsk->drqp.nsect;
     uint16_t        sectsz = bios_dsk->drqp.sect_sz;
+    uint16_t        prdt_idx;
 
     _fmemset(&ahci->abCmd[0], 0, sizeof(ahci->abCmd));
@@ -310,11 +315,24 @@
     /* Lock memory needed for DMA. */
     ahci->edds.num_avail = NUM_EDDS_SG;
+    DBG_AHCI("AHCI: S/G list for %lu bytes (skip %u)\n", 
+             (uint32_t)n_sect * sectsz, bios_dsk->drqp.skip_a);
     vds_build_sg_list(&ahci->edds, bios_dsk->drqp.buffer, (uint32_t)n_sect * sectsz);
 
+    prdt_idx = ahci->cur_prd;
+
     /* Set up the PRDT. */
-    ahci->aPrdt[0].phys_addr = ahci->edds.u.sg[0].phys_addr;
-    ahci->aPrdt[0].len       = ahci->edds.u.sg[0].size - 1;
-
-    /* Build variable part first of command dword (reuses 'cmd'). */
+    ahci->aPrdt[prdt_idx].len       = ahci->edds.u.sg[prdt_idx].size - 1;
+    ahci->aPrdt[prdt_idx].phys_addr = ahci->edds.u.sg[prdt_idx].phys_addr;
+    ++prdt_idx;
+
+    if (bios_dsk->drqp.skip_a) {
+        ahci->aPrdt[prdt_idx].len       = bios_dsk->drqp.skip_a - 1;
+        ahci->aPrdt[prdt_idx].phys_addr = ahci->sink_buf_phys;
+        ++prdt_idx;
+    }
+
+    ahci->cur_prd = prdt_idx;
+
+    /* Build variable part of first command DWORD (reuses 'cmd'). */
     if (cmd == AHCI_CMD_WRITE_DMA_EXT)
         cmd = RT_BIT_32(6);     /* Indicate a write to device. */
@@ -327,5 +345,5 @@
     cmd |= 5;   /* Five DWORDs. */
 
-    ahci_port_cmd_sync(ahci, cmd, n_sect * sectsz);
+    ahci_port_cmd_sync(ahci, cmd);
 
     /* Unlock the buffer again. */
@@ -422,4 +440,5 @@
 
     ahci->cur_port = u8Port;
+    ahci->cur_prd  = 0;
 }
 
@@ -481,5 +500,5 @@
 
 uint16_t ahci_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf, 
-                         uint16_t header, uint32_t length, uint8_t inout, char __far *buffer)
+                         uint16_t skip_b, uint32_t length, uint8_t inout, char __far *buffer)
 {
     bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
@@ -492,7 +511,7 @@
     }
 
-    /* The header length must be even. */
-    if (header & 1) {
-        DBG_AHCI("%s: header must be even (%04x)\n", __func__, header);
+    /* The skip length must be even. */
+    if (skip_b & 1) {
+        DBG_AHCI("%s: skip must be even (%04x)\n", __func__, skip_b);
         return 1;
     }
@@ -501,6 +520,7 @@
     device_id = device_id - BX_MAX_ATA_DEVICES - BX_MAX_SCSI_DEVICES;
 
-    DBG_AHCI("%s: reading %lu bytes, header %u, device %d, port %d\n", __func__,
-             length, header, device_id, bios_dsk->ahcidev[device_id].port);
+    DBG_AHCI("%s: reading %lu bytes, skip %u/%u, device %d, port %d\n", __func__,
+             length, bios_dsk->drqp.skip_b, bios_dsk->drqp.skip_a, 
+             device_id, bios_dsk->ahcidev[device_id].port);
     DBG_AHCI("%s: reading %u %u-byte sectors\n", __func__,
              bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz);
@@ -520,4 +540,11 @@
     bios_dsk->drqp.trsfsectors = 0;
     bios_dsk->drqp.trsfbytes   = 0;
+
+    /* Set up a PRD entry to throw away the beginning of the transfer. */
+    if (bios_dsk->drqp.skip_b) {
+        ahci->aPrdt[0].len       = bios_dsk->drqp.skip_b - 1;
+        ahci->aPrdt[0].phys_addr = ahci->sink_buf_phys;
+        ahci->cur_prd++;
+    }
 
     ahci_cmd_data(bios_dsk, ATA_CMD_PACKET);
@@ -761,4 +788,9 @@
     ahci->iobase   = io_base;
 
+    /* Physical address of memory used for throwing away ATAPI data when reading 512-byte
+     * blocks from 2048-byte CD sectors.
+     */
+    ahci->sink_buf_phys = 0xCC000;  //@todo: find some better place!
+
     /* Reset the controller. */
     ahci_ctrl_set_bits(io_base, AHCI_REG_GHC, AHCI_GHC_HR);
Index: /trunk/src/VBox/Devices/PC/BIOS-new/ebda.h
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/ebda.h	(revision 39596)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/ebda.h	(revision 39597)
@@ -201,4 +201,6 @@
     uint16_t    trsfsectors;        /* Actual sectors transferred. */
     uint32_t    trsfbytes;          /* Actual bytes transferred. */
+    uint16_t    skip_b;             /* Bytes to skip before transfer. */
+    uint16_t    skip_a;             /* Bytes to skip after transfer. */
 } disk_req_t;
 
Index: /trunk/src/VBox/Devices/PC/BIOS-new/eltorito.c
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/eltorito.c	(revision 39596)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/eltorito.c	(revision 39597)
@@ -366,8 +366,13 @@
     bios_dsk->drqp.sect_sz = 512;
 
+    bios_dsk->drqp.skip_a = 2048 - nbsectors * 512L % 2048;
+
     if (device > BX_MAX_ATA_DEVICES)
         error = ahci_cmd_packet(device, 12, (char __far *)&atapicmd, 0, nbsectors*512L, ATA_DATA_IN, MK_FP(boot_segment,0));
     else
         error = ata_cmd_packet(device, 12, (char __far *)&atapicmd, 0, nbsectors*512L, ATA_DATA_IN, MK_FP(boot_segment,0));
+
+    bios_dsk->drqp.skip_a = 0;
+
     if (error != 0)
         return 12;
@@ -529,9 +534,9 @@
         
         // start lba on cd
-        slba  = (uint32_t)vlba/4;
-        before= (uint32_t)vlba%4;
+        slba   = (uint32_t)vlba / 4;
+        before = (uint32_t)vlba % 4;
         
         // end lba on cd
-        elba = (uint32_t)(vlba+nbsectors-1)/4;
+        elba = (uint32_t)(vlba + nbsectors - 1) / 4;
 
         _fmemset(&atapicmd, 0, sizeof(atapicmd));
@@ -543,8 +548,14 @@
         bios_dsk->drqp.sect_sz = 512;
 
+        bios_dsk->drqp.skip_b = before * 512;
+        bios_dsk->drqp.skip_a = 2048 - nbsectors * 512L % 2048 - bios_dsk->drqp.skip_b;
+
         if (device > BX_MAX_ATA_DEVICES)
             status = ahci_cmd_packet(device, 12, (char __far *)&atapicmd, before*512, nbsectors*512L, ATA_DATA_IN, MK_FP(segment,offset));
         else
             status = ata_cmd_packet(device, 12, (char __far *)&atapicmd, before*512, nbsectors*512L, ATA_DATA_IN, MK_FP(segment,offset));
+
+        bios_dsk->drqp.skip_b = 0;
+        bios_dsk->drqp.skip_a = 0;
 
         if (status != 0) {
