SCSI inquiry to get storage device serial number

1144 views
Skip to first unread message

galapogos

unread,
Jun 7, 2009, 11:17:16 PM6/7/09
to
Hi,

I'm trying to get the serial number of a storage device. I've tried
sg3_utils and sg_inq does this. I tried calling the functions within
the sg3 source files, but I can't seem to build it even after
including the relevant header files.

I've also tried forming my own SCSI inquiry CDB and sending it to the
device, but I only seem to get the vendor ID and product ID, no serial
number and other information.

Does anyone know how to use the functions within sg3_utils, or how to
obtain the serial number?

Thanks!

Michael Baeuerle

unread,
Jun 8, 2009, 5:09:18 AM6/8/09
to
galapogos wrote:
>
> I'm trying to get the serial number of a storage device. I've tried
> sg3_utils and sg_inq does this. I tried calling the functions within
> the sg3 source files, but I can't seem to build it even after
> including the relevant header files.

You have to link against "libsgutils". Copy the following files:
- .libs/libsgutils.a
- sg_cmds.h
- sg_include.h
- sg_lib.h
- sg_inq.c

... and build a binary like this:
gcc -o sg_inq sg_inq.c -lsgutils

Now you can strip down "sg_inq.c" to your needs.

> I've also tried forming my own SCSI inquiry CDB and sending it to the
> device, but I only seem to get the vendor ID and product ID, no serial
> number and other information.

The Standard Inquiry Data don't contain the serial number, you have to
readout the "Vital Product Data" page 0x80. For details look at the SPC
document.

> Does anyone know how to use the functions within sg3_utils, or how to
> obtain the serial number?

Example:
----------------------------------------------------------------------
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <scsi/sg.h>

int main(void)
{
const char devicefile[] = "/dev/sg1";
const char* file_name = NULL;
int sg_fd;
unsigned char reply_buffer[96];
unsigned char sense_buffer[32];
sg_io_hdr_t io_hdr;
unsigned char inquiry[6]
= {0x12, 0x01, 0x80, 0x00, sizeof(reply_buffer), 0x00};
int i;

/* Open device file */
file_name = devicefile;
printf("\nGet Type & SN from device file: %s\n\n", file_name);
if ((sg_fd = open(file_name, O_RDWR | O_EXCL)) < 0)
{
fprintf(stderr, "Cannot open devicefile!\n\n");
exit(1);
}

/* Send INQUIRY command */
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
io_hdr.mx_sb_len = sizeof(sense_buffer);
io_hdr.sbp = sense_buffer;
io_hdr.dxfer_len = sizeof(reply_buffer);
io_hdr.dxferp = reply_buffer;
io_hdr.cmd_len = sizeof(inquiry);
io_hdr.cmdp = inquiry;
io_hdr.timeout = 1000; /* Miliseconds */
if (ioctl(sg_fd, SG_IO, &io_hdr) < 0)
{
fprintf(stderr, "Cannot send INQUIRY command!\n\n");
exit(1);
}
if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
{
fprintf(stderr, "INQUIRY command failed!\n");
if (io_hdr.sb_len_wr > 0)
{
printf("Sense data: ");
for (i = 0; i < io_hdr.sb_len_wr; i++)
{
printf("0x%02X ", sense_buffer[i]);
}
printf("\n");
}
exit(1);
}

/* Extract SN */
if (reply_buffer[1] != 0x80)
{
fprintf(stderr, "Unit serial number page invalid!\n\n");
exit(1);
}
printf("Device type: 0x%02X\n", reply_buffer[1] & 0x1F);
printf("Serial number: ");
for (i = 4; i < reply_buffer[3] + 4; i++)
{
printf("%c", reply_buffer[i]);
}
printf("\n\n");
exit(0);
}
----------------------------------------------------------------------
You want to tune the error handling. ILLEGAL REQUEST may occur and it
must not be a real error because VPD page support was not mandatory (or
not specified at all) in older SCSI revisions.

The output from my example should look like this for a disk [1]:
----------------------------------------------------------------------
$ ./getsn

Get Type & SN from device file: /dev/sg1

Device type: 0x00
Serial number: AJF61666
----------------------------------------------------------------------


Micha

[1] http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type

galapogos

unread,
Jun 9, 2009, 11:01:36 AM6/9/09
to

Thanks! That worked...

Lynn McGuire

unread,
Jul 14, 2009, 12:37:28 PM7/14/09
to
> I'm trying to get the serial number of a storage device. I've tried
> sg3_utils and sg_inq does this. I tried calling the functions within
> the sg3 source files, but I can't seem to build it even after
> including the relevant header files.

I take it that my DiskID32 http://www.winsim.com/diskid32/diskid32.html
program fails also ?

Lynn

kumar.a...@gmail.com

unread,
Feb 24, 2016, 3:03:28 PM2/24/16
to
Thank you so much for such a nice explanation.
But if i want information like(FRU number, part number) . then how to get those info ?

Scott Lurndal

unread,
Feb 24, 2016, 3:16:27 PM2/24/16
to
You're referring to a seven year old post.

All the information you need is in the SCSI standard docs, if you
read them in the context of Michale's example.

Michael Baeuerle

unread,
Feb 25, 2016, 3:32:59 PM2/25/16
to
Scott Lurndal wrote:
> kumar.a...@gmail.com writes:
> > On Monday, 8 June 2009 14:39:18 UTC+5:30, Michael Baeuerle wrote:
> > >
> > > [1] http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type
> >
> > Thank you so much for such a nice explanation.
> > But if i want information like(FRU number, part number) . then how to get those info ?
>
> You're referring to a seven year old post.

No problem, I'm still there :-)

Michael Baeuerle

unread,
Feb 29, 2016, 7:52:12 AM2/29/16
to
kumar.a...@gmail.com wrote:
>
> [...]
> But if i want information like(FRU number, part number) . then how to
> get those info ?

Current versions of sg_utils can display VPD pagesน out-of-the-box, you
don't need to write a program any more. Example:
|
| # sg_map -x -i
| /dev/sg0 0 0 0 0 0 /dev/sda TOSHIBA PX02SMF040 0205
| # sg_vpd --enumerate /dev/sg0
| [...]
| sn 0x80 Unit serial number
| [long list]
| # sg_vpd --page=sv /dev/sg0
| Supported VPD pages VPD page:
| Supported VPD pages [sv]
| Unit serial number [sn]
| [shorter list]
| # sg_vpd --page=sn /dev/sg0
| Unit serial number VPD page:
| Unit serial number: Z520A004TY95

It looks like that things like FRU number can't be read out in a
standard way.


______________
น) They are defined in the SPC4 document
Reply all
Reply to author
Forward
0 new messages