]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot: Split out device path functions
authorJan Janssen <medhefgo@web.de>
Sat, 7 Jan 2023 10:39:07 +0000 (11:39 +0100)
committerJan Janssen <medhefgo@web.de>
Wed, 22 Feb 2023 20:54:11 +0000 (21:54 +0100)
No code changes aside from renaming path_replace_hd() and making its
parameter take any device path node type.

12 files changed:
src/boot/efi/boot.c
src/boot/efi/cpio.c
src/boot/efi/device-path-util.c [new file with mode: 0644]
src/boot/efi/device-path-util.h [new file with mode: 0644]
src/boot/efi/drivers.c
src/boot/efi/meson.build
src/boot/efi/part-discovery.c
src/boot/efi/shim.c
src/boot/efi/stub.c
src/boot/efi/util.c
src/boot/efi/util.h
src/boot/efi/vmm.c

index 3bd3469f821a6c415c071df5b70c7dab0a6c4918..ee507e379ac98c77c04f4fb62e9b728e9c446d4a 100644 (file)
@@ -3,6 +3,7 @@
 #include "bcd.h"
 #include "bootspec-fundamental.h"
 #include "console.h"
+#include "device-path-util.h"
 #include "devicetree.h"
 #include "drivers.h"
 #include "efivars-fundamental.h"
index 2e971a91679d41b14e1b79f2452d695eef1e5a4f..acfefbb001576067fc1374ba82a8ac41fe795c5c 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include "cpio.h"
+#include "device-path-util.h"
 #include "measure.h"
 #include "proto/device-path.h"
 #include "util.h"
diff --git a/src/boot/efi/device-path-util.c b/src/boot/efi/device-path-util.c
new file mode 100644 (file)
index 0000000..4e0b3db
--- /dev/null
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include "device-path-util.h"
+#include "proto/device-path.h"
+#include "util.h"
+
+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;
+
+        assert(file);
+        assert(ret_dp);
+
+        err = BS->HandleProtocol(device, MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL), (void **) &dp);
+        if (err != EFI_SUCCESS)
+                return err;
+
+        EFI_DEVICE_PATH *end_node = dp;
+        while (!IsDevicePathEnd(end_node))
+                end_node = NextDevicePathNode(end_node);
+
+        size_t file_size = strsize16(file);
+        size_t dp_size = (uint8_t *) end_node - (uint8_t *) dp;
+
+        /* Make a copy that can also hold a file media device path. */
+        *ret_dp = xmalloc(dp_size + file_size + sizeof(FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH));
+        dp = mempcpy(*ret_dp, dp, dp_size);
+
+        /* Replace end node with file media device path. Use memcpy() in case dp is unaligned (if accessed as
+         * FILEPATH_DEVICE_PATH). */
+        dp->Type = MEDIA_DEVICE_PATH;
+        dp->SubType = MEDIA_FILEPATH_DP;
+        dp->Length = sizeof(FILEPATH_DEVICE_PATH) + file_size;
+        memcpy((uint8_t *) dp + sizeof(FILEPATH_DEVICE_PATH), file, file_size);
+
+        dp = NextDevicePathNode(dp);
+        SetDevicePathEndNode(dp);
+        return EFI_SUCCESS;
+}
+
+EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret) {
+        EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *dp_to_text;
+        EFI_STATUS err;
+        _cleanup_free_ char16_t *str = NULL;
+
+        assert(dp);
+        assert(ret);
+
+        err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_DEVICE_PATH_TO_TEXT_PROTOCOL), NULL, (void **) &dp_to_text);
+        if (err != EFI_SUCCESS) {
+                /* If the device path to text protocol is not available we can still do a best-effort attempt
+                 * to convert it ourselves if we are given filepath-only device path. */
+
+                size_t size = 0;
+                for (const EFI_DEVICE_PATH *node = dp; !IsDevicePathEnd(node);
+                     node = NextDevicePathNode(node)) {
+
+                        if (DevicePathType(node) != MEDIA_DEVICE_PATH ||
+                            DevicePathSubType(node) != MEDIA_FILEPATH_DP)
+                                return err;
+
+                        size_t path_size = DevicePathNodeLength(node);
+                        if (path_size <= offsetof(FILEPATH_DEVICE_PATH, PathName) || path_size % sizeof(char16_t))
+                                return EFI_INVALID_PARAMETER;
+                        path_size -= offsetof(FILEPATH_DEVICE_PATH, PathName);
+
+                        _cleanup_free_ char16_t *old = str;
+                        str = xmalloc(size + path_size);
+                        if (old) {
+                                memcpy(str, old, size);
+                                str[size / sizeof(char16_t) - 1] = '\\';
+                        }
+
+                        memcpy(str + (size / sizeof(char16_t)),
+                               ((uint8_t *) node) + offsetof(FILEPATH_DEVICE_PATH, PathName),
+                               path_size);
+                        size += path_size;
+                }
+
+                *ret = TAKE_PTR(str);
+                return EFI_SUCCESS;
+        }
+
+        str = dp_to_text->ConvertDevicePathToText(dp, false, false);
+        if (!str)
+                return EFI_OUT_OF_RESOURCES;
+
+        *ret = TAKE_PTR(str);
+        return EFI_SUCCESS;
+}
+
+bool device_path_startswith(const EFI_DEVICE_PATH *dp, const EFI_DEVICE_PATH *start) {
+        if (!start)
+                return true;
+        if (!dp)
+                return false;
+        for (;;) {
+                if (IsDevicePathEnd(start))
+                        return true;
+                if (IsDevicePathEnd(dp))
+                        return false;
+                size_t l1 = DevicePathNodeLength(start);
+                size_t l2 = DevicePathNodeLength(dp);
+                if (l1 != l2)
+                        return false;
+                if (memcmp(dp, start, l1) != 0)
+                        return false;
+                start = NextDevicePathNode(start);
+                dp = NextDevicePathNode(dp);
+        }
+}
+
+EFI_DEVICE_PATH *device_path_replace_node(
+                const EFI_DEVICE_PATH *path, const EFI_DEVICE_PATH *node, const EFI_DEVICE_PATH *new_node) {
+
+        /* Create a new device path as a copy of path, while chopping off the remainder starting at the given
+         * node. If new_node is provided, it is appended at the end of the new path. */
+
+        assert(path);
+        assert(node);
+
+        size_t len = (uint8_t *) node - (uint8_t *) path, new_node_len = 0;
+        if (new_node)
+                new_node_len = DevicePathNodeLength(new_node);
+
+        EFI_DEVICE_PATH *ret = xmalloc(len + new_node_len + sizeof(EFI_DEVICE_PATH));
+        EFI_DEVICE_PATH *end = mempcpy(ret, path, len);
+
+        if (new_node)
+                end = mempcpy(end, new_node, new_node_len);
+
+        SetDevicePathEndNode(end);
+        return ret;
+}
diff --git a/src/boot/efi/device-path-util.h b/src/boot/efi/device-path-util.h
new file mode 100644 (file)
index 0000000..acc6ed0
--- /dev/null
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#pragma once
+
+#include "efi.h"
+
+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);
+EFI_DEVICE_PATH *device_path_replace_node(
+                const EFI_DEVICE_PATH *path, const EFI_DEVICE_PATH *node, const EFI_DEVICE_PATH *new_node);
index 25bf6947236e12e32d47ced52801d765380ffc33..067455771f6ad4eff37bf729496330ab1ae42610 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include "device-path-util.h"
 #include "drivers.h"
 #include "util.h"
 
index e6166075be1c0eef2f8a956fb2faa3a5108f75b4..bf595c33901edb86f86e5554e3a03f010509cc8e 100644 (file)
@@ -332,6 +332,7 @@ efi_headers = files(
         'bcd.h',
         'console.h',
         'cpio.h',
+        'device-path-util.h',
         'devicetree.h',
         'drivers.h',
         'efi-string.h',
@@ -366,6 +367,7 @@ efi_headers = files(
 
 common_sources = files(
         'console.c',
+        'device-path-util.c',
         'devicetree.c',
         'drivers.c',
         'efi-string.c',
index 5d3999550990e8e8be77a33549e4e5f6b3b16c88..e71daf0382d47912575d7426c3938981a8bdde51 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include "device-path-util.h"
 #include "part-discovery.h"
 #include "proto/block-io.h"
 #include "proto/device-path.h"
@@ -29,31 +30,6 @@ typedef struct {
 } _packed_ GptHeader;
 assert_cc(sizeof(GptHeader) == 512);
 
-static EFI_DEVICE_PATH *path_replace_hd(
-                const EFI_DEVICE_PATH *path,
-                const EFI_DEVICE_PATH *node,
-                const HARDDRIVE_DEVICE_PATH *new_node) {
-
-        /* Create a new device path as a copy of path, while chopping off the remainder starting at the given
-         * node. If new_node is provided, it is appended at the end of the new path. */
-
-        assert(path);
-        assert(node);
-
-        size_t len = (uint8_t *) node - (uint8_t *) path, new_node_len = 0;
-        if (new_node)
-                new_node_len = DevicePathNodeLength(&new_node->Header);
-
-        EFI_DEVICE_PATH *ret = xmalloc(len + new_node_len + sizeof(EFI_DEVICE_PATH));
-        EFI_DEVICE_PATH *end = mempcpy(ret, path, len);
-
-        if (new_node)
-                end = mempcpy(end, new_node, new_node_len);
-
-        SetDevicePathEndNode(end);
-        return ret;
-}
-
 static bool verify_gpt(/*const*/ GptHeader *h, EFI_LBA lba_expected) {
         uint32_t crc32, crc32_saved;
         EFI_STATUS err;
@@ -204,7 +180,7 @@ static EFI_STATUS find_device(const EFI_GUID *type, EFI_HANDLE *device, EFI_DEVI
 
         /* Chop off the partition part, leaving us with the full path to the disk itself. */
         _cleanup_free_ EFI_DEVICE_PATH *disk_path = NULL;
-        EFI_DEVICE_PATH *p = disk_path = path_replace_hd(partition_path, part_node, NULL);
+        EFI_DEVICE_PATH *p = disk_path = device_path_replace_node(partition_path, part_node, NULL);
 
         EFI_HANDLE disk_handle;
         EFI_BLOCK_IO_PROTOCOL *block_io;
@@ -258,7 +234,7 @@ static EFI_STATUS find_device(const EFI_GUID *type, EFI_HANDLE *device, EFI_DEVI
                 }
 
                 /* Patch in the data we found */
-                *ret_device_path = path_replace_hd(partition_path, part_node, &hd);
+                *ret_device_path = device_path_replace_node(partition_path, part_node, (EFI_DEVICE_PATH *) &hd);
                 return EFI_SUCCESS;
         }
 
index e0bb470cf2b62a747ca2f73c62ae4d7a3b700258..dda727ee8ed6d5f04815f54d56ddbc7be35955ed 100644 (file)
@@ -8,6 +8,7 @@
  * https://github.com/mjg59/efitools
  */
 
+#include "device-path-util.h"
 #include "secure-boot.h"
 #include "shim.h"
 #include "util.h"
index 4b8e1e69d90b6cd51d8487a83b2724e9c2ee73e4..2635445b04030ade51ef425a0d15c7b71f44de86 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include "cpio.h"
+#include "device-path-util.h"
 #include "devicetree.h"
 #include "graphics.h"
 #include "linux.h"
index 96c62e6bfa210f09b624596e7cc473e018d0bf0c..19c4788b8f00748c5dc4bf29ebb429b2cbb4d621 100644 (file)
@@ -622,91 +622,6 @@ EFI_STATUS open_volume(EFI_HANDLE device, EFI_FILE **ret_file) {
         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;
-
-        assert(file);
-        assert(ret_dp);
-
-        err = BS->HandleProtocol(device, MAKE_GUID_PTR(EFI_DEVICE_PATH_PROTOCOL), (void **) &dp);
-        if (err != EFI_SUCCESS)
-                return err;
-
-        EFI_DEVICE_PATH *end_node = dp;
-        while (!IsDevicePathEnd(end_node))
-                end_node = NextDevicePathNode(end_node);
-
-        size_t file_size = strsize16(file);
-        size_t dp_size = (uint8_t *) end_node - (uint8_t *) dp;
-
-        /* Make a copy that can also hold a file media device path. */
-        *ret_dp = xmalloc(dp_size + file_size + sizeof(FILEPATH_DEVICE_PATH) + sizeof(EFI_DEVICE_PATH));
-        dp = mempcpy(*ret_dp, dp, dp_size);
-
-        /* Replace end node with file media device path. Use memcpy() in case dp is unaligned (if accessed as
-         * FILEPATH_DEVICE_PATH). */
-        dp->Type = MEDIA_DEVICE_PATH;
-        dp->SubType = MEDIA_FILEPATH_DP;
-        dp->Length = sizeof(FILEPATH_DEVICE_PATH) + file_size;
-        memcpy((uint8_t *) dp + sizeof(FILEPATH_DEVICE_PATH), file, file_size);
-
-        dp = NextDevicePathNode(dp);
-        SetDevicePathEndNode(dp);
-        return EFI_SUCCESS;
-}
-
-EFI_STATUS device_path_to_str(const EFI_DEVICE_PATH *dp, char16_t **ret) {
-        EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *dp_to_text;
-        EFI_STATUS err;
-        _cleanup_free_ char16_t *str = NULL;
-
-        assert(dp);
-        assert(ret);
-
-        err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_DEVICE_PATH_TO_TEXT_PROTOCOL), NULL, (void **) &dp_to_text);
-        if (err != EFI_SUCCESS) {
-                /* If the device path to text protocol is not available we can still do a best-effort attempt
-                 * to convert it ourselves if we are given filepath-only device path. */
-
-                size_t size = 0;
-                for (const EFI_DEVICE_PATH *node = dp; !IsDevicePathEnd(node);
-                     node = NextDevicePathNode(node)) {
-
-                        if (DevicePathType(node) != MEDIA_DEVICE_PATH ||
-                            DevicePathSubType(node) != MEDIA_FILEPATH_DP)
-                                return err;
-
-                        size_t path_size = DevicePathNodeLength(node);
-                        if (path_size <= offsetof(FILEPATH_DEVICE_PATH, PathName) || path_size % sizeof(char16_t))
-                                return EFI_INVALID_PARAMETER;
-                        path_size -= offsetof(FILEPATH_DEVICE_PATH, PathName);
-
-                        _cleanup_free_ char16_t *old = str;
-                        str = xmalloc(size + path_size);
-                        if (old) {
-                                memcpy(str, old, size);
-                                str[size / sizeof(char16_t) - 1] = '\\';
-                        }
-
-                        memcpy(str + (size / sizeof(char16_t)),
-                               ((uint8_t *) node) + offsetof(FILEPATH_DEVICE_PATH, PathName),
-                               path_size);
-                        size += path_size;
-                }
-
-                *ret = TAKE_PTR(str);
-                return EFI_SUCCESS;
-        }
-
-        str = dp_to_text->ConvertDevicePathToText(dp, false, false);
-        if (!str)
-                return EFI_OUT_OF_RESOURCES;
-
-        *ret = TAKE_PTR(str);
-        return EFI_SUCCESS;
-}
-
 void *find_configuration_table(const EFI_GUID *guid) {
         for (size_t i = 0; i < ST->NumberOfTableEntries; i++)
                 if (efi_guid_equal(&ST->ConfigurationTable[i].VendorGuid, guid))
index 614d83fb71b07dcfcedd58eceec25f6bfdefe20f..198e8449716b9b7d0830248188127050192bd9b5 100644 (file)
@@ -184,8 +184,6 @@ static inline void beep(unsigned beep_count) {}
 #endif
 
 EFI_STATUS open_volume(EFI_HANDLE device, EFI_FILE **ret_file);
-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);
 
 static inline bool efi_guid_equal(const EFI_GUID *a, const EFI_GUID *b) {
         return memcmp(a, b, sizeof(EFI_GUID)) == 0;
index c3816e1b2dfc00b93df1b7da12964649096c3bde..61b50a3b94fdc86d6a4d3254812c6d1b8d4f0e78 100644 (file)
@@ -4,6 +4,7 @@
 #  include <cpuid.h>
 #endif
 
+#include "device-path-util.h"
 #include "drivers.h"
 #include "efi-string.h"
 #include "proto/device-path.h"
@@ -39,27 +40,6 @@ bool is_direct_boot(EFI_HANDLE device) {
         return false;
 }
 
-static bool device_path_startswith(const EFI_DEVICE_PATH *dp, const EFI_DEVICE_PATH *start) {
-        if (!start)
-                return true;
-        if (!dp)
-                return false;
-        for (;;) {
-                if (IsDevicePathEnd(start))
-                        return true;
-                if (IsDevicePathEnd(dp))
-                        return false;
-                size_t l1 = DevicePathNodeLength(start);
-                size_t l2 = DevicePathNodeLength(dp);
-                if (l1 != l2)
-                        return false;
-                if (memcmp(dp, start, l1) != 0)
-                        return false;
-                start = NextDevicePathNode(start);
-                dp    = NextDevicePathNode(dp);
-        }
-}
-
 /*
  * Try find ESP when not loaded from ESP
  *