/** * Construct a DHCP server with a default configuration. */ VBoxNetDhcp::VBoxNetDhcp():VBoxNetBaseService("VBoxNetDhcp", "VBoxNetDhcp") { /* m_enmTrunkType = kIntNetTrunkType_WhateverNone; */ RTMAC mac; mac.au8[0] = 0x08; mac.au8[1] = 0x00; mac.au8[2] = 0x27; mac.au8[3] = 0x40; mac.au8[4] = 0x41; mac.au8[5] = 0x42; setMacAddress(mac); RTNETADDRIPV4 address; address.u = RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8( 10, 0, 2, 5))); setIpv4Address(address); setSendBufSize(8 * _1K); setRecvBufSize(50 * _1K); m_uCurMsgType = UINT8_MAX; m_cbCurMsg = 0; m_pCurMsg = NULL; memset(&m_CurHdrs, '\0', sizeof(m_CurHdrs)); m_fIgnoreCmdLineParameters = true; for(unsigned int i = 0; i < RT_ELEMENTS(g_aOptionDefs); ++i) addCommandLineOption(&g_aOptionDefs[i]); }
VBoxNetLwipNAT::VBoxNetLwipNAT(SOCKET icmpsock4, SOCKET icmpsock6) : VBoxNetBaseService("VBoxNetNAT", "nat-network") { LogFlowFuncEnter(); m_ProxyOptions.ipv6_enabled = 0; m_ProxyOptions.ipv6_defroute = 0; m_ProxyOptions.icmpsock4 = icmpsock4; m_ProxyOptions.icmpsock6 = icmpsock6; m_ProxyOptions.tftp_root = NULL; m_ProxyOptions.src4 = NULL; m_ProxyOptions.src6 = NULL; RT_ZERO(m_src4); RT_ZERO(m_src6); m_src4.sin_family = AF_INET; m_src6.sin6_family = AF_INET6; #if HAVE_SA_LEN m_src4.sin_len = sizeof(m_src4); m_src6.sin6_len = sizeof(m_src6); #endif m_ProxyOptions.nameservers = NULL; m_LwipNetIf.name[0] = 'N'; m_LwipNetIf.name[1] = 'T'; RTMAC mac; mac.au8[0] = 0x52; mac.au8[1] = 0x54; mac.au8[2] = 0; mac.au8[3] = 0x12; mac.au8[4] = 0x35; mac.au8[5] = 0; setMacAddress(mac); RTNETADDRIPV4 address; address.u = RT_MAKE_U32_FROM_U8( 10, 0, 2, 2); // NB: big-endian setIpv4Address(address); address.u = RT_H2N_U32_C(0xffffff00); setIpv4Netmask(address); fDontLoadRulesOnStartup = false; for(unsigned int i = 0; i < RT_ELEMENTS(g_aGetOptDef); ++i) addCommandLineOption(&g_aGetOptDef[i]); LogFlowFuncLeave(); }
RTDECL(uint32_t) ASMByteSwapU32(uint32_t u32) { return RT_MAKE_U32_FROM_U8(RT_BYTE4(u32), RT_BYTE3(u32), RT_BYTE2(u32), RT_BYTE1(u32)); }
RTDECL(int) RTCidrStrToIPv4(const char *pszAddress, PRTIPV4ADDR pNetwork, PRTIPV4ADDR pNetmask) { uint8_t cBits; uint8_t addr[4]; uint32_t u32Netmask; uint32_t u32Network; const char *psz = pszAddress; const char *pszNetmask; char *pszNext; int rc = VINF_SUCCESS; int cDelimiter = 0; int cDelimiterLimit = 0; AssertPtrReturn(pszAddress, VERR_INVALID_PARAMETER); AssertPtrReturn(pNetwork, VERR_INVALID_PARAMETER); AssertPtrReturn(pNetmask, VERR_INVALID_PARAMETER); pszNetmask = RTStrStr(psz, "/"); *(uint32_t *)addr = 0; if (!pszNetmask) cBits = 32; else { rc = RTStrToUInt8Ex(pszNetmask + 1, &pszNext, 10, &cBits); if ( RT_FAILURE(rc) || cBits > 32 || rc != VINF_SUCCESS) /* No trailing symbols are acceptable after the digit */ return VERR_INVALID_PARAMETER; } u32Netmask = ~(uint32_t)((1<< (32 - cBits)) - 1); if (cBits <= 8) cDelimiterLimit = 0; else if (cBits <= 16) cDelimiterLimit = 1; else if (cBits <= 24) cDelimiterLimit = 2; else if (cBits <= 32) cDelimiterLimit = 3; for (;;) { rc = RTStrToUInt8Ex(psz, &pszNext, 10, &addr[cDelimiter]); if ( RT_FAILURE(rc) || rc == VWRN_NUMBER_TOO_BIG) return VERR_INVALID_PARAMETER; if (*pszNext == '.') cDelimiter++; else if ( cDelimiter >= cDelimiterLimit && ( *pszNext == '\0' || *pszNext == '/')) break; else return VERR_INVALID_PARAMETER; if (cDelimiter > 3) /* not more than four octets */ return VERR_INVALID_PARAMETER; psz = pszNext + 1; } u32Network = RT_MAKE_U32_FROM_U8(addr[3], addr[2], addr[1], addr[0]); /* Corner case: see RFC 790 page 2 and RFC 4632 page 6. */ if ( addr[0] == 0 && ( *(uint32_t *)addr != 0 || u32Netmask == (uint32_t)~0)) return VERR_INVALID_PARAMETER; if ((u32Network & ~u32Netmask) != 0) return VERR_INVALID_PARAMETER; *pNetmask = u32Netmask; *pNetwork = u32Network; return VINF_SUCCESS; }
int main() { RTTEST hTest; int rc = RTTestInitAndCreate("tstRTGetOpt", &hTest); if (rc) return rc; RTGETOPTSTATE GetState; RTGETOPTUNION Val; #define CHECK(expr) do { if (!(expr)) { RTTestIFailed("error line %d (iNext=%d): %s\n", __LINE__, GetState.iNext, #expr); } } while (0) #define CHECK2(expr, fmt) \ do { \ if (!(expr)) { \ RTTestIFailed("error line %d (iNext=%d): %s\n", __LINE__, GetState.iNext, #expr); \ RTTestIFailureDetails fmt; \ } \ } while (0) #define CHECK_pDef(paOpts, i) \ CHECK2(Val.pDef == &(paOpts)[(i)], ("Got #%d (%p) expected #%d\n", (int)(Val.pDef - &(paOpts)[0]), Val.pDef, i)); #define CHECK_GETOPT(expr, chRet, iInc) \ do { \ const int iPrev = GetState.iNext; \ const int rcGetOpt = (expr); \ CHECK2(rcGetOpt == (chRet), ("got %d, expected %d\n", rcGetOpt, (chRet))); \ CHECK2(GetState.iNext == (iInc) + iPrev, ("iNext=%d expected %d\n", GetState.iNext, (iInc) + iPrev)); \ GetState.iNext = (iInc) + iPrev; \ } while (0) #define CHECK_GETOPT_STR(expr, chRet, iInc, str) \ do { \ const int iPrev = GetState.iNext; \ const int rcGetOpt = (expr); \ CHECK2(rcGetOpt == (chRet), ("got %d, expected %d\n", rcGetOpt, (chRet))); \ CHECK2(GetState.iNext == (iInc) + iPrev, ("iNext=%d expected %d\n", GetState.iNext, (iInc) + iPrev)); \ CHECK2(VALID_PTR(Val.psz) && !strcmp(Val.psz, (str)), ("got %s, expected %s\n", Val.psz, (str))); \ GetState.iNext = (iInc) + iPrev; \ } while (0) /* * The basics. */ RTTestSub(hTest, "Basics"); static const RTGETOPTDEF s_aOpts2[] = { { "--optwithstring", 's', RTGETOPT_REQ_STRING }, { "--optwithint", 'i', RTGETOPT_REQ_INT32 }, { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, { NULL, 'q', RTGETOPT_REQ_NOTHING }, { "--quiet", 384, RTGETOPT_REQ_NOTHING }, { "-novalue", 385, RTGETOPT_REQ_NOTHING }, { "-startvm", 386, RTGETOPT_REQ_STRING }, { "nodash", 387, RTGETOPT_REQ_NOTHING }, { "nodashval", 388, RTGETOPT_REQ_STRING }, { "--gateway", 'g', RTGETOPT_REQ_IPV4ADDR }, { "--mac", 'm', RTGETOPT_REQ_MACADDR }, { "--strindex", 400, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX }, { "strindex", 400, RTGETOPT_REQ_STRING | RTGETOPT_FLAG_INDEX }, { "--intindex", 401, RTGETOPT_REQ_INT32 | RTGETOPT_FLAG_INDEX }, { "--macindex", 402, RTGETOPT_REQ_MACADDR | RTGETOPT_FLAG_INDEX }, { "--indexnovalue", 403, RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_INDEX }, { "--macindexnegative", 404, RTGETOPT_REQ_NOTHING }, { "--twovalues", 405, RTGETOPT_REQ_STRING }, { "--twovaluesindex", 406, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_INDEX }, { "--threevalues", 407, RTGETOPT_REQ_UINT32 }, { "--boolean", 408, RTGETOPT_REQ_BOOL_ONOFF }, { "--booleanindex", 409, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX }, }; const char *argv2[] = { "-s", "string1", "-sstring2", "-s:string3", "-s=string4", "-s:", "-s=", "--optwithstring", "string5", "--optwithstring:string6", "--optwithstring=string7", "--optwithstring:", "--optwithstring=", "-i", "-42", "-i:-42", "-i=-42", "--optwithint", "42", "--optwithint:42", "--optwithint=42", "-v", "--verbose", "-q", "--quiet", "-novalue", "-startvm", "myvm", "nodash", "nodashval", "string9", "filename1", "-q", "filename2", "-vqi999", "-g192.168.1.1", "-m08:0:27:00:ab:f3", "--mac:1:::::c", "--strindex786", "string10", "--strindex786:string11", "--strindex786=string12", "strindex687", "string13", "strindex687:string14", "strindex687=string15", "strindex688:", "strindex689=", "--intindex137", "1000", "--macindex138", "08:0:27:00:ab:f3", "--indexnovalue1", "--macindexnegative", "--twovalues", "firstvalue", "secondvalue", "--twovalues:firstvalue", "secondvalue", "--twovaluesindex4", "1", "0xA", "--twovaluesindex5=2", "0xB", "--threevalues", "1", "0xC", "thirdvalue", /* bool on/off */ "--boolean", "on", "--boolean", "off", "--boolean", "invalid", "--booleanindex2", "on", "--booleanindex7", "off", "--booleanindex9", "invalid", /* standard options */ "--help", "-help", "-?", "-h", "--version", "-version", "-V", /* done */ NULL }; int argc2 = (int)RT_ELEMENTS(argv2) - 1; CHECK(RT_SUCCESS(RTGetOptInit(&GetState, argc2, (char **)argv2, &s_aOpts2[0], RT_ELEMENTS(s_aOpts2), 0, 0 /* fFlags */))); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 2); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string1")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string2")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string3")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string4")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 2); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string5")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string6")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string7")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 's', 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "")); CHECK(GetState.uIndex == UINT32_MAX); /* -i */ CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2); CHECK(Val.i32 == -42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == -42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == -42); /* --optwithint */ CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2); CHECK(Val.i32 == 42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == 42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == 42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'v', 1); CHECK_pDef(s_aOpts2, 2); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'v', 1); CHECK_pDef(s_aOpts2, 2); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'q', 1); CHECK_pDef(s_aOpts2, 3); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 384, 1); CHECK_pDef(s_aOpts2, 4); /* -novalue / -startvm (single dash long options) */ CHECK_GETOPT(RTGetOpt(&GetState, &Val), 385, 1); CHECK_pDef(s_aOpts2, 5); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 386, 2); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "myvm")); /* no-dash options */ CHECK_GETOPT(RTGetOpt(&GetState, &Val), 387, 1); CHECK_pDef(s_aOpts2, 7); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 388, 2); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string9")); /* non-option, option, non-option */ CHECK_GETOPT(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1); CHECK(Val.psz && !strcmp(Val.psz, "filename1")); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'q', 1); CHECK_pDef(s_aOpts2, 3); CHECK_GETOPT(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1); CHECK(Val.psz && !strcmp(Val.psz, "filename2")); /* compress short options */ CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'v', 0); CHECK_pDef(s_aOpts2, 2); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'q', 0); CHECK_pDef(s_aOpts2, 3); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == 999); /* IPv4 */ RTTestSub(hTest, "RTGetOpt - IPv4"); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'g', 1); CHECK(Val.IPv4Addr.u == RT_H2N_U32_C(RT_BSWAP_U32_C(RT_MAKE_U32_FROM_U8(192,168,1,1)))); /* Ethernet MAC address. */ RTTestSub(hTest, "RTGetOpt - MAC Address"); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'm', 1); CHECK( Val.MacAddr.au8[0] == 0x08 && Val.MacAddr.au8[1] == 0x00 && Val.MacAddr.au8[2] == 0x27 && Val.MacAddr.au8[3] == 0x00 && Val.MacAddr.au8[4] == 0xab && Val.MacAddr.au8[5] == 0xf3); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'm', 1); CHECK( Val.MacAddr.au8[0] == 0x01 && Val.MacAddr.au8[1] == 0x00 && Val.MacAddr.au8[2] == 0x00 && Val.MacAddr.au8[3] == 0x00 && Val.MacAddr.au8[4] == 0x00 && Val.MacAddr.au8[5] == 0x0c); /* string with indexed argument */ RTTestSub(hTest, "RTGetOpt - Option w/ Index"); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 2); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string10")); CHECK(GetState.uIndex == 786); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string11")); CHECK(GetState.uIndex == 786); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string12")); CHECK(GetState.uIndex == 786); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 2); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string13")); CHECK(GetState.uIndex == 687); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string14")); CHECK(GetState.uIndex == 687); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "string15")); CHECK(GetState.uIndex == 687); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "")); CHECK(GetState.uIndex == 688); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 400, 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "")); CHECK(GetState.uIndex == 689); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 401, 2); CHECK(Val.i32 == 1000); CHECK(GetState.uIndex == 137); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 402, 2); CHECK( Val.MacAddr.au8[0] == 0x08 && Val.MacAddr.au8[1] == 0x00 && Val.MacAddr.au8[2] == 0x27 && Val.MacAddr.au8[3] == 0x00 && Val.MacAddr.au8[4] == 0xab && Val.MacAddr.au8[5] == 0xf3); CHECK(GetState.uIndex == 138); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 403, 1); CHECK(GetState.uIndex == 1); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 404, 1); CHECK(GetState.uIndex == UINT32_MAX); /* RTGetOptFetchValue tests */ RTTestSub(hTest, "RTGetOptFetchValue"); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 405, 2); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "firstvalue")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "secondvalue")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 405, 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "firstvalue")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "secondvalue")); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 406, 2); CHECK(Val.u32 == 1); CHECK(GetState.uIndex == 4); CHECK_GETOPT(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_UINT32), VINF_SUCCESS, 1); CHECK(Val.u32 == 10); CHECK(GetState.uIndex == 4); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 406, 1); CHECK(Val.u32 == 2); CHECK(GetState.uIndex == 5); CHECK_GETOPT(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_UINT32), VINF_SUCCESS, 1); CHECK(Val.u32 == 11); CHECK(GetState.uIndex == 5); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 407, 2); CHECK(Val.u32 == 1); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_UINT32), VINF_SUCCESS, 1); CHECK(Val.u32 == 12); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "thirdvalue")); CHECK(GetState.uIndex == UINT32_MAX); /* bool on/off tests */ RTTestSub(hTest, "RTGetOpt - bool on/off"); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 408, 2); CHECK(Val.f); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 408, 2); CHECK(!Val.f); CHECK_GETOPT(RTGetOpt(&GetState, &Val), VERR_GETOPT_UNKNOWN_OPTION, 2); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "invalid")); /* bool on/off with indexed argument */ CHECK_GETOPT(RTGetOpt(&GetState, &Val), 409, 2); CHECK(Val.f); CHECK(GetState.uIndex == 2); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 409, 2); CHECK(!Val.f); CHECK(GetState.uIndex == 7); CHECK_GETOPT(RTGetOpt(&GetState, &Val), VERR_GETOPT_UNKNOWN_OPTION, 2); CHECK(VALID_PTR(Val.psz) && !strcmp(Val.psz, "invalid")); /* standard options. */ RTTestSub(hTest, "Standard options"); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'h', 1); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'h', 1); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'h', 1); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'h', 1); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'V', 1); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'V', 1); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'V', 1); /* the end */ CHECK_GETOPT(RTGetOpt(&GetState, &Val), 0, 0); CHECK(Val.pDef == NULL); CHECK(argc2 == GetState.iNext); /* * Options first. */ RTTestSub(hTest, "Options first"); const char *argv3[] = { "foo1", "-s", "string1", "foo2", "--optwithstring", "string2", "foo3", "-i", "-42", "foo4", "-i:-42", "-i=-42", "foo5", "foo6", "foo7", "-i:-42", "-i=-42", "foo8", "--twovalues", "firstvalue", "secondvalue", "foo9", "--twovalues:firstvalue", "secondvalue", "foo10", "--", "--optwithstring", "foo11", "foo12", /* done */ NULL }; int argc3 = (int)RT_ELEMENTS(argv3) - 1; CHECK(RT_SUCCESS(RTGetOptInit(&GetState, argc3, (char **)argv3, &s_aOpts2[0], RT_ELEMENTS(s_aOpts2), 0, RTGETOPTINIT_FLAGS_OPTS_FIRST))); /* -s */ CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 's', 2, "string1"); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 's', 2, "string2"); CHECK(GetState.uIndex == UINT32_MAX); /* -i */ CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2); CHECK(Val.i32 == -42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == -42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == -42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == -42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == -42); /* --twovalues */ CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 405, 2, "firstvalue"); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT_STR(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1, "secondvalue"); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 405, 1, "firstvalue"); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT_STR(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1, "secondvalue"); CHECK(GetState.uIndex == UINT32_MAX); /* -- */ CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 2, "foo1"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo2"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo3"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo4"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo5"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo6"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo7"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo8"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo9"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo10"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "--optwithstring"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo11"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo12"); /* the end */ CHECK_GETOPT(RTGetOpt(&GetState, &Val), 0, 0); CHECK(Val.pDef == NULL); CHECK(argc3 == GetState.iNext); /* * Options first, part 2: No dash-dash. */ const char *argv4[] = { "foo1", "-s", "string1", "foo2", "--optwithstring", "string2", "foo3", "-i", "-42", "foo4", "-i:-42", "-i=-42", "foo5", "foo6", "foo7", "-i:-42", "-i=-42", "foo8", "--twovalues", "firstvalue", "secondvalue", "foo9", "--twovalues:firstvalue", "secondvalue", "foo10", "foo11", "foo12", /* done */ NULL }; int argc4 = (int)RT_ELEMENTS(argv4) - 1; CHECK(RT_SUCCESS(RTGetOptInit(&GetState, argc4, (char **)argv4, &s_aOpts2[0], RT_ELEMENTS(s_aOpts2), 0, RTGETOPTINIT_FLAGS_OPTS_FIRST))); /* -s */ CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 's', 2, "string1"); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 's', 2, "string2"); CHECK(GetState.uIndex == UINT32_MAX); /* -i */ CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 2); CHECK(Val.i32 == -42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == -42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == -42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == -42); CHECK_GETOPT(RTGetOpt(&GetState, &Val), 'i', 1); CHECK(Val.i32 == -42); /* --twovalues */ CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 405, 2, "firstvalue"); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT_STR(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1, "secondvalue"); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), 405, 1, "firstvalue"); CHECK(GetState.uIndex == UINT32_MAX); CHECK_GETOPT_STR(RTGetOptFetchValue(&GetState, &Val, RTGETOPT_REQ_STRING), VINF_SUCCESS, 1, "secondvalue"); CHECK(GetState.uIndex == UINT32_MAX); /* -- */ CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo1"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo2"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo3"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo4"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo5"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo6"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo7"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo8"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo9"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo10"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo11"); CHECK_GETOPT_STR(RTGetOpt(&GetState, &Val), VINF_GETOPT_NOT_OPTION, 1, "foo12"); /* the end */ CHECK_GETOPT(RTGetOpt(&GetState, &Val), 0, 0); CHECK(Val.pDef == NULL); CHECK(argc4 == GetState.iNext); /* * Summary. */ return RTTestSummaryAndDestroy(hTest); }
/** * Initalizes the triple fault / boot hack. * * Always call vmmR0TripleFaultHackTerm to clean up, even when this call fails. * * @returns VBox status code. */ int vmmR0TripleFaultHackInit(void) { /* * Map the first page. */ int rc = RTR0MemObjEnterPhys(&g_hMemPage0, 0, PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE); AssertRCReturn(rc, rc); rc = RTR0MemObjMapKernel(&g_hMapPage0, g_hMemPage0, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE); AssertRCReturn(rc, rc); g_pbPage0 = (uint8_t *)RTR0MemObjAddress(g_hMapPage0); LogRel(("0040:0067 = %04x:%04x\n", RT_MAKE_U16(g_pbPage0[0x467+2], g_pbPage0[0x467+3]), RT_MAKE_U16(g_pbPage0[0x467+0], g_pbPage0[0x467+1]) )); /* * Allocate some "low core" memory. If that fails, just grab some memory. */ //rc = RTR0MemObjAllocPhys(&g_hMemLowCore, PAGE_SIZE, _1M - 1); //__debugbreak(); rc = RTR0MemObjEnterPhys(&g_hMemLowCore, 0x7000, PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE); AssertRCReturn(rc, rc); rc = RTR0MemObjMapKernel(&g_hMapLowCore, g_hMemLowCore, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE); AssertRCReturn(rc, rc); g_pbLowCore = (uint8_t *)RTR0MemObjAddress(g_hMapLowCore); g_HCPhysLowCore = RTR0MemObjGetPagePhysAddr(g_hMapLowCore, 0); LogRel(("Low core at %RHp mapped at %p\n", g_HCPhysLowCore, g_pbLowCore)); /* * Save memory we'll be overwriting. */ g_pvSavedLowCore = RTMemAlloc(PAGE_SIZE); AssertReturn(g_pvSavedLowCore, VERR_NO_MEMORY); memcpy(g_pvSavedLowCore, g_pbLowCore, PAGE_SIZE); g_u32SavedVector = RT_MAKE_U32_FROM_U8(g_pbPage0[0x467], g_pbPage0[0x467+1], g_pbPage0[0x467+2], g_pbPage0[0x467+3]); g_u16SavedCadIndicator = RT_MAKE_U16(g_pbPage0[0x472], g_pbPage0[0x472+1]); /* * Install the code. */ size_t cbCode = (uintptr_t)&vmmR0TripleFaultHackEnd - (uintptr_t)&vmmR0TripleFaultHackStart; AssertLogRelReturn(cbCode <= PAGE_SIZE, VERR_OUT_OF_RANGE); memcpy(g_pbLowCore, &vmmR0TripleFaultHackStart, cbCode); g_pbPage0[0x467+0] = 0x00; g_pbPage0[0x467+1] = 0x70; g_pbPage0[0x467+2] = 0x00; g_pbPage0[0x467+3] = 0x00; g_pbPage0[0x472+0] = 0x34; g_pbPage0[0x472+1] = 0x12; /* * Configure the status port and cmos shutdown command. */ uint32_t fSaved = ASMIntDisableFlags(); ASMOutU8(0x70, 0x0f); ASMOutU8(0x71, 0x0a); ASMOutU8(0x70, 0x05); ASMInU8(0x71); ASMReloadCR3(); ASMWriteBackAndInvalidateCaches(); ASMSetFlags(fSaved); #if 1 /* For testing & debugging. */ vmmR0TripleFaultHackTripleFault(); #endif return VINF_SUCCESS; }
void UIVMPreviewWindow::sltRecreatePreview() { /* Only do this if we are visible: */ if (!isVisible()) return; /* Remove preview if any: */ if (m_pPreviewImg) { delete m_pPreviewImg; m_pPreviewImg = 0; } /* We are not creating preview for inaccessible VMs: */ if (m_machineState == KMachineState_Null) return; if (!m_machine.isNull() && m_vRect.width() > 0 && m_vRect.height() > 0) { QImage image(size(), QImage::Format_ARGB32); image.fill(Qt::transparent); QPainter painter(&image); bool fDone = false; /* Preview enabled? */ if (m_pUpdateTimer->interval() > 0) { /* Use the image which may be included in the save state. */ if ( m_machineState == KMachineState_Saved || m_machineState == KMachineState_Restoring) { ULONG width = 0, height = 0; QVector<BYTE> screenData = m_machine.ReadSavedScreenshotPNGToArray(0, width, height); if (screenData.size() != 0) { QImage shot = QImage::fromData(screenData.data(), screenData.size(), "PNG").scaled(m_vRect.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); dimImage(shot); painter.drawImage(m_vRect.x(), m_vRect.y(), shot); fDone = true; } } /* Use the current VM output. */ else if ( m_machineState == KMachineState_Running // || m_machineState == KMachineState_Saving /* Not sure if this is valid */ || m_machineState == KMachineState_Paused) { if (m_session.GetState() == KSessionState_Locked) { CVirtualBox vbox = vboxGlobal().virtualBox(); if (vbox.isOk()) { const CConsole& console = m_session.GetConsole(); if (!console.isNull()) { CDisplay display = console.GetDisplay(); /* Todo: correct aspect radio */ // ULONG w, h, bpp; // display.GetScreenResolution(0, w, h, bpp); // QImage shot = QImage(w, h, QImage::Format_RGB32); // shot.fill(Qt::black); // display.TakeScreenShot(0, shot.bits(), shot.width(), shot.height()); QVector<BYTE> screenData = display.TakeScreenShotToArray(0, m_vRect.width(), m_vRect.height()); if ( display.isOk() && screenData.size() != 0) { /* Unfortunately we have to reorder the pixel * data, cause the VBox API returns RGBA data, * which is not a format QImage understand. * Todo: check for 32bit alignment, for both * the data and the scanlines. Maybe we need to * copy the data in any case. */ uint32_t *d = (uint32_t*)screenData.data(); for (int i = 0; i < screenData.size() / 4; ++i) { uint32_t e = d[i]; d[i] = RT_MAKE_U32_FROM_U8(RT_BYTE3(e), RT_BYTE2(e), RT_BYTE1(e), RT_BYTE4(e)); } QImage shot = QImage((uchar*)d, m_vRect.width(), m_vRect.height(), QImage::Format_RGB32); if (m_machineState == KMachineState_Paused) dimImage(shot); painter.drawImage(m_vRect.x(), m_vRect.y(), shot); fDone = true; } } } } } } if (fDone) m_pPreviewImg = new QImage(image); } update(); }
/** * Deals with complicated MMIO writes. * * Complicated means unaligned or non-dword/qword sized accesses depending on * the MMIO region's access mode flags. * * @returns Strict VBox status code. Any EM scheduling status code, * VINF_IOM_R3_MMIO_WRITE, VINF_IOM_R3_MMIO_READ_WRITE or * VINF_IOM_R3_MMIO_READ may be returned. * * @param pVM The cross context VM structure. * @param pVCpu The cross context virtual CPU structure of the calling EMT. * @param pRange The range to write to. * @param GCPhys The physical address to start writing. * @param pvValue Where to store the value. * @param cbValue The size of the value to write. */ static VBOXSTRICTRC iomMMIODoComplicatedWrite(PVM pVM, PVMCPU pVCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhys, void const *pvValue, unsigned cbValue) { AssertReturn( (pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) != IOMMMIO_FLAGS_WRITE_PASSTHRU && (pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) <= IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING, VERR_IOM_MMIO_IPE_1); AssertReturn(cbValue != 0 && cbValue <= 16, VERR_IOM_MMIO_IPE_2); RTGCPHYS const GCPhysStart = GCPhys; NOREF(GCPhysStart); bool const fReadMissing = (pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_DWORD_READ_MISSING || (pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING; /* * Do debug stop if requested. */ int rc = VINF_SUCCESS; NOREF(pVM); #ifdef VBOX_STRICT if (pRange->fFlags & IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_WRITE) { # ifdef IN_RING3 LogRel(("IOM: Complicated write %#x byte at %RGp to %s, initiating debugger intervention\n", cbValue, GCPhys, R3STRING(pRange->pszDesc))); rc = DBGFR3EventSrc(pVM, DBGFEVENT_DEV_STOP, RT_SRC_POS, "Complicated write %#x byte at %RGp to %s\n", cbValue, GCPhys, R3STRING(pRange->pszDesc)); if (rc == VERR_DBGF_NOT_ATTACHED) rc = VINF_SUCCESS; # else return VINF_IOM_R3_MMIO_WRITE; # endif } #endif /* * Check if we should ignore the write. */ if ((pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_ONLY_DWORD) { Assert(cbValue != 4 || (GCPhys & 3)); return VINF_SUCCESS; } if ((pRange->fFlags & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD) { Assert((cbValue != 4 && cbValue != 8) || (GCPhys & (cbValue - 1))); return VINF_SUCCESS; } /* * Split and conquer. */ for (;;) { unsigned const offAccess = GCPhys & 3; unsigned cbThisPart = 4 - offAccess; if (cbThisPart > cbValue) cbThisPart = cbValue; /* * Get the missing bits (if any). */ uint32_t u32MissingValue = 0; if (fReadMissing && cbThisPart != 4) { int rc2 = pRange->CTX_SUFF(pfnReadCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhys & ~(RTGCPHYS)3, &u32MissingValue, sizeof(u32MissingValue)); switch (rc2) { case VINF_SUCCESS: break; case VINF_IOM_MMIO_UNUSED_FF: u32MissingValue = UINT32_C(0xffffffff); break; case VINF_IOM_MMIO_UNUSED_00: u32MissingValue = 0; break; #ifndef IN_RING3 case VINF_IOM_R3_MMIO_READ: case VINF_IOM_R3_MMIO_READ_WRITE: case VINF_IOM_R3_MMIO_WRITE: LogFlow(("iomMMIODoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [read]\n", GCPhys, GCPhysStart, cbValue, rc2)); rc2 = VBOXSTRICTRC_TODO(iomMmioRing3WritePending(pVCpu, GCPhys, pvValue, cbValue, pRange)); if (rc == VINF_SUCCESS || rc2 < rc) rc = rc2; return rc; #endif default: if (RT_FAILURE(rc2)) { Log(("iomMMIODoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [read]\n", GCPhys, GCPhysStart, cbValue, rc2)); return rc2; } AssertMsgReturn(rc2 >= VINF_EM_FIRST && rc2 <= VINF_EM_LAST, ("%Rrc\n", rc2), VERR_IPE_UNEXPECTED_INFO_STATUS); if (rc == VINF_SUCCESS || rc2 < rc) rc = rc2; break; } } /* * Merge missing and given bits. */ uint32_t u32GivenMask; uint32_t u32GivenValue; switch (cbThisPart) { case 1: u32GivenValue = *(uint8_t const *)pvValue; u32GivenMask = UINT32_C(0x000000ff); break; case 2: u32GivenValue = *(uint16_t const *)pvValue; u32GivenMask = UINT32_C(0x0000ffff); break; case 3: u32GivenValue = RT_MAKE_U32_FROM_U8(((uint8_t const *)pvValue)[0], ((uint8_t const *)pvValue)[1], ((uint8_t const *)pvValue)[2], 0); u32GivenMask = UINT32_C(0x00ffffff); break; case 4: u32GivenValue = *(uint32_t const *)pvValue; u32GivenMask = UINT32_C(0xffffffff); break; default: AssertFailedReturn(VERR_IOM_MMIO_IPE_3); } if (offAccess) { u32GivenValue <<= offAccess * 8; u32GivenMask <<= offAccess * 8; } uint32_t u32Value = (u32MissingValue & ~u32GivenMask) | (u32GivenValue & u32GivenMask); /* * Do DWORD write to the device. */ int rc2 = pRange->CTX_SUFF(pfnWriteCallback)(pRange->CTX_SUFF(pDevIns), pRange->CTX_SUFF(pvUser), GCPhys & ~(RTGCPHYS)3, &u32Value, sizeof(u32Value)); switch (rc2) { case VINF_SUCCESS: break; #ifndef IN_RING3 case VINF_IOM_R3_MMIO_READ: case VINF_IOM_R3_MMIO_READ_WRITE: case VINF_IOM_R3_MMIO_WRITE: Log3(("iomMMIODoComplicatedWrite: deferring GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [write]\n", GCPhys, GCPhysStart, cbValue, rc2)); AssertReturn(pVCpu->iom.s.PendingMmioWrite.cbValue == 0, VERR_IOM_MMIO_IPE_1); AssertReturn(cbValue + (GCPhys & 3) <= sizeof(pVCpu->iom.s.PendingMmioWrite.abValue), VERR_IOM_MMIO_IPE_2); pVCpu->iom.s.PendingMmioWrite.GCPhys = GCPhys & ~(RTGCPHYS)3; pVCpu->iom.s.PendingMmioWrite.cbValue = cbValue + (GCPhys & 3); *(uint32_t *)pVCpu->iom.s.PendingMmioWrite.abValue = u32Value; if (cbValue > cbThisPart) memcpy(&pVCpu->iom.s.PendingMmioWrite.abValue[4], (uint8_t const *)pvValue + cbThisPart, cbValue - cbThisPart); VMCPU_FF_SET(pVCpu, VMCPU_FF_IOM); if (rc == VINF_SUCCESS) rc = VINF_IOM_R3_MMIO_COMMIT_WRITE; return rc2; #endif default: if (RT_FAILURE(rc2)) { Log(("iomMMIODoComplicatedWrite: GCPhys=%RGp GCPhysStart=%RGp cbValue=%u rc=%Rrc [write]\n", GCPhys, GCPhysStart, cbValue, rc2)); return rc2; } AssertMsgReturn(rc2 >= VINF_EM_FIRST && rc2 <= VINF_EM_LAST, ("%Rrc\n", rc2), VERR_IPE_UNEXPECTED_INFO_STATUS); if (rc == VINF_SUCCESS || rc2 < rc) rc = rc2; break; } /* * Advance. */ cbValue -= cbThisPart; if (!cbValue) break; GCPhys += cbThisPart; pvValue = (uint8_t const *)pvValue + cbThisPart; } return rc; }