VirtualBox

Ignore:
Timestamp:
Feb 14, 2025 8:49:02 PM (3 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
167551
Message:

Runtime/RTAcpi*: Updates and fixes, RTIasl can now mostly generate identical AML code for vbox.dsl, apart from a single optimization where iasl can fold certain operations on constants into an integer, like ShiftLeft(One,1) for instance, bugref:10733

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/acpi/acpi-ns.cpp

    r108221 r108230  
    4141#define LOG_GROUP RTLOGGROUP_ACPI
    4242#include <iprt/assert.h>
    43 #include <iprt/errcore.h>
     43#include <iprt/err.h>
    4444#include <iprt/list.h>
    4545#include <iprt/mem.h>
     
    7777    }
    7878    RTMemFree(pNsEntry);
     79}
     80
     81
     82static PRTACPINSENTRY rtAcpiNsLookupWorkerSingleNameSeg(PCRTACPINSENTRY pNsEntry, const char *pszNameSeg)
     83{
     84    do
     85    {
     86        PRTACPINSENTRY pIt;
     87        RTListForEach(&pNsEntry->LstNsEntries, pIt, RTACPINSENTRY, NdNs)
     88        {
     89            if (!memcmp(&pIt->achNameSeg[0], pszNameSeg, sizeof(pIt->achNameSeg)))
     90                return pIt;
     91        }
     92
     93        pNsEntry = pNsEntry->pParent;
     94    } while (pNsEntry);
     95
     96    return NULL;
    7997}
    8098
     
    117135    }
    118136    else
     137    {
    119138        pNsEntry = pNsRoot->aNsStack[pNsRoot->idxNsStack];
     139
     140        /* For single name segments there is a special search rule which searches recursively upwards in the namespace. */
     141        if (pszNameString[4] == '\0')
     142        {
     143            if (fExcludeLast)
     144            {
     145                AssertPtr(ppszNameSegLast);
     146                *ppszNameSegLast = pszNameString;
     147                return pNsEntry;
     148            }
     149            else
     150                return rtAcpiNsLookupWorkerSingleNameSeg(pNsEntry, pszNameString);
     151        }
     152    }
    120153
    121154    /* This ASSUMES the namestring has always full 4 character name segments and is well formed. */
     
    157190
    158191/**
     192 * Looks up a name string under the specified entry.
     193 *
     194 * @returns Pointer to the namespace entry or NULL if not found.
     195 * @param   pNsEntry            The namespace entry to start searching at.
     196 * @param   pszNameString       The name string to look for.
     197 */
     198static PCRTACPINSENTRY rtAcpiNsLookupSubTree(PCRTACPINSENTRY pNsEntry, const char *pszNameString)
     199{
     200    /* This ASSUMES the namestring has always full 4 character name segments and is well formed. */
     201    do
     202    {
     203        Assert(pszNameString[0] != '\0' && pszNameString[1] != '\0' && pszNameString[2] != '\0' && pszNameString[3] != '\0');
     204
     205        PCRTACPINSENTRY pIt;
     206        bool fFound = false;
     207        RTListForEach(&pNsEntry->LstNsEntries, pIt, RTACPINSENTRY, NdNs)
     208        {
     209            if (!memcmp(&pIt->achNameSeg[0], pszNameString, sizeof(pIt->achNameSeg)))
     210            {
     211                pNsEntry = pIt;
     212                fFound = true;
     213                break;
     214            }
     215        }
     216
     217        /* The name path is invalid. */
     218        if (!fFound)
     219            return NULL;
     220
     221        pszNameString += 4;
     222    } while (*pszNameString++ == '.');
     223
     224    return pNsEntry;
     225}
     226
     227
     228/**
    159229 * Adds a new entry in the given namespace under the given path.
    160230 *
     
    163233 * @param   pszNameString       The namestring to add.
    164234 * @param   fSwitchTo           Flag whether to switch to the new entry.
     235 * @param   fIgnoreExisting     Flag whether to ignore any existing entry in the namespace parents.
    165236 * @param   ppNsEntry           Where to store the pointer to the created entry on success.
    166237 */
    167 static int rtAcpiNsAddEntryWorker(PRTACPINSROOT pNsRoot, const char *pszNameString, bool fSwitchTo, PRTACPINSENTRY *ppNsEntry)
     238static int rtAcpiNsAddEntryWorker(PRTACPINSROOT pNsRoot, const char *pszNameString, bool fSwitchTo, bool fIgnoreExisting, PRTACPINSENTRY *ppNsEntry)
    168239{
    169240    AssertReturn(   !fSwitchTo
    170241                 || pNsRoot->idxNsStack < RT_ELEMENTS(pNsRoot->aNsStack),
    171242                 VERR_INVALID_STATE);
     243
     244    /* Does it exist already? */
     245    if (!fIgnoreExisting)
     246    {
     247        PRTACPINSENTRY pNsEntry = rtAcpiNsLookupWorker(pNsRoot, pszNameString, false /*fExcludeLast*/, NULL);
     248        if (pNsEntry)
     249        {
     250            *ppNsEntry = pNsEntry;
     251            if (fSwitchTo)
     252                pNsRoot->aNsStack[++pNsRoot->idxNsStack] = pNsEntry;
     253            return VERR_ALREADY_EXISTS;
     254        }
     255    }
    172256
    173257    int rc;
     
    209293        pNsRoot->idxNsStack        = 0;
    210294        pNsRoot->aNsStack[pNsRoot->idxNsStack] = &pNsRoot->RootEntry;
     295        /* Create the default scopes. */
     296        int rc = rtAcpiNsAddEntryAstNode(pNsRoot, "\\_SB_", NULL /*pAstNd*/, false /*fSwitchTo*/);
     297        if (RT_SUCCESS(rc))
     298            rc = rtAcpiNsAddEntryAstNode(pNsRoot, "\\_PR_", NULL /*pAstNd*/, false /*fSwitchTo*/);
     299        if (RT_SUCCESS(rc))
     300            rc = rtAcpiNsAddEntryAstNode(pNsRoot, "\\_GPE", NULL /*pAstNd*/, false /*fSwitchTo*/);
     301        if (RT_SUCCESS(rc))
     302            rc = rtAcpiNsAddEntryAstNode(pNsRoot, "\\_SI_", NULL /*pAstNd*/, false /*fSwitchTo*/);
     303        if (RT_SUCCESS(rc))
     304            rc = rtAcpiNsAddEntryAstNode(pNsRoot, "\\_TZ_", NULL /*pAstNd*/, false /*fSwitchTo*/);
     305        Assert(RT_SUCCESS(rc) || rc == VERR_NO_MEMORY);
     306        if (RT_FAILURE(rc))
     307        {
     308            RTMemFree(pNsRoot);
     309            pNsRoot = NULL;
     310        }
    211311    }
    212312    return pNsRoot;
     
    226326
    227327
     328DECLHIDDEN(int) rtAcpiNsSwitchTo(PRTACPINSROOT pNsRoot, const char *pszNameString)
     329{
     330    PRTACPINSENTRY pNsEntry = rtAcpiNsLookup(pNsRoot, pszNameString);
     331    if (!pNsEntry)
     332        return VERR_NOT_FOUND;
     333
     334    pNsRoot->aNsStack[++pNsRoot->idxNsStack] = pNsEntry;
     335    return VINF_SUCCESS;
     336}
     337
     338
    228339DECLHIDDEN(int) rtAcpiNsAddEntryAstNode(PRTACPINSROOT pNsRoot, const char *pszNameString, PCRTACPIASTNODE pAstNd, bool fSwitchTo)
    229340{
    230341    PRTACPINSENTRY pNsEntry = NULL;
    231     int rc = rtAcpiNsAddEntryWorker(pNsRoot, pszNameString, fSwitchTo, &pNsEntry);
     342    int rc = rtAcpiNsAddEntryWorker(pNsRoot, pszNameString, fSwitchTo, false /*fIgnoreExisting*/, &pNsEntry);
     343    if (rc == VERR_ALREADY_EXISTS)
     344        rc = VINF_SUCCESS;
    232345    if (RT_SUCCESS(rc))
    233346    {
     
    243356{
    244357    PRTACPINSENTRY pNsEntry = NULL;
    245     int rc = rtAcpiNsAddEntryWorker(pNsRoot, pszNameString, false /*fSwitchTo*/, &pNsEntry);
     358    int rc = rtAcpiNsAddEntryWorker(pNsRoot, pszNameString, false /*fSwitchTo*/, true /*fIgnoreExisting*/, &pNsEntry);
    246359    if (RT_SUCCESS(rc))
    247360    {
     
    259372{
    260373    PRTACPINSENTRY pNsEntry = NULL;
    261     int rc = rtAcpiNsAddEntryWorker(pNsRoot, pszNameString, false /*fSwitchTo*/, &pNsEntry);
     374    int rc = rtAcpiNsAddEntryWorker(pNsRoot, pszNameString, false /*fSwitchTo*/, false /*fIgnoreExisting*/, &pNsEntry);
    262375    if (RT_SUCCESS(rc))
    263376    {
     
    350463
    351464
     465DECLHIDDEN(int) rtAcpiNsCompressNameString(PCRTACPINSROOT pNsRoot, PCRTACPINSENTRY pNsEntry, const char *pszNameString, char *pszNameStringComp, size_t cchNameStringComp)
     466{
     467    size_t cchNameString = strlen(pszNameString);
     468    if (cchNameString > cchNameStringComp)
     469        return VERR_BUFFER_OVERFLOW;
     470
     471    if (   *pszNameString != '\\'
     472        || pNsEntry != rtAcpiNsGetCurrent(pNsRoot))
     473    {
     474        memcpy(pszNameStringComp, pszNameString, cchNameString + 1);
     475        return VINF_SUCCESS;
     476    }
     477
     478    /* Try to remove as many components as possible. */
     479    uint32_t cEntries = 0;
     480    PCRTACPINSENTRY aNsEntries[255]; /* Maximum amount of name segments possible. */
     481    do
     482    {
     483        aNsEntries[cEntries++] = pNsEntry;
     484        pNsEntry = pNsEntry->pParent;
     485    } while (pNsEntry);
     486
     487    Assert(cEntries > 0); /* Should have at least the root entry. */
     488
     489    /* Remove the \ specifier. */
     490    pszNameString++;
     491    cchNameString--;
     492    uint32_t idxEntry = 1;
     493    while (idxEntry < cEntries)
     494    {
     495        pNsEntry = aNsEntries[idxEntry++];
     496        if (memcmp(pszNameString, &pNsEntry->achNameSeg[0], sizeof(pNsEntry->achNameSeg)))
     497            break;
     498
     499        Assert(pszNameString[4] == '.');
     500        pszNameString += 5;
     501        cchNameString -= 5;
     502    }
     503
     504    /* The remaining string is what we end up with. */
     505    memcpy(pszNameStringComp, pszNameString, cchNameString + 1);
     506    return VINF_SUCCESS;
     507}
     508
     509
     510DECLHIDDEN(int) rtAcpiNsAbsoluteNameStringToRelative(PRTACPINSROOT pNsRoot, PCRTACPINSENTRY pNsEntrySrc, const char *pszNameStringDst, char *pszNameStringRel, size_t cchNameStringRel)
     511{
     512    size_t cchNameStringDst = strlen(pszNameStringDst);
     513    if (cchNameStringDst > cchNameStringRel)
     514        return VERR_BUFFER_OVERFLOW;
     515
     516    /* Init with the default. */
     517    memcpy(pszNameStringRel, pszNameStringDst, cchNameStringDst + 1);
     518    if (*pszNameStringDst != '\\')
     519        return VINF_SUCCESS;
     520
     521    PCRTACPINSENTRY pNsDst = rtAcpiNsLookup(pNsRoot, pszNameStringDst);
     522    AssertReturn(pNsDst, VERR_NOT_FOUND);
     523
     524    uint32_t cEntriesSrc = 0;
     525    PCRTACPINSENTRY aNsEntriesSrc[255]; /* Maximum amount of name segments possible. */
     526    do
     527    {
     528        aNsEntriesSrc[cEntriesSrc++] = pNsEntrySrc;
     529        pNsEntrySrc = pNsEntrySrc->pParent;
     530    } while (pNsEntrySrc);
     531
     532    uint32_t cEntriesDst = 0;
     533    PCRTACPINSENTRY aNsEntriesDst[255]; /* Maximum amount of name segments possible. */
     534    do
     535    {
     536        aNsEntriesDst[cEntriesDst++] = pNsDst;
     537        pNsDst = pNsDst->pParent;
     538    } while (pNsDst);
     539
     540    Assert(cEntriesSrc > 0 && cEntriesDst > 0); /* Should have at least the root entry. */
     541    uint32_t idxEntrySrc = cEntriesSrc;
     542    idxEntrySrc--;
     543    cEntriesDst--;
     544    Assert(aNsEntriesSrc[idxEntrySrc] == aNsEntriesDst[cEntriesDst]);
     545
     546    /* Remove the \ specifier. */
     547    size_t cchNameStringNew = cchNameStringDst;
     548    pszNameStringDst++;
     549    cchNameStringNew--;
     550
     551    /* Find the first different path entry. */
     552    while (   idxEntrySrc
     553           && cEntriesDst)
     554    {
     555        if (   aNsEntriesSrc[--idxEntrySrc] != aNsEntriesDst[--cEntriesDst]
     556            || pszNameStringDst[4] == '\0')
     557            break;
     558
     559        Assert(pszNameStringDst[4] == '.');
     560        pszNameStringDst += 5;
     561        cchNameStringNew -= 5;
     562    }
     563
     564    /*
     565     * Calculate how many parent prefixes we need to add.
     566     * If the remaining name path is just a segment it must be a
     567     * direct parent of the source and can be written as a simple name segment
     568     * due to the default search rules.
     569     */
     570    uint32_t cParentPrefixes =   (   rtAcpiNsLookupSubTree(aNsEntriesSrc[idxEntrySrc], pszNameStringDst)
     571                                  || pszNameStringDst[4] == '\0')
     572                               ? 0
     573                               : idxEntrySrc + 1;
     574    /* Only overwrite with our result if it is shorter. */
     575    if (cParentPrefixes + cchNameStringNew < cchNameStringDst)
     576    {
     577        for (uint32_t i = 0; i < cParentPrefixes; i++)
     578            pszNameStringRel[i] = '^';
     579        memcpy(&pszNameStringRel[cParentPrefixes], pszNameStringDst, cchNameStringNew + 1);
     580    }
     581    return VINF_SUCCESS;
     582}
     583
     584
    352585DECLHIDDEN(int) rtAcpiNsPop(PRTACPINSROOT pNsRoot)
    353586{
     
    358591
    359592
    360 DECLHIDDEN(PCRTACPINSENTRY) rtAcpiNsLookup(PRTACPINSROOT pNsRoot, const char *pszNameString)
     593DECLHIDDEN(PRTACPINSENTRY) rtAcpiNsLookup(PRTACPINSROOT pNsRoot, const char *pszNameString)
    361594{
    362595    return rtAcpiNsLookupWorker(pNsRoot, pszNameString, false /*fExcludeLast*/, NULL /*ppszNameSegLast*/);
    363596}
     597
     598
     599DECLHIDDEN(PCRTACPINSENTRY) rtAcpiNsGetCurrent(PCRTACPINSROOT pNsRoot)
     600{
     601    return pNsRoot->aNsStack[pNsRoot->idxNsStack];
     602}
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