From: H. Peter Anvin Date: Mon, 8 Feb 2010 00:26:40 +0000 (-0800) Subject: sysdump: actually make the new backend system work X-Git-Tag: syslinux-3.85-pre8^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9bb975b60999ddd94610b2d66ac7b2b9bfaaea20;p=platform%2Fupstream%2Fsyslinux.git sysdump: actually make the new backend system work With these changes, both TFTP and Ymodem seem to actually work. Signed-off-by: H. Peter Anvin --- diff --git a/com32/sysdump/backend.h b/com32/sysdump/backend.h index 21a9ff8..0926c8d 100644 --- a/com32/sysdump/backend.h +++ b/com32/sysdump/backend.h @@ -19,6 +19,8 @@ struct backend { size_t zbytes; const char **argv; + uint32_t now; + int (*write)(struct backend *); z_stream zstream; @@ -32,9 +34,9 @@ int write_data(struct backend *be, const void *buf, size_t len); int flush_data(struct backend *be); /* cpio.c */ +#define cpio_init init_data int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen, const char *filename); -int cpio_init(struct backend *be, const char *argv[]); int cpio_mkdir(struct backend *be, const char *filename); int cpio_writefile(struct backend *be, const char *filename, const void *data, size_t len); diff --git a/com32/sysdump/be_tftp.c b/com32/sysdump/be_tftp.c index 7964238..07fdb08 100644 --- a/com32/sysdump/be_tftp.c +++ b/com32/sysdump/be_tftp.c @@ -126,6 +126,7 @@ static int be_tftp_write(struct backend *be) *((uint16_t *)(buffer+2)) = htons(++tftp.seq); memcpy(buffer+4, data, chunk); data += chunk; + len -= chunk; if (send_ack_packet(&tftp, buffer, chunk+4)) return -1; diff --git a/com32/sysdump/be_ymodem.c b/com32/sysdump/be_ymodem.c index b36bd03..fa2cc60 100644 --- a/com32/sysdump/be_ymodem.c +++ b/com32/sysdump/be_ymodem.c @@ -19,7 +19,7 @@ enum { struct ymodem_state { struct serial_if serial; - uint16_t seq; + unsigned int seq, blocks; }; /* @@ -75,7 +75,7 @@ static void send_ack(struct ymodem_state *ym, const uint8_t *blk, static void send_ack_blk(struct ymodem_state *ym, uint8_t *blk) { - printf("Sending block %u...\r", ym->seq); + printf("Sending block %u/%u...\r", ym->seq, ym->blocks); blk[0] = STX; blk[1] = ym->seq++; @@ -106,13 +106,24 @@ static int be_ymodem_write(struct backend *be) struct ymodem_state ym; const char *buf; size_t len, chunk; + const char ymodem_banner[] = "Now begin Ymodem download...\r\n"; + + buf = be->outbuf; + len = be->zbytes; + + putchar('\n'); ym.seq = 0; + ym.blocks = (len+1023)/1024; /* Initialize serial port */ if (serial_init(&ym.serial, &be->argv[1])) return -1; + /* Write banner */ + printf("Writing banner...\n"); + serial_write(&ym.serial, ymodem_banner, sizeof ymodem_banner-1); + /* Wait for initial handshake */ printf("Waiting for handshake...\n"); do { @@ -120,20 +131,20 @@ static int be_ymodem_write(struct backend *be) } while (ack_buf != 'C'); /* Send filename block */ - snprintf((char *)blk_buf+3, 1024, "%s%c%zu", be->argv[0], 0, be->zbytes); + memset(blk_buf, 0, sizeof blk_buf); + snprintf((char *)blk_buf+3, 1024, "%s%c%zu 0%o 0644", + be->argv[0], 0, be->zbytes, be->now); send_ack_blk(&ym, blk_buf); - buf = be->outbuf; - len = be->zbytes; - while (len) { chunk = len < 1024 ? len : 1024; memcpy(blk_buf+3, buf, chunk); if (chunk < 1024) - memset(blk_buf+3+1024-chunk, 0x1a, 1024-chunk); + memset(blk_buf+3+chunk, 0x1a, 1024-chunk); send_ack_blk(&ym, blk_buf); + buf += chunk; len -= chunk; } @@ -147,17 +158,10 @@ static int be_ymodem_write(struct backend *be) ym.seq = 0; printf("Sending batch termination block...\n"); - memset(blk_buf+3, 0, 128); - blk_buf[0] = SOH; - blk_buf[1] = 0; - blk_buf[2] = 0xff; - add_crc16(blk_buf + 3, 128); - serial_write(&ym.serial, blk_buf, 128 + 5); - /* - * rb doesn't seem to ack the EOT for an end batch transfer, - * contrary to spec. - */ - printf("Done.\n"); + memset(blk_buf+3, 0, 1024); + send_ack_blk(&ym, blk_buf); + + printf("Cleaning up... \n"); serial_cleanup(&ym.serial); return 0; diff --git a/com32/sysdump/cpio.c b/com32/sysdump/cpio.c index dfc7c94..81d0d4b 100644 --- a/com32/sysdump/cpio.c +++ b/com32/sysdump/cpio.c @@ -12,8 +12,6 @@ #include "backend.h" #include "ctime.h" -static uint32_t now; - int cpio_pad(struct backend *be) { static char pad[4]; /* Up to 4 zero bytes */ @@ -40,7 +38,7 @@ int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen, 0, /* c_uid */ 0, /* c_gid */ 1, /* c_nlink */ - now, /* c_mtime */ + be->now, /* c_mtime */ datalen, /* c_filesize */ 0, /* c_maj */ 0, /* c_min */ @@ -54,12 +52,6 @@ int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen, return rv; } -int cpio_init(struct backend *be, const char *argv[]) -{ - now = posix_time(); - return init_data(be, argv); -} - int cpio_mkdir(struct backend *be, const char *filename) { return cpio_hdr(be, MODE_DIR, 0, filename); diff --git a/com32/sysdump/main.c b/com32/sysdump/main.c index 1924506..f4b5ad9 100644 --- a/com32/sysdump/main.c +++ b/com32/sysdump/main.c @@ -24,6 +24,7 @@ #include "sysdump.h" const char program[] = "sysdump"; +const char version[] = "SYSDUMP " VERSION_STR " " DATE "\n"; __noreturn die(const char *msg) { @@ -33,8 +34,6 @@ __noreturn die(const char *msg) static void dump_all(struct backend *be, const char *argv[]) { - static const char version[] = "SYSDUMP " VERSION_STR " " DATE "\n"; - cpio_init(be, argv); cpio_writefile(be, "sysdump", version, sizeof version); @@ -47,9 +46,7 @@ static void dump_all(struct backend *be, const char *argv[]) dump_vesa_tables(be); cpio_close(be); - printf("Uploading data... "); flush_data(be); - printf("done.\n"); } static struct backend *backends[] = @@ -75,6 +72,7 @@ int main(int argc, char *argv[]) struct backend **bep, *be; openconsole(&dev_null_r, &dev_stdcon_w); + fputs(version, stdout); if (argc < 2) usage(); @@ -90,6 +88,8 @@ int main(int argc, char *argv[]) /* Do this as early as possible */ snapshot_lowmem(); + printf("Backend: %s\n", be->name); + /* Do the actual data dump */ dump_all(be, (const char **)argv + 2); diff --git a/com32/sysdump/serial.c b/com32/sysdump/serial.c index 71b3067..03f6403 100644 --- a/com32/sysdump/serial.c +++ b/com32/sysdump/serial.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "serial.h" @@ -28,8 +29,13 @@ int serial_init(struct serial_if *sif, const char *argv[]) uint8_t dll, dlm, lcr; port = strtoul(argv[0], NULL, 0); - if (port <= 3) - port = *(uint16_t *)(0x400 + port*2); + if (port <= 3) { + uint16_t addr = ((uint16_t *)0x400)[port]; + printf("Serial port %u is at 0x%04x\n", port, addr); + port = addr; + } + + sif->port = port; if (argv[1]) speed = strtoul(argv[1], NULL, 0); @@ -38,12 +44,14 @@ int serial_init(struct serial_if *sif, const char *argv[]) divisor = 115200/speed; + cli(); /* Just in case... */ + /* Save old register settings */ sif->old.lcr = inb(port + LCR); sif->old.mcr = inb(port + MCR); sif->old.iir = inb(port + IIR); - /* Set 115200n81 */ + /* Set speed */ outb(0x83, port + LCR); /* Enable divisor access */ sif->old.dll = inb(port + DLL); sif->old.dlm = inb(port + DLM); @@ -54,17 +62,21 @@ int serial_init(struct serial_if *sif, const char *argv[]) dll = inb(port + DLL); dlm = inb(port + DLM); lcr = inb(port + LCR); - outb(0x03, port + LCR); + outb(0x03, port + LCR); /* Enable data access, n81 */ (void)inb(port + IER); /* Synchronize */ sif->old.ier = inb(port + IER); + /* Disable interrupts */ + outb(0, port + IER); + + sti(); + if (dll != (uint8_t)divisor || dlm != (uint8_t)(divisor >> 8) || - lcr != 0x83) + lcr != 0x83) { + printf("No serial port detected!\n"); return -1; /* This doesn't look like a serial port */ - - /* Disable interrupts */ - outb(0, port + IER); + } /* Enable 16550A FIFOs if available */ outb(0x41, port + FCR); /* Enable FIFO */ @@ -119,6 +131,6 @@ void serial_cleanup(struct serial_if *sif) (void)inb(port + IER); outb(sif->old.mcr, port + MCR); outb(sif->old.ier, port + IER); - if ((sif->old.iir & 0xc0) != 0xc0) + if (sif->old.iir < 0xc0) outb(0x00, port + FCR); /* Disable FIFOs */ } diff --git a/com32/sysdump/zout.c b/com32/sysdump/zout.c index 61dd514..0334d80 100644 --- a/com32/sysdump/zout.c +++ b/com32/sysdump/zout.c @@ -9,23 +9,19 @@ #include #include #include "backend.h" +#include "ctime.h" #define ALLOC_CHUNK 65536 int init_data(struct backend *be, const char *argv[]) { + be->now = posix_time(); be->argv = argv; - be->alloc = ALLOC_CHUNK; - be->outbuf = malloc(ALLOC_CHUNK); - if (!be->outbuf) - return -1; - memset(&be->zstream, 0, sizeof be->zstream); - be->zstream.next_out = (void *)be->outbuf; - be->zstream.avail_out = ALLOC_CHUNK; - + be->zstream.next_out = be->outbuf = NULL; + be->zstream.avail_out = be->alloc = 0; be->dbytes = be->zbytes = 0; /* Initialize a gzip data stream */ @@ -39,20 +35,22 @@ int init_data(struct backend *be, const char *argv[]) static int do_deflate(struct backend *be, int flush) { int rv; + char *buf; + + while (1) { + rv = deflate(&be->zstream, flush); + be->zbytes = be->alloc - be->zstream.avail_out; + if (be->zstream.avail_out) + return rv; /* Not an issue of output space... */ - rv = deflate(&be->zstream, flush); - be->zbytes = be->alloc - be->zstream.avail_out; - if (be->zstream.avail_out == 0) { - char *buf; buf = realloc(be->outbuf, be->alloc + ALLOC_CHUNK); if (!buf) return Z_MEM_ERROR; be->outbuf = buf; + be->alloc += ALLOC_CHUNK; be->zstream.next_out = (void *)(buf + be->zbytes); be->zstream.avail_out = be->alloc - be->zbytes; } - - return rv; } @@ -67,8 +65,10 @@ int write_data(struct backend *be, const void *buf, size_t len) while (be->zstream.avail_in) { rv = do_deflate(be, Z_NO_FLUSH); - if (rv < 0) + if (rv < 0) { + printf("do_deflate returned %d\n", rv); return -1; + } } return 0; } @@ -78,17 +78,21 @@ int flush_data(struct backend *be) { int rv = Z_OK; - while (rv == Z_OK) { + while (rv != Z_STREAM_END) { rv = do_deflate(be, Z_FINISH); if (rv < 0) return -1; } + printf("Uploading data, %u bytes... ", be->zbytes); + if (be->write(be)) return -1; free(be->outbuf); be->outbuf = NULL; be->dbytes = be->zbytes = be->alloc = 0; + + printf("done.\n"); return 0; }