summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-09-21 16:52:35 -0700
committerH. Peter Anvin <hpa@zytor.com>2007-09-21 16:52:35 -0700
commit5a16eeb519c87fa4c437e838af81731b8d355052 (patch)
treef59258a720429d5ad8beaf2070f73cab6a187077
parent31daeb2ddb972dc70b929da1c93288e821c87ed7 (diff)
downloadsyslinux-5a16eeb519c87fa4c437e838af81731b8d355052.tar.gz
memdump: a debugging utility to dump memory over a serial port
A memory-dumping utility which runs in real mode. Thus, it can be used to get memory dumps from a relatively pristine system.
-rw-r--r--Makefile5
-rw-r--r--memdump/Makefile64
-rw-r--r--memdump/README19
-rw-r--r--memdump/__divdi3.c29
-rw-r--r--memdump/__udivmoddi4.c31
-rw-r--r--memdump/argv.c92
-rw-r--r--memdump/code16.h6
-rw-r--r--memdump/com16.ld127
-rw-r--r--memdump/conio.c42
-rw-r--r--memdump/crt0.S53
-rw-r--r--memdump/errno.h7
-rw-r--r--memdump/io.h40
-rw-r--r--memdump/main.c153
-rw-r--r--memdump/malloc.h54
-rw-r--r--memdump/memcpy.S23
-rw-r--r--memdump/memset.S21
-rw-r--r--memdump/mystuff.h24
-rw-r--r--memdump/printf.c297
-rw-r--r--memdump/serial.c80
-rw-r--r--memdump/skipatou.c10
-rw-r--r--memdump/stdio.h21
-rw-r--r--memdump/stdlib.h14
-rw-r--r--memdump/string.h23
-rw-r--r--memdump/strtoul.c72
-rw-r--r--memdump/ymodem.txt2112
-rw-r--r--memdump/ymsend.c167
-rw-r--r--memdump/ymsend.h27
27 files changed, 3611 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 03e69fd0..0bd2121c 100644
--- a/Makefile
+++ b/Makefile
@@ -73,11 +73,12 @@ BTARGET = kwdhash.gen version.gen version.h \
ldlinux.bss ldlinux.sys ldlinux.bin \
pxelinux.0 isolinux.bin isolinux-debug.bin \
extlinux.bin extlinux.bss extlinux.sys
-BOBJECTS = $(BTARGET) mbr/mbr.bin dos/syslinux.com win32/syslinux.exe memdisk/memdisk
+BOBJECTS = $(BTARGET) mbr/mbr.bin dos/syslinux.com win32/syslinux.exe \
+ memdisk/memdisk memdump/memdump.com
# BESUBDIRS and IESUBDIRS are "early", i.e. before the root; BSUBDIRS
# and ISUBDIRS are "late", after the root.
BESUBDIRS = mbr
-BSUBDIRS = memdisk dos win32
+BSUBDIRS = memdisk memdump dos win32
ITARGET = copybs.com gethostip mkdiskimage
IOBJECTS = $(ITARGET) mtools/syslinux unix/syslinux extlinux/extlinux
IESUBDIRS =
diff --git a/memdump/Makefile b/memdump/Makefile
new file mode 100644
index 00000000..40497028
--- /dev/null
+++ b/memdump/Makefile
@@ -0,0 +1,64 @@
+TMPFILE = $(shell mktemp /tmp/gcc_ok.XXXXXX)
+
+gcc_ok = $(shell tmpf=$(TMPFILE); if gcc $(1) -c -x c /dev/null -o $$tmpf 2>/dev/null; \
+ then echo $(1); else echo $(2); fi; rm -f $$tmpf)
+
+M32 := $(call gcc_ok,-m32,) $(call gcc_ok,-ffreestanding,) $(call gcc_ok,-fno-stack-protector,)
+
+CC = gcc
+LD = ld -m elf_i386
+OBJCOPY = objcopy
+OPTFLAGS = -g -Os -march=i386 -falign-functions=0 -falign-jumps=0 -falign-loops=0 -fomit-frame-pointer
+INCLUDES = -include code16.h -I.
+CFLAGS = $(M32) -mregparm=3 -DREGPARM=3 -W -Wall -msoft-float $(OPTFLAGS) $(INCLUDES)
+LDFLAGS = -T com16.ld
+AR = ar
+RANLIB = ranlib
+LIBGCC := $(shell $(CC) --print-libgcc)
+
+SRCS = main.c serial.c ymsend.c
+OBJS = crt0.o $(patsubst %.c,%.o,$(notdir $(SRCS)))
+LIBOBJS = conio.o memcpy.o memset.o skipatou.o strtoul.o \
+ argv.o printf.o __divdi3.o __udivmoddi4.o
+
+.SUFFIXES: .c .o .i .s .S .elf .com
+
+VPATH = .:..:../libfat
+
+TARGETS = memdump.com
+
+all: $(TARGETS)
+
+tidy:
+ -rm -f *.o *.i *.s *.a .*.d *.elf
+
+clean: tidy
+
+spotless: clean
+ -rm -f *~ $(TARGETS)
+
+installer:
+
+memdump.elf: $(OBJS) libcom.a
+ $(LD) $(LDFLAGS) -o $@ $^
+
+libcom.a: $(LIBOBJS)
+ -rm -f $@
+ $(AR) cq $@ $^
+ $(RANLIB) $@
+
+memdump.com: memdump.elf
+ $(OBJCOPY) -O binary $< $@
+
+%.o: %.c
+ $(CC) -Wp,-MT,$@,-MD,.$@.d $(CFLAGS) -c -o $@ $<
+%.i: %.c
+ $(CC) $(CFLAGS) -E -o $@ $<
+%.s: %.c
+ $(CC) $(CFLAGS) -S -o $@ $<
+%.o: %.S
+ $(CC) -Wp,-MT,$@,-MD,.$@.d $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $<
+%.s: %.S
+ $(CC) $(CFLAGS) -E -o $@ $<
+
+-include .*.d
diff --git a/memdump/README b/memdump/README
new file mode 100644
index 00000000..2b825775
--- /dev/null
+++ b/memdump/README
@@ -0,0 +1,19 @@
+This is a very simple COMBOOT program which can be used to dump memory
+regions over a serial port. To use it, type on the SYSLINUX command
+line:
+
+memdump <port> <prefix> <start>,<len> <start>,<len>...
+
+For example:
+
+memdump 0 funnysystem- 0,0x600 0x9fc00,0x400 0xf0000,0x10000
+
+... dumps three memory ranges (the standard BIOS memory ranges, often
+useful) onto serial port 0. The <port> can either be in the range 0-3
+for the standard BIOS serial port, or the I/O address of the UART.
+
+The data is transferred using the YMODEM protocol; the Unix
+implementation of this protocol is called "rb" and is part of the
+"lrzsz" (or "rzsz") package. If one uses a terminal program like
+Minicom, there is often a way to invoke it from inside the terminal
+program; in Minicom, this is done with the Ctrl-A R control sequence.
diff --git a/memdump/__divdi3.c b/memdump/__divdi3.c
new file mode 100644
index 00000000..3641396f
--- /dev/null
+++ b/memdump/__divdi3.c
@@ -0,0 +1,29 @@
+/*
+ * arch/i386/libgcc/__divdi3.c
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem);
+
+int64_t __divdi3(int64_t num, int64_t den)
+{
+ int minus = 0;
+ int64_t v;
+
+ if ( num < 0 ) {
+ num = -num;
+ minus = 1;
+ }
+ if ( den < 0 ) {
+ den = -den;
+ minus ^= 1;
+ }
+
+ v = __udivmoddi4(num, den, NULL);
+ if ( minus )
+ v = -v;
+
+ return v;
+}
diff --git a/memdump/__udivmoddi4.c b/memdump/__udivmoddi4.c
new file mode 100644
index 00000000..8e7661f5
--- /dev/null
+++ b/memdump/__udivmoddi4.c
@@ -0,0 +1,31 @@
+#include <stdint.h>
+
+uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *rem_p)
+{
+ uint64_t quot = 0, qbit = 1;
+
+ if ( den == 0 ) {
+ asm volatile("int $0");
+ return 0; /* If trap returns... */
+ }
+
+ /* Left-justify denominator and count shift */
+ while ( (int64_t)den >= 0 ) {
+ den <<= 1;
+ qbit <<= 1;
+ }
+
+ while ( qbit ) {
+ if ( den <= num ) {
+ num -= den;
+ quot += qbit;
+ }
+ den >>= 1;
+ qbit >>= 1;
+ }
+
+ if ( rem_p )
+ *rem_p = num;
+
+ return quot;
+}
diff --git a/memdump/argv.c b/memdump/argv.c
new file mode 100644
index 00000000..9aaa4d38
--- /dev/null
+++ b/memdump/argv.c
@@ -0,0 +1,92 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2004 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * argv.c
+ *
+ * Parse a single C string into argc and argv (argc is return value.)
+ * memptr points to available memory.
+ */
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#define ALIGN_UP(p,t) ((t *)(((uintptr_t)(p) + (sizeof(t)-1)) & ~(sizeof(t)-1)))
+
+extern char _end[]; /* Symbol created by linker */
+void *__mem_end = &_end; /* Global variable for use by malloc() */
+
+int __parse_argv(char ***argv, const char *str)
+{
+ char *mem = __mem_end;
+ const char *p = str;
+ char *q = mem;
+ char *r;
+ char **arg;
+ int wasspace = 0;
+ int argc = 1;
+
+ /* First copy the string, turning whitespace runs into nulls */
+ for ( p = str ; ; p++ ) {
+ if ( *p <= ' ' ) {
+ if ( !wasspace ) {
+ wasspace = 1;
+ *q++ = '\0';
+ }
+ } else {
+ if ( wasspace ) {
+ argc++;
+ wasspace = 0;
+ }
+ *q++ = *p;
+ }
+
+ /* This test is AFTER we have processed the null byte;
+ we treat it as a whitespace character so it terminates
+ the last argument */
+ if ( ! *p )
+ break;
+ }
+
+ /* Now create argv */
+ arg = ALIGN_UP(q,char *);
+ *argv = arg;
+ *arg++ = mem; /* argv[0] */
+
+ q--; /* Point q to final null */
+ for ( r = mem ; r < q ; r++ ) {
+ if ( *r == '\0' ) {
+ *arg++ = r+1;
+ }
+ }
+
+ *arg++ = NULL; /* Null pointer at the end */
+ __mem_end = arg; /* End of memory we used */
+
+ return argc;
+}
diff --git a/memdump/code16.h b/memdump/code16.h
new file mode 100644
index 00000000..ca765651
--- /dev/null
+++ b/memdump/code16.h
@@ -0,0 +1,6 @@
+/* Must be included first of all */
+#ifdef __ASSEMBLY__
+ .code16
+#else
+__asm__ (".code16gcc");
+#endif
diff --git a/memdump/com16.ld b/memdump/com16.ld
new file mode 100644
index 00000000..08a1e95e
--- /dev/null
+++ b/memdump/com16.ld
@@ -0,0 +1,127 @@
+/*
+ * Linker script for COM16 binaries
+ */
+
+/* Script for -z combreloc: combine and sort reloc sections */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386",
+ "elf32-i386")
+OUTPUT_ARCH(i386)
+EXTERN(_start)
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0x100;
+ PROVIDE (__executable_start = .);
+
+ .init :
+ {
+ KEEP (*(.init))
+ } =0x90909090
+ .text :
+ {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ } =0x90909090
+ .fini :
+ {
+ KEEP (*(.fini))
+ } =0x90909090
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+
+ /* Ensure the __preinit_array_start label is properly aligned. We
+ could instead move the label definition inside the section, but
+ the linker would then create the section even if it turns out to
+ be empty, which isn't pretty. */
+ . = ALIGN(4);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { *(.preinit_array) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { *(.init_array) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { *(.fini_array) }
+ PROVIDE (__fini_array_end = .);
+ PROVIDE (__ctors_start = .);
+ .ctors :
+ {
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+ PROVIDE (__ctors_end = .);
+ PROVIDE (__dtors_start = .);
+ .dtors :
+ {
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+ PROVIDE (__dtors_end = .);
+
+ /* Adjust the address for the data segment. Avoid mixing code and
+ data within same 128-byte chunk. */
+ . = ALIGN(128);
+
+ .data :
+ {
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections. */
+ . = ALIGN(32 / 8);
+ }
+ . = ALIGN(32 / 8);
+ _end = .;
+ PROVIDE (end = .);
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /DISCARD/ : { *(.note.GNU-stack) }
+}
diff --git a/memdump/conio.c b/memdump/conio.c
new file mode 100644
index 00000000..4d58dcbd
--- /dev/null
+++ b/memdump/conio.c
@@ -0,0 +1,42 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2001-2004 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * conio.c
+ *
+ * Output to the screen
+ */
+
+#include <stdarg.h>
+#include "mystuff.h"
+
+int putchar(int ch)
+{
+ if ( ch == '\n' )
+ putchar('\r');
+ asm("movb $0x02,%%ah ; int $0x21" : : "d" (ch));
+ return ch;
+}
+
+/* Note: doesn't put '\n' like the stdc version does */
+int puts(const char *s)
+{
+ int count = 0;
+
+ while ( *s ) {
+ putchar(*s);
+ count++;
+ s++;
+ }
+
+ return count;
+}
diff --git a/memdump/crt0.S b/memdump/crt0.S
new file mode 100644
index 00000000..92297ecf
--- /dev/null
+++ b/memdump/crt0.S
@@ -0,0 +1,53 @@
+ .code16
+
+#ifndef REGPARM
+# error "This file assumes -mregparm=3 -DREGPARM=3"
+#endif
+
+ .section ".init","ax"
+ .globl _start
+ .type _start,@function
+_start:
+ # Align the stack and make sure the high half is zero
+ andl $0xfff8,%esp
+
+ # Clear the .bss
+ cld
+ xorl %eax,%eax
+ movw $__bss_start,%di
+ movw $_end+3,%cx
+ subw %di,%cx
+ shrw $2,%cx
+ rep ; stosl
+
+ # Compute argc and argv (assumes REGPARM)
+ xorl %edx,%edx
+ movzbw 0x80,%bx
+ movb %dl,0x81(%bx) # Zero-terminate string
+ movb $0x81,%dl
+ pushl %eax # Make space for argv
+ movl %esp,%eax
+ calll __parse_argv
+ pushl %eax # argc
+
+ # Initialize malloc
+ # calll __init_memory_arena
+
+ # Now call main... (NOTE: gcc forces main to be regparm 0)
+ popl %eax # argc
+ popl %edx # argv
+ calll main
+
+ # Here %eax is the exit code, fall through into exit
+
+ .size _start,.-_start
+
+ .globl exit
+ .type exit,@function
+exit:
+ # Exit code already in %eax
+ movb $0x4c,%ah # Terminate program
+ int $0x21
+1: hlt
+ jmp 1b
+ .size exit,.-exit
diff --git a/memdump/errno.h b/memdump/errno.h
new file mode 100644
index 00000000..30aa046f
--- /dev/null
+++ b/memdump/errno.h
@@ -0,0 +1,7 @@
+#ifndef ERRNO_H
+#define ERRNO_H
+
+int errno;
+void perror(const char *);
+
+#endif /* ERRNO_H */
diff --git a/memdump/io.h b/memdump/io.h
new file mode 100644
index 00000000..a592402f
--- /dev/null
+++ b/memdump/io.h
@@ -0,0 +1,40 @@
+#ifndef IO_H
+#define IO_H
+
+static inline void outb(unsigned char v, unsigned short p)
+{
+ asm volatile("outb %1,%0" : : "d" (p), "a" (v));
+}
+
+static inline unsigned char inb(unsigned short p)
+{
+ unsigned char v;
+ asm volatile("inb %1,%0" : "=a" (v) : "d" (p));
+ return v;
+}
+
+static inline void outw(unsigned short v, unsigned short p)
+{
+ asm volatile("outw %1,%0" : : "d" (p), "a" (v));
+}
+
+static inline unsigned short inw(unsigned short p)
+{
+ unsigned short v;
+ asm volatile("inw %1,%0" : "=a" (v) : "d" (p));
+ return v;
+}
+
+static inline void outl(unsigned int v, unsigned short p)
+{
+ asm volatile("outl %1,%0" : : "d" (p), "a" (v));
+}
+
+static inline unsigned int inl(unsigned short p)
+{
+ unsigned int v;
+ asm volatile("inl %1,%0" : "=a" (v) : "d" (p));
+ return v;
+}
+
+#endif
diff --git a/memdump/main.c b/memdump/main.c
new file mode 100644
index 00000000..c8fa39d9
--- /dev/null
+++ b/memdump/main.c
@@ -0,0 +1,153 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ * Boston MA 02111-1307, USA; either version 2 of the License, or
+ * (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "mystuff.h"
+#include "ymsend.h"
+#include "io.h"
+
+const char *program = "memdump";
+
+void __attribute__((noreturn)) die(const char *msg)
+{
+ puts(program);
+ puts(": ");
+ puts(msg);
+ putchar('\n');
+ exit(1);
+}
+
+#ifdef DEBUG
+# define dprintf printf
+#else
+# define dprintf(...) ((void)0)
+#endif
+
+static inline __attribute__((const)) uint16_t ds(void)
+{
+ uint16_t v;
+ asm("movw %%ds,%0" : "=rm" (v));
+ return v;
+}
+
+#define GDT_ENTRY(flags,base,limit) \
+ (((uint64_t)(base & 0xff000000) << 32) | \
+ ((uint64_t)flags << 40) | \
+ ((uint64_t)(limit & 0x00ff0000) << 32) | \
+ ((uint64_t)(base & 0x00ffff00) << 16) | \
+ ((uint64_t)(limit & 0x0000ffff)))
+
+static void get_bytes(void *buf, size_t len, struct file_info *finfo,
+ size_t pos)
+{
+ size_t end;
+ static uint64_t gdt[6];
+ size_t bufl;
+
+ pos += (size_t)finfo->pvt; /* Add base */
+ end = pos+len;
+
+ if (end <= 0x100000) {
+ /* Can stay in real mode */
+ asm volatile("movw %3,%%fs ; "
+ "fs; rep; movsl ; "
+ "movw %2,%%cx ; "
+ "rep; movsb"
+ : : "D" (buf), "c" (len >> 2), "r" ((uint16_t)(len & 3)),
+ "rm" ((uint16_t)(pos >> 4)), "S" (pos & 15)
+ : "memory");
+ } else {
+ bufl = (ds() << 4)+(size_t)buf;
+ gdt[2] = GDT_ENTRY(0x0093, pos, 0xffff);
+ gdt[3] = GDT_ENTRY(0x0093, bufl, 0xffff);
+ asm volatile("pushal ; int $0x15 ; popal"
+ : : "a" (0x8700), "c" ((len+1) >> 1), "S" (&gdt)
+ : "memory");
+ }
+}
+
+static uint32_t pci_readl(int bus, int devfn, int reg)
+{
+ outl(0x80000000 | (bus << 16) | (devfn << 8) | reg, 0xcf8);
+ return inl(0xcfc);
+}
+
+int main(int argc, char *argv[])
+{
+ uint16_t bios_ports[4];
+ const char *prefix;
+ char filename[1024];
+ int i;
+ static struct serial_if sif =
+ {
+ .read = serial_read,
+ .write = serial_write,
+ };
+ struct file_info finfo;
+ const char serial_banner[] = "Now being Ymodem download...\r\n";
+
+ puts("Hello, world...\n");
+
+ printf("03:02.00 id = 0x%08x\n", pci_readl(3,2<<3,0));
+ printf("03:02.00 cmd = 0x%08x\n", pci_readl(3,2<<3,4));
+ printf("03:02.00 bar = 0x%08x\n", pci_readl(3,2<<3,0x10));
+
+ if (argc < 4)
+ die("usage: memdump port prefix start,len...");
+
+ finfo.pvt = (void *)0x400;
+ get_bytes(bios_ports, 8, &finfo, 0); /* Get BIOS serial ports */
+
+ for (i = 0; i < 4; i++)
+ printf("ttyS%i (COM%i) is at %#x\n", i, i+1, bios_ports[i]);
+
+ sif.port = strtoul(argv[1], NULL, 0);
+ if (sif.port <= 3) {
+ sif.port = bios_ports[sif.port];
+ }
+
+ if (serial_init(&sif))
+ die("failed to initialize serial port");
+
+ prefix = argv[2];
+
+ puts("Printing prefix...\n");
+ sif.write(&sif, serial_banner, sizeof serial_banner-1);
+
+ for (i = 3; i < argc; i++) {
+ uint32_t start, len;
+ char *ep;
+
+ start = strtoul(argv[i], &ep, 0);
+ if (*ep != ',')
+ die("invalid range specification");
+ len = strtoul(ep+1, NULL, 0);
+
+ sprintf(filename, "%s%#x,%#x", prefix, start, len);
+ finfo.name = filename;
+ finfo.size = len;
+ finfo.pvt = (void *)start;
+
+ puts("Sending ");
+ puts(filename);
+ puts("...\n");
+
+ send_ymodem(&sif, &finfo, get_bytes);
+ }
+
+ puts("Sending closing signature...\n");
+ end_ymodem(&sif);
+
+ return 0;
+}
diff --git a/memdump/malloc.h b/memdump/malloc.h
new file mode 100644
index 00000000..70d0e635
--- /dev/null
+++ b/memdump/malloc.h
@@ -0,0 +1,54 @@
+/*
+ * malloc.h
+ *
+ * Internals for the memory allocator
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+/*
+ * This is the minimum chunk size we will ask the kernel for; this should
+ * be a multiple of the page size on all architectures.
+ */
+#define MALLOC_CHUNK_SIZE 65536
+#define MALLOC_CHUNK_MASK (MALLOC_CHUNK_SIZE-1)
+
+/*
+ * This structure should be a power of two. This becomes the
+ * alignment unit.
+ */
+struct free_arena_header;
+
+struct arena_header {
+ size_t type;
+ size_t size; /* Also gives the location of the next entry */
+ struct free_arena_header *next, *prev;
+};
+
+#ifdef DEBUG_MALLOC
+#define ARENA_TYPE_USED 0x64e69c70
+#define ARENA_TYPE_FREE 0x012d610a
+#define ARENA_TYPE_HEAD 0x971676b5
+#define ARENA_TYPE_DEAD 0xeeeeeeee
+#else
+#define ARENA_TYPE_USED 0
+#define ARENA_TYPE_FREE 1
+#define ARENA_TYPE_HEAD 2
+#endif
+
+#define ARENA_SIZE_MASK (sizeof(struct arena_header)-1)
+
+#define ARENA_ALIGN_UP(p) ((char *)(((uintptr_t)(p) + ARENA_SIZE_MASK) & ~ARENA_SIZE_MASK))
+#define ARENA_ALIGN_DOWN(p) ((char *)((uintptr_t)(p) & ~ARENA_SIZE_MASK))
+
+/*
+ * This structure should be no more than twice the size of the
+ * previous structure.
+ */
+struct free_arena_header {
+ struct arena_header a;
+ struct free_arena_header *next_free, *prev_free;
+};
+
+extern struct free_arena_header __malloc_head;
diff --git a/memdump/memcpy.S b/memdump/memcpy.S
new file mode 100644
index 00000000..76eef73c
--- /dev/null
+++ b/memdump/memcpy.S
@@ -0,0 +1,23 @@
+#
+# memcpy.S
+#
+# Simple 16-bit memcpy() implementation
+#
+
+ .text
+ .code16gcc
+ .globl memcpy
+ .type memcpy, @function
+memcpy:
+ cld
+ pushw %di
+ pushw %si
+ movw %ax,%di
+ movw %dx,%si
+ # The third argument is already in cx
+ rep ; movsb
+ popw %si
+ popw %di
+ ret
+
+ .size memcpy,.-memcpy
diff --git a/memdump/memset.S b/memdump/memset.S
new file mode 100644
index 00000000..86e12ab2
--- /dev/null
+++ b/memdump/memset.S
@@ -0,0 +1,21 @@
+#
+# memset.S
+#
+# Minimal 16-bit memset() implementation
+#
+
+ .text
+ .code16gcc
+ .globl memset
+ .type memset, @function
+memset:
+ cld
+ pushw %di
+ movw %ax,%di
+ movb %dl,%al
+ # The third argument is already in %cx
+ rep ; stosb
+ popw %di
+ retl
+
+ .size memset,.-memset
diff --git a/memdump/mystuff.h b/memdump/mystuff.h
new file mode 100644
index 00000000..7c5ac6f5
--- /dev/null
+++ b/memdump/mystuff.h
@@ -0,0 +1,24 @@
+#ifndef MYSTUFF_H
+#define MYSTUFF_H
+
+#include <stdlib.h>
+
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef signed short int16_t;
+typedef unsigned short uint16_t;
+typedef signed int int32_t;
+typedef unsigned int uint32_t;
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+
+unsigned int skip_atou(const char **s);
+unsigned long strtoul(const char *, char **, int);
+
+static inline int
+isdigit(int ch)
+{
+ return (ch >= '0') && (ch <= '9');
+}
+
+#endif /* MYSTUFF_H */
diff --git a/memdump/printf.c b/memdump/printf.c
new file mode 100644
index 00000000..99b389f6
--- /dev/null
+++ b/memdump/printf.c
@@ -0,0 +1,297 @@
+/*
+ * Oh, it's a waste of space, but oh-so-yummy for debugging. It's just
+ * initialization code anyway, so it doesn't take up space when we're
+ * actually running. This version of printf() does not include 64-bit
+ * support. "Live with it."
+ *
+ * Most of this code was shamelessly snarfed from the Linux kernel, then
+ * modified. It's therefore GPL.
+ *
+ * printf() isn't actually needed to build syslinux.com, but during
+ * debugging it's handy.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "mystuff.h"
+
+static int strnlen(const char *s, int maxlen)
+{
+ const char *es = s;
+ while ( *es && maxlen ) {
+ es++; maxlen--;
+ }
+
+ return (es-s);
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIAL 32 /* 0x */
+#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+static char * number(char * str, long num, int base, int size, int precision
+ ,int type)
+{
+ char c,sign,tmp[66];
+ const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
+ int i;
+
+ if (type & LARGE)
+ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return 0;
+ c = (type & ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & SIGN) {
+ if (num < 0) {
+ sign = '-';
+ num = -num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else while (num != 0)
+ tmp[i++] = digits[do_div(num,base)];
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT)))
+ while(size-->0)
+ *str++ = ' ';
+ if (sign)
+ *str++ = sign;
+ if (type & SPECIAL) {
+ if (base==8)
+ *str++ = '0';
+ else if (base==16) {
+ *str++ = '0';
+ *str++ = digits[33];
+ }
+ }
+ if (!(type & LEFT))
+ while (size-- > 0)
+ *str++ = c;
+ while (i < precision--)
+ *str++ = '0';
+ while (i-- > 0)
+ *str++ = tmp[i];
+ while (size-- > 0)
+ *str++ = ' ';
+ return str;
+}
+
+/* Forward decl. needed for IP address printing stuff... */
+int sprintf(char * buf, const char *fmt, ...);
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ int len;
+ unsigned long num;
+ int i, base;
+ char * str;
+ const char *s;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* 'h', 'l', or 'L' for integer fields */
+
+ for (str=buf ; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ *str++ = *fmt;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-': flags |= LEFT; goto repeat;
+ case '+': flags |= PLUS; goto repeat;
+ case ' ': flags |= SPACE; goto repeat;
+ case '#': flags |= SPECIAL; goto repeat;
+ case '0': flags |= ZEROPAD; goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (isdigit(*fmt))
+ field_width = skip_atou(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (isdigit(*fmt))
+ precision = skip_atou(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+ qualifier = *fmt;
+ ++fmt;
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT))
+ while (--field_width > 0)
+ *str++ = ' ';
+ *str++ = (unsigned char) va_arg(args, int);
+ while (--field_width > 0)
+ *str++ = ' ';
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+ len = strnlen(s, precision);
+
+ if (!(flags & LEFT))
+ while (len < field_width--)
+ *str++ = ' ';
+ for (i = 0; i < len; ++i)
+ *str++ = *s++;
+ while (len < field_width--)
+ *str++ = ' ';
+ continue;
+
+ case 'p':
+ if (field_width == -1) {
+ field_width = 2*sizeof(void *);
+ flags |= ZEROPAD;
+ }
+ str = number(str,
+ (unsigned long) va_arg(args, void *), 16,
+ field_width, precision, flags);
+ continue;
+
+
+ case 'n':
+ if (qualifier == 'l') {
+ long * ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else {
+ int * ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ continue;
+
+ case '%':
+ *str++ = '%';
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'X':
+ flags |= LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ *str++ = '%';
+ if (*fmt)
+ *str++ = *fmt;
+ else
+ --fmt;
+ continue;
+ }
+ if (qualifier == 'l')
+ num = va_arg(args, unsigned long);
+ else if (qualifier == 'h') {
+ num = (unsigned short) va_arg(args, int);
+ if (flags & SIGN)
+ num = (short) num;
+ } else if (flags & SIGN)
+ num = va_arg(args, int);
+ else
+ num = va_arg(args, unsigned int);
+ str = number(str, num, base, field_width, precision, flags);
+ }
+ *str = '\0';
+ return str-buf;
+}
+
+int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
+int printf(const char *fmt, ...)
+{
+ char printf_buf[1024];
+ va_list args;
+ int printed;
+
+ va_start(args, fmt);
+ printed = vsprintf(printf_buf, fmt, args);
+ va_end(args);
+
+ puts(printf_buf);
+
+ return printed;
+}
diff --git a/memdump/serial.c b/memdump/serial.c
new file mode 100644
index 00000000..902dcc3d
--- /dev/null
+++ b/memdump/serial.c
@@ -0,0 +1,80 @@
+#include "mystuff.h"
+#include "ymsend.h"
+#include "io.h"
+
+enum {
+ THR = 0,
+ RBR = 0,
+ DLL = 0,
+ DLM = 1,
+ IER = 1,
+ IIR = 2,
+ FCR = 2,
+ LCR = 3,
+ MCR = 4,
+ LSR = 5,
+ MSR = 6,
+ SCR = 7,
+};
+
+int serial_init(struct serial_if *sif)
+{
+ uint16_t port = sif->port;
+ uint8_t dll, dlm, lcr;
+
+ /* Set 115200n81 */
+ outb(0x83, port+LCR);
+ outb(0x01, port+DLL);
+ outb(0x00, port+DLM);
+ (void)inb(port+IER); /* Synchronize */
+ dll = inb(port+DLL);
+ dlm = inb(port+DLM);
+ lcr = inb(port+LCR);
+ outb(0x03, port+LCR);
+ (void)inb(port+IER); /* Synchronize */
+
+ if (dll != 0x01 || dlm != 0x00 || lcr != 0x83)
+ return -1; /* This doesn't look like a serial port */
+
+ /* Disable interrupts */
+ outb(port+IER, 0);
+
+ /* Enable 16550A FIFOs if available */
+ outb(port+FCR, 0x01); /* Enable FIFO */
+ (void)inb(port+IER); /* Synchronize */
+ if (inb(port+IIR) < 0xc0)
+ outb(port+FCR, 0x00); /* Disable FIFOs if non-functional */
+ (void)inb(port+IER); /* Synchronize */
+
+ return 0;
+}
+
+void serial_write(struct serial_if *sif, const void *data, size_t n)
+{
+ uint16_t port = sif->port;
+ const char *p = data;
+ uint8_t lsr;
+
+ while (n--) {
+ do {
+ lsr = inb(port+LSR);
+ } while (!(lsr & 0x20));
+
+ outb(*p++, port+THR);
+ }
+}
+
+void serial_read(struct serial_if *sif, void *data, size_t n)
+{
+ uint16_t port = sif->port;
+ char *p = data;
+ uint8_t lsr;
+
+ while (n--) {
+ do {
+ lsr = inb(port+LSR);
+ } while (!(lsr & 0x01));
+
+ *p++ = inb(port+RBR);
+ }
+}
diff --git a/memdump/skipatou.c b/memdump/skipatou.c
new file mode 100644
index 00000000..f71c5342
--- /dev/null
+++ b/memdump/skipatou.c
@@ -0,0 +1,10 @@
+#include "mystuff.h"
+
+unsigned int skip_atou(const char **s)
+{
+ int i=0;
+
+ while (isdigit(**s))
+ i = i*10 + *((*s)++) - '0';
+ return i;
+}
diff --git a/memdump/stdio.h b/memdump/stdio.h
new file mode 100644
index 00000000..97988c24
--- /dev/null
+++ b/memdump/stdio.h
@@ -0,0 +1,21 @@
+#ifndef STDIO_H
+#define STDIO_H
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+typedef unsigned int off_t;
+
+int putchar(int);
+int puts(const char *);
+int sprintf(char * buf, const char *fmt, ...);
+int vsprintf(char *buf, const char *fmt, va_list args);
+int printf(const char *fmt, ...);
+
+#define stdin 0
+#define stdout 1
+#define stderr 2
+
+#define fprintf(x, y, ...) printf(y, ## __VA_ARGS__)
+
+#endif /* STDIO_H */
diff --git a/memdump/stdlib.h b/memdump/stdlib.h
new file mode 100644
index 00000000..6ead86af
--- /dev/null
+++ b/memdump/stdlib.h
@@ -0,0 +1,14 @@
+#ifndef STDLIB_H
+#define STDLIB_H
+
+#define NULL ((void *)0)
+
+typedef int ssize_t;
+typedef unsigned int size_t;
+
+void __attribute__((noreturn)) exit(int);
+
+void *malloc(size_t);
+void free(void *);
+
+#endif
diff --git a/memdump/string.h b/memdump/string.h
new file mode 100644
index 00000000..44f77dac
--- /dev/null
+++ b/memdump/string.h
@@ -0,0 +1,23 @@
+/*
+ * string.h
+ */
+
+#ifndef _STRING_H
+#define _STRING_H
+
+/* Standard routines */
+#define memcpy(a,b,c) __builtin_memcpy(a,b,c)
+#define memset(a,b,c) __builtin_memset(a,b,c)
+#define strcpy(a,b) __builtin_strcpy(a,b)
+#define strlen(a) __builtin_strlen(a)
+
+/* This only returns true or false */
+static inline int memcmp(const void *__m1, const void *__m2, unsigned int __n)
+{
+ _Bool rv;
+ asm volatile("cld ; repe ; cmpsb ; setne %0"
+ : "=abd" (rv), "+D" (__m1), "+S" (__m2), "+c" (__n));
+ return rv;
+}
+
+#endif /* _STRING_H */
diff --git a/memdump/strtoul.c b/memdump/strtoul.c
new file mode 100644
index 00000000..cd09d3d0
--- /dev/null
+++ b/memdump/strtoul.c
@@ -0,0 +1,72 @@
+/*
+ * strtoul.c
+ *
+ */
+
+#include "mystuff.h"
+
+static inline int isspace(int c)
+{
+ return (c <= ' '); /* Close enough */
+}
+
+static inline int digitval(int ch)
+{
+ if (ch >= '0' && ch <= '9') {
+ return ch - '0';
+ } else if (ch >= 'A' && ch <= 'Z') {
+ return ch - 'A' + 10;
+ } else if (ch >= 'a' && ch <= 'z') {
+ return ch - 'a' + 10;
+ } else {
+ return -1;
+ }
+}
+
+unsigned long strtoul(const char *nptr, char **endptr, int base)
+{
+ int minus = 0;
+ unsigned long v = 0;
+ int d;
+
+ while (isspace((unsigned char)*nptr)) {
+ nptr++;
+ }
+
+ /* Single optional + or - */
+ {
+ char c = *nptr;
+ if (c == '-' || c == '+') {
+ minus = (c == '-');
+ nptr++;
+ }
+ }
+
+ if (base == 0) {
+ if (nptr[0] == '0' &&
+ (nptr[1] == 'x' || nptr[1] == 'X')) {
+ nptr += 2;
+ base = 16;
+ } else if (nptr[0] == '0') {
+ nptr++;
+ base = 8;
+ } else {
+ base = 10;
+ }
+ } else if (base == 16) {
+ if (nptr[0] == '0' &&
+ (nptr[1] == 'x' || nptr[1] == 'X')) {
+ nptr += 2;
+ }
+ }
+
+ while ((d = digitval(*nptr)) >= 0 && d < base) {
+ v = v * base + d;
+ nptr++;
+ }
+
+ if (endptr)
+ *endptr = (char *)nptr;
+
+ return minus ? -v : v;
+}
diff --git a/memdump/ymodem.txt b/memdump/ymodem.txt
new file mode 100644
index 00000000..24a65781
--- /dev/null
+++ b/memdump/ymodem.txt
@@ -0,0 +1,2112 @@
+
+
+
+ - 1 -
+
+
+
+ XMODEM/YMODEM PROTOCOL REFERENCE
+ A compendium of documents describing the
+
+ XMODEM and YMODEM
+
+ File Transfer Protocols
+
+
+
+
+ This document was formatted 10-14-88.
+
+
+
+
+
+
+
+ Edited by Chuck Forsberg
+
+
+
+
+
+
+
+
+
+ This file may be redistributed without restriction
+ provided the text is not altered.
+
+ Please distribute as widely as possible.
+
+ Questions to Chuck Forsberg
+
+
+
+
+
+ Omen Technology Inc
+ The High Reliability Software
+ 17505-V Sauvie Island Road
+ Portland Oregon 97231
+ VOICE: 503-621-3406 :VOICE
+ TeleGodzilla BBS: 503-621-3746 Speed 19200(Telebit PEP),2400,1200,300
+ CompuServe: 70007,2304
+ GEnie: CAF
+ UUCP: ...!tektronix!reed!omen!caf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - 2 -
+
+
+
+ 1. TOWER OF BABEL
+
+ A "YMODEM Tower of Babel" has descended on the microcomputing community
+ bringing with it confusion, frustration, bloated phone bills, and wasted
+ man hours. Sadly, I (Chuck Forsberg) am partly to blame for this mess.
+
+ As author of the early 1980s batch and 1k XMODEM extensions, I assumed
+ readers of earlier versions of this document would implement as much of
+ the YMODEM protocol as their programming skills and computing environments
+ would permit. This proved a rather naive assumption as programmers
+ motivated by competitive pressure implemented as little of YMODEM as
+ possible. Some have taken whatever parts of YMODEM that appealed to them,
+ applied them to MODEM7 Batch, Telink, XMODEM or whatever, and called the
+ result YMODEM.
+
+ Jeff Garbers (Crosstalk package development director) said it all: "With
+ protocols in the public domain, anyone who wants to dink around with them
+ can go ahead." [1]
+
+ Documents containing altered examples derived from YMODEM.DOC have added
+ to the confusion. In one instance, some self styled rewriter of history
+ altered the heading in YMODEM.DOC's Figure 1 from "1024 byte Packets" to
+ "YMODEM/CRC File Transfer Protocol". None of the XMODEM and YMODEM
+ examples shown in that document were correct.
+
+ To put an end to this confusion, we must make "perfectly clear" what
+ YMODEM stands for, as Ward Christensen defined it in his 1985 coining of
+ the term.
+
+ To the majority of you who read, understood, and respected Ward's
+ definition of YMODEM, I apologize for the inconvenience.
+
+ 1.1 Definitions
+
+ ARC ARC is a program that compresses one or more files into an archive
+ and extracts files from such archives.
+
+ XMODEM refers to the file transfer etiquette introduced by Ward
+ Christensen's 1977 MODEM.ASM program. The name XMODEM comes from
+ Keith Petersen's XMODEM.ASM program, an adaptation of MODEM.ASM
+ for Remote CP/M (RCPM) systems. It's also called the MODEM or
+ MODEM2 protocol. Some who are unaware of MODEM7's unusual batch
+ file mode call it MODEM7. Other aliases include "CP/M Users'
+ Group" and "TERM II FTP 3". The name XMODEM caught on partly
+ because it is distinctive and partly because of media interest in
+
+
+ __________
+
+ 1. Page C/12, PC-WEEK July 12, 1987
+
+
+
+
+ Chapter 1
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 3
+
+
+
+ bulletin board and RCPM systems where it was accessed with an
+ "XMODEM" command. This protocol is supported by every serious
+ communications program because of its universality, simplicity,
+ and reasonable performance.
+
+ XMODEM/CRC replaces XMODEM's 1 byte checksum with a two byte Cyclical
+ Redundancy Check (CRC-16), giving modern error detection
+ protection.
+
+ XMODEM-1k Refers to the XMODEM/CRC protocol with 1024 byte data blocks.
+
+ YMODEM Refers to the XMODEM/CRC (optional 1k blocks) protocol with batch
+ transmission as described below. In a nutshell, YMODEM means
+ BATCH.
+
+ YMODEM-g Refers to the streaming YMODEM variation described below.
+
+ True YMODEM(TM) In an attempt to sort out the YMODEM Tower of Babel, Omen
+ Technology has trademarked the term True YMODEM(TM) to represent
+ the complete YMODEM protocol described in this document, including
+ pathname, length, and modification date transmitted in block 0.
+ Please contact Omen Technology about certifying programs for True
+ YMODEM(TM) compliance.
+
+ ZMODEM uses familiar XMODEM/CRC and YMODEM technology in a new protocol
+ that provides reliability, throughput, file management, and user
+ amenities appropriate to contemporary data communications.
+
+ ZOO Like ARC, ZOO is a program that compresses one or more files into
+ a "zoo archive". ZOO supports many different operating systems
+ including Unix and VMS.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chapter 1
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 4
+
+
+
+ 2. YMODEM MINIMUM REQUIREMENTS
+
+ All programs claiming to support YMODEM must meet the following minimum
+ requirements:
+
+ + The sending program shall send the pathname (file name) in block 0.
+
+ + The pathname shall be a null terminated ASCII string as described
+ below.
+
+ For those who are too lazy to read the entire document:
+
+ + Unless specifically requested, only the file name portion is
+ sent.
+
+ + No drive letter is sent.
+
+ + Systems that do not distinguish between upper and lower case
+ letters in filenames shall send the pathname in lower case only.
+
+
+ + The receiving program shall use this pathname for the received file
+ name, unless explicitly overridden.
+
+ + When the receiving program receives this block and successfully
+ opened the output file, it shall acknowledge this block with an ACK
+ character and then proceed with a normal XMODEM file transfer
+ beginning with a "C" or NAK tranmsitted by the receiver.
+
+ + The sending program shall use CRC-16 in response to a "C" pathname
+ nak, otherwise use 8 bit checksum.
+
+ + The receiving program must accept any mixture of 128 and 1024 byte
+ blocks within each file it receives. Sending programs may
+ arbitrarily switch between 1024 and 128 byte blocks.
+
+ + The sending program must not change the length of an unacknowledged
+ block.
+
+ + At the end of each file, the sending program shall send EOT up to ten
+ times until it receives an ACK character. (This is part of the
+ XMODEM spec.)
+
+ + The end of a transfer session shall be signified by a null (empty)
+ pathname, this pathname block shall be acknowledged the same as other
+ pathname blocks.
+
+ Programs not meeting all of these requirements are not YMODEM compatible,
+ and shall not be described as supporting YMODEM.
+
+ Meeting these MINIMUM requirements does not guarantee reliable file
+
+
+
+ Chapter 2
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 5
+
+
+
+ transfers under stress. Particular attention is called to XMODEM's single
+ character supervisory messages that are easily corrupted by transmission
+ errors.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chapter 2
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 6
+
+
+
+ 3. WHY YMODEM?
+
+ Since its development half a decade ago, the Ward Christensen modem
+ protocol has enabled a wide variety of computer systems to interchange
+ data. There is hardly a communications program that doesn't at least
+ claim to support this protocol.
+
+ Advances in computing, modems and networking have revealed a number of
+ weaknesses in the original protocol:
+
+ + The short block length caused throughput to suffer when used with
+ timesharing systems, packet switched networks, satellite circuits,
+ and buffered (error correcting) modems.
+
+ + The 8 bit arithmetic checksum and other aspects allowed line
+ impairments to interfere with dependable, accurate transfers.
+
+ + Only one file could be sent per command. The file name had to be
+ given twice, first to the sending program and then again to the
+ receiving program.
+
+ + The transmitted file could accumulate as many as 127 extraneous
+ bytes.
+
+ + The modification date of the file was lost.
+
+ A number of other protocols have been developed over the years, but none
+ have displaced XMODEM to date:
+
+ + Lack of public domain documentation and example programs have kept
+ proprietary protocols such as Blast, Relay, and others tightly bound
+ to the fortunes of their suppliers.
+
+ + Complexity discourages the widespread application of BISYNC, SDLC,
+ HDLC, X.25, and X.PC protocols.
+
+ + Performance compromises and complexity have limited the popularity of
+ the Kermit protocol, which was developed to allow file transfers in
+ environments hostile to XMODEM.
+
+ The XMODEM protocol extensions and YMODEM Batch address some of these
+ weaknesses while maintaining most of XMODEM's simplicity.
+
+ YMODEM is supported by the public domain programs YAM (CP/M),
+ YAM(CP/M-86), YAM(CCPM-86), IMP (CP/M), KMD (CP/M), rz/sz (Unix, Xenix,
+ VMS, Berkeley Unix, Venix, Xenix, Coherent, IDRIS, Regulus). Commercial
+ implementations include MIRROR, and Professional-YAM.[1] Communications
+
+
+
+
+
+
+
+ Chapter 3
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 7
+
+
+
+ programs supporting these extensions have been in use since 1981.
+
+ The 1k block length (XMODEM-1k) described below may be used in conjunction
+ with YMODEM Batch Protocol, or with single file transfers identical to the
+ XMODEM/CRC protocol except for minimal changes to support 1k blocks.
+
+ Another extension is the YMODEM-g protocol. YMODEM-g provides batch
+ transfers with maximum throughput when used with end to end error
+ correcting media, such as X.PC and error correcting modems, including 9600
+ bps units by TeleBit, U.S.Robotics, Hayes, Electronic Vaults, Data Race,
+ and others.
+
+ To complete this tome, edited versions of Ward Christensen's original
+ protocol document and John Byrns's CRC-16 document are included for
+ reference.
+
+ References to the MODEM or MODEM7 protocol have been changed to XMODEM to
+ accommodate the vernacular. In Australia, it is properly called the
+ Christensen Protocol.
+
+
+ 3.1 Some Messages from the Pioneer
+
+ #: 130940 S0/Communications 25-Apr-85 18:38:47
+ Sb: my protocol
+ Fm: Ward Christensen 76703,302 [2]
+ To: all
+
+ Be aware the article[3] DID quote me correctly in terms of the phrases
+ like "not robust", etc.
+
+ It was a quick hack I threw together, very unplanned (like everything I
+ do), to satisfy a personal need to communicate with "some other" people.
+
+ ONLY the fact that it was done in 8/77, and that I put it in the public
+ domain immediately, made it become the standard that it is.
+
+
+
+
+
+
+
+ __________________________________________________________________________
+
+ 1. Available for IBM PC,XT,AT, Unix and Xenix
+
+ 2. Edited for typesetting appearance
+
+ 3. Infoworld April 29 p. 16
+
+
+
+
+ Chapter 3
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 8
+
+
+
+ I think its time for me to
+
+ (1) document it; (people call me and say "my product is going to include
+ it - what can I 'reference'", or "I'm writing a paper on it, what do I put
+ in the bibliography") and
+
+ (2) propose an "incremental extension" to it, which might take "exactly"
+ the form of Chuck Forsberg's YAM protocol. He wrote YAM in C for CP/M and
+ put it in the public domain, and wrote a batch protocol for Unix[4] called
+ rb and sb (receive batch, send batch), which was basically XMODEM with
+ (a) a record 0 containing filename date time and size
+ (b) a 1K block size option
+ (c) CRC-16.
+
+ He did some clever programming to detect false ACK or EOT, but basically
+ left them the same.
+
+ People who suggest I make SIGNIFICANT changes to the protocol, such as
+ "full duplex", "multiple outstanding blocks", "multiple destinations", etc
+ etc don't understand that the incredible simplicity of the protocol is one
+ of the reasons it survived to this day in as many machines and programs as
+ it may be found in!
+
+ Consider the PC-NET group back in '77 or so - documenting to beat the band
+ - THEY had a protocol, but it was "extremely complex", because it tried to
+ be "all things to all people" - i.e. send binary files on a 7-bit system,
+ etc. I was not that "benevolent". I (emphasize > I < ) had an 8-bit UART,
+ so "my protocol was an 8-bit protocol", and I would just say "sorry" to
+ people who were held back by 7-bit limitations. ...
+
+ Block size: Chuck Forsberg created an extension of my protocol, called
+ YAM, which is also supported via his public domain programs for UNIX
+ called rb and sb - receive batch and send batch. They cleverly send a
+ "block 0" which contains the filename, date, time, and size.
+ Unfortunately, its UNIX style, and is a bit weird[5] - octal numbers, etc.
+ BUT, it is a nice way to overcome the kludgy "echo the chars of the name"
+ introduced with MODEM7. Further, chuck uses CRC-16 and optional 1K
+ blocks. Thus the record 0, 1K, and CRC, make it a "pretty slick new
+ protocol" which is not significantly different from my own.
+
+ Also, there is a catchy name - YMODEM. That means to some that it is the
+ "next thing after XMODEM", and to others that it is the Y(am)MODEM
+
+
+ __________
+
+ 4. VAX/VMS versions of these programs are also available.
+
+ 5. The file length, time, and file mode are optional. The pathname and
+ file length may be sent alone if desired.
+
+
+
+
+ Chapter 3
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 9
+
+
+
+ protocol. I don't want to emphasize that too much - out of fear that
+ other mfgrs might think it is a "competitive" protocol, rather than an
+ "unaffiliated" protocol. Chuck is currently selling a much-enhanced
+ version of his CP/M-80 C program YAM, calling it Professional Yam, and its
+ for the PC - I'm using it right now. VERY slick! 32K capture buffer,
+ script, scrolling, previously captured text search, plus built-in commands
+ for just about everything - directory (sorted every which way), XMODEM,
+ YMODEM, KERMIT, and ASCII file upload/download, etc. You can program it
+ to "behave" with most any system - for example when trying a number for
+ CIS it detects the "busy" string back from the modem and substitutes a
+ diff phone # into the dialing string and branches back to try it.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chapter 3
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 10
+
+
+
+ 4. XMODEM PROTOCOL ENHANCEMENTS
+
+ This chapter discusses the protocol extensions to Ward Christensen's 1982
+ XMODEM protocol description document.
+
+ The original document recommends the user be asked whether to continue
+ trying or abort after 10 retries. Most programs no longer ask the
+ operator whether he wishes to keep retrying. Virtually all correctable
+ errors are corrected within the first few retransmissions. If the line is
+ so bad that ten attempts are insufficient, there is a significant danger
+ of undetected errors. If the connection is that bad, it's better to
+ redial for a better connection, or mail a floppy disk.
+
+
+ 4.1 Graceful Abort
+
+ The YAM and Professional-YAM X/YMODEM routines recognize a sequence of two
+ consecutive CAN (Hex 18) characters without modem errors (overrun,
+ framing, etc.) as a transfer abort command. This sequence is recognized
+ when is waiting for the beginning of a block or for an acknowledgement to
+ a block that has been sent. The check for two consecutive CAN characters
+ reduces the number of transfers aborted by line hits. YAM sends eight CAN
+ characters when it aborts an XMODEM, YMODEM, or ZMODEM protocol file
+ transfer. Pro-YAM then sends eight backspaces to delete the CAN
+ characters from the remote's keyboard input buffer, in case the remote had
+ already aborted the transfer and was awaiting a keyboarded command.
+
+
+ 4.2 CRC-16 Option
+
+ The XMODEM protocol uses an optional two character CRC-16 instead of the
+ one character arithmetic checksum used by the original protocol and by
+ most commercial implementations. CRC-16 guarantees detection of all
+ single and double bit errors, all errors with an odd number of error
+ bits, all burst errors of length 16 or less, 99.9969% of all 17-bit error
+ bursts, and 99.9984 per cent of all possible longer error bursts. By
+ contrast, a double bit error, or a burst error of 9 bits or more can sneak
+ past the XMODEM protocol arithmetic checksum.
+
+ The XMODEM/CRC protocol is similar to the XMODEM protocol, except that the
+ receiver specifies CRC-16 by sending C (Hex 43) instead of NAK when
+ requesting the FIRST block. A two byte CRC is sent in place of the one
+ byte arithmetic checksum.
+
+ YAM's c option to the r command enables CRC-16 in single file reception,
+ corresponding to the original implementation in the MODEM7 series
+ programs. This remains the default because many commercial communications
+ programs and bulletin board systems still do not support CRC-16,
+ especially those written in Basic or Pascal.
+
+ XMODEM protocol with CRC is accurate provided both sender and receiver
+
+
+
+ Chapter 4 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 11
+
+
+
+ both report a successful transmission. The protocol is robust in the
+ presence of characters lost by buffer overloading on timesharing systems.
+
+ The single character ACK/NAK responses generated by the receiving program
+ adapt well to split speed modems, where the reverse channel is limited to
+ ten per cent or less of the main channel's speed.
+
+ XMODEM and YMODEM are half duplex protocols which do not attempt to
+ transmit information and control signals in both directions at the same
+ time. This avoids buffer overrun problems that have been reported by
+ users attempting to exploit full duplex asynchronous file transfer
+ protocols such as Blast.
+
+ Professional-YAM adds several proprietary logic enhancements to XMODEM's
+ error detection and recovery. These compatible enhancements eliminate
+ most of the bad file transfers other programs make when using the XMODEM
+ protocol under less than ideal conditions.
+
+
+ 4.3 XMODEM-1k 1024 Byte Block
+
+ Disappointing throughput downloading from Unix with YMODEM[1] lead to the
+ development of 1024 byte blocks in 1982. 1024 byte blocks reduce the
+ effect of delays from timesharing systems, modems, and packet switched
+ networks on throughput by 87.5 per cent in addition to decreasing XMODEM's
+ 3 per cent overhead (block number, CRC, etc.).
+
+ Some environments cannot accept 1024 byte bursts, including some networks
+ and minicomputer ports. The longer block length should be an option.
+
+ The choice to use 1024 byte blocks is expressed to the sending program on
+ its command line or selection menu.[2] 1024 byte blocks improve throughput
+ in many applications.
+
+ An STX (02) replaces the SOH (01) at the beginning of the transmitted
+ block to notify the receiver of the longer block length. The transmitted
+ block contains 1024 bytes of data. The receiver should be able to accept
+ any mixture of 128 and 1024 byte blocks. The block number (in the second
+ and third bytes of the block) is incremented by one for each block
+ regardless of the block length.
+
+ The sender must not change between 128 and 1024 byte block lengths if it
+ has not received a valid ACK for the current block. Failure to observe
+
+
+ __________
+
+ 1. The name hadn't been coined yet, but the protocol was the same.
+
+ 2. See "KMD/IMP Exceptions to YMODEM" below.
+
+
+
+
+ Chapter 4 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 12
+
+
+
+ this restriction allows transmission errors to pass undetected.
+
+ If 1024 byte blocks are being used, it is possible for a file to "grow" up
+ to the next multiple of 1024 bytes. This does not waste disk space if the
+ allocation granularity is 1k or greater. With YMODEM batch transmission,
+ the optional file length transmitted in the file name block allows the
+ receiver to discard the padding, preserving the exact file length and
+ contents.
+
+ 1024 byte blocks may be used with batch file transmission or with single
+ file transmission. CRC-16 should be used with the k option to preserve
+ data integrity over phone lines. If a program wishes to enforce this
+ recommendation, it should cancel the transfer, then issue an informative
+ diagnostic message if the receiver requests checksum instead of CRC-16.
+
+ Under no circumstances may a sending program use CRC-16 unless the
+ receiver commands CRC-16.
+
+ Figure 1. XMODEM-1k Blocks
+
+ SENDER RECEIVER
+ "sx -k foo.bar"
+ "foo.bar open x.x minutes"
+ C
+ STX 01 FE Data[1024] CRC CRC
+ ACK
+ STX 02 FD Data[1024] CRC CRC
+ ACK
+ STX 03 FC Data[1000] CPMEOF[24] CRC CRC
+ ACK
+ EOT
+ ACK
+
+ Figure 2. Mixed 1024 and 128 byte Blocks
+
+ SENDER RECEIVER
+ "sx -k foo.bar"
+ "foo.bar open x.x minutes"
+ C
+ STX 01 FE Data[1024] CRC CRC
+ ACK
+ STX 02 FD Data[1024] CRC CRC
+ ACK
+ SOH 03 FC Data[128] CRC CRC
+ ACK
+ SOH 04 FB Data[100] CPMEOF[28] CRC CRC
+ ACK
+ EOT
+ ACK
+
+
+
+
+
+ Chapter 4 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 13
+
+
+
+ 5. YMODEM Batch File Transmission
+
+ The YMODEM Batch protocol is an extension to the XMODEM/CRC protocol that
+ allows 0 or more files to be transmitted with a single command. (Zero
+ files may be sent if none of the requested files is accessible.) The
+ design approach of the YMODEM Batch protocol is to use the normal routines
+ for sending and receiving XMODEM blocks in a layered fashion similar to
+ packet switching methods.
+
+ Why was it necessary to design a new batch protocol when one already
+ existed in MODEM7?[1] The batch file mode used by MODEM7 is unsuitable
+ because it does not permit full pathnames, file length, file date, or
+ other attribute information to be transmitted. Such a restrictive design,
+ hastily implemented with only CP/M in mind, would not have permitted
+ extensions to current areas of personal computing such as Unix, DOS, and
+ object oriented systems. In addition, the MODEM7 batch file mode is
+ somewhat susceptible to transmission impairments.
+
+ As in the case of single a file transfer, the receiver initiates batch
+ file transmission by sending a "C" character (for CRC-16).
+
+ The sender opens the first file and sends block number 0 with the
+ following information.[2]
+
+ Only the pathname (file name) part is required for batch transfers.
+
+ To maintain upwards compatibility, all unused bytes in block 0 must be set
+ to null.
+
+ Pathname The pathname (conventionally, the file name) is sent as a null
+ terminated ASCII string. This is the filename format used by the
+ handle oriented MSDOS(TM) functions and C library fopen functions.
+ An assembly language example follows:
+ DB 'foo.bar',0
+ No spaces are included in the pathname. Normally only the file name
+ stem (no directory prefix) is transmitted unless the sender has
+ selected YAM's f option to send the full pathname. The source drive
+ (A:, B:, etc.) is not sent.
+
+ Filename Considerations:
+
+
+
+ __________
+
+ 1. The MODEM7 batch protocol transmitted CP/M FCB bytes f1...f8 and
+ t1...t3 one character at a time. The receiver echoed these bytes as
+ received, one at a time.
+
+ 2. Only the data part of the block is described here.
+
+
+
+
+ Chapter 5 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 14
+
+
+
+ + File names are forced to lower case unless the sending system
+ supports upper/lower case file names. This is a convenience for
+ users of systems (such as Unix) which store filenames in upper
+ and lower case.
+
+ + The receiver should accommodate file names in lower and upper
+ case.
+
+ + When transmitting files between different operating systems,
+ file names must be acceptable to both the sender and receiving
+ operating systems.
+
+ If directories are included, they are delimited by /; i.e.,
+ "subdir/foo" is acceptable, "subdir\foo" is not.
+
+ Length The file length and each of the succeeding fields are optional.[3]
+ The length field is stored in the block as a decimal string counting
+ the number of data bytes in the file. The file length does not
+ include any CPMEOF (^Z) or other garbage characters used to pad the
+ last block.
+
+ If the file being transmitted is growing during transmission, the
+ length field should be set to at least the final expected file
+ length, or not sent.
+
+ The receiver stores the specified number of characters, discarding
+ any padding added by the sender to fill up the last block.
+
+ Modification Date The mod date is optional, and the filename and length
+ may be sent without requiring the mod date to be sent.
+
+ Iff the modification date is sent, a single space separates the
+ modification date from the file length.
+
+ The mod date is sent as an octal number giving the time the contents
+ of the file were last changed, measured in seconds from Jan 1 1970
+ Universal Coordinated Time (GMT). A date of 0 implies the
+ modification date is unknown and should be left as the date the file
+ is received.
+
+ This standard format was chosen to eliminate ambiguities arising from
+ transfers between different time zones.
+
+
+
+
+
+ __________
+
+ 3. Fields may not be skipped.
+
+
+
+
+ Chapter 5 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 15
+
+
+
+ Mode Iff the file mode is sent, a single space separates the file mode
+ from the modification date. The file mode is stored as an octal
+ string. Unless the file originated from a Unix system, the file mode
+ is set to 0. rb(1) checks the file mode for the 0x8000 bit which
+ indicates a Unix type regular file. Files with the 0x8000 bit set
+ are assumed to have been sent from another Unix (or similar) system
+ which uses the same file conventions. Such files are not translated
+ in any way.
+
+
+ Serial Number Iff the serial number is sent, a single space separates the
+ serial number from the file mode. The serial number of the
+ transmitting program is stored as an octal string. Programs which do
+ not have a serial number should omit this field, or set it to 0. The
+ receiver's use of this field is optional.
+
+
+ Other Fields YMODEM was designed to allow additional header fields to be
+ added as above without creating compatibility problems with older
+ YMODEM programs. Please contact Omen Technology if other fields are
+ needed for special application requirements.
+
+ The rest of the block is set to nulls. This is essential to preserve
+ upward compatibility.[4]
+
+ If the filename block is received with a CRC or other error, a
+ retransmission is requested. After the filename block has been received,
+ it is ACK'ed if the write open is successful. If the file cannot be
+ opened for writing, the receiver cancels the transfer with CAN characters
+ as described above.
+
+ The receiver then initiates transfer of the file contents with a "C"
+ character, according to the standard XMODEM/CRC protocol.
+
+ After the file contents and XMODEM EOT have been transmitted and
+ acknowledged, the receiver again asks for the next pathname.
+
+ Transmission of a null pathname terminates batch file transmission.
+
+ Note that transmission of no files is not necessarily an error. This is
+ possible if none of the files requested of the sender could be opened for
+ reading.
+
+
+
+ __________
+
+ 4. If, perchance, this information extends beyond 128 bytes (possible
+ with Unix 4.2 BSD extended file names), the block should be sent as a
+ 1k block as described above.
+
+
+
+
+ Chapter 5 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 16
+
+
+
+ Most YMODEM receivers request CRC-16 by default.
+
+ The Unix programs sz(1) and rz(1) included in the source code file
+ RZSZ.ZOO should answer other questions about YMODEM batch protocol.
+
+ Figure 3. YMODEM Batch Transmission Session (1 file)
+
+ SENDER RECEIVER
+ "sb foo.*<CR>"
+ "sending in batch mode etc."
+ C (command:rb)
+ SOH 00 FF foo.c NUL[123] CRC CRC
+ ACK
+ C
+ SOH 01 FE Data[128] CRC CRC
+ ACK
+ SOH 02 FC Data[128] CRC CRC
+ ACK
+ SOH 03 FB Data[100] CPMEOF[28] CRC CRC
+ ACK
+ EOT
+ NAK
+ EOT
+ ACK
+ C
+ SOH 00 FF NUL[128] CRC CRC
+ ACK
+
+ Figure 7. YMODEM Header Information and Features
+
+ _____________________________________________________________
+ | Program | Length | Date | Mode | S/N | 1k-Blk | YMODEM-g |
+ |___________|________|______|______|_____|________|__________|
+ |Unix rz/sz | yes | yes | yes | no | yes | sb only |
+ |___________|________|______|______|_____|________|__________|
+ |VMS rb/sb | yes | no | no | no | yes | no |
+ |___________|________|______|______|_____|________|__________|
+ |Pro-YAM | yes | yes | no | yes | yes | yes |
+ |___________|________|______|______|_____|________|__________|
+ |CP/M YAM | no | no | no | no | yes | no |
+ |___________|________|______|______|_____|________|__________|
+ |KMD/IMP | ? | no | no | no | yes | no |
+ |___________|________|______|______|_____|________|__________|
+
+ 5.1 KMD/IMP Exceptions to YMODEM
+
+ KMD and IMP use a "CK" character sequence emitted by the receiver to
+ trigger the use of 1024 byte blocks as an alternative to specifying this
+ option to the sending program. This two character sequence generally
+ works well on single process micros in direct communication, provided the
+ programs rigorously adhere to all the XMODEM recommendations included
+
+
+
+ Chapter 5 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 17
+
+
+
+ Figure 4. YMODEM Batch Transmission Session (2 files)
+
+ SENDER RECEIVER
+ "sb foo.c baz.c<CR>"
+ "sending in batch mode etc."
+ C (command:rb)
+ SOH 00 FF foo.c NUL[123] CRC CRC
+ ACK
+ C
+ SOH 01 FE Data[128] CRC CRC
+ ACK
+ SOH 02 FC Data[128] CRC CRC
+ ACK
+ SOH 03 FB Data[100] CPMEOF[28] CRC CRC
+ ACK
+ EOT
+ NAK
+ EOT
+ ACK
+ C
+ SOH 00 FF baz.c NUL[123] CRC CRC
+ ACK
+ C
+ SOH 01 FB Data[100] CPMEOF[28] CRC CRC
+ ACK
+ EOT
+ NAK
+ EOT
+ ACK
+ C
+ SOH 00 FF NUL[128] CRC CRC
+ ACK
+
+ Figure 5. YMODEM Batch Transmission Session-1k Blocks
+
+ SENDER RECEIVER
+ "sb -k foo.*<CR>"
+ "sending in batch mode etc."
+ C (command:rb)
+ SOH 00 FF foo.c NUL[123] CRC CRC
+ ACK
+ C
+ STX 01 FD Data[1024] CRC CRC
+ ACK
+ SOH 02 FC Data[128] CRC CRC
+ ACK
+ SOH 03 FB Data[100] CPMEOF[28] CRC CRC
+ ACK
+ EOT
+ NAK
+ EOT
+
+
+
+ Chapter 5 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 18
+
+
+
+ ACK
+ C
+ SOH 00 FF NUL[128] CRC CRC
+ ACK
+
+ Figure 6. YMODEM Filename block transmitted by sz
+
+ -rw-r--r-- 6347 Jun 17 1984 20:34 bbcsched.txt
+
+ 00 0100FF62 62637363 6865642E 74787400 |...bbcsched.txt.|
+ 10 36333437 20333331 34373432 35313320 |6347 3314742513 |
+ 20 31303036 34340000 00000000 00000000 |100644..........|
+ 30 00000000 00000000 00000000 00000000
+ 40 00000000 00000000 00000000 00000000
+ 50 00000000 00000000 00000000 00000000
+ 60 00000000 00000000 00000000 00000000
+ 70 00000000 00000000 00000000 00000000
+ 80 000000CA 56
+
+ herein. Programs with marginal XMODEM implementations do not fare so
+ well. Timesharing systems and packet switched networks can separate the
+ successive characters, rendering this method unreliable.
+
+ Sending programs may detect the CK sequence if the operating enviornment
+ does not preclude reliable implementation.
+
+ Instead of the standard YMODEM file length in decimal, KMD and IMP
+ transmit the CP/M record count in the last two bytes of the header block.
+
+
+ 6. YMODEM-g File Transmission
+
+ Developing technology is providing phone line data transmission at ever
+ higher speeds using very specialized techniques. These high speed modems,
+ as well as session protocols such as X.PC, provide high speed, nearly
+ error free communications at the expense of considerably increased delay
+ time.
+
+ This delay time is moderate compared to human interactions, but it
+ cripples the throughput of most error correcting protocols.
+
+ The g option to YMODEM has proven effective under these circumstances.
+ The g option is driven by the receiver, which initiates the batch transfer
+ by transmitting a G instead of C. When the sender recognizes the G, it
+ bypasses the usual wait for an ACK to each transmitted block, sending
+ succeeding blocks at full speed, subject to XOFF/XON or other flow control
+ exerted by the medium.
+
+ The sender expects an inital G to initiate the transmission of a
+ particular file, and also expects an ACK on the EOT sent at the end of
+ each file. This synchronization allows the receiver time to open and
+
+
+
+ Chapter 6 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 19
+
+
+
+ close files as necessary.
+
+ If an error is detected in a YMODEM-g transfer, the receiver aborts the
+ transfer with the multiple CAN abort sequence. The ZMODEM protocol should
+ be used in applications that require both streaming throughput and error
+ recovery.
+
+ Figure 8. YMODEM-g Transmission Session
+
+ SENDER RECEIVER
+ "sb foo.*<CR>"
+ "sending in batch mode etc..."
+ G (command:rb -g)
+ SOH 00 FF foo.c NUL[123] CRC CRC
+ G
+ SOH 01 FE Data[128] CRC CRC
+ STX 02 FD Data[1024] CRC CRC
+ SOH 03 FC Data[128] CRC CRC
+ SOH 04 FB Data[100] CPMEOF[28] CRC CRC
+ EOT
+ ACK
+ G
+ SOH 00 FF NUL[128] CRC CRC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chapter 6 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 20
+
+
+
+ 7. XMODEM PROTOCOL OVERVIEW
+
+ 8/9/82 by Ward Christensen.
+
+ I will maintain a master copy of this. Please pass on changes or
+ suggestions via CBBS/Chicago at (312) 545-8086, CBBS/CPMUG (312) 849-1132
+ or by voice at (312) 849-6279.
+
+ 7.1 Definitions
+
+ <soh> 01H
+ <eot> 04H
+ <ack> 06H
+ <nak> 15H
+ <can> 18H
+ <C> 43H
+
+
+ 7.2 Transmission Medium Level Protocol
+
+ Asynchronous, 8 data bits, no parity, one stop bit.
+
+ The protocol imposes no restrictions on the contents of the data being
+ transmitted. No control characters are looked for in the 128-byte data
+ messages. Absolutely any kind of data may be sent - binary, ASCII, etc.
+ The protocol has not formally been adopted to a 7-bit environment for the
+ transmission of ASCII-only (or unpacked-hex) data , although it could be
+ simply by having both ends agree to AND the protocol-dependent data with
+ 7F hex before validating it. I specifically am referring to the checksum,
+ and the block numbers and their ones- complement.
+
+ Those wishing to maintain compatibility of the CP/M file structure, i.e.
+ to allow modemming ASCII files to or from CP/M systems should follow this
+ data format:
+
+ + ASCII tabs used (09H); tabs set every 8.
+
+ + Lines terminated by CR/LF (0DH 0AH)
+
+ + End-of-file indicated by ^Z, 1AH. (one or more)
+
+ + Data is variable length, i.e. should be considered a continuous
+ stream of data bytes, broken into 128-byte chunks purely for the
+ purpose of transmission.
+
+ + A CP/M "peculiarity": If the data ends exactly on a 128-byte
+ boundary, i.e. CR in 127, and LF in 128, a subsequent sector
+ containing the ^Z EOF character(s) is optional, but is preferred.
+ Some utilities or user programs still do not handle EOF without ^Zs.
+
+
+
+
+
+ Chapter 7 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 21
+
+
+
+ + The last block sent is no different from others, i.e. there is no
+ "short block".
+ Figure 9. XMODEM Message Block Level Protocol
+
+ Each block of the transfer looks like:
+ <SOH><blk #><255-blk #><--128 data bytes--><cksum>
+ in which:
+ <SOH> = 01 hex
+ <blk #> = binary number, starts at 01 increments by 1, and
+ wraps 0FFH to 00H (not to 01)
+ <255-blk #> = blk # after going thru 8080 "CMA" instr, i.e.
+ each bit complemented in the 8-bit block number.
+ Formally, this is the "ones complement".
+ <cksum> = the sum of the data bytes only. Toss any carry.
+
+ 7.3 File Level Protocol
+
+ 7.3.1 Common_to_Both_Sender_and_Receiver
+ All errors are retried 10 times. For versions running with an operator
+ (i.e. NOT with XMODEM), a message is typed after 10 errors asking the
+ operator whether to "retry or quit".
+
+ Some versions of the protocol use <can>, ASCII ^X, to cancel transmission.
+ This was never adopted as a standard, as having a single "abort" character
+ makes the transmission susceptible to false termination due to an <ack>
+ <nak> or <soh> being corrupted into a <can> and aborting transmission.
+
+ The protocol may be considered "receiver driven", that is, the sender need
+ not automatically re-transmit, although it does in the current
+ implementations.
+
+
+ 7.3.2 Receive_Program_Considerations
+ The receiver has a 10-second timeout. It sends a <nak> every time it
+ times out. The receiver's first timeout, which sends a <nak>, signals the
+ transmitter to start. Optionally, the receiver could send a <nak>
+ immediately, in case the sender was ready. This would save the initial 10
+ second timeout. However, the receiver MUST continue to timeout every 10
+ seconds in case the sender wasn't ready.
+
+ Once into a receiving a block, the receiver goes into a one-second timeout
+ for each character and the checksum. If the receiver wishes to <nak> a
+ block for any reason (invalid header, timeout receiving data), it must
+ wait for the line to clear. See "programming tips" for ideas
+
+ Synchronizing: If a valid block number is received, it will be: 1) the
+ expected one, in which case everything is fine; or 2) a repeat of the
+ previously received block. This should be considered OK, and only
+ indicates that the receivers <ack> got glitched, and the sender re-
+ transmitted; 3) any other block number indicates a fatal loss of
+ synchronization, such as the rare case of the sender getting a line-glitch
+
+
+
+ Chapter 7 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 22
+
+
+
+ that looked like an <ack>. Abort the transmission, sending a <can>
+
+
+ 7.3.3 Sending_program_considerations
+ While waiting for transmission to begin, the sender has only a single very
+ long timeout, say one minute. In the current protocol, the sender has a
+ 10 second timeout before retrying. I suggest NOT doing this, and letting
+ the protocol be completely receiver-driven. This will be compatible with
+ existing programs.
+
+ When the sender has no more data, it sends an <eot>, and awaits an <ack>,
+ resending the <eot> if it doesn't get one. Again, the protocol could be
+ receiver-driven, with the sender only having the high-level 1-minute
+ timeout to abort.
+
+
+ Here is a sample of the data flow, sending a 3-block message. It includes
+ the two most common line hits - a garbaged block, and an <ack> reply
+ getting garbaged. <xx> represents the checksum byte.
+
+ Figure 10. Data flow including Error Recovery
+
+ SENDER RECEIVER
+ times out after 10 seconds,
+ <--- <nak>
+ <soh> 01 FE -data- <xx> --->
+ <--- <ack>
+ <soh> 02 FD -data- xx ---> (data gets line hit)
+ <--- <nak>
+ <soh> 02 FD -data- xx --->
+ <--- <ack>
+ <soh> 03 FC -data- xx --->
+ (ack gets garbaged) <--- <ack>
+ <soh> 03 FC -data- xx ---> <ack>
+ <eot> --->
+ <--- <anything except ack>
+ <eot> --->
+ <--- <ack>
+ (finished)
+
+ 7.4 Programming Tips
+
+ + The character-receive subroutine should be called with a parameter
+ specifying the number of seconds to wait. The receiver should first
+ call it with a time of 10, then <nak> and try again, 10 times.
+
+ After receiving the <soh>, the receiver should call the character
+ receive subroutine with a 1-second timeout, for the remainder of the
+ message and the <cksum>. Since they are sent as a continuous stream,
+ timing out of this implies a serious like glitch that caused, say,
+ 127 characters to be seen instead of 128.
+
+
+
+ Chapter 7 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 23
+
+
+
+ + When the receiver wishes to <nak>, it should call a "PURGE"
+ subroutine, to wait for the line to clear. Recall the sender tosses
+ any characters in its UART buffer immediately upon completing sending
+ a block, to ensure no glitches were mis- interpreted.
+
+ The most common technique is for "PURGE" to call the character
+ receive subroutine, specifying a 1-second timeout,[1] and looping
+ back to PURGE until a timeout occurs. The <nak> is then sent,
+ ensuring the other end will see it.
+
+ + You may wish to add code recommended by John Mahr to your character
+ receive routine - to set an error flag if the UART shows framing
+ error, or overrun. This will help catch a few more glitches - the
+ most common of which is a hit in the high bits of the byte in two
+ consecutive bytes. The <cksum> comes out OK since counting in 1-byte
+ produces the same result of adding 80H + 80H as with adding 00H +
+ 00H.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ __________
+
+ 1. These times should be adjusted for use with timesharing systems.
+
+
+
+
+ Chapter 7 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 24
+
+
+
+ 8. XMODEM/CRC Overview
+
+ Original 1/13/85 by John Byrns -- CRC option.
+
+ Please pass on any reports of errors in this document or suggestions for
+ improvement to me via Ward's/CBBS at (312) 849-1132, or by voice at (312)
+ 885-1105.
+
+ The CRC used in the Modem Protocol is an alternate form of block check
+ which provides more robust error detection than the original checksum.
+ Andrew S. Tanenbaum says in his book, Computer Networks, that the CRC-
+ CCITT used by the Modem Protocol will detect all single and double bit
+ errors, all errors with an odd number of bits, all burst errors of length
+ 16 or less, 99.997% of 17-bit error bursts, and 99.998% of 18-bit and
+ longer bursts.[1]
+
+ The changes to the Modem Protocol to replace the checksum with the CRC are
+ straight forward. If that were all that we did we would not be able to
+ communicate between a program using the old checksum protocol and one
+ using the new CRC protocol. An initial handshake was added to solve this
+ problem. The handshake allows a receiving program with CRC capability to
+ determine whether the sending program supports the CRC option, and to
+ switch it to CRC mode if it does. This handshake is designed so that it
+ will work properly with programs which implement only the original
+ protocol. A description of this handshake is presented in section 10.
+
+ Figure 11. Message Block Level Protocol, CRC mode
+
+ Each block of the transfer in CRC mode looks like:
+ <SOH><blk #><255-blk #><--128 data bytes--><CRC hi><CRC lo>
+ in which:
+ <SOH> = 01 hex
+ <blk #> = binary number, starts at 01 increments by 1, and
+ wraps 0FFH to 00H (not to 01)
+ <255-blk #> = ones complement of blk #.
+ <CRC hi> = byte containing the 8 hi order coefficients of the CRC.
+ <CRC lo> = byte containing the 8 lo order coefficients of the CRC.
+
+ 8.1 CRC Calculation
+
+ 8.1.1 Formal_Definition
+ To calculate the 16 bit CRC the message bits are considered to be the
+ coefficients of a polynomial. This message polynomial is first multiplied
+ by X^16 and then divided by the generator polynomial (X^16 + X^12 + X^5 +
+
+
+ __________
+
+ 1. This reliability figure is misleading because XMODEM's critical
+ supervisory functions are not protected by this CRC.
+
+
+
+
+ Chapter 8 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 25
+
+
+
+ 1) using modulo two arithmetic. The remainder left after the division is
+ the desired CRC. Since a message block in the Modem Protocol is 128 bytes
+ or 1024 bits, the message polynomial will be of order X^1023. The hi order
+ bit of the first byte of the message block is the coefficient of X^1023 in
+ the message polynomial. The lo order bit of the last byte of the message
+ block is the coefficient of X^0 in the message polynomial.
+
+ Figure 12. Example of CRC Calculation written in C
+
+ The following XMODEM crc routine is taken from "rbsb.c". Please refer to
+ the source code for these programs (contained in RZSZ.ZOO) for usage. A
+ fast table driven version is also included in this file.
+
+ /* update CRC */
+ unsigned short
+ updcrc(c, crc)
+ register c;
+ register unsigned crc;
+ {
+ register count;
+
+ for (count=8; --count>=0;) {
+ if (crc & 0x8000) {
+ crc <<= 1;
+ crc += (((c<<=1) & 0400) != 0);
+ crc ^= 0x1021;
+ }
+ else {
+ crc <<= 1;
+ crc += (((c<<=1) & 0400) != 0);
+ }
+ }
+ return crc;
+ }
+
+ 8.2 CRC File Level Protocol Changes
+
+ 8.2.1 Common_to_Both_Sender_and_Receiver
+ The only change to the File Level Protocol for the CRC option is the
+ initial handshake which is used to determine if both the sending and the
+ receiving programs support the CRC mode. All Modem Programs should support
+ the checksum mode for compatibility with older versions. A receiving
+ program that wishes to receive in CRC mode implements the mode setting
+ handshake by sending a <C> in place of the initial <nak>. If the sending
+ program supports CRC mode it will recognize the <C> and will set itself
+ into CRC mode, and respond by sending the first block as if a <nak> had
+ been received. If the sending program does not support CRC mode it will
+ not respond to the <C> at all. After the receiver has sent the <C> it will
+ wait up to 3 seconds for the <soh> that starts the first block. If it
+ receives a <soh> within 3 seconds it will assume the sender supports CRC
+ mode and will proceed with the file exchange in CRC mode. If no <soh> is
+
+
+
+ Chapter 8 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 26
+
+
+
+ received within 3 seconds the receiver will switch to checksum mode, send
+ a <nak>, and proceed in checksum mode. If the receiver wishes to use
+ checksum mode it should send an initial <nak> and the sending program
+ should respond to the <nak> as defined in the original Modem Protocol.
+ After the mode has been set by the initial <C> or <nak> the protocol
+ follows the original Modem Protocol and is identical whether the checksum
+ or CRC is being used.
+
+
+ 8.2.2 Receive_Program_Considerations
+ There are at least 4 things that can go wrong with the mode setting
+ handshake.
+
+ 1. the initial <C> can be garbled or lost.
+
+ 2. the initial <soh> can be garbled.
+
+ 3. the initial <C> can be changed to a <nak>.
+
+ 4. the initial <nak> from a receiver which wants to receive in checksum
+ can be changed to a <C>.
+
+ The first problem can be solved if the receiver sends a second <C> after
+ it times out the first time. This process can be repeated several times.
+ It must not be repeated too many times before sending a <nak> and
+ switching to checksum mode or a sending program without CRC support may
+ time out and abort. Repeating the <C> will also fix the second problem if
+ the sending program cooperates by responding as if a <nak> were received
+ instead of ignoring the extra <C>.
+
+ It is possible to fix problems 3 and 4 but probably not worth the trouble
+ since they will occur very infrequently. They could be fixed by switching
+ modes in either the sending or the receiving program after a large number
+ of successive <nak>s. This solution would risk other problems however.
+
+
+ 8.2.3 Sending_Program_Considerations
+ The sending program should start in the checksum mode. This will insure
+ compatibility with checksum only receiving programs. Anytime a <C> is
+ received before the first <nak> or <ack> the sending program should set
+ itself into CRC mode and respond as if a <nak> were received. The sender
+ should respond to additional <C>s as if they were <nak>s until the first
+ <ack> is received. This will assist the receiving program in determining
+ the correct mode when the <soh> is lost or garbled. After the first <ack>
+ is received the sending program should ignore <C>s.
+
+
+
+
+
+
+
+
+
+ Chapter 8 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 27
+
+
+
+ 8.3 Data Flow Examples with CRC Option
+
+ Here is a data flow example for the case where the receiver requests
+ transmission in the CRC mode but the sender does not support the CRC
+ option. This example also includes various transmission errors. <xx>
+ represents the checksum byte.
+
+ Figure 13. Data Flow: Receiver has CRC Option, Sender Doesn't
+
+ SENDER RECEIVER
+ <--- <C>
+ times out after 3 seconds,
+ <--- <C>
+ times out after 3 seconds,
+ <--- <C>
+ times out after 3 seconds,
+ <--- <C>
+ times out after 3 seconds,
+ <--- <nak>
+ <soh> 01 FE -data- <xx> --->
+ <--- <ack>
+ <soh> 02 FD -data- <xx> ---> (data gets line hit)
+ <--- <nak>
+ <soh> 02 FD -data- <xx> --->
+ <--- <ack>
+ <soh> 03 FC -data- <xx> --->
+ (ack gets garbaged) <--- <ack>
+ times out after 10 seconds,
+ <--- <nak>
+ <soh> 03 FC -data- <xx> --->
+ <--- <ack>
+ <eot> --->
+ <--- <ack>
+
+ Here is a data flow example for the case where the receiver requests
+ transmission in the CRC mode and the sender supports the CRC option. This
+ example also includes various transmission errors. <xxxx> represents the
+ 2 CRC bytes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chapter 8 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 28
+
+
+
+ Figure 14. Receiver and Sender Both have CRC Option
+
+ SENDER RECEIVER
+ <--- <C>
+ <soh> 01 FE -data- <xxxx> --->
+ <--- <ack>
+ <soh> 02 FD -data- <xxxx> ---> (data gets line hit)
+ <--- <nak>
+ <soh> 02 FD -data- <xxxx> --->
+ <--- <ack>
+ <soh> 03 FC -data- <xxxx> --->
+ (ack gets garbaged) <--- <ack>
+ times out after 10 seconds,
+ <--- <nak>
+ <soh> 03 FC -data- <xxxx> --->
+ <--- <ack>
+ <eot> --->
+ <--- <ack>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chapter 8 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 29
+
+
+
+ 9. MORE INFORMATION
+
+ Please contact Omen Technology for troff source files and typeset copies
+ of this document.
+
+
+ 9.1 TeleGodzilla Bulletin Board
+
+ More information may be obtained by calling TeleGodzilla at 503-621-3746.
+ Speed detection is automatic for 1200, 2400 and 19200(Telebit PEP) bps.
+ TrailBlazer modem users may issue the TeleGodzilla trailblazer command to
+ swith to 19200 bps once they have logged in.
+
+ Interesting files include RZSZ.ZOO (C source code), YZMODEM.ZOO (Official
+ XMODEM, YMODEM, and ZMODEM protocol descriptions), ZCOMMEXE.ARC,
+ ZCOMMDOC.ARC, and ZCOMMHLP.ARC (PC-DOS shareware comm program with XMODEM,
+ True YMODEM(TM), ZMODEM, Kermit Sliding Windows, Telink, MODEM7 Batch,
+ script language, etc.).
+
+
+ 9.2 Unix UUCP Access
+
+ UUCP sites can obtain the current version of this file with
+ uucp omen!/u/caf/public/ymodem.doc /tmp
+ A continually updated list of available files is stored in
+ /usr/spool/uucppublic/FILES. When retrieving these files with uucp,
+ remember that the destination directory on your system must be writeable
+ by anyone, or the UUCP transfer will fail.
+
+ The following L.sys line calls TeleGodzilla (Pro-YAM in host operation).
+ TeleGodzilla determines the incoming speed automatically.
+
+ In response to "Name Please:" uucico gives the Pro-YAM "link" command as a
+ user name. The password (Giznoid) controls access to the Xenix system
+ connected to the IBM PC's other serial port. Communications between
+ Pro-YAM and Xenix use 9600 bps; YAM converts this to the caller's speed.
+
+ Finally, the calling uucico logs in as uucp.
+
+ omen Any ACU 2400 1-503-621-3746 se:--se: link ord: Giznoid in:--in: uucp
+
+
+
+ 10. REVISIONS
+
+ 6-18-88 Further revised for clarity. Corrected block numbering in two
+ examples.
+ 10-27-87 Optional fields added for number of files remaining to be sent
+ and total number of bytes remaining to be sent.
+ 10-18-87 Flow control discussion added to 1024 byte block descritpion,
+ minor revisions for clarity per user comments.
+
+
+
+ Chapter 10 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 30
+
+
+
+ 8-03-87 Revised for clarity.
+ 5-31-1987 emphasizes minimum requirements for YMODEM, and updates
+ information on accessing files.
+ 9-11-1986 clarifies nomenclature and some minor points.
+ The April 15 1986 edition clarifies some points concerning CRC
+ calculations and spaces in the header.
+
+
+ 11. YMODEM Programs
+
+ ZCOMM, A shareware little brother to Professional-YAM, is available as
+ ZCOMMEXE.ARC on TeleGodzilla and other bulletin board systems. ZCOMM may
+ be used to test YMODEM amd ZMODEM implementations.
+
+ Unix programs supporting YMODEM are available on TeleGodzilla in RZSZ.ZOO.
+ This ZOO archive includes a ZCOMM/Pro-YAM/PowerCom script ZUPL.T to upload
+ a bootstrap program MINIRB.C, compile it, and then upload the rest of the
+ files using the compiled MINIRB. Most Unix like systems are supported,
+ including V7, Xenix, Sys III, 4.2 BSD, SYS V, Idris, Coherent, and
+ Regulus.
+
+ A version for VAX-VMS is available in VRBSB.SHQ.
+
+ Irv Hoff has added 1k blocks and basic YMODEM batch transfers to the KMD
+ and IMP series programs, which replace the XMODEM and MODEM7/MDM7xx series
+ respectively. Overlays are available for a wide variety of CP/M systems.
+
+ Questions about Professional-YAM communications software may be directed
+ to:
+ Chuck Forsberg
+ Omen Technology Inc
+ 17505-V Sauvie Island Road
+ Portland Oregon 97231
+ VOICE: 503-621-3406 :VOICE
+ Modem: 503-621-3746 Speed: 19200(Telebit PEP),2400,1200,300
+ Usenet: ...!tektronix!reed!omen!caf
+ CompuServe: 70007,2304
+ GEnie: CAF
+
+ Unlike ZMODEM and Kermit, XMODEM and YMODEM place obstacles in the path of
+ a reliable high performance implementation, evidenced by poor reliability
+ under stress of the industry leaders' XMODEM and YMODEM programs. Omen
+ Technology provides consulting and other services to those wishing to
+ implement XMODEM, YMODEM, and ZMODEM with state of the art features and
+ reliability.
+
+
+
+
+
+
+
+
+
+ Chapter 11 Xmodem Protocol Overview
+
+
+
+
+
+
+
+
+
+
+
+ CONTENTS
+
+
+ 1. TOWER OF BABEL................................................... 2
+ 1.1 Definitions................................................. 2
+
+ 2. YMODEM MINIMUM REQUIREMENTS...................................... 4
+
+ 3. WHY YMODEM?...................................................... 6
+ 3.1 Some Messages from the Pioneer.............................. 7
+
+ 4. XMODEM PROTOCOL ENHANCEMENTS..................................... 10
+ 4.1 Graceful Abort.............................................. 10
+ 4.2 CRC-16 Option............................................... 10
+ 4.3 XMODEM-1k 1024 Byte Block................................... 11
+
+ 5. YMODEM Batch File Transmission................................... 13
+ 5.1 KMD/IMP Exceptions to YMODEM................................ 16
+
+ 6. YMODEM-g File Transmission....................................... 18
+
+ 7. XMODEM PROTOCOL OVERVIEW......................................... 20
+ 7.1 Definitions................................................. 20
+ 7.2 Transmission Medium Level Protocol.......................... 20
+ 7.3 File Level Protocol......................................... 21
+ 7.4 Programming Tips............................................ 22
+
+ 8. XMODEM/CRC Overview.............................................. 24
+ 8.1 CRC Calculation............................................. 24
+ 8.2 CRC File Level Protocol Changes............................. 25
+ 8.3 Data Flow Examples with CRC Option.......................... 27
+
+ 9. MORE INFORMATION................................................. 29
+ 9.1 TeleGodzilla Bulletin Board................................. 29
+ 9.2 Unix UUCP Access............................................ 29
+
+ 10. REVISIONS........................................................ 29
+
+ 11. YMODEM Programs.................................................. 30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - i -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ LIST OF FIGURES
+
+
+ Figure 1. XMODEM-1k Blocks.......................................... 12
+
+ Figure 2. Mixed 1024 and 128 byte Blocks............................ 12
+
+ Figure 3. YMODEM Batch Transmission Session (1 file)................ 16
+
+ Figure 4. YMODEM Batch Transmission Session (2 files)............... 16
+
+ Figure 5. YMODEM Batch Transmission Session-1k Blocks............... 16
+
+ Figure 6. YMODEM Filename block transmitted by sz................... 16
+
+ Figure 7. YMODEM Header Information and Features.................... 16
+
+ Figure 8. YMODEM-g Transmission Session............................. 19
+
+ Figure 9. XMODEM Message Block Level Protocol....................... 21
+
+ Figure 10. Data flow including Error Recovery........................ 22
+
+ Figure 11. Message Block Level Protocol, CRC mode.................... 24
+
+ Figure 12. Example of CRC Calculation written in C................... 25
+
+ Figure 13. Data Flow: Receiver has CRC Option, Sender Doesn't........ 27
+
+ Figure 14. Receiver and Sender Both have CRC Option.................. 28
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - ii -
+
+
+
+
diff --git a/memdump/ymsend.c b/memdump/ymsend.c
new file mode 100644
index 00000000..b4b16a55
--- /dev/null
+++ b/memdump/ymsend.c
@@ -0,0 +1,167 @@
+/*
+ * Ymodem send routine. Only supports 1K blocks and CRC mode.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include "ymsend.h"
+
+enum {
+ SOH = 0x01,
+ STX = 0x02,
+ EOT = 0x04,
+ ACK = 0x06,
+ NAK = 0x15,
+ CAN = 0x18,
+};
+
+/*
+ * Append a CRC16 to a block
+ */
+static void add_crc16(uint8_t *blk, int len)
+{
+ static const uint16_t crctab[256] = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+ };
+ uint16_t crc = 0;
+
+ while (len--)
+ crc = crctab[(crc >> 8) ^ *blk++] ^ crc << 8;
+
+ *blk++ = crc >> 8;
+ *blk = crc;
+}
+
+static void send_ack_blk(struct serial_if *sif, const void *data, size_t bytes)
+{
+ uint8_t ack_buf;
+
+ if (bytes)
+ sif->write(sif, data, bytes);
+
+ do {
+ do {
+ sif->read(sif, &ack_buf, 1);
+ } while (ack_buf != ACK && ack_buf != NAK);
+ } while (ack_buf == NAK);
+}
+
+static const uint8_t eot_buf = EOT;
+
+void send_ymodem(struct serial_if *sif, struct file_info *fileinfo,
+ void (*gen_data)(void *, size_t, struct file_info *, size_t))
+{
+ uint8_t ack_buf, blk_buf[1024+5], *np, *q;
+ const char *p;
+ size_t len, lx, pos;
+ int blk;
+
+ /* Wait for initial handshake */
+ printf("Waiting for handshake...\n");
+ do {
+ sif->read(sif, &ack_buf, 1);
+ } while (ack_buf != 'C');
+
+ /* Send initial batch header (filename, length etc.) */
+ q = blk_buf + 3;
+ p = fileinfo->name;
+ while (*p)
+ *q++ = *p++;
+ *q++ = '\0';
+
+ lx = len = fileinfo->size;
+ do {
+ q++;
+ lx /= 10;
+ } while (lx);
+
+ np = q;
+ lx = len;
+ do {
+ *--np = (lx % 10) + '0';
+ lx /= 10;
+ } while (lx);
+
+ while (q < blk_buf+1024+3)
+ *q++ = 0;
+
+ blk = 0;
+ pos = 0;
+ do {
+ if (blk != 0) {
+ gen_data(blk_buf+3, 1024, fileinfo, pos);
+ pos += 1024;
+ len = (len < 1024) ? 0 : len-1024;
+ }
+
+ blk_buf[0] = STX;
+ blk_buf[1] = blk;
+ blk_buf[2] = ~blk;
+ add_crc16(blk_buf+3, 1024);
+
+ printf("Sending block %d...\r", blk);
+ send_ack_blk(sif, blk_buf, 1024+5);
+
+ blk++;
+ } while(len);
+
+ printf("\nSending EOT...\n");
+ send_ack_blk(sif, &eot_buf, 1);
+ printf("Done.\n");
+}
+
+void end_ymodem(struct serial_if *sif)
+{
+ uint8_t ack_buf;
+ uint8_t blk_buf[128+5];
+
+ /* Wait for initial handshake */
+ printf("END: Waiting for handshake...\n");
+ do {
+ sif->read(sif, &ack_buf, 1);
+ } while (ack_buf != 'C');
+
+ memset(blk_buf, 0, sizeof blk_buf);
+ blk_buf[0] = SOH;
+ blk_buf[1] = 0;
+ blk_buf[2] = 0xff;
+ add_crc16(blk_buf+3, 128);
+ printf("Sending block 0...\n");
+ send_ack_blk(sif, &blk_buf, 128+5);
+
+ printf("Sending EOT...\n");
+ sif->write(sif, &eot_buf, 1);
+ /* rb doesn't ack the EOT for an end batch transfer. */
+ printf("Done.\n");
+}
diff --git a/memdump/ymsend.h b/memdump/ymsend.h
new file mode 100644
index 00000000..9bcd5403
--- /dev/null
+++ b/memdump/ymsend.h
@@ -0,0 +1,27 @@
+#ifndef YMSEND_H
+#define YMSEND_H
+
+#include "mystuff.h"
+
+struct serial_if {
+ int port;
+ void *pvt;
+ void (*read)(struct serial_if *, void *, size_t);
+ void (*write)(struct serial_if *, const void *, size_t);
+};
+
+struct file_info {
+ const char *name;
+ size_t size;
+ void *pvt;
+};
+
+void send_ymodem(struct serial_if *, struct file_info *,
+ void (*)(void *, size_t, struct file_info *, size_t));
+void end_ymodem(struct serial_if *);
+
+int serial_init(struct serial_if *sif);
+void serial_read(struct serial_if *sif, void *data, size_t n);
+void serial_write(struct serial_if *sif, const void *data, size_t n);
+
+#endif /* YMSEND_H */