VirtualBox

Changeset 106027 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Sep 12, 2024 11:24:04 AM (3 months ago)
Author:
vboxsync
Message:

BIOS: Add the AHCI/SCSI data block to the EBDA to make the whole thing relocatable (see bugref:6549).

Location:
trunk/src/VBox/Devices/PC/BIOS
Files:
5 edited

Legend:

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

    r104068 r106027  
    348348static uint16_t ahci_cmd_data(bio_dsk_t __far *bios_dsk, uint8_t cmd)
    349349{
    350     ahci_t __far    *ahci  = bios_dsk->ahci_seg :> 0;
     350    ahci_t __far    *ahci  = (read_word(0x0040, 0x000E) + bios_dsk->ahci_ofs) :> 0;
    351351    uint16_t        n_sect = bios_dsk->drqp.nsect;
    352352    uint16_t        sectsz = bios_dsk->drqp.sect_sz;
     
    524524    uint16_t        device_id;
    525525    uint16_t        rc;
     526    uint16_t        ahci_seg = read_word(0x0040, 0x000E) + bios_dsk->ahci_ofs;
    526527
    527528    device_id = VBOX_GET_AHCI_DEVICE(bios_dsk->drqp.dev_id);
     
    533534             device_id, bios_dsk->ahcidev[device_id].port);
    534535
    535     high_bits_save(bios_dsk->ahci_seg :> 0);
    536     ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
     536    high_bits_save(ahci_seg :> 0);
     537    ahci_port_init(ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
    537538    rc = ahci_cmd_data(bios_dsk, AHCI_CMD_READ_DMA_EXT);
    538539    DBG_AHCI("%s: transferred %lu bytes\n", __func__, ((ahci_t __far *)(bios_dsk->ahci_seg :> 0))->aCmdHdr[1]);
     
    541542    rep_movsw(bios_dsk->drqp.buffer, bios_dsk->drqp.buffer, bios_dsk->drqp.nsect * 512 / 2);
    542543#endif
    543     high_bits_restore(bios_dsk->ahci_seg :> 0);
     544    high_bits_restore(ahci_seg :> 0);
    544545    return rc;
    545546}
     
    556557    uint16_t        device_id;
    557558    uint16_t        rc;
     559    uint16_t        ahci_seg = read_word(0x0040, 0x000E) + bios_dsk->ahci_ofs;
    558560
    559561    device_id = VBOX_GET_AHCI_DEVICE(bios_dsk->drqp.dev_id);
     
    565567             bios_dsk->ahcidev[device_id].port);
    566568
    567     high_bits_save(bios_dsk->ahci_seg :> 0);
    568     ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
     569    high_bits_save(ahci_seg :> 0);
     570    ahci_port_init(ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
    569571    rc = ahci_cmd_data(bios_dsk, AHCI_CMD_WRITE_DMA_EXT);
    570572    DBG_AHCI("%s: transferred %lu bytes\n", __func__, ((ahci_t __far *)(bios_dsk->ahci_seg :> 0))->aCmdHdr[1]);
    571573    bios_dsk->drqp.trsfsectors = bios_dsk->drqp.nsect;
    572     high_bits_restore(bios_dsk->ahci_seg :> 0);
     574    high_bits_restore(ahci_seg :> 0);
    573575    return rc;
    574576}
     
    582584                         uint32_t length, uint8_t inout, char __far *buffer)
    583585{
    584     bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
     586    uint16_t        ebda_seg = read_word(0x0040, 0x000E);
     587    bio_dsk_t __far *bios_dsk = ebda_seg :> &EbdaData->bdisk;
     588    uint16_t        ahci_seg = ebda_seg + bios_dsk->ahci_ofs;
    585589    ahci_t __far    *ahci;
    586590
     
    604608//    bios_dsk->drqp.sect_sz = 2048;
    605609
    606     ahci = bios_dsk->ahci_seg :> 0;
     610    ahci = ahci_seg :> 0;
    607611    high_bits_save(ahci);
    608612
    609     ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
     613    ahci_port_init(ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
    610614
    611615    /* Copy the ATAPI command where the HBA can fetch it. */
     
    825829
    826830/**
    827  * Allocates 1K of conventional memory.
    828  */
    829 static uint16_t ahci_mem_alloc(void)
    830 {
    831     uint16_t    base_mem_kb;
    832     uint16_t    ahci_seg;
    833 
    834     base_mem_kb = read_word(0x00, 0x0413);
    835 
    836     DBG_AHCI("AHCI: %dK of base mem\n", base_mem_kb);
    837 
    838     if (base_mem_kb == 0)
    839         return 0;
    840 
    841     base_mem_kb--; /* Allocate one block. */
    842     ahci_seg = (((uint32_t)base_mem_kb * 1024) >> 4); /* Calculate start segment. */
    843 
    844     write_word(0x00, 0x0413, base_mem_kb);
    845 
    846     return ahci_seg;
    847 }
    848 
    849 /**
    850831 * Initializes the AHCI HBA and detects attached devices.
    851832 */
     
    855836    uint32_t            val;
    856837    uint16_t            ebda_seg;
     838    uint16_t            ahci_ofs;
    857839    uint16_t            ahci_seg;
    858840    bio_dsk_t __far     *bios_dsk;
    859841    ahci_t __far        *ahci;
    860842
     843    /* Allocate 1K of base memory (this will move the EBDA). */
     844    ahci_ofs = ebda_mem_alloc(1/*KB*/);
     845    if (ahci_ofs == 0)
     846    {
     847        DBG_AHCI("AHCI: Could not allocate 1K of memory\n");
     848        return 0;
     849    }
    861850
    862851    ebda_seg = read_word(0x0040, 0x000E);
     852    ahci_seg = ebda_seg + ahci_ofs;
    863853    bios_dsk = ebda_seg :> &EbdaData->bdisk;
    864854
     
    868858             ahci_ctrl_extract_bits(val, 0x0000ffff,  0));
    869859
    870     /* Allocate 1K of base memory. */
    871     ahci_seg = ahci_mem_alloc();
    872     if (ahci_seg == 0)
    873     {
    874         DBG_AHCI("AHCI: Could not allocate 1K of memory, can't boot from controller\n");
    875         return 0;
    876     }
    877     DBG_AHCI("AHCI: ahci_seg=%04x, size=%04x, pointer at EBDA:%04x (EBDA size=%04x)\n",
    878              ahci_seg, sizeof(ahci_t), (uint16_t)&EbdaData->bdisk.ahci_seg, sizeof(ebda_data_t));
    879 
    880     bios_dsk->ahci_seg    = ahci_seg;
     860    DBG_AHCI("AHCI: ahci_ofs=%04x, size=%04x, pointer at EBDA:%04x (EBDA size=%04x)\n",
     861             ahci_ofs, sizeof(ahci_t), (uint16_t)&EbdaData->bdisk.ahci_ofs, sizeof(ebda_data_t));
     862
     863    bios_dsk->ahci_ofs    = ahci_ofs;
    881864    bios_dsk->ahci_devcnt = 0;
    882865
  • trunk/src/VBox/Devices/PC/BIOS/biosint.h

    r98103 r106027  
    283283extern  void        delay_boot(uint16_t secs);
    284284extern  bx_bool     set_enable_a20(bx_bool val);
     285extern  uint16_t    ebda_mem_alloc(int n_kb);
    285286
    286287#define printf(...)  bios_printf(BIOS_PRINTF_SCREEN, __VA_ARGS__)
  • trunk/src/VBox/Devices/PC/BIOS/ebda.h

    r104194 r106027  
    198198/* SCSI specific device information. */
    199199typedef struct {
    200     uint16_t    hba_seg;        /* Segment of HBA driver data block. */
     200    uint16_t    hba_ofs;        /* Offset (in paragraphs) of HBA driver data block within EBDA. */
    201201    uint8_t     idx_hba;        /* The HBA driver to use. */
    202202    uint8_t     target_id;      /* Target ID. */
     
    285285    ahci_dev_t  ahcidev[BX_MAX_AHCI_DEVICES];
    286286    uint8_t     ahci_devcnt;        /* Number of SATA devices. */
    287     uint16_t    ahci_seg;           /* Segment of AHCI data block. */
     287    uint16_t    ahci_ofs;           /* Offset (in paragraphs) of AHCI data block within EBDA. */
    288288#endif
    289289
  • trunk/src/VBox/Devices/PC/BIOS/post.c

    r98103 r106027  
    217217
    218218#endif
     219
     220/**
     221 * Allocate n KB of conventional memory at the end of the EBDA.
     222 * Returns offset (in paragraphs) to the allocated block within
     223 * the EBDA.
     224 *
     225 * NB: By default, the EBDA is 1KB in size, located at 639KB
     226 * into the start of memory (just below the video RAM). Optional
     227 * BIOS components may need additional real-mode addressable RAM
     228 * which is added to the EBDA.
     229 *
     230 * The EBDA should be relocatable as a whole. All pointers to
     231 * the EBDA must be relative, actual address is calculated from
     232 * the value at 40:0E.
     233 *
     234 * Items like PS/2 mouse support must be at a fixed offset from
     235 * the start of the EBDA. Therefore, any additional memory gets
     236 * allocated at the end and the original EBDA contents are
     237 * shifted down.
     238 *
     239 * WARNING: When successful, this function moves the EBDA!
     240 */
     241uint16_t ebda_mem_alloc(int n_kb)
     242{
     243    uint16_t        base_mem_kb;
     244    uint16_t        ebda_kb;
     245    uint16_t        user_ofs;   /* Offset and size in paragraphs */
     246    uint16_t        user_size;
     247    uint16_t        old_ebda_seg;
     248    uint16_t        new_ebda_seg;
     249
     250    base_mem_kb = read_word(0x00, 0x0413);
     251
     252    DPRINT("BIOS: %dK of base mem, removing %dK\n", base_mem_kb, n_kb);
     253
     254    if (base_mem_kb == 0)
     255        return 0;
     256
     257    /* Reduce conventional memory size and update the BDA. */
     258    base_mem_kb -= n_kb;
     259    write_word(0x0040, 0x0013, base_mem_kb);
     260
     261    /* Figure out what's where. */
     262    old_ebda_seg = read_word(0x0040, 0x000E);
     263    ebda_kb      = read_byte(old_ebda_seg, 0);
     264    user_ofs     = ebda_kb * (1024 / 16);   /* Old EBDA size == new mem offset. */
     265    user_size    = n_kb * (1024 / 16);
     266
     267    /* Shift the existing EBDA down. */
     268    new_ebda_seg = old_ebda_seg - user_size;
     269    /* This is where we should be using memmove(), but we know how our own memcpy() works. */
     270    _fmemcpy(MK_FP(new_ebda_seg, 0), MK_FP(old_ebda_seg, 0), user_ofs * 16);
     271    _fmemset(MK_FP(new_ebda_seg + user_ofs, 0), 0, user_size * 16);
     272
     273    /* Update the EBDA location and size. */
     274    write_word(0x0040, 0x000E, new_ebda_seg);
     275    write_byte(new_ebda_seg, 0, ebda_kb + n_kb);
     276
     277    DPRINT("BIOS: added %04X paras at EBDA offset %04X\n", user_size, user_ofs);
     278
     279    return user_ofs;
     280}
     281
  • trunk/src/VBox/Devices/PC/BIOS/scsi.c

    r100984 r106027  
    104104
    105105/**
    106  * Allocates 1K of conventional memory.
    107  */
    108 static uint16_t scsi_hba_mem_alloc(void)
    109 {
    110     uint16_t    base_mem_kb;
    111     uint16_t    hba_seg;
    112 
    113     base_mem_kb = read_word(0x00, 0x0413);
    114 
    115     DBG_SCSI("SCSI: %dK of base mem\n", base_mem_kb);
    116 
    117     if (base_mem_kb == 0)
    118         return 0;
    119 
    120     base_mem_kb--; /* Allocate one block. */
    121     hba_seg = (((uint32_t)base_mem_kb * 1024) >> 4); /* Calculate start segment. */
    122 
    123     write_word(0x00, 0x0413, base_mem_kb);
    124 
    125     return hba_seg;
    126 }
    127 
    128 /**
    129106 * Read sectors from an attached SCSI device.
    130107 *
     
    160137
    161138
    162     hba_seg   = bios_dsk->scsidev[device_id].hba_seg;
     139    hba_seg   = read_word(0x0040, 0x000E) + bios_dsk->scsidev[device_id].hba_ofs;
    163140    idx_hba   = bios_dsk->scsidev[device_id].idx_hba;
    164141    target_id = bios_dsk->scsidev[device_id].target_id;
     
    213190    cdb.pad2    = 0;
    214191
    215     hba_seg   = bios_dsk->scsidev[device_id].hba_seg;
     192    hba_seg   = read_word(0x0040, 0x000E) + bios_dsk->scsidev[device_id].hba_ofs;
    216193    idx_hba   = bios_dsk->scsidev[device_id].idx_hba;
    217194    target_id = bios_dsk->scsidev[device_id].target_id;
     
    275252
    276253    high_bits_save(&eax_hi);
    277     hba_seg   = bios_dsk->scsidev[device_id].hba_seg;
     254    hba_seg   = read_word(0x0040, 0x000E) + bios_dsk->scsidev[device_id].hba_ofs;
    278255    idx_hba   = bios_dsk->scsidev[device_id].idx_hba;
    279256    target_id = bios_dsk->scsidev[device_id].target_id;
     
    301278 *
    302279 * @param   hba_seg    Segement of the HBA controller block.
     280 * @param   hba_ofs    Offset of the HBA controller block within the EBDA.
    303281 * @param   idx_hba    The HBA driver index used for accessing the enumerated devices.
    304282 */
    305 static void scsi_enumerate_attached_devices(uint16_t hba_seg, uint8_t idx_hba)
     283static void scsi_enumerate_attached_devices(uint16_t hba_seg, uint16_t hba_ofs, uint8_t idx_hba)
    306284{
    307285    int                 i;
     
    433411                hd_index = devcount_scsi + BX_MAX_ATA_DEVICES;
    434412
    435                 bios_dsk->scsidev[devcount_scsi].hba_seg   = hba_seg;
     413                bios_dsk->scsidev[devcount_scsi].hba_ofs   = hba_ofs;
    436414                bios_dsk->scsidev[devcount_scsi].idx_hba   = idx_hba;
    437415                bios_dsk->scsidev[devcount_scsi].target_id = i;
     
    494472            removable = buffer[1] & 0x80 ? 1 : 0;
    495473
    496             bios_dsk->scsidev[devcount_scsi].hba_seg   = hba_seg;
     474            bios_dsk->scsidev[devcount_scsi].hba_ofs   = hba_ofs;
    497475            bios_dsk->scsidev[devcount_scsi].idx_hba   = idx_hba;
    498476            bios_dsk->scsidev[devcount_scsi].target_id = i;
     
    544522            int rc;
    545523            uint8_t  u8Bus, u8DevFn;
    546             uint16_t hba_seg = scsi_hba_mem_alloc();
    547             if (hba_seg == 0) /* No point in trying the rest if we are out of memory. */
     524            uint16_t hba_seg;
     525            uint16_t hba_ofs = ebda_mem_alloc(1/*KB*/);
     526            if (hba_ofs == 0) /* No point in trying the rest if we are out of memory. */
    548527                break;
     528
     529            hba_seg = read_word(0x0040, 0x000E) + hba_ofs;
    549530
    550531            u8Bus = (busdevfn & 0xff00) >> 8;
     
    554535            rc = hbaacc[i].init(hba_seg :> 0, u8Bus, u8DevFn);
    555536            if (!rc)
    556                 scsi_enumerate_attached_devices(hba_seg, i);
     537                scsi_enumerate_attached_devices(hba_seg, hba_ofs, i);
    557538            /** @todo Free memory on error. */
    558539        }
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