diff options
-rw-r--r-- | com32/sysdump/backend.h | 30 | ||||
-rw-r--r-- | com32/sysdump/be_null.c | 30 | ||||
-rw-r--r-- | com32/sysdump/be_tftp.c | 82 | ||||
-rw-r--r-- | com32/sysdump/be_ymodem.c | 116 | ||||
-rw-r--r-- | com32/sysdump/cpio.c | 17 | ||||
-rw-r--r-- | com32/sysdump/dmi.c | 8 | ||||
-rw-r--r-- | com32/sysdump/main.c | 17 | ||||
-rw-r--r-- | com32/sysdump/memmap.c | 2 | ||||
-rw-r--r-- | com32/sysdump/serial.c | 2 | ||||
-rw-r--r-- | com32/sysdump/zout.c | 72 |
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; } |