Blame view

drivers/net/netconsole.c 7.49 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
68ceb29e7   wdenk   Add support for c...
2
3
4
  /*
   * (C) Copyright 2004
   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
68ceb29e7   wdenk   Add support for c...
5
6
7
   */
  
  #include <common.h>
68ceb29e7   wdenk   Add support for c...
8
  #include <command.h>
f1f0ae6a9   Simon Glass   env: Move get_env...
9
  #include <env.h>
52cb4d4fb   Jean-Christophe PLAGNIOL-VILLARD   stdio/device: rew...
10
  #include <stdio_dev.h>
68ceb29e7   wdenk   Add support for c...
11
  #include <net.h>
2c8fe5120   Joe Hershberger   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   Joe Hershberger   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   wdenk   Add support for c...
21
  static int net_timeout;
e1902ac69   Joe Hershberger   net: cosmetic: ne...
22
  static uchar nc_ether[6]; /* server enet address */
049a95a77   Joe Hershberger   net: cosmetic: Ch...
23
  static struct in_addr nc_ip; /* server ip */
7f51898c1   Joe Hershberger   net: Make netcons...
24
25
  static short nc_out_port; /* target output port */
  static short nc_in_port; /* source input port */
e1902ac69   Joe Hershberger   net: cosmetic: ne...
26
27
  static const char *output_packet; /* used by first send udp */
  static int output_packet_len;
f8be7d659   Joe Hershberger   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   wdenk   Add support for c...
33

03eb129f8   Luca Ceresoli   NET: pass source ...
34
  static void nc_wait_arp_handler(uchar *pkt, unsigned dest,
049a95a77   Joe Hershberger   net: cosmetic: Ch...
35
  				 struct in_addr sip, unsigned src,
68ceb29e7   wdenk   Add support for c...
36
37
  				 unsigned len)
  {
22f6e99d5   Joe Hershberger   net: Refactor to ...
38
  	net_set_state(NETLOOP_SUCCESS); /* got arp reply - quit net loop */
68ceb29e7   wdenk   Add support for c...
39
  }
049a95a77   Joe Hershberger   net: cosmetic: Ch...
40
41
  static void nc_handler(uchar *pkt, unsigned dest, struct in_addr sip,
  		       unsigned src, unsigned len)
68ceb29e7   wdenk   Add support for c...
42
  {
eedcd078f   wdenk   * Patch by Detlev...
43
  	if (input_size)
22f6e99d5   Joe Hershberger   net: Refactor to ...
44
  		net_set_state(NETLOOP_SUCCESS); /* got input - quit net loop */
68ceb29e7   wdenk   Add support for c...
45
  }
6a38a5f3d   Joe Hershberger   net: cosmetic: Cl...
46
  static void nc_timeout_handler(void)
68ceb29e7   wdenk   Add support for c...
47
  {
22f6e99d5   Joe Hershberger   net: Refactor to ...
48
  	net_set_state(NETLOOP_SUCCESS);
68ceb29e7   wdenk   Add support for c...
49
  }
049a95a77   Joe Hershberger   net: cosmetic: Ch...
50
  static int is_broadcast(struct in_addr ip)
e827fec2b   Joe Hershberger   net: Allow netcon...
51
  {
049a95a77   Joe Hershberger   net: cosmetic: Ch...
52
53
  	static struct in_addr netmask;
  	static struct in_addr our_ip;
e827fec2b   Joe Hershberger   net: Allow netcon...
54
  	static int env_changed_id;
f1f0ae6a9   Simon Glass   env: Move get_env...
55
  	int env_id = env_get_id();
e827fec2b   Joe Hershberger   net: Allow netcon...
56
57
58
  
  	/* update only when the environment has changed */
  	if (env_changed_id != env_id) {
723806cc5   Simon Glass   env: Rename some ...
59
60
  		netmask = env_get_ip("netmask");
  		our_ip = env_get_ip("ipaddr");
e827fec2b   Joe Hershberger   net: Allow netcon...
61
62
63
  
  		env_changed_id = env_id;
  	}
049a95a77   Joe Hershberger   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   Joe Hershberger   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   Simon Glass   env: Move get_env...
74
  	int env_id = env_get_id();
e827fec2b   Joe Hershberger   net: Allow netcon...
75
76
77
  
  	/* update only when the environment has changed */
  	if (env_changed_id != env_id) {
00caae6d4   Simon Glass   env: Rename geten...
78
  		if (env_get("ncip")) {
723806cc5   Simon Glass   env: Rename some ...
79
  			nc_ip = env_get_ip("ncip");
049a95a77   Joe Hershberger   net: cosmetic: Ch...
80
  			if (!nc_ip.s_addr)
e827fec2b   Joe Hershberger   net: Allow netcon...
81
  				return -1;	/* ncip is 0.0.0.0 */
00caae6d4   Simon Glass   env: Rename geten...
82
  			p = strchr(env_get("ncip"), ':');
e827fec2b   Joe Hershberger   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   Joe Hershberger   net: cosmetic: Cl...
87
  		} else {
049a95a77   Joe Hershberger   net: cosmetic: Ch...
88
  			nc_ip.s_addr = ~0; /* ncip is not set, so broadcast */
6a38a5f3d   Joe Hershberger   net: cosmetic: Cl...
89
  		}
e827fec2b   Joe Hershberger   net: Allow netcon...
90

00caae6d4   Simon Glass   env: Rename geten...
91
  		p = env_get("ncoutport");
e827fec2b   Joe Hershberger   net: Allow netcon...
92
93
  		if (p != NULL)
  			nc_out_port = simple_strtoul(p, NULL, 10);
00caae6d4   Simon Glass   env: Rename geten...
94
  		p = env_get("ncinport");
e827fec2b   Joe Hershberger   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   Joe Hershberger   net: cosmetic: Fi...
109
   * Called from net_loop in net/net.c before each packet
e827fec2b   Joe Hershberger   net: Allow netcon...
110
   */
6a38a5f3d   Joe Hershberger   net: cosmetic: Cl...
111
  void nc_start(void)
68ceb29e7   wdenk   Add support for c...
112
  {
e827fec2b   Joe Hershberger   net: Allow netcon...
113
  	refresh_settings_from_env();
0adb5b761   Joe Hershberger   net: cosmetic: Na...
114
  	if (!output_packet_len || memcmp(nc_ether, net_null_ethaddr, 6)) {
68ceb29e7   wdenk   Add support for c...
115
  		/* going to check for input packet */
ece223b52   Joe Hershberger   net: Refactor to ...
116
  		net_set_udp_handler(nc_handler);
bc0571fc1   Joe Hershberger   net: cosmetic: Fi...
117
  		net_set_timeout_handler(net_timeout, nc_timeout_handler);
68ceb29e7   wdenk   Add support for c...
118
119
  	} else {
  		/* send arp request */
eedcd078f   wdenk   * Patch by Detlev...
120
  		uchar *pkt;
ece223b52   Joe Hershberger   net: Refactor to ...
121
  		net_set_arp_handler(nc_wait_arp_handler);
1203fccee   Joe Hershberger   net: cosmetic: Cl...
122
123
  		pkt = (uchar *)net_tx_packet + net_eth_hdr_size() +
  			IP_UDP_HDR_SIZE;
e1902ac69   Joe Hershberger   net: cosmetic: ne...
124
  		memcpy(pkt, output_packet, output_packet_len);
1203fccee   Joe Hershberger   net: cosmetic: Cl...
125
126
  		net_send_udp_packet(nc_ether, nc_ip, nc_out_port, nc_in_port,
  				    output_packet_len);
68ceb29e7   wdenk   Add support for c...
127
128
  	}
  }
049a95a77   Joe Hershberger   net: cosmetic: Ch...
129
  int nc_input_packet(uchar *pkt, struct in_addr src_ip, unsigned dest_port,
8a0eccb10   Joe Hershberger   net: Filter incom...
130
  	unsigned src_port, unsigned len)
68ceb29e7   wdenk   Add support for c...
131
  {
eedcd078f   wdenk   * Patch by Detlev...
132
  	int end, chunk;
8a0eccb10   Joe Hershberger   net: Filter incom...
133
  	if (dest_port != nc_in_port || !len)
e1902ac69   Joe Hershberger   net: cosmetic: ne...
134
  		return 0; /* not for us */
68ceb29e7   wdenk   Add support for c...
135

049a95a77   Joe Hershberger   net: cosmetic: Ch...
136
  	if (src_ip.s_addr != nc_ip.s_addr && !is_broadcast(nc_ip))
8a0eccb10   Joe Hershberger   net: Filter incom...
137
  		return 0; /* not from our client */
4ef8d53ca   Joe Hershberger   net: Allow filter...
138
139
  	debug_cond(DEBUG_DEV_PKT, "input: \"%*.*s\"
  ", len, len, pkt);
e1902ac69   Joe Hershberger   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   wdenk   * Patch by Detlev...
144
145
  
  	end = input_offset + input_size;
3cacc6a77   Joe Hershberger   net: Fix buffer o...
146
  	if (end >= sizeof(input_buffer))
e1902ac69   Joe Hershberger   net: cosmetic: ne...
147
  		end -= sizeof(input_buffer);
eedcd078f   wdenk   * Patch by Detlev...
148
149
  
  	chunk = len;
3cacc6a77   Joe Hershberger   net: Fix buffer o...
150
151
  	/* Check if packet will wrap in input_buffer */
  	if (end + len >= sizeof(input_buffer)) {
e1902ac69   Joe Hershberger   net: cosmetic: ne...
152
  		chunk = sizeof(input_buffer) - end;
3cacc6a77   Joe Hershberger   net: Fix buffer o...
153
  		/* Copy the second part of the pkt to start of input_buffer */
eedcd078f   wdenk   * Patch by Detlev...
154
155
  		memcpy(input_buffer, pkt + chunk, len - chunk);
  	}
3cacc6a77   Joe Hershberger   net: Fix buffer o...
156
  	/* Copy first (or only) part of pkt after end of current valid input*/
e1902ac69   Joe Hershberger   net: cosmetic: ne...
157
  	memcpy(input_buffer + end, pkt, chunk);
eedcd078f   wdenk   * Patch by Detlev...
158
159
  
  	input_size += len;
68ceb29e7   wdenk   Add support for c...
160
161
  	return 1;
  }
e1902ac69   Joe Hershberger   net: cosmetic: ne...
162
  static void nc_send_packet(const char *buf, int len)
68ceb29e7   wdenk   Add support for c...
163
  {
c163e4367   Bernhard Nortmann   net: fix netconso...
164
165
166
  #ifdef CONFIG_DM_ETH
  	struct udevice *eth;
  #else
68ceb29e7   wdenk   Add support for c...
167
  	struct eth_device *eth;
c163e4367   Bernhard Nortmann   net: fix netconso...
168
  #endif
68ceb29e7   wdenk   Add support for c...
169
170
  	int inited = 0;
  	uchar *pkt;
eedcd078f   wdenk   * Patch by Detlev...
171
  	uchar *ether;
049a95a77   Joe Hershberger   net: cosmetic: Ch...
172
  	struct in_addr ip;
68ceb29e7   wdenk   Add support for c...
173

4ef8d53ca   Joe Hershberger   net: Allow filter...
174
175
  	debug_cond(DEBUG_DEV_PKT, "output: \"%*.*s\"
  ", len, len, buf);
e1902ac69   Joe Hershberger   net: cosmetic: ne...
176
177
  	eth = eth_get_dev();
  	if (eth == NULL)
68ceb29e7   wdenk   Add support for c...
178
  		return;
0adb5b761   Joe Hershberger   net: cosmetic: Na...
179
  	if (!memcmp(nc_ether, net_null_ethaddr, 6)) {
c163e4367   Bernhard Nortmann   net: fix netconso...
180
  		if (eth_is_active(eth))
eedcd078f   wdenk   * Patch by Detlev...
181
182
183
  			return;	/* inside net loop */
  		output_packet = buf;
  		output_packet_len = len;
efd9bb9c0   Suriyan Ramasami   netconsole loses ...
184
  		input_recursion = 1;
bc0571fc1   Joe Hershberger   net: cosmetic: Fi...
185
  		net_loop(NETCONS); /* wait for arp reply and send packet */
efd9bb9c0   Suriyan Ramasami   netconsole loses ...
186
  		input_recursion = 0;
eedcd078f   wdenk   * Patch by Detlev...
187
  		output_packet_len = 0;
68ceb29e7   wdenk   Add support for c...
188
189
  		return;
  	}
c163e4367   Bernhard Nortmann   net: fix netconso...
190
  	if (!eth_is_active(eth)) {
f8be7d659   Joe Hershberger   net: Improve the ...
191
  		if (eth_is_on_demand_init()) {
d2eaec600   Joe Hershberger   net: Remove the b...
192
  			if (eth_init() < 0)
f8be7d659   Joe Hershberger   net: Improve the ...
193
194
  				return;
  			eth_set_last_protocol(NETCONS);
6a38a5f3d   Joe Hershberger   net: cosmetic: Cl...
195
  		} else {
d2eaec600   Joe Hershberger   net: Remove the b...
196
  			eth_init_state_only();
6a38a5f3d   Joe Hershberger   net: cosmetic: Cl...
197
  		}
f8be7d659   Joe Hershberger   net: Improve the ...
198

68ceb29e7   wdenk   Add support for c...
199
200
  		inited = 1;
  	}
1203fccee   Joe Hershberger   net: cosmetic: Cl...
201
  	pkt = (uchar *)net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE;
e1902ac69   Joe Hershberger   net: cosmetic: ne...
202
  	memcpy(pkt, buf, len);
eedcd078f   wdenk   * Patch by Detlev...
203
204
  	ether = nc_ether;
  	ip = nc_ip;
1203fccee   Joe Hershberger   net: cosmetic: Cl...
205
  	net_send_udp_packet(ether, ip, nc_out_port, nc_in_port, len);
68ceb29e7   wdenk   Add support for c...
206

f8be7d659   Joe Hershberger   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   wdenk   Add support for c...
213
  }
6a38a5f3d   Joe Hershberger   net: cosmetic: Cl...
214
  static int nc_stdio_start(struct stdio_dev *dev)
68ceb29e7   wdenk   Add support for c...
215
  {
e827fec2b   Joe Hershberger   net: Allow netcon...
216
  	int retval;
eedcd078f   wdenk   * Patch by Detlev...
217

7f51898c1   Joe Hershberger   net: Make netcons...
218
219
  	nc_out_port = 6666; /* default port */
  	nc_in_port = nc_out_port;
eedcd078f   wdenk   * Patch by Detlev...
220

e827fec2b   Joe Hershberger   net: Allow netcon...
221
222
223
  	retval = refresh_settings_from_env();
  	if (retval != 0)
  		return retval;
eedcd078f   wdenk   * Patch by Detlev...
224

d7310c7e6   Joe Hershberger   net: Make sure Ne...
225
226
  	/*
  	 * Initialize the static IP settings and buffer pointers
bc0571fc1   Joe Hershberger   net: cosmetic: Fi...
227
  	 * incase we call net_send_udp_packet before net_loop
d7310c7e6   Joe Hershberger   net: Make sure Ne...
228
229
  	 */
  	net_init();
eedcd078f   wdenk   * Patch by Detlev...
230
  	return 0;
68ceb29e7   wdenk   Add support for c...
231
  }
6a38a5f3d   Joe Hershberger   net: cosmetic: Cl...
232
  static void nc_stdio_putc(struct stdio_dev *dev, char c)
68ceb29e7   wdenk   Add support for c...
233
234
235
236
  {
  	if (output_recursion)
  		return;
  	output_recursion = 1;
e1902ac69   Joe Hershberger   net: cosmetic: ne...
237
  	nc_send_packet(&c, 1);
68ceb29e7   wdenk   Add support for c...
238
239
240
  
  	output_recursion = 0;
  }
6a38a5f3d   Joe Hershberger   net: cosmetic: Cl...
241
  static void nc_stdio_puts(struct stdio_dev *dev, const char *s)
68ceb29e7   wdenk   Add support for c...
242
  {
b2323ea6f   wdenk   Auto-size RAM on ...
243
  	int len;
68ceb29e7   wdenk   Add support for c...
244
245
246
  	if (output_recursion)
  		return;
  	output_recursion = 1;
1a9845b4f   Michael Walle   netconsole: suppo...
247
248
  	len = strlen(s);
  	while (len) {
b41411954   Masahiro Yamada   linux/kernel.h: s...
249
  		int send_len = min(len, (int)sizeof(input_buffer));
1a9845b4f   Michael Walle   netconsole: suppo...
250
251
252
253
  		nc_send_packet(s, send_len);
  		len -= send_len;
  		s += send_len;
  	}
68ceb29e7   wdenk   Add support for c...
254
255
256
  
  	output_recursion = 0;
  }
6a38a5f3d   Joe Hershberger   net: cosmetic: Cl...
257
  static int nc_stdio_getc(struct stdio_dev *dev)
68ceb29e7   wdenk   Add support for c...
258
  {
b2323ea6f   wdenk   Auto-size RAM on ...
259
  	uchar c;
68ceb29e7   wdenk   Add support for c...
260
261
262
  	input_recursion = 1;
  
  	net_timeout = 0;	/* no timeout */
eedcd078f   wdenk   * Patch by Detlev...
263
  	while (!input_size)
bc0571fc1   Joe Hershberger   net: cosmetic: Fi...
264
  		net_loop(NETCONS);
68ceb29e7   wdenk   Add support for c...
265
266
  
  	input_recursion = 0;
b2323ea6f   wdenk   Auto-size RAM on ...
267
  	c = input_buffer[input_offset++];
e1902ac69   Joe Hershberger   net: cosmetic: ne...
268
269
  	if (input_offset >= sizeof(input_buffer))
  		input_offset -= sizeof(input_buffer);
eedcd078f   wdenk   * Patch by Detlev...
270
  	input_size--;
68ceb29e7   wdenk   Add support for c...
271

eedcd078f   wdenk   * Patch by Detlev...
272
  	return c;
68ceb29e7   wdenk   Add support for c...
273
  }
6a38a5f3d   Joe Hershberger   net: cosmetic: Cl...
274
  static int nc_stdio_tstc(struct stdio_dev *dev)
68ceb29e7   wdenk   Add support for c...
275
  {
c163e4367   Bernhard Nortmann   net: fix netconso...
276
277
278
  #ifdef CONFIG_DM_ETH
  	struct udevice *eth;
  #else
68ceb29e7   wdenk   Add support for c...
279
  	struct eth_device *eth;
c163e4367   Bernhard Nortmann   net: fix netconso...
280
  #endif
68ceb29e7   wdenk   Add support for c...
281
282
283
  
  	if (input_recursion)
  		return 0;
eedcd078f   wdenk   * Patch by Detlev...
284
  	if (input_size)
68ceb29e7   wdenk   Add support for c...
285
  		return 1;
e1902ac69   Joe Hershberger   net: cosmetic: ne...
286
  	eth = eth_get_dev();
c163e4367   Bernhard Nortmann   net: fix netconso...
287
  	if (eth_is_active(eth))
68ceb29e7   wdenk   Add support for c...
288
289
290
291
292
  		return 0;	/* inside net loop */
  
  	input_recursion = 1;
  
  	net_timeout = 1;
bc0571fc1   Joe Hershberger   net: cosmetic: Fi...
293
  	net_loop(NETCONS);	/* kind of poll */
68ceb29e7   wdenk   Add support for c...
294
295
  
  	input_recursion = 0;
eedcd078f   wdenk   * Patch by Detlev...
296
  	return input_size != 0;
68ceb29e7   wdenk   Add support for c...
297
  }
e1902ac69   Joe Hershberger   net: cosmetic: ne...
298
  int drv_nc_init(void)
68ceb29e7   wdenk   Add support for c...
299
  {
52cb4d4fb   Jean-Christophe PLAGNIOL-VILLARD   stdio/device: rew...
300
  	struct stdio_dev dev;
68ceb29e7   wdenk   Add support for c...
301
  	int rc;
e1902ac69   Joe Hershberger   net: cosmetic: ne...
302
  	memset(&dev, 0, sizeof(dev));
68ceb29e7   wdenk   Add support for c...
303

e1902ac69   Joe Hershberger   net: cosmetic: ne...
304
  	strcpy(dev.name, "nc");
1caf934a0   Bin Meng   video: Drop DEV_F...
305
  	dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
6a38a5f3d   Joe Hershberger   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   wdenk   Add support for c...
311

e1902ac69   Joe Hershberger   net: cosmetic: ne...
312
  	rc = stdio_register(&dev);
68ceb29e7   wdenk   Add support for c...
313
314
315
  
  	return (rc == 0) ? 1 : rc;
  }