chdir: collapse /./ and /../ in path for conventional filesystems
[profile/ivi/syslinux.git] / memdump / srecsend.c
1 /*
2  * SREC send routine.
3  */
4
5 #include <string.h>
6 #include <stdio.h>
7 #include "srecsend.h"
8
9 static void make_srec(struct serial_if *sif, char type, size_t addr,
10                       const void *data, size_t len)
11 {
12     char buf[80];               /* More than the largest possible size */
13     char *p;
14     const uint8_t *dp = data;
15     size_t alen = (type == '0') ? 4 : 8;
16     uint8_t csum;
17
18     p = buf;
19     p += sprintf(p, "S%c%02X%0*zX", type, len+alen+1, alen, addr);
20     
21     csum = (len+alen+1) + addr + (addr >> 8) + (addr >> 16) + (addr >> 24);
22     while (len) {
23         p += sprintf(p, "%02X", *dp);
24         csum += *dp;
25         dp++;
26     }
27     csum = 0xff - csum;
28     p += sprintf(p, "%02X\r\n", csum);
29
30     sif->write(sif, buf, p-buf);
31 }
32
33 void send_srec(struct serial_if *sif, struct file_info *fileinfo,
34                void (*gen_data) (void *, size_t, struct file_info *, size_t))
35 {
36     uint8_t blk_buf[1024];
37     const uint8_t *np;
38     size_t addr, len, bytes, chunk, offset, pos;
39     int blk;
40
41     len = fileinfo->size;
42
43     make_srec(sif, '0', 0, NULL, 0);
44
45     blk = 0;
46     pos = 0;
47     addr = fileinfo->base;
48     while (len) {
49         gen_data(blk_buf, sizeof blk_buf, fileinfo, pos);
50         pos += sizeof blk_buf;
51         bytes = sizeof blk_buf;
52         if (bytes > len)
53             bytes = len;
54         len -= bytes;
55
56         printf("Sending block %d...\r", blk);
57         
58         np = blk_buf;
59         while (bytes) {
60             chunk = bytes > 32 ? 32 : bytes;
61
62             make_srec(sif, '3', addr, np, chunk);
63
64             bytes -= chunk;
65             offset += chunk;
66             np += chunk;
67             addr += chunk;
68         }
69         blk++;
70     }
71
72     printf("\nSending EOT...\n");
73     make_srec(sif, '7', fileinfo->base, NULL, 0);
74     printf("Done.\n");
75 }