- Timestamp:
- Oct 19, 2018 10:30:13 AM (6 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
-
doc/manual/en_US/user_AdvancedTopics.xml (modified) (1 diff)
-
src/VBox/Devices/PC/DevACPI.cpp (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/manual/en_US/user_AdvancedTopics.xml
r73276 r74939 2383 2383 <sect1 id="changeacpicust"> 2384 2384 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): 2390 2392 </para> 2391 2393 2392 2394 <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 2399 2404 <filename>/sys/firmware/acpi/tables/</filename>. 2400 2405 </para> -
trunk/src/VBox/Devices/PC/DevACPI.cpp
r71892 r74939 83 83 GPE1_OFFSET = -1 /**< not supported */ 84 84 }; 85 86 /* Maximum supported number of custom ACPI tables */ 87 #define MAX_CUST_TABLES 4 85 88 86 89 /* Undef this to enable 24 bit PM timer (mostly for debugging purposes) */ … … 438 441 R3PTRTYPE(PFNPCICONFIGWRITE) pfnAcpiPciConfigWrite; 439 442 440 /** If custom table should be supported*/441 bool fUseCust;443 /** Number of custom ACPI tables */ 444 uint8_t cCustTbls; 442 445 /** ACPI OEM ID */ 443 446 uint8_t au8OemId[6]; … … 452 455 uint32_t Alignment4; 453 456 454 /** The custom tablebinary data. */455 R3PTRTYPE(uint8_t *) pu8CustBin;457 /** Custom ACPI tables binary data. */ 458 R3PTRTYPE(uint8_t *) apu8CustBin[MAX_CUST_TABLES]; 456 459 /** The size of the custom table binary. */ 457 uint64_t cbCustBin;460 uint64_t acbCustBin[MAX_CUST_TABLES]; 458 461 459 462 /** SMBus Host Status Register */ … … 2802 2805 acpiR3PrepareHeader(pThis, &xsdt->header, "XSDT", (uint32_t)size, 1 /* according to ACPI 3.0 specs */); 2803 2806 2804 if (pThis-> fUseCust)2807 if (pThis->cCustTbls > 0) 2805 2808 memcpy(xsdt->header.au8OemTabId, pThis->au8OemTabId, 8); 2806 2809 … … 3057 3060 3058 3061 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 3075 3062 /** 3076 3063 * Used by acpiR3PlantTables to plant a MMCONFIG PCI config space access (MCFG) … … 3111 3098 { 3112 3099 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 */ 3112 static 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; 3113 3150 } 3114 3151 … … 3124 3161 RTGCPHYS32 GCPhysSsdt = 0; 3125 3162 RTGCPHYS32 GCPhysMcfg = 0; 3126 RTGCPHYS32 GCPhysCust = 0;3163 RTGCPHYS32 aGCPhysCust[MAX_CUST_TABLES] = {0}; 3127 3164 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]; 3130 3167 uint32_t cAddr; 3131 3168 uint32_t iMadt = 0; … … 3147 3184 iMcfg = cAddr++; /* MCFG */ 3148 3185 3149 if (pThis->fUseCust) 3150 iCust = cAddr++; /* CUST */ 3186 if (pThis->cCustTbls > 0) 3187 { 3188 iCust = cAddr; /* CUST */ 3189 cAddr += pThis->cCustTbls; 3190 } 3151 3191 3152 3192 iSsdt = cAddr++; /* SSDT */ … … 3221 3261 GCPhysCur = RT_ALIGN_32(GCPhysCur + sizeof(ACPITBLMCFG) + sizeof(ACPITBLMCFGENTRY), 16); 3222 3262 } 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); 3227 3268 } 3228 3269 … … 3261 3302 if (pThis->fUseMcfg) 3262 3303 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)); 3265 3306 Log((" SSDT 0x%08X", GCPhysSsdt + addend)); 3266 3307 Log(("\n")); … … 3292 3333 aGCPhysXsdt[iMcfg] = GCPhysMcfg + addend; 3293 3334 } 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)); 3299 3344 } 3300 3345 … … 3540 3585 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 3541 3586 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 } 3546 3594 } 3547 3595 return VINF_SUCCESS; … … 3633 3681 "AcpiCreatorRev\0" 3634 3682 "CustomTable\0" 3635 "SLICTable\0" 3683 "CustomTable0\0" 3684 "CustomTable1\0" 3685 "CustomTable2\0" 3686 "CustomTable3\0" 3636 3687 "Parallel0IoPortBase\0" 3637 3688 "Parallel1IoPortBase\0" … … 3688 3739 N_("Configuration error: Failed to read \"PciPref64LimitGB\"")); 3689 3740 pThis->u64PciPref64Max = _1G64 * u64PciPref64MaxGB; 3690 3691 /* query whether we are supposed to present custom table */3692 pThis->fUseCust = false;3693 3741 3694 3742 /* query whether we are supposed to present SMC */ … … 3895 3943 3896 3944 /* 3897 * Get the custom table binary file name.3945 * Load custom ACPI tables. 3898 3946 */ 3899 3947 char *pszCustBinFile; 3948 3949 /* Maintain legacy behavior for CustomTable config key. 3950 * If present, use it as alias for CustomTable1. */ 3900 3951 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 { 3967 3954 if (RT_FAILURE(rc)) 3968 3955 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 } 3970 4028 } 3971 4029
Note:
See TracChangeset
for help on using the changeset viewer.

