Blame view
drivers/net/netconsole.c
7.49 KB
83d290c56 SPDX: Convert all... |
1 |
// SPDX-License-Identifier: GPL-2.0+ |
68ceb29e7 Add support for c... |
2 3 4 |
/* * (C) Copyright 2004 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
68ceb29e7 Add support for c... |
5 6 7 |
*/ #include <common.h> |
68ceb29e7 Add support for c... |
8 |
#include <command.h> |
f1f0ae6a9 env: Move get_env... |
9 |
#include <env.h> |
52cb4d4fb stdio/device: rew... |
10 |
#include <stdio_dev.h> |
68ceb29e7 Add support for c... |
11 |
#include <net.h> |
2c8fe5120 net: Make the net... |
12 13 14 15 16 |
#ifndef CONFIG_NETCONSOLE_BUFFER_SIZE #define CONFIG_NETCONSOLE_BUFFER_SIZE 512 #endif static char input_buffer[CONFIG_NETCONSOLE_BUFFER_SIZE]; |
e1902ac69 net: cosmetic: ne... |
17 18 19 20 |
static int input_size; /* char count in input buffer */ static int input_offset; /* offset to valid chars in input buffer */ static int input_recursion; static int output_recursion; |
68ceb29e7 Add support for c... |
21 |
static int net_timeout; |
e1902ac69 net: cosmetic: ne... |
22 |
static uchar nc_ether[6]; /* server enet address */ |
049a95a77 net: cosmetic: Ch... |
23 |
static struct in_addr nc_ip; /* server ip */ |
7f51898c1 net: Make netcons... |
24 25 |
static short nc_out_port; /* target output port */ static short nc_in_port; /* source input port */ |
e1902ac69 net: cosmetic: ne... |
26 27 |
static const char *output_packet; /* used by first send udp */ static int output_packet_len; |
f8be7d659 net: Improve the ... |
28 29 30 31 32 |
/* * Start with a default last protocol. * We are only interested in NETCONS or not. */ enum proto_t net_loop_last_protocol = BOOTP; |
68ceb29e7 Add support for c... |
33 |
|
03eb129f8 NET: pass source ... |
34 |
static void nc_wait_arp_handler(uchar *pkt, unsigned dest, |
049a95a77 net: cosmetic: Ch... |
35 |
struct in_addr sip, unsigned src, |
68ceb29e7 Add support for c... |
36 37 |
unsigned len) { |
22f6e99d5 net: Refactor to ... |
38 |
net_set_state(NETLOOP_SUCCESS); /* got arp reply - quit net loop */ |
68ceb29e7 Add support for c... |
39 |
} |
049a95a77 net: cosmetic: Ch... |
40 41 |
static void nc_handler(uchar *pkt, unsigned dest, struct in_addr sip, unsigned src, unsigned len) |
68ceb29e7 Add support for c... |
42 |
{ |
eedcd078f * Patch by Detlev... |
43 |
if (input_size) |
22f6e99d5 net: Refactor to ... |
44 |
net_set_state(NETLOOP_SUCCESS); /* got input - quit net loop */ |
68ceb29e7 Add support for c... |
45 |
} |
6a38a5f3d net: cosmetic: Cl... |
46 |
static void nc_timeout_handler(void) |
68ceb29e7 Add support for c... |
47 |
{ |
22f6e99d5 net: Refactor to ... |
48 |
net_set_state(NETLOOP_SUCCESS); |
68ceb29e7 Add support for c... |
49 |
} |
049a95a77 net: cosmetic: Ch... |
50 |
static int is_broadcast(struct in_addr ip) |
e827fec2b net: Allow netcon... |
51 |
{ |
049a95a77 net: cosmetic: Ch... |
52 53 |
static struct in_addr netmask; static struct in_addr our_ip; |
e827fec2b net: Allow netcon... |
54 |
static int env_changed_id; |
f1f0ae6a9 env: Move get_env... |
55 |
int env_id = env_get_id(); |
e827fec2b net: Allow netcon... |
56 57 58 |
/* update only when the environment has changed */ if (env_changed_id != env_id) { |
723806cc5 env: Rename some ... |
59 60 |
netmask = env_get_ip("netmask"); our_ip = env_get_ip("ipaddr"); |
e827fec2b net: Allow netcon... |
61 62 63 |
env_changed_id = env_id; } |
049a95a77 net: cosmetic: Ch... |
64 65 66 67 |
return (ip.s_addr == ~0 || /* 255.255.255.255 (global bcast) */ ((netmask.s_addr & our_ip.s_addr) == (netmask.s_addr & ip.s_addr) && /* on the same net and */ (netmask.s_addr | ip.s_addr) == ~0)); /* bcast to our net */ |
e827fec2b net: Allow netcon... |
68 69 70 71 72 73 |
} static int refresh_settings_from_env(void) { const char *p; static int env_changed_id; |
f1f0ae6a9 env: Move get_env... |
74 |
int env_id = env_get_id(); |
e827fec2b net: Allow netcon... |
75 76 77 |
/* update only when the environment has changed */ if (env_changed_id != env_id) { |
00caae6d4 env: Rename geten... |
78 |
if (env_get("ncip")) { |
723806cc5 env: Rename some ... |
79 |
nc_ip = env_get_ip("ncip"); |
049a95a77 net: cosmetic: Ch... |
80 |
if (!nc_ip.s_addr) |
e827fec2b net: Allow netcon... |
81 |
return -1; /* ncip is 0.0.0.0 */ |
00caae6d4 env: Rename geten... |
82 |
p = strchr(env_get("ncip"), ':'); |
e827fec2b net: Allow netcon... |
83 84 85 86 |
if (p != NULL) { nc_out_port = simple_strtoul(p + 1, NULL, 10); nc_in_port = nc_out_port; } |
6a38a5f3d net: cosmetic: Cl... |
87 |
} else { |
049a95a77 net: cosmetic: Ch... |
88 |
nc_ip.s_addr = ~0; /* ncip is not set, so broadcast */ |
6a38a5f3d net: cosmetic: Cl... |
89 |
} |
e827fec2b net: Allow netcon... |
90 |
|
00caae6d4 env: Rename geten... |
91 |
p = env_get("ncoutport"); |
e827fec2b net: Allow netcon... |
92 93 |
if (p != NULL) nc_out_port = simple_strtoul(p, NULL, 10); |
00caae6d4 env: Rename geten... |
94 |
p = env_get("ncinport"); |
e827fec2b net: Allow netcon... |
95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
if (p != NULL) nc_in_port = simple_strtoul(p, NULL, 10); if (is_broadcast(nc_ip)) /* broadcast MAC address */ memset(nc_ether, 0xff, sizeof(nc_ether)); else /* force arp request */ memset(nc_ether, 0, sizeof(nc_ether)); } return 0; } /** |
bc0571fc1 net: cosmetic: Fi... |
109 |
* Called from net_loop in net/net.c before each packet |
e827fec2b net: Allow netcon... |
110 |
*/ |
6a38a5f3d net: cosmetic: Cl... |
111 |
void nc_start(void) |
68ceb29e7 Add support for c... |
112 |
{ |
e827fec2b net: Allow netcon... |
113 |
refresh_settings_from_env(); |
0adb5b761 net: cosmetic: Na... |
114 |
if (!output_packet_len || memcmp(nc_ether, net_null_ethaddr, 6)) { |
68ceb29e7 Add support for c... |
115 |
/* going to check for input packet */ |
ece223b52 net: Refactor to ... |
116 |
net_set_udp_handler(nc_handler); |
bc0571fc1 net: cosmetic: Fi... |
117 |
net_set_timeout_handler(net_timeout, nc_timeout_handler); |
68ceb29e7 Add support for c... |
118 119 |
} else { /* send arp request */ |
eedcd078f * Patch by Detlev... |
120 |
uchar *pkt; |
ece223b52 net: Refactor to ... |
121 |
net_set_arp_handler(nc_wait_arp_handler); |
1203fccee net: cosmetic: Cl... |
122 123 |
pkt = (uchar *)net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; |
e1902ac69 net: cosmetic: ne... |
124 |
memcpy(pkt, output_packet, output_packet_len); |
1203fccee net: cosmetic: Cl... |
125 126 |
net_send_udp_packet(nc_ether, nc_ip, nc_out_port, nc_in_port, output_packet_len); |
68ceb29e7 Add support for c... |
127 128 |
} } |
049a95a77 net: cosmetic: Ch... |
129 |
int nc_input_packet(uchar *pkt, struct in_addr src_ip, unsigned dest_port, |
8a0eccb10 net: Filter incom... |
130 |
unsigned src_port, unsigned len) |
68ceb29e7 Add support for c... |
131 |
{ |
eedcd078f * Patch by Detlev... |
132 |
int end, chunk; |
8a0eccb10 net: Filter incom... |
133 |
if (dest_port != nc_in_port || !len) |
e1902ac69 net: cosmetic: ne... |
134 |
return 0; /* not for us */ |
68ceb29e7 Add support for c... |
135 |
|
049a95a77 net: cosmetic: Ch... |
136 |
if (src_ip.s_addr != nc_ip.s_addr && !is_broadcast(nc_ip)) |
8a0eccb10 net: Filter incom... |
137 |
return 0; /* not from our client */ |
4ef8d53ca net: Allow filter... |
138 139 |
debug_cond(DEBUG_DEV_PKT, "input: \"%*.*s\" ", len, len, pkt); |
e1902ac69 net: cosmetic: ne... |
140 141 142 143 |
if (input_size == sizeof(input_buffer)) return 1; /* no space */ if (len > sizeof(input_buffer) - input_size) len = sizeof(input_buffer) - input_size; |
eedcd078f * Patch by Detlev... |
144 145 |
end = input_offset + input_size; |
3cacc6a77 net: Fix buffer o... |
146 |
if (end >= sizeof(input_buffer)) |
e1902ac69 net: cosmetic: ne... |
147 |
end -= sizeof(input_buffer); |
eedcd078f * Patch by Detlev... |
148 149 |
chunk = len; |
3cacc6a77 net: Fix buffer o... |
150 151 |
/* Check if packet will wrap in input_buffer */ if (end + len >= sizeof(input_buffer)) { |
e1902ac69 net: cosmetic: ne... |
152 |
chunk = sizeof(input_buffer) - end; |
3cacc6a77 net: Fix buffer o... |
153 |
/* Copy the second part of the pkt to start of input_buffer */ |
eedcd078f * Patch by Detlev... |
154 155 |
memcpy(input_buffer, pkt + chunk, len - chunk); } |
3cacc6a77 net: Fix buffer o... |
156 |
/* Copy first (or only) part of pkt after end of current valid input*/ |
e1902ac69 net: cosmetic: ne... |
157 |
memcpy(input_buffer + end, pkt, chunk); |
eedcd078f * Patch by Detlev... |
158 159 |
input_size += len; |
68ceb29e7 Add support for c... |
160 161 |
return 1; } |
e1902ac69 net: cosmetic: ne... |
162 |
static void nc_send_packet(const char *buf, int len) |
68ceb29e7 Add support for c... |
163 |
{ |
c163e4367 net: fix netconso... |
164 165 166 |
#ifdef CONFIG_DM_ETH struct udevice *eth; #else |
68ceb29e7 Add support for c... |
167 |
struct eth_device *eth; |
c163e4367 net: fix netconso... |
168 |
#endif |
68ceb29e7 Add support for c... |
169 170 |
int inited = 0; uchar *pkt; |
eedcd078f * Patch by Detlev... |
171 |
uchar *ether; |
049a95a77 net: cosmetic: Ch... |
172 |
struct in_addr ip; |
68ceb29e7 Add support for c... |
173 |
|
4ef8d53ca net: Allow filter... |
174 175 |
debug_cond(DEBUG_DEV_PKT, "output: \"%*.*s\" ", len, len, buf); |
e1902ac69 net: cosmetic: ne... |
176 177 |
eth = eth_get_dev(); if (eth == NULL) |
68ceb29e7 Add support for c... |
178 |
return; |
0adb5b761 net: cosmetic: Na... |
179 |
if (!memcmp(nc_ether, net_null_ethaddr, 6)) { |
c163e4367 net: fix netconso... |
180 |
if (eth_is_active(eth)) |
eedcd078f * Patch by Detlev... |
181 182 183 |
return; /* inside net loop */ output_packet = buf; output_packet_len = len; |
efd9bb9c0 netconsole loses ... |
184 |
input_recursion = 1; |
bc0571fc1 net: cosmetic: Fi... |
185 |
net_loop(NETCONS); /* wait for arp reply and send packet */ |
efd9bb9c0 netconsole loses ... |
186 |
input_recursion = 0; |
eedcd078f * Patch by Detlev... |
187 |
output_packet_len = 0; |
68ceb29e7 Add support for c... |
188 189 |
return; } |
c163e4367 net: fix netconso... |
190 |
if (!eth_is_active(eth)) { |
f8be7d659 net: Improve the ... |
191 |
if (eth_is_on_demand_init()) { |
d2eaec600 net: Remove the b... |
192 |
if (eth_init() < 0) |
f8be7d659 net: Improve the ... |
193 194 |
return; eth_set_last_protocol(NETCONS); |
6a38a5f3d net: cosmetic: Cl... |
195 |
} else { |
d2eaec600 net: Remove the b... |
196 |
eth_init_state_only(); |
6a38a5f3d net: cosmetic: Cl... |
197 |
} |
f8be7d659 net: Improve the ... |
198 |
|
68ceb29e7 Add support for c... |
199 200 |
inited = 1; } |
1203fccee net: cosmetic: Cl... |
201 |
pkt = (uchar *)net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; |
e1902ac69 net: cosmetic: ne... |
202 |
memcpy(pkt, buf, len); |
eedcd078f * Patch by Detlev... |
203 204 |
ether = nc_ether; ip = nc_ip; |
1203fccee net: cosmetic: Cl... |
205 |
net_send_udp_packet(ether, ip, nc_out_port, nc_in_port, len); |
68ceb29e7 Add support for c... |
206 |
|
f8be7d659 net: Improve the ... |
207 208 209 210 211 212 |
if (inited) { if (eth_is_on_demand_init()) eth_halt(); else eth_halt_state_only(); } |
68ceb29e7 Add support for c... |
213 |
} |
6a38a5f3d net: cosmetic: Cl... |
214 |
static int nc_stdio_start(struct stdio_dev *dev) |
68ceb29e7 Add support for c... |
215 |
{ |
e827fec2b net: Allow netcon... |
216 |
int retval; |
eedcd078f * Patch by Detlev... |
217 |
|
7f51898c1 net: Make netcons... |
218 219 |
nc_out_port = 6666; /* default port */ nc_in_port = nc_out_port; |
eedcd078f * Patch by Detlev... |
220 |
|
e827fec2b net: Allow netcon... |
221 222 223 |
retval = refresh_settings_from_env(); if (retval != 0) return retval; |
eedcd078f * Patch by Detlev... |
224 |
|
d7310c7e6 net: Make sure Ne... |
225 226 |
/* * Initialize the static IP settings and buffer pointers |
bc0571fc1 net: cosmetic: Fi... |
227 |
* incase we call net_send_udp_packet before net_loop |
d7310c7e6 net: Make sure Ne... |
228 229 |
*/ net_init(); |
eedcd078f * Patch by Detlev... |
230 |
return 0; |
68ceb29e7 Add support for c... |
231 |
} |
6a38a5f3d net: cosmetic: Cl... |
232 |
static void nc_stdio_putc(struct stdio_dev *dev, char c) |
68ceb29e7 Add support for c... |
233 234 235 236 |
{ if (output_recursion) return; output_recursion = 1; |
e1902ac69 net: cosmetic: ne... |
237 |
nc_send_packet(&c, 1); |
68ceb29e7 Add support for c... |
238 239 240 |
output_recursion = 0; } |
6a38a5f3d net: cosmetic: Cl... |
241 |
static void nc_stdio_puts(struct stdio_dev *dev, const char *s) |
68ceb29e7 Add support for c... |
242 |
{ |
b2323ea6f Auto-size RAM on ... |
243 |
int len; |
68ceb29e7 Add support for c... |
244 245 246 |
if (output_recursion) return; output_recursion = 1; |
1a9845b4f netconsole: suppo... |
247 248 |
len = strlen(s); while (len) { |
b41411954 linux/kernel.h: s... |
249 |
int send_len = min(len, (int)sizeof(input_buffer)); |
1a9845b4f netconsole: suppo... |
250 251 252 253 |
nc_send_packet(s, send_len); len -= send_len; s += send_len; } |
68ceb29e7 Add support for c... |
254 255 256 |
output_recursion = 0; } |
6a38a5f3d net: cosmetic: Cl... |
257 |
static int nc_stdio_getc(struct stdio_dev *dev) |
68ceb29e7 Add support for c... |
258 |
{ |
b2323ea6f Auto-size RAM on ... |
259 |
uchar c; |
68ceb29e7 Add support for c... |
260 261 262 |
input_recursion = 1; net_timeout = 0; /* no timeout */ |
eedcd078f * Patch by Detlev... |
263 |
while (!input_size) |
bc0571fc1 net: cosmetic: Fi... |
264 |
net_loop(NETCONS); |
68ceb29e7 Add support for c... |
265 266 |
input_recursion = 0; |
b2323ea6f Auto-size RAM on ... |
267 |
c = input_buffer[input_offset++]; |
e1902ac69 net: cosmetic: ne... |
268 269 |
if (input_offset >= sizeof(input_buffer)) input_offset -= sizeof(input_buffer); |
eedcd078f * Patch by Detlev... |
270 |
input_size--; |
68ceb29e7 Add support for c... |
271 |
|
eedcd078f * Patch by Detlev... |
272 |
return c; |
68ceb29e7 Add support for c... |
273 |
} |
6a38a5f3d net: cosmetic: Cl... |
274 |
static int nc_stdio_tstc(struct stdio_dev *dev) |
68ceb29e7 Add support for c... |
275 |
{ |
c163e4367 net: fix netconso... |
276 277 278 |
#ifdef CONFIG_DM_ETH struct udevice *eth; #else |
68ceb29e7 Add support for c... |
279 |
struct eth_device *eth; |
c163e4367 net: fix netconso... |
280 |
#endif |
68ceb29e7 Add support for c... |
281 282 283 |
if (input_recursion) return 0; |
eedcd078f * Patch by Detlev... |
284 |
if (input_size) |
68ceb29e7 Add support for c... |
285 |
return 1; |
e1902ac69 net: cosmetic: ne... |
286 |
eth = eth_get_dev(); |
c163e4367 net: fix netconso... |
287 |
if (eth_is_active(eth)) |
68ceb29e7 Add support for c... |
288 289 290 291 292 |
return 0; /* inside net loop */ input_recursion = 1; net_timeout = 1; |
bc0571fc1 net: cosmetic: Fi... |
293 |
net_loop(NETCONS); /* kind of poll */ |
68ceb29e7 Add support for c... |
294 295 |
input_recursion = 0; |
eedcd078f * Patch by Detlev... |
296 |
return input_size != 0; |
68ceb29e7 Add support for c... |
297 |
} |
e1902ac69 net: cosmetic: ne... |
298 |
int drv_nc_init(void) |
68ceb29e7 Add support for c... |
299 |
{ |
52cb4d4fb stdio/device: rew... |
300 |
struct stdio_dev dev; |
68ceb29e7 Add support for c... |
301 |
int rc; |
e1902ac69 net: cosmetic: ne... |
302 |
memset(&dev, 0, sizeof(dev)); |
68ceb29e7 Add support for c... |
303 |
|
e1902ac69 net: cosmetic: ne... |
304 |
strcpy(dev.name, "nc"); |
1caf934a0 video: Drop DEV_F... |
305 |
dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT; |
6a38a5f3d net: cosmetic: Cl... |
306 307 308 309 310 |
dev.start = nc_stdio_start; dev.putc = nc_stdio_putc; dev.puts = nc_stdio_puts; dev.getc = nc_stdio_getc; dev.tstc = nc_stdio_tstc; |
68ceb29e7 Add support for c... |
311 |
|
e1902ac69 net: cosmetic: ne... |
312 |
rc = stdio_register(&dev); |
68ceb29e7 Add support for c... |
313 314 315 |
return (rc == 0) ? 1 : rc; } |