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