/*********************************************************
- * Copyright (C) 2004-2019 VMware, Inc. All rights reserved.
+ * Copyright (c) 2004-2024 Broadcom. All Rights Reserved.
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
*
* NB: This library is *NOT* threadsafe, so if you want to avoid
* corrupting your log statements or other screwups, add your own
- * locking around calls to RpcVMX_Log.
+ * locking around calls to RpcVMX_Log. The exception is
+ * RpcVMX_LogVWithBuffer which does not use any global state but
+ * requires the caller to manage its own buffers.
*/
#ifndef _RPCVMX_H_
#include "rpcvmxext.h"
#define RPCVMX_MAX_LOG_LEN (2048) /* 2kb max - make it dynamic? */
+#define RPCVMX_LOG_BUFSIZE (RPCVMX_MAX_LOG_LEN + sizeof "log")
+
+typedef struct RpcVMXState {
+ char logBuf[RPCVMX_LOG_BUFSIZE];
+ unsigned int logOffset;
+} RpcVMXState;
+
/*
* Set a prefix to prepend to any future log statements.
const char *RpcVMX_LogGetPrefix(const char *prefix);
/*
- * Save as RpcVMX_Log but takes a va_list instead of inline arguments.
+ * Same as RpcVMX_Log but takes a va_list instead of inline arguments.
+ */
+void RpcVMX_LogV(const char *fmt,
+ va_list args);
+
+/*
+ * Same as RpcVMX_LogV but uses the caller-specified buffer to back the log.
*/
-void RpcVMX_LogV(const char *fmt, va_list args);
+void RpcVMX_LogVWithBuffer(RpcVMXState *rpcBuffer,
+ const char *fmt,
+ va_list args);
/*
* Get the value of "guestinfo.$key" in the host VMX dictionary and return it.
* Returns the default if the key is not set.
*/
-char *RpcVMX_ConfigGetString(const char *defval, const char *key);
+char *RpcVMX_ConfigGetString(const char *defval,
+ const char *key);
/*
* Same as _ConfigGetString, but convert the value to a 32-bit quantity.
* XXX Returns 0, *NOT* the default, if the key was set but the value could
* not be converted to an int32.
*/
-int32 RpcVMX_ConfigGetLong(int32 defval, const char *key);
+int32 RpcVMX_ConfigGetLong(int32 defval,
+ const char *key);
/*
* Same as _ConfigGetString, but convert the value to a Bool. Returns the
* default value if the key was set but could not be converted.
*/
-Bool RpcVMX_ConfigGetBool(Bool defval, const char *key);
+Bool RpcVMX_ConfigGetBool(Bool defval,
+ const char *key);
#endif /* _VMXRPC_H_ */
/*********************************************************
- * Copyright (c) 2004-2018,2019,2021,2023 VMware, Inc. All rights reserved.
+ * Copyright (c) 2004-2024 Broadcom. All Rights Reserved.
+ * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
#include "rpcvmx.h"
-typedef struct {
- char logBuf[RPCVMX_MAX_LOG_LEN + sizeof "log"];
- unsigned int logOffset;
-} RpcVMXState;
-
static RpcVMXState RpcVMX = { "log ", sizeof "log" };
*/
void
-RpcVMX_LogV(const char *fmt, va_list args)
+RpcVMX_LogV(const char *fmt,
+ va_list args)
{
int payloadLen;
char receiveBuffer[16];
}
+/*
+ *----------------------------------------------------------------------------
+ *
+ * RpcVMX_LogVWithBuffer --
+ *
+ * Construct an output string using the provided format string and
+ * argument list, then send it to the VMX using the RPCI "log" command.
+ *
+ * Uses the caller-provided buffer to back the log, rather than the
+ * global RpcVMXState.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Sends the log command described above.
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void
+RpcVMX_LogVWithBuffer(RpcVMXState *rpcBuffer, // IN/OUT
+ const char *fmt, // IN
+ va_list args) // IN
+{
+ int payloadLen;
+ char receiveBuffer[16];
+
+ if (rpcBuffer == NULL || fmt == NULL) {
+ return;
+ }
+
+ if (rpcBuffer->logOffset >= sizeof rpcBuffer->logBuf) {
+ /*
+ * The RpcVMXState is not valid, because the prefix is taking up the
+ * entire buffer. Since we can't log any actual message, silently fail.
+ */
+ return;
+ }
+
+ payloadLen = Str_Vsnprintf(rpcBuffer->logBuf + rpcBuffer->logOffset,
+ sizeof rpcBuffer->logBuf - rpcBuffer->logOffset,
+ fmt, args);
+
+ if (payloadLen < 1) {
+ /*
+ * Overflow. We need more space in the buffer. Just set the length to
+ * the buffer size and send the (truncated) log message.
+ */
+ payloadLen = sizeof rpcBuffer->logBuf - rpcBuffer->logOffset;
+ }
+
+ /*
+ * Use a pre-allocated receive buffer so that it's possible to
+ * perform the log without needing to call malloc. This makes
+ * RpcVMX_LogVWithBuffer suitable to be used in Windows kernel interrupt
+ * handlers. (It also makes it faster.) The log command only ever
+ * returns two character strings "1 " on success and "0 " on
+ * failure, so we don't need a sizeable buffer.
+ */
+ RpcOut_SendOneRawPreallocated(rpcBuffer->logBuf,
+ (size_t)rpcBuffer->logOffset + payloadLen,
+ receiveBuffer, sizeof receiveBuffer);
+}
+
+
/*
*----------------------------------------------------------------------------
*
*/
char *
-RpcVMX_ConfigGetString(const char *defval, const char *var)
+RpcVMX_ConfigGetString(const char *defval,
+ const char *var)
{
char *value;
if (!RpcOut_sendOne(&value, NULL, "info-get guestinfo.%s", var)) {
*/
Bool
-RpcVMX_ConfigGetBool(Bool defval, const char *var)
+RpcVMX_ConfigGetBool(Bool defval,
+ const char *var)
{
char *value = RpcVMX_ConfigGetString(NULL, var);
Bool ret = defval;
*/
int32
-RpcVMX_ConfigGetLong(int32 defval, const char *var)
+RpcVMX_ConfigGetLong(int32 defval,
+ const char *var)
{
char *value = RpcVMX_ConfigGetString(NULL, var);
int32 ret = defval;
*/
void
-RpcVMX_ReportDriverVersion(const char *drivername, const char *versionString)
+RpcVMX_ReportDriverVersion(const char *drivername,
+ const char *versionString)
{
char setVersionCmd[128];
Str_Sprintf(setVersionCmd, sizeof(setVersionCmd),