CFGM.cpp revision b3547e42ce5221377866e3fa041b3086b7cc1562
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * CFGM - Configuration Manager.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Copyright (C) 2006-2008 Sun Microsystems, Inc.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * available from http://www.virtualbox.org. This file is free software;
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * you can redistribute it and/or modify it under the terms of the GNU
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * General Public License (GPL) as published by the Free Software
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * additional information or have any questions.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/** @page pg_cfgm CFGM - The Configuration Manager
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * The configuration manager is a directory containing the VM configuration at
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * run time. It works in a manner similar to the windows registry - it's like a
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * file system hierarchy, but the files (values) live in a separate name space
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * and can include the path separators.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * The configuration is normally created via a callback passed to VMR3Create()
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * via the pfnCFGMConstructor parameter. To make testcase writing a bit simpler,
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * we allow the callback to be NULL, in which case a simple default
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * configuration will be created by cfgmR3CreateDefaultTree(). The
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Console::configConstructor() method in Main/ConsoleImpl2.cpp creates the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * configuration from the XML.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Devices, drivers, services and other PDM stuff are given their own subtree
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * where they are protected from accessing information of any parents. This is
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * is implemented via the CFGMR3SetRestrictedRoot() API.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Data validation out over the basic primitives is left to the caller. The
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * caller is in a better position to know the proper validation rules of the
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * individual properties.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @see grp_cfgm
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @section sec_cfgm_primitives Data Primitives
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * CFGM supports the following data primitives:
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync * - Integers. Representation is unsigned 64-bit. Boolean, unsigned and
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync * small integers, and pointers are all represented using this primitive.
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync * - Zero terminated character strings. These are of course UTF-8.
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync * - Variable length byte strings. This can be used to get/put binary
8608612b77e4d9bccdd4ff30a40ce7cc68966570vboxsync * objects like for instance RTMAC.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync/*******************************************************************************
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync* Header Files *
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync*******************************************************************************/
022e56bff837db399121bc76e4f404a6cd959d6evboxsync/*******************************************************************************
022e56bff837db399121bc76e4f404a6cd959d6evboxsync* Internal Functions *
022e56bff837db399121bc76e4f404a6cd959d6evboxsync*******************************************************************************/
022e56bff837db399121bc76e4f404a6cd959d6evboxsyncstatic void cfgmR3DumpPath(PCFGMNODE pNode, PCDBGFINFOHLP pHlp);
022e56bff837db399121bc76e4f404a6cd959d6evboxsyncstatic void cfgmR3Dump(PCFGMNODE pRoot, unsigned iLevel, PCDBGFINFOHLP pHlp);
022e56bff837db399121bc76e4f404a6cd959d6evboxsyncstatic DECLCALLBACK(void) cfgmR3Info(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
022e56bff837db399121bc76e4f404a6cd959d6evboxsyncstatic int cfgmR3ResolveNode(PCFGMNODE pNode, const char *pszPath, PCFGMNODE *ppChild);
022e56bff837db399121bc76e4f404a6cd959d6evboxsyncstatic int cfgmR3ResolveLeaf(PCFGMNODE pNode, const char *pszName, PCFGMLEAF *ppLeaf);
022e56bff837db399121bc76e4f404a6cd959d6evboxsyncstatic int cfgmR3InsertLeaf(PCFGMNODE pNode, const char *pszName, PCFGMLEAF *ppLeaf);
022e56bff837db399121bc76e4f404a6cd959d6evboxsyncstatic void cfgmR3RemoveLeaf(PCFGMNODE pNode, PCFGMLEAF pLeaf);
c6ccc50e63b794d6ef52f52de638eeb08c61417evboxsync * Constructs the configuration for the VM.
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync * @returns VBox status code.
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync * @param pVM Pointer to VM which configuration has not yet been loaded.
c6ccc50e63b794d6ef52f52de638eeb08c61417evboxsync * @param pfnCFGMConstructor Pointer to callback function for constructing the VM configuration tree.
c6ccc50e63b794d6ef52f52de638eeb08c61417evboxsync * This is called in the EM.
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync * @param pvUser The user argument passed to pfnCFGMConstructor.
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync * @thread EMT.
864051af8bf1aae6d2b5c52529b348234f22541dvboxsyncVMMR3DECL(int) CFGMR3Init(PVM pVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUser)
864051af8bf1aae6d2b5c52529b348234f22541dvboxsync LogFlow(("CFGMR3Init: pfnCFGMConstructor=%p pvUser=%p\n", pfnCFGMConstructor, pvUser));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Init data members.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Register DBGF into item.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int rc = DBGFR3InfoRegisterInternal(pVM, "cfgm", "Dumps a part of the CFGM tree. The argument indicates where to start.", cfgmR3Info);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Create the configuration tree.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Root Node.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync PCFGMNODE pRoot = (PCFGMNODE)MMR3HeapAllocZ(pVM, MM_TAG_CFGM, sizeof(*pRoot));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Call the constructor.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync Log(("CFGMR3Init: Successfully constructed the configuration\n"));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync NOT_DMIK(AssertMsgFailed(("Constructor failed with rc=%Rrc pfnCFGMConstructor=%p\n", rc, pfnCFGMConstructor)));
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Terminates the configuration manager.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns VBox status code.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pVM VM handle.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Gets the root node for the VM.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns Pointer to root node.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pVM VM handle.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Gets the parent of a CFGM node.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns Pointer to the parent node.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns NULL if pNode is Root or pNode is the start of a
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * restricted subtree (use CFGMr3GetParentEx() for that).
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pNode The node which parent we query.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncVMMR3DECL(PCFGMNODE) CFGMR3GetParent(PCFGMNODE pNode)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Gets the parent of a CFGM node.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns Pointer to the parent node.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns NULL if pNode is Root or pVM is not correct.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pVM The VM handle, used as token that the caller is trusted.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pNode The node which parent we query.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncVMMR3DECL(PCFGMNODE) CFGMR3GetParentEx(PVM pVM, PCFGMNODE pNode)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Query a child node.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns Pointer to the specified node.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns NULL if node was not found or pNode is NULL.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pNode Node pszPath is relative to.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pszPath Path to the child node or pNode.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * It's good style to end this with '/'.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncVMMR3DECL(PCFGMNODE) CFGMR3GetChild(PCFGMNODE pNode, const char *pszPath)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int rc = cfgmR3ResolveNode(pNode, pszPath, &pChild);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Query a child node by a format string.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns Pointer to the specified node.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns NULL if node was not found or pNode is NULL.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pNode Node pszPath is relative to.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pszPathFormat Path to the child node or pNode.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * It's good style to end this with '/'.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param ... Arguments to pszPathFormat.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncVMMR3DECL(PCFGMNODE) CFGMR3GetChildF(PCFGMNODE pNode, const char *pszPathFormat, ...)
81b3101ea5e60964f67c97185bbd43dbf75c5ab5vboxsync PCFGMNODE pRet = CFGMR3GetChildFV(pNode, pszPathFormat, Args);
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * Query a child node by a format string.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns Pointer to the specified node.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @returns NULL if node was not found or pNode is NULL.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pNode Node pszPath is relative to.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param pszPathFormat Path to the child node or pNode.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * It's good style to end this with '/'.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync * @param Args Arguments to pszPathFormat.
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsyncVMMR3DECL(PCFGMNODE) CFGMR3GetChildFV(PCFGMNODE pNode, const char *pszPathFormat, va_list Args)
e0e0c19eefceaf5d4ec40f9466b58a771f50e799vboxsync int rc = cfgmR3ResolveNode(pNode, pszPath, &pChild);
int rc;
if (pCur)
return rc;
if (pNode)
while (*psz)
if (!*psz)
int rc;
if (pCur)
return rc;
if (pNode)
while (*psz)
if (!*psz)
if (penmType)
return rc;
case CFGMVALUETYPE_INTEGER:
case CFGMVALUETYPE_STRING:
case CFGMVALUETYPE_BYTES:
return rc;
return rc;
VMMR3DECL(int) CFGMR3QueryIntegerDef(PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def)
return rc;
VMMR3DECL(int) CFGMR3QueryString(PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString)
return rc;
VMMR3DECL(int) CFGMR3QueryStringDef(PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef)
return rc;
return rc;
int rc;
if (!pRoot)
return VERR_NO_MEMORY;
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
#ifdef DEBUG
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
UPDATERC();
return rcAll;
if (pNode)
pszPath++;
if (!*pszPath)
if (!pChild)
return VERR_CFGM_INVALID_CHILD_PATH;
return VINF_SUCCESS;
if (!pszNext)
if (!pChild)
return VERR_CFGM_CHILD_NOT_FOUND;
return VERR_CFGM_NO_PARENT;
int rc;
if (pNode)
while (pLeaf)
return VINF_SUCCESS;
return rc;
if (pNew)
return pNew;
VMMR3DECL(int) CFGMR3InsertSubTree(PCFGMNODE pNode, const char *pszName, PCFGMNODE pSubTree, PCFGMNODE *ppChild)
if (ppChild)
return rc;
int rc;
if (pNode)
pszName++;
if (pszDup)
if (pszNext)
pszNext++;
if (!pChild)
if (!pszNext)
if (ppChild)
else if (!pszNext)
else if (*pszName)
if (pPrev)
return VERR_CFGM_NODE_EXISTS;
if (pNew)
if (pPrev)
if (ppChild)
return rc;
VMMR3DECL(int) CFGMR3InsertNodeF(PCFGMNODE pNode, PCFGMNODE *ppChild, const char *pszNameFormat, ...)
return rc;
VMMR3DECL(int) CFGMR3InsertNodeFV(PCFGMNODE pNode, PCFGMNODE *ppChild, const char *pszNameFormat, va_list Args)
int rc;
char *pszName;
if (pszName)
return rc;
if (pNode)
int rc;
if (*pszName)
if (pNode)
if (pPrev)
return VERR_CFGM_LEAF_EXISTS;
if (pNew)
if (pPrev)
return rc;
if (pNode)
if (pLeaf)
case CFGMVALUETYPE_BYTES:
case CFGMVALUETYPE_STRING:
case CFGMVALUETYPE_INTEGER:
return rc;
int rc;
if (pNode)
char *pszStringCopy = (char *)MMR3HeapAlloc(pNode->pVM, MM_TAG_CFGM_STRING, RT_ALIGN_Z(cchString, 16));
if (pszStringCopy)
return rc;
VMMR3DECL(int) CFGMR3InsertBytes(PCFGMNODE pNode, const char *pszName, const void *pvBytes, size_t cbBytes)
int rc;
if (pNode)
return rc;
return rc;
VMMR3DECL(int) CFGMR3QueryU64Def(PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def)
return rc;
VMMR3DECL(int) CFGMR3QueryS64Def(PCFGMNODE pNode, const char *pszName, int64_t *pi64, int64_t i64Def)
return rc;
return rc;
VMMR3DECL(int) CFGMR3QueryU32Def(PCFGMNODE pNode, const char *pszName, uint32_t *pu32, uint32_t u32Def)
return rc;
return rc;
VMMR3DECL(int) CFGMR3QueryS32Def(PCFGMNODE pNode, const char *pszName, int32_t *pi32, int32_t i32Def)
return rc;
return rc;
VMMR3DECL(int) CFGMR3QueryU16Def(PCFGMNODE pNode, const char *pszName, uint16_t *pu16, uint16_t u16Def)
return rc;
return rc;
VMMR3DECL(int) CFGMR3QueryS16Def(PCFGMNODE pNode, const char *pszName, int16_t *pi16, int16_t i16Def)
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
VMMR3DECL(int) CFGMR3QueryPortDef(PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort, RTIOPORT PortDef)
VMMR3DECL(int) CFGMR3QueryUIntDef(PCFGMNODE pNode, const char *pszName, unsigned int *pu, unsigned int uDef)
VMMR3DECL(int) CFGMR3QuerySIntDef(PCFGMNODE pNode, const char *pszName, signed int *pi, signed int iDef)
if (u64 == u)
*ppv = (void *)u;
return rc;
if (u64 == u)
*ppv = (void *)u;
return rc;
if (u64 == u)
*pGCPtr = u;
return rc;
VMMR3DECL(int) CFGMR3QueryGCPtrDef(PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr, RTGCPTR GCPtrDef)
if (u64 == u)
*pGCPtr = u;
return rc;
if (u64 == u)
*pGCPtr = u;
return rc;
VMMR3DECL(int) CFGMR3QueryGCPtrUDef(PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr, RTGCUINTPTR GCPtrDef)
if (u64 == u)
*pGCPtr = u;
return rc;
*pGCPtr = u;
return rc;
VMMR3DECL(int) CFGMR3QueryGCPtrSDef(PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr, RTGCINTPTR GCPtrDef)
*pGCPtr = u;
return rc;
if (pszString)
return rc;
VMMR3DECL(int) CFGMR3QueryStringAllocDef(PCFGMNODE pNode, const char *pszName, char **ppszString, const char *pszDef)
if (pszString)
return rc;
pHlp->pfnPrintf(pHlp, "] (level %d)%s\n", iLevel, pRoot->fRestrictedRoot ? " (restricted root)" : "");
unsigned cchMax = 0;
case CFGMVALUETYPE_INTEGER:
pHlp->pfnPrintf(pHlp, " %-*s <integer> = %#018llx (%lld)\n", cchMax, pLeaf->szName, pLeaf->Value.Integer.u64, pLeaf->Value.Integer.u64);
case CFGMVALUETYPE_STRING:
pHlp->pfnPrintf(pHlp, " %-*s <string> = \"%s\" (cch=%d)\n", cchMax, pLeaf->szName, pLeaf->Value.String.psz, pLeaf->Value.String.cch);
case CFGMVALUETYPE_BYTES: