cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/* $Id$ */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** @file
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * VirtualBox Validation Kit - Testbox C Helper Utility.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Copyright (C) 2012-2014 Oracle Corporation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
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 *
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 *
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
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Header Files *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/buildconfig.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/env.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/initterm.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/message.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/mp.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/string.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/stream.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/system.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# include <iprt/x86.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# include <iprt/asm-amd64-x86.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#ifdef RT_OS_DARWIN
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# include <sys/types.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# include <sys/sysctl.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
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.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerReport(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF(argc); NOREF(argv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
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 */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("CPUID Dump\n"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "Leaf eax ebx ecx edx\n"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "---------------------------------------------\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync static uint32_t const s_auRanges[] =
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync UINT32_C(0x00000000),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync UINT32_C(0x80000000),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync UINT32_C(0x80860000),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync UINT32_C(0xc0000000),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync UINT32_C(0x40000000),
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync };
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (uint32_t iRange = 0; iRange < RT_ELEMENTS(s_auRanges); iRange++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t const uFirst = s_auRanges[iRange];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uEax, uEbx, uEcx, uEdx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuIdExSlow(uFirst, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uEax >= uFirst && uEax < uFirst + 100)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t const cLeafs = RT_MIN(uEax - uFirst + 1, 32);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (uint32_t iLeaf = 0; iLeaf < cLeafs; iLeaf++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uLeaf = uFirst + iLeaf;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuIdExSlow(uLeaf, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Clear APIC IDs to avoid submitting new reports all the time. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uLeaf == 1)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uEbx &= UINT32_C(0x00ffffff);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uLeaf == 0xb)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uEdx = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uLeaf == 0x8000001e)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uEax = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* Clear some other node/cpu/core/thread ids. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uLeaf == 0x8000001e)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uEbx &= UINT32_C(0xffffff00);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uEcx &= UINT32_C(0xffffff00);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("%08x: %08x %08x %08x %08x\n", uLeaf, uEax, uEbx, uEcx, uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * DMI info.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("DMI Info\n"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "--------\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync static const struct { const char *pszName; RTSYSDMISTR enmDmiStr; } s_aDmiStrings[] =
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "Product Name", RTSYSDMISTR_PRODUCT_NAME },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "Product version", RTSYSDMISTR_PRODUCT_VERSION },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "Product UUID", RTSYSDMISTR_PRODUCT_UUID },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "Product Serial", RTSYSDMISTR_PRODUCT_SERIAL },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "System Manufacturer", RTSYSDMISTR_MANUFACTURER },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync };
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (uint32_t iDmiString = 0; iDmiString < RT_ELEMENTS(s_aDmiStrings); iDmiString++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char szTmp[4096];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RT_ZERO(szTmp);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTSystemQueryDmiString(s_aDmiStrings[iDmiString].enmDmiStr, szTmp, sizeof(szTmp) - 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("%25s: %s\n", s_aDmiStrings[iDmiString].pszName, RTStrStrip(szTmp));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("%25s: %s [rc=%Rrc]\n", s_aDmiStrings[iDmiString].pszName, RTStrStrip(szTmp), rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Dump the environment.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("Environment\n"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "-----------\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTENV hEnv;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTEnvClone(&hEnv, RTENV_DEFAULT);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t cVars = RTEnvCountEx(hEnv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (uint32_t iVar = 0; iVar < cVars; iVar++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char szVar[1024];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char szValue[16384];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTEnvGetByIndexEx(hEnv, iVar, szVar, sizeof(szVar), szValue, sizeof(szValue));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* zap the value of variables that are subject to change. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync && ( !strcmp(szVar, "TESTBOX_SCRIPT_REV")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(szVar, "TESTBOX_ID")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(szVar, "TESTBOX_SCRATCH_SIZE")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(szVar, "TESTBOX_TIMEOUT")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(szVar, "TESTBOX_TIMEOUT_ABS")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(szVar, "TESTBOX_TEST_SET_ID")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync )
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync )
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync strcpy(szValue, "<volatile>");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("%25s=%s\n", szVar, szValue);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (rc == VERR_BUFFER_OVERFLOW)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("%25s=%s [VERR_BUFFER_OVERFLOW]\n", szVar, szValue);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("rc=%Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTEnvDestroy(hEnv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** @todo enumerate volumes and whatnot. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf("\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Print the total memory size in bytes. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerMemSize(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF(argc); NOREF(argv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t cb;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTSystemQueryTotalRam(&cb);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf("%llu\n", cb);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("%Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynctypedef enum { HWVIRTTYPE_NONE, HWVIRTTYPE_VTX, HWVIRTTYPE_AMDV } HWVIRTTYPE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic HWVIRTTYPE isHwVirtSupported(void)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uEax, uEbx, uEcx, uEdx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* VT-x */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuId(0x00000000, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (ASMIsValidStdRange(uEax))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuId(0x00000001, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uEcx & X86_CPUID_FEATURE_ECX_VMX)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return HWVIRTTYPE_VTX;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* AMD-V */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (ASMIsValidExtRange(uEax))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuId(0x80000001, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uEcx & X86_CPUID_AMD_FEATURE_ECX_SVM)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return HWVIRTTYPE_AMDV;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return HWVIRTTYPE_NONE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Print the 'true' if VT-x or AMD-v is supported, 'false' it not. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerCpuHwVirt(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF(argc); NOREF(argv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf(isHwVirtSupported() != HWVIRTTYPE_NONE ? "true\n" : "false\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
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{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF(argc); NOREF(argv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync HWVIRTTYPE enmHwVirt = isHwVirtSupported();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int fSupported = -1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (enmHwVirt == HWVIRTTYPE_AMDV)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uEax, uEbx, uEcx, uEdx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (ASMIsValidExtRange(uEax) && uEax >= 0x8000000a)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuId(0x8000000a, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uEdx & RT_BIT(0) /* AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING */)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fSupported = 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fSupported = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf(fSupported == 1 ? "true\n" : fSupported == 0 ? "false\n" : "dunno\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
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{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF(argc); NOREF(argv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync HWVIRTTYPE enmHwVirt = isHwVirtSupported();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int fSupported = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (enmHwVirt != HWVIRTTYPE_NONE)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if defined(RT_ARCH_AMD64)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fSupported = 1; /* We're running long mode, so it must be supported. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#elif defined(RT_ARCH_X86)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# ifdef RT_OS_DARWIN
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* On darwin, we just ask the kernel via sysctl. Rules are a bit different here. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int f64bitCapable = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t cbParameter = sizeof(f64bitCapable);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = sysctlbyname("hw.cpu64bit_capable", &f64bitCapable, &cbParameter, NULL, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rc != -1)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fSupported = f64bitCapable != 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync# endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* PAE and HwVirt are required */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uEax, uEbx, uEcx, uEdx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuId(0x00000000, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (ASMIsValidStdRange(uEax))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuId(0x00000001, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uEdx & X86_CPUID_FEATURE_EDX_PAE)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* AMD will usually advertise long mode in 32-bit mode. Intel OTOH,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync won't necessarily do so. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (ASMIsValidExtRange(uEax))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuId(0x80000001, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (uEdx & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fSupported = 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (enmHwVirt != HWVIRTTYPE_AMDV)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fSupported = -1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf(fSupported == 1 ? "true\n" : fSupported == 0 ? "false\n" : "dunno\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Print the CPU 'revision', if available. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerCpuRevision(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF(argc); NOREF(argv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uEax, uEbx, uEcx, uEdx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuId(0, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (ASMIsValidStdRange(uEax) && uEax >= 1)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uEax1 = ASMCpuId_EAX(1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uVersion = (ASMGetCpuFamily(uEax1) << 24)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync | (ASMGetCpuModel(uEax1, ASMIsIntelCpuEx(uEbx, uEcx, uEdx)) << 8)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync | ASMGetCpuStepping(uEax1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf("%#x\n", uVersion);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Print the CPU name, if available. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerCpuName(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF(argc); NOREF(argv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char szTmp[1024];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTMpGetDescription(NIL_RTCPUID, szTmp, sizeof(szTmp));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf("%s\n", RTStrStrip(szTmp));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Print the CPU vendor name, 'GenuineIntel' and such. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic RTEXITCODE handlerCpuVendor(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF(argc); NOREF(argv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t uEax, uEbx, uEcx, uEdx;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMCpuId(0, &uEax, &uEbx, &uEcx, &uEdx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf("%.04s%.04s%.04s\n", &uEbx, &uEdx, &uEcx);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int cch = RTPrintf("%s\n", RTBldCfgTargetArch());
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncint main(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTR3InitExe(argc, &argv, 0);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTMsgInitFailure(rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The first argument is a command. Figure out which and call its handler.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync static const struct
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const char *pszCommand;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTEXITCODE (*pfnHandler)(int argc, char **argv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fNoArgs;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync } s_aHandlers[] =
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "cpuvendor", handlerCpuVendor, true },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "cpuname", handlerCpuName, true },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "cpurevision", handlerCpuRevision, true },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "cpuhwvirt", handlerCpuHwVirt, true },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "nestedpaging", handlerCpuNestedPaging, true },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "longmode", handlerCpuLongMode, true },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "memsize", handlerMemSize, true },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "report", handlerReport, true }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync };
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (argc < 2)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTMsgErrorExit(RTEXITCODE_SYNTAX, "expected command as the first argument");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (unsigned i = 0; i < RT_ELEMENTS(s_aHandlers); i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!strcmp(argv[1], s_aHandlers[i].pszCommand))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( s_aHandlers[i].fNoArgs
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync && argc != 2)
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 }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Help or version query?
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (int i = 1; i < argc; i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( !strcmp(argv[i], "--help")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(argv[i], "-h")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(argv[i], "-?")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(argv[i], "help") )
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("usage: %s <cmd> [cmd specific args]\n"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "\n"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "commands:\n", argv[0]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (unsigned j = 0; j < RT_ELEMENTS(s_aHandlers); j++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf(" %s\n", s_aHandlers[j].pszCommand);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if ( !strcmp(argv[i], "--version")
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || !strcmp(argv[i], "-V") )
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("%sr%u", RTBldCfgVersion(), RTBldCfgRevision());
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return argc == 2 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Syntax error.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTMsgErrorExit(RTEXITCODE_SYNTAX, "unknown command '%s'", argv[1]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync