]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IScsiDxe/IScsiDns.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiDns.c
1 /** @file
2 Perform DNS resolution based on UEFI DNS protocols.
3
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "IScsiImpl.h"
10
11 /**
12 Notify the callback function when an event is triggered.
13
14 @param[in] Event The triggered event.
15 @param[in] Context The opaque parameter to the function.
16
17 **/
18 VOID
19 EFIAPI
20 IScsiCommonNotify (
21 IN EFI_EVENT Event,
22 IN VOID *Context
23 )
24 {
25 *((BOOLEAN *)Context) = TRUE;
26 }
27
28 /**
29 Retrieve the host address using the EFI_DNS4_PROTOCOL.
30
31 @param[in] Image The handle of the driver image.
32 @param[in] Controller The handle of the controller.
33 @param[in, out] NvData The Session config data structure.
34
35 @retval EFI_SUCCESS Operation succeeded.
36 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
37 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
38 @retval Others Other errors as indicated.
39
40 **/
41 EFI_STATUS
42 IScsiDns4 (
43 IN EFI_HANDLE Image,
44 IN EFI_HANDLE Controller,
45 IN OUT ISCSI_SESSION_CONFIG_NVDATA *NvData
46 )
47 {
48 EFI_STATUS Status;
49 EFI_DNS4_PROTOCOL *Dns4;
50 EFI_DNS4_CONFIG_DATA Dns4CfgData;
51 EFI_DNS4_COMPLETION_TOKEN Token;
52 BOOLEAN IsDone;
53 EFI_HANDLE Dns4Handle;
54 EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
55 EFI_IPv4_ADDRESS *DnsServerList;
56 UINTN DnsServerListCount;
57 UINTN DataSize;
58 CHAR16 *HostName;
59
60 DnsServerList = NULL;
61 DnsServerListCount = 0;
62 Dns4Handle = NULL;
63 Dns4 = NULL;
64 ZeroMem (&Token, sizeof (EFI_DNS4_COMPLETION_TOKEN));
65
66 //
67 // Get DNS server list from EFI IPv4 Configuration II protocol.
68 //
69 Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **)&Ip4Config2);
70 if (!EFI_ERROR (Status)) {
71 //
72 // Get the required size.
73 //
74 DataSize = 0;
75 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, NULL);
76 if (Status == EFI_BUFFER_TOO_SMALL) {
77 DnsServerList = AllocatePool (DataSize);
78 if (DnsServerList == NULL) {
79 return EFI_OUT_OF_RESOURCES;
80 }
81
82 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, DnsServerList);
83 if (EFI_ERROR (Status)) {
84 FreePool (DnsServerList);
85 DnsServerList = NULL;
86 } else {
87 DnsServerListCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
88 }
89 }
90 }
91
92 //
93 // Create a DNS child instance and get the protocol.
94 //
95 Status = NetLibCreateServiceChild (
96 Controller,
97 Image,
98 &gEfiDns4ServiceBindingProtocolGuid,
99 &Dns4Handle
100 );
101 if (EFI_ERROR (Status)) {
102 goto Exit;
103 }
104
105 Status = gBS->OpenProtocol (
106 Dns4Handle,
107 &gEfiDns4ProtocolGuid,
108 (VOID **)&Dns4,
109 Image,
110 Controller,
111 EFI_OPEN_PROTOCOL_BY_DRIVER
112 );
113 if (EFI_ERROR (Status)) {
114 goto Exit;
115 }
116
117 //
118 // Configure DNS4 instance for the DNS server address and protocol.
119 //
120 ZeroMem (&Dns4CfgData, sizeof (Dns4CfgData));
121 Dns4CfgData.DnsServerListCount = DnsServerListCount;
122 Dns4CfgData.DnsServerList = DnsServerList;
123 Dns4CfgData.EnableDnsCache = TRUE;
124 IP4_COPY_ADDRESS (&Dns4CfgData.StationIp, &NvData->LocalIp);
125 IP4_COPY_ADDRESS (&Dns4CfgData.SubnetMask, &NvData->SubnetMask);
126 Dns4CfgData.Protocol = EFI_IP_PROTO_UDP;
127 Status = Dns4->Configure (
128 Dns4,
129 &Dns4CfgData
130 );
131 if (EFI_ERROR (Status)) {
132 goto Exit;
133 }
134
135 //
136 // Create event to set the is done flag when name resolution is finished.
137 //
138 ZeroMem (&Token, sizeof (Token));
139 Status = gBS->CreateEvent (
140 EVT_NOTIFY_SIGNAL,
141 TPL_NOTIFY,
142 IScsiCommonNotify,
143 &IsDone,
144 &Token.Event
145 );
146 if (EFI_ERROR (Status)) {
147 goto Exit;
148 }
149
150 //
151 // Start asynchronous name resolution.
152 //
153 Token.Status = EFI_NOT_READY;
154 IsDone = FALSE;
155
156 HostName = (CHAR16 *)AllocateZeroPool (ISCSI_NAME_MAX_SIZE);
157 if (HostName == NULL) {
158 return EFI_OUT_OF_RESOURCES;
159 }
160
161 AsciiStrToUnicodeStrS (
162 NvData->TargetUrl,
163 HostName,
164 ISCSI_NAME_MAX_SIZE
165 );
166
167 Status = Dns4->HostNameToIp (Dns4, HostName, &Token);
168 if (EFI_ERROR (Status)) {
169 goto Exit;
170 }
171
172 while (!IsDone) {
173 Dns4->Poll (Dns4);
174 }
175
176 //
177 // Name resolution is done, check result.
178 //
179 Status = Token.Status;
180 if (!EFI_ERROR (Status)) {
181 if (Token.RspData.H2AData == NULL) {
182 Status = EFI_DEVICE_ERROR;
183 goto Exit;
184 }
185
186 if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) {
187 Status = EFI_DEVICE_ERROR;
188 goto Exit;
189 }
190
191 //
192 // We just return the first IP address from DNS protocol.
193 //
194 IP4_COPY_ADDRESS (&NvData->TargetIp.v4, Token.RspData.H2AData->IpList);
195 Status = EFI_SUCCESS;
196 }
197
198 Exit:
199
200 if (Token.Event != NULL) {
201 gBS->CloseEvent (Token.Event);
202 }
203
204 if (Token.RspData.H2AData != NULL) {
205 if (Token.RspData.H2AData->IpList != NULL) {
206 FreePool (Token.RspData.H2AData->IpList);
207 }
208
209 FreePool (Token.RspData.H2AData);
210 }
211
212 if (Dns4 != NULL) {
213 Dns4->Configure (Dns4, NULL);
214
215 gBS->CloseProtocol (
216 Dns4Handle,
217 &gEfiDns4ProtocolGuid,
218 Image,
219 Controller
220 );
221 }
222
223 if (Dns4Handle != NULL) {
224 NetLibDestroyServiceChild (
225 Controller,
226 Image,
227 &gEfiDns4ServiceBindingProtocolGuid,
228 Dns4Handle
229 );
230 }
231
232 return Status;
233 }
234
235 /**
236 Retrieve the host address using the EFI_DNS6_PROTOCOL.
237
238 @param[in] Image The handle of the driver image.
239 @param[in] Controller The handle of the controller.
240 @param[in, out] NvData The Session config data structure.
241
242 @retval EFI_SUCCESS Operation succeeded.
243 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
244 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
245 @retval Others Other errors as indicated.
246
247 **/
248 EFI_STATUS
249 IScsiDns6 (
250 IN EFI_HANDLE Image,
251 IN EFI_HANDLE Controller,
252 IN OUT ISCSI_SESSION_CONFIG_NVDATA *NvData
253 )
254 {
255 EFI_STATUS Status;
256 EFI_DNS6_PROTOCOL *Dns6;
257 EFI_DNS6_CONFIG_DATA Dns6ConfigData;
258 EFI_DNS6_COMPLETION_TOKEN Token;
259 EFI_HANDLE Dns6Handle;
260 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
261 EFI_IPv6_ADDRESS *DnsServerList;
262 UINTN DnsServerListCount;
263 UINTN DataSize;
264 BOOLEAN IsDone;
265 CHAR16 *HostName;
266
267 DnsServerList = NULL;
268 DnsServerListCount = 0;
269 Dns6 = NULL;
270 Dns6Handle = NULL;
271 ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));
272
273 //
274 // Get DNS server list from EFI IPv6 Configuration protocol.
275 //
276 Status = gBS->HandleProtocol (Controller, &gEfiIp6ConfigProtocolGuid, (VOID **)&Ip6Config);
277 if (!EFI_ERROR (Status)) {
278 //
279 // Get the required size.
280 //
281 DataSize = 0;
282 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);
283 if (Status == EFI_BUFFER_TOO_SMALL) {
284 DnsServerList = AllocatePool (DataSize);
285 if (DnsServerList == NULL) {
286 return EFI_OUT_OF_RESOURCES;
287 }
288
289 Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);
290 if (EFI_ERROR (Status)) {
291 FreePool (DnsServerList);
292 DnsServerList = NULL;
293 } else {
294 DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
295 }
296 }
297 }
298
299 //
300 // Create a DNSv6 child instance and get the protocol.
301 //
302 Status = NetLibCreateServiceChild (
303 Controller,
304 Image,
305 &gEfiDns6ServiceBindingProtocolGuid,
306 &Dns6Handle
307 );
308 if (EFI_ERROR (Status)) {
309 goto Exit;
310 }
311
312 Status = gBS->OpenProtocol (
313 Dns6Handle,
314 &gEfiDns6ProtocolGuid,
315 (VOID **)&Dns6,
316 Image,
317 Controller,
318 EFI_OPEN_PROTOCOL_BY_DRIVER
319 );
320 if (EFI_ERROR (Status)) {
321 goto Exit;
322 }
323
324 //
325 // Configure DNS6 instance for the DNS server address and protocol.
326 //
327 ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));
328 Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;
329 Dns6ConfigData.DnsServerList = DnsServerList;
330 Dns6ConfigData.EnableDnsCache = TRUE;
331 Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;
332 Status = Dns6->Configure (
333 Dns6,
334 &Dns6ConfigData
335 );
336 if (EFI_ERROR (Status)) {
337 goto Exit;
338 }
339
340 Token.Status = EFI_NOT_READY;
341 IsDone = FALSE;
342 //
343 // Create event to set the IsDone flag when name resolution is finished.
344 //
345 Status = gBS->CreateEvent (
346 EVT_NOTIFY_SIGNAL,
347 TPL_NOTIFY,
348 IScsiCommonNotify,
349 &IsDone,
350 &Token.Event
351 );
352 if (EFI_ERROR (Status)) {
353 goto Exit;
354 }
355
356 //
357 // Start asynchronous name resolution.
358 //
359 HostName = (CHAR16 *)AllocateZeroPool (ISCSI_NAME_MAX_SIZE);
360 if (HostName == NULL) {
361 return EFI_OUT_OF_RESOURCES;
362 }
363
364 AsciiStrToUnicodeStrS (
365 NvData->TargetUrl,
366 HostName,
367 ISCSI_NAME_MAX_SIZE
368 );
369 Status = Dns6->HostNameToIp (Dns6, HostName, &Token);
370 if (EFI_ERROR (Status)) {
371 goto Exit;
372 }
373
374 while (!IsDone) {
375 Dns6->Poll (Dns6);
376 }
377
378 //
379 // Name resolution is done, check result.
380 //
381 Status = Token.Status;
382 if (!EFI_ERROR (Status)) {
383 if (Token.RspData.H2AData == NULL) {
384 Status = EFI_DEVICE_ERROR;
385 goto Exit;
386 }
387
388 if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) {
389 Status = EFI_DEVICE_ERROR;
390 goto Exit;
391 }
392
393 //
394 // We just return the first IPv6 address from DNS protocol.
395 //
396 IP6_COPY_ADDRESS (&NvData->TargetIp.v6, Token.RspData.H2AData->IpList);
397 Status = EFI_SUCCESS;
398 }
399
400 Exit:
401
402 if (Token.Event != NULL) {
403 gBS->CloseEvent (Token.Event);
404 }
405
406 if (Token.RspData.H2AData != NULL) {
407 if (Token.RspData.H2AData->IpList != NULL) {
408 FreePool (Token.RspData.H2AData->IpList);
409 }
410
411 FreePool (Token.RspData.H2AData);
412 }
413
414 if (Dns6 != NULL) {
415 Dns6->Configure (Dns6, NULL);
416
417 gBS->CloseProtocol (
418 Dns6Handle,
419 &gEfiDns6ProtocolGuid,
420 Image,
421 Controller
422 );
423 }
424
425 if (Dns6Handle != NULL) {
426 NetLibDestroyServiceChild (
427 Controller,
428 Image,
429 &gEfiDns6ServiceBindingProtocolGuid,
430 Dns6Handle
431 );
432 }
433
434 return Status;
435 }