File 2000-libefi-device-path-introduce-make_multiple_file_devi.patch of Package systemd

From 3d0f798c21c36aa4810913315c127dcd5a087d0a Mon Sep 17 00:00:00 2001
From: Raito Bezarius <masterancpp@gmail.com>
Date: Sat, 17 Jun 2023 19:42:43 +0200
Subject: [PATCH 2000/2007] libefi(device-path): introduce
 `make_multiple_file_device_path`
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This build an `EfiDevicePath**` of the form:

`FilePath(\files[0])\EndNode()FilePath(\files[1])\EndNode()…\FilePath(\files[n])\EndNode()`

which should really be read as a list:

[ FilePath(\files[0])\EndNode() ; FilePath(\files(1))\EndNode() ; … ;
FilePath(\files[n])\EndNode() ]
---
 src/boot/device-path-util.c | 63 +++++++++++++++++++++++++++++++++++++
 src/boot/device-path-util.h | 14 +++++++++
 2 files changed, 77 insertions(+)

diff --git a/src/boot/device-path-util.c b/src/boot/device-path-util.c
index 2a85e8bbfc..e7a067ea01 100644
--- a/src/boot/device-path-util.c
+++ b/src/boot/device-path-util.c
@@ -3,6 +3,69 @@
 #include "device-path-util.h"
 #include "util.h"
 
+EFI_STATUS make_multiple_file_device_path(
+                EFI_HANDLE device, const char16_t **files, EFI_DEVICE_PATH ***ret_dp) {
+        EFI_STATUS err;
+        EFI_DEVICE_PATH *cur_dp = NULL, **iterator_dp = NULL;
+        EFI_DEVICE_PATH *original_device_path = NULL;
+        size_t n_files = strv_length((const void**)files);
+
+        assert(files);
+        assert(ret_dp);
+
+        if (n_files == 0) {
+                *ret_dp = NULL;
+                return EFI_SUCCESS;
+        };
+
+        err = BS->HandleProtocol(device, MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL),
+                                 (void **) &original_device_path);
+        if (err != EFI_SUCCESS)
+                return err;
+
+        EFI_DEVICE_PATH *end_node = original_device_path;
+        while (!device_path_is_end(end_node))
+                end_node = device_path_next_node(end_node);
+
+        size_t o_dp_size = (uint8_t *) end_node - (uint8_t *) original_device_path;
+
+
+        *ret_dp = xnew(EFI_DEVICE_PATH*, n_files + 1);
+
+        iterator_dp = ret_dp[0];
+
+        STRV_FOREACH(file, files) {
+                size_t file_size = strsize16(*file);
+
+                /* 1st element: FILEPATH_DEVICE_PATH + path name payload */
+                /* 2nd element: DEVICE_PATH_END_NODE */
+                *iterator_dp = xnew(EFI_DEVICE_PATH, o_dp_size +
+                                    sizeof(FILEPATH_DEVICE_PATH)
+                                    + file_size
+                                    + sizeof(EFI_DEVICE_PATH));
+                cur_dp = *iterator_dp;
+
+                /* Prepend the original device path */
+                cur_dp = mempcpy(cur_dp, original_device_path, o_dp_size);
+
+                FILEPATH_DEVICE_PATH *file_dp = (FILEPATH_DEVICE_PATH *) cur_dp;
+                file_dp->Header = (EFI_DEVICE_PATH) {
+                        .Type = MEDIA_DEVICE_PATH,
+                        .SubType = MEDIA_FILEPATH_DP,
+                        .Length = sizeof(FILEPATH_DEVICE_PATH) + file_size,
+                };
+                memcpy(file_dp->PathName, *file, file_size);
+
+                cur_dp = device_path_next_node(cur_dp);
+                *cur_dp = DEVICE_PATH_END_NODE;
+
+                iterator_dp++;
+        }
+        *iterator_dp = NULL;
+
+        return EFI_SUCCESS;
+}
+
 EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DEVICE_PATH **ret_dp) {
         EFI_STATUS err;
         EFI_DEVICE_PATH *dp;
diff --git a/src/boot/device-path-util.h b/src/boot/device-path-util.h
index 08f1a9c216..5071b44016 100644
--- a/src/boot/device-path-util.h
+++ b/src/boot/device-path-util.h
@@ -3,6 +3,8 @@
 
 #include "proto/device-path.h"
 
+EFI_STATUS make_multiple_file_device_path(EFI_HANDLE device, const char16_t **files, EFI_DEVICE_PATH
+                ***ret_dp);
 EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DEVICE_PATH **ret_dp);
 EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret);
 bool device_path_startswith(const EFI_DEVICE_PATH *dp, const EFI_DEVICE_PATH *start);
@@ -19,9 +21,21 @@ static inline bool device_path_is_end(const EFI_DEVICE_PATH *dp) {
         return dp->Type == END_DEVICE_PATH_TYPE && dp->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE;
 }
 
+static inline bool device_path_is_end_instance(const EFI_DEVICE_PATH *dp) {
+        assert(dp);
+        return dp->Type == END_DEVICE_PATH_TYPE && dp->SubType == END_INSTANCE_DEVICE_PATH_SUBTYPE;
+}
+
 #define DEVICE_PATH_END_NODE                               \
         (EFI_DEVICE_PATH) {                                \
                 .Type = END_DEVICE_PATH_TYPE,              \
                 .SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE, \
                 .Length = sizeof(EFI_DEVICE_PATH)          \
         }
+
+#define DEVICE_PATH_END_INSTANCE                             \
+        (EFI_DEVICE_PATH) {                                  \
+                .Type = END_DEVICE_PATH_TYPE,                \
+                .SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE, \
+                .Length = sizeof(EFI_DEVICE_PATH)            \
+        }
-- 
2.49.0

openSUSE Build Service is sponsored by