diff options
author | Sebastian Schmelzer | 2010-10-25 16:53:54 +0200 |
---|---|---|
committer | Sebastian Schmelzer | 2010-10-25 16:53:54 +0200 |
commit | 3050a9253437f4a4b5ad4bf3b3efdc3c660a5137 (patch) | |
tree | 91ac22153e416aac7ca20916b314b5e2ffa871b1 /contrib/syslinux-4.02/com32/sysdump | |
download | preboot-master.tar.gz preboot-master.tar.xz preboot-master.zip |
Diffstat (limited to 'contrib/syslinux-4.02/com32/sysdump')
26 files changed, 4182 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/com32/sysdump/Makefile b/contrib/syslinux-4.02/com32/sysdump/Makefile new file mode 100644 index 0000000..bffee3a --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/Makefile @@ -0,0 +1,60 @@ +## ----------------------------------------------------------------------- +## +## Copyright 2001-2008 H. Peter Anvin - All Rights Reserved +## Copyright 2010 Intel Corporation; author: H. Peter Anvin +## +## 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., 51 Franklin St, Fifth Floor, +## Boston MA 02110-1301, USA; either version 2 of the License, or +## (at your option) any later version; incorporated herein by reference. +## +## ----------------------------------------------------------------------- + +## +## Simple menu system +## + +topdir = ../.. +include ../MCONFIG +-include $(topdir)/version.mk + +LIBS = ../libutil/libutil_com.a ../lib/libcom32.a $(LIBGCC) +LNXLIBS = ../libutil/libutil_lnx.a + +MODULES = sysdump.c32 +TESTFILES = + +SRCS = $(wildcard *.c) +OBJS = $(patsubst %.c,%.o,$(SRCS)) + +# The DATE is set on the make command line when building binaries for +# official release. Otherwise, substitute a hex string that is pretty much +# guaranteed to be unique to be unique from build to build. +ifndef HEXDATE +HEXDATE := $(shell $(PERL) $(topdir)/now.pl $(SRCS) $(wildcard *.h)) +endif +ifndef DATE +DATE := $(shell sh $(topdir)/gen-id.sh $(VERSION) $(HEXDATE)) +endif + +CFLAGS += -DDATE='"$(DATE)"' + +all: $(MODULES) $(TESTFILES) + +sysdump.elf : $(OBJS) $(LIBS) $(C_LIBS) + $(LD) $(LDFLAGS) -o $@ $^ + +tidy dist: + rm -f *.o *.lo *.a *.lst *.elf .*.d *.tmp + +clean: tidy + rm -f *.lnx + +spotless: clean + rm -f *.lss *.c32 *.com + rm -f *~ \#* + +install: + +-include .*.d diff --git a/contrib/syslinux-4.02/com32/sysdump/README b/contrib/syslinux-4.02/com32/sysdump/README new file mode 100644 index 0000000..2b82577 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/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/contrib/syslinux-4.02/com32/sysdump/acpi.c b/contrib/syslinux-4.02/com32/sysdump/acpi.c new file mode 100644 index 0000000..8671fc8 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/acpi.c @@ -0,0 +1,259 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * 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., 51 Franklin St, Fifth Floor, + * Boston MA 02110-1301, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * Dump ACPI information + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "sysdump.h" +#include "backend.h" +#include "rbtree.h" + +struct acpi_rsdp { + uint8_t magic[8]; /* "RSD PTR " */ + uint8_t csum; + char oemid[6]; + uint8_t rev; + uint32_t rsdt_addr; + uint32_t len; + uint64_t xsdt_addr; + uint8_t xcsum; + uint8_t rsvd[3]; +}; + +struct acpi_hdr { + char sig[4]; /* Signature */ + uint32_t len; + uint8_t rev; + uint8_t csum; + char oemid[6]; + char oemtblid[16]; + uint32_t oemrev; + uint32_t creatorid; + uint32_t creatorrev; +}; + +struct acpi_rsdt { + struct acpi_hdr hdr; + uint32_t entry[0]; +}; + +struct acpi_xsdt { + struct acpi_hdr hdr; + uint64_t entry[0]; +}; + +static struct rbtree *rb_types, *rb_addrs; + +static bool rb_has(struct rbtree **tree, uint64_t key) +{ + struct rbtree *node; + + node = rb_search(*tree, key); + if (node && node->key == key) + return true; + + node = malloc(sizeof *node); + if (node) { + node->key = key; + *tree = rb_insert(*tree, node); + } + return false; +} + +static inline bool addr_ok(uint64_t addr) +{ + /* We can only handle 32-bit addresses for now... */ + return addr <= 0xffffffff; +} + +enum tbl_errs { + ERR_NONE, /* No errors */ + ERR_CSUM, /* Invalid checksum */ + ERR_SIZE, /* Impossibly large table */ + ERR_NOSIG /* No signature */ +}; + +static uint8_t checksum_range(const void *start, uint32_t size) +{ + const uint8_t *p = start; + uint8_t csum = 0; + + while (size--) + csum += *p++; + + return csum; +} + +static enum tbl_errs is_valid_table(const void *ptr) +{ + const struct acpi_hdr *hdr = ptr; + + if (hdr->sig[0] == 0) + return ERR_NOSIG; + + if (hdr->len < 10 || hdr->len > (1 << 20)) { + /* Either insane or too large to dump */ + return ERR_SIZE; + } + + return checksum_range(hdr, hdr->len) == 0 ? ERR_NONE : ERR_CSUM; +} + +static const struct acpi_rsdp *scan_for_rsdp(uint32_t base, uint32_t end) +{ + for (base &= ~15; base < end-20; base += 16) { + const struct acpi_rsdp *rsdp = (const struct acpi_rsdp *)base; + + if (memcmp(rsdp->magic, "RSD PTR ", 8)) + continue; + + if (checksum_range(rsdp, 20)) + continue; + + if (rsdp->rev > 0) { + if (base + rsdp->len >= end || + checksum_range(rsdp, rsdp->len)) + continue; + } + + return rsdp; + } + + return NULL; +} + +static const struct acpi_rsdp *find_rsdp(void) +{ + uint32_t ebda; + const struct acpi_rsdp *rsdp; + + ebda = (*(uint16_t *)0x40e) << 4; + if (ebda >= 0x70000 && ebda < 0xa0000) { + rsdp = scan_for_rsdp(ebda, ebda+1024); + + if (rsdp) + return rsdp; + } + + return scan_for_rsdp(0xe0000, 0x100000); +} + +static void dump_table(struct backend *be, + const char name[], const void *ptr, uint32_t len) +{ + char namebuf[64]; + uint32_t name_key = *(uint32_t *)name; + + if (rb_has(&rb_addrs, (size_t)ptr)) + return; /* Already dumped this table */ + + if (!rb_has(&rb_types, name_key)) { + snprintf(namebuf, sizeof namebuf, "acpi/%4.4s", name); + cpio_mkdir(be, namebuf); + } + + snprintf(namebuf, sizeof namebuf, "acpi/%4.4s/%08x", name, (uint32_t)ptr); + cpio_hdr(be, MODE_FILE, len, namebuf); + + write_data(be, ptr, len); +} + +static void dump_rsdt(struct backend *be, const struct acpi_rsdp *rsdp) +{ + const struct acpi_rsdt *rsdt; + uint32_t i, n; + + rsdt = (const struct acpi_rsdt *)rsdp->rsdt_addr; + + if (memcmp(rsdt->hdr.sig, "RSDT", 4) || is_valid_table(rsdt) > ERR_CSUM) + return; + + dump_table(be, rsdt->hdr.sig, rsdt, rsdt->hdr.len); + + if (rsdt->hdr.len < 36) + return; + + n = (rsdt->hdr.len - 36) >> 2; + + for (i = 0; i < n; i++) { + const struct acpi_hdr *hdr = (const struct acpi_hdr *)(rsdt->entry[i]); + + if (is_valid_table(hdr) <= ERR_CSUM) + dump_table(be, hdr->sig, hdr, hdr->len); + } +} + +static void dump_xsdt(struct backend *be, const struct acpi_rsdp *rsdp) +{ + const struct acpi_xsdt *xsdt; + uint32_t rsdp_len = rsdp->rev > 0 ? rsdp->len : 20; + uint32_t i, n; + + if (rsdp_len < 34) + return; + + if (!addr_ok(rsdp->xsdt_addr)) + return; + + xsdt = (const struct acpi_xsdt *)(size_t)rsdp->xsdt_addr; + + if (memcmp(xsdt->hdr.sig, "XSDT", 4) || is_valid_table(xsdt) > ERR_CSUM) + return; + + dump_table(be, xsdt->hdr.sig, xsdt, xsdt->hdr.len); + + if (xsdt->hdr.len < 36) + return; + + n = (xsdt->hdr.len - 36) >> 3; + + for (i = 0; i < n; i++) { + const struct acpi_hdr *hdr; + if (addr_ok(xsdt->entry[i])) { + hdr = (const struct acpi_hdr *)(size_t)(xsdt->entry[i]); + + if (is_valid_table(hdr) <= ERR_CSUM) + dump_table(be, hdr->sig, hdr, hdr->len); + } + } +} + +void dump_acpi(struct backend *be) +{ + const struct acpi_rsdp *rsdp; + uint32_t rsdp_len; + + rsdp = find_rsdp(); + + printf("Dumping ACPI... "); + + if (!rsdp) + return; /* No ACPI information found */ + + cpio_mkdir(be, "acpi"); + + rsdp_len = rsdp->rev > 0 ? rsdp->len : 20; + + dump_table(be, "RSDP", rsdp, rsdp_len); + + dump_rsdt(be, rsdp); + dump_xsdt(be, rsdp); + + rb_destroy(rb_types); + rb_destroy(rb_addrs); + + printf("done.\n"); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/backend.h b/contrib/syslinux-4.02/com32/sysdump/backend.h new file mode 100644 index 0000000..f2b3bc2 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/backend.h @@ -0,0 +1,55 @@ +#ifndef BACKEND_H +#define BACKEND_H + +#include <stddef.h> +#include <inttypes.h> +#include <stdbool.h> +#include <zlib.h> +#include "serial.h" + +/* Backend flags */ +#define BE_NEEDLEN 0x01 + +struct backend { + const char *name; + const char *helpmsg; + int minargs; + + size_t dbytes; + size_t zbytes; + const char **argv; + + uint32_t now; + + int (*write)(struct backend *); + + z_stream zstream; + char *outbuf; + size_t alloc; +}; + +/* zout.c */ +int init_data(struct backend *be, const char *argv[]); +int write_data(struct backend *be, const void *buf, size_t len); +int flush_data(struct backend *be); + +/* cpio.c */ +#define cpio_init init_data +int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen, + const char *filename); +int cpio_mkdir(struct backend *be, const char *filename); +int cpio_writefile(struct backend *be, const char *filename, + const void *data, size_t len); +int cpio_close(struct backend *be); +#define MODE_FILE 0100644 +#define MODE_DIR 0040755 + +/* backends.c */ +struct backend *get_backend(const char *name); + +/* backends */ +extern struct backend be_tftp; +extern struct backend be_ymodem; +extern struct backend be_srec; + +#endif /* BACKEND_H */ diff --git a/contrib/syslinux-4.02/com32/sysdump/be_srec.c b/contrib/syslinux-4.02/com32/sysdump/be_srec.c new file mode 100644 index 0000000..fc69c88 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/be_srec.c @@ -0,0 +1,85 @@ +/* + * S-records dump routine -- dumps S-records on the console + */ + +#include <string.h> +#include <stdio.h> +#include <inttypes.h> +#include <minmax.h> +#include "backend.h" + +/* Write a single S-record */ +static int write_srecord(unsigned int len, unsigned int alen, + uint32_t addr, uint8_t type, const void *data) +{ + char buf[2+2+8+255*2+2+2]; + char *p = buf; + uint8_t csum; + const uint8_t *dptr = data; + unsigned int i; + + switch (alen) { + case 2: + addr &= 0xffff; + break; + case 3: + addr &= 0xffffff; + break; + case 4: + break; + } + + csum = (len+alen+1) + addr + (addr >> 8) + (addr >> 16) + (addr >> 24); + for (i = 0; i < len; i++) + csum += dptr[i]; + csum = 0xff-csum; + + p += sprintf(p, "S%c%02X%0*X", type, len+alen+1, alen*2, addr); + for (i = 0; i < len; i++) + p += sprintf(p, "%02X", dptr[i]); + p += sprintf(p, "%02X\n", csum); + + fputs(buf, stdout); + return 0; +} + +static int be_srec_write(struct backend *be) +{ + char name[33]; + const char *buf; + size_t len, chunk, offset, hdrlen; + + buf = be->outbuf; + len = be->zbytes; + + putchar('\n'); + + hdrlen = snprintf(name, sizeof name, "%.32s", + be->argv[0] ? be->argv[0] : ""); + + /* Write head record */ + write_srecord(hdrlen, 2, 0, '0', name); + + /* Write data records */ + offset = 0; + while (len) { + chunk = min(len, (size_t)32); + + write_srecord(chunk, 4, offset, '3', buf); + buf += chunk; + len -= chunk; + offset += chunk; + } + + /* Write termination record */ + write_srecord(0, 4, 0, '7', NULL); + + return 0; +} + +struct backend be_srec = { + .name = "srec", + .helpmsg = "[filename]", + .minargs = 0, + .write = be_srec_write, +}; diff --git a/contrib/syslinux-4.02/com32/sysdump/be_tftp.c b/contrib/syslinux-4.02/com32/sysdump/be_tftp.c new file mode 100644 index 0000000..36a91eb --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/be_tftp.c @@ -0,0 +1,178 @@ +/* + * TFTP data output backend + */ + +#include <string.h> +#include <stdio.h> +#include <syslinux/pxe.h> +#include <syslinux/config.h> +#include <netinet/in.h> +#include <sys/times.h> + +#include "backend.h" + +enum tftp_opcode { + TFTP_RRQ = 1, + TFTP_WRQ = 2, + TFTP_DATA = 3, + TFTP_ACK = 4, + TFTP_ERROR = 5, +}; + +struct tftp_state { + uint32_t my_ip; + uint32_t srv_ip; + uint32_t srv_gw; + uint16_t my_port; + uint16_t srv_port; + uint16_t seq; +}; + +#define RCV_BUF 2048 + +static int send_ack_packet(struct tftp_state *tftp, + const void *pkt, size_t len) +{ + com32sys_t ireg, oreg; + t_PXENV_UDP_WRITE *uw; + t_PXENV_UDP_READ *ur; + clock_t start; + static const clock_t timeouts[] = { + 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, + 37, 44, 53, 64, 77, 92, 110, 132, 159, 191, 229, 0 + }; + const clock_t *timeout; + int err = -1; + + uw = lmalloc(sizeof *uw + len); + ur = lmalloc(sizeof *ur + RCV_BUF); + + memset(&ireg, 0, sizeof ireg); + ireg.eax.w[0] = 0x0009; + + for (timeout = timeouts ; *timeout ; timeout++) { + memset(uw, 0, sizeof uw); + memcpy(uw+1, pkt, len); + uw->ip = tftp->srv_ip; + uw->gw = tftp->srv_gw; + uw->src_port = tftp->my_port; + uw->dst_port = tftp->srv_port ? tftp->srv_port : htons(69); + uw->buffer_size = len; + uw->buffer = FAR_PTR(uw+1); + + ireg.ebx.w[0] = PXENV_UDP_WRITE; + ireg.es = SEG(uw); + ireg.edi.w[0] = OFFS(uw); + + __intcall(0x22, &ireg, &oreg); + + start = times(NULL); + + do { + memset(ur, 0, sizeof ur); + ur->src_ip = tftp->srv_ip; + ur->dest_ip = tftp->my_ip; + ur->s_port = tftp->srv_port; + ur->d_port = tftp->my_port; + ur->buffer_size = RCV_BUF; + ur->buffer = FAR_PTR(ur+1); + + ireg.ebx.w[0] = PXENV_UDP_READ; + ireg.es = SEG(ur); + ireg.edi.w[0] = OFFS(ur); + __intcall(0x22, &ireg, &oreg); + + if (!(oreg.eflags.l & EFLAGS_CF) && + ur->status == PXENV_STATUS_SUCCESS && + tftp->srv_ip == ur->src_ip && + (tftp->srv_port == 0 || + tftp->srv_port == ur->s_port)) { + uint16_t *xb = (uint16_t *)(ur+1); + if (ntohs(xb[0]) == TFTP_ACK && + ntohs(xb[1]) == tftp->seq) { + tftp->srv_port = ur->s_port; + err = 0; /* All good! */ + goto done; + } else if (ntohs(xb[1]) == TFTP_ERROR) { + goto done; + } + } + } while ((clock_t)(times(NULL) - start) < *timeout); + } + +done: + lfree(ur); + lfree(uw); + + return err; +} + +static int be_tftp_write(struct backend *be) +{ + static uint16_t local_port = 0x4000; + struct tftp_state tftp; + char buffer[512+4+6]; + int nlen; + const union syslinux_derivative_info *sdi = + syslinux_derivative_info(); + const char *data = be->outbuf; + size_t len = be->zbytes; + size_t chunk; + + tftp.my_ip = sdi->pxe.myip; + tftp.my_port = htons(local_port++); + tftp.srv_gw = ((tftp.srv_ip ^ tftp.my_ip) & sdi->pxe.ipinfo->netmask) + ? sdi->pxe.ipinfo->gateway : 0; + tftp.srv_port = 0; + tftp.seq = 0; + + if (be->argv[1]) { + tftp.srv_ip = pxe_dns(be->argv[1]); + if (!tftp.srv_ip) { + printf("\nUnable to resolve hostname: %s\n", be->argv[1]); + return -1; + } + } else { + tftp.srv_ip = sdi->pxe.ipinfo->serverip; + if (!tftp.srv_ip) { + printf("\nNo server IP address\n"); + return -1; + } + } + + printf("server %u.%u.%u.%u... ", + ((uint8_t *)&tftp.srv_ip)[0], + ((uint8_t *)&tftp.srv_ip)[1], + ((uint8_t *)&tftp.srv_ip)[2], + ((uint8_t *)&tftp.srv_ip)[3]); + + buffer[0] = 0; + buffer[1] = TFTP_WRQ; + nlen = strlcpy(buffer+2, be->argv[0], 512); + memcpy(buffer+3+nlen, "octet", 6); + + if (send_ack_packet(&tftp, buffer, 2+nlen+1+6)) + return -1; + + do { + chunk = len >= 512 ? 512 : len; + + buffer[1] = TFTP_DATA; + *((uint16_t *)(buffer+2)) = htons(++tftp.seq); + memcpy(buffer+4, data, chunk); + data += chunk; + len -= chunk; + + if (send_ack_packet(&tftp, buffer, chunk+4)) + return -1; + } while (chunk == 512); + + return 0; +} + +struct backend be_tftp = { + .name = "tftp", + .helpmsg = "filename [tftp_server]", + .minargs = 1, + .write = be_tftp_write, +}; diff --git a/contrib/syslinux-4.02/com32/sysdump/be_ymodem.c b/contrib/syslinux-4.02/com32/sysdump/be_ymodem.c new file mode 100644 index 0000000..316b3d4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/be_ymodem.c @@ -0,0 +1,175 @@ +/* + * Ymodem send routine. Only supports 1K blocks and CRC mode. + */ + +#include <string.h> +#include <stdio.h> +#include <inttypes.h> +#include "backend.h" +#include "serial.h" + +enum { + SOH = 0x01, + STX = 0x02, + EOT = 0x04, + ACK = 0x06, + NAK = 0x15, + CAN = 0x18, +}; + +struct ymodem_state { + struct serial_if serial; + unsigned int seq, blocks; +}; + +/* + * 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(struct ymodem_state *ym, const uint8_t *blk, + size_t bytes); + +static void send_ack_blk(struct ymodem_state *ym, uint8_t *blk) +{ + printf("Sending block %u/%u...\r", ym->seq, ym->blocks); + + blk[0] = STX; + blk[1] = ym->seq++; + blk[2] = ~blk[1]; + add_crc16(blk+3, 1024); + + send_ack(ym, blk, 1024+5); +} + +static void send_ack(struct ymodem_state *ym, const uint8_t *blk, size_t bytes) +{ + uint8_t ack_buf; + + do { + serial_write(&ym->serial, blk, bytes); + + do { + serial_read(&ym->serial, &ack_buf, 1); + } while (ack_buf != ACK && ack_buf != NAK); + } while (ack_buf == NAK); +} + +static int be_ymodem_write(struct backend *be) +{ + static const uint8_t eot_buf = EOT; + uint8_t ack_buf; + uint8_t blk_buf[1024 + 5]; + struct ymodem_state ym; + const char *buf; + size_t len, chunk; + const char ymodem_banner[] = "Now begin Ymodem download...\r\n"; + + buf = be->outbuf; + len = be->zbytes; + + putchar('\n'); + + ym.seq = 0; + ym.blocks = (len+1023)/1024; + + /* Initialize serial port */ + if (serial_init(&ym.serial, &be->argv[1])) + return -1; + + /* Write banner */ + printf("Writing banner...\n"); + serial_write(&ym.serial, ymodem_banner, sizeof ymodem_banner-1); + + /* Wait for initial handshake */ + printf("Waiting for handshake...\n"); + do { + serial_read(&ym.serial, &ack_buf, 1); + } while (ack_buf != 'C'); + + /* Send filename block */ + memset(blk_buf, 0, sizeof blk_buf); + snprintf((char *)blk_buf+3, 1024, "%s%c%zu 0%o 0644", + be->argv[0], 0, be->zbytes, be->now); + send_ack_blk(&ym, blk_buf); + + while (len) { + chunk = len < 1024 ? len : 1024; + + memcpy(blk_buf+3, buf, chunk); + if (chunk < 1024) + memset(blk_buf+3+chunk, 0x1a, 1024-chunk); + + send_ack_blk(&ym, blk_buf); + buf += chunk; + len -= chunk; + } + + printf("\nSending EOT...\n"); + send_ack(&ym, &eot_buf, 1); + + printf("Waiting for handshake...\n"); + do { + serial_read(&ym.serial, &ack_buf, 1); + } while (ack_buf != 'C'); + ym.seq = 0; + + printf("Sending batch termination block...\n"); + memset(blk_buf+3, 0, 1024); + send_ack_blk(&ym, blk_buf); + + printf("Cleaning up... \n"); + serial_cleanup(&ym.serial); + + return 0; +} + +struct backend be_ymodem = { + .name = "ymodem", + .helpmsg = "filename [port [speed]]", + .minargs = 1, + .write = be_ymodem_write, +}; diff --git a/contrib/syslinux-4.02/com32/sysdump/cpio.c b/contrib/syslinux-4.02/com32/sysdump/cpio.c new file mode 100644 index 0000000..81d0d4b --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/cpio.c @@ -0,0 +1,75 @@ +/* + * cpio.c + * + * Write a compressed CPIO file + */ + +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include <stdbool.h> +#include <zlib.h> +#include "backend.h" +#include "ctime.h" + +int cpio_pad(struct backend *be) +{ + static char pad[4]; /* Up to 4 zero bytes */ + if (be->dbytes & 3) + return write_data(be, pad, -be->dbytes & 3); + else + return 0; +} + +int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen, + const char *filename) +{ + static uint32_t inode = 2; + char hdr[6+13*8+1]; + int nlen = strlen(filename)+1; + int rv = 0; + + cpio_pad(be); + + sprintf(hdr, "%06o%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", + 070701, /* c_magic */ + inode++, /* c_ino */ + mode, /* c_mode */ + 0, /* c_uid */ + 0, /* c_gid */ + 1, /* c_nlink */ + be->now, /* c_mtime */ + datalen, /* c_filesize */ + 0, /* c_maj */ + 0, /* c_min */ + 0, /* c_rmaj */ + 0, /* c_rmin */ + nlen, /* c_namesize */ + 0); /* c_chksum */ + rv |= write_data(be, hdr, 6+13*8); + rv |= write_data(be, filename, nlen); + rv |= cpio_pad(be); + return rv; +} + +int cpio_mkdir(struct backend *be, const char *filename) +{ + return cpio_hdr(be, MODE_DIR, 0, filename); +} + +int cpio_writefile(struct backend *be, const char *filename, + const void *data, size_t len) +{ + int rv; + + rv = cpio_hdr(be, MODE_FILE, len, filename); + rv |= write_data(be, data, len); + rv |= cpio_pad(be); + + return rv; +} + +int cpio_close(struct backend *be) +{ + return cpio_hdr(be, 0, 0, "TRAILER!!!"); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/cpuid.c b/contrib/syslinux-4.02/com32/sysdump/cpuid.c new file mode 100644 index 0000000..372a70d --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/cpuid.c @@ -0,0 +1,91 @@ +/* + * Dump CPUID information + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <com32.h> +#include <sys/cpu.h> +#include "sysdump.h" +#include "backend.h" + +struct cpuid_data { + uint32_t eax, ebx, ecx, edx; +}; + +struct cpuid_info { + uint32_t eax, ecx; + struct cpuid_data data; +}; + +static void get_cpuid(uint32_t eax, uint32_t ecx, struct cpuid_data *data) +{ + asm("pushl %%ebx ; cpuid ; movl %%ebx,%1 ; popl %%ebx" + : "=a" (data->eax), "=r" (data->ebx), + "=c" (data->ecx), "=d" (data->edx) + : "a" (eax), "c" (ecx)); +} + +#define CPUID_CHUNK 128 + +void dump_cpuid(struct backend *be) +{ + struct cpuid_info *buf = NULL; + int nentry, nalloc; + uint32_t region; + struct cpuid_data base_leaf; + uint32_t base, leaf, count; + struct cpuid_data invalid_leaf; + struct cpuid_data data; + + if (!cpu_has_eflag(EFLAGS_ID)) + return; + + printf("Dumping CPUID... "); + + nentry = nalloc = 0; + + /* Find out what the CPU returns for invalid leaves */ + get_cpuid(0, 0, &base_leaf); + get_cpuid(base_leaf.eax+1, 0, &invalid_leaf); + + for (region = 0 ; region <= 0xffff ; region++) { + base = region << 16; + + get_cpuid(base, 0, &base_leaf); + if (region && !memcmp(&base_leaf, &invalid_leaf, sizeof base_leaf)) + continue; + + if ((base_leaf.eax ^ base) & 0xffff0000) + continue; + + for (leaf = base ; leaf <= base_leaf.eax ; leaf++) { + get_cpuid(leaf, 0, &data); + count = 0; + + do { + if (nentry >= nalloc) { + nalloc += CPUID_CHUNK; + buf = realloc(buf, nalloc*sizeof *buf); + if (!buf) + return; /* FAILED */ + } + buf[nentry].eax = leaf; + buf[nentry].ecx = count; + buf[nentry].data = data; + nentry++; + count++; + + get_cpuid(leaf, count, &data); + } while (memcmp(&data, &buf[nentry-1].data, sizeof data) && + (data.eax | data.ebx | data.ecx | data.edx)); + } + } + + if (nentry) + cpio_writefile(be, "cpuid", buf, nentry*sizeof *buf); + free(buf); + + printf("done.\n"); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/ctime.c b/contrib/syslinux-4.02/com32/sysdump/ctime.c new file mode 100644 index 0000000..56c8efb --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/ctime.c @@ -0,0 +1,77 @@ +#include <com32.h> +#include <string.h> +#include "ctime.h" + +static uint8_t frombcd(uint8_t v) +{ + uint8_t a = v & 0x0f; + uint8_t b = v >> 4; + + return a + b*10; +} + +uint32_t posix_time(void) +{ + /* Days from March 1 for a specific month, starting in March */ + static const unsigned int yday[12] = + { 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337 }; + com32sys_t ir, d0, d1, t0; + unsigned int c, y, mo, d, h, m, s; + uint32_t t; + + memset(&ir, 0, sizeof ir); + + ir.eax.b[1] = 0x04; + __intcall(0x1A, &ir, &d0); + + ir.eax.b[1] = 0x02; + __intcall(0x1A, &ir, &t0); + + ir.eax.b[1] = 0x04; + __intcall(0x1A, &ir, &d1); + + if (t0.ecx.b[1] < 0x12) + d0 = d1; + + c = frombcd(d0.ecx.b[1]); + y = frombcd(d0.ecx.b[0]); + mo = frombcd(d0.edx.b[1]); + d = frombcd(d0.edx.b[0]); + + h = frombcd(t0.ecx.b[1]); + m = frombcd(t0.ecx.b[0]); + s = frombcd(t0.edx.b[1]); + + /* We of course have no idea about the timezone, so ignore it */ + + /* + * Look for impossible dates... this code was written in 2010, so + * assume any century less than 20 is just broken. + */ + if (c < 20) + c = 20; + y += c*100; + + /* Consider Jan and Feb as the last months of the previous year */ + if (mo < 3) { + y--; + mo += 12; + } + + /* + * Just in case: if the month is nonsense, don't read off the end + * of the table... + */ + if (mo-3 > 11) + return 0; + + t = y*365 + y/4 - y/100 + y/400 + yday[mo-3] + d - 719469; + t *= 24; + t += h; + t *= 60; + t += m; + t *= 60; + t += s; + + return t; +} diff --git a/contrib/syslinux-4.02/com32/sysdump/ctime.h b/contrib/syslinux-4.02/com32/sysdump/ctime.h new file mode 100644 index 0000000..e646125 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/ctime.h @@ -0,0 +1,8 @@ +#ifndef CTIME_H +#define CTIME_H + +#include <inttypes.h> + +uint32_t posix_time(void); + +#endif /* CTIME_H */ diff --git a/contrib/syslinux-4.02/com32/sysdump/data.h b/contrib/syslinux-4.02/com32/sysdump/data.h new file mode 100644 index 0000000..deacf72 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/data.h @@ -0,0 +1,2 @@ +#ifndef DATA_H +#define DATA_H diff --git a/contrib/syslinux-4.02/com32/sysdump/dmi.c b/contrib/syslinux-4.02/com32/sysdump/dmi.c new file mode 100644 index 0000000..be4cce4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/dmi.c @@ -0,0 +1,126 @@ +/* + * Dump DMI information in a way hopefully compatible with dmidecode + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "sysdump.h" +#include "backend.h" + +struct dmi_header { + char signature[5]; + uint8_t csum; + uint16_t tbllen; + uint32_t tbladdr; + uint16_t nstruc; + uint8_t revision; + uint8_t reserved; +}; + +struct smbios_header { + char signature[4]; + uint8_t csum; + uint8_t len; + uint8_t major; + uint8_t minor; + uint16_t maxsize; + uint8_t revision; + uint8_t fmt[5]; + + struct dmi_header dmi; +}; + +static uint8_t checksum(const void *buf, size_t len) +{ + const uint8_t *p = buf; + uint8_t csum = 0; + + while (len--) + csum += *p++; + + return csum; +} + +static bool is_old_dmi(size_t dptr) +{ + const struct dmi_header *dmi = (void *)dptr; + + return !memcmp(dmi->signature, "_DMI_", 5) && + !checksum(dmi, 0x0f); + return false; +} + +static bool is_smbios(size_t dptr) +{ + const struct smbios_header *smb = (void *)dptr; + + return !memcmp(smb->signature, "_SM_", 4) && + !checksum(smb, smb->len) && + is_old_dmi(dptr+16); +} + +static void dump_smbios(struct backend *be, size_t dptr) +{ + const struct smbios_header *smb = (void *)dptr; + struct smbios_header smx = *smb; + char filename[32]; + + snprintf(filename, sizeof filename, "dmi/%05x.%08x", + dptr, smb->dmi.tbladdr); + cpio_hdr(be, MODE_FILE, smb->dmi.tbllen + 32, filename); + + /* + * Adjust the address of the smbios table to be 32, to + * make dmidecode happy. The checksum on the smbios table is unchanged, + * since it includes the checksum on the dmi table. + */ + smx.dmi.tbladdr = sizeof smx; + smx.dmi.csum -= checksum(&smx.dmi, 0x0f); + + write_data(be, &smx, sizeof smx); + write_data(be, (const void *)smb->dmi.tbladdr, smb->dmi.tbllen); +} + +static void dump_old_dmi(struct backend *be, size_t dptr) +{ + const struct dmi_header *dmi = (void *)dptr; + struct fake { + struct dmi_header dmi; + char pad[16]; + } fake; + char filename[32]; + + snprintf(filename, sizeof filename, "dmi/%05x.%08x", + dptr, dmi->tbladdr); + cpio_hdr(be, MODE_FILE, dmi->tbllen + 32, filename); + + /* + * Adjust the address of the smbios table to be 32, to + * make dmidecode happy. + */ + fake.dmi = *dmi; + memset(&fake.pad, 0, sizeof fake.pad); + fake.dmi.tbladdr = sizeof fake; + fake.dmi.csum -= checksum(&fake.dmi, 0x0f); + + write_data(be, &fake, sizeof fake); + write_data(be, (const void *)dmi->tbladdr, dmi->tbllen); +} + +void dump_dmi(struct backend *be) +{ + size_t dptr; + + cpio_mkdir(be, "dmi"); + + /* Search for _SM_ or _DMI_ structure */ + for (dptr = 0xf0000 ; dptr < 0x100000 ; dptr += 16) { + if (is_smbios(dptr)) { + dump_smbios(be, dptr); + dptr += 16; /* Skip the subsequent DMI header */ + } else if (is_old_dmi(dptr)) { + dump_old_dmi(be, dptr); + } + } +} diff --git a/contrib/syslinux-4.02/com32/sysdump/main.c b/contrib/syslinux-4.02/com32/sysdump/main.c new file mode 100644 index 0000000..d0d40a7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/main.c @@ -0,0 +1,99 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * Copyright 2010 Intel Corporation; author: H. Peter Anvin + * + * 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 <stdbool.h> +#include <inttypes.h> +#include <dprintf.h> +#include <console.h> +#include <sys/cpu.h> +#include "../../version.h" +#include "backend.h" +#include "sysdump.h" + +const char program[] = "sysdump"; +const char version[] = "SYSDUMP " VERSION_STR " " DATE "\n"; + +__noreturn die(const char *msg) +{ + printf("%s: %s\n", program, msg); + exit(1); +} + +static void dump_all(struct backend *be, const char *argv[]) +{ + cpio_init(be, argv); + + cpio_writefile(be, "sysdump", version, sizeof version-1); + + dump_memory_map(be); + dump_memory(be); + dump_dmi(be); + dump_acpi(be); + dump_cpuid(be); + dump_pci(be); + dump_vesa_tables(be); + + cpio_close(be); + flush_data(be); +} + +static struct backend *backends[] = +{ + &be_tftp, + &be_ymodem, + &be_srec, + NULL +}; + +__noreturn usage(void) +{ + struct backend **bep, *be; + + printf("Usage:\n"); + for (bep = backends ; (be = *bep) ; bep++) + printf(" %s %s %s\n", program, be->name, be->helpmsg); + + exit(1); +} + +int main(int argc, char *argv[]) +{ + struct backend **bep, *be; + + openconsole(&dev_null_r, &dev_stdcon_w); + fputs(version, stdout); + + if (argc < 2) + usage(); + + for (bep = backends ; (be = *bep) ; bep++) { + if (!strcmp(be->name, argv[1])) + break; + } + + if (!be || argc < be->minargs + 2) + usage(); + + /* Do this as early as possible */ + snapshot_lowmem(); + + printf("Backend: %s\n", be->name); + + /* Do the actual data dump */ + dump_all(be, (const char **)argv + 2); + + return 0; +} diff --git a/contrib/syslinux-4.02/com32/sysdump/memmap.c b/contrib/syslinux-4.02/com32/sysdump/memmap.c new file mode 100644 index 0000000..251107d --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/memmap.c @@ -0,0 +1,85 @@ +/* + * Dump memory map information + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <com32.h> +#include "sysdump.h" +#include "backend.h" + +#define E820_CHUNK 128 +struct e820_info { + uint32_t ebx; + uint32_t len; + uint8_t data[24]; +}; + +static void dump_e820(struct backend *be) +{ + com32sys_t ireg, oreg; + struct e820_info *curr; + struct e820_info *buf, *p; + int nentry, nalloc; + + curr = lmalloc(sizeof *curr); + + buf = p = NULL; + nentry = nalloc = 0; + memset(&ireg, 0, sizeof ireg); + memset(&curr, 0, sizeof curr); + + ireg.eax.l = 0xe820; + ireg.edx.l = 0x534d4150; + ireg.ecx.l = sizeof curr->data; + ireg.es = SEG(curr->data); + ireg.edi.w[0] = OFFS(curr->data); + + do { + __intcall(0x15, &ireg, &oreg); + if ((oreg.eflags.l & EFLAGS_CF) || + oreg.eax.l != 0x534d4150) + break; + + if (nentry >= nalloc) { + nalloc += E820_CHUNK; + buf = realloc(buf, nalloc*sizeof *buf); + if (!buf) + return; /* FAILED */ + } + memcpy(buf[nentry].data, curr->data, sizeof curr->data); + buf[nentry].ebx = ireg.ebx.l; + buf[nentry].len = oreg.ecx.l; + nentry++; + + ireg.ebx.l = oreg.ebx.l; + } while (ireg.ebx.l); + + if (nentry) + cpio_writefile(be, "memmap/15e820", buf, nentry*sizeof *buf); + + free(buf); + lfree(curr); +} + +void dump_memory_map(struct backend *be) +{ + com32sys_t ireg, oreg; + + cpio_mkdir(be, "memmap"); + + memset(&ireg, 0, sizeof ireg); + __intcall(0x12, &ireg, &oreg); + cpio_writefile(be, "memmap/12", &oreg, sizeof oreg); + + ireg.eax.b[1] = 0x88; + __intcall(0x15, &ireg, &oreg); + cpio_writefile(be, "memmap/1588", &oreg, sizeof oreg); + + ireg.eax.w[0] = 0xe801; + __intcall(0x15, &ireg, &oreg); + cpio_writefile(be, "memmap/15e801", &oreg, sizeof oreg); + + dump_e820(be); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/memory.c b/contrib/syslinux-4.02/com32/sysdump/memory.c new file mode 100644 index 0000000..6552e7f --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/memory.c @@ -0,0 +1,51 @@ +/* + * Dump memory + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/cpu.h> +#include "sysdump.h" +#include "backend.h" + +static char *lowmem; +static size_t lowmem_len; + +void *zero_addr; /* Hack to keep gcc from complaining */ + +void snapshot_lowmem(void) +{ + extern void _start(void); + + lowmem_len = (size_t)_start; + lowmem = malloc(lowmem_len); + if (lowmem) { + printf("Snapshotting lowmem... "); + cli(); + memcpy(lowmem, zero_addr, lowmem_len); + sti(); + printf("ok\n"); + } +} + +static void dump_memory_range(struct backend *be, const void *where, + const void *addr, size_t len) +{ + char filename[32]; + + sprintf(filename, "memory/%08zx", (size_t)addr); + cpio_writefile(be, filename, where, len); +} + +void dump_memory(struct backend *be) +{ + printf("Dumping memory... "); + + cpio_mkdir(be, "memory"); + + if (lowmem) + dump_memory_range(be, lowmem, zero_addr, lowmem_len); + + printf("done.\n"); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/pci.c b/contrib/syslinux-4.02/com32/sysdump/pci.c new file mode 100644 index 0000000..1d68727 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/pci.c @@ -0,0 +1,70 @@ +/* + * Dump PCI device headers + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/pci.h> +#include "sysdump.h" +#include "backend.h" + +static void dump_pci_device(struct backend *be, pciaddr_t a, uint8_t hdrtype) +{ + unsigned int bus = pci_bus(a); + unsigned int dev = pci_dev(a); + unsigned int func = pci_func(a); + uint8_t data[256]; + unsigned int i; + char filename[32]; + + hdrtype &= 0x7f; + + printf("Scanning PCI bus... %02x:%02x.%x\r", bus, dev, func); + + /* Assume doing a full device dump is actually safe... */ + for (i = 0; i < sizeof data; i += 4) + *(uint32_t *)(data+i) = pci_readl(a + i); + + snprintf(filename, sizeof filename, "pci/%02x:%02x.%x", + bus, dev, func); + cpio_writefile(be, filename, data, sizeof data); +} + +void dump_pci(struct backend *be) +{ + int cfgtype; + unsigned int nbus, ndev, nfunc, maxfunc; + pciaddr_t a; + uint32_t did; + uint8_t hdrtype; + + cfgtype = pci_set_config_type(PCI_CFG_AUTO); + if (cfgtype == PCI_CFG_NONE) + return; + + cpio_mkdir(be, "pci"); + + for (nbus = 0; nbus < MAX_PCI_BUSES; nbus++) { + for (ndev = 0; ndev < MAX_PCI_DEVICES; ndev++) { + maxfunc = 1; /* Assume a single-function device */ + + for (nfunc = 0; nfunc < maxfunc; nfunc++) { + a = pci_mkaddr(nbus, ndev, nfunc, 0); + did = pci_readl(a); + + if (did == 0xffffffff || did == 0xffff0000 || + did == 0x0000ffff || did == 0x00000000) + continue; + + hdrtype = pci_readb(a + 0x0e); + if (hdrtype & 0x80) + maxfunc = MAX_PCI_FUNC; /* Multifunction device */ + + dump_pci_device(be, a, hdrtype); + } + } + } + + printf("Scanning PCI bus... done. \n"); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/rbtree.c b/contrib/syslinux-4.02/com32/sysdump/rbtree.c new file mode 100644 index 0000000..1d10e09 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/rbtree.c @@ -0,0 +1,132 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +/* + * rbtree.c + * + * Simple implementation of a left-leaning red-black tree with 64-bit + * integer keys. The search operation will return the highest node <= + * the key; only search and insert are supported, but additional + * standard llrbtree operations can be coded up at will. + * + * See http://www.cs.princeton.edu/~rs/talks/LLRB/RedBlack.pdf for + * information about left-leaning red-black trees. + */ + +#include <stdlib.h> +#include "rbtree.h" + +struct rbtree *rb_search(struct rbtree *tree, uint64_t key) +{ + struct rbtree *best = NULL; + + while (tree) { + if (tree->key == key) + return tree; + else if (tree->key > key) + tree = tree->left; + else { + best = tree; + tree = tree->right; + } + } + return best; +} + +static bool is_red(struct rbtree *h) +{ + return h && h->red; +} + +static struct rbtree *rotate_left(struct rbtree *h) +{ + struct rbtree *x = h->right; + h->right = x->left; + x->left = h; + x->red = x->left->red; + x->left->red = true; + return x; +} + +static struct rbtree *rotate_right(struct rbtree *h) +{ + struct rbtree *x = h->left; + h->left = x->right; + x->right = h; + x->red = x->right->red; + x->right->red = true; + return x; +} + +static void color_flip(struct rbtree *h) +{ + h->red = !h->red; + h->left->red = !h->left->red; + h->right->red = !h->right->red; +} + +struct rbtree *rb_insert(struct rbtree *tree, struct rbtree *node) +{ + node->left = node->right = NULL; + node->red = false; + + if (!tree) { + node->red = true; + return node; + } + + if (is_red(tree->left) && is_red(tree->right)) + color_flip(tree); + + if (node->key < tree->key) + tree->left = rb_insert(tree->left, node); + else + tree->right = rb_insert(tree->right, node); + + if (is_red(tree->right)) + tree = rotate_left(tree); + + if (is_red(tree->left) && is_red(tree->left->left)) + tree = rotate_right(tree); + + return tree; +} + +void rb_destroy(struct rbtree *tree) +{ + if (tree->left) + rb_destroy(tree->left); + if (tree->right) + rb_destroy(tree->right); + free(tree); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/rbtree.h b/contrib/syslinux-4.02/com32/sysdump/rbtree.h new file mode 100644 index 0000000..dcdcd6b --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/rbtree.h @@ -0,0 +1,53 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 1996-2009 The NASM Authors - All Rights Reserved + * See the file AUTHORS included with the NASM distribution for + * the specific copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following + * conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ----------------------------------------------------------------------- */ + +#ifndef NASM_RBTREE_H +#define NASM_RBTREE_H + +#include <inttypes.h> +#include <stdbool.h> + +/* This structure should be embedded in a larger data structure; + the final output from rb_search() can then be converted back + to the larger data structure via container_of(). */ +struct rbtree { + uint64_t key; + struct rbtree *left, *right; + bool red; +}; + +struct rbtree *rb_insert(struct rbtree *, struct rbtree *); +struct rbtree *rb_search(struct rbtree *, uint64_t); +void rb_destroy(struct rbtree *); + +#endif /* NASM_RBTREE_H */ diff --git a/contrib/syslinux-4.02/com32/sysdump/serial.c b/contrib/syslinux-4.02/com32/sysdump/serial.c new file mode 100644 index 0000000..a398753 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/serial.c @@ -0,0 +1,169 @@ +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <console.h> +#include <sys/io.h> +#include <sys/cpu.h> +#include <syslinux/config.h> + +#include "serial.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, const char *argv[]) +{ + const struct syslinux_serial_console_info *sci + = syslinux_serial_console_info(); + uint16_t port; + unsigned int divisor; + uint8_t dll, dlm, lcr; + + if (!argv[0]) { + if (sci->iobase) { + port = sci->iobase; + } else { + printf("No port number specified and not using serial console!\n"); + return -1; + } + } else { + port = strtoul(argv[0], NULL, 0); + if (port <= 3) { + uint16_t addr = ((uint16_t *)0x400)[port]; + if (!addr) { + printf("No serial port address found!\n"); + return -1; + } + printf("Serial port %u is at 0x%04x\n", port, addr); + port = addr; + } + } + + sif->port = port; + sif->console = false; + + divisor = 1; /* Default speed = 115200 bps */ + + /* Check to see if this is the same as the serial console */ + if (port == sci->iobase) { + /* Overlaying the console... */ + sif->console = true; + + /* Default to already configured speed */ + divisor = sci->divisor; + + /* Shut down I/O to the console for the time being */ + openconsole(&dev_null_r, &dev_null_w); + } + + if (argv[0] && argv[1]) + divisor = 115200/strtoul(argv[1], NULL, 0); + + cli(); /* Just in case... */ + + /* Save old register settings */ + sif->old.lcr = inb(port + LCR); + sif->old.mcr = inb(port + MCR); + sif->old.iir = inb(port + IIR); + + /* Set speed */ + outb(0x83, port + LCR); /* Enable divisor access */ + sif->old.dll = inb(port + DLL); + sif->old.dlm = inb(port + DLM); + outb(divisor, port + DLL); + outb(divisor >> 8, port + DLM); + (void)inb(port + IER); /* Synchronize */ + + dll = inb(port + DLL); + dlm = inb(port + DLM); + lcr = inb(port + LCR); + outb(0x03, port + LCR); /* Enable data access, n81 */ + (void)inb(port + IER); /* Synchronize */ + sif->old.ier = inb(port + IER); + + /* Disable interrupts */ + outb(0, port + IER); + + sti(); + + if (dll != (uint8_t)divisor || + dlm != (uint8_t)(divisor >> 8) || + lcr != 0x83) { + serial_cleanup(sif); + printf("No serial port detected!\n"); + return -1; /* This doesn't look like a serial port */ + } + + /* Enable 16550A FIFOs if available */ + outb(0x01, port + FCR); /* Enable FIFO */ + (void)inb(port + IER); /* Synchronize */ + if (inb(port + IIR) < 0xc0) + outb(0x00, port + FCR); /* 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); + } +} + +void serial_cleanup(struct serial_if *sif) +{ + uint16_t port = sif->port; + + outb(0x83, port + LCR); + (void)inb(port + IER); + outb(sif->old.dll, port + DLL); + outb(sif->old.dlm, port + DLM); + (void)inb(port + IER); + outb(sif->old.lcr & 0x7f, port + LCR); + (void)inb(port + IER); + outb(sif->old.mcr, port + MCR); + outb(sif->old.ier, port + IER); + if (sif->old.iir < 0xc0) + outb(0x00, port + FCR); /* Disable FIFOs */ + + /* Re-enable console messages, if we shut them down */ + if (sif->console) + openconsole(&dev_null_r, &dev_stdcon_w); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/serial.h b/contrib/syslinux-4.02/com32/sysdump/serial.h new file mode 100644 index 0000000..356f2ce --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/serial.h @@ -0,0 +1,19 @@ +#ifndef SERIAL_H +#define SERIAL_H + +#include <stddef.h> + +struct serial_if { + uint16_t port; + bool console; + struct { + uint8_t dll, dlm, ier, iir, lcr, mcr; + } old; +}; + +int serial_init(struct serial_if *sif, const char *argv[]); +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); +void serial_cleanup(struct serial_if *sif); + +#endif /* SERIAL_H */ diff --git a/contrib/syslinux-4.02/com32/sysdump/srecsend.h b/contrib/syslinux-4.02/com32/sysdump/srecsend.h new file mode 100644 index 0000000..667be20 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/srecsend.h @@ -0,0 +1,9 @@ +#ifndef SRECSEND_H +#define SRECSEND_H + +#include "file.h" + +void send_srec(struct serial_if *, struct file_info *, + void (*)(void *, size_t, struct file_info *, size_t)); + +#endif /* SRECSEND_H */ diff --git a/contrib/syslinux-4.02/com32/sysdump/sysdump.h b/contrib/syslinux-4.02/com32/sysdump/sysdump.h new file mode 100644 index 0000000..a5b963f --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/sysdump.h @@ -0,0 +1,15 @@ +#ifndef SYSDUMP_H +#define SYSDUMP_H + +struct backend; + +void dump_memory_map(struct backend *); +void snapshot_lowmem(void); +void dump_memory(struct backend *); +void dump_dmi(struct backend *); +void dump_acpi(struct backend *); +void dump_cpuid(struct backend *); +void dump_pci(struct backend *); +void dump_vesa_tables(struct backend *); + +#endif /* SYSDUMP_H */ diff --git a/contrib/syslinux-4.02/com32/sysdump/vesa.c b/contrib/syslinux-4.02/com32/sysdump/vesa.c new file mode 100644 index 0000000..017f9e4 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/vesa.c @@ -0,0 +1,63 @@ +#include <string.h> +#include <stdio.h> +#include "../lib/sys/vesa/vesa.h" +#include "backend.h" +#include "sysdump.h" + +void dump_vesa_tables(struct backend *be) +{ + com32sys_t rm; + struct vesa_info *vip; + struct vesa_general_info *gip, gi; + struct vesa_mode_info *mip, mi; + uint16_t mode, *mode_ptr; + char modefile[64]; + + printf("Scanning VESA BIOS... "); + + /* Allocate space in the bounce buffer for these structures */ + vip = lmalloc(sizeof *vip); + gip = &vip->gi; + mip = &vip->mi; + + memset(&rm, 0, sizeof rm); + memset(gip, 0, sizeof *gip); + + gip->signature = VBE2_MAGIC; /* Get VBE2 extended data */ + rm.eax.w[0] = 0x4F00; /* Get SVGA general information */ + rm.edi.w[0] = OFFS(gip); + rm.es = SEG(gip); + __intcall(0x10, &rm, &rm); + memcpy(&gi, gip, sizeof gi); + + if (rm.eax.w[0] != 0x004F) + return; /* Function call failed */ + if (gi.signature != VESA_MAGIC) + return; /* No magic */ + + cpio_mkdir(be, "vesa"); + + cpio_writefile(be, "vesa/global.bin", &gi, sizeof gi); + + mode_ptr = GET_PTR(gi.video_mode_ptr); + while ((mode = *mode_ptr++) != 0xFFFF) { + memset(mip, 0, sizeof *mip); + rm.eax.w[0] = 0x4F01; /* Get SVGA mode information */ + rm.ecx.w[0] = mode; + rm.edi.w[0] = OFFS(mip); + rm.es = SEG(mip); + __intcall(0x10, &rm, &rm); + + /* Must be a supported mode */ + if (rm.eax.w[0] != 0x004f) + continue; + + memcpy(&mi, mip, sizeof mi); + + sprintf(modefile, "vesa/mode%04x.bin", mode); + cpio_writefile(be, modefile, &mi, sizeof mi); + } + + lfree(vip); + printf("done.\n"); +} diff --git a/contrib/syslinux-4.02/com32/sysdump/ymodem.txt b/contrib/syslinux-4.02/com32/sysdump/ymodem.txt new file mode 100644 index 0000000..2264ff7 --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/ymodem.txt @@ -0,0 +1,2108 @@ + + + + - 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/contrib/syslinux-4.02/com32/sysdump/zout.c b/contrib/syslinux-4.02/com32/sysdump/zout.c new file mode 100644 index 0000000..ece934c --- /dev/null +++ b/contrib/syslinux-4.02/com32/sysdump/zout.c @@ -0,0 +1,99 @@ +/* + * Compress input and feed it to a block-oriented back end. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <stdbool.h> +#include <zlib.h> +#include "backend.h" +#include "ctime.h" + +#define ALLOC_CHUNK 65536 + +int init_data(struct backend *be, const char *argv[]) +{ + be->now = posix_time(); + be->argv = argv; + + memset(&be->zstream, 0, sizeof be->zstream); + + be->zstream.next_out = NULL; + be->outbuf = NULL; + be->zstream.avail_out = be->alloc = 0; + be->dbytes = be->zbytes = 0; + + /* Initialize a gzip data stream */ + if (deflateInit2(&be->zstream, 9, Z_DEFLATED, + 16+15, 9, Z_DEFAULT_STRATEGY) < 0) + return -1; + + return 0; +} + +static int do_deflate(struct backend *be, int flush) +{ + int rv; + char *buf; + + while (1) { + rv = deflate(&be->zstream, flush); + be->zbytes = be->alloc - be->zstream.avail_out; + if (be->zstream.avail_out) + return rv; /* Not an issue of output space... */ + + buf = realloc(be->outbuf, be->alloc + ALLOC_CHUNK); + if (!buf) + return Z_MEM_ERROR; + be->outbuf = buf; + be->alloc += ALLOC_CHUNK; + be->zstream.next_out = (void *)(buf + be->zbytes); + be->zstream.avail_out = be->alloc - be->zbytes; + } +} + + +int write_data(struct backend *be, const void *buf, size_t len) +{ + int rv = Z_OK; + + be->zstream.next_in = (void *)buf; + be->zstream.avail_in = len; + + be->dbytes += len; + + while (be->zstream.avail_in) { + rv = do_deflate(be, Z_NO_FLUSH); + if (rv < 0) { + printf("do_deflate returned %d\n", rv); + return -1; + } + } + return 0; +} + +/* Output the data and shut down the stream */ +int flush_data(struct backend *be) +{ + int rv = Z_OK; + + while (rv != Z_STREAM_END) { + rv = do_deflate(be, Z_FINISH); + if (rv < 0) + return -1; + } + + printf("Uploading data, %u bytes... ", be->zbytes); + + if (be->write(be)) + return -1; + + free(be->outbuf); + be->outbuf = NULL; + be->dbytes = be->zbytes = be->alloc = 0; + + printf("done.\n"); + return 0; +} |