aboutsummaryrefslogtreecommitdiffstats
path: root/com32/sysdump
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2010-06-22 13:35:29 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2010-06-22 13:35:29 -0700
commit77d76c3ff1d922cda47754bdce98807e9a560585 (patch)
treebc398fbe9a432294ffa0cf01bb26235b9ecb0786 /com32/sysdump
parentd966918e7304ff405fae20916cf137d737c92dea (diff)
downloadsyslinux-77d76c3ff1d922cda47754bdce98807e9a560585.tar.gz
syslinux-77d76c3ff1d922cda47754bdce98807e9a560585.tar.xz
syslinux-77d76c3ff1d922cda47754bdce98807e9a560585.zip
sysdump: output S-records to the console
Sometimes we have a console path that can be captured (virtual machine, serial console, ...) but no realistic path for two-way or binary communication. Add an option to output S-records to the console as an inefficient but hopefully reliable way to get data out. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'com32/sysdump')
-rw-r--r--com32/sysdump/backend.h1
-rw-r--r--com32/sysdump/be_srec.c84
-rw-r--r--com32/sysdump/main.c1
3 files changed, 86 insertions, 0 deletions
diff --git a/com32/sysdump/backend.h b/com32/sysdump/backend.h
index 0926c8d5..f2b3bc25 100644
--- a/com32/sysdump/backend.h
+++ b/com32/sysdump/backend.h
@@ -50,5 +50,6 @@ struct backend *get_backend(const char *name);
/* backends */
extern struct backend be_tftp;
extern struct backend be_ymodem;
+extern struct backend be_srec;
#endif /* BACKEND_H */
diff --git a/com32/sysdump/be_srec.c b/com32/sysdump/be_srec.c
new file mode 100644
index 00000000..3b52b1af
--- /dev/null
+++ b/com32/sysdump/be_srec.c
@@ -0,0 +1,84 @@
+/*
+ * S-records dump routine -- dumps S-records on the console
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <minmax.h>
+#include "backend.h"
+
+/* Write a single S-record */
+static int write_srecord(unsigned int len, unsigned int alen,
+ uint32_t addr, uint8_t type, const void *data)
+{
+ char buf[2+2+8+255*2+2+2];
+ char *p = buf;
+ uint8_t csum;
+ const uint8_t *dptr = data;
+ unsigned int i;
+
+ switch (alen) {
+ case 2:
+ addr &= 0xffff;
+ break;
+ case 3:
+ addr &= 0xffffff;
+ break;
+ case 4:
+ break;
+ }
+
+ csum = (len+alen+1) + addr + (addr >> 8) + (addr >> 16) + (addr >> 24);
+ for (i = 0; i < len; i++)
+ csum += dptr[i];
+ csum = 0xff-csum;
+
+ p += sprintf(p, "S%c%02X%0*X", type, len+alen+1, alen*2, addr);
+ for (i = 0; i < len; i++)
+ p += sprintf(p, "%02X", dptr[i]);
+ p += sprintf(p, "%02X\n", csum);
+
+ fputs(buf, stdout);
+ return 0;
+}
+
+static int be_srec_write(struct backend *be)
+{
+ char name[33];
+ const char *buf;
+ size_t len, chunk, offset, hdrlen;
+
+ buf = be->outbuf;
+ len = be->zbytes;
+
+ putchar('\n');
+
+ hdrlen = snprintf(name, sizeof name, "%.32s",
+ be->argv[0] ? be->argv[0] : "");
+
+ /* Write head record */
+ write_srecord(hdrlen, 2, 0, '0', name);
+
+ /* Write data records */
+ offset = 0;
+ while (len) {
+ chunk = min(len, (size_t)32);
+
+ write_srecord(chunk, 4, offset, '3', buf);
+ buf += chunk;
+ len -= chunk;
+ }
+
+ /* Write termination record */
+ write_srecord(0, 4, 0, '7', NULL);
+
+ return 0;
+}
+
+struct backend be_srec = {
+ .name = "srec",
+ .helpmsg = "[filename]",
+ .minargs = 0,
+ .write = be_srec_write,
+};
diff --git a/com32/sysdump/main.c b/com32/sysdump/main.c
index 26f562be..d0d40a7b 100644
--- a/com32/sysdump/main.c
+++ b/com32/sysdump/main.c
@@ -54,6 +54,7 @@ static struct backend *backends[] =
{
&be_tftp,
&be_ymodem,
+ &be_srec,
NULL
};