49#define PCI_SYSFS_PATH "/sys/bus/pci/devices"
50#define QUADRA_VENDOR_ID 0x1d82
51#define QUADRA_DEVICE_ID 0x0401
54#define ARTIFACTS_BAR4_OFFSET 0xF920000
56#define BAR4_MIN_ADDRESS 0x840000000ULL
57#define NOR_FLASH_CMD_ADDRESS 0x84F8F5020ULL
58#define NOR_FLASH_CMD_OFFSET (NOR_FLASH_CMD_ADDRESS - BAR4_MIN_ADDRESS)
59#define NOR_READ_WAIT_SECONDS 100
61#define CORE_LOG_PTR_TABLE_OFFSET 0xF8F5000
62#define CORE_RESET_LOG_PTR_TABLE_OFFSET 0xF8FD0C0
63#define CORE_LOG_SIZE ((size_t)1024 * 1024)
64#define CORE_RESET_LOG_SIZE ((size_t)64 * 1024)
66#define FL_LOG_ENTRY_SIZE 128
71const char *
const core_names[NUM_CORES] = {
"np",
"dp",
"ep",
"tp",
"fp",
"fl"};
78static void set_log_file_ownership(
const char *fname)
81 const char *sudo_user = getenv(
"SUDO_USER");
82 if (!sudo_user || sudo_user[0] ==
'\0')
84 struct passwd pw_buf, *pw = NULL;
86 (void)getpwnam_r(sudo_user, &pw_buf, pwbuf,
sizeof(pwbuf), &pw);
88 if (pw && chown(fname, pw->pw_uid, pw->pw_gid) != 0)
92 (void)fprintf(stderr,
"[WARN] chown(%s) failed: %s\n",
106static int read_nvme_sn(
const QuadraDevice *qd,
char *sn,
size_t sn_len)
108 char nvme_dir[PATH_MAX];
109 if (snprintf(nvme_dir,
sizeof(nvme_dir),
"%s/nvme", qd->sysfs_path) < 0)
112 DIR *dir = opendir(nvme_dir);
117 struct dirent *entry;
118 while ((entry = readdir(dir)))
120 if (strncmp(entry->d_name,
"nvme", 4) != 0)
123 char serial_path[PATH_MAX];
124 if (snprintf(serial_path,
sizeof(serial_path),
"%s/%s/serial",
125 nvme_dir, entry->d_name) < 0)
128 FILE *fp = fopen(serial_path,
"r");
132 char raw_sn[21] = {0};
133 if (fgets(raw_sn,
sizeof(raw_sn), fp))
135 raw_sn[strcspn(raw_sn,
" \t\r\n")] =
'\0';
138 for (
char *p = raw_sn; *p; ++p)
140 if (!isalnum((
unsigned char)*p) && *p !=
'-')
143 (void)snprintf(sn, sn_len,
"%s", raw_sn);
152 return found ? 0 : -1;
155int bdf_to_sysfs(
const char* bdf,
char* sysfs_path,
size_t pathsz,
int *domain,
int *bus,
int *slot,
int *func)
157 unsigned int d=0, b=0, s=0, f=0;
158 if (sscanf(bdf,
"%x:%x:%x.%x", &d, &b, &s, &f) != 4)
160 if (snprintf(sysfs_path, pathsz,
"/sys/bus/pci/devices/%04x:%02x:%02x.%x", d, b, s, f) < 0)
162 if (domain) *domain = (int)d;
163 if (bus) *bus = (int)b;
164 if (slot) *slot = (int)s;
165 if (func) *func = (int)f;
169static int safe_realloc_devices(QuadraDevice **p_devs,
int new_cap)
171 QuadraDevice *new_devs = realloc(*p_devs, new_cap *
sizeof(**p_devs));
182int quadra_device_find(QuadraDevice **out_devs)
187 perror(
"opendir(sysfs)");
191 struct dirent *entry;
192 QuadraDevice *devs = calloc(8,
sizeof(*devs));
193 int dev_count = 0, capacity = 8;
201 while ((entry = readdir(dir)))
203 if (entry->d_name[0] ==
'.')
206 if (snprintf(path,
sizeof(path),
"%s/%s",
PCI_SYSFS_PATH, entry->d_name) < 0)
210 if (stat(path, &st) < 0 || !S_ISDIR(st.st_mode))
213 char ven_path[PATH_MAX], dev_path[PATH_MAX];
214 if (snprintf(ven_path,
sizeof(ven_path),
"%s/vendor", path) < 0)
216 if (snprintf(dev_path,
sizeof(dev_path),
"%s/device", path) < 0)
219 FILE *fv = fopen(ven_path,
"r");
224 if (!fgets(buf,
sizeof(buf), fv))
231 unsigned long ven = strtoul(buf, NULL, 0);
236 FILE *fd = fopen(dev_path,
"r");
240 if (!fgets(buf,
sizeof(buf), fd))
247 unsigned long dev = strtoul(buf, NULL, 0);
251 if (dev_count >= capacity)
254 if (safe_realloc_devices(&devs, capacity) < 0)
261 if (bdf_to_sysfs(entry->d_name,
262 devs[dev_count].sysfs_path,
sizeof(devs[dev_count].sysfs_path),
263 &devs[dev_count].domain, &devs[dev_count].bus, &devs[dev_count].slot,
264 &devs[dev_count].func) == 0)
282int quadra_init_mmap(QuadraDevice *qd)
284 char bar4path[PATH_MAX];
285 struct stat bar4stat;
286 if (snprintf(bar4path,
sizeof(bar4path),
"%s/resource4", qd->sysfs_path) < 0)
290 (void)fprintf(stderr,
"Permission error: You must run as root (sudo)\n");
297 qd->bar4_fd = open(bar4path, O_RDONLY | O_SYNC);
298 if (qd->bar4_fd == -1)
300 perror(
"open(bar4)");
303 if (fstat(qd->bar4_fd, &bar4stat) == 0)
305 qd->barsize = bar4stat.st_size;
308 if (qd->barsize == 0)
310 off_t sz = lseek(qd->bar4_fd, 0, SEEK_END);
313 qd->barsize = (off_t)sz;
314 (void)lseek(qd->bar4_fd, 0, SEEK_SET);
317 if (qd->barsize == 0)
319 (void)fprintf(stderr,
"Cannot determine BAR4 size for %s\n", bar4path);
324 qd->bar4_base = mmap(NULL, qd->barsize, PROT_READ, MAP_SHARED, qd->bar4_fd, 0);
325 if (qd->bar4_base == MAP_FAILED || qd->bar4_base == NULL)
327 if (qd->bar4_base != NULL && errno == EACCES)
328 (void)fprintf(stderr,
"Permission error: Cannot mmap %s. Run as root (sudo).\n", bar4path);
329 else if (qd->bar4_base != NULL && errno == EINVAL)
330 (void)fprintf(stderr,
"EINVAL: mmap() on BAR4 failed. Try kernel flag 'iomem=relaxed'.\n");
332 (
void)fprintf(stderr,
"Failed to mmap BAR4 at %s: %s\n", bar4path, strerror(errno));
335 qd->bar4_base = NULL;
341void quadra_cleanup(QuadraDevice *qd)
343 if (qd->bar4_base && qd->bar4_base != MAP_FAILED)
345 munmap(qd->bar4_base, qd->barsize);
346 qd->bar4_base = NULL;
348 if (qd->bar4_fd >= 0)
364static int quadra_nor_dispatch(QuadraDevice *qd, uint32_t command)
366 char bar4path[PATH_MAX];
367 if (snprintf(bar4path,
sizeof(bar4path),
"%s/resource4", qd->sysfs_path) < 0)
371 int fd = open(bar4path, O_RDWR | O_SYNC);
375 (void)fprintf(stderr,
"Failed to open BAR4 (O_RDWR) at %s for NOR command: %s\n",
380 void *map = mmap(NULL, qd->barsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
381 if (map == MAP_FAILED)
384 (void)fprintf(stderr,
"Failed to mmap BAR4 (RW) at %s for NOR command: %s\n",
392 munmap(map, qd->barsize);
402static void quadra_nor_read_wait(
void)
406 (void)fprintf(stderr,
"\r[INFO] NOR flash operation in progress... %d%%",
410 (void)fprintf(stderr,
"\r[INFO] NOR flash operation in progress... 100%%\n");
422int quadra_nor_command(QuadraDevice *qd, uint32_t command)
424 if (quadra_nor_dispatch(qd, command) != 0)
430 quadra_nor_read_wait();
431 (void)fprintf(stderr,
"[INFO] NOR flash command complete.\n");
434 (void)fprintf(stderr,
435 "[INFO] NOR flash erase command dispatched.\n"
436 "[INFO] Erasing NOR flash logs may take up to 100 seconds to complete.\n");
439 (void)fprintf(stderr,
440 "[INFO] NOR flash write command dispatched.\n"
441 "[INFO] Writing DDR logs to NOR flash may take up to 100 seconds to complete.\n");
443 case NOR_CMD_EXCEPTION:
444 (void)fprintf(stderr,
"[INFO] NOR flash exception command dispatched.\n");
447 (void)fprintf(stderr,
"[INFO] Unsupported NOR flash command: %u\n", command);
454void fill_core_log_offsets(QuadraDevice *qd)
456 uint8_t *base = qd->bar4_base;
458 for (
int i = 0; i < NUM_CORES; ++i)
460 uint32_t log_offset = *(uint32_t *)(base + offset + 4 * (
size_t)i) & 0x0FFFFFFF;
461 if ((
size_t)log_offset +
CORE_LOG_SIZE > (size_t)qd->barsize)
463 (void)fprintf(stderr,
464 "[WARN] Core %s log offset 0x%x + 0x%zx exceeds BAR4 size 0x%lx, skipping\n",
465 core_names[i], log_offset,
CORE_LOG_SIZE, (
unsigned long)qd->barsize);
468 qd->core_log_offsets[i] = log_offset;
474void fill_core_reset_log_offsets(QuadraDevice *qd)
476 uint8_t *base = qd->bar4_base;
478 for (
int i = 0; i < NUM_CORES_NO_FL; ++i)
480 uint32_t log_offset = *(uint32_t *)(base + offset + 4 * (
size_t)i) & 0x0FFFFFFF;
483 (void)fprintf(stderr,
484 "[WARN] Core %s reset-log offset 0x%x + 0x%zx exceeds BAR4 size 0x%lx, skipping\n",
488 qd->core_log_offsets[i] = log_offset;
507static int dump_fl_core(QuadraDevice *qd,
const char *outdir)
509 uint32_t fl_offset = qd->core_log_offsets[
FL_CORE_IDX];
510 if ((
size_t)fl_offset + 8 > (
size_t)qd->barsize)
512 (void)fprintf(stderr,
"[WARN] FL offset 0x%x out of BAR4 range, skipping\n", fl_offset);
515 uint8_t *base = qd->bar4_base + fl_offset;
518 memcpy(&signature, base,
sizeof(signature));
519 (void)fprintf(stderr,
"[INFO] FL Signature 0x%08x\n", signature);
523 (void)fprintf(stderr,
"[WARN] FL log: invalid signature, skipping\n");
528 memcpy(&len_field, base + 4,
sizeof(len_field));
529 uint32_t log_len = len_field & 0xFFFFFF;
531 if ((
size_t)fl_offset + 8 + payload_size > (size_t)qd->barsize)
533 (void)fprintf(stderr,
534 "[ERR] FL log payload_size %zu exceeds BAR4 bounds (%lu)\n",
535 payload_size, (
unsigned long)qd->barsize);
539 char fname[PATH_MAX];
540 if (snprintf(fname,
sizeof(fname),
"%s/raw_fl_slot_%02x_%04x.bin",
541 outdir, qd->bus, qd->domain) < 0)
544 uint8_t *raw = base + 8;
545 FILE *fp = fopen(fname,
"wb");
552 for (
size_t i = 0; i < payload_size; ++i)
555 (void)fputc(raw[i], fp);
559 set_log_file_ownership(fname);
560 (void)fprintf(stderr,
"[INFO] Dumped log: %s\n", fname);
575int dump_raw_logs(QuadraDevice *qd,
const char *outdir,
bool core_reset_log)
580 fill_core_reset_log_offsets(qd);
581 num_cores = NUM_CORES_NO_FL;
585 fill_core_log_offsets(qd);
586 num_cores = NUM_CORES;
590 (void)read_nvme_sn(qd, sn,
sizeof(sn));
593 time_t now = time(NULL);
595 struct tm *tm_info = localtime_r(&now, &tm_buf);
597 (void)strftime(ts,
sizeof(ts),
"%Y%m%d-%H%M%S", tm_info);
600 for (
int core_idx = 0; core_idx < num_cores; ++core_idx)
602 const char *core = core_names[core_idx];
606 rc |= (dump_fl_core(qd, outdir) != 0) ? -1 : 0;
610 uint32_t log_offset = qd->core_log_offsets[core_idx];
611 if ((
size_t)log_offset + (
size_t)qd->log_size > (
size_t)qd->barsize)
613 (void)fprintf(stderr,
614 "[ERROR] %s log offset 0x%x out of BAR4 range, skipping\n",
619 char fname[PATH_MAX];
622 n = snprintf(fname,
sizeof(fname),
"%s/raw_%s_%04x_%02x_%02x_%x_%s_%s.bin",
623 outdir, core, (
unsigned)qd->domain, (
unsigned)qd->bus,
624 (
unsigned)qd->slot, (
unsigned)qd->func, sn, ts);
626 n = snprintf(fname,
sizeof(fname),
"%s/raw_%s_%04x_%02x_%02x_%x_%s.bin",
627 outdir, core, (
unsigned)qd->domain, (
unsigned)qd->bus,
628 (
unsigned)qd->slot, (
unsigned)qd->func, sn);
630 n = snprintf(fname,
sizeof(fname),
"%s/raw_%s_%04x_%02x_%02x_%x_%s.bin",
631 outdir, core, (
unsigned)qd->domain, (
unsigned)qd->bus,
632 (
unsigned)qd->slot, (
unsigned)qd->func, ts);
634 n = snprintf(fname,
sizeof(fname),
"%s/raw_%s_%04x_%02x_%02x_%x.bin",
635 outdir, core, (
unsigned)qd->domain, (
unsigned)qd->bus,
636 (
unsigned)qd->slot, (
unsigned)qd->func);
637 if (n < 0 || (
size_t)n >=
sizeof(fname))
639 (void)fprintf(stderr,
640 "[ERROR] %s log filename truncated or encoding error, skipping\n", core);
644 FILE *fp = fopen(fname,
"wb");
651 if (fwrite(qd->bar4_base + log_offset, 1, (
size_t)qd->log_size, fp) != (
size_t)qd->log_size)
653 (void)fprintf(stderr,
"[ERROR] Short write on %s\n", fname);
655 set_log_file_ownership(fname);
660 set_log_file_ownership(fname);
661 if (memcmp(qd->bar4_base + log_offset,
"hashid", 6) == 0)
664 memcpy(hstr, qd->bar4_base + log_offset, 16);
665 (void)fprintf(stderr,
"%s: %s\n", core, hstr);
667 (void)fprintf(stderr,
"[INFO] Dumped log: %s\n", fname);
682int dump_nor_logs(QuadraDevice *qd,
const char *outdir)
685 for (
int core_idx = 0; core_idx < NUM_CORES_NO_FL; ++core_idx)
687 const char *core = core_names[core_idx];
689 uint32_t log_offset = qd->core_log_offsets[core_idx];
690 if ((
size_t)log_offset + (
size_t)qd->log_size > (
size_t)qd->barsize)
692 (void)fprintf(stderr,
693 "[ERROR] %s log offset 0x%x out of BAR4 range, skipping\n",
698 char fname[PATH_MAX];
699 if (snprintf(fname,
sizeof(fname),
"%s/raw_%s_slot_%02x_%04x.bin",
700 outdir, core, qd->bus, qd->domain) < 0)
continue;
701 FILE *fp = fopen(fname,
"wb");
708 if (fwrite(qd->bar4_base + log_offset, 1, (
size_t)qd->log_size, fp) != (
size_t)qd->log_size)
710 (void)fprintf(stderr,
"[ERROR] Short write on %s\n", fname);
712 set_log_file_ownership(fname);
717 set_log_file_ownership(fname);
718 if (memcmp(qd->bar4_base + log_offset,
"hashid", 6) == 0)
721 memcpy(hstr, qd->bar4_base + log_offset, 16);
722 (void)fprintf(stderr,
"%s: %s\n", core, hstr);
724 (void)fprintf(stderr,
"[INFO] Dumped persistent log: %s\n", fname);
740static int validate_quadra_sysfs(
const char *sysfs_path)
742 char vpath[PATH_MAX], dpath[PATH_MAX], buf[32];
744 if (snprintf(vpath,
sizeof(vpath),
"%s/vendor", sysfs_path) < 0 ||
745 snprintf(dpath,
sizeof(dpath),
"%s/device", sysfs_path) < 0)
748 FILE *f = fopen(vpath,
"r");
751 (void)fprintf(stderr,
"[ERROR] No PCI device at %s\n", sysfs_path);
754 if (!fgets(buf,
sizeof(buf), f)) { (void)fclose(f);
return -1; }
758 (void)fprintf(stderr,
"[ERROR] Device at %s is not a NETINT device.\n",
763 f = fopen(dpath,
"r");
765 if (!fgets(buf,
sizeof(buf), f)) { (void)fclose(f);
return -1; }
769 (void)fprintf(stderr,
"[ERROR] Device at %s is not a Quadra device.\n",
786int quadra_device_find_by_bdf(
const char *domain_str,
const char *slot_str,
789 if (!slot_str || !out)
792 unsigned int domain = domain_str ? (
unsigned int)strtoul(domain_str, NULL, 16) : 0;
793 unsigned int bus = (
unsigned int)strtoul(slot_str, NULL, 16);
795 if (domain > 0xFFFF || bus > 0xFF)
797 (void)fprintf(stderr,
"[ERROR] --domain or -s value out of range.\n");
802 (void)snprintf(bdf,
sizeof(bdf),
"%04x:%02x:00.0", domain, bus);
804 char sysfs_path[PATH_MAX];
805 (void)snprintf(sysfs_path,
sizeof(sysfs_path),
"%s/%s",
PCI_SYSFS_PATH, bdf);
807 if (validate_quadra_sysfs(sysfs_path) != 0)
810 QuadraDevice *qd = calloc(1,
sizeof(*qd));
813 if (bdf_to_sysfs(bdf, qd->sysfs_path,
sizeof(qd->sysfs_path),
814 &qd->domain, &qd->bus, &qd->slot, &qd->func) != 0)
833int quadra_device_find_by_block_dev(
const char *blkdev, QuadraDevice **out)
839 char link_path[PATH_MAX];
840 if (snprintf(link_path,
sizeof(link_path),
841 "/sys/block/%s/device/device", blkdev) < 0)
844 char link_target[PATH_MAX];
845 ssize_t len = readlink(link_path, link_target,
sizeof(link_target) - 1);
848 (void)fprintf(stderr,
"[ERROR] Block device '%s' not found.\n", blkdev);
851 link_target[len] =
'\0';
854 char *last_slash = strrchr(link_target,
'/');
855 const char *bdf = last_slash ? last_slash + 1 : link_target;
857 char sysfs_path[PATH_MAX];
858 if (snprintf(sysfs_path,
sizeof(sysfs_path),
"%s/%s",
PCI_SYSFS_PATH, bdf) < 0)
861 if (validate_quadra_sysfs(sysfs_path) != 0)
863 (void)fprintf(stderr,
"[ERROR] '%s' does not correspond to a Quadra device.\n",
868 QuadraDevice *qd = calloc(1,
sizeof(*qd));
871 if (bdf_to_sysfs(bdf, qd->sysfs_path,
sizeof(qd->sysfs_path),
872 &qd->domain, &qd->bus, &qd->slot, &qd->func) != 0)
895static int dump_artifacts(QuadraDevice *qd,
const char *outdir)
897 const uint8_t *artifacts_base = qd->bar4_base + qd->log_artifacts_offset;
899 uint32_t artifacts_size;
900 memcpy(&artifacts_size, artifacts_base,
sizeof(artifacts_size));
902 if (artifacts_size == 0)
904 (void)fprintf(stderr,
"[INFO] Artifacts: size header is 0 - artifacts were not loaded into DDR.\n");
909 if (artifacts_size > max_data_size)
911 (void)fprintf(stderr,
"[WARN] Artifacts: size %u exceeds max %u size - stale DDR data or artifacts not loaded.\n",
912 artifacts_size, max_data_size);
917 if (data[0] != 0x1f || data[1] != 0x8b)
919 (void)fprintf(stderr,
"[WARN] Artifacts: invalid gzip magic 0x%02x 0x%02x - stale DDR data or artifacts not loaded\n",
924 char fname[PATH_MAX];
925 if (snprintf(fname,
sizeof(fname),
"%s/artifacts_slot_%02x_%04x.tar.gz",
926 outdir, qd->bus, qd->domain) < 0)
929 FILE *fp = fopen(fname,
"wb");
932 perror(
"fopen(artifacts)");
935 if (fwrite(data, 1, artifacts_size, fp) != artifacts_size)
937 (void)fprintf(stderr,
"[ERROR] artifacts write failed on %s\n", fname);
942 set_log_file_ownership(fname);
943 (void)fprintf(stderr,
"[INFO] Artifacts saved: %s (%u bytes)\n", fname, artifacts_size);
947int ni_rsrc_log_dump(
const char *outdir,
bool core_reset_log)
949 QuadraDevice *devs = NULL;
950 int ndev = quadra_device_find(&devs);
954 (void)fprintf(stderr,
"[WARN] No Quadra devices found in sysfs (vendor 1d82).\n");
958 for (
int i = 0; i < ndev; ++i)
960 if (quadra_init_mmap(&devs[i]) == 0)
962 int rc = dump_raw_logs(&devs[i], outdir ? outdir :
".", core_reset_log);
963 fail_count += (rc != 0);
964 dump_artifacts(&devs[i], outdir ? outdir :
".");
965 quadra_cleanup(&devs[i]);
969 (void)fprintf(stderr,
"[ERROR] Failed to mmap device %d\n", i);
974 return (fail_count == 0) ? 0 : 2;
986int nor_cmd_decode(
const char *nor_cmd, uint32_t *out_cmd)
988 if (!nor_cmd || !out_cmd)
991 if (strcmp(nor_cmd,
"w") == 0)
993 *out_cmd = NOR_CMD_WRITE;
996 if (strcmp(nor_cmd,
"r") == 0)
998 *out_cmd = NOR_CMD_READ;
1001 if (strcmp(nor_cmd,
"e") == 0)
1003 *out_cmd = NOR_CMD_ERASE;
1006 if (strcmp(nor_cmd,
"ex") == 0)
1008 *out_cmd = NOR_CMD_EXCEPTION;
1012 (void)fprintf(stderr,
1013 "[ERROR] Unknown NOR command '%s'. Use w, r, e, or ex.\n", nor_cmd);
1033int ni_rsrc_nor_cmd_run(QuadraDevice *devs,
int ndev,
1034 uint32_t cmd,
const char *outdir)
1036 if (!devs || ndev <= 0)
1039 const char *odir = outdir ? outdir :
".";
1042 if (cmd == NOR_CMD_READ)
1045 bool *ready = (
bool *)calloc((
size_t)ndev,
sizeof(bool));
1050 for (
int i = 0; i < ndev; ++i)
1052 if (quadra_init_mmap(&devs[i]) != 0)
1054 (void)fprintf(stderr,
1055 "[ERROR] Failed to mmap device %d\n", i);
1059 if (quadra_nor_dispatch(&devs[i], NOR_CMD_READ) != 0)
1061 (void)fprintf(stderr,
1062 "[ERROR] NOR read dispatch failed on device %d\n",
1064 quadra_cleanup(&devs[i]);
1068 (void)fprintf(stderr,
1069 "[INFO] NOR read dispatched to device %d\n", i);
1074 quadra_nor_read_wait();
1077 for (
int i = 0; i < ndev; ++i)
1081 fill_core_log_offsets(&devs[i]);
1082 int rc = dump_nor_logs(&devs[i], odir);
1083 fail_count += (rc != 0);
1084 (void)fprintf(stderr,
"[INFO] NOR flash command complete.\n");
1085 quadra_cleanup(&devs[i]);
1093 for (
int i = 0; i < ndev; ++i)
1095 if (quadra_init_mmap(&devs[i]) != 0)
1097 (void)fprintf(stderr,
1098 "[ERROR] Failed to mmap device %d\n", i);
1102 if (quadra_nor_command(&devs[i], cmd) != 0)
1104 (void)fprintf(stderr,
1105 "[ERROR] NOR command failed on device %d\n", i);
1106 quadra_cleanup(&devs[i]);
1110 quadra_cleanup(&devs[i]);
1114 return (fail_count == 0) ? 0 : 2;
1130int ni_rsrc_nor_log_command(
const char *nor_cmd,
const char *outdir)
1133 if (nor_cmd_decode(nor_cmd, &cmd) != 0)
1136 QuadraDevice *devs = NULL;
1137 int ndev = quadra_device_find(&devs);
1141 (void)fprintf(stderr,
1142 "[WARN] No Quadra devices found in sysfs (vendor 1d82).\n");
1146 int rc = ni_rsrc_nor_cmd_run(devs, ndev, cmd, outdir);
#define LOG_ARTIFACTS_MAX_SIZE
#define CPU_LOG_ARTIFACTS_HEADER_SIZE
#define CORE_RESET_LOG_SIZE
#define CORE_LOG_PTR_TABLE_OFFSET
#define ARTIFACTS_BAR4_OFFSET
#define FL_LOG_ENTRY_SIZE
#define NOR_FLASH_CMD_OFFSET
#define CORE_RESET_LOG_PTR_TABLE_OFFSET
#define NOR_READ_WAIT_SECONDS
ni_retcode_t ni_strerror(char *dest, size_t dmax, int errnum)
void ni_usleep(int64_t usec)