]> git.proxmox.com Git - mirror_edk2.git/blob - StdLib/EfiSocketLib/DxeSupport.c
284fa9cdfebc79be91e1d4f8d4f062d84fe7db78
[mirror_edk2.git] / StdLib / EfiSocketLib / DxeSupport.c
1 /** @file
2 SocketDxe support routines
3
4 Copyright (c) 2011, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Socket.h"
16
17
18 /**
19 Creates a child handle and installs gEfiSocketProtocolGuid.
20
21 This routine creates a child handle for the socket driver and
22 installs the ::gEfiSocketProtocolGuid on that handle with a pointer
23 to the ::EFI_SOCKET_PROTOCOL structure address.
24
25 This routine is called by ::EslServiceGetProtocol in UseSocketDxe
26 when the socket application is linked with UseSocketDxe.
27
28 @param [in] pThis Address of the EFI_SERVICE_BINDING_PROTOCOL structure.
29 @param [in] pChildHandle Pointer to the handle of the child to create. If it is NULL,
30 then a new handle is created. If it is a pointer to an existing UEFI handle,
31 then the protocol is added to the existing UEFI handle.
32
33 @retval EFI_SUCCESS The protocol was added to ChildHandle.
34 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
35 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
36 the child
37 @retval other The child handle was not created
38
39 **/
40 EFI_STATUS
41 EFIAPI
42 EslDxeCreateChild (
43 IN EFI_SERVICE_BINDING_PROTOCOL * pThis,
44 IN OUT EFI_HANDLE * pChildHandle
45 )
46 {
47 ESL_SOCKET * pSocket;
48 EFI_STATUS Status;
49
50 DBG_ENTER ( );
51
52 //
53 // Create a socket structure
54 //
55 Status = EslSocketAllocate ( pChildHandle,
56 DEBUG_SOCKET,
57 &pSocket );
58
59 //
60 // Return the operation status
61 //
62 DBG_EXIT_STATUS ( Status );
63 return Status;
64 }
65
66
67 /**
68 Removes gEfiSocketProtocolGuid and destroys the child handle.
69
70 This routine uninstalls ::gEfiSocketProtocolGuid from the child handle
71 and destroys the child handle if necessary.
72
73 This routine is called from ???.
74
75 @param [in] pThis Address of the EFI_SERVICE_BINDING_PROTOCOL structure.
76 @param [in] ChildHandle Handle of the child to destroy
77
78 @retval EFI_SUCCESS The protocol was removed from ChildHandle.
79 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
80 @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
81 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
82 because its services are being used.
83 @retval other The child handle was not destroyed
84
85 **/
86 EFI_STATUS
87 EFIAPI
88 EslDxeDestroyChild (
89 IN EFI_SERVICE_BINDING_PROTOCOL * pThis,
90 IN EFI_HANDLE ChildHandle
91 )
92 {
93 ESL_LAYER * pLayer;
94 ESL_SOCKET * pSocket;
95 ESL_SOCKET * pSocketPrevious;
96 EFI_SOCKET_PROTOCOL * pSocketProtocol;
97 EFI_STATUS Status;
98 EFI_TPL TplPrevious;
99
100 DBG_ENTER ( );
101
102 //
103 // Locate the socket control structure
104 //
105 pLayer = &mEslLayer;
106 Status = gBS->OpenProtocol (
107 ChildHandle,
108 &gEfiSocketProtocolGuid,
109 (VOID **)&pSocketProtocol,
110 pLayer->ImageHandle,
111 NULL,
112 EFI_OPEN_PROTOCOL_GET_PROTOCOL
113 );
114 if ( !EFI_ERROR ( Status )) {
115 pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
116
117 //
118 // Synchronize with the socket layer
119 //
120 RAISE_TPL ( TplPrevious, TPL_SOCKETS );
121
122 //
123 // Walk the socket list
124 //
125 pSocketPrevious = pLayer->pSocketList;
126 if ( NULL != pSocketPrevious ) {
127 if ( pSocket == pSocketPrevious ) {
128 //
129 // Remove the socket from the head of the list
130 //
131 pLayer->pSocketList = pSocket->pNext;
132 }
133 else {
134 //
135 // Find the socket in the middle of the list
136 //
137 while (( NULL != pSocketPrevious )
138 && ( pSocket != pSocketPrevious->pNext )) {
139 //
140 // Set the next socket
141 //
142 pSocketPrevious = pSocketPrevious->pNext;
143 }
144 if ( NULL != pSocketPrevious ) {
145 //
146 // Remove the socket from the middle of the list
147 //
148 pSocketPrevious = pSocket->pNext;
149 }
150 }
151 }
152 else {
153 DEBUG (( DEBUG_ERROR | DEBUG_POOL,
154 "ERROR - Socket list is empty!\r\n" ));
155 }
156
157 //
158 // Release the socket layer synchronization
159 //
160 RESTORE_TPL ( TplPrevious );
161
162 //
163 // Determine if the socket was found
164 //
165 if ( NULL != pSocketPrevious ) {
166 pSocket->pNext = NULL;
167
168 //
169 // Remove the socket protocol
170 //
171 Status = gBS->UninstallMultipleProtocolInterfaces (
172 ChildHandle,
173 &gEfiSocketProtocolGuid,
174 &pSocket->SocketProtocol,
175 NULL );
176 if ( !EFI_ERROR ( Status )) {
177 DEBUG (( DEBUG_POOL | DEBUG_INFO,
178 "Removed: gEfiSocketProtocolGuid from 0x%08x\r\n",
179 ChildHandle ));
180
181 //
182 // Free the socket structure
183 //
184 Status = gBS->FreePool ( pSocket );
185 if ( !EFI_ERROR ( Status )) {
186 DEBUG (( DEBUG_POOL,
187 "0x%08x: Free pSocket, %d bytes\r\n",
188 pSocket,
189 sizeof ( *pSocket )));
190 }
191 else {
192 DEBUG (( DEBUG_ERROR | DEBUG_POOL,
193 "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",
194 pSocket,
195 Status ));
196 }
197 }
198 else {
199 DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,
200 "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",
201 ChildHandle,
202 Status ));
203 }
204 }
205 else {
206 DEBUG (( DEBUG_ERROR | DEBUG_INFO,
207 "ERROR - The socket was not in the socket list!\r\n" ));
208 Status = EFI_NOT_FOUND;
209 }
210 }
211 else {
212 DEBUG (( DEBUG_ERROR,
213 "ERROR - Failed to open socket protocol on 0x%08x, Status; %r\r\n",
214 ChildHandle,
215 Status ));
216 }
217
218 //
219 // Return the operation status
220 //
221 DBG_EXIT_STATUS ( Status );
222 return Status;
223 }
224
225
226 /**
227 Install the socket service
228
229 This routine installs the ::gEfiSocketServiceBindingProtocolGuid
230 on the SocketDxe image handle to announce the availability
231 of the socket layer to the rest of EFI.
232
233 SocketDxe's EntryPoint routine calls this routine to
234 make the socket layer available.
235
236 @param [in] pImageHandle Address of the image handle
237
238 @retval EFI_SUCCESS Service installed successfully
239 **/
240 EFI_STATUS
241 EFIAPI
242 EslDxeInstall (
243 IN EFI_HANDLE * pImageHandle
244 )
245 {
246 EFI_STATUS Status;
247
248 //
249 // Install the socket service binding protocol
250 //
251 Status = gBS->InstallMultipleProtocolInterfaces (
252 pImageHandle,
253 &gEfiSocketServiceBindingProtocolGuid,
254 mEslLayer.pServiceBinding,
255 NULL
256 );
257 if ( !EFI_ERROR ( Status )) {
258 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
259 "Installed: gEfiSocketServiceBindingProtocolGuid on 0x%08x\r\n",
260 *pImageHandle ));
261 }
262 else {
263 DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
264 "ERROR - InstallMultipleProtocolInterfaces failed, Status: %r\r\n",
265 Status ));
266 }
267
268 //
269 // Return the operation status
270 //
271 return Status;
272 }
273
274
275 /**
276 Uninstall the socket service
277
278 This routine removes the gEfiSocketServiceBindingProtocolGuid from
279 the SocketDxe image handle to notify EFI that the socket layer
280 is no longer available.
281
282 SocketDxe's DriverUnload routine calls this routine to remove the
283 socket layer.
284
285 @param [in] ImageHandle Handle for the image.
286
287 @retval EFI_SUCCESS Service installed successfully
288 **/
289 EFI_STATUS
290 EFIAPI
291 EslDxeUninstall (
292 IN EFI_HANDLE ImageHandle
293 )
294 {
295 EFI_STATUS Status;
296
297 //
298 // Install the socket service binding protocol
299 //
300 Status = gBS->UninstallMultipleProtocolInterfaces (
301 ImageHandle,
302 &gEfiSocketServiceBindingProtocolGuid,
303 mEslLayer.pServiceBinding,
304 NULL
305 );
306 if ( !EFI_ERROR ( Status )) {
307 DEBUG (( DEBUG_POOL | DEBUG_INIT,
308 "Removed: gEfiSocketServiceBindingProtocolGuid from 0x%08x\r\n",
309 ImageHandle ));
310 }
311 else {
312 DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
313 "ERROR - Failed to remove gEfiSocketServiceBindingProtocolGuid from 0x%08x, Status: %r\r\n",
314 ImageHandle,
315 Status ));
316 }
317
318 //
319 // Return the operation status
320 //
321 return Status;
322 }