VirtualBox

Changeset 74939 in vbox for trunk


Ignore:
Timestamp:
Oct 19, 2018 10:30:13 AM (6 years ago)
Author:
vboxsync
Message:

ACPI: Support up to four custom tables, not just one. Thanks, canardoscode!

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/manual/en_US/user_AdvancedTopics.xml

    r73276 r74939  
    23832383  <sect1 id="changeacpicust">
    23842384
    2385     <title>Configuring the Custom ACPI Table</title>
    2386 
    2387     <para>
    2388       VirtualBox can be configured to present an custom ACPI table to
    2389       the guest. Use the following command to configure this:
     2385    <title>Configuring Custom ACPI Tables</title>
     2386
     2387    <para>
     2388      VirtualBox can be configured to present up to four custom ACPI tables
     2389      to the guest. A command such as the following can be used to configure
     2390      custom ACPI tables (note that CustomTable1, CustomTable2, and
     2391      CustomTable3 are available in addition to CustomTable0):
    23902392    </para>
    23912393
    23922394<screen>VBoxManage setextradata "VM name"
    2393       "VBoxInternal/Devices/acpi/0/Config/CustomTable" "/path/to/table.bin"</screen>
    2394 
    2395     <para>
    2396       Configuring a custom ACPI table can prevent Windows Vista and
    2397       Windows 7 from asking for a new product key. On Linux hosts, one
    2398       of the host tables can be read from
     2395      "VBoxInternal/Devices/acpi/0/Config/CustomTable0" "/path/to/table.bin"</screen>
     2396
     2397    <para>
     2398      Configuring custom ACPI tables can for example avoid the need to
     2399      ask for a new product key in Windows Vista/7/8 and later guests.
     2400    </para>
     2401
     2402    <para>
     2403      On Linux hosts, one of the system's ACPI tables can be read from
    23992404      <filename>/sys/firmware/acpi/tables/</filename>.
    24002405    </para>
  • trunk/src/VBox/Devices/PC/DevACPI.cpp

    r71892 r74939  
    8383    GPE1_OFFSET                         =   -1    /**<  not supported  */
    8484};
     85
     86/* Maximum supported number of custom ACPI tables */
     87#define MAX_CUST_TABLES 4
    8588
    8689/* Undef this to enable 24 bit PM timer (mostly for debugging purposes) */
     
    438441    R3PTRTYPE(PFNPCICONFIGWRITE)  pfnAcpiPciConfigWrite;
    439442
    440     /** If custom table should be supported */
    441     bool                fUseCust;
     443    /** Number of custom ACPI tables */
     444    uint8_t             cCustTbls;
    442445    /** ACPI OEM ID */
    443446    uint8_t             au8OemId[6];
     
    452455    uint32_t            Alignment4;
    453456
    454     /** The custom table binary data. */
    455     R3PTRTYPE(uint8_t *) pu8CustBin;
     457    /** Custom ACPI tables binary data. */
     458    R3PTRTYPE(uint8_t *) apu8CustBin[MAX_CUST_TABLES];
    456459    /** The size of the custom table binary. */
    457     uint64_t            cbCustBin;
     460    uint64_t            acbCustBin[MAX_CUST_TABLES];
    458461
    459462    /** SMBus Host Status Register */
     
    28022805    acpiR3PrepareHeader(pThis, &xsdt->header, "XSDT", (uint32_t)size, 1 /* according to ACPI 3.0 specs */);
    28032806
    2804     if (pThis->fUseCust)
     2807    if (pThis->cCustTbls > 0)
    28052808        memcpy(xsdt->header.au8OemTabId, pThis->au8OemTabId, 8);
    28062809
     
    30573060
    30583061
    3059 /** Custom Description Table */
    3060 static void acpiR3SetupCust(ACPIState *pThis, RTGCPHYS32 addr)
    3061 {
    3062     ACPITBLCUST cust;
    3063 
    3064     /* First the ACPI version 1 version of the structure. */
    3065     memset(&cust, 0, sizeof(cust));
    3066     acpiR3PrepareHeader(pThis, &cust.header, "CUST", sizeof(cust), 1);
    3067 
    3068     memcpy(cust.header.au8OemTabId, pThis->au8OemTabId, 8);
    3069     cust.header.u32OemRevision = RT_H2LE_U32(pThis->u32OemRevision);
    3070     cust.header.u8Checksum = acpiR3Checksum((uint8_t *)&cust, sizeof(cust));
    3071 
    3072     acpiR3PhysCopy(pThis, addr, pThis->pu8CustBin, pThis->cbCustBin);
    3073 }
    3074 
    30753062/**
    30763063 * Used by acpiR3PlantTables to plant a MMCONFIG PCI config space access (MCFG)
     
    31113098{
    31123099    return 0xe0000;
     3100}
     3101
     3102/**
     3103 * Called by acpiR3Construct to read and allocate a custom ACPI table
     3104 *
     3105 * @param   pDevIns         The device instance.
     3106 * @param   ppu8CustBin     Address to receive the address of the table
     3107 * @param   pcbCustBin      Address to receive the size of the the table.
     3108 * @param   pszCustBinFile
     3109 * @param   pBufAvail       Maximum space in bytes available for the custom
     3110 *                          table (including header).
     3111 */
     3112static int acpiR3ReadCustomTable(PPDMDEVINS pDevIns, uint8_t **ppu8CustBin, uint64_t *pcbCustBin,
     3113                                 char *pszCustBinFile, uint32_t cbBufAvail)
     3114{
     3115    RTFILE FileCUSTBin;
     3116    int rc = RTFileOpen(&FileCUSTBin, pszCustBinFile,
     3117                        RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     3118    if (RT_SUCCESS(rc))
     3119    {
     3120        rc = RTFileGetSize(FileCUSTBin, pcbCustBin);
     3121        if (RT_SUCCESS(rc))
     3122        {
     3123            /* The following checks should be in sync the AssertReleaseMsg's below. */
     3124            if (    *pcbCustBin > cbBufAvail
     3125                ||  *pcbCustBin < sizeof(ACPITBLHEADER))
     3126                rc = VERR_TOO_MUCH_DATA;
     3127
     3128            /*
     3129             * Allocate buffer for the custom table binary data.
     3130             */
     3131            *ppu8CustBin = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, *pcbCustBin);
     3132            if (*ppu8CustBin)
     3133            {
     3134                rc = RTFileRead(FileCUSTBin, *ppu8CustBin, *pcbCustBin, NULL);
     3135                if (RT_FAILURE(rc))
     3136                {
     3137                    AssertMsgFailed(("RTFileRead(,,%d,NULL) -> %Rrc\n", *pcbCustBin, rc));
     3138                    PDMDevHlpMMHeapFree(pDevIns, *ppu8CustBin);
     3139                    *ppu8CustBin = NULL;
     3140                }
     3141            }
     3142            else
     3143            {
     3144                rc = VERR_NO_MEMORY;
     3145            }
     3146            RTFileClose(FileCUSTBin);
     3147        }
     3148    }
     3149    return rc;
    31133150}
    31143151
     
    31243161    RTGCPHYS32 GCPhysSsdt = 0;
    31253162    RTGCPHYS32 GCPhysMcfg = 0;
    3126     RTGCPHYS32 GCPhysCust = 0;
     3163    RTGCPHYS32 aGCPhysCust[MAX_CUST_TABLES] = {0};
    31273164    uint32_t   addend = 0;
    3128     RTGCPHYS32 aGCPhysRsdt[8];
    3129     RTGCPHYS32 aGCPhysXsdt[8];
     3165    RTGCPHYS32 aGCPhysRsdt[7 + MAX_CUST_TABLES];
     3166    RTGCPHYS32 aGCPhysXsdt[7 + MAX_CUST_TABLES];
    31303167    uint32_t   cAddr;
    31313168    uint32_t   iMadt  = 0;
     
    31473184        iMcfg = cAddr++;        /* MCFG */
    31483185
    3149     if (pThis->fUseCust)
    3150         iCust = cAddr++;        /* CUST */
     3186    if (pThis->cCustTbls > 0)
     3187    {
     3188        iCust = cAddr;          /* CUST */
     3189        cAddr += pThis->cCustTbls;
     3190    }
    31513191
    31523192    iSsdt = cAddr++;            /* SSDT */
     
    32213261        GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLMCFG) + sizeof(ACPITBLMCFGENTRY), 16);
    32223262    }
    3223     if (pThis->fUseCust)
    3224     {
    3225         GCPhysCust = GCPhysCur;
    3226         GCPhysCur = RT_ALIGN_32(GCPhysCur + pThis->cbCustBin, 16);
     3263
     3264    for (uint8_t i = 0; i < pThis->cCustTbls; i++)
     3265    {
     3266        aGCPhysCust[i] = GCPhysCur;
     3267        GCPhysCur = RT_ALIGN_32(GCPhysCur + pThis->acbCustBin[i], 16);
    32273268    }
    32283269
     
    32613302    if (pThis->fUseMcfg)
    32623303        Log((" MCFG 0x%08X", GCPhysMcfg + addend));
    3263     if (pThis->fUseCust)
    3264         Log((" CUST 0x%08X", GCPhysCust + addend));
     3304    for (uint8_t i = 0; i < pThis->cCustTbls; i++)
     3305        Log((" CUST(%d) 0x%08X", i, aGCPhysCust[i] + addend));
    32653306    Log((" SSDT 0x%08X", GCPhysSsdt + addend));
    32663307    Log(("\n"));
     
    32923333        aGCPhysXsdt[iMcfg] = GCPhysMcfg + addend;
    32933334    }
    3294     if (pThis->fUseCust)
    3295     {
    3296         acpiR3SetupCust(pThis, GCPhysCust + addend);
    3297         aGCPhysRsdt[iCust] = GCPhysCust + addend;
    3298         aGCPhysXsdt[iCust] = GCPhysCust + addend;
     3335    for (uint8_t i = 0; i < pThis->cCustTbls; i++)
     3336    {
     3337        Assert(i < MAX_CUST_TABLES);
     3338        acpiR3PhysCopy(pThis, aGCPhysCust[i] + addend, pThis->apu8CustBin[i], pThis->acbCustBin[i]);
     3339        aGCPhysRsdt[iCust + i] = aGCPhysCust[i] + addend;
     3340        aGCPhysXsdt[iCust + i] = aGCPhysCust[i] + addend;
     3341        uint8_t* pSig = pThis->apu8CustBin[i];
     3342        LogRel(("ACPI: Planted custom table '%c%c%c%c' at 0x%08X\n",
     3343               pSig[0], pSig[1], pSig[2], pSig[3], aGCPhysCust[i] + addend));
    32993344    }
    33003345
     
    35403585    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
    35413586    ACPIState *pThis = PDMINS_2_DATA(pDevIns, ACPIState *);
    3542     if (pThis->pu8CustBin)
    3543     {
    3544         PDMDevHlpMMHeapFree(pDevIns, pThis->pu8CustBin);
    3545         pThis->pu8CustBin = NULL;
     3587    for (uint8_t i = 0; i < pThis->cCustTbls; i++)
     3588    {
     3589        if (pThis->apu8CustBin[i])
     3590        {
     3591            PDMDevHlpMMHeapFree(pDevIns, pThis->apu8CustBin[i]);
     3592            pThis->apu8CustBin[i] = NULL;
     3593        }
    35463594    }
    35473595    return VINF_SUCCESS;
     
    36333681                              "AcpiCreatorRev\0"
    36343682                              "CustomTable\0"
    3635                               "SLICTable\0"
     3683                              "CustomTable0\0"
     3684                              "CustomTable1\0"
     3685                              "CustomTable2\0"
     3686                              "CustomTable3\0"
    36363687                              "Parallel0IoPortBase\0"
    36373688                              "Parallel1IoPortBase\0"
     
    36883739                                N_("Configuration error: Failed to read \"PciPref64LimitGB\""));
    36893740    pThis->u64PciPref64Max = _1G64 * u64PciPref64MaxGB;
    3690 
    3691     /* query whether we are supposed to present custom table */
    3692     pThis->fUseCust = false;
    36933741
    36943742    /* query whether we are supposed to present SMC */
     
    38953943
    38963944    /*
    3897      * Get the custom table binary file name.
     3945     * Load custom ACPI tables.
    38983946     */
    38993947    char *pszCustBinFile;
     3948
     3949    /* Maintain legacy behavior for CustomTable config key.
     3950     * If present, use it as alias for CustomTable1. */
    39003951    rc = CFGMR3QueryStringAlloc(pCfg, "CustomTable", &pszCustBinFile);
    3901     if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    3902         rc = CFGMR3QueryStringAlloc(pCfg, "SLICTable", &pszCustBinFile);
    3903     if (rc == VERR_CFGM_VALUE_NOT_FOUND)
    3904     {
    3905         pszCustBinFile = NULL;
    3906         rc = VINF_SUCCESS;
    3907     }
    3908     else if (RT_FAILURE(rc))
    3909         return PDMDEV_SET_ERROR(pDevIns, rc,
    3910                                 N_("Configuration error: Querying \"CustomTable\" as a string failed"));
    3911     else if (!*pszCustBinFile)
    3912     {
    3913         MMR3HeapFree(pszCustBinFile);
    3914         pszCustBinFile = NULL;
    3915     }
    3916 
    3917     /*
    3918      * Determine the custom table binary size, open specified ROM file in the process.
    3919      */
    3920     if (pszCustBinFile)
    3921     {
    3922         RTFILE FileCUSTBin;
    3923         rc = RTFileOpen(&FileCUSTBin, pszCustBinFile,
    3924                         RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
    3925         if (RT_SUCCESS(rc))
    3926         {
    3927             rc = RTFileGetSize(FileCUSTBin, &pThis->cbCustBin);
    3928             if (RT_SUCCESS(rc))
    3929             {
    3930                 /* The following checks should be in sync the AssertReleaseMsg's below. */
    3931                 if (    pThis->cbCustBin > 3072
    3932                     ||  pThis->cbCustBin < sizeof(ACPITBLHEADER))
    3933                     rc = VERR_TOO_MUCH_DATA;
    3934 
    3935                 /*
    3936                  * Allocate buffer for the custom table binary data.
    3937                  */
    3938                 pThis->pu8CustBin = (uint8_t *)PDMDevHlpMMHeapAlloc(pDevIns, pThis->cbCustBin);
    3939                 if (pThis->pu8CustBin)
    3940                 {
    3941                     rc = RTFileRead(FileCUSTBin, pThis->pu8CustBin, pThis->cbCustBin, NULL);
    3942                     if (RT_FAILURE(rc))
    3943                     {
    3944                         AssertMsgFailed(("RTFileRead(,,%d,NULL) -> %Rrc\n", pThis->cbCustBin, rc));
    3945                         PDMDevHlpMMHeapFree(pDevIns, pThis->pu8CustBin);
    3946                         pThis->pu8CustBin = NULL;
    3947                     }
    3948                     else
    3949                     {
    3950                         pThis->fUseCust = true;
    3951                         memcpy(&pThis->au8OemId[0], &pThis->pu8CustBin[10], 6);
    3952                         memcpy(&pThis->au8OemTabId[0], &pThis->pu8CustBin[16], 8);
    3953                         memcpy(&pThis->u32OemRevision, &pThis->pu8CustBin[24], 4);
    3954                         memcpy(&pThis->au8CreatorId[0], &pThis->pu8CustBin[28], 4);
    3955                         memcpy(&pThis->u32CreatorRev, &pThis->pu8CustBin[32], 4);
    3956                         LogRel(("ACPI: Reading custom ACPI table from file '%s' (%d bytes)\n", pszCustBinFile,
    3957                                 pThis->cbCustBin));
    3958                     }
    3959                 }
    3960                 else
    3961                     rc = VERR_NO_MEMORY;
    3962 
    3963                 RTFileClose(FileCUSTBin);
    3964             }
    3965         }
    3966         MMR3HeapFree(pszCustBinFile);
     3952    if (rc != VERR_CFGM_VALUE_NOT_FOUND)
     3953    {
    39673954        if (RT_FAILURE(rc))
    39683955            return PDMDEV_SET_ERROR(pDevIns, rc,
    3969                                     N_("Error reading custom ACPI table"));
     3956                                    N_("Configuration error: Querying \"CustomTable\" as a string failed"));
     3957        if (!*pszCustBinFile)
     3958        {
     3959            MMR3HeapFree(pszCustBinFile);
     3960            pszCustBinFile = NULL;
     3961        }
     3962        else if (pszCustBinFile)
     3963        {
     3964            /* Try creating CustomTable0 using legacy value. */
     3965            rc = CFGMR3InsertString(pCfg, "CustomTable0", pszCustBinFile);
     3966            if (rc == VERR_CFGM_LEAF_EXISTS)
     3967                LogRel(("ACPI: Warning: \"CustomTable\" configuration"
     3968                        " setting ignored as \"CustomTable0\" setting exists.\n"));
     3969            MMR3HeapFree(pszCustBinFile);
     3970        }
     3971    }
     3972
     3973    /* Total space available for custom ACPI tables
     3974     * @todo define as appropriate, remove as a magic number, and document
     3975     *       limitation in product manual */
     3976    uint32_t cbBufAvail = 3072;
     3977    pThis->cCustTbls = 0;
     3978
     3979    const char* custTblConfigKeys[] = {"CustomTable0", "CustomTable1", "CustomTable2", "CustomTable3"};
     3980    for (unsigned i = 0; i < RT_ELEMENTS(custTblConfigKeys); ++i)
     3981    {
     3982        const char* pszConfigKey = custTblConfigKeys[i];
     3983
     3984        /*
     3985         * Get the custom table binary file name.
     3986         */
     3987        rc = CFGMR3QueryStringAlloc(pCfg, pszConfigKey, &pszCustBinFile);
     3988        if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     3989        {
     3990            pszCustBinFile = NULL;
     3991            rc = VINF_SUCCESS;
     3992        }
     3993        else if (RT_FAILURE(rc))
     3994            return PDMDEV_SET_ERROR(pDevIns, rc,
     3995                                    N_("Configuration error: Querying \"CustomTableN\" as a string failed"));
     3996        else if (!*pszCustBinFile)
     3997        {
     3998            MMR3HeapFree(pszCustBinFile);
     3999            pszCustBinFile = NULL;
     4000        }
     4001        /*
     4002         * Determine the custom table binary size, open specified file in the process.
     4003         */
     4004        if (pszCustBinFile)
     4005        {
     4006            uint32_t tblIdx = pThis->cCustTbls;
     4007            rc = acpiR3ReadCustomTable(pDevIns, &(pThis->apu8CustBin[tblIdx]),
     4008                                       &(pThis->acbCustBin[tblIdx]), pszCustBinFile, cbBufAvail);
     4009            LogRel(("ACPI: Reading custom ACPI table(%u) from file '%s' (%d bytes)\n",
     4010                    tblIdx, pszCustBinFile, pThis->acbCustBin[tblIdx]));
     4011            MMR3HeapFree(pszCustBinFile);
     4012            if (RT_FAILURE(rc))
     4013                return PDMDEV_SET_ERROR(pDevIns, rc, N_("Error reading custom ACPI table."));
     4014            cbBufAvail -= pThis->acbCustBin[tblIdx];
     4015
     4016            /* Update custom OEM attributes based on custom table
     4017             * @todo: is it intended for custom tables to overwrite user provided values above? */
     4018            ACPITBLHEADER *pTblHdr = (ACPITBLHEADER*)pThis->apu8CustBin[tblIdx];
     4019            memcpy(&pThis->au8OemId[0], &pTblHdr->au8OemId[0], 6);
     4020            memcpy(&pThis->au8OemTabId[0], &pTblHdr->au8OemTabId[0], 8);
     4021            pThis->u32OemRevision = pTblHdr->u32OemRevision;
     4022            memcpy(&pThis->au8CreatorId[0], &pTblHdr->au8CreatorId[0], 4);
     4023            pThis->u32CreatorRev = pTblHdr->u32CreatorRev;
     4024
     4025            pThis->cCustTbls++;
     4026            Assert(pThis->cCustTbls <= MAX_CUST_TABLES);
     4027        }
    39704028    }
    39714029
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