diff --git a/src/creator.c b/src/creator.c index 0ea27841..2cff356a 100644 --- a/src/creator.c +++ b/src/creator.c @@ -458,16 +458,17 @@ make_ipv4_path(uint8_t *buf, ssize_t size, } ssize_t NONNULL(3, 4, 5, 6, 7) PUBLIC -efi_generate_ipv4_device_path(uint8_t *buf, ssize_t size, - const char * const ifname, - const char * const local_addr, - const char * const remote_addr, - const char * const gateway_addr, - const char * const netmask, - uint16_t local_port, - uint16_t remote_port, - uint16_t protocol, - uint8_t addr_origin) +efi_generate_ipv4_device_path_with_uri(uint8_t *buf, ssize_t size, + const char * const ifname, + const char * const local_addr, + const char * const remote_addr, + const char * const gateway_addr, + const char * const netmask, + uint16_t local_port, + uint16_t remote_port, + uint16_t protocol, + uint8_t addr_origin, + const char * const uri) { ssize_t off = 0; ssize_t sz; @@ -488,6 +489,15 @@ efi_generate_ipv4_device_path(uint8_t *buf, ssize_t size, } off += sz; + if (uri) { + sz = efidp_make_uri(buf+off, size?size-off:0, uri); + if (sz < 0) { + efi_error("could not make URI DP node"); + return -1; + } + off += sz; + } + sz = efidp_make_end_entire(buf+off, size?size-off:0); if (sz < 0) { efi_error("could not make EndEntire DP node"); @@ -498,6 +508,24 @@ efi_generate_ipv4_device_path(uint8_t *buf, ssize_t size, return off; } +ssize_t NONNULL(3, 4, 5, 6, 7) PUBLIC +efi_generate_ipv4_device_path(uint8_t *buf, ssize_t size, + const char * const ifname, + const char * const local_addr, + const char * const remote_addr, + const char * const gateway_addr, + const char * const netmask, + uint16_t local_port, + uint16_t remote_port, + uint16_t protocol, + uint8_t addr_origin) +{ + return efi_generate_ipv4_device_path_with_uri(buf, size, ifname, + local_addr, remote_addr, gateway_addr, netmask, + local_port, remote_port, protocol, addr_origin, + NULL); +} + uint32_t PUBLIC efi_get_libefiboot_version(void) { diff --git a/src/dp-message.c b/src/dp-message.c index 9ae5d34d..6fd1ad87 100644 --- a/src/dp-message.c +++ b/src/dp-message.c @@ -628,6 +628,7 @@ efidp_make_mac_addr(uint8_t *buf, ssize_t size, uint8_t if_type, ssize_t req = sizeof (*mac); if (size && sz == req) { mac->if_type = if_type; + memset(mac->mac_addr, 0, 32); memcpy(mac->mac_addr, mac_addr, mac_addr_size > 32 ? 32 : mac_addr_size); } @@ -638,6 +639,25 @@ efidp_make_mac_addr(uint8_t *buf, ssize_t size, uint8_t if_type, return sz; } +ssize_t NONNULL(3) PUBLIC +efidp_make_uri(uint8_t *buf, ssize_t size, const char * const uristring) +{ + efidp_uri *uri = (efidp_uri *)buf; + size_t urilen = strlen(uristring); + ssize_t req = offsetof(efidp_uri, uri) + urilen; + + ssize_t sz = efidp_make_generic(buf, size, EFIDP_MESSAGE_TYPE, + EFIDP_MSG_URI, req); + if (size && sz == req) { + memcpy(uri->uri, (uint8_t *)uristring, urilen); + } + + if (sz < 0) + efi_error("efidp_make_generic failed"); + + return sz; +} + ssize_t PUBLIC efidp_make_ipv4(uint8_t *buf, ssize_t size, uint32_t local, uint32_t remote, uint32_t gateway, uint32_t netmask, diff --git a/src/efivar.c b/src/efivar.c index 09f85edd..1ab7c397 100644 --- a/src/efivar.c +++ b/src/efivar.c @@ -447,7 +447,7 @@ usage(int ret) " -a, --append append to variable specified by --name\n" " -f, --datafile= load or save variable contents from \n" " -e, --export= export variable to \n" - " -i, --import= import variable from import variable from \n" " -L, --list-guids show internal guid list\n" " -w, --write write to variable specified by --name\n\n" "Help options:\n" diff --git a/src/include/efivar/efiboot-creator.h b/src/include/efivar/efiboot-creator.h index 175417db..d6084a13 100644 --- a/src/include/efivar/efiboot-creator.h +++ b/src/include/efivar/efiboot-creator.h @@ -47,6 +47,21 @@ extern ssize_t efi_generate_ipv4_device_path(uint8_t *buf, ssize_t size, __attribute__((__nonnull__ (3,4,5,6,7))) __attribute__((__visibility__ ("default"))); +extern ssize_t efi_generate_ipv4_device_path_with_uri( + uint8_t *buf, ssize_t size, + const char * const ifname, + const char * const local_addr, + const char * const remote_addr, + const char * const gateway_addr, + const char * const netmask, + uint16_t local_port, + uint16_t remote_port, + uint16_t protocol, + uint8_t addr_origin, + const char * const uri) + __attribute__((__nonnull__ (3,4,5,6,7))) + __attribute__((__visibility__ ("default"))); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/include/efivar/efivar-dp.h b/src/include/efivar/efivar-dp.h index bfbf874a..517fe776 100644 --- a/src/include/efivar/efivar-dp.h +++ b/src/include/efivar/efivar-dp.h @@ -651,6 +651,8 @@ typedef struct { efidp_header header; uint8_t uri[]; } EFIVAR_PACKED efidp_uri; +extern ssize_t efidp_make_uri(uint8_t *buf, ssize_t size, + const char * const uristring); #define EFIDP_MSG_UFS 0x19 typedef struct { diff --git a/src/include/version.mk b/src/include/version.mk index eeaf6c59..ae55d310 100644 --- a/src/include/version.mk +++ b/src/include/version.mk @@ -1 +1 @@ -VERSION=38 +VERSION=39 diff --git a/src/libefiboot.abixml b/src/libefiboot.abixml index 07e89a82..04b41495 100644 --- a/src/libefiboot.abixml +++ b/src/libefiboot.abixml @@ -7,6 +7,7 @@ + @@ -68,24 +69,24 @@ - + - + - + - + - + - + - + @@ -623,7 +624,7 @@ - + @@ -635,9 +636,24 @@ + - + + + + + + + + + + + + + + + @@ -652,13 +668,13 @@ - + - + @@ -671,13 +687,19 @@ - + + + + + + + - + @@ -685,7 +707,7 @@ - + @@ -694,14 +716,14 @@ - + - + - + @@ -836,7 +858,7 @@ - + @@ -888,7 +910,7 @@ - + @@ -995,14 +1017,14 @@ - + - + @@ -1038,7 +1060,7 @@ - + @@ -1066,7 +1088,7 @@ - + @@ -1078,7 +1100,7 @@ - + @@ -1091,7 +1113,7 @@ - + @@ -1101,13 +1123,13 @@ - + - + @@ -1119,7 +1141,7 @@ - + @@ -1152,7 +1174,7 @@ - + @@ -1175,7 +1197,7 @@ - + @@ -1194,14 +1216,14 @@ - + - + @@ -1209,14 +1231,14 @@ - + - + @@ -1294,940 +1316,940 @@ - - + + - + - + - + - - - + + + - + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + + + - + - - + + - + - - + + - + - + - + - + @@ -2250,7 +2272,7 @@ - + diff --git a/src/libefiboot.map.in b/src/libefiboot.map.in index 0771eac5..0899dae1 100644 --- a/src/libefiboot.map.in +++ b/src/libefiboot.map.in @@ -37,3 +37,7 @@ LIBEFIBOOT_1.30 { LIBEFIBOOT_1.31 { global: efi_get_libefiboot_version; } LIBEFIBOOT_1.30; + +LIBEFIBOOT_1.32 { + global: efi_generate_ipv4_device_path_with_uri; +} LIBEFIBOOT_1.31; diff --git a/src/libefisec.abixml b/src/libefisec.abixml index eb5d7b9a..af82c596 100644 --- a/src/libefisec.abixml +++ b/src/libefisec.abixml @@ -111,47 +111,47 @@ - - + + - + - + - + - + - + - + - + - + - + - + - + - + - - + + @@ -167,101 +167,101 @@ - - + + - - - - - - - - + + + + + + + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + @@ -503,17 +503,17 @@ - + - + - + @@ -522,11 +522,11 @@ - + - + diff --git a/src/libefivar.abixml b/src/libefivar.abixml index 64379078..16d9eada 100644 --- a/src/libefivar.abixml +++ b/src/libefivar.abixml @@ -69,6 +69,7 @@ + @@ -275,11 +276,11 @@ - + - + @@ -332,12 +333,12 @@ - + - + @@ -365,7 +366,7 @@ - + @@ -379,1149 +380,1156 @@ - - - - + + + + + - + - + - - - - - - - - + - - - - - + + + + + + + + + + + - - - - - + + + + + - - - - - - + + + + + - - - - - - + + + + + + - - - - + + + + + + - - - - + + + + - + - + + + + + + + - - + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - - - + + + - + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - - + + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + + + - + - + - + - + - + - - + + - + - - + + - + - - + + - + - + - + - - - - - - - - - - - - + + + + + + + + + + + + - + - - - - - - - + + + + + + + - + - + - + - - + + - - - + + + - - - + + + - - - + + + - + - + - - + + - - + + @@ -1544,30 +1552,30 @@ - + - + - + - + - + - + - + - + - + @@ -1577,11 +1585,11 @@ - + - + @@ -1613,56 +1621,56 @@ - - + + - - + + - - + + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1671,166 +1679,166 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + + + + + + + - + - - - - - - - - - - + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - + - + - + - - + + - + @@ -1855,14 +1863,14 @@ - + - + @@ -1903,22 +1911,22 @@ - + - + - + - + @@ -1943,56 +1951,56 @@ - + - + - + - - - - - - - + + - - + - + - - + + + + + + + + @@ -2000,50 +2008,50 @@ - + - + - - - - - + + + + + - + - + - + - + - - - - - - - - + + + + + + + + - - - - - + + + + + @@ -2062,19 +2070,19 @@ - + - + - + - + @@ -2104,40 +2112,40 @@ - + - + - + - + - + - + - + - - + + - + - + @@ -2146,9 +2154,9 @@ - - + + @@ -2158,84 +2166,84 @@ - + - + - + - + - + - - + + - - + + - - + + - - + + - + - - - + + + - + - - + + - + - + - + - + @@ -2245,25 +2253,25 @@ - - + + - + - + - + - + - - + + @@ -2307,24 +2315,24 @@ - - - - + + + + - + - + - + @@ -2335,7 +2343,7 @@ - + @@ -2348,7 +2356,7 @@ - + @@ -2388,7 +2396,7 @@ - + @@ -2399,7 +2407,7 @@ - + @@ -2410,18 +2418,18 @@ - + - + - + @@ -2446,7 +2454,7 @@ - + @@ -2481,16 +2489,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -2502,39 +2510,39 @@ - - + + - + - + - + - - - + + + - - - + + + - + - - + + @@ -2542,8 +2550,8 @@ - - + + @@ -2553,13 +2561,13 @@ - + - + - - + + diff --git a/src/libefivar.map.in b/src/libefivar.map.in index 59f1a723..a00e3e1a 100644 --- a/src/libefivar.map.in +++ b/src/libefivar.map.in @@ -164,3 +164,7 @@ LIBEFIVAR_1.38 { efi_strptime; efi_strftime; } LIBEFIVAR_1.37; + +LIBEFIVAR_1.39 { + global: efidp_make_uri; +} LIBEFIVAR_1.38; diff --git a/src/linux-virtblk.c b/src/linux-virtblk.c index 34ad45e8..c104f101 100644 --- a/src/linux-virtblk.c +++ b/src/linux-virtblk.c @@ -35,19 +35,19 @@ parse_virtblk(struct device *dev, const char *path, const char *root UNUSED) { const char *current = path; uint32_t tosser; - int pos0 = -1, pos1 = -1; + int pos0 = -1, pos1 = -1, pos2 = -1; int rc; debug("entry"); debug("searching for virtio0/"); - rc = sscanf(current, "%nvirtio%x/%n", &pos0, &tosser, &pos1); - debug("current:'%s' rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1); - dbgmk(" ", pos0, pos1); + rc = sscanf(current, "%nvirtio%x/%nblock/%n", &pos0, &tosser, &pos1, &pos2); + debug("current:'%s' rc:%d pos0:%d pos1:%d pos2:%d\n", current, rc, pos0, pos1, pos2); + dbgmk(" ", pos0, pos1, pos2); /* - * If we couldn't find virtioX/ then it isn't a virtio device. + * If we couldn't find virtioX/block/ then it isn't a virtio device. */ - if (rc < 1) + if ((rc < 1) || (pos2 == -1)) return 0; dev->interface_type = virtblk; diff --git a/src/linux-virtnet.c b/src/linux-virtnet.c new file mode 100644 index 00000000..24dfdb07 --- /dev/null +++ b/src/linux-virtnet.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * libefiboot - library for the manipulation of EFI boot variables + * Copyright 2012-2019 Red Hat, Inc. + */ + +#include "fix_coverity.h" + +#include +#include +#include +#include +#include + +#include "efiboot.h" + +/* + * support for virtio net devices + * /sys/class/net/enp1s0 look like: + * enp1s0 -> ../../devices/pci0000:00/0000:00:02.0/0000:01:00.0/virtio1/net/enp1s0 + * + * PciRoot(0x0)/Pci(0x2,0x0)/Pci(0x0,0x0)/... + */ +static ssize_t +parse_virtnet(struct device *dev, const char *path, const char *root UNUSED) +{ + const char *current = path; + uint32_t tosser; + int pos0 = -1, pos1 = -1, pos2 = -1; + int rc; + + debug("entry"); + + debug("searching for virtio0/"); + rc = sscanf(current, "%nvirtio%x/%nnet/%n", &pos0, &tosser, &pos1, &pos2); + debug("current:'%s' rc:%d pos0:%d pos1:%d pos2:%d\n", current, rc, pos0, pos1, pos2); + dbgmk(" ", pos0, pos1, pos2); + /* + * If we couldn't find virtioX/net/ then it isn't a virtio device. + */ + if ((rc < 1) || (pos2 == -1)) + return 0; + + dev->interface_type = network; + current += pos1; + + debug("current:'%s' sz:%zd\n", current, current - path); + return current - path; +} + +enum interface_type virtnet_iftypes[] = { network, unknown }; + +struct dev_probe HIDDEN virtnet_parser = { + .name = "virtio net", + .iftypes = virtnet_iftypes, + .parse = parse_virtnet, + .create = NULL, +}; + +// vim:fenc=utf-8:tw=75:noet diff --git a/src/linux.c b/src/linux.c index 47e45ae4..659e2135 100644 --- a/src/linux.c +++ b/src/linux.c @@ -267,6 +267,7 @@ static struct dev_probe *dev_probes[] = { &virtual_root_parser, &pci_parser, &virtblk_parser, + &virtnet_parser, &sas_parser, &sata_parser, &nvme_parser, @@ -601,6 +602,7 @@ struct device HIDDEN } int HIDDEN +/* FIXME Rename */ make_blockdev_path(uint8_t *buf, ssize_t size, struct device *dev) { ssize_t off = 0; @@ -634,23 +636,25 @@ make_mac_path(uint8_t *buf, ssize_t size, const char * const ifname) { struct ifreq ifr; struct ethtool_drvinfo drvinfo = { 0, }; - int fd = -1, rc; + int fd = -1, rc, i; + unsigned int n = 0; ssize_t ret = -1, sz, off = 0; - char busname[PATH_MAX+1] = ""; - struct device dev; + struct device devbuf; + struct device *dev = &devbuf; - memset(&dev, 0, sizeof (dev)); - dev.interface_type = network; - dev.ifname = strdupa(ifname); - if (!dev.ifname) + memset(dev, 0, sizeof (*dev)); + dev->interface_type = network; + dev->ifname = strdupa(ifname); + if (!dev->ifname) return -1; + dev->driver = ""; /* * find the device link, which looks like: * ../../devices/$PCI_STUFF/net/$IFACE */ - rc = sysfs_readlink(&dev.link, "class/net/%s", ifname); - if (rc < 0 || !dev.link) + rc = sysfs_readlink(&(dev->link), "class/net/%s", ifname); + if (rc < 0 || !dev->link) goto err; memset(&ifr, 0, sizeof (ifr)); @@ -667,13 +671,106 @@ make_mac_path(uint8_t *buf, ssize_t size, const char * const ifname) if (rc < 0) goto err; - strncpy(busname, drvinfo.bus_info, PATH_MAX); + /* + * FIXME: copy/paste of device_get() + */ + size_t nmemb = (sizeof(dev_probes) + / sizeof(dev_probes[0])) + 1; + + dev->probes = calloc(nmemb, sizeof(struct dev_probe *)); + if (!dev->probes) { + efi_error("could not allocate %zd bytes", + nmemb * sizeof(struct dev_probe *)); + goto err; + } + + const char *current = dev->link; + bool needs_root = true; + int last_successful_probe = -1; + + debug("searching for device nodes in %s", dev->link); + for (i = 0; + dev_probes[i] && dev_probes[i]->parse && *current; + i++) { + struct dev_probe *probe = dev_probes[i]; + int pos; + + if (!needs_root && + (probe->flags & DEV_PROVIDES_ROOT)) { + debug("not testing %s because flags is 0x%x", + probe->name, probe->flags); + continue; + } + + debug("trying %s", probe->name); + pos = probe->parse(dev, current, dev->link); + if (pos < 0) { + efi_error("parsing %s failed", probe->name); + goto err; + } else if (pos > 0) { + char match[pos+1]; + + strncpy(match, current, pos); + match[pos] = '\0'; + debug("%s matched '%s'", probe->name, match); + dev->flags |= probe->flags; + + if (probe->flags & DEV_PROVIDES_ROOT || + probe->flags & DEV_ABBREV_ONLY) + needs_root = false; + + /* FIXME: useless code */ + if (probe->create) + print_dev_dp_node(dev, probe); + + dev->probes[n++] = dev_probes[i]; + current += pos; + if (current[0] == '\0') + debug("finished"); + else + debug("current:'%s'", current); + last_successful_probe = i; + + if (!*current || !strncmp(current, "net/", 4)) + break; + + continue; + } + + debug("dev_probes[%d]: %p dev->interface_type: %d\n", + i+1, dev_probes[i+1], dev->interface_type); + if (dev_probes[i+1] == NULL && dev->interface_type == unknown) { + pos = 0; + rc = sscanf(current, "%*[^/]/%n", &pos); + if (rc < 0) { +slash_err: + efi_error("Cannot parse device link segment \"%s\"", current); + goto err; + } + + while (current[pos] == '/') + pos += 1; + + if (!current[pos]) + goto slash_err; + + debug("Cannot parse device link segment '%s'", current); + debug("Skipping to '%s'", current + pos); + debug("This means we can only create abbreviated paths"); + dev->flags |= DEV_ABBREV_ONLY; + i = last_successful_probe; + current += pos; + + if (!*current || !strncmp(current, "net/", 4)) + break; + } + } rc = ioctl(fd, SIOCGIFHWADDR, &ifr); if (rc < 0) goto err; - sz = pci_parser.create(&dev, buf, size, off); + sz = make_blockdev_path(buf, size, dev); if (sz < 0) goto err; off += sz; @@ -686,10 +783,13 @@ make_mac_path(uint8_t *buf, ssize_t size, const char * const ifname) goto err; off += sz; + ret = off; err: if (fd >= 0) close(fd); + if (dev->probes) + free(dev->probes); return ret; } diff --git a/src/linux.h b/src/linux.h index 3489e9c1..a64dab38 100644 --- a/src/linux.h +++ b/src/linux.h @@ -354,6 +354,7 @@ extern struct dev_probe sas_parser; extern struct dev_probe sata_parser; extern struct dev_probe nvme_parser; extern struct dev_probe virtblk_parser; +extern struct dev_probe virtnet_parser; extern struct dev_probe i2o_parser; extern struct dev_probe scsi_parser; extern struct dev_probe ata_parser;