Преглед на файлове

sysvars: add function to marshall sysvars for sending to FPGA

Package sysvars in such a way that the FPGA can use them directly,
including marshalling pointer values.
H. Peter Anvin преди 1 година
родител
ревизия
a3c43eabf5
променени са 2 файла, в които са добавени 55 реда и са изтрити 0 реда
  1. 2 0
      esp32/max80/sysvars.h
  2. 53 0
      esp32/max80/sysvars_marshall.c

+ 2 - 0
esp32/max80/sysvars.h

@@ -75,6 +75,8 @@ extern_c const char *getvar_tostr_r(size_t var, char *buf);
 extern_c bool setvar_fromstr(size_t var, const char *str);
 extern_c void sysvar_reset(void);
 extern_c size_t sysvar_find(size_t ns, const char *name);
+extern_c size_t sysvar_marshall(enum sysvars_enum first, size_t count,
+				void *buf, size_t *buflen, uintptr_t extaddr);
 
 /* Type-specific definitions/getters/setters */
 /* Note that t contains a leading underscore to avoid bool/_Bool issues */

+ 53 - 0
esp32/max80/sysvars_marshall.c

@@ -0,0 +1,53 @@
+/*
+ * Marshall sysvars into a buffer to be sent to the FPGA.
+ */
+
+#include "common.h"
+#include "sysvars.h"
+
+/*
+ * Marshall a set or subset of sysvar entries into a buffer
+ * for use by another CPU (for which the address to said buffer
+ * might differ from what this CPU uses.)
+ *
+ * Returns the number of entries successfully marshalled.
+ * extaddr refers to the external address of the buffer, for which
+ * internal pointers should be adjusted.
+ *
+ * On return, *buflen is adjusted to the number of bytes actually used.
+ */
+size_t sysvar_marshall(enum sysvars_enum first, size_t count,
+		       void *buf, size_t *buflen, uintptr_t extaddr)
+{
+    static const size_t align_mask = 3;
+    size_t bytes = count * sizeof(sysvar_t);
+    if (*buflen < bytes) {
+	/* Only space for a partial result */
+	count = *buflen / sizeof(sysvar_t);
+	bytes = count * sizeof(sysvar_t);
+    }
+    sysvar_t *vp = (sysvar_t *)buf;
+    size_t bufsize = *buflen;
+    const sysvar_t *v = &sysvar_val[first];
+    const sysvar_type_t *t = &sysvar_types[first];
+    size_t ok = 0;
+    intptr_t adjust = extaddr - (uintptr_t)buf;
+
+    while (count--) {
+	sysvar_t vv = *vp++ = *v++;
+	sysvar_type_t type = *t++;
+	if (type->datasize) {
+	    size_t dsize = type->datasize(vv);
+	    size_t adj_bytes = (bytes + align_mask) & ~align_mask;
+	    if (adj_bytes + dsize > bufsize)
+		break;		/* Insufficient buffer space */
+	    char *dp = (char *)buf + adj_bytes;
+	    memcpy(dp, vv.v_ptr, dsize);
+	    vv.v_ptr = (void *)((uintptr_t)vv.v_ptr + adjust);
+	    bytes = adj_bytes + dsize;
+	}
+	ok++;
+    }
+    *buflen = bytes;
+    return ok;
+}