summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--com32/sysdump/backend.h30
-rw-r--r--com32/sysdump/be_null.c30
-rw-r--r--com32/sysdump/be_tftp.c82
-rw-r--r--com32/sysdump/be_ymodem.c116
-rw-r--r--com32/sysdump/cpio.c17
-rw-r--r--com32/sysdump/dmi.c8
-rw-r--r--com32/sysdump/main.c17
-rw-r--r--com32/sysdump/memmap.c2
-rw-r--r--com32/sysdump/serial.c2
-rw-r--r--com32/sysdump/zout.c72
10 files changed, 183 insertions, 193 deletions
diff --git a/com32/sysdump/backend.h b/com32/sysdump/backend.h
index 0be80c63..21a9ff83 100644
--- a/com32/sysdump/backend.h
+++ b/com32/sysdump/backend.h
@@ -15,41 +15,26 @@ struct backend {
const char *helpmsg;
int minargs;
- unsigned int blocksize;
- unsigned int flags;
-
size_t dbytes;
size_t zbytes;
+ const char **argv;
- int (*open)(struct backend *, const char *argv[], size_t len);
- int (*write)(struct backend *, const char *buf, size_t len);
+ int (*write)(struct backend *);
z_stream zstream;
char *outbuf;
-
- union {
- struct {
- uint32_t my_ip;
- uint32_t srv_ip;
- uint16_t my_port;
- uint16_t srv_port;
- uint16_t seq;
- } tftp;
- struct {
- struct serial_if serial;
- uint16_t seq;
- } ymodem;
- };
+ size_t alloc;
};
/* zout.c */
-int init_data(struct backend *be, const char *argv[], size_t len);
-int write_data(struct backend *be, const void *buf, size_t len, bool flush);
+int init_data(struct backend *be, const char *argv[]);
+int write_data(struct backend *be, const void *buf, size_t len);
+int flush_data(struct backend *be);
/* cpio.c */
int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen,
const char *filename);
-int cpio_init(struct backend *be, const char *argv[], size_t len);
+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);
@@ -63,6 +48,5 @@ struct backend *get_backend(const char *name);
/* backends */
extern struct backend be_tftp;
extern struct backend be_ymodem;
-extern struct backend be_null;
#endif /* BACKEND_H */
diff --git a/com32/sysdump/be_null.c b/com32/sysdump/be_null.c
deleted file mode 100644
index 4aab99ce..00000000
--- a/com32/sysdump/be_null.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Null data output backend
- */
-
-#include "backend.h"
-
-static int be_null_open(struct backend *be, const char *argv[], size_t len)
-{
- (void)be;
- (void)argv;
- (void)len;
- return 0;
-}
-
-static int be_null_write(struct backend *be, const char *buf, size_t len)
-{
- (void)be;
- (void)buf;
- (void)len;
- return 0;
-}
-
-struct backend be_null = {
- .name = "null",
- .helpmsg = "",
- .minargs = 0,
- .blocksize = 32768, /* arbitrary */
- .open = be_null_open,
- .write = be_null_write,
-};
diff --git a/com32/sysdump/be_tftp.c b/com32/sysdump/be_tftp.c
index e9a98873..79642385 100644
--- a/com32/sysdump/be_tftp.c
+++ b/com32/sysdump/be_tftp.c
@@ -18,9 +18,16 @@ enum tftp_opcode {
TFTP_ERROR = 5,
};
-static uint16_t local_port = 0x4000;
+struct tftp_state {
+ uint32_t my_ip;
+ uint32_t srv_ip;
+ uint16_t my_port;
+ uint16_t srv_port;
+ uint16_t seq;
+};
-static int send_ack_packet(struct backend *be, const void *pkt, size_t len)
+static int send_ack_packet(struct tftp_state *tftp,
+ const void *pkt, size_t len)
{
com32sys_t ireg, oreg;
t_PXENV_UDP_WRITE *uw = __com32.cs_bounce;
@@ -38,9 +45,9 @@ static int send_ack_packet(struct backend *be, const void *pkt, size_t len)
for (timeout = timeouts ; *timeout ; timeout++) {
memset(uw, 0, sizeof uw);
memcpy(uw+1, pkt, len);
- uw->ip = be->tftp.srv_ip;
- uw->src_port = be->tftp.my_port;
- uw->dst_port = be->tftp.srv_port ? be->tftp.srv_port : htons(69);
+ uw->ip = tftp->srv_ip;
+ uw->src_port = tftp->my_port;
+ uw->dst_port = tftp->srv_port ? tftp->srv_port : htons(69);
uw->buffer_size = len;
uw->buffer = FAR_PTR(uw+1);
@@ -54,10 +61,10 @@ static int send_ack_packet(struct backend *be, const void *pkt, size_t len)
do {
memset(ur, 0, sizeof ur);
- ur->src_ip = be->tftp.srv_ip;
- ur->dest_ip = be->tftp.my_ip;
- ur->s_port = be->tftp.srv_port;
- ur->d_port = be->tftp.my_port;
+ ur->src_ip = tftp->srv_ip;
+ ur->dest_ip = tftp->my_ip;
+ ur->s_port = tftp->srv_port;
+ ur->d_port = tftp->my_port;
ur->buffer_size = __com32.cs_bounce_size - sizeof *ur;
ur->buffer = FAR_PTR(ur+1);
@@ -68,13 +75,13 @@ static int send_ack_packet(struct backend *be, const void *pkt, size_t len)
if (!(oreg.eflags.l & EFLAGS_CF) &&
ur->status == PXENV_STATUS_SUCCESS &&
- be->tftp.srv_ip == ur->src_ip &&
- (be->tftp.srv_port == 0 ||
- be->tftp.srv_port == ur->s_port)) {
+ tftp->srv_ip == ur->src_ip &&
+ (tftp->srv_port == 0 ||
+ tftp->srv_port == ur->s_port)) {
uint16_t *xb = (uint16_t *)(ur+1);
if (ntohs(xb[0]) == TFTP_ACK &&
- ntohs(xb[1]) == be->tftp.seq) {
- be->tftp.srv_port = ur->s_port;
+ ntohs(xb[1]) == tftp->seq) {
+ tftp->srv_port = ur->s_port;
return 0; /* All good! */
} else if (ntohs(xb[1]) == TFTP_ERROR) {
return -1; /* All bad! */
@@ -86,47 +93,50 @@ static int send_ack_packet(struct backend *be, const void *pkt, size_t len)
return -1; /* No success... */
}
-static int be_tftp_open(struct backend *be, const char *argv[], size_t len)
+static int be_tftp_write(struct backend *be)
{
+ static uint16_t local_port = 0x4000;
+ struct tftp_state tftp;
char buffer[512+4+6];
int nlen;
const union syslinux_derivative_info *sdi =
syslinux_derivative_info();
+ const char *data = be->outbuf;
+ size_t len = be->zbytes;
+ size_t chunk;
- (void)len;
-
- be->tftp.my_ip = sdi->pxe.myip;
- be->tftp.my_port = htons(local_port++);
- be->tftp.srv_ip = pxe_dns(argv[1]);
- be->tftp.srv_port = 0;
- be->tftp.seq = 0;
+ tftp.my_ip = sdi->pxe.myip;
+ tftp.my_port = htons(local_port++);
+ tftp.srv_ip = pxe_dns(be->argv[1]);
+ tftp.srv_port = 0;
+ tftp.seq = 0;
buffer[0] = 0;
buffer[1] = TFTP_WRQ;
- nlen = strlcpy(buffer+2, argv[0], 512);
+ nlen = strlcpy(buffer+2, be->argv[0], 512);
memcpy(buffer+3+nlen, "octet", 6);
- return send_ack_packet(be, buffer, 2+nlen+1+6);
-}
+ if (send_ack_packet(&tftp, buffer, 2+nlen+1+6))
+ return -1;
-static int be_tftp_write(struct backend *be, const char *buf, size_t len)
-{
- char buffer[512+4];
+ do {
+ chunk = len >= 512 ? 512 : len;
- buffer[0] = 0;
- buffer[1] = TFTP_DATA;
- *((uint16_t *)(buffer+2)) = htons(++be->tftp.seq);
- memcpy(buffer+4, buf, len);
+ buffer[1] = TFTP_DATA;
+ *((uint16_t *)(buffer+2)) = htons(++tftp.seq);
+ memcpy(buffer+4, data, chunk);
+ data += chunk;
+
+ if (send_ack_packet(&tftp, buffer, chunk+4))
+ return -1;
+ } while (chunk == 512);
- return send_ack_packet(be, buffer, len+4);
+ return 0;
}
struct backend be_tftp = {
.name = "tftp",
.helpmsg = "filename tftp_server",
.minargs = 2,
- .blocksize = 512,
- .flags = 0,
- .open = be_tftp_open,
.write = be_tftp_write,
};
diff --git a/com32/sysdump/be_ymodem.c b/com32/sysdump/be_ymodem.c
index 632758d9..b36bd039 100644
--- a/com32/sysdump/be_ymodem.c
+++ b/com32/sysdump/be_ymodem.c
@@ -17,6 +17,11 @@ enum {
CAN = 0x18,
};
+struct ymodem_state {
+ struct serial_if serial;
+ uint16_t seq;
+};
+
/*
* Append a CRC16 to a block
*/
@@ -65,101 +70,102 @@ static void add_crc16(uint8_t * blk, int len)
*blk = crc;
}
-static void send_ack(struct backend *be, const uint8_t *blk, size_t bytes);
+static void send_ack(struct ymodem_state *ym, const uint8_t *blk,
+ size_t bytes);
-static void send_ack_blk(struct backend *be, uint8_t *blk)
+static void send_ack_blk(struct ymodem_state *ym, uint8_t *blk)
{
- printf("Sending block %u...\r", be->ymodem.seq);
+ printf("Sending block %u...\r", ym->seq);
blk[0] = STX;
- blk[1] = be->ymodem.seq++;
+ blk[1] = ym->seq++;
blk[2] = ~blk[1];
add_crc16(blk+3, 1024);
- send_ack(be, blk, 1024+5);
+ send_ack(ym, blk, 1024+5);
}
-static void send_ack(struct backend *be, const uint8_t *blk, size_t bytes)
+static void send_ack(struct ymodem_state *ym, const uint8_t *blk, size_t bytes)
{
uint8_t ack_buf;
- serial_write(&be->ymodem.serial, blk, bytes);
+ serial_write(&ym->serial, blk, bytes);
do {
do {
- serial_read(&be->ymodem.serial, &ack_buf, 1);
+ serial_read(&ym->serial, &ack_buf, 1);
} while (ack_buf != ACK && ack_buf != NAK);
} while (ack_buf == NAK);
}
-static int be_ymodem_open(struct backend *be, const char *argv[], size_t len)
+static int be_ymodem_write(struct backend *be)
{
- uint8_t ack_buf, blk_buf[1024 + 5];
+ static const uint8_t eot_buf = EOT;
+ uint8_t ack_buf;
+ uint8_t blk_buf[1024 + 5];
+ struct ymodem_state ym;
+ const char *buf;
+ size_t len, chunk;
- be->ymodem.seq = 0;
+ ym.seq = 0;
/* Initialize serial port */
- if (serial_init(&be->ymodem.serial, argv+1))
+ if (serial_init(&ym.serial, &be->argv[1]))
return -1;
-
+
/* Wait for initial handshake */
printf("Waiting for handshake...\n");
do {
- serial_read(&be->ymodem.serial, &ack_buf, 1);
+ serial_read(&ym.serial, &ack_buf, 1);
} while (ack_buf != 'C');
- snprintf((char *)blk_buf+3, 1024, "%s%c%zu", argv[0], 0, len);
- send_ack_blk(be, blk_buf);
+ /* Send filename block */
+ snprintf((char *)blk_buf+3, 1024, "%s%c%zu", be->argv[0], 0, be->zbytes);
+ send_ack_blk(&ym, blk_buf);
- return 0;
-}
-
-static int be_ymodem_write(struct backend *be, const char *buf, size_t len)
-{
- static const uint8_t eot_buf = EOT;
- uint8_t ack_buf;
- uint8_t blk_buf[1024 + 5];
-
- memcpy(blk_buf+3, buf, len);
- if (len < 1024)
- memset(blk_buf+3+1024-len, 0x1a, 1024-len);
+ buf = be->outbuf;
+ len = be->zbytes;
- send_ack_blk(be, blk_buf);
+ while (len) {
+ chunk = len < 1024 ? len : 1024;
- if (len < 1024) {
- printf("\nSending EOT...\n");
- send_ack(be, &eot_buf, 1);
+ memcpy(blk_buf+3, buf, chunk);
+ if (chunk < 1024)
+ memset(blk_buf+3+1024-chunk, 0x1a, 1024-chunk);
- printf("Waiting for handshake...\n");
- do {
- serial_read(&be->ymodem.serial, &ack_buf, 1);
- } while (ack_buf != 'C');
- be->ymodem.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(&be->ymodem.serial, blk_buf, 128 + 5);
- /*
- * rb doesn't seem to ack the EOT for an end batch transfer,
- * contrary to spec.
- */
- printf("Done.\n");
- serial_cleanup(&be->ymodem.serial);
+ send_ack_blk(&ym, blk_buf);
+ len -= chunk;
}
+ printf("\nSending EOT...\n");
+ send_ack(&ym, &eot_buf, 1);
+
+ printf("Waiting for handshake...\n");
+ do {
+ serial_read(&ym.serial, &ack_buf, 1);
+ } while (ack_buf != 'C');
+ 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");
+ serial_cleanup(&ym.serial);
+
return 0;
-}
+}
struct backend be_ymodem = {
.name = "ymodem",
.helpmsg = "filename port [speed]",
.minargs = 2,
- .blocksize = 1024,
- .flags = BE_NEEDLEN,
- .open = be_ymodem_open,
.write = be_ymodem_write,
};
diff --git a/com32/sysdump/cpio.c b/com32/sysdump/cpio.c
index 30e3d496..dfc7c946 100644
--- a/com32/sysdump/cpio.c
+++ b/com32/sysdump/cpio.c
@@ -18,7 +18,7 @@ int cpio_pad(struct backend *be)
{
static char pad[4]; /* Up to 4 zero bytes */
if (be->dbytes & 3)
- return write_data(be, pad, -be->dbytes & 3, false);
+ return write_data(be, pad, -be->dbytes & 3);
else
return 0;
}
@@ -48,16 +48,16 @@ int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen,
0, /* c_rmin */
nlen, /* c_namesize */
0); /* c_chksum */
- rv |= write_data(be, hdr, 6+13*8, false);
- rv |= write_data(be, filename, nlen, false);
+ rv |= write_data(be, hdr, 6+13*8);
+ rv |= write_data(be, filename, nlen);
rv |= cpio_pad(be);
return rv;
}
-int cpio_init(struct backend *be, const char *argv[], size_t len)
+int cpio_init(struct backend *be, const char *argv[])
{
now = posix_time();
- return init_data(be, argv, len);
+ return init_data(be, argv);
}
int cpio_mkdir(struct backend *be, const char *filename)
@@ -71,7 +71,7 @@ int cpio_writefile(struct backend *be, const char *filename,
int rv;
rv = cpio_hdr(be, MODE_FILE, len, filename);
- rv |= write_data(be, data, len, false);
+ rv |= write_data(be, data, len);
rv |= cpio_pad(be);
return rv;
@@ -79,8 +79,5 @@ int cpio_writefile(struct backend *be, const char *filename,
int cpio_close(struct backend *be)
{
- int rv;
- rv = cpio_hdr(be, 0, 0, "TRAILER!!!");
- rv |= write_data(be, NULL, 0, true);
- return rv;
+ return cpio_hdr(be, 0, 0, "TRAILER!!!");
}
diff --git a/com32/sysdump/dmi.c b/com32/sysdump/dmi.c
index 64f95a9a..be4cce46 100644
--- a/com32/sysdump/dmi.c
+++ b/com32/sysdump/dmi.c
@@ -78,8 +78,8 @@ static void dump_smbios(struct backend *be, size_t dptr)
smx.dmi.tbladdr = sizeof smx;
smx.dmi.csum -= checksum(&smx.dmi, 0x0f);
- write_data(be, &smx, sizeof smx, false);
- write_data(be, (const void *)smb->dmi.tbladdr, smb->dmi.tbllen, false);
+ write_data(be, &smx, sizeof smx);
+ write_data(be, (const void *)smb->dmi.tbladdr, smb->dmi.tbllen);
}
static void dump_old_dmi(struct backend *be, size_t dptr)
@@ -104,8 +104,8 @@ static void dump_old_dmi(struct backend *be, size_t dptr)
fake.dmi.tbladdr = sizeof fake;
fake.dmi.csum -= checksum(&fake.dmi, 0x0f);
- write_data(be, &fake, sizeof fake, false);
- write_data(be, (const void *)dmi->tbladdr, dmi->tbllen, false);
+ write_data(be, &fake, sizeof fake);
+ write_data(be, (const void *)dmi->tbladdr, dmi->tbllen);
}
void dump_dmi(struct backend *be)
diff --git a/com32/sysdump/main.c b/com32/sysdump/main.c
index 4c58f5f4..19245061 100644
--- a/com32/sysdump/main.c
+++ b/com32/sysdump/main.c
@@ -31,11 +31,11 @@ __noreturn die(const char *msg)
exit(1);
}
-static void dump_all(struct backend *be, const char *argv[], size_t len)
+static void dump_all(struct backend *be, const char *argv[])
{
static const char version[] = "SYSDUMP " VERSION_STR " " DATE "\n";
- cpio_init(be, argv, len);
+ cpio_init(be, argv);
cpio_writefile(be, "sysdump", version, sizeof version);
@@ -47,13 +47,15 @@ static void dump_all(struct backend *be, const char *argv[], size_t len)
dump_vesa_tables(be);
cpio_close(be);
+ printf("Uploading data... ");
+ flush_data(be);
+ printf("done.\n");
}
static struct backend *backends[] =
{
&be_tftp,
&be_ymodem,
- &be_null,
NULL
};
@@ -88,11 +90,8 @@ int main(int argc, char *argv[])
/* Do this as early as possible */
snapshot_lowmem();
- if (be->flags & BE_NEEDLEN) {
- dump_all(&be_null, NULL, 0);
- dump_all(be, (const char **)argv + 2, be_null.zbytes);
- } else {
- dump_all(be, (const char **)argv + 2, 0);
- }
+ /* Do the actual data dump */
+ dump_all(be, (const char **)argv + 2);
+
return 0;
}
diff --git a/com32/sysdump/memmap.c b/com32/sysdump/memmap.c
index c8cfc032..a85f0925 100644
--- a/com32/sysdump/memmap.c
+++ b/com32/sysdump/memmap.c
@@ -33,7 +33,7 @@ static void dump_e820(struct backend *be)
ireg.ecx.l = sizeof curr->data;
ireg.es = SEG(curr->data);
ireg.edi.w[0] = OFFS(curr->data);
-
+
do {
__intcall(0x15, &ireg, &oreg);
if ((oreg.eflags.l & EFLAGS_CF) ||
diff --git a/com32/sysdump/serial.c b/com32/sysdump/serial.c
index f96ae3fa..71b3067a 100644
--- a/com32/sysdump/serial.c
+++ b/com32/sysdump/serial.c
@@ -122,5 +122,3 @@ void serial_cleanup(struct serial_if *sif)
if ((sif->old.iir & 0xc0) != 0xc0)
outb(0x00, port + FCR); /* Disable FIFOs */
}
-
-
diff --git a/com32/sysdump/zout.c b/com32/sysdump/zout.c
index d3be893d..61dd514d 100644
--- a/com32/sysdump/zout.c
+++ b/com32/sysdump/zout.c
@@ -10,19 +10,21 @@
#include <zlib.h>
#include "backend.h"
-int init_data(struct backend *be, const char *argv[], size_t len)
+#define ALLOC_CHUNK 65536
+
+int init_data(struct backend *be, const char *argv[])
{
- be->outbuf = malloc(be->blocksize);
- if (!be->outbuf)
- return -1;
+ be->argv = argv;
- if (be->open(be, argv, len))
+ 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 = be->blocksize;
+ be->zstream.avail_out = ALLOC_CHUNK;
be->dbytes = be->zbytes = 0;
@@ -34,7 +36,27 @@ int init_data(struct backend *be, const char *argv[], size_t len)
return 0;
}
-int write_data(struct backend *be, const void *buf, size_t len, bool flush)
+static int do_deflate(struct backend *be, int flush)
+{
+ int rv;
+
+ 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->zstream.next_out = (void *)(buf + be->zbytes);
+ be->zstream.avail_out = be->alloc - be->zbytes;
+ }
+
+ return rv;
+}
+
+
+int write_data(struct backend *be, const void *buf, size_t len)
{
int rv = Z_OK;
@@ -42,27 +64,31 @@ int write_data(struct backend *be, const void *buf, size_t len, bool flush)
be->zstream.avail_in = len;
be->dbytes += len;
-
- while (be->zstream.avail_in || (flush && rv == Z_OK)) {
- rv = deflate(&be->zstream, flush ? Z_FINISH : Z_NO_FLUSH);
- if (be->zstream.avail_out == 0) {
- if (be->write(be, be->outbuf, be->blocksize))
- return -1;
- be->zbytes += be->blocksize;
- be->zstream.next_out = (void *)be->outbuf;
- be->zstream.avail_out = be->blocksize;
- }
- if (rv == Z_STREAM_ERROR)
+
+ while (be->zstream.avail_in) {
+ rv = do_deflate(be, Z_NO_FLUSH);
+ if (rv < 0)
return -1;
}
+ return 0;
+}
- if (flush) {
- /* Output the last (fractional) packet... may be zero */
- if (be->write(be, be->outbuf, be->blocksize - be->zstream.avail_out))
+/* Output the data and shut down the stream */
+int flush_data(struct backend *be)
+{
+ int rv = Z_OK;
+
+ while (rv == Z_OK) {
+ rv = do_deflate(be, Z_FINISH);
+ if (rv < 0)
return -1;
- be->zbytes += be->blocksize - be->zstream.avail_out;
- free(be->outbuf);
}
+ if (be->write(be))
+ return -1;
+
+ free(be->outbuf);
+ be->outbuf = NULL;
+ be->dbytes = be->zbytes = be->alloc = 0;
return 0;
}