Open Ranguvar opened 1 month ago
Hello,
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <scsi/sg.h>
#include <string.h>
#define SMART_READ_CMD_LEN 12
#define INQUIRY_CMD_LEN 6
#define SMART_READ_RESP_LEN 512
#define INQUIRY_RESP_LEN 96
#define SENSE_BUFFER_LEN 32
int main(int argc, char *argv[]) {
int fd, output_fd;
unsigned char smart_read_cmd[SMART_READ_CMD_LEN] = {0xa1, 0x0c, 0x0e, 0xd0, 1, 0, 0x4f, 0xc2, 0, 0xb0, 0, 0};
unsigned char inquiry_cmd[INQUIRY_CMD_LEN] = {0x12, 0, 0, 0, INQUIRY_RESP_LEN, 0};
unsigned char smart_read_resp[SMART_READ_RESP_LEN];
unsigned char inquiry_resp[INQUIRY_RESP_LEN];
unsigned char sense_buffer[SENSE_BUFFER_LEN];
sg_io_hdr_t io_hdr;
if (argc < 2) {
printf("Please enter a device file\n");
return 1;
}
char *device_file_name = argv[1];
char *output_file_name = "smart_data.bin";
if ((fd = open(device_file_name, O_RDONLY)) < 0) {
printf("Could not open device file: %s\n", device_file_name);
return 1;
}
output_fd = open(output_file_name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (output_fd < 0) {
printf("Failed to open output file: %s\n", output_file_name);
close(fd);
return 1;
}
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = SMART_READ_CMD_LEN;
io_hdr.mx_sb_len = SENSE_BUFFER_LEN;
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
io_hdr.dxfer_len = SMART_READ_RESP_LEN;
io_hdr.dxferp = smart_read_resp;
io_hdr.cmdp = smart_read_cmd;
io_hdr.sbp = sense_buffer;
io_hdr.timeout = 20000;
if (ioctl(fd, SG_IO, &io_hdr) < 0) {
printf("IOCTL call for SMART READ failed\n");
close(output_fd);
close(fd);
return 1;
}
if (write(output_fd, smart_read_resp, SMART_READ_RESP_LEN) != SMART_READ_RESP_LEN) {
printf("Error writing data to file\n");
close(output_fd);
close(fd);
return 1;
}
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = INQUIRY_CMD_LEN;
io_hdr.mx_sb_len = SENSE_BUFFER_LEN;
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
io_hdr.dxfer_len = INQUIRY_RESP_LEN;
io_hdr.dxferp = inquiry_resp;
io_hdr.cmdp = inquiry_cmd;
io_hdr.sbp = sense_buffer;
io_hdr.timeout = 20000;
if (ioctl(fd, SG_IO, &io_hdr) < 0) {
printf("IOCTL call for SCSI INQUIRY failed\n");
close(output_fd);
close(fd);
return 1;
}
if (write(output_fd, inquiry_resp, INQUIRY_RESP_LEN) != INQUIRY_RESP_LEN) {
printf("Error writing data to file\n");
close(output_fd);
close(fd);
return 1;
}
printf("Data saved to %s\n", output_file_name);
close(output_fd);
close(fd);
return 0;
}
Above is a small C script which should give you what you want, this is the bin file when inspected with hexedit Compile it with gcc using
gcc file.c
then do
sudo ./a.out /dev/sda
or whatever the path to the device file is
Thank you so much! This works perfectly. Really fantastic, I did not expect so much help so quickly. I was able to confirm that my drive also uses the SM2259 microcontroller and B47R NAND flash.
If you'd like to put a license on it, I would share with others in SSD/Linux communities. It'd be a very useful addition to smartmontools or QDiskInfo though, even as a command-line option.
Thank you so much! This works perfectly. Really fantastic, I did not expect so much help so quickly. I was able to confirm that my drive also uses the SM2259 microcontroller and B47R NAND flash.
If you'd like to put a license on it, I would share with others in SSD/Linux communities. It'd be a very useful addition to smartmontools or QDiskInfo though, even as a command-line option.
I might add it yes, feel free to share it under the BSD or GPL 3 License. Does CrystalDiskInfo also do this for NVMe drives?
Yes, CrystalDiskInfo's Copy works on NVMe drives and outputs similar info. I can't compare it directly to SATA drives as my sole Windows install only has direct access to NVMe. Looks like this code would need changes to support NVMe as well (IOCTL call for SMART READ failed).
I will look into getting the same type of data from NVMe first and then I will try to add this functionality. I have some friends with NVMe drives on Windows so I'll ask them for some dumps.
Thanks for creating this project! It works great on latest Arch with [testing] repos under Sway.
Perhaps you might help me find this information, whether or not you could add the feature to QDiskInfo? I'm looking for a Linux equivalent to CrystalDiskInfo's Edit -> Copy Option -> ASCII View, which shows the raw hex SMART data including the vendor specific data which should follow it.
This would allow me to check microcontroller and flash details. For example see: https://hddoracle.com/viewtopic.php?p=22539#p22539
Even if you know of a way to read this via smartctl or otherwise for now, that would really help me. It would be a great feature to have in the GUI eventually as well. I've been trying to use smartctl with -A, -d, and -v but have not found the data I seek.
Thanks again!