2 * EfiLib/gnuefi-helper.c
3 * GNU-EFI support functions
5 * Borrowed from the TianoCore EDK II, with modifications by Rod Smith
7 * Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
8 * This program and the accompanying materials
9 * are licensed and made available under the terms and conditions of the BSD License
10 * which accompanies this distribution. The full text of the license may be found at
11 * http://opensource.org/licenses/bsd-license.php
13 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "gnuefi-helper.h"
19 #include "DevicePathUtilities.h"
20 #include "refit_call_wrapper.h"
21 #include "LegacyBios.h"
23 EFI_GUID gEfiDevicePathUtilitiesProtocolGuid
= { 0x09576E91, 0x6D3F, 0x11D2, { 0x8E, 0x39, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B }};
24 EFI_GUID gEfiGlobalVariableGuid
= { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }};
25 EFI_GUID gEfiLegacyBiosProtocolGuid
= { 0xdb9a1e3d, 0x45cb, 0x4abb, { 0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d }};
28 Convert a Null-terminated Unicode string to a Null-terminated
29 ASCII string and returns the ASCII string.
31 This function converts the content of the Unicode string Source
32 to the ASCII string Destination by copying the lower 8 bits of
33 each Unicode character. It returns Destination. The function terminates
34 the ASCII string Destination by appending a Null-terminator character
35 at the end. The caller is responsible to make sure Destination points
36 to a buffer with size equal or greater than (StrLen (Source) + 1) in bytes.
38 If Destination is NULL, then ASSERT().
39 If Source is NULL, then ASSERT().
40 If Source is not aligned on a 16-bit boundary, then ASSERT().
41 If Source and Destination overlap, then ASSERT().
43 If any Unicode characters in Source contain non-zero value in
44 the upper 8 bits, then ASSERT().
46 If PcdMaximumUnicodeStringLength is not zero, and Source contains
47 more than PcdMaximumUnicodeStringLength Unicode characters not including
48 the Null-terminator, then ASSERT().
50 If PcdMaximumAsciiStringLength is not zero, and Source contains more
51 than PcdMaximumAsciiStringLength Unicode characters not including the
52 Null-terminator, then ASSERT().
54 @param Source Pointer to a Null-terminated Unicode string.
55 @param Destination Pointer to a Null-terminated ASCII string.
61 UnicodeStrToAsciiStr (
63 OUT CHAR8
*Destination
66 ASSERT (Destination
!= NULL
);
67 ASSERT (Source
!= NULL
);
68 ASSERT (((UINTN
) Source
& 0x01) == 0);
71 // Source and Destination should not overlap
73 ASSERT ((UINTN
) ((CHAR16
*) Destination
- Source
) > StrLen (Source
));
74 ASSERT ((UINTN
) ((CHAR8
*) Source
- Destination
) > StrLen (Source
));
77 // // If PcdMaximumUnicodeStringLength is not zero,
78 // // length of Source should not more than PcdMaximumUnicodeStringLength
80 // if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) {
81 // ASSERT (StrLen (Source) < PcdGet32 (PcdMaximumUnicodeStringLength));
84 while (*Source
!= '\0') {
86 // If any Unicode characters in Source contain
87 // non-zero value in the upper 8 bits, then ASSERT().
89 ASSERT (*Source
< 0x100);
90 *(Destination
++) = (CHAR8
) *(Source
++);
99 Returns the length of a Null-terminated ASCII string.
101 This function returns the number of ASCII characters in the Null-terminated
102 ASCII string specified by String.
104 If String is NULL, then ASSERT().
105 If PcdMaximumAsciiStringLength is not zero and String contains more than
106 PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator,
109 @param String Pointer to a Null-terminated ASCII string.
111 @return The length of String.
116 IN CONST CHAR8
*String
121 ASSERT (String
!= NULL
);
123 for (Length
= 0; *String
!= '\0'; String
++, Length
++) {
125 // // If PcdMaximumUnicodeStringLength is not zero,
126 // // length should not more than PcdMaximumUnicodeStringLength
128 // if (PcdGet32 (PcdMaximumAsciiStringLength) != 0) {
129 // ASSERT (Length < PcdGet32 (PcdMaximumAsciiStringLength));
136 Determine whether a given device path is valid.
137 If DevicePath is NULL, then ASSERT().
139 @param DevicePath A pointer to a device path data structure.
140 @param MaxSize The maximum size of the device path data structure.
142 @retval TRUE DevicePath is valid.
143 @retval FALSE The length of any node node in the DevicePath is less
144 than sizeof (EFI_DEVICE_PATH_PROTOCOL).
145 @retval FALSE If MaxSize is not zero, the size of the DevicePath
147 @retval FALSE If PcdMaximumDevicePathNodeCount is not zero, the node
148 count of the DevicePath exceeds PcdMaximumDevicePathNodeCount.
153 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
,
161 ASSERT (DevicePath
!= NULL
);
163 for (Count
= 0, Size
= 0; !IsDevicePathEnd (DevicePath
); DevicePath
= NextDevicePathNode (DevicePath
)) {
164 NodeLength
= DevicePathNodeLength (DevicePath
);
165 if (NodeLength
< sizeof (EFI_DEVICE_PATH_PROTOCOL
)) {
171 if (Size
+ END_DEVICE_PATH_LENGTH
> MaxSize
) {
176 // if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) {
178 // if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) {
185 // Only return TRUE when the End Device Path node is valid.
187 return (BOOLEAN
) (DevicePathNodeLength (DevicePath
) == END_DEVICE_PATH_LENGTH
);
191 Returns the size of a device path in bytes.
193 This function returns the size, in bytes, of the device path data structure
194 specified by DevicePath including the end of device path node.
195 If DevicePath is NULL or invalid, then 0 is returned.
197 @param DevicePath A pointer to a device path data structure.
199 @retval 0 If DevicePath is NULL or invalid.
200 @retval Others The size of a device path in bytes.
206 IN CONST EFI_DEVICE_PATH_PROTOCOL
*DevicePath
209 CONST EFI_DEVICE_PATH_PROTOCOL
*Start
;
211 if (DevicePath
== NULL
) {
215 if (!IsDevicePathValid (DevicePath
, 0)) {
220 // Search for the end of the device path structure
223 while (!IsDevicePathEnd (DevicePath
)) {
224 DevicePath
= NextDevicePathNode (DevicePath
);
228 // Compute the size and add back in the size of the end device path structure
230 return ((UINTN
) DevicePath
- (UINTN
) Start
) + DevicePathNodeLength (DevicePath
);
234 Creates a copy of the current device path instance and returns a pointer to the next device path
237 This function creates a copy of the current device path instance. It also updates
238 DevicePath to point to the next device path instance in the device path (or NULL
239 if no more) and updates Size to hold the size of the device path instance copy.
240 If DevicePath is NULL, then NULL is returned.
241 If DevicePath points to a invalid device path, then NULL is returned.
242 If there is not enough memory to allocate space for the new device path, then
244 The memory is allocated from EFI boot services memory. It is the responsibility
245 of the caller to free the memory allocated.
246 If Size is NULL, then ASSERT().
248 @param DevicePath On input, this holds the pointer to the current
249 device path instance. On output, this holds
250 the pointer to the next device path instance
251 or NULL if there are no more device path
252 instances in the device path pointer to a
253 device path data structure.
254 @param Size On output, this holds the size of the device
255 path instance, in bytes or zero, if DevicePath
258 @return A pointer to the current device path instance.
261 EFI_DEVICE_PATH_PROTOCOL
*
263 GetNextDevicePathInstance (
264 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
268 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
269 EFI_DEVICE_PATH_PROTOCOL
*ReturnValue
;
272 ASSERT (Size
!= NULL
);
274 if (DevicePath
== NULL
|| *DevicePath
== NULL
) {
279 if (!IsDevicePathValid (*DevicePath
, 0)) {
284 // Find the end of the device path instance
286 DevPath
= *DevicePath
;
287 while (!IsDevicePathEndType (DevPath
)) {
288 DevPath
= NextDevicePathNode (DevPath
);
292 // Compute the size of the device path instance
294 *Size
= ((UINTN
) DevPath
- (UINTN
) (*DevicePath
)) + sizeof (EFI_DEVICE_PATH_PROTOCOL
);
297 // Make a copy and return the device path instance
299 Temp
= DevPath
->SubType
;
300 DevPath
->SubType
= END_ENTIRE_DEVICE_PATH_SUBTYPE
;
301 ReturnValue
= DuplicateDevicePath (*DevicePath
);
302 DevPath
->SubType
= Temp
;
305 // If DevPath is the end of an entire device path, then another instance
306 // does not follow, so *DevicePath is set to NULL.
308 if (DevicePathSubType (DevPath
) == END_ENTIRE_DEVICE_PATH_SUBTYPE
) {
311 *DevicePath
= NextDevicePathNode (DevPath
);