1#include <syslinux/pxe_api.h>
2#include <com32.h>
3#include <core.h>
4#include <net.h>
5#include <pxe.h>
6#include <minmax.h>
7
8/* Common receive buffer */
9static __lowmem char packet_buf[PKTBUF_SIZE] __aligned(16);
10
11extern uint16_t get_port(void);
12extern void free_port(uint16_t);
13
14const struct url_scheme url_schemes[] = {
15    { "tftp", tftp_open, 0 },
16    { NULL, NULL, 0 }
17};
18
19/**
20 * Open a socket
21 *
22 * @param:socket, the socket to open
23 *
24 * @out: error code, 0 on success, -1 on failure
25 */
26int core_udp_open(struct pxe_pvt_inode *socket __unused)
27{
28    struct net_private_tftp *priv = &socket->net.tftp;
29
30    /* Allocate local UDP port number */
31    priv->localport = get_port();
32
33    return 0;
34}
35
36/**
37 * Close a socket
38 *
39 * @param:socket, the socket to open
40 */
41void core_udp_close(struct pxe_pvt_inode *socket)
42{
43    struct net_private_tftp *priv = &socket->net.tftp;
44
45    if (priv->localport)
46	free_port(priv->localport);
47}
48
49/**
50 * Establish a connection on an open socket
51 *
52 * @param:socket, the open socket
53 * @param:ip, the ip address
54 * @param:port, the port number, host-byte order
55 */
56void core_udp_connect(struct pxe_pvt_inode *socket, uint32_t ip,
57		      uint16_t port)
58{
59    struct net_private_tftp *priv = &socket->net.tftp;
60
61    socket->tftp_remoteport = htons(port);
62    priv->remoteip = ip;
63
64}
65
66/**
67 * Tear down a connection on an open socket
68 *
69 * @param:socket, the open socket
70 */
71void core_udp_disconnect(struct pxe_pvt_inode *socket __unused)
72{
73}
74
75/**
76 * Read data from the network stack
77 *
78 * @param:socket, the open socket
79 * @param:buf, location of buffer to store data
80 * @param:buf_len, size of buffer
81
82 * @out: src_ip, ip address of the data source
83 * @out: src_port, port number of the data source, host-byte order
84 */
85int core_udp_recv(struct pxe_pvt_inode *socket, void *buf, uint16_t *buf_len,
86		  uint32_t *src_ip, uint16_t *src_port)
87{
88    static __lowmem struct s_PXENV_UDP_READ  udp_read;
89    struct net_private_tftp *priv = &socket->net.tftp;
90    uint16_t bytes;
91    int err;
92
93    udp_read.status      = 0;
94    udp_read.buffer      = FAR_PTR(packet_buf);
95    udp_read.buffer_size = PKTBUF_SIZE;
96    udp_read.dest_ip     = IPInfo.myip;
97    udp_read.d_port      = priv->localport;
98
99    err = pxe_call(PXENV_UDP_READ, &udp_read);
100    if (err)
101	return err;
102
103    if (udp_read.status)
104	return udp_read.status;
105
106    bytes = min(udp_read.buffer_size, *buf_len);
107    memcpy(buf, packet_buf, bytes);
108
109    *src_ip = udp_read.src_ip;
110    *src_port = ntohs(udp_read.s_port);
111    *buf_len = bytes;
112
113    return 0;
114}
115
116/**
117 * Send a UDP packet.
118 *
119 * @param:socket, the open socket
120 * @param:data, data buffer to send
121 * @param:len, size of data bufer
122 */
123void core_udp_send(struct pxe_pvt_inode *socket, const void *data, size_t len)
124{
125    static __lowmem struct s_PXENV_UDP_WRITE udp_write;
126    struct net_private_tftp *priv = &socket->net.tftp;
127    void *lbuf;
128    uint16_t tid;
129
130    lbuf = lmalloc(len);
131    if (!lbuf)
132	return;
133
134    memcpy(lbuf, data, len);
135
136    tid = priv->localport;   /* TID(local port No) */
137    udp_write.buffer    = FAR_PTR(lbuf);
138    udp_write.ip        = priv->remoteip;
139    udp_write.gw        = gateway(udp_write.ip);
140    udp_write.src_port  = tid;
141    udp_write.dst_port  = socket->tftp_remoteport;
142    udp_write.buffer_size = len;
143
144    pxe_call(PXENV_UDP_WRITE, &udp_write);
145
146    lfree(lbuf);
147}
148
149/**
150 * Send a UDP packet to a destination
151 *
152 * @param:socket, the open socket
153 * @param:data, data buffer to send
154 * @param:len, size of data bufer
155 * @param:ip, the ip address
156 * @param:port, the port number, host-byte order
157 */
158void core_udp_sendto(struct pxe_pvt_inode *socket, const void *data, size_t len,
159		     uint32_t ip, uint16_t port)
160{
161    static __lowmem struct s_PXENV_UDP_WRITE udp_write;
162    struct net_private_tftp *priv = &socket->net.tftp;
163    void *lbuf;
164    uint16_t tid;
165
166    lbuf = lmalloc(len);
167    if (!lbuf)
168	return;
169
170    memcpy(lbuf, data, len);
171
172    tid = priv->localport;   /* TID(local port No) */
173    udp_write.buffer    = FAR_PTR(lbuf);
174    udp_write.ip        = ip;
175    udp_write.gw        = gateway(udp_write.ip);
176    udp_write.src_port  = tid;
177    udp_write.dst_port  = htons(port);
178    udp_write.buffer_size = len;
179
180    pxe_call(PXENV_UDP_WRITE, &udp_write);
181
182    lfree(lbuf);
183}
184
185
186/**
187 * Network stack-specific initialization
188 *
189 * Initialize UDP stack
190 */
191void net_core_init(void)
192{
193    int err;
194    static __lowmem struct s_PXENV_UDP_OPEN udp_open;
195    udp_open.src_ip = IPInfo.myip;
196    err = pxe_call(PXENV_UDP_OPEN, &udp_open);
197    if (err || udp_open.status) {
198        printf("Failed to initialize UDP stack ");
199        printf("%d\n", udp_open.status);
200	kaboom();
201    }
202}
203
204void probe_undi(void)
205{
206}
207
208void pxe_init_isr(void)
209{
210}
211
212int reset_pxe(void)
213{
214    static __lowmem struct s_PXENV_UDP_CLOSE udp_close;
215    int err = 0;
216
217    pxe_idle_cleanup();
218
219    pxe_call(PXENV_UDP_CLOSE, &udp_close);
220
221    return err;
222}
223