sysvars_marshall.c 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. /*
  2. * Marshall sysvars into a buffer to be sent to the FPGA.
  3. */
  4. #include "common.h"
  5. #include "sysvars.h"
  6. #include <stdio.h>
  7. /*
  8. * Marshall a set or subset of sysvar entries into a buffer
  9. * for use by another CPU (for which the address to said buffer
  10. * might differ from what this CPU uses.)
  11. *
  12. * Returns the number of entries successfully marshalled.
  13. * extaddr refers to the external address of the buffer, for which
  14. * internal pointers should be adjusted.
  15. *
  16. * On return, *buflen is adjusted to the number of bytes actually used.
  17. */
  18. size_t sysvar_marshall(enum sysvar_enum first, size_t count,
  19. void *buf, size_t *buflen, uintptr_t extaddr)
  20. {
  21. static const size_t align_mask = 3;
  22. size_t bytes = count * sizeof(sysvar_t);
  23. if (*buflen < bytes) {
  24. /* Only space for a partial result */
  25. count = *buflen / sizeof(sysvar_t);
  26. bytes = count * sizeof(sysvar_t);
  27. }
  28. sysvar_t *vp = (sysvar_t *)buf;
  29. size_t bufsize = *buflen;
  30. const sysvar_t *v = &sysvar_val[first];
  31. const sysvar_type_t *t = &sysvar_types[first];
  32. size_t ok = 0;
  33. intptr_t adjust = extaddr - (uintptr_t)buf;
  34. while (count--) {
  35. sysvar_t vv = *v++;
  36. sysvar_type_t type = *t++;
  37. if (type && type->datasize && vv.v_ptr) {
  38. size_t dsize = type->datasize(vv);
  39. size_t adj_bytes = (bytes + align_mask) & ~align_mask;
  40. if (adj_bytes + dsize > bufsize)
  41. break; /* Insufficient buffer space */
  42. char *dp = (char *)buf + adj_bytes;
  43. memcpy(dp, vv.v_ptr, dsize);
  44. vv.v_ptr = dp + adjust;
  45. bytes = adj_bytes + dsize;
  46. }
  47. *vp++ = vv;
  48. ok++;
  49. }
  50. *buflen = bytes;
  51. return ok;
  52. }