cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * VirtualBox Validation Kit - Testbox C Helper Utility.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Copyright (C) 2012-2014 Oracle Corporation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * available from http://www.virtualbox.org. This file is free software;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * General Public License (GPL) as published by the Free Software
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The contents of this file may alternatively be used under the terms
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * of the Common Development and Distribution License Version 1.0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * VirtualBox OSE distribution, in which case the provisions of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * CDDL are applicable instead of those of the GPL.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * You may elect to license modified versions of this file under the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * terms and conditions of either the GPL or the CDDL or both.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Header Files *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Generates a kind of report of the hardware, software and whatever else we
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * think might be useful to know about the testbox.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerReport(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * For now, a simple CPUID dump. Need to figure out how to share code
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * like this with other bits, putting it in IPRT.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "Leaf eax ebx ecx edx\n"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "---------------------------------------------\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (uint32_t iRange = 0; iRange < RT_ELEMENTS(s_auRanges); iRange++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuIdExSlow(uFirst, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t const cLeafs = RT_MIN(uEax - uFirst + 1, 32);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuIdExSlow(uLeaf, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Clear APIC IDs to avoid submitting new reports all the time. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("%08x: %08x %08x %08x %08x\n", uLeaf, uEax, uEbx, uEcx, uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * DMI info.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "--------\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync static const struct { const char *pszName; RTSYSDMISTR enmDmiStr; } s_aDmiStrings[] =
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "Product version", RTSYSDMISTR_PRODUCT_VERSION },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "System Manufacturer", RTSYSDMISTR_MANUFACTURER },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (uint32_t iDmiString = 0; iDmiString < RT_ELEMENTS(s_aDmiStrings); iDmiString++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTSystemQueryDmiString(s_aDmiStrings[iDmiString].enmDmiStr, szTmp, sizeof(szTmp) - 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("%25s: %s\n", s_aDmiStrings[iDmiString].pszName, RTStrStrip(szTmp));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("%25s: %s [rc=%Rrc]\n", s_aDmiStrings[iDmiString].pszName, RTStrStrip(szTmp), rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Dump the environment.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "-----------\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTEnvGetByIndexEx(hEnv, iVar, szVar, sizeof(szVar), szValue, sizeof(szValue));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* zap the value of variables that are subject to change. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("%25s=%s [VERR_BUFFER_OVERFLOW]\n", szVar, szValue);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** @todo enumerate volumes and whatnot. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Print the total memory size in bytes. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerMemSize(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynctypedef enum { HWVIRTTYPE_NONE, HWVIRTTYPE_VTX, HWVIRTTYPE_AMDV } HWVIRTTYPE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* AMD-V */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Print the 'true' if VT-x or AMD-v is supported, 'false' it not. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerCpuHwVirt(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf(isHwVirtSupported() != HWVIRTTYPE_NONE ? "true\n" : "false\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Print the 'true' if nested paging is supported, 'false' if not and
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * 'dunno' if we cannot tell. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerCpuNestedPaging(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (ASMIsValidExtRange(uEax) && uEax >= 0x8000000a)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uEdx & RT_BIT(0) /* AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING */)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf(fSupported == 1 ? "true\n" : fSupported == 0 ? "false\n" : "dunno\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Print the 'true' if long mode guests are supported, 'false' if not and
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * 'dunno' if we cannot tell. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerCpuLongMode(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fSupported = 1; /* We're running long mode, so it must be supported. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* On darwin, we just ask the kernel via sysctl. Rules are a bit different here. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = sysctlbyname("hw.cpu64bit_capable", &f64bitCapable, &cbParameter, NULL, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* PAE and HwVirt are required */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* AMD will usually advertise long mode in 32-bit mode. Intel OTOH,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync won't necessarily do so. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf(fSupported == 1 ? "true\n" : fSupported == 0 ? "false\n" : "dunno\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Print the CPU 'revision', if available. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerCpuRevision(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync | (ASMGetCpuModel(uEax1, ASMIsIntelCpuEx(uEbx, uEcx, uEdx)) << 8)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Print the CPU name, if available. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerCpuName(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTMpGetDescription(NIL_RTCPUID, szTmp, sizeof(szTmp));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Print the CPU vendor name, 'GenuineIntel' and such. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerCpuVendor(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf("%.04s%.04s%.04s\n", &uEbx, &uEdx, &uEcx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The first argument is a command. Figure out which and call its handler.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync static const struct
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTMsgErrorExit(RTEXITCODE_SYNTAX, "expected command as the first argument");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (unsigned i = 0; i < RT_ELEMENTS(s_aHandlers); i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTMsgErrorExit(RTEXITCODE_SYNTAX, "the command '%s' does not take any arguments", argv[1]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return s_aHandlers[i].pfnHandler(argc - 1, argv + 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Help or version query?
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (unsigned j = 0; j < RT_ELEMENTS(s_aHandlers); j++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("%sr%u", RTBldCfgVersion(), RTBldCfgRevision());
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return argc == 2 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Syntax error.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTMsgErrorExit(RTEXITCODE_SYNTAX, "unknown command '%s'", argv[1]);