With these changes, both TFTP and Ymodem seem to actually work.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
size_t zbytes;
const char **argv;
+ uint32_t now;
+
int (*write)(struct backend *);
z_stream zstream;
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);
*((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;
struct ymodem_state {
struct serial_if serial;
- uint16_t seq;
+ unsigned int seq, blocks;
};
/*
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++;
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 {
} 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;
}
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;
#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 */
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 */
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);
#include "sysdump.h"
const char program[] = "sysdump";
+const char version[] = "SYSDUMP " VERSION_STR " " DATE "\n";
__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);
dump_vesa_tables(be);
cpio_close(be);
- printf("Uploading data... ");
flush_data(be);
- printf("done.\n");
}
static struct backend *backends[] =
struct backend **bep, *be;
openconsole(&dev_null_r, &dev_stdcon_w);
+ fputs(version, stdout);
if (argc < 2)
usage();
/* 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);
#include <stdlib.h>
#include <stdio.h>
#include <sys/io.h>
+#include <sys/cpu.h>
#include "serial.h"
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);
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);
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 */
(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 */
}
#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 */
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;
}
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;
}
{
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;
}