Add serial stream payload support from Ed Swierk <eswierk@arastra.com>
[coreboot.git] / src / stream / serial_stream.c
1 #include <console/console.h>
2 #include <stdlib.h>
3 #include <stddef.h>
4 #include <stream/read_bytes.h>
5 #include <string.h>
6
7 /* if they set the precompressed rom stream, they better have set a type */
8 #if CONFIG_PRECOMPRESSED_ROM_STREAM && ((!CONFIG_COMPRESSED_ROM_STREAM) && (!CONFIG_COMPRESSED_ROM_STREAM_NRV2B) && (!CONFIG_COMPRESSED_ROM_STREAM_LZMA))
9 #error "You set CONFIG_PRECOMPRESSED_ROM_STREAM but need to set CONFIG_COMPRESSED_ROM_STREAM (implies NRV2B, deprecated) or CONFIG_COMPRESSED_ROM_STREAM_NRV2B or CONFIG_COMPRESSED_ROM_STREAM_LZMA"
10 #endif
11
12 #if (CONFIG_COMPRESSED_ROM_STREAM) || (CONFIG_COMPRESSED_ROM_STREAM_NRV2B) 
13 #define HAVE_UNCOMPRESSER 1
14 #include "../lib/nrv2b.c"
15 #endif
16
17 #if (CONFIG_COMPRESSED_ROM_STREAM_LZMA)
18 #if HAVE_UNCOMPRESSER
19 #error "You're defining more than one compression type, which is not allowed (of course)"
20 #endif
21 #define HAVE_UNCOMPRESSER 1
22 #include "../lib/lzma.c"
23 #endif
24
25 #include "../lib/xmodem.c"
26
27 /* Blocks of RAM for storing stream data */
28 static unsigned char *stream_start = (unsigned char *) 0x02000000;
29 static unsigned char *stream_end;
30 static unsigned char *temp_start = (unsigned char *) 0x03000000;
31 static int stream_max_bytes = 0x00800000;
32
33 #if HAVE_UNCOMPRESSER
34 static unsigned long uncompress(uint8_t *src, uint8_t *dest)
35 {
36 #if (CONFIG_COMPRESSED_ROM_STREAM) || (CONFIG_COMPRESSED_ROM_STREAM_NRV2B) 
37         unsigned long ilen;
38         return unrv2b(src, dest, &ilen);
39 #endif
40 #if (CONFIG_COMPRESSED_ROM_STREAM_LZMA)
41         return ulzma(src, dest);
42 #endif
43 }
44 #endif
45
46 int stream_init(void)
47 {
48         int len;
49
50         printk_debug("serial_stream: downloading to 0x%08lx; start XMODEM transfer now!\n", temp_start);
51         if ((len = xmodemReceive(temp_start, stream_max_bytes)) <= 0) {
52                 printk_debug("\nserial_stream: XMODEM transfer failed\n");
53                 return -1;
54         }
55         printk_debug("\nserial_stream: XMODEM transfer complete; %d bytes received\n", len);
56 #if HAVE_UNCOMPRESSER
57         printk_debug("serial_stream: uncompressing to 0x%08lx\n", stream_start);
58         len = uncompress((uint8_t *) temp_start, (uint8_t *) stream_start);
59         printk_debug("serial_stream: %d bytes uncompressed\n", len);
60 #else
61         printk_debug("serial_stream: copying to 0x%08lx\n", stream_start);
62         memcpy(stream_start, temp_start, len);
63 #endif
64         stream_end = stream_start + len - 1;
65         return 0;
66 }
67
68 void stream_fini(void)
69 {
70 }
71
72 byte_offset_t stream_skip(byte_offset_t count)
73 {
74         if ((stream_start + count) > stream_end) {
75                 printk_warning("%6d:%s() - overflowed source buffer\n",
76                         __LINE__, __FUNCTION__);
77                 count = 0;
78                 if (stream_start <= stream_end) {
79                         count = (stream_end - stream_start) + 1;
80                 }
81         }
82         stream_start += count;
83         return count;
84 }
85
86 byte_offset_t stream_read(void *vdest, byte_offset_t count)
87 {
88         unsigned char *old_start = stream_start;
89         count = stream_skip(count);
90         memcpy(vdest, old_start, count);
91         return count;
92 }