1 /** @file
2   Implement the connection to the socket driver
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 <Uefi.h>
16 
17 #include <Library/DebugLib.h>
18 #include <Library/UefiBootServicesTableLib.h>
19 #include <Library/UefiLib.h>
20 
21 #include <Protocol/EfiSocket.h>
22 #include <Protocol/ServiceBinding.h>
23 
24 
25 /**
26   Free the socket resources
27 
28   This releases the socket resources allocated by calling
29   EslServiceGetProtocol.
30 
31   This routine is called from the ::close routine in BsdSocketLib
32   to release the socket resources.
33 
34   @param [in] pSocketProtocol   Address of an ::EFI_SOCKET_PROTOCOL
35                                 structure
36 
37   @return       Value for ::errno, zero (0) indicates success.
38 
39  **/
40 int
EslServiceFreeProtocol(IN EFI_SOCKET_PROTOCOL * pSocketProtocol)41 EslServiceFreeProtocol (
42   IN EFI_SOCKET_PROTOCOL * pSocketProtocol
43   )
44 {
45   EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;
46   int RetVal;
47   EFI_STATUS Status;
48 
49   //
50   //  Assume success
51   //
52   RetVal = 0;
53 
54   //
55   //  Locate the socket protocol
56   //
57   Status = gBS->LocateProtocol ( &gEfiSocketServiceBindingProtocolGuid,
58                                  NULL,
59                                  (VOID **) &pServiceBinding );
60   if ( !EFI_ERROR ( Status )) {
61     //
62     //  Release the handle
63     //
64     Status = pServiceBinding->DestroyChild ( pServiceBinding,
65                                              pSocketProtocol->SocketHandle );
66   }
67   if ( EFI_ERROR ( Status )) {
68     RetVal = EIO;
69   }
70 
71   //
72   //  Return the operation status
73   //
74   return RetVal;
75 }
76 
77 
78 /**
79   Connect to the EFI socket library
80 
81   This routine establishes a connection to the socket driver
82   and returns the API (::EFI_SOCKET_PROTOCOL address) to the
83   socket file system layer in BsdSocketLib.  This routine looks for
84   the gEfiSocketServiceBindingProtocolGuid to locate the socket
85   driver.  This routine then creates a child handle and locates
86   the gEfiSocketProtocolGuid protocol on that handle to get the
87   ::EFI_SOCKET_PROTOCOL structure address.
88 
89   This routine is called from the ::socket routine in BsdSocketLib
90   to create the data structure and initialize the API for a socket.
91   Note that this implementation is only used by socket applications
92   that link directly to UseSocketDxe.
93 
94   @param [in] ppSocketProtocol  Address to receive the ::EFI_SOCKET_PROTOCOL
95                                 structure address
96 
97   @return       Value for ::errno, zero (0) indicates success.
98 
99  **/
100 int
EslServiceGetProtocol(IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol)101 EslServiceGetProtocol (
102   IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol
103   )
104 {
105   EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;
106   int RetVal;
107   EFI_HANDLE SocketHandle;
108   EFI_STATUS Status;
109 
110   //
111   //  Locate the socket protocol
112   //
113   Status = gBS->LocateProtocol ( &gEfiSocketServiceBindingProtocolGuid,
114                                  NULL,
115                                  (VOID **)&pServiceBinding );
116   if ( !EFI_ERROR ( Status )) {
117     //
118     //  Create a new socket
119     //
120     SocketHandle = NULL;
121     Status = pServiceBinding->CreateChild ( pServiceBinding,
122                                             &SocketHandle );
123     if ( !EFI_ERROR ( Status )) {
124       //
125       //  Get the socket protocol
126       //
127       Status = gBS->OpenProtocol ( SocketHandle,
128                                    &gEfiSocketProtocolGuid,
129                                    (VOID **)ppSocketProtocol,
130                                    NULL,
131                                    NULL,
132                                    EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL );
133       if ( !EFI_ERROR ( Status )) {
134         //
135         //  Success!
136         //
137         RetVal = 0;
138       }
139       else {
140         DEBUG (( DEBUG_ERROR,
141                   "ERROR - No socket protocol on 0x%08x, Status: %r\r\n",
142                   SocketHandle,
143                   Status ));
144         RetVal = ENODEV;
145       }
146     }
147     else {
148       //
149       //  Translate the error
150       //
151       DEBUG (( DEBUG_ERROR,
152                 "ERROR - CreateChild failed, Status: %r\r\n",
153                 Status ));
154       switch ( Status ) {
155       case EFI_SUCCESS:
156         RetVal = 0;
157         break;
158 
159       case EFI_ACCESS_DENIED:
160       case EFI_WRITE_PROTECTED:
161         RetVal = EACCES;
162         break;
163 
164       case EFI_NO_RESPONSE:
165         RetVal = EHOSTUNREACH;
166         break;
167 
168       case EFI_BAD_BUFFER_SIZE:
169       case EFI_BUFFER_TOO_SMALL:
170       case EFI_INVALID_PARAMETER:
171         RetVal = EINVAL;
172         break;
173 
174       case EFI_DEVICE_ERROR:
175       case EFI_MEDIA_CHANGED:
176       case EFI_NO_MEDIA:
177       case EFI_VOLUME_CORRUPTED:
178         RetVal = EIO;
179         break;
180 
181       case EFI_NOT_FOUND:
182         RetVal = ENOENT;
183         break;
184 
185       default:
186       case EFI_OUT_OF_RESOURCES:
187         RetVal = ENOMEM;
188         break;
189 
190       case EFI_VOLUME_FULL:
191         RetVal = ENOSPC;
192         break;
193 
194       case EFI_UNSUPPORTED:
195         RetVal = ENOSYS;
196         break;
197 
198       case EFI_NO_MAPPING:
199         RetVal = ENXIO;
200         break;
201 
202       case EFI_LOAD_ERROR:
203         RetVal = ESRCH;
204         break;
205 
206       case EFI_TIMEOUT:
207         RetVal = ETIMEDOUT;
208         break;
209 
210       case EFI_NOT_READY:
211         RetVal = EWOULDBLOCK;
212         break;
213       }
214     }
215   }
216   else {
217     DEBUG (( DEBUG_ERROR,
218               "ERROR - Socket driver not loaded, Status: %r\r\n",
219               Status ));
220     RetVal = ENODEV;
221   }
222 
223   //
224   //  Return the operation status
225   //
226   return RetVal;
227 }
228