sysdump: actually make the new backend system work syslinux-3.85-pre8
authorH. Peter Anvin <hpa@zytor.com>
Mon, 8 Feb 2010 00:26:40 +0000 (16:26 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Mon, 8 Feb 2010 00:26:40 +0000 (16:26 -0800)
With these changes, both TFTP and Ymodem seem to actually work.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
com32/sysdump/backend.h
com32/sysdump/be_tftp.c
com32/sysdump/be_ymodem.c
com32/sysdump/cpio.c
com32/sysdump/main.c
com32/sysdump/serial.c
com32/sysdump/zout.c

index 21a9ff8..0926c8d 100644 (file)
@@ -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);
index 7964238..07fdb08 100644 (file)
@@ -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;
index b36bd03..fa2cc60 100644 (file)
@@ -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;
index dfc7c94..81d0d4b 100644 (file)
@@ -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);
index 1924506..f4b5ad9 100644 (file)
@@ -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);
 
index 71b3067..03f6403 100644 (file)
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/io.h>
+#include <sys/cpu.h>
 
 #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 */
 }
index 61dd514..0334d80 100644 (file)
@@ -9,23 +9,19 @@
 #include <stdbool.h>
 #include <zlib.h>
 #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;
 }