]>
Commit | Line | Data |
---|---|---|
f739fcd8 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
e70f8dfa LL |
2 | /* |
3 | * EFI device path interface | |
4 | * | |
5 | * Copyright (c) 2017 Leif Lindholm | |
e70f8dfa LL |
6 | */ |
7 | ||
8 | #include <common.h> | |
9 | #include <efi_loader.h> | |
10 | ||
11 | const efi_guid_t efi_guid_device_path_utilities_protocol = | |
12 | EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID; | |
13 | ||
3acef5da HS |
14 | /* |
15 | * Get size of a device path. | |
16 | * | |
17 | * This function implements the GetDevicePathSize service of the device path | |
18 | * utilities protocol. The device path length includes the end of path tag | |
19 | * which may be an instance end. | |
20 | * | |
21 | * See the Unified Extensible Firmware Interface (UEFI) specification | |
22 | * for details. | |
23 | * | |
24 | * @device_path device path | |
25 | * @return size in bytes | |
26 | */ | |
e70f8dfa LL |
27 | static efi_uintn_t EFIAPI get_device_path_size( |
28 | const struct efi_device_path *device_path) | |
29 | { | |
30 | efi_uintn_t sz = 0; | |
31 | ||
3acef5da | 32 | EFI_ENTRY("%pD", device_path); |
e70f8dfa LL |
33 | /* size includes the END node: */ |
34 | if (device_path) | |
35 | sz = efi_dp_size(device_path) + sizeof(struct efi_device_path); | |
36 | return EFI_EXIT(sz); | |
37 | } | |
38 | ||
3acef5da HS |
39 | /* |
40 | * Duplicate a device path. | |
41 | * | |
42 | * This function implements the DuplicateDevicePath service of the device path | |
43 | * utilities protocol. | |
44 | * | |
45 | * The UEFI spec does not indicate what happens to the end tag. We follow the | |
46 | * EDK2 logic: In case the device path ends with an end of instance tag, the | |
47 | * copy will also end with an end of instance tag. | |
48 | * | |
49 | * See the Unified Extensible Firmware Interface (UEFI) specification | |
50 | * for details. | |
51 | * | |
52 | * @device_path device path | |
53 | * @return copy of the device path | |
54 | */ | |
e70f8dfa LL |
55 | static struct efi_device_path * EFIAPI duplicate_device_path( |
56 | const struct efi_device_path *device_path) | |
57 | { | |
3acef5da | 58 | EFI_ENTRY("%pD", device_path); |
e70f8dfa LL |
59 | return EFI_EXIT(efi_dp_dup(device_path)); |
60 | } | |
61 | ||
3acef5da HS |
62 | /* |
63 | * Append device path. | |
64 | * | |
65 | * This function implements the AppendDevicePath service of the device path | |
66 | * utilities protocol. | |
67 | * | |
68 | * See the Unified Extensible Firmware Interface (UEFI) specification | |
69 | * for details. | |
70 | * | |
71 | * @src1 1st device path | |
72 | * @src2 2nd device path | |
73 | * @return concatenated device path | |
74 | */ | |
e70f8dfa LL |
75 | static struct efi_device_path * EFIAPI append_device_path( |
76 | const struct efi_device_path *src1, | |
77 | const struct efi_device_path *src2) | |
78 | { | |
3acef5da | 79 | EFI_ENTRY("%pD, %pD", src1, src2); |
e70f8dfa LL |
80 | return EFI_EXIT(efi_dp_append(src1, src2)); |
81 | } | |
82 | ||
3acef5da HS |
83 | /* |
84 | * Append device path node. | |
85 | * | |
86 | * This function implements the AppendDeviceNode service of the device path | |
87 | * utilities protocol. | |
88 | * | |
89 | * See the Unified Extensible Firmware Interface (UEFI) specification | |
90 | * for details. | |
91 | * | |
92 | * @device_path device path | |
93 | * @device_node device node | |
94 | * @return concatenated device path | |
95 | */ | |
e70f8dfa LL |
96 | static struct efi_device_path * EFIAPI append_device_node( |
97 | const struct efi_device_path *device_path, | |
98 | const struct efi_device_path *device_node) | |
99 | { | |
3acef5da | 100 | EFI_ENTRY("%pD, %p", device_path, device_node); |
e70f8dfa LL |
101 | return EFI_EXIT(efi_dp_append_node(device_path, device_node)); |
102 | } | |
103 | ||
3acef5da HS |
104 | /* |
105 | * Append device path instance. | |
106 | * | |
107 | * This function implements the AppendDevicePathInstance service of the device | |
108 | * path utilities protocol. | |
109 | * | |
110 | * See the Unified Extensible Firmware Interface (UEFI) specification | |
111 | * for details. | |
112 | * | |
113 | * @device_path 1st device path | |
114 | * @device_path_instance 2nd device path | |
115 | * @return concatenated device path | |
116 | */ | |
e70f8dfa LL |
117 | static struct efi_device_path * EFIAPI append_device_path_instance( |
118 | const struct efi_device_path *device_path, | |
119 | const struct efi_device_path *device_path_instance) | |
120 | { | |
3acef5da HS |
121 | EFI_ENTRY("%pD, %pD", device_path, device_path_instance); |
122 | return EFI_EXIT(efi_dp_append_instance(device_path, | |
123 | device_path_instance)); | |
e70f8dfa LL |
124 | } |
125 | ||
3acef5da HS |
126 | /* |
127 | * Get next device path instance. | |
128 | * | |
129 | * This function implements the GetNextDevicePathInstance service of the device | |
130 | * path utilities protocol. | |
131 | * | |
132 | * See the Unified Extensible Firmware Interface (UEFI) specification | |
133 | * for details. | |
134 | * | |
135 | * @device_path_instance next device path instance | |
136 | * @device_path_instance_size size of the device path instance | |
137 | * @return concatenated device path | |
138 | */ | |
e70f8dfa LL |
139 | static struct efi_device_path * EFIAPI get_next_device_path_instance( |
140 | struct efi_device_path **device_path_instance, | |
141 | efi_uintn_t *device_path_instance_size) | |
142 | { | |
3acef5da HS |
143 | EFI_ENTRY("%pD, %p", device_path_instance, device_path_instance_size); |
144 | return EFI_EXIT(efi_dp_get_next_instance(device_path_instance, | |
145 | device_path_instance_size)); | |
e70f8dfa LL |
146 | } |
147 | ||
3acef5da HS |
148 | /* |
149 | * Check if a device path contains more than one instance. | |
150 | * | |
151 | * This function implements the AppendDeviceNode service of the device path | |
152 | * utilities protocol. | |
153 | * | |
154 | * See the Unified Extensible Firmware Interface (UEFI) specification | |
155 | * for details. | |
156 | * | |
157 | * @device_path device path | |
158 | * @device_node device node | |
159 | * @return concatenated device path | |
160 | */ | |
e70f8dfa LL |
161 | static bool EFIAPI is_device_path_multi_instance( |
162 | const struct efi_device_path *device_path) | |
163 | { | |
3acef5da HS |
164 | EFI_ENTRY("%pD", device_path); |
165 | return EFI_EXIT(efi_dp_is_multi_instance(device_path)); | |
e70f8dfa LL |
166 | } |
167 | ||
211314c1 HS |
168 | /* |
169 | * Create device node. | |
170 | * | |
171 | * This function implements the CreateDeviceNode service of the device path | |
172 | * utilities protocol. | |
173 | * | |
174 | * See the Unified Extensible Firmware Interface (UEFI) specification | |
175 | * for details. | |
176 | * | |
177 | * @node_type node type | |
178 | * @node_sub_type node sub type | |
179 | * @node_length node length | |
180 | * @return device path node | |
181 | */ | |
e70f8dfa LL |
182 | static struct efi_device_path * EFIAPI create_device_node( |
183 | uint8_t node_type, uint8_t node_sub_type, uint16_t node_length) | |
184 | { | |
185 | EFI_ENTRY("%u, %u, %u", node_type, node_sub_type, node_length); | |
211314c1 HS |
186 | return EFI_EXIT(efi_dp_create_device_node(node_type, node_sub_type, |
187 | node_length)); | |
e70f8dfa LL |
188 | } |
189 | ||
190 | const struct efi_device_path_utilities_protocol efi_device_path_utilities = { | |
191 | .get_device_path_size = get_device_path_size, | |
192 | .duplicate_device_path = duplicate_device_path, | |
193 | .append_device_path = append_device_path, | |
194 | .append_device_node = append_device_node, | |
195 | .append_device_path_instance = append_device_path_instance, | |
196 | .get_next_device_path_instance = get_next_device_path_instance, | |
197 | .is_device_path_multi_instance = is_device_path_multi_instance, | |
198 | .create_device_node = create_device_node, | |
199 | }; |