OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
Uri.c
Go to the documentation of this file.
1
9
10STATIC EFI_DEVICE_PATH_PROTOCOL mEndDevicePath = {
11 END_DEVICE_PATH_TYPE,
12 END_ENTIRE_DEVICE_PATH_SUBTYPE,
13 {
14 END_DEVICE_PATH_LENGTH,
15 0
16 }
17};
18
19BOOLEAN
21 CHAR16 *Uri
22 )
23{
24 ASSERT (Uri != NULL);
25
26 return (OcStrniCmp (L"https://", Uri, L_STR_LEN (L"https://")) == 0);
27}
28
29EFI_DEVICE_PATH_PROTOCOL *
31 EFI_DEVICE_PATH_PROTOCOL *DevicePath
32 )
33{
34 EFI_DEVICE_PATH_PROTOCOL *Previous;
35 EFI_DEVICE_PATH_PROTOCOL *Node;
36
37 for ( Previous = NULL, Node = DevicePath
38 ; !IsDevicePathEnd (Node)
39 ; Node = NextDevicePathNode (Node))
40 {
41 Previous = Node;
42 }
43
44 if ( (Previous != NULL)
45 && (DevicePathType (Previous) == MESSAGING_DEVICE_PATH)
46 && (DevicePathSubType (Previous) == MSG_URI_DP)
47 )
48 {
49 return Previous;
50 }
51
52 return NULL;
53}
54
55//
56// See HttpBootCheckImageType and HttpUrlGetPath within it for how to get
57// the proper filename from URL: we would need to use HttpParseUrl, then
58// HttpUrlGetPath, then HttpUrlFreeParser.
59//
60// However, here are some examples:
61//
62// - https://myserver.com/images/OpenShell.efi
63// - https://myserver.com/download.php?a=1&b=2&filename=OpenShell.efi
64// - https://myserver.com/images/OpenShell.efi?secure=123
65//
66// Rather than parse the URL properly, we can handle all of the above
67// (one of which would not be handled by proper parsing of the filename
68// part, since the filename is in a parameter; even though this is a fudge,
69// as the parameter must come last to be fixed up) if we check if url ends
70// with the file ext, and replace it if so; otherwise check if the part
71// ending at '?' ends with ext and replace it if so.
72//
73STATIC
74EFI_STATUS
76 IN CHAR8 *Uri,
77 IN CHAR8 *FromExt,
78 IN CHAR8 *ToExt,
79 OUT CHAR8 **OtherUri,
80 IN BOOLEAN OnlySearchForFromExt
81 )
82{
83 CHAR8 *SearchUri;
84 UINTN UriLen;
85 UINTN OtherUriLen;
86 UINTN FromExtLen;
87 UINTN ToExtLen;
88 INTN SizeChange;
89 CHAR8 *ParamsStart;
90
91 ASSERT (FromExt != NULL);
92
93 if (!OnlySearchForFromExt) {
94 ASSERT (ToExt != NULL);
95 ASSERT (OtherUri != NULL);
96 *OtherUri = NULL;
97 }
98
99 UriLen = AsciiStrLen (Uri);
100 if (UriLen > MAX_INTN - 1) {
102 return EFI_INVALID_PARAMETER;
103 }
104
105 FromExtLen = AsciiStrLen (FromExt);
106 if (FromExtLen > MAX_INTN - 1) {
108 return EFI_INVALID_PARAMETER;
109 }
110
111 if (UriLen < FromExtLen) {
112 return EFI_NOT_FOUND;
113 }
114
115 if (OnlySearchForFromExt) {
116 SearchUri = Uri;
117 } else {
118 ToExtLen = AsciiStrLen (ToExt);
119 if (ToExtLen > MAX_INTN - 1) {
121 return EFI_INVALID_PARAMETER;
122 }
123
124 if (BaseOverflowSubSN ((INTN)ToExtLen, (INTN)FromExtLen, &SizeChange)) {
125 return EFI_INVALID_PARAMETER;
126 }
127
128 if (BaseOverflowAddSN ((INTN)UriLen, SizeChange, (INTN *)&OtherUriLen)) {
129 return EFI_INVALID_PARAMETER;
130 }
131
132 if (OtherUriLen > MAX_INTN - 1) {
134 return EFI_INVALID_PARAMETER;
135 }
136
137 *OtherUri = AllocatePool (MAX (UriLen, OtherUriLen) + 1);
138 if (*OtherUri == NULL) {
139 return EFI_OUT_OF_RESOURCES;
140 }
141
142 CopyMem (*OtherUri, Uri, UriLen + 1);
143 SearchUri = *OtherUri;
144 }
145
146 if (AsciiStrnCmp (&SearchUri[UriLen - FromExtLen], FromExt, FromExtLen) == 0) {
147 if (!OnlySearchForFromExt) {
148 CopyMem (&SearchUri[UriLen - FromExtLen], ToExt, ToExtLen + 1);
149 if (SizeChange < -1) {
150 ZeroMem (&SearchUri[UriLen + SizeChange + 1], -(SizeChange + 1));
151 }
152 }
153
154 return EFI_SUCCESS;
155 }
156
157 ParamsStart = AsciiStrStr (SearchUri, "?");
158 if ( (ParamsStart != NULL)
159 && (AsciiStrnCmp (ParamsStart - FromExtLen, FromExt, FromExtLen) == 0))
160 {
161 if (!OnlySearchForFromExt) {
162 CopyMem (ParamsStart + SizeChange, ParamsStart, &SearchUri[UriLen] - ParamsStart + 1);
163 CopyMem (ParamsStart - FromExtLen, ToExt, ToExtLen);
164 if (SizeChange < -1) {
165 ZeroMem (&SearchUri[UriLen + SizeChange + 1], -(SizeChange + 1));
166 }
167 }
168
169 return EFI_SUCCESS;
170 }
171
172 if (!OnlySearchForFromExt) {
173 FreePool (*OtherUri);
174 *OtherUri = NULL;
175 }
176
177 return EFI_NOT_FOUND;
178}
179
180//
181// We have the filename in the returned device path, so we can try to load the
182// matching file (.chunklist or .dmg, whichever one was not fetched), if we
183// we find the other.
184//
185EFI_STATUS
187 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
188 IN CHAR8 *FromExt,
189 IN CHAR8 *ToExt,
190 OUT CHAR8 **OtherUri,
191 IN BOOLEAN OnlySearchForFromExt
192 )
193{
194 EFI_DEVICE_PATH_PROTOCOL *Previous;
195 CHAR8 *Uri;
196
197 ASSERT (DevicePath != NULL);
198
199 Previous = GetUriNode (DevicePath);
200 if (Previous == NULL) {
201 return EFI_INVALID_PARAMETER;
202 }
203
204 Uri = (CHAR8 *)Previous + sizeof (EFI_DEVICE_PATH_PROTOCOL);
205
207 Uri,
208 FromExt,
209 ToExt,
210 OtherUri,
211 OnlySearchForFromExt
212 );
213}
214
215//
216// Determine whether file at URI has extension. This isn't only checking
217// the file part of the URI, instead it first checks the argument to the last
218// param, if there is one. This is a convenience to allow the 'download.php'
219// example shown at ExtractOtherUriFromUri.
220//
221BOOLEAN
223 IN CHAR8 *Uri,
224 IN CHAR8 *Ext
225 )
226{
227 return (!EFI_ERROR (ExtractOtherUriFromUri (Uri, Ext, NULL, NULL, TRUE)));
228}
229
230EFI_STATUS
232 EFI_DEVICE_PATH_PROTOCOL *DevicePath,
233 VOID *Uri,
234 OC_STRING_FORMAT StringFormat,
235 EFI_DEVICE_PATH_PROTOCOL **UriDevicePath
236 )
237{
238 UINTN Length;
239 UINTN UriSize;
240 VOID *OriginalUri;
241 EFI_DEVICE_PATH_PROTOCOL *Previous;
242 EFI_DEVICE_PATH_PROTOCOL *Node;
243 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
244
245 ASSERT (UriDevicePath != NULL);
246 *UriDevicePath = NULL;
247
248 TmpDevicePath = DuplicateDevicePath (DevicePath);
249 if (TmpDevicePath == NULL) {
250 return EFI_OUT_OF_RESOURCES;
251 }
252
253 //
254 // If last non-end node is a URI node, replace it with an end node.
255 //
256 Previous = GetUriNode (TmpDevicePath);
257 if (Previous == NULL) {
258 FreePool (TmpDevicePath);
259 return EFI_INVALID_PARAMETER;
260 }
261
262 CopyMem (Previous, &mEndDevicePath, sizeof (mEndDevicePath));
263
264 //
265 // Create replacement URI node with the input boot file URI.
266 //
267 if (StringFormat == OcStringFormatUnicode) {
268 OriginalUri = Uri;
269 UriSize = StrSize (Uri);
270 Uri = AllocatePool (UriSize * sizeof (CHAR8));
271 if (Uri == NULL) {
272 return EFI_OUT_OF_RESOURCES;
273 }
274
275 UnicodeStrToAsciiStrS (OriginalUri, Uri, UriSize);
276 } else {
277 OriginalUri = NULL;
278 UriSize = AsciiStrSize (Uri);
279 }
280
281 Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + UriSize;
282 Node = AllocatePool (Length);
283 if (Node == NULL) {
284 FreePool (TmpDevicePath);
285 return EFI_OUT_OF_RESOURCES;
286 }
287
288 Node->Type = MESSAGING_DEVICE_PATH;
289 Node->SubType = MSG_URI_DP;
290 SetDevicePathNodeLength (Node, Length);
291 CopyMem ((UINT8 *)Node + sizeof (EFI_DEVICE_PATH_PROTOCOL), Uri, UriSize);
292 if (OriginalUri != NULL) {
293 FreePool (Uri);
294 }
295
296 *UriDevicePath = AppendDevicePathNode (TmpDevicePath, Node);
297 FreePool (Node);
298 FreePool (TmpDevicePath);
299 if (*UriDevicePath == NULL) {
300 return EFI_OUT_OF_RESOURCES;
301 }
302
303 return EFI_SUCCESS;
304}
UINT64 Length
#define L_STR_LEN(String)
Definition OcStringLib.h:26
INTN EFIAPI OcStrniCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString, IN UINTN Length)
@ OcStringFormatUnicode
Definition OcStringLib.h:51
enum _OC_STRING_FORMAT OC_STRING_FORMAT
STATIC EFI_STATUS ExtractOtherUriFromUri(IN CHAR8 *Uri, IN CHAR8 *FromExt, IN CHAR8 *ToExt, OUT CHAR8 **OtherUri, IN BOOLEAN OnlySearchForFromExt)
Definition Uri.c:75
EFI_DEVICE_PATH_PROTOCOL * GetUriNode(EFI_DEVICE_PATH_PROTOCOL *DevicePath)
Definition Uri.c:30
EFI_STATUS HttpBootAddUri(EFI_DEVICE_PATH_PROTOCOL *DevicePath, VOID *Uri, OC_STRING_FORMAT StringFormat, EFI_DEVICE_PATH_PROTOCOL **UriDevicePath)
Definition Uri.c:231
BOOLEAN UriFileHasExtension(IN CHAR8 *Uri, IN CHAR8 *Ext)
Definition Uri.c:222
BOOLEAN HasHttpsUri(CHAR16 *Uri)
Definition Uri.c:20
STATIC EFI_DEVICE_PATH_PROTOCOL mEndDevicePath
Definition Uri.c:10
EFI_STATUS ExtractOtherUriFromDevicePath(IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, IN CHAR8 *FromExt, IN CHAR8 *ToExt, OUT CHAR8 **OtherUri, IN BOOLEAN OnlySearchForFromExt)
Definition Uri.c:186
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define ASSERT(x)
Definition coder.h:55
#define MAX(a, b)
Definition coder.h:59