blob: ac250bbfcc9986113c6cdf61ab6e2e74f512f92f [file] [log] [blame]
Tom Rini70df9d62018-05-07 17:02:21 -04001// SPDX-License-Identifier: GPL-2.0+
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +01002/*
3 * EFI device path interface
4 *
5 * Copyright (c) 2017 Leif Lindholm
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +01006 */
7
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +01008#include <efi_loader.h>
9
10const efi_guid_t efi_guid_device_path_utilities_protocol =
11 EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID;
12
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +020013/*
14 * Get size of a device path.
15 *
16 * This function implements the GetDevicePathSize service of the device path
17 * utilities protocol. The device path length includes the end of path tag
18 * which may be an instance end.
19 *
20 * See the Unified Extensible Firmware Interface (UEFI) specification
21 * for details.
22 *
23 * @device_path device path
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +010024 * Return: size in bytes
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +020025 */
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +010026static efi_uintn_t EFIAPI get_device_path_size(
27 const struct efi_device_path *device_path)
28{
29 efi_uintn_t sz = 0;
30
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +020031 EFI_ENTRY("%pD", device_path);
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +010032 /* size includes the END node: */
33 if (device_path)
34 sz = efi_dp_size(device_path) + sizeof(struct efi_device_path);
35 return EFI_EXIT(sz);
36}
37
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +020038/*
39 * Duplicate a device path.
40 *
41 * This function implements the DuplicateDevicePath service of the device path
42 * utilities protocol.
43 *
44 * The UEFI spec does not indicate what happens to the end tag. We follow the
45 * EDK2 logic: In case the device path ends with an end of instance tag, the
46 * copy will also end with an end of instance tag.
47 *
48 * See the Unified Extensible Firmware Interface (UEFI) specification
49 * for details.
50 *
51 * @device_path device path
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +010052 * Return: copy of the device path
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +020053 */
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +010054static struct efi_device_path * EFIAPI duplicate_device_path(
55 const struct efi_device_path *device_path)
56{
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +020057 EFI_ENTRY("%pD", device_path);
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +010058 return EFI_EXIT(efi_dp_dup(device_path));
59}
60
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +020061/*
62 * Append device path.
63 *
64 * This function implements the AppendDevicePath service of the device path
65 * utilities protocol.
66 *
67 * See the Unified Extensible Firmware Interface (UEFI) specification
68 * for details.
69 *
70 * @src1 1st device path
71 * @src2 2nd device path
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +010072 * Return: concatenated device path
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +020073 */
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +010074static struct efi_device_path * EFIAPI append_device_path(
75 const struct efi_device_path *src1,
76 const struct efi_device_path *src2)
77{
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +020078 EFI_ENTRY("%pD, %pD", src1, src2);
Heinrich Schuchardtf8de0092024-05-24 14:54:26 +020079 return EFI_EXIT(efi_dp_concat(src1, src2, 0));
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +010080}
81
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +020082/*
83 * Append device path node.
84 *
85 * This function implements the AppendDeviceNode service of the device path
86 * utilities protocol.
87 *
88 * See the Unified Extensible Firmware Interface (UEFI) specification
89 * for details.
90 *
91 * @device_path device path
92 * @device_node device node
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +010093 * Return: concatenated device path
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +020094 */
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +010095static struct efi_device_path * EFIAPI append_device_node(
96 const struct efi_device_path *device_path,
97 const struct efi_device_path *device_node)
98{
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +020099 EFI_ENTRY("%pD, %p", device_path, device_node);
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +0100100 return EFI_EXIT(efi_dp_append_node(device_path, device_node));
101}
102
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +0200103/*
104 * Append device path instance.
105 *
106 * This function implements the AppendDevicePathInstance service of the device
107 * path utilities protocol.
108 *
109 * See the Unified Extensible Firmware Interface (UEFI) specification
110 * for details.
111 *
112 * @device_path 1st device path
113 * @device_path_instance 2nd device path
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100114 * Return: concatenated device path
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +0200115 */
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +0100116static struct efi_device_path * EFIAPI append_device_path_instance(
117 const struct efi_device_path *device_path,
118 const struct efi_device_path *device_path_instance)
119{
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +0200120 EFI_ENTRY("%pD, %pD", device_path, device_path_instance);
121 return EFI_EXIT(efi_dp_append_instance(device_path,
122 device_path_instance));
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +0100123}
124
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +0200125/*
126 * Get next device path instance.
127 *
128 * This function implements the GetNextDevicePathInstance service of the device
129 * path utilities protocol.
130 *
131 * See the Unified Extensible Firmware Interface (UEFI) specification
132 * for details.
133 *
134 * @device_path_instance next device path instance
135 * @device_path_instance_size size of the device path instance
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100136 * Return: concatenated device path
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +0200137 */
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +0100138static struct efi_device_path * EFIAPI get_next_device_path_instance(
139 struct efi_device_path **device_path_instance,
140 efi_uintn_t *device_path_instance_size)
141{
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +0200142 EFI_ENTRY("%pD, %p", device_path_instance, device_path_instance_size);
143 return EFI_EXIT(efi_dp_get_next_instance(device_path_instance,
144 device_path_instance_size));
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +0100145}
146
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +0200147/*
148 * Check if a device path contains more than one instance.
149 *
150 * This function implements the AppendDeviceNode service of the device path
151 * utilities protocol.
152 *
153 * See the Unified Extensible Firmware Interface (UEFI) specification
154 * for details.
155 *
156 * @device_path device path
157 * @device_node device node
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100158 * Return: concatenated device path
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +0200159 */
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +0100160static bool EFIAPI is_device_path_multi_instance(
161 const struct efi_device_path *device_path)
162{
Heinrich Schuchardtcb0f7ce2018-04-16 07:59:09 +0200163 EFI_ENTRY("%pD", device_path);
164 return EFI_EXIT(efi_dp_is_multi_instance(device_path));
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +0100165}
166
Heinrich Schuchardtb41c8e22018-04-16 07:59:05 +0200167/*
168 * Create device node.
169 *
170 * This function implements the CreateDeviceNode service of the device path
171 * utilities protocol.
172 *
173 * See the Unified Extensible Firmware Interface (UEFI) specification
174 * for details.
175 *
176 * @node_type node type
177 * @node_sub_type node sub type
178 * @node_length node length
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100179 * Return: device path node
Heinrich Schuchardtb41c8e22018-04-16 07:59:05 +0200180 */
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +0100181static struct efi_device_path * EFIAPI create_device_node(
182 uint8_t node_type, uint8_t node_sub_type, uint16_t node_length)
183{
184 EFI_ENTRY("%u, %u, %u", node_type, node_sub_type, node_length);
Heinrich Schuchardtb41c8e22018-04-16 07:59:05 +0200185 return EFI_EXIT(efi_dp_create_device_node(node_type, node_sub_type,
186 node_length));
Leif Lindholmb6e6fdc2018-03-09 17:43:21 +0100187}
188
189const struct efi_device_path_utilities_protocol efi_device_path_utilities = {
190 .get_device_path_size = get_device_path_size,
191 .duplicate_device_path = duplicate_device_path,
192 .append_device_path = append_device_path,
193 .append_device_node = append_device_node,
194 .append_device_path_instance = append_device_path_instance,
195 .get_next_device_path_instance = get_next_device_path_instance,
196 .is_device_path_multi_instance = is_device_path_multi_instance,
197 .create_device_node = create_device_node,
198};