TestBoxHelper.cpp revision cf22150eaeeb72431bf1cf65c309a431454fb22b
/* $Id$ */
/** @file
* VirtualBox Validation Kit - Testbox C Helper Utility.
*/
/*
* Copyright (C) 2012-2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <iprt/buildconfig.h>
#include <iprt/initterm.h>
#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
# include <iprt/asm-amd64-x86.h>
#endif
#ifdef RT_OS_DARWIN
#endif
/**
* Generates a kind of report of the hardware, software and whatever else we
* think might be useful to know about the testbox.
*/
{
#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
/*
* For now, a simple CPUID dump. Need to figure out how to share code
* like this with other bits, putting it in IPRT.
*/
RTPrintf("CPUID Dump\n"
"Leaf eax ebx ecx edx\n"
"---------------------------------------------\n");
static uint32_t const s_auRanges[] =
{
UINT32_C(0x00000000),
UINT32_C(0x80000000),
UINT32_C(0x80860000),
UINT32_C(0xc0000000),
UINT32_C(0x40000000),
};
{
{
{
/* Clear APIC IDs to avoid submitting new reports all the time. */
if (uLeaf == 1)
if (uLeaf == 0xb)
uEdx = 0;
if (uLeaf == 0x8000001e)
uEax = 0;
if (uLeaf == 0x8000001e)
{
}
}
}
}
RTPrintf("\n");
/*
* DMI info.
*/
RTPrintf("DMI Info\n"
"--------\n");
{
{ "Product Name", RTSYSDMISTR_PRODUCT_NAME },
{ "Product version", RTSYSDMISTR_PRODUCT_VERSION },
{ "Product UUID", RTSYSDMISTR_PRODUCT_UUID },
{ "Product Serial", RTSYSDMISTR_PRODUCT_SERIAL },
{ "System Manufacturer", RTSYSDMISTR_MANUFACTURER },
};
{
char szTmp[4096];
if (RT_SUCCESS(rc))
else
}
RTPrintf("\n");
#else
#endif
/*
* Dump the environment.
*/
RTPrintf("Environment\n"
"-----------\n");
if (RT_SUCCESS(rc))
{
{
char szVar[1024];
char szValue[16384];
/* zap the value of variables that are subject to change. */
)
)
if (RT_SUCCESS(rc))
else if (rc == VERR_BUFFER_OVERFLOW)
else
}
}
/** @todo enumerate volumes and whatnot. */
}
/** Print the total memory size in bytes. */
{
if (RT_SUCCESS(rc))
{
}
return RTEXITCODE_FAILURE;
}
static HWVIRTTYPE isHwVirtSupported(void)
{
#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
/* VT-x */
if (ASMIsValidStdRange(uEax))
{
if (uEcx & X86_CPUID_FEATURE_ECX_VMX)
return HWVIRTTYPE_VTX;
}
/* AMD-V */
if (ASMIsValidExtRange(uEax))
{
return HWVIRTTYPE_AMDV;
}
#endif
return HWVIRTTYPE_NONE;
}
/** Print the 'true' if VT-x or AMD-v is supported, 'false' it not. */
{
}
/** Print the 'true' if nested paging is supported, 'false' if not and
* 'dunno' if we cannot tell. */
{
int fSupported = -1;
#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
if (enmHwVirt == HWVIRTTYPE_AMDV)
{
{
fSupported = 1;
else
fSupported = 0;
}
}
#endif
}
/** Print the 'true' if long mode guests are supported, 'false' if not and
* 'dunno' if we cannot tell. */
{
int fSupported = 0;
if (enmHwVirt != HWVIRTTYPE_NONE)
{
#if defined(RT_ARCH_AMD64)
#elif defined(RT_ARCH_X86)
# ifdef RT_OS_DARWIN
/* On darwin, we just ask the kernel via sysctl. Rules are a bit different here. */
int f64bitCapable = 0;
if (rc != -1)
fSupported = f64bitCapable != 0;
else
# endif
{
/* PAE and HwVirt are required */
if (ASMIsValidStdRange(uEax))
{
if (uEdx & X86_CPUID_FEATURE_EDX_PAE)
{
/* AMD will usually advertise long mode in 32-bit mode. Intel OTOH,
won't necessarily do so. */
if (ASMIsValidExtRange(uEax))
{
fSupported = 1;
else if (enmHwVirt != HWVIRTTYPE_AMDV)
fSupported = -1;
}
}
}
}
#endif
}
}
/** Print the CPU 'revision', if available. */
{
#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
{
}
#endif
return RTEXITCODE_FAILURE;
}
/** Print the CPU name, if available. */
{
char szTmp[1024];
if (RT_SUCCESS(rc))
{
}
return RTEXITCODE_FAILURE;
}
/** Print the CPU vendor name, 'GenuineIntel' and such. */
{
#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
#else
#endif
}
{
if (RT_FAILURE(rc))
return RTMsgInitFailure(rc);
/*
* The first argument is a command. Figure out which and call its handler.
*/
static const struct
{
const char *pszCommand;
bool fNoArgs;
} s_aHandlers[] =
{
{ "cpuvendor", handlerCpuVendor, true },
{ "cpuname", handlerCpuName, true },
{ "cpurevision", handlerCpuRevision, true },
{ "cpuhwvirt", handlerCpuHwVirt, true },
{ "nestedpaging", handlerCpuNestedPaging, true },
{ "longmode", handlerCpuLongMode, true },
{ "memsize", handlerMemSize, true },
{ "report", handlerReport, true }
};
if (argc < 2)
for (unsigned i = 0; i < RT_ELEMENTS(s_aHandlers); i++)
{
{
if ( s_aHandlers[i].fNoArgs
&& argc != 2)
}
}
/*
* Help or version query?
*/
for (int i = 1; i < argc; i++)
{
RTPrintf("usage: %s <cmd> [cmd specific args]\n"
"\n"
"commands:\n", argv[0]);
for (unsigned j = 0; j < RT_ELEMENTS(s_aHandlers); j++)
return RTEXITCODE_FAILURE;
}
{
}
/*
* Syntax error.
*/
}