#include #include #include #include #include #include #include #include #include #include #define IDENTIFY_LEN 4096 #define BUFMARGIN 4096 int bascii_copy(sno, buf, size, max) char *sno; char *buf; int size; int max; { static char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; static char *reserved = ","; int i, j; if (size >= max) { return -1; } /* * Try copying as ascii string */ for (i = 0; i < size && (isprint(buf[i]) && !strchr(reserved, buf[i])); i++) { sno[i] = buf[i]; } /* The size specified may or may not include the null character. * The first cond. is true if the null char. is included, and * The second cond. is true if the null char. is not included */ if (i == size || (i == (size -1) && buf[i] == '\0')) { sno[i] = '\0'; return 0; } /* * Copy as a hex string */ if (2 * size >= max) { return 0; } for (i = j = 0; i < size; i++) { sno[j++] = hex[(buf[i] >> 4) & 0x0f]; sno[j++] = hex[buf[i] & 0x0f]; } sno[j] = '\0'; return 0; } int main (int argc, char *argv[]) { int fd = -1, ret = -1; struct nvme_admin_cmd cmd; char *rwbuf = NULL; char *rwbuf_512 = NULL; char cab_serial_no[34] = { 0 }; char str[66] = {'\0'}, str1[66] = {'\0'}; uint64_t bit1_64, bit2_64, eui_64; uint64_t *eui_ptr = NULL, *nguid1_ptr = NULL; uint64_t *nguid2_ptr = NULL; unsigned long addr; int rwbufsz; if (argc < 2) { printf("no of arguments are less than 2\n"); return -1; } if ((fd = open(argv[1], O_RDONLY)) < 0) { printf("open failed for %s\n", argv[1]); return -1; } rwbufsz = IDENTIFY_LEN + BUFMARGIN; rwbuf = malloc(rwbufsz + 8192); // Allocate extra for alignments addr = (unsigned long) rwbuf; /* * Align to page size */ addr += 4096; addr >>= 12; addr <<= 12; /* * Make address 512 byte aligned, but not page aligned */ addr |= 0x200; rwbuf_512 = (char *) addr; memset(&cmd, 0 ,sizeof(cmd)); cmd.opcode = 0x06; /* 0x06 for identify*/ cmd.nsid = 0; cmd.addr = (uint64_t)rwbuf_512; /*buffer address*/ cmd.data_len = rwbufsz; cmd.cdw10 = 1; /* Identify Controller data structure */ cmd.timeout_ms = 5000; ret = ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd); if (ret != 0 ) { printf("first ioctl failed with ret %d, alloc addr = %p," " align addr=%p\n", ret, rwbuf, rwbuf_512); free(rwbuf); close(fd); return -1; } ///////////////////copy here/////// ret = bascii_copy(cab_serial_no, rwbuf_512 + 4, 20, sizeof(cab_serial_no)); if (ret != 0) { printf("bascii_copy failed with ret %d\n", ret); free(rwbuf); close(fd); return -1; } printf("cab_serial_no is :%s:\n", cab_serial_no); memset(&cmd, 0 ,sizeof(cmd)); cmd.opcode = 0x06; /* 0x06 for identify*/ cmd.addr = (uint64_t)rwbuf_512; /*buffer address*/ cmd.data_len = rwbufsz; cmd.timeout_ms = 5000; cmd.nsid = 1; cmd.cdw10 = 0; /* Identify Namespace data structure */ memset(rwbuf_512, 0, 8192); ret= ioctl(fd, NVME_IOCTL_ADMIN_CMD, &cmd); if (ret != 0 ) { printf("IOCTL failed with ret %d \n", ret); close(fd); free(rwbuf); return ret; } else { nguid1_ptr = (uint64_t *)(rwbuf_512 + 104); nguid2_ptr = (uint64_t *)(rwbuf_512 + 112); eui_ptr = (uint64_t *)(rwbuf_512 + 120); bit1_64 = bswap_64(* nguid1_ptr); bit2_64 = bswap_64(* nguid2_ptr); eui_64 = bswap_64(* eui_ptr); snprintf(str, 66, "%.16lX", eui_64); snprintf(str1, 66, "%.16lX%.16lX", bit1_64, bit2_64); if(eui_64 != 0) { printf("from eui_64: %s\n", str); printf("from bit1_64 and bit2_64 no: %s\n", str1); } else if (bit1_64 != 0 || bit2_64 != 0) { printf("in else if lun_serial no: %s\n", str1); } else { printf("in else no LSN\n"); } } close(fd); free(rwbuf); }