summaryrefslogtreecommitdiff
path: root/com32/sysdump
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-02-07 16:26:40 -0800
committerH. Peter Anvin <hpa@zytor.com>2010-02-07 16:26:40 -0800
commit9bb975b60999ddd94610b2d66ac7b2b9bfaaea20 (patch)
treebabfba3570be52426078b00330dc05d6dfa35d0d /com32/sysdump
parent88f5f9b480f036ef9da9cf9deb41935c9ad9743c (diff)
downloadsyslinux-9bb975b60999ddd94610b2d66ac7b2b9bfaaea20.tar.gz
sysdump: actually make the new backend system worksyslinux-3.85-pre8
With these changes, both TFTP and Ymodem seem to actually work. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'com32/sysdump')
-rw-r--r--com32/sysdump/backend.h4
-rw-r--r--com32/sysdump/be_tftp.c1
-rw-r--r--com32/sysdump/be_ymodem.c40
-rw-r--r--com32/sysdump/cpio.c10
-rw-r--r--com32/sysdump/main.c8
-rw-r--r--com32/sysdump/serial.c30
-rw-r--r--com32/sysdump/zout.c36
7 files changed, 72 insertions, 57 deletions
diff --git a/com32/sysdump/backend.h b/com32/sysdump/backend.h
index 21a9ff83..0926c8d5 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 79642385..07fdb084 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 b36bd039..fa2cc602 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 dfc7c946..81d0d4be 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 19245061..f4b5ad92 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 71b3067a..03f6403a 100644
--- a/com32/sysdump/serial.c
+++ b/com32/sysdump/serial.c
@@ -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 */
}
diff --git a/com32/sysdump/zout.c b/com32/sysdump/zout.c
index 61dd514d..0334d80a 100644
--- a/com32/sysdump/zout.c
+++ b/com32/sysdump/zout.c
@@ -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;
}