root/memdump/main.c

Revision 3dededd20d70d571268417dc41edc95f0fe6602e, 3.6 KB (checked in by H. Peter Anvin <hpa@…>, 2 years ago)

memdump: allow outputting S-records

Allow outputting S-records, for users who only have the capability of
passively monitoring a serial port as opposed to being able to capture
the contents directly.

Signed-off-by: H. Peter Anvin <hpa@…>

  • Property mode set to 100644
Line 
1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
4 *
5 *   This program is free software; you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 *   Boston MA 02111-1307, USA; either version 2 of the License, or
9 *   (at your option) any later version; incorporated herein by reference.
10 *
11 * ----------------------------------------------------------------------- */
12
13#include <stdio.h>
14#include <string.h>
15#include <stdlib.h>
16#include <stdbool.h>
17#include "mystuff.h"
18#include "ymsend.h"
19#include "srecsend.h"
20#include "io.h"
21
22const char *program = "memdump";
23
24void __attribute__ ((noreturn)) die(const char *msg)
25{
26    puts(program);
27    puts(": ");
28    puts(msg);
29    putchar('\n');
30    exit(1);
31}
32
33#ifdef DEBUG
34# define dprintf printf
35#else
36# define dprintf(...) ((void)0)
37#endif
38
39static inline __attribute__ ((const))
40uint16_t ds(void)
41{
42    uint16_t v;
43asm("movw %%ds,%0":"=rm"(v));
44    return v;
45}
46
47#define GDT_ENTRY(flags,base,limit)             \
48        (((uint64_t)(base & 0xff000000) << 32) |        \
49         ((uint64_t)flags << 40) |                      \
50         ((uint64_t)(limit & 0x00ff0000) << 32) |       \
51         ((uint64_t)(base & 0x00ffff00) << 16) |        \
52         ((uint64_t)(limit & 0x0000ffff)))
53
54static void get_bytes(void *buf, size_t len, struct file_info *finfo,
55                      size_t pos)
56{
57    size_t end;
58    static uint64_t gdt[6];
59    size_t bufl;
60
61    pos += (size_t) finfo->pvt; /* Add base */
62    end = pos + len;
63
64    if (end <= 0x100000) {
65        /* Can stay in real mode */
66        asm volatile ("movw %3,%%fs ; "
67                      "fs; rep; movsl ; "
68                      "movw %2,%%cx ; "
69                      "rep; movsb"::"D" (buf), "c"(len >> 2),
70                      "r"((uint16_t) (len & 3)), "rm"((uint16_t) (pos >> 4)),
71                      "S"(pos & 15)
72                      :"memory");
73    } else {
74        bufl = (ds() << 4) + (size_t) buf;
75        gdt[2] = GDT_ENTRY(0x0093, pos, 0xffff);
76        gdt[3] = GDT_ENTRY(0x0093, bufl, 0xffff);
77        asm volatile ("pushal ; int $0x15 ; popal"::"a" (0x8700),
78                      "c"((len + 1) >> 1), "S"(&gdt)
79                      :"memory");
80    }
81}
82
83int main(int argc, char *argv[])
84{
85    uint16_t bios_ports[4];
86    const char *prefix;
87    char filename[1024];
88    int i;
89    static struct serial_if sif = {
90        .read = serial_read,
91        .write = serial_write,
92    };
93    struct file_info finfo;
94    const char ymodem_banner[] = "Now begin Ymodem download...\r\n";
95    bool srec = false;
96
97    if (argv[1][0] == '-') {
98        srec = argv[1][1] == 's';
99        argc--;
100        argv++;
101    }
102
103    if (argc < 4)
104        die("usage: memdump [-s] port prefix start,len...");
105
106    finfo.pvt = (void *)0x400;
107    get_bytes(bios_ports, 8, &finfo, 0);        /* Get BIOS serial ports */
108
109    for (i = 0; i < 4; i++)
110        printf("ttyS%i (COM%i) is at %#x\n", i, i + 1, bios_ports[i]);
111
112    sif.port = strtoul(argv[1], NULL, 0);
113    if (sif.port <= 3) {
114        sif.port = bios_ports[sif.port];
115    }
116
117    if (serial_init(&sif))
118        die("failed to initialize serial port");
119
120    prefix = argv[2];
121
122    if (!srec) {
123        puts("Printing prefix...\n");
124        sif.write(&sif, ymodem_banner, sizeof ymodem_banner - 1);
125    }
126
127    for (i = 3; i < argc; i++) {
128        uint32_t start, len;
129        char *ep;
130
131        start = strtoul(argv[i], &ep, 0);
132        if (*ep != ',')
133            die("invalid range specification");
134        len = strtoul(ep + 1, NULL, 0);
135
136        sprintf(filename, "%s%#x-%#x.bin", prefix, start, len);
137        finfo.name = filename;
138        finfo.size = len;
139        finfo.pvt = (void *)start;
140
141        puts("Sending ");
142        puts(filename);
143        puts("...\n");
144
145        if (srec)
146            send_srec(&sif, &finfo, get_bytes);
147        else
148            send_ymodem(&sif, &finfo, get_bytes);
149    }
150
151    if (!srec) {
152        puts("Sending closing signature...\n");
153        end_ymodem(&sif);
154    }
155
156    return 0;
157}
Note: See TracBrowser for help on using the browser.