aboutsummaryrefslogtreecommitdiffstats
path: root/core/fs/pxe/core.c
diff options
context:
space:
mode:
authorMatt Fleming <matt.fleming@intel.com>2013-03-22 14:54:09 +0000
committerMatt Fleming <matt.fleming@intel.com>2013-04-23 15:30:17 +0100
commitfe283b78c973268f2d1f0309826ceeb5c9e8978d (patch)
treede90b141427ab9222bb3e82afef6f880778b3cf2 /core/fs/pxe/core.c
parentbb229372b2c3f9fbb0cdd0a7221a6cc4aba5d2ed (diff)
downloadsyslinux-fe283b78c973268f2d1f0309826ceeb5c9e8978d.tar.gz
syslinux-fe283b78c973268f2d1f0309826ceeb5c9e8978d.tar.xz
syslinux-fe283b78c973268f2d1f0309826ceeb5c9e8978d.zip
efi: Add network supportsyslinux-6.00-pre5
Add TCP and UDP support to the EFI firmware backend. This necessitated moving all tcp functions to a core_tcp_* prefix so that they could be implemented differently for BIOS+lwip and EFI. Unfortunately, the tcp_* prefix is already in use by the lwip code. To maintain symmetry, the UDP functions were also moved from net_core_* to core_udp_*. The net_core API was introduced in 5.x to allow the legacy PXE and lwip stacks to live side by side, and the intention was that net_core_init() would take a protocol argument to build a protocol-specific object. It turned out to be easier to call either udp or tcp functions directly because the semantics of read/write differ between protocols. Booting an IPv4 EFI PXE stack using tftp and http has been tested. There are a couple of TODO items left, o dns resolve code is missing o ftp hasn't been tested Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'core/fs/pxe/core.c')
-rw-r--r--core/fs/pxe/core.c124
1 files changed, 103 insertions, 21 deletions
diff --git a/core/fs/pxe/core.c b/core/fs/pxe/core.c
index e330ba82..e6bbee9b 100644
--- a/core/fs/pxe/core.c
+++ b/core/fs/pxe/core.c
@@ -17,29 +17,15 @@ const struct url_scheme url_schemes[] = {
* Open a socket
*
* @param:socket, the socket to open
- * @param:proto, the protocol of the new connection
*
* @out: error code, 0 on success, -1 on failure
*/
-int net_core_open(struct pxe_pvt_inode *socket, enum net_core_proto proto)
+int core_udp_open(struct pxe_pvt_inode *socket)
{
struct net_private_lwip *priv = &socket->net.lwip;
- enum netconn_type type;
int err;
- switch (proto) {
- case NET_CORE_TCP:
- type = NETCONN_TCP;
- break;
- case NET_CORE_UDP:
- type = NETCONN_UDP;
- break;
- default:
- type = NETCONN_INVALID;
- break;
- }
-
- priv->conn = netconn_new(type);
+ priv->conn = netconn_new(NETCONN_UDP);
if (!priv->conn)
return -1;
@@ -58,7 +44,7 @@ int net_core_open(struct pxe_pvt_inode *socket, enum net_core_proto proto)
*
* @param:socket, the socket to open
*/
-void net_core_close(struct pxe_pvt_inode *socket)
+void core_udp_close(struct pxe_pvt_inode *socket)
{
struct net_private_lwip *priv = &socket->net.lwip;
@@ -75,7 +61,7 @@ void net_core_close(struct pxe_pvt_inode *socket)
* @param:ip, the ip address
* @param:port, the port number, host-byte order
*/
-void net_core_connect(struct pxe_pvt_inode *socket, uint32_t ip,
+void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t ip,
uint16_t port)
{
struct net_private_lwip *priv = &socket->net.lwip;
@@ -90,7 +76,7 @@ void net_core_connect(struct pxe_pvt_inode *socket, uint32_t ip,
*
* @param:socket, the open socket
*/
-void net_core_disconnect(struct pxe_pvt_inode *socket)
+void core_udp_disconnect(struct pxe_pvt_inode *socket)
{
struct net_private_lwip *priv = &socket->net.lwip;
netconn_disconnect(priv->conn);
@@ -106,7 +92,7 @@ void net_core_disconnect(struct pxe_pvt_inode *socket)
* @out: src_ip, ip address of the data source
* @out: src_port, port number of the data source, host-byte order
*/
-int net_core_recv(struct pxe_pvt_inode *socket, void *buf, uint16_t *buf_len,
+int core_udp_recv(struct pxe_pvt_inode *socket, void *buf, uint16_t *buf_len,
uint32_t *src_ip, uint16_t *src_port)
{
struct net_private_lwip *priv = &socket->net.lwip;
@@ -143,7 +129,7 @@ int net_core_recv(struct pxe_pvt_inode *socket, void *buf, uint16_t *buf_len,
* @param:data, data buffer to send
* @param:len, size of data bufer
*/
-void net_core_send(struct pxe_pvt_inode *socket, const void *data, size_t len)
+void core_udp_send(struct pxe_pvt_inode *socket, const void *data, size_t len)
{
struct netconn *conn = socket->net.lwip.conn;
struct netbuf *nbuf;
@@ -212,3 +198,99 @@ void probe_undi(void)
pxe_undi_iface.IfaceType, pxe_undi_iface.ServiceFlags);
}
+int core_tcp_open(struct pxe_pvt_inode *socket)
+{
+ socket->net.lwip.conn = netconn_new(NETCONN_TCP);
+ if (!socket->net.lwip.conn)
+ return -1;
+
+ return 0;
+}
+int core_tcp_connect(struct pxe_pvt_inode *socket, uint32_t ip, uint16_t port)
+{
+ struct ip_addr addr;
+ err_t err;
+
+ addr.addr = ip;
+ err = netconn_connect(socket->net.lwip.conn, &addr, port);
+ if (err) {
+ printf("netconn_connect error %d\n", err);
+ return -1;
+ }
+
+ return 0;
+}
+
+int core_tcp_write(struct pxe_pvt_inode *socket, const void *data, size_t len,
+ bool copy)
+{
+ err_t err;
+ u8_t flags = copy ? NETCONN_COPY : NETCONN_NOCOPY;
+
+ err = netconn_write(socket->net.lwip.conn, data, len, flags);
+ if (err) {
+ printf("netconn_write failed: %d\n", err);
+ return -1;
+ }
+
+ return 0;
+}
+
+void core_tcp_close_file(struct inode *inode)
+{
+ struct pxe_pvt_inode *socket = PVT(inode);
+
+ if (socket->net.lwip.conn) {
+ netconn_delete(socket->net.lwip.conn);
+ socket->net.lwip.conn = NULL;
+ }
+ if (socket->net.lwip.buf) {
+ netbuf_delete(socket->net.lwip.buf);
+ socket->net.lwip.buf = NULL;
+ }
+}
+
+bool core_tcp_is_connected(struct pxe_pvt_inode *socket)
+{
+ if (socket->net.lwip.conn)
+ return true;
+
+ return false;
+}
+
+void core_tcp_fill_buffer(struct inode *inode)
+{
+ struct pxe_pvt_inode *socket = PVT(inode);
+ void *data;
+ u16_t len;
+ err_t err;
+
+ /* Clean up or advance an inuse netbuf */
+ if (socket->net.lwip.buf) {
+ if (netbuf_next(socket->net.lwip.buf) < 0) {
+ netbuf_delete(socket->net.lwip.buf);
+ socket->net.lwip.buf = NULL;
+ }
+ }
+ /* If needed get a new netbuf */
+ if (!socket->net.lwip.buf) {
+ err = netconn_recv(socket->net.lwip.conn, &(socket->net.lwip.buf));
+ if (!socket->net.lwip.buf || err) {
+ socket->tftp_goteof = 1;
+ if (inode->size == -1)
+ inode->size = socket->tftp_filepos;
+ socket->ops->close(inode);
+ return;
+ }
+ }
+ /* Report the current fragment of the netbuf */
+ err = netbuf_data(socket->net.lwip.buf, &data, &len);
+ if (err) {
+ printf("netbuf_data err: %d\n", err);
+ kaboom();
+ }
+ socket->tftp_dataptr = data;
+ socket->tftp_filepos += len;
+ socket->tftp_bytesleft = len;
+ return;
+}