]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
boot: Manually convert filepaths if needed
authorJan Janssen <medhefgo@web.de>
Mon, 14 Nov 2022 14:24:32 +0000 (15:24 +0100)
committerJan Janssen <medhefgo@web.de>
Sat, 19 Nov 2022 15:36:02 +0000 (16:36 +0100)
The conversion of a filepath device path to text is needed for the stub
loader to find credential files.

src/boot/efi/util.c

index 5547d288de1b2bb5bc07e17476b4d6696bd7f689..57436dbf0cada22b0cc9801abd223aefc1ac6a54 100644 (file)
@@ -772,19 +772,51 @@ EFI_STATUS make_file_device_path(EFI_HANDLE device, const char16_t *file, EFI_DE
 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(&(EFI_GUID) EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID, NULL, (void **) &dp_to_text);
-        if (err != EFI_SUCCESS)
-                return err;
+        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;
+        }
 
-        char16_t *str = dp_to_text->ConvertDevicePathToText(dp, false, false);
+        str = dp_to_text->ConvertDevicePathToText(dp, false, false);
         if (!str)
                 return EFI_OUT_OF_RESOURCES;
 
-        *ret = str;
+        *ret = TAKE_PTR(str);
         return EFI_SUCCESS;
 }