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