From 0b7d5ca48da819cf0b6b31ef7a1bae76a8b89463 Mon Sep 17 00:00:00 2001 From: Arseny Maslennikov Date: Sat, 14 Feb 2026 09:00:00 +0300 Subject: [PATCH 1/2] dp-message: add IPv6 device path constructor Also, publish it in efivar-dp.h. All arguments are either IPv6 addresses (arrays of 16 uint8_t) or words in host byte order. Scope IDs for addresses should be unnecessary, since, in practice, the device to use is defined in the other path components. Signed-off-by: Arseny Maslennikov --- docs/efidp_make_generic.3 | 9 ++++++++- src/dp-message.c | 31 +++++++++++++++++++++++++++++++ src/include/efivar/efivar-dp.h | 5 +++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/docs/efidp_make_generic.3 b/docs/efidp_make_generic.3 index 68feefbc..eac7f752 100644 --- a/docs/efidp_make_generic.3 +++ b/docs/efidp_make_generic.3 @@ -2,7 +2,7 @@ .SH NAME efidp_make_generic, efidp_make_end_instance, efidp_make_end_entire, efidp_make_vendor, efidp_make_file, efidp_make_hd, efidp_make_nvme, -efidp_make_sas, efidp_make_ipv4, efidp_make_mac_addr, efidp_make_sata, +efidp_make_sas, efidp_make_ipv4, efidp_make_ipv6, efidp_make_mac_addr, efidp_make_sata, efidp_make_scsi, efidp_make_acpi_hid, efidp_make_acpi_hid_ex, efidp_make_edd10, efidp_make_pci, efidp_make_hw_vendor, efidp_make_msg_vendor, efidp_make_media_vendor \- Create EFI Device Path node data structures for specific device types @@ -62,6 +62,13 @@ Format EFI Device Path structures as printable strings. uint16_t \fIlocal_port\fB, uint16_t \fIremote_port\fB, uint16_t \fIprotocol\fB, int \fIis_static\fB);\fR +\fBssize_t \fRefidp_make_ipv6\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB, +.ta \nZu + uint8_t *\fIlocal\fB, uint8_t *\fIremote\fB, + uint8_t *\fIgateway\fB, uint8_t \fIprefix_length\fB, + uint16_t \fIlocal_port\fB, uint16_t \fIremote_port\fB, + uint16_t \fIprotocol\fB, uint8_t \fIaddr_origin\fB);\fR + \fBssize_t \fRefidp_make_mac_addr\fB(\kZuint8_t *\fIbuf\fB, ssize_t \fIsize\fB, .ta \nZu uint8_t \fIif_type\fB, diff --git a/src/dp-message.c b/src/dp-message.c index 464fe0f9..cac15978 100644 --- a/src/dp-message.c +++ b/src/dp-message.c @@ -704,6 +704,37 @@ efidp_make_ipv4(uint8_t *buf, ssize_t size, uint32_t local, uint32_t remote, return sz; } +ssize_t PUBLIC +efidp_make_ipv6(uint8_t *buf, ssize_t size, + uint8_t *local_ipv6_addr, uint8_t *remote_ipv6_addr, + uint8_t *gateway_ipv6_addr, uint8_t prefix_length, + uint16_t local_port, uint16_t remote_port, + uint16_t protocol, uint8_t addr_origin) +{ + efidp_ipv6_addr *ipv6 = (efidp_ipv6_addr *)buf; + ssize_t sz = efidp_make_generic(buf, size, EFIDP_MESSAGE_TYPE, + EFIDP_MSG_IPv6, sizeof (*ipv6)); + ssize_t req = sizeof (*ipv6); + if (size && sz == req) { + memcpy(ipv6->local_ipv6_addr, local_ipv6_addr, + sizeof(ipv6->local_ipv6_addr)); + memcpy(ipv6->remote_ipv6_addr, remote_ipv6_addr, + sizeof(ipv6->remote_ipv6_addr)); + ipv6->local_port = htons(local_port); + ipv6->remote_port = htons(remote_port); + ipv6->protocol = htons(protocol); + ipv6->ip_addr_origin = addr_origin; + ipv6->prefix_length = prefix_length; + memcpy(ipv6->gateway_ipv6_addr, gateway_ipv6_addr, + sizeof(ipv6->gateway_ipv6_addr)); + } + + if (sz < 0) + efi_error("efidp_make_generic failed"); + + return sz; +} + ssize_t PUBLIC efidp_make_scsi(uint8_t *buf, ssize_t size, uint16_t target, uint16_t lun) { diff --git a/src/include/efivar/efivar-dp.h b/src/include/efivar/efivar-dp.h index 85a7f544..90e235d0 100644 --- a/src/include/efivar/efivar-dp.h +++ b/src/include/efivar/efivar-dp.h @@ -471,6 +471,11 @@ typedef struct { uint8_t prefix_length; uint8_t gateway_ipv6_addr[16]; } EFIVAR_PACKED efidp_ipv6_addr; +extern ssize_t efidp_make_ipv6(uint8_t *buf, ssize_t size, + uint8_t *local_ipv6_addr, uint8_t *remote_ipv6_addr, + uint8_t *gateway_ipv6_addr, uint8_t prefix_length, + uint16_t local_port, uint16_t remote_port, + uint16_t protocol, uint8_t addr_origin); #define EFIDP_IPv6_ORIGIN_MANUAL 0x00 #define EFIDP_IPv6_ORIGIN_STATIC 0x00 From 2d978de205dba88842d1595f245fa35ea7b8c9d5 Mon Sep 17 00:00:00 2001 From: Arseny Maslennikov Date: Sat, 14 Feb 2026 09:00:00 +0300 Subject: [PATCH 2/2] creator: add new function: efi_generate_ipv6_device_path If 0 is passed as the prefix_length argument, use a default value of 64. I doubt passing 0 there is universally safe. Provide a complete API accepting all the specified fields, but only set IPAddressOrigin for now and force everything else to defaults. Signed-off-by: Arseny Maslennikov --- src/creator.c | 62 ++++++++++++++++++++++++++++ src/include/efivar/efiboot-creator.h | 13 ++++++ 2 files changed, 75 insertions(+) diff --git a/src/creator.c b/src/creator.c index f780a80b..0b497463 100644 --- a/src/creator.c +++ b/src/creator.c @@ -493,6 +493,68 @@ efi_generate_ipv4_device_path(uint8_t *buf, ssize_t size, return off; } +static ssize_t NONNULL(3, 4, 5) +make_ipv6_path(uint8_t *buf, ssize_t size, + const char * const local_addr UNUSED, + const char * const remote_addr UNUSED, + const char * const gateway_addr UNUSED, + uint8_t prefix_length UNUSED, + uint16_t local_port UNUSED, + uint16_t remote_port UNUSED, + uint16_t protocol UNUSED, + uint8_t addr_origin) +{ + ssize_t ret; + + ret = efidp_make_ipv6(buf, size, 0, 0, 0, 64, 0, 0, 0, addr_origin); + if (ret < 0) + efi_error("could not make ipv6 DP node"); + return ret; +} + +ssize_t NONNULL(3, 4, 5, 6) PUBLIC +efi_generate_ipv6_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, + uint8_t prefix_length, + uint16_t local_port, + uint16_t remote_port, + uint16_t protocol, + uint8_t addr_origin) +{ + ssize_t off = 0; + ssize_t sz; + + sz = make_mac_path(buf, size, ifname); + if (sz < 0) { + efi_error("could not make MAC DP node"); + return -1; + } + off += sz; + + sz = make_ipv6_path(buf+off, size?size-off:0, + local_addr, remote_addr, + gateway_addr, prefix_length, + local_port, remote_port, + protocol, addr_origin); + if (sz < 0) { + efi_error("could not make IPV6 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"); + return -1; + } + off += sz; + + return off; +} + uint32_t PUBLIC efi_get_libefiboot_version(void) { diff --git a/src/include/efivar/efiboot-creator.h b/src/include/efivar/efiboot-creator.h index 175417db..7ffcbf82 100644 --- a/src/include/efivar/efiboot-creator.h +++ b/src/include/efivar/efiboot-creator.h @@ -47,6 +47,19 @@ 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_ipv6_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, + uint8_t prefix_length, + uint16_t local_port, + uint16_t remote_port, + uint16_t protocol, + uint8_t addr_origin) + __attribute__((__nonnull__ (3,4,5,6))) + __attribute__((__visibility__ ("default"))); + #ifdef __cplusplus } /* extern "C" */ #endif