3 #include "fs/pxe/pxe.h"
5 extern EFI_GUID Tcp4ServiceBindingProtocol
;
6 extern EFI_GUID Tcp4Protocol
;
9 extern struct efi_binding
*efi_create_binding(EFI_GUID
*, EFI_GUID
*);
10 extern void efi_destroy_binding(struct efi_binding
*, EFI_GUID
*);
11 int core_tcp_open(struct pxe_pvt_inode
*socket
)
13 struct efi_binding
*b
;
15 b
= efi_create_binding(&Tcp4ServiceBindingProtocol
, &Tcp4Protocol
);
19 socket
->net
.efi
.binding
= b
;
24 static EFIAPI
void null_cb(EFI_EVENT ev
, void *context
)
26 EFI_TCP4_COMPLETION_TOKEN
*token
= context
;
30 uefi_call_wrapper(BS
->CloseEvent
, 1, token
->Event
);
33 static int volatile cb_status
= -1;
34 static EFIAPI
void tcp_cb(EFI_EVENT ev
, void *context
)
36 EFI_TCP4_COMPLETION_TOKEN
*token
= context
;
40 if (token
->Status
== EFI_SUCCESS
)
46 int core_tcp_connect(struct pxe_pvt_inode
*socket
, uint32_t ip
, uint16_t port
)
48 EFI_TCP4_CONNECTION_TOKEN token
;
49 EFI_TCP4_ACCESS_POINT
*ap
;
50 EFI_TCP4_CONFIG_DATA tdata
;
51 struct efi_binding
*b
= socket
->net
.efi
.binding
;
53 EFI_TCP4
*tcp
= (EFI_TCP4
*)b
->this;
56 memset(&tdata
, 0, sizeof(tdata
));
58 ap
= &tdata
.AccessPoint
;
59 memcpy(&ap
->StationAddress
, &IPInfo
.myip
, sizeof(IPInfo
.myip
));
60 memcpy(&ap
->SubnetMask
, &IPInfo
.netmask
, sizeof(IPInfo
.netmask
));
61 memcpy(&ap
->RemoteAddress
, &ip
, sizeof(ip
));
62 ap
->RemotePort
= port
;
63 ap
->ActiveFlag
= TRUE
; /* Initiate active open */
65 tdata
.TimeToLive
= 64;
67 status
= uefi_call_wrapper(tcp
->Configure
, 2, tcp
, &tdata
);
68 if (status
!= EFI_SUCCESS
)
71 status
= efi_setup_event(&token
.CompletionToken
.Event
,
72 (EFI_EVENT_NOTIFY
)tcp_cb
, &token
.CompletionToken
);
73 if (status
!= EFI_SUCCESS
)
76 status
= uefi_call_wrapper(tcp
->Connect
, 2, tcp
, &token
);
77 if (status
!= EFI_SUCCESS
) {
78 Print(L
"Failed to connect: %d\n", status
);
82 while (cb_status
== -1)
83 uefi_call_wrapper(tcp
->Poll
, 1, tcp
);
92 uefi_call_wrapper(BS
->CloseEvent
, 1, token
.CompletionToken
.Event
);
96 bool core_tcp_is_connected(struct pxe_pvt_inode
*socket
)
98 if (socket
->net
.efi
.binding
)
104 int core_tcp_write(struct pxe_pvt_inode
*socket
, const void *data
,
105 size_t len
, bool copy
)
107 EFI_TCP4_TRANSMIT_DATA txdata
;
108 EFI_TCP4_FRAGMENT_DATA
*frag
;
109 struct efi_binding
*b
= socket
->net
.efi
.binding
;
110 EFI_TCP4_IO_TOKEN iotoken
;
112 EFI_TCP4
*tcp
= (EFI_TCP4
*)b
->this;
117 memset(&iotoken
, 0, sizeof(iotoken
));
118 memset(&txdata
, 0, sizeof(txdata
));
120 txdata
.DataLength
= len
;
121 txdata
.FragmentCount
= 1;
123 frag
= &txdata
.FragmentTable
[0];
124 frag
->FragmentLength
= len
;
125 frag
->FragmentBuffer
= (void *)data
;
127 iotoken
.Packet
.TxData
= &txdata
;
129 status
= efi_setup_event(&iotoken
.CompletionToken
.Event
,
130 (EFI_EVENT_NOTIFY
)tcp_cb
, &iotoken
.CompletionToken
);
131 if (status
!= EFI_SUCCESS
)
134 status
= uefi_call_wrapper(tcp
->Transmit
, 2, tcp
, &iotoken
);
135 if (status
!= EFI_SUCCESS
) {
136 Print(L
"tcp transmit failed, %d\n", status
);
140 while (cb_status
== -1)
141 uefi_call_wrapper(tcp
->Poll
, 1, tcp
);
150 uefi_call_wrapper(BS
->CloseEvent
, 1, iotoken
.CompletionToken
.Event
);
154 void core_tcp_close_file(struct inode
*inode
)
156 struct pxe_pvt_inode
*socket
= PVT(inode
);
157 struct efi_binding
*b
= socket
->net
.efi
.binding
;
158 EFI_TCP4_CLOSE_TOKEN token
;
160 EFI_TCP4
*tcp
= (EFI_TCP4
*)b
->this;
162 if (!socket
->tftp_goteof
) {
163 memset(&token
, 0, sizeof(token
));
165 status
= efi_setup_event(&token
.CompletionToken
.Event
,
166 (EFI_EVENT_NOTIFY
)null_cb
,
167 &token
.CompletionToken
);
168 if (status
!= EFI_SUCCESS
)
171 status
= uefi_call_wrapper(tcp
->Close
, 2, tcp
, &token
);
172 if (status
!= EFI_SUCCESS
)
173 Print(L
"tcp close failed: %d\n", status
);
176 efi_destroy_binding(b
, &Tcp4ServiceBindingProtocol
);
177 socket
->net
.efi
.binding
= NULL
;
180 static char databuf
[8192];
182 void core_tcp_fill_buffer(struct inode
*inode
)
184 struct pxe_pvt_inode
*socket
= PVT(inode
);
185 struct efi_binding
*b
= socket
->net
.efi
.binding
;
186 EFI_TCP4_IO_TOKEN iotoken
;
187 EFI_TCP4_RECEIVE_DATA rxdata
;
188 EFI_TCP4_FRAGMENT_DATA
*frag
;
190 EFI_TCP4
*tcp
= (EFI_TCP4
*)b
->this;
194 memset(&iotoken
, 0, sizeof(iotoken
));
195 memset(&rxdata
, 0, sizeof(rxdata
));
197 status
= efi_setup_event(&iotoken
.CompletionToken
.Event
,
198 (EFI_EVENT_NOTIFY
)tcp_cb
, &iotoken
.CompletionToken
);
199 if (status
!= EFI_SUCCESS
)
202 iotoken
.Packet
.RxData
= &rxdata
;
203 rxdata
.FragmentCount
= 1;
204 rxdata
.DataLength
= sizeof(databuf
);
205 frag
= &rxdata
.FragmentTable
[0];
206 frag
->FragmentBuffer
= databuf
;
207 frag
->FragmentLength
= sizeof(databuf
);
209 status
= uefi_call_wrapper(tcp
->Receive
, 2, tcp
, &iotoken
);
210 if (status
== EFI_CONNECTION_FIN
) {
211 socket
->tftp_goteof
= 1;
212 if (inode
->size
== (uint64_t)-1)
213 inode
->size
= socket
->tftp_filepos
;
214 socket
->ops
->close(inode
);
218 while (cb_status
== -1)
219 uefi_call_wrapper(tcp
->Poll
, 1, tcp
);
224 len
= frag
->FragmentLength
;
225 memcpy(databuf
, frag
->FragmentBuffer
, len
);
228 socket
->tftp_dataptr
= data
;
229 socket
->tftp_filepos
+= len
;
230 socket
->tftp_bytesleft
= len
;
233 uefi_call_wrapper(BS
->CloseEvent
, 1, iotoken
.CompletionToken
.Event
);