1 #include <pkgconf/system.h>
3 #if !defined(CYGPKG_NET_FTPCLIENT)
4 #error "Configuration is missing: CYGPKG_NET_FTPCLIENT"
7 #if !defined(CYGPKG_COMPRESS_ZLIB)
8 #error "Configuration is missing: CYGPKG_COMPRESS_ZLIB"
11 #include <pkgconf/compress_zlib.h>
12 #if !defined(CYGSEM_COMPRESS_ZLIB_DEFLATE_MAKES_GZIP)
13 #error "Configuration is missing: CYGSEM_COMPRESS_ZLIB_DEFLATE_MAKES_GZIP"
17 #if !defined(CYGPKG_CRC)
18 #error "Configuration is missing: CYGPKG_CRC"
25 #include <ftpclient.h>
26 #include <cyg/compress/zlib.h>
28 #include <pkgconf/net.h>
29 #include <sys/param.h>
30 #include <sys/socket.h>
31 #include <sys/ioctl.h>
32 #include <sys/errno.h>
35 #include <netinet/in.h>
36 #include <netinet/ip.h>
37 #include <netinet/ip_icmp.h>
38 #include <net/route.h>
40 #include <cyg/infra/diag.h>
41 #include <cyg/kernel/kapi.h>
45 #include <arpa/inet.h>
51 #define FTP_SERV "192.168.1.125"
52 #define FTP_USER "george"
53 #define FTP_PASS "allen"
57 #ifdef CYGHWR_NET_DRIVER_ETH0
58 static struct bootp eth0_bootp_data;
59 static const char *eth0_name = "eth0";
61 #ifdef CYGHWR_NET_DRIVER_ETH1
62 static struct bootp eth1_bootp_data;
63 static const char *eth1_name = "eth1";
67 core_info_t test_core_info = {
68 .fence0 = KCORE_FENCE0_PAT,
69 .fence1 = KCORE_FENCE1_PAT,
70 .fence2 = KCORE_FENCE2_PAT,
71 .fence3 = KCORE_FENCE3_PAT,
72 .crash = KCORE_CRASH_PANIC,
73 .panicstr = "This is a panic string",
76 .physical_banks[0] = { 0x700000, 0x40000 },
77 .physical_banks[1] = { 0x740000, 0x40000 },
86 .dbatl[0] = 0xDEAD0000, .dbatu[0] = 0xDEAD1000,
87 .dbatl[1] = 0xDEAD0001, .dbatu[1] = 0xDEAD1001,
88 .dbatl[2] = 0xDEAD0002, .dbatu[2] = 0xDEAD1002,
89 .dbatl[3] = 0xDEAD0003, .dbatu[3] = 0xDEAD1003,
90 .dbatl[4] = 0xDEAD0004, .dbatu[4] = 0xDEAD1004,
91 .dbatl[5] = 0xDEAD0005, .dbatu[5] = 0xDEAD1005,
92 .dbatl[6] = 0xDEAD0006, .dbatu[6] = 0xDEAD1006,
93 .dbatl[7] = 0xDEAD2007, .dbatu[7] = 0xDEAD3007,
94 .ibatl[0] = 0xDEAD2000, .ibatu[0] = 0xDEAD3000,
95 .ibatl[1] = 0xDEAD2001, .ibatu[1] = 0xDEAD3001,
96 .ibatl[2] = 0xDEAD2002, .ibatu[2] = 0xDEAD3002,
97 .ibatl[3] = 0xDEAD2003, .ibatu[3] = 0xDEAD3003,
98 .ibatl[4] = 0xDEAD2004, .ibatu[4] = 0xDEAD3004,
99 .ibatl[5] = 0xDEAD2005, .ibatu[5] = 0xDEAD3005,
100 .ibatl[6] = 0xDEAD2006, .ibatu[6] = 0xDEAD3006,
101 .ibatl[7] = 0xDEAD2007, .ibatu[7] = 0xDEAD3007,
105 #define FTP_BUFSIZE 4096
108 char buf[FTP_BUFSIZE], *bufp;
112 int (*get_data)(char **ptr, void *param);
116 int _ftp_write_gz(char *buf, int len, void *priv)
118 struct ftp_data *dp = (struct ftp_data *)priv;
124 // Ugly hack - zlib needs a value for 'avail_in' at initialization
125 // time, even though we don't have anything ready yet
126 dp->stream.avail_in = 0;
129 while ((dp->len == 0) && (dp->src_len > 0)) {
130 // Has input buffer been exhausted?
131 if (dp->stream.avail_in == 0) {
132 dp->src_len = (*dp->get_data)(&src, dp->get_param);
133 dp->stream.next_in = src;
134 dp->stream.avail_in = dp->src_len;
136 // See if more data is available to be compressed
137 dp->stream.avail_out = FTP_BUFSIZE;
138 dp->stream.next_out = dp->buf;
139 err = deflate(&dp->stream, dp->src_len ? Z_NO_FLUSH : Z_FINISH);
140 dp->len = FTP_BUFSIZE - dp->stream.avail_out;
143 // Move up to 'len' bytes from internal buffer
148 memcpy(buf, dp->bufp, res);
154 struct _simple_get_data_param {
160 simple_get_data(char **ptr, void *param)
162 struct _simple_get_data_param *gp = (struct _simple_get_data_param *)param;
174 // Parse (scan/copy) network addresses. If the IP address contains
175 // a '/', then use that to determine the netmask and ignore the
179 parse_eth_addrs(char *desired_ip, char *desired_netmask,
180 char *ip, char *netmask, char *broadcast)
183 bool found_netmask = false;
184 int mask_size, mask, ip_addr;
186 // diag_printf("parse - ip: '%s', mask: '%s'\n", desired_ip, desired_netmask);
188 src = desired_ip; dst = ip;
191 // Do something with netmask
193 found_netmask = true;
196 mask_size = (mask_size * 10) + (*src++ - '0');
198 mask = 0xFFFFFFFF << (32-mask_size);
204 if (!found_netmask) {
205 if (!inet_aton(desired_netmask, (struct in_addr *)&mask)) {
206 diag_printf("Error: Invalid netmask '%s'\n", desired_netmask);
207 return false; // Illegal netmask
210 strcpy(netmask, inet_ntoa(*(struct in_addr *)&mask));
211 if (!inet_aton(ip, (struct in_addr *)&ip_addr)) {
212 diag_printf("Error: Invalid IP address '%s'\n", ip);
215 ip_addr = (ip_addr & mask) | ~mask;
216 strcpy(broadcast, inet_ntoa(*(struct in_addr *)&ip_addr));
217 // diag_printf("ip: '%s', netmask: '%s', broadcast: '%s'\n", ip, netmask, broadcast);
221 struct core_dump_param {
226 kcore_seg_t cpu_hdr, ram_hdr;
227 cpu_kcore_hdr_t cpu_info;
228 phys_ram_seg_t cpu_phys_segs[8];
231 #define ALIGN(v,n) ((((v)+((n)-1))/(n))*(n))
234 dump_core(char **ptr, void *param)
236 struct core_dump_param *dp = (struct core_dump_param *)param;
241 // File header (kcore_hdr_t)
243 *ptr = (char *)&dp->hdr;
244 return ALIGN(sizeof(dp->hdr), 8);
246 // CPU header (kcore_seg_t)
248 *ptr = (char *)&dp->cpu_hdr;
249 return ALIGN(sizeof(dp->cpu_hdr), 8);
251 // CPU info (cpu_kcore_hdr_t)
254 *ptr = (char *)&dp->cpu_info;
255 return sizeof(dp->cpu_info);
257 // Physical RAM segment descriptions (phys_ram_seg_t)
258 *ptr = (char *)&dp->cpu_phys_segs[dp->segno];
259 if (++dp->segno == dp->cp->nsegs) {
262 return sizeof(dp->cpu_phys_segs[0]);
264 // RAM header (kcore_seg_t)
266 *ptr = (char *)&dp->ram_hdr;
268 return ALIGN(sizeof(dp->ram_hdr), 8);
271 *ptr = (char *)dp->cpu_phys_segs[dp->segno].start;
272 len = dp->cpu_phys_segs[dp->segno].size;
273 if (++dp->segno == dp->cp->nsegs) {
281 diag_printf("Bad core dump phase: %d\n", dp->phase);
287 expand_file_name(char *file_name, char *path, char *ip)
289 char *fn = nvram_get("dump_name");
290 char *dp = file_name;
293 if (!fn) fn = "XPathOS.%i.core.gz";
294 if (!path) path = "/";
304 fn += 2; // Skip '%i'
316 do_core_dump(core_info_t *cp, char *ip)
318 struct core_dump_param cd;
319 // Caution - this can't be on the stack unless you increase the stack size!
320 static struct ftp_data dp;
322 unsigned long total_ram_size;
324 char *dump_ip, *dump_user, *dump_pass;
326 dump_ip = nvram_get("dump_server");
328 diag_printf("Can't dump: server IP missing in NVRAM\n");
331 dump_user = nvram_get("dump_user");
333 diag_printf("Can't dump: user name missing in NVRAM\n");
336 dump_pass = nvram_get("dump_pass");
338 diag_printf("Can't dump: password missing in NVRAM\n");
341 expand_file_name(file_name, nvram_get("dump_path"), ip);
343 // Fill in core dump structures
344 cd.hdr.c_midmag = KCORE_HDR_MAGIC;
345 cd.hdr.c_hdrsize = ALIGN(sizeof(cd.hdr), 8);
346 cd.hdr.c_seghdrsize = ALIGN(sizeof(cd.cpu_hdr), 8);
347 cd.hdr.c_nseg = cp->nsegs;
349 cd.cpu_hdr.c_midmag = KCORE_CPU_SEGMENT;
350 cd.cpu_hdr.c_size = sizeof(kcore_seg_t)+sizeof(cpu_kcore_hdr_t)+(cp->nsegs*sizeof(phys_ram_seg_t));
351 // Copy info from core-dump area
352 cd.cpu_info.pvr = cp->pvr;
353 cd.cpu_info.sdr1 = cp->sdr1;
354 for (i = 0; i < 8; i++) {
355 cd.cpu_info.sr[i] = cp->sr[i];
356 cd.cpu_info.dbatl[i] = cp->dbatl[i];
357 cd.cpu_info.dbatu[i] = cp->dbatu[i];
358 cd.cpu_info.ibatl[i] = cp->ibatl[i];
359 cd.cpu_info.ibatu[i] = cp->ibatu[i];
361 for (i = 0; i < 8; i++) {
362 cd.cpu_phys_segs[i].start = cp->physical_banks[i].base;
363 cd.cpu_phys_segs[i].size = cp->physical_banks[i].length;
367 cd.ram_hdr.c_midmag = KCORE_DATA_SEGMENT;
368 cd.ram_hdr.c_size = sizeof(kcore_seg_t)+total_ram_size;
374 dp.get_data = dump_core;
378 dp.stream.next_in = 0;
379 dp.stream.avail_in = 0x1000;
380 dp.stream.next_out = dp.buf;
381 dp.stream.avail_out = FTP_BUFSIZE;
382 dp.stream.zalloc = (alloc_func)0;
383 dp.stream.zfree = (free_func)0;
384 dp.stream.opaque = (voidpf)0;
386 err = deflateInit(&dp.stream, Z_DEFAULT_COMPRESSION);
387 diag_printf("err = %d\n", err);
389 diag_printf("... dumping core as %s\n", file_name);
391 wlen = ftp_put_var(dump_ip, dump_user, dump_pass, file_name,
392 _ftp_write_gz, &dp, ftpclient_printf);
393 diag_printf("res = %d\n", wlen);
394 deflateEnd(&dp.stream);
398 scan_args(char *cmdline, int *argc, char **argv, char **alt_cmdline)
403 argv[indx++] = "secondary-load";
404 *alt_cmdline = (char *)0;
406 // Skip over any white space
407 while (*cp && (*cp == ' ')) cp++;
409 // Check for -- break
410 if ((cp[0] == '-') && (cp[1] == '-')) {
411 // End of normal list
413 while (*cp && (*cp == ' ')) cp++;
432 loader_main(char *cmdline)
437 char *argv[MAX_ARGV], *alt_cmdline;
438 bool force_dump = false;
439 bool quick_boot = false;
440 bool verbose = false;
441 char *boot_info = (char *)NULL;
442 // Caution - this can't be on the stack unless you increase the stack size!
443 static struct ftp_data dp;
444 struct _simple_get_data_param gp;
445 #ifdef CYGHWR_NET_DRIVER_ETH0
446 char eth0_ip[32], eth0_netmask[32], eth0_broadcast[32];
448 #ifdef CYGHWR_NET_DRIVER_ETH1
449 char eth1_ip[32], eth1_netmask[32], eth1_broadcast[32];
453 scan_args(cmdline, &argc, argv, &alt_cmdline);
455 i = getopt(argc, argv, "fqv");
468 diag_printf("Invalid return from getopt: %d\n", i);
472 boot_info = argv[optind];
475 if (!(eth_gateway = nvram_get("net_gateway"))) {
476 diag_printf("Error: need network gateway\n");
479 #ifdef CYGHWR_NET_DRIVER_ETH0
480 if (!parse_eth_addrs(nvram_get("net0_ip"), nvram_get("net0_mask"),
481 eth0_ip, eth0_netmask, eth0_broadcast)) {
482 diag_printf("Can't set up ethernet 'net0' - I give up!\n");
485 build_bootp_record(ð0_bootp_data,
492 show_bootp(eth0_name, ð0_bootp_data);
493 if (!init_net(eth0_name, ð0_bootp_data)) {
494 diag_printf("Network initialization failed for eth0\n");
497 #ifdef CYGHWR_NET_DRIVER_ETH1
498 if (!parse_eth_addrs(nvram_get("net1_ip"), nvram_get("net1_mask"),
499 eth1_ip, eth1_netmask, eth1_broadcast)) {
500 diag_printf("Can't set up ethernet 'net1' - I give up!\n");
503 build_bootp_record(ð1_bootp_data,
510 show_bootp(eth1_name, ð1_bootp_data);
511 if (!init_net(eth1_name, ð1_bootp_data)) {
512 diag_printf("Network initialization failed for eth1\n");
518 // See if the 'core dump' page contains an indication that a
519 // dump should be taken
522 do_core_dump(&test_core_info, eth0_ip);
527 len = ftp_get(FTP_SERV, FTP_USER, FTP_PASS, "TEST.dat",
528 (char *)0x200000, 0x100000, ftpclient_printf);
529 diag_printf("res = %d\n", len);
530 if (len <= 0) exit(0);
531 wlen = ftp_put(FTP_SERV, FTP_USER, FTP_PASS, "TEST2.dat",
532 (char *)0x200000, len, ftpclient_printf);
533 diag_printf("res = %d\n", wlen);
535 // Set up to compress data
536 gp.ptr = (char *)0x200000;
539 dp.get_data = simple_get_data;
543 dp.stream.next_in = 0;
544 dp.stream.avail_in = 0x1000;
545 dp.stream.next_out = dp.buf;
546 dp.stream.avail_out = FTP_BUFSIZE;
547 dp.stream.zalloc = (alloc_func)0;
548 dp.stream.zfree = (free_func)0;
549 dp.stream.opaque = (voidpf)0;
551 err = deflateInit(&dp.stream, Z_DEFAULT_COMPRESSION);
552 diag_printf("err = %d\n", err);
553 wlen = ftp_put_var(FTP_SERV, FTP_USER, FTP_PASS, "TEST3.dat.gz",
554 _ftp_write_gz, &dp, ftpclient_printf);
555 diag_printf("res = %d\n", wlen);
556 deflateEnd(&dp.stream);
564 return (loader_main("-f -t test joe -- junk"));