2 * libefiboot - library for the manipulation of EFI boot variables
3 * Copyright 2012-2015 Red Hat, Inc.
4 * Copyright (C) 2001 Dell Computer Corporation <Matt_Domsch@dell.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of the
9 * License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see
18 * <http://www.gnu.org/licenses/>.
26 #include <linux/ethtool.h>
27 #include <linux/version.h>
28 #include <linux/sockios.h>
30 #include <scsi/scsi.h>
32 #include <sys/ioctl.h>
33 #include <sys/socket.h>
34 #include <sys/sysmacros.h>
35 #include <sys/types.h>
36 #include <sys/param.h>
41 #include <sys/sysmacros.h>
52 __attribute__((__visibility__ ("hidden")))
53 set_disk_and_part_name(struct disk_info *info)
58 rc = sysfs_readlink(&linkbuf, "/sys/dev/block/%"PRIu64":%hhu",
59 info->major, info->minor);
64 ultimate = strrchr(linkbuf, '/');
73 penultimate = strrchr(linkbuf, '/');
81 * If there's a better way to figure this out, it'd be good, because
82 * I don't want to have to change this for every new disk type...
84 if (!strcmp(penultimate, "block")) {
85 if (!info->disk_name) {
86 info->disk_name = strdup(ultimate);
90 if (!info->part_name) {
91 rc = asprintf(&info->part_name, "%s%d", info->disk_name,
96 } else if (!strncmp(penultimate, "nvme", 4)) {
97 if (!info->disk_name) {
98 info->disk_name = strdup(ultimate);
102 if (!info->part_name) {
103 rc = asprintf(&info->part_name, "%sp%d",
104 info->disk_name, info->part);
109 if (!info->disk_name) {
110 info->disk_name = strdup(penultimate);
111 if (!info->disk_name)
114 if (!info->part_name) {
115 info->part_name = strdup(ultimate);
116 if (!info->part_name)
125 __attribute__((__visibility__ ("hidden")))
126 get_partition_number(const char *devpath)
128 struct stat statbuf = { 0, };
130 unsigned int maj, min;
135 rc = stat(devpath, &statbuf);
139 if (!S_ISBLK(statbuf.st_mode)) {
144 maj = major(statbuf.st_rdev);
145 min = minor(statbuf.st_rdev);
147 rc = sysfs_readlink(&linkbuf, "/sys/dev/block/%u:%u", maj, min);
151 rc = read_sysfs_file(&partbuf, "/sys/dev/block/%s/partition", linkbuf);
155 rc = sscanf((char *)partbuf, "%d\n", &ret);
162 __attribute__((__visibility__ ("hidden")))
163 find_parent_devpath(const char * const child, char **parent)
169 /* strip leading /dev/ */
170 node = strrchr(child, '/');
175 /* look up full path symlink */
176 ret = sysfs_readlink(&linkbuf, "/sys/class/block/%s", node);
181 node = strrchr(linkbuf, '/');
187 node = strrchr(linkbuf, '/');
193 /* write out new path */
194 ret = asprintf(parent, "/dev/%s", node);
202 sysfs_test_nvme(const char *buf, ssize_t size)
204 if (!strncmp(buf, "nvme/", MIN(size, 5)))
210 sysfs_test_sata(const char *buf, ssize_t size)
212 if (!strncmp(buf, "ata", MIN(size, 3)))
218 sysfs_test_sas(const char *buf, ssize_t size)
222 struct stat statbuf = { 0, };
228 newbuf = strndupa(buf, size+1);
234 rc = sscanf(newbuf, "host%d/%n", &host, &sz);
236 return (errno == 0) ? 0 : -1;
238 rc = asprintfa(&path, "/sys/class/scsi_host/host%d/host_sas_address",
243 rc = stat(path, &statbuf);
250 sysfs_sata_get_port_info(uint32_t print_id, struct disk_info *info)
257 d = opendir("/sys/class/ata_device/");
259 efi_error("opendir failed on /sys/class/ata_device/");
263 while ((de = readdir(d)) != NULL) {
264 uint32_t found_print_id;
266 uint32_t found_devno = 0;
268 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
272 rc = sscanf(de->d_name, "dev%d.%d.%d", &found_print_id,
273 &found_pmp, &found_devno);
274 if (rc < 2 || rc > 3) {
278 } else if (found_print_id != print_id) {
280 } else if (rc == 3) {
282 * the kernel doesn't't ever tell us the SATA PMPN
283 * sentinal value, it'll give us devM.N instead of
284 * devM.N.O in that case instead.
286 if (found_pmp > 0x7fff) {
291 info->sata_info.ata_devno = 0;
292 info->sata_info.ata_pmp = found_pmp;
294 } else if (rc == 2) {
295 info->sata_info.ata_devno = 0;
296 info->sata_info.ata_pmp = 0xffff;
302 rc = read_sysfs_file(&buf, "/sys/class/ata_port/ata%d/port_no",
307 rc = sscanf((char *)buf, "%d", &info->sata_info.ata_port);
312 * ata_port numbers are 1-indexed from libata in the kernel, but
313 * they're 0-indexed in the spec. For maximal confusion.
315 if (info->sata_info.ata_port == 0) {
319 info->sata_info.ata_port -= 1;
326 sysfs_parse_nvme(uint8_t *buf, ssize_t size, ssize_t *off,
327 const char *pbuf, ssize_t psize, ssize_t *poff,
328 struct disk_info *info)
332 uint8_t *filebuf = NULL;
339 newpbuf = strndupa(pbuf, psize+1);
342 newpbuf[psize] = '\0';
351 rc = sscanf(newpbuf, "nvme/nvme%d/nvme%dn%d%n", &tosser0,
352 &ctrl_id, &ns_id, &psz);
357 info->nvme_info.ctrl_id = ctrl_id;
358 info->nvme_info.ns_id = ns_id;
359 info->nvme_info.has_eui = 0;
360 info->interface_type = nvme;
363 * now fish the eui out of sysfs is there is one...
365 rc = read_sysfs_file(&filebuf,
366 "/sys/class/block/nvme%dn%d/eui",
368 if (rc < 0 && errno == ENOENT) {
369 rc = read_sysfs_file(&filebuf,
370 "/sys/class/block/nvme%dn%d/device/eui",
379 rc = sscanf((char *)filebuf,
380 "%02hhx %02hhx %02hhx %02hhx "
381 "%02hhx %02hhx %02hhx %02hhx",
382 &eui[0], &eui[1], &eui[2], &eui[3],
383 &eui[4], &eui[5], &eui[6], &eui[7]);
388 info->nvme_info.has_eui = 1;
389 memcpy(info->nvme_info.eui, eui, sizeof(eui));
392 *off = efidp_make_nvme(buf, size,
393 info->nvme_info.ns_id,
394 info->nvme_info.has_eui ? info->nvme_info.eui
401 sysfs_parse_sata(uint8_t *buf, ssize_t size, ssize_t *off,
402 const char *pbuf, ssize_t psize, ssize_t *poff,
403 struct disk_info *info)
414 uint32_t scsi_device;
415 uint32_t scsi_target;
420 newpbuf = strndupa(pbuf, psize+1);
423 newpbuf[psize] = '\0';
425 /* find the ata info:
426 * ata1/host0/target0:0:0/
429 rc = sscanf(newpbuf, "ata%d/host%d/target%d:%d:%d/%n",
430 &print_id, &scsi_bus, &scsi_device, &scsi_target, &scsi_lun,
436 /* find the emulated scsi bits (and ignore them)
439 uint32_t dummy0, dummy1, dummy2;
441 rc = sscanf(newpbuf+*poff, "%d:%d:%d:%"PRIu64"/%n", &dummy0, &dummy1,
442 &dummy2, &dummy3, &psz);
450 char *disk_name = NULL;
451 char *part_name = NULL;
453 rc = sscanf(newpbuf+*poff, "block/%m[^/]%n/%m[^/]%n", &disk_name, &psz,
456 rc = asprintf(&part_name, "%s%d", disk_name, info->part);
463 } else if (rc != 2) {
470 info->sata_info.scsi_bus = scsi_bus;
471 info->sata_info.scsi_device = scsi_device;
472 info->sata_info.scsi_target = scsi_target;
473 info->sata_info.scsi_lun = scsi_lun;
475 rc = sysfs_sata_get_port_info(print_id, info);
482 /* check the original of this; it's guaranteed in our copy */
483 if (pbuf[*poff] != '\0') {
490 info->disk_name = disk_name;
491 info->part_name = part_name;
492 if (info->interface_type == interface_type_unknown)
493 info->interface_type = sata;
495 if (info->interface_type == ata) {
496 *off = efidp_make_atapi(buf, size, info->sata_info.ata_port,
497 info->sata_info.ata_pmp,
498 info->sata_info.ata_devno);
500 *off = efidp_make_sata(buf, size, info->sata_info.ata_port,
501 info->sata_info.ata_pmp,
502 info->sata_info.ata_devno);
508 sysfs_parse_sas(uint8_t *buf, ssize_t size, ssize_t *off,
509 const char *pbuf, ssize_t psize, ssize_t *poff,
510 struct disk_info *info)
514 uint8_t *filebuf = NULL;
515 uint64_t sas_address;
519 newpbuf = strndupa(pbuf, psize+1);
522 newpbuf[psize] = '\0';
528 * host4/port-4:0/end_device-4:0/target4:0:0/4:0:0:0/block/sdc/sdc1
530 uint32_t tosser0, tosser1, tosser2;
532 /* ignore a bunch of stuff
534 * or host4/port-4:0:0
536 rc = sscanf(newpbuf+*poff, "host%d/port-%d:%d%n", &tosser0, &tosser1,
543 rc = sscanf(pbuf+*poff, ":%d%n", &tosser0, &psz);
544 if (rc != 0 && rc != 1)
550 * or /end_device-4:0:0
551 * awesomely these are the exact same fields that go into port-blah,
552 * but we don't care for now about any of them anyway.
554 rc = sscanf(newpbuf+*poff, "/end_device-%d:%d%n", &tosser0, &tosser1,
561 rc = sscanf(newpbuf+*poff, ":%d%n", &tosser0, &psz);
562 if (rc != 0 && rc != 1)
570 rc = sscanf(newpbuf+*poff, "/target%d:%d:%"PRIu64"/%n", &tosser0,
571 &tosser1, &tosser3, &psz);
579 rc = sscanf(newpbuf+*poff, "%d:%d:%d:%"PRIu64"/%n",
580 &info->sas_info.scsi_bus,
581 &info->sas_info.scsi_device,
582 &info->sas_info.scsi_target,
583 &info->sas_info.scsi_lun, &psz);
591 char *disk_name = NULL;
592 char *part_name = NULL;
593 rc = sscanf(newpbuf+*poff, "block/%m[^/]/%m[^/]%n", &disk_name,
599 /* check the original of this; it's guaranteed in our copy */
600 if (pbuf[*poff] != '\0') {
608 * we also need to get the actual sas_address from someplace...
610 rc = read_sysfs_file(&filebuf,
611 "/sys/class/block/%s/device/sas_address",
616 rc = sscanf((char *)filebuf, "%"PRIx64, &sas_address);
620 info->sas_info.sas_address = sas_address;
621 info->disk_name = disk_name;
622 info->part_name = part_name;
623 info->interface_type = sas;
625 *off = efidp_make_sas(buf, size, sas_address);
630 make_pci_path(uint8_t *buf, ssize_t size, char *pathstr, ssize_t *pathoff)
637 if (pathstr == NULL || pathoff == NULL || pathstr[0] == '\0') {
644 uint16_t root_domain;
646 uint32_t acpi_hid = 0;
647 uint64_t acpi_uid_int = 0;
649 * find the pci root domain and port; they basically look like:
653 rc = sscanf(pathstr+poff, "pci%hx:%hhx/%n", &root_domain,
659 uint8_t *fbuf = NULL;
660 rc = read_sysfs_file(&fbuf,
661 "/sys/devices/pci%04x:%02x/firmware_node/hid",
662 root_domain, root_bus);
667 rc = sscanf((char *)fbuf, "PNP%hx", &tmp16);
670 acpi_hid = EFIDP_EFI_PNP_ID(tmp16);
672 /* Apparently basically nothing can look up a PcieRoot() node,
673 * because they just check _CID. So since _CID for the root pretty
674 * much always has to be PNP0A03 anyway, just use that no matter
677 if (acpi_hid == EFIDP_ACPI_PCIE_ROOT_HID)
678 acpi_hid = EFIDP_ACPI_PCI_ROOT_HID;
683 rc = read_sysfs_file(&fbuf,
684 "/sys/devices/pci%4x:%02x/firmware_node/uid",
685 root_domain, root_bus);
686 if (rc <= 0 && errno != ENOENT)
689 rc = sscanf((char *)fbuf, "%"PRIu64"\n", &acpi_uid_int);
691 /* kernel uses "%s\n" to print it, so there
692 * should always be some value and a newline... */
693 int l = strlen((char *)buf);
703 sz = efidp_make_acpi_hid_ex(buf+off, size?size-off:0,
704 acpi_hid, 0, 0, "", (char *)fbuf,
707 sz = efidp_make_acpi_hid(buf+off, size?size-off:0,
708 acpi_hid, acpi_uid_int);
714 /* find the pci domain/bus/device/function:
715 * 0000:00:01.0/0000:01:00.0/
716 * ^d ^b ^d ^f (of the last one in the series)
721 uint8_t bus, device, function;
722 rc = sscanf(pathstr+poff, "%hx:%hhx:%hhx.%hhx/%n",
723 &domain, &bus, &device, &function, &psz);
729 sz = efidp_make_pci(buf+off, size?size-off:0, device, function);
742 __attribute__((__visibility__ ("hidden")))
743 make_blockdev_path(uint8_t *buf, ssize_t size, struct disk_info *info)
745 char *linkbuf = NULL;
746 char *driverbuf = NULL;
747 ssize_t off=0, sz=0, loff=0;
752 rc = sysfs_readlink(&linkbuf, "/sys/dev/block/%"PRIu64":%u",
753 info->major, info->minor);
758 * the sysfs path basically looks like:
759 * ../../devices/pci$PCI_STUFF/$BLOCKDEV_STUFF/block/$DISK/$PART
761 rc = sscanf(linkbuf+loff, "../../devices/%n", &lsz);
767 sz = make_pci_path(buf, size, linkbuf+loff, &tmplsz);
773 char *tmppath = strdupa(linkbuf);
776 tmppath[loff] = '\0';
777 rc = sysfs_readlink(&driverbuf, "/sys/dev/block/%s/driver", tmppath);
781 char *driver = strrchr(driverbuf, '/');
782 if (!driver || !*driver)
786 if (!strncmp(driver, "pata_", 5) || !(strcmp(driver, "ata_piix")))
787 info->interface_type = ata;
789 if (info->interface_type == interface_type_unknown ||
790 info->interface_type == atapi ||
791 info->interface_type == usb ||
792 info->interface_type == i1394 ||
793 info->interface_type == fibre ||
794 info->interface_type == i2o ||
795 info->interface_type == md) {
799 rc = sscanf(linkbuf+loff, "virtio%x/%n", &tosser, &tmpoff);
802 } else if (rc == 1) {
803 info->interface_type = virtblk;
809 /* /dev/nvme0n1 looks like:
810 * /sys/dev/block/259:0 -> ../../devices/pci0000:00/0000:00:1d.0/0000:05:00.0/nvme/nvme0/nvme0n1
813 rc = sysfs_test_nvme(linkbuf+loff, PATH_MAX-off);
818 rc = sysfs_parse_nvme(buf+off, size?size-off:0, &sz,
819 linkbuf+loff, PATH_MAX-off,
829 /* /dev/sda as SATA looks like:
830 * /sys/dev/block/8:0 -> ../../devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0/0:0:0:0/block/sda
833 rc = sysfs_test_sata(linkbuf+loff, PATH_MAX-off);
836 if (!found && rc > 0) {
838 rc = sysfs_parse_sata(buf+off, size?size-off:0, &sz,
839 linkbuf+loff, PATH_MAX-off,
849 /* /dev/sdc as SAS looks like:
850 * /sys/dev/block/8:32 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/host4/port-4:0/end_device-4:0/target4:0:0/4:0:0:0/block/sdc
853 rc = sysfs_test_sas(linkbuf+loff, PATH_MAX-off);
858 rc = sysfs_parse_sas(buf+off, size?size-off:0, &sz,
859 linkbuf+loff, PATH_MAX-off,
869 if (!found && info->interface_type == scsi) {
872 rc = sysfs_readlink(&linkbuf, "/sys/class/block/%s/device",
877 rc = sscanf(linkbuf, "../../../%d:%d:%d:%"PRIu64,
878 &info->scsi_info.scsi_bus,
879 &info->scsi_info.scsi_device,
880 &info->scsi_info.scsi_target,
881 &info->scsi_info.scsi_lun);
885 sz = efidp_make_scsi(buf+off, size?size-off:0,
886 info->scsi_info.scsi_target,
887 info->scsi_info.scsi_lun);
903 __attribute__((__visibility__ ("hidden")))
904 eb_disk_info_from_fd(int fd, struct disk_info *info)
909 memset(info, 0, sizeof *info);
911 info->pci_root.root_pci_domain = 0xffff;
912 info->pci_root.root_pci_bus = 0xff;
914 memset(&buf, 0, sizeof(struct stat));
915 rc = fstat(fd, &buf);
920 if (S_ISBLK(buf.st_mode)) {
921 info->major = buf.st_rdev >> 8;
922 info->minor = buf.st_rdev & 0xFF;
923 } else if (S_ISREG(buf.st_mode)) {
924 info->major = buf.st_dev >> 8;
925 info->minor = buf.st_dev & 0xFF;
927 printf("Cannot stat non-block or non-regular file\n");
931 /* IDE disks can have up to 64 partitions, or 6 bits worth,
932 * and have one bit for the disk number.
933 * This leaves an extra bit at the top.
935 if (info->major == 3) {
936 info->disknum = (info->minor >> 6) & 1;
937 info->controllernum = (info->major - 3 + 0) + info->disknum;
938 info->interface_type = ata;
939 info->part = info->minor & 0x3F;
941 } else if (info->major == 22) {
942 info->disknum = (info->minor >> 6) & 1;
943 info->controllernum = (info->major - 22 + 2) + info->disknum;
944 info->interface_type = ata;
945 info->part = info->minor & 0x3F;
947 } else if (info->major >= 33 && info->major <= 34) {
948 info->disknum = (info->minor >> 6) & 1;
949 info->controllernum = (info->major - 33 + 4) + info->disknum;
950 info->interface_type = ata;
951 info->part = info->minor & 0x3F;
953 } else if (info->major >= 56 && info->major <= 57) {
954 info->disknum = (info->minor >> 6) & 1;
955 info->controllernum = (info->major - 56 + 8) + info->disknum;
956 info->interface_type = ata;
957 info->part = info->minor & 0x3F;
959 } else if (info->major >= 88 && info->major <= 91) {
960 info->disknum = (info->minor >> 6) & 1;
961 info->controllernum = (info->major - 88 + 12) + info->disknum;
962 info->interface_type = ata;
963 info->part = info->minor & 0x3F;
967 /* I2O disks can have up to 16 partitions, or 4 bits worth. */
968 if (info->major >= 80 && info->major <= 87) {
969 info->interface_type = i2o;
970 info->disknum = 16*(info->major-80) + (info->minor >> 4);
971 info->part = (info->minor & 0xF);
975 /* SCSI disks can have up to 16 partitions, or 4 bits worth
976 * and have one bit for the disk number.
978 if (info->major == 8) {
979 info->interface_type = scsi;
980 info->disknum = (info->minor >> 4);
981 info->part = (info->minor & 0xF);
983 } else if (info->major >= 65 && info->major <= 71) {
984 info->interface_type = scsi;
985 info->disknum = 16*(info->major-64) + (info->minor >> 4);
986 info->part = (info->minor & 0xF);
988 } else if (info->major >= 128 && info->major <= 135) {
989 info->interface_type = scsi;
990 info->disknum = 16*(info->major-128) + (info->minor >> 4);
991 info->part = (info->minor & 0xF);
1000 make_net_pci_path(uint8_t *buf, ssize_t size, const char * const ifname)
1002 char *linkbuf = NULL;
1003 ssize_t off=0, sz=0, loff=0;
1007 rc = sysfs_readlink(&linkbuf, "/sys/class/net/%s", ifname);
1012 * the sysfs path basically looks like:
1013 * ../../devices/$PCI_STUFF/net/$IFACE
1015 rc = sscanf(linkbuf+loff, "../../devices/%n", &lsz);
1021 sz = make_pci_path(buf, size, linkbuf+loff, &tmplsz);
1031 __attribute__((__visibility__ ("hidden")))
1032 make_mac_path(uint8_t *buf, ssize_t size, const char * const ifname)
1035 struct ethtool_drvinfo drvinfo = { 0, };
1037 ssize_t ret = -1, sz, off=0;
1038 char busname[PATH_MAX+1] = "";
1040 memset(&ifr, 0, sizeof (ifr));
1041 strncpy(ifr.ifr_name, ifname, IF_NAMESIZE);
1042 drvinfo.cmd = ETHTOOL_GDRVINFO;
1043 ifr.ifr_data = (caddr_t)&drvinfo;
1045 fd = socket(AF_INET, SOCK_DGRAM, 0);
1049 rc = ioctl(fd, SIOCETHTOOL, &ifr);
1053 strncpy(busname, drvinfo.bus_info, PATH_MAX);
1055 rc = ioctl(fd, SIOCGIFHWADDR, &ifr);
1059 sz = make_net_pci_path(buf, size, ifname);
1064 sz = efidp_make_mac_addr(buf+off, size?size-off:0,
1065 ifr.ifr_ifru.ifru_hwaddr.sa_family,
1066 (uint8_t *)ifr.ifr_ifru.ifru_hwaddr.sa_data,
1067 sizeof(ifr.ifr_ifru.ifru_hwaddr.sa_data));