2 * libefiboot - library for the manipulation of EFI boot variables
3 * Copyright 2012-2018 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License as
7 * published by the Free Software Foundation; either version 2.1 of the
8 * License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "fix_coverity.h"
32 * support for NVMe devices
34 * /sys/dev/block/$major:$minor looks like:
35 * 259:0 -> ../../devices/pci0000:00/0000:00:1d.0/0000:05:00.0/nvme/nvme0/nvme0n1
36 * 259:1 -> ../../devices/pci0000:00/0000:00:1d.0/0000:05:00.0/nvme/nvme0/nvme0n1/nvme0n1p1
38 * /sys/dev/block/259:0/device looks like:
39 * device -> ../../nvme0
41 * /sys/dev/block/259:1/partition looks like:
45 * /sys/class/block/nvme0n1/eui looks like:
46 * $ cat /sys/class/block/nvme0n1/eui
47 * 00 25 38 53 5a 16 1d a9
51 parse_nvme(struct device *dev, const char *current, const char *root UNUSED)
54 int32_t tosser0, tosser1, tosser2, ctrl_id, ns_id, partition;
55 uint8_t *filebuf = NULL;
56 int pos0 = 0, pos1 = 0;
59 pos0 = strlen(current);
60 spaces = alloca(pos0+1);
61 memset(spaces, ' ', pos0+1);
67 debug("searching for nvme/nvme0/nvme0n1 or nvme/nvme0/nvme0n1/nvme0n1p1");
68 rc = sscanf(current, "nvme/nvme%d/nvme%dn%d%n/nvme%dn%dp%d%n",
69 &tosser0, &ctrl_id, &ns_id, &pos0,
70 &tosser1, &tosser2, &partition, &pos1);
71 debug("current:\"%s\" rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
72 arrow(LOG_DEBUG, spaces, 9, pos0, rc, 3);
73 arrow(LOG_DEBUG, spaces, 9, pos1, rc, 6);
75 * If it isn't of that form, it's not one of our nvme devices.
77 if (rc != 3 && rc != 6)
80 dev->nvme_info.ctrl_id = ctrl_id;
81 dev->nvme_info.ns_id = ns_id;
82 dev->nvme_info.has_eui = 0;
83 dev->interface_type = nvme;
87 dev->part = partition;
93 * now fish the eui out of sysfs is there is one...
95 rc = read_sysfs_file(&filebuf,
96 "class/block/nvme%dn%d/eui",
98 if ((rc < 0 && errno == ENOENT) || filebuf == NULL) {
99 rc = read_sysfs_file(&filebuf,
100 "class/block/nvme%dn%d/device/eui",
103 if (rc >= 0 && filebuf != NULL) {
109 rc = sscanf((char *)filebuf,
110 "%02hhx %02hhx %02hhx %02hhx "
111 "%02hhx %02hhx %02hhx %02hhx",
112 &eui[0], &eui[1], &eui[2], &eui[3],
113 &eui[4], &eui[5], &eui[6], &eui[7]);
118 dev->nvme_info.has_eui = 1;
119 memcpy(dev->nvme_info.eui, eui, sizeof(eui));
126 dp_create_nvme(struct device *dev,
127 uint8_t *buf, ssize_t size, ssize_t off)
133 sz = efidp_make_nvme(buf + off, size ? size - off : 0,
134 dev->nvme_info.ns_id,
135 dev->nvme_info.has_eui ? dev->nvme_info.eui
141 make_part_name(struct device *dev)
149 rc = asprintf(&ret, "%sp%d", dev->disk_name, dev->part);
151 efi_error("could not allocate memory");
158 static enum interface_type nvme_iftypes[] = { nvme, unknown };
160 struct dev_probe HIDDEN nvme_parser = {
162 .iftypes = nvme_iftypes,
163 .flags = DEV_PROVIDES_HD,
165 .create = dp_create_nvme,
166 .make_part_name = make_part_name,