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