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 */
9 static __lowmem char packet_buf[PKTBUF_SIZE] __aligned(16);
10 
11 extern uint16_t get_port(void);
12 extern void free_port(uint16_t);
13 
14 const 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  */
core_udp_open(struct pxe_pvt_inode * socket __unused)26 int 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  */
core_udp_close(struct pxe_pvt_inode * socket)41 void 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  */
core_udp_connect(struct pxe_pvt_inode * socket,uint32_t ip,uint16_t port)56 void 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  */
core_udp_disconnect(struct pxe_pvt_inode * socket __unused)71 void 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  */
core_udp_recv(struct pxe_pvt_inode * socket,void * buf,uint16_t * buf_len,uint32_t * src_ip,uint16_t * src_port)85 int 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  */
core_udp_send(struct pxe_pvt_inode * socket,const void * data,size_t len)123 void 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  */
core_udp_sendto(struct pxe_pvt_inode * socket,const void * data,size_t len,uint32_t ip,uint16_t port)158 void 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  */
net_core_init(void)191 void 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 
probe_undi(void)204 void probe_undi(void)
205 {
206 }
207 
pxe_init_isr(void)208 void pxe_init_isr(void)
209 {
210 }
211 
reset_pxe(void)212 int 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