2 * EfiLib/gnuefi-helper.c
3 * GNU-EFI support functions
5 * Copyright (c) 2014 Roderick W. Smith
6 * With extensive borrowing from other sources (mostly Tianocore)
8 * This software is licensed under the terms of the GNU GPLv3,
9 * a copy of which should come with this file.
13 #include "gnuefi-helper.h"
14 #include "DevicePathUtilities.h"
15 #include "refit_call_wrapper.h"
16 #include "LegacyBios.h"
18 EFI_GUID gEfiDevicePathUtilitiesProtocolGuid
= { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
19 EFI_GUID gEfiGlobalVariableGuid
= { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }};
20 EFI_GUID gEfiLegacyBiosProtocolGuid
= { 0xdb9a1e3d, 0x45cb, 0x4abb, { 0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d }};
23 Convert a Null-terminated Unicode string to a Null-terminated
24 ASCII string and returns the ASCII string.
26 This function converts the content of the Unicode string Source
27 to the ASCII string Destination by copying the lower 8 bits of
28 each Unicode character. It returns Destination. The function terminates
29 the ASCII string Destination by appending a Null-terminator character
30 at the end. The caller is responsible to make sure Destination points
31 to a buffer with size equal or greater than (StrLen (Source) + 1) in bytes.
33 If Destination is NULL, then ASSERT().
34 If Source is NULL, then ASSERT().
35 If Source is not aligned on a 16-bit boundary, then ASSERT().
36 If Source and Destination overlap, then ASSERT().
38 If any Unicode characters in Source contain non-zero value in
39 the upper 8 bits, then ASSERT().
41 If PcdMaximumUnicodeStringLength is not zero, and Source contains
42 more than PcdMaximumUnicodeStringLength Unicode characters not including
43 the Null-terminator, then ASSERT().
45 If PcdMaximumAsciiStringLength is not zero, and Source contains more
46 than PcdMaximumAsciiStringLength Unicode characters not including the
47 Null-terminator, then ASSERT().
49 @param Source Pointer to a Null-terminated Unicode string.
50 @param Destination Pointer to a Null-terminated ASCII string.
56 UnicodeStrToAsciiStr (
58 OUT CHAR8
*Destination
61 ASSERT (Destination
!= NULL
);
62 ASSERT (Source
!= NULL
);
63 ASSERT (((UINTN
) Source
& 0x01) == 0);
66 // Source and Destination should not overlap
68 ASSERT ((UINTN
) ((CHAR16
*) Destination
- Source
) > StrLen (Source
));
69 ASSERT ((UINTN
) ((CHAR8
*) Source
- Destination
) > StrLen (Source
));
72 // // If PcdMaximumUnicodeStringLength is not zero,
73 // // length of Source should not more than PcdMaximumUnicodeStringLength
75 // if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) {
76 // ASSERT (StrLen (Source) < PcdGet32 (PcdMaximumUnicodeStringLength));
79 while (*Source
!= '\0') {
81 // If any Unicode characters in Source contain
82 // non-zero value in the upper 8 bits, then ASSERT().
84 ASSERT (*Source
< 0x100);
85 *(Destination
++) = (CHAR8
) *(Source
++);
94 Returns the length of a Null-terminated ASCII string.
96 This function returns the number of ASCII characters in the Null-terminated
97 ASCII string specified by String.
99 If String is NULL, then ASSERT().
100 If PcdMaximumAsciiStringLength is not zero and String contains more than
101 PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator,
104 @param String Pointer to a Null-terminated ASCII string.
106 @return The length of String.
111 IN CONST CHAR8
*String
116 ASSERT (String
!= NULL
);
118 for (Length
= 0; *String
!= '\0'; String
++, Length
++) {
120 // // If PcdMaximumUnicodeStringLength is not zero,
121 // // length should not more than PcdMaximumUnicodeStringLength
123 // if (PcdGet32 (PcdMaximumAsciiStringLength) != 0) {
124 // ASSERT (Length < PcdGet32 (PcdMaximumAsciiStringLength));
131 Determine whether a given device path is valid.
132 If DevicePath is NULL, then ASSERT().
134 @param DevicePath A pointer to a device path data structure.
135 @param MaxSize The maximum size of the device path data structure.
137 @retval TRUE DevicePath is valid.
138 @retval FALSE The length of any node node in the DevicePath is less
139 than sizeof (EFI_DEVICE_PATH_PROTOCOL).
140 @retval FALSE If MaxSize is not zero, the size of the DevicePath
142 @retval FALSE If PcdMaximumDevicePathNodeCount is not zero, the node
143 count of the DevicePath exceeds PcdMaximumDevicePathNodeCount.
148 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
156 ASSERT (DevicePath
!= NULL
);
158 for (Count
= 0, Size
= 0; !IsDevicePathEnd (DevicePath
); DevicePath
= NextDevicePathNode (DevicePath
)) {
159 NodeLength
= DevicePathNodeLength (DevicePath
);
160 if (NodeLength
< sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
166 if (Size
+ END_DEVICE_PATH_LENGTH
> MaxSize
) {
171 // if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) {
173 // if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) {
180 // Only return TRUE when the End Device Path node is valid.
182 return (BOOLEAN
) (DevicePathNodeLength (DevicePath
) == END_DEVICE_PATH_LENGTH
);
186 Returns the size of a device path in bytes.
188 This function returns the size, in bytes, of the device path data structure
189 specified by DevicePath including the end of device path node.
190 If DevicePath is NULL or invalid, then 0 is returned.
192 @param DevicePath A pointer to a device path data structure.
194 @retval 0 If DevicePath is NULL or invalid.
195 @retval Others The size of a device path in bytes.
201 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
204 CONST EFI_DEVICE_PATH_PROTOCOL
*Start
;
206 if (DevicePath
== NULL
) {
210 if (!IsDevicePathValid (DevicePath
, 0)) {
215 // Search for the end of the device path structure
218 while (!IsDevicePathEnd (DevicePath
)) {
219 DevicePath
= NextDevicePathNode (DevicePath
);
223 // Compute the size and add back in the size of the end device path structure
225 return ((UINTN
) DevicePath
- (UINTN
) Start
) + DevicePathNodeLength (DevicePath
);
229 Creates a copy of the current device path instance and returns a pointer to the next device path
232 This function creates a copy of the current device path instance. It also updates
233 DevicePath to point to the next device path instance in the device path (or NULL
234 if no more) and updates Size to hold the size of the device path instance copy.
235 If DevicePath is NULL, then NULL is returned.
236 If DevicePath points to a invalid device path, then NULL is returned.
237 If there is not enough memory to allocate space for the new device path, then
239 The memory is allocated from EFI boot services memory. It is the responsibility
240 of the caller to free the memory allocated.
241 If Size is NULL, then ASSERT().
243 @param DevicePath On input, this holds the pointer to the current
244 device path instance. On output, this holds
245 the pointer to the next device path instance
246 or NULL if there are no more device path
247 instances in the device path pointer to a
248 device path data structure.
249 @param Size On output, this holds the size of the device
250 path instance, in bytes or zero, if DevicePath
253 @return A pointer to the current device path instance.
256 EFI_DEVICE_PATH_PROTOCOL
*
258 GetNextDevicePathInstance (
259 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
263 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
264 EFI_DEVICE_PATH_PROTOCOL
*ReturnValue
;
267 ASSERT (Size
!= NULL
);
269 if (DevicePath
== NULL
|| *DevicePath
== NULL
) {
274 if (!IsDevicePathValid (*DevicePath
, 0)) {
279 // Find the end of the device path instance
281 DevPath
= *DevicePath
;
282 while (!IsDevicePathEndType (DevPath
)) {
283 DevPath
= NextDevicePathNode (DevPath
);
287 // Compute the size of the device path instance
289 *Size
= ((UINTN
) DevPath
- (UINTN
) (*DevicePath
)) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
292 // Make a copy and return the device path instance
294 Temp
= DevPath
->SubType
;
295 DevPath
->SubType
= END_ENTIRE_DEVICE_PATH_SUBTYPE
;
296 ReturnValue
= DuplicateDevicePath (*DevicePath
);
297 DevPath
->SubType
= Temp
;
300 // If DevPath is the end of an entire device path, then another instance
301 // does not follow, so *DevicePath is set to NULL.
303 if (DevicePathSubType (DevPath
) == END_ENTIRE_DEVICE_PATH_SUBTYPE
) {
306 *DevicePath
= NextDevicePathNode (DevPath
);