VirtualBox

Changeset 92279 in vbox for trunk/src/VBox/Devices/PC/BIOS


Ignore:
Timestamp:
Nov 8, 2021 11:33:38 PM (3 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
148124
Message:

BIOS: Fixed INT 15h/E820h reporting of memory above 1TiB, simplified code a little to save space (29 bytes). bugref:10093

File:
1 edited

Legend:

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

    r87784 r92279  
    592592} mem_range_t;
    593593
    594 void set_e820_range(uint16_t reg_ES, uint16_t reg_DI, uint32_t start, uint32_t end,
    595                     uint8_t extra_start, uint8_t extra_end, uint16_t type)
     594void set_e820_range(uint16_t reg_ES, uint16_t reg_DI, uint32_t start, uint32_t end, uint8_t type)
    596595{
    597     mem_range_t __far   *range;
    598 
    599     range = reg_ES :> (mem_range_t *)reg_DI;
    600     range->start  = start;
    601     range->xstart = extra_start;
    602     end -= start;
    603     extra_end -= extra_start;
    604     range->len    = end;
    605     range->xlen   = extra_end;
    606     range->type   = type;
     596    mem_range_t __far *fpRange = reg_ES :> (mem_range_t *)reg_DI;
     597    fpRange->start  = start;
     598    fpRange->len    = end - start;
     599    fpRange->type   = type;
     600    fpRange->xlen   = 0;
     601    fpRange->xstart = 0;
     602}
     603
     604void set_e820_range_above_4g(uint16_t reg_ES, uint16_t reg_DI, uint16_t c64k_above_4G_low, uint16_t c64k_above_4G_high)
     605{
     606    mem_range_t __far *fpRange = reg_ES :> (mem_range_t *)reg_DI;
     607    fpRange->start  = 0;        /* Starts at 4G, so low start address dword is zero */
     608    fpRange->xstart = 1;        /* And the high start dword is 1. */
     609    fpRange->len    = (uint32_t)c64k_above_4G_low << 16;
     610    fpRange->xlen   = c64k_above_4G_high;
     611    fpRange->type   = 1;        /* type is usable */
    607612}
    608613
    609614void BIOSCALL int15_function32(sys32_regs_t r)
    610615{
    611     uint32_t    extended_memory_size=0; // 64bits long
    612     uint32_t    extra_lowbits_memory_size=0;
    613     uint8_t     extra_highbits_memory_size=0;
    614     uint32_t    mcfgStart, mcfgSize;
    615 
    616616    BX_DEBUG_INT15("int15 AX=%04x\n",AX);
    617617
     
    635635        case 0x20: // coded by osmaker aka K.J.
    636636            if(EDX == 0x534D4150) {
    637                 extended_memory_size = inb_cmos(0x35);
    638                 extended_memory_size <<= 8;
     637                uint32_t extended_memory_size; // 64bits long
     638                uint16_t c64k_above_4G_low;
     639                uint16_t c64k_above_4G_high;
     640                uint32_t mcfgStart, mcfgSize;
     641
     642                /** @todo r=bird: I think we can do the first bit here in 16-bit, then decide
     643                 * whether we need to use 0x31 & 0x30 before blowing it up to 32-bit.  Only, I'm
     644                 * a little bit too tired to think straight... */
     645                extended_memory_size  = (uint16_t)inb_cmos(0x35) << 8;
    639646                extended_memory_size |= inb_cmos(0x34);
    640647                extended_memory_size *= 64;
     
    646653#endif /* !VBOX */
    647654                extended_memory_size *= 1024;
    648                 extended_memory_size += (16L * 1024 * 1024);
     655                extended_memory_size += 16L * 1024 * 1024;
    649656
    650657                if(extended_memory_size <= (16L * 1024 * 1024)) {
    651                     extended_memory_size = inb_cmos(0x31);
    652                     extended_memory_size <<= 8;
     658                    extended_memory_size = (uint16_t)inb_cmos(0x31) << 8;
    653659                    extended_memory_size |= inb_cmos(0x30);
    654660                    extended_memory_size *= 1024;
     
    657663
    658664                /* This is the amount of memory above 4GB measured in 64KB units. */
    659                 extra_lowbits_memory_size = inb_cmos(0x62);
    660                 extra_lowbits_memory_size <<= 8;
    661                 extra_lowbits_memory_size |= inb_cmos(0x61);
    662                 extra_lowbits_memory_size <<= 16;
    663                 extra_highbits_memory_size = inb_cmos(0x63);
    664                 /* 0x64 and 0x65 can be used if we need to dig 1 TB or more at a later point. */
    665 
    666                 mcfgStart = 0;
     665                c64k_above_4G_low   = (uint16_t)inb_cmos(0x62) << 8;
     666                c64k_above_4G_low  |= inb_cmos(0x61);
     667
     668                c64k_above_4G_high  = (uint16_t)inb_cmos(0x64) << 8;
     669                c64k_above_4G_high |= inb_cmos(0x63);
     670                /* 0x65 can be used if we need to go beyond 255 TiB */
     671
     672                mcfgStart = 0; /// @todo implement mcfg reporting
    667673                mcfgSize  = 0;
    668674
     
    670676                {
    671677                    case 0:
    672                         set_e820_range(ES, DI,
    673                                        0x0000000L, 0x0009fc00L, 0, 0, 1);
     678                        set_e820_range(ES, DI, 0x0000000L, 0x0009fc00L, 1);
    674679                        EBX = 1;
    675680                        break;
    676681                    case 1:
    677                         set_e820_range(ES, DI,
    678                                        0x0009fc00L, 0x000a0000L, 0, 0, 2);
     682                        set_e820_range(ES, DI, 0x0009fc00L, 0x000a0000L, 2);
    679683                        EBX = 2;
    680684                        break;
     
    691695                         * a single reserved range from 0xd0000 to 0xffffff.
    692696                         * A 128K area starting from 0xd0000 works. */
    693                         set_e820_range(ES, DI,
    694                                        0x000f0000L, 0x00100000L, 0, 0, 2);
     697                        set_e820_range(ES, DI, 0x000f0000L, 0x00100000L, 2);
    695698                        EBX = 3;
    696699                        break;
    697700                    case 3:
    698                         set_e820_range(ES, DI,
    699                                        0x00100000L,
    700                                        extended_memory_size - ACPI_DATA_SIZE, 0, 0, 1);
     701                        set_e820_range(ES, DI, 0x00100000L,
     702                                       extended_memory_size - ACPI_DATA_SIZE, 1);
    701703                        EBX = 4;
    702704                        break;
     
    704706                        set_e820_range(ES, DI,
    705707                                       extended_memory_size - ACPI_DATA_SIZE,
    706                                        extended_memory_size, 0, 0, 3); // ACPI RAM
     708                                       extended_memory_size, 3); // ACPI RAM
    707709                        EBX = 5;
    708710                        break;
    709711                    case 5:
    710                         set_e820_range(ES, DI,
    711                                        0xfec00000,
    712                                        0xfec00000 + 0x1000, 0, 0, 2); // I/O APIC
     712                        set_e820_range(ES, DI, 0xfec00000, 0xfec00000 + 0x1000, 2); // I/O APIC
    713713                        EBX = 6;
    714714                        break;
    715715                    case 6:
    716                         set_e820_range(ES, DI,
    717                                        0xfee00000,
    718                                        0xfee00000 + 0x1000, 0, 0, 2); // Local APIC
     716                        set_e820_range(ES, DI, 0xfee00000, 0xfee00000 + 0x1000, 2); // Local APIC
    719717                        EBX = 7;
    720718                        break;
     
    723721                        /* We don't set the end to 1GB here and rely on the 32-bit
    724722                           unsigned wrap around effect (0-0xfffc0000L). */
    725                         set_e820_range(ES, DI,
    726                                        0xfffc0000L, 0x00000000L, 0, 0, 2);
     723                        set_e820_range(ES, DI, 0xfffc0000L, 0x00000000L, 2);
    727724                        if (mcfgStart != 0)
    728725                            EBX = 8;
     726                        else if (c64k_above_4G_low || c64k_above_4G_high)
     727                            EBX = 9;
    729728                        else
    730                         {
    731                             if (extra_highbits_memory_size || extra_lowbits_memory_size)
    732                                 EBX = 9;
    733                             else
    734                                 EBX = 0;
    735                         }
     729                            EBX = 0;
    736730                        break;
    737731                     case 8:
    738732                        /* PCI MMIO config space (MCFG) */
    739                         set_e820_range(ES, DI,
    740                                        mcfgStart, mcfgStart + mcfgSize, 0, 0, 2);
    741 
    742                         if (extra_highbits_memory_size || extra_lowbits_memory_size)
     733                        set_e820_range(ES, DI, mcfgStart, mcfgStart + mcfgSize, 2);
     734                        if (c64k_above_4G_low || c64k_above_4G_high)
    743735                            EBX = 9;
    744736                        else
     
    751743                           Note2* works only up to 1TB because of uint8_t for
    752744                                  the upper bits!*/
    753                         if (extra_highbits_memory_size || extra_lowbits_memory_size)
     745                        if (c64k_above_4G_low || c64k_above_4G_high)
    754746                        {
    755                             set_e820_range(ES, DI,
    756                                            0x00000000L, extra_lowbits_memory_size,
    757                                            1 /*x4GB*/, extra_highbits_memory_size + 1 /*x4GB*/, 1);
     747                            set_e820_range_above_4g(ES, DI, c64k_above_4G_low, c64k_above_4G_high);
    758748                            EBX = 0;
    759749                            break;
Note: See TracChangeset for help on using the changeset viewer.

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