summaryrefslogtreecommitdiff
path: root/utils/jztool
diff options
context:
space:
mode:
Diffstat (limited to 'utils/jztool')
-rw-r--r--utils/jztool/src/x1000.c99
1 files changed, 88 insertions, 11 deletions
diff --git a/utils/jztool/src/x1000.c b/utils/jztool/src/x1000.c
index f59727a2ca..e4bd466562 100644
--- a/utils/jztool/src/x1000.c
+++ b/utils/jztool/src/x1000.c
@@ -25,19 +25,72 @@
25#include <stdbool.h> 25#include <stdbool.h>
26#include <string.h> 26#include <string.h>
27 27
28/* TODO: these functions could be refactored to be CPU-agnostic */ 28#define X1000_TCSM_BASE 0xf4000000
29
30#define X1000_SPL_LOAD_ADDR (X1000_TCSM_BASE + 0x1000)
31#define X1000_SPL_EXEC_ADDR (X1000_TCSM_BASE + 0x1800)
32
33#define X1000_STANDARD_DRAM_BASE 0x80004000
34
35#define HDR_BEGIN 128 /* header must begin within this many bytes */
36#define HDR_LEN 256 /* header length cannot exceed this */
37
38#define MIN(a,b) ((a) < (b) ? (a) : (b))
39
40/* search for header value, label must be a 4-character string.
41 * Returns the found value or 0 if the label wasn't found. */
42static uint32_t search_header(const unsigned char* source, size_t length,
43 const char* label)
44{
45 size_t search_len = MIN(length, HDR_BEGIN);
46 if(search_len < 8)
47 return 0;
48 search_len -= 7;
49
50 /* find the beginning marker */
51 size_t i;
52 for(i = 8; i < search_len; i += 4)
53 if(!memcmp(&source[i], "BEGINHDR", 8))
54 break;
55 if(i >= search_len)
56 return 0;
57 i += 8;
58
59 /* search within the header */
60 search_len = MIN(length, i + HDR_LEN) - 7;
61 for(; i < search_len; i += 8) {
62 if(!memcmp(&source[i], "ENDH", 4)) {
63 break;
64 } else if(!memcmp(&source[i], label, 4)) {
65 i += 4;
66 /* read little-endian value */
67 uint32_t ret = source[i];
68 ret |= source[i+1] << 8;
69 ret |= source[i+2] << 16;
70 ret |= source[i+3] << 24;
71 return ret;
72 }
73 }
74
75 return 0;
76}
77
29static int run_stage1(jz_usbdev* dev, jz_buffer* buf) 78static int run_stage1(jz_usbdev* dev, jz_buffer* buf)
30{ 79{
31 int rc = jz_usb_send(dev, 0xf4001000, buf->size, buf->data); 80 int rc = jz_usb_send(dev, X1000_SPL_LOAD_ADDR, buf->size, buf->data);
32 if(rc < 0) 81 if(rc < 0)
33 return rc; 82 return rc;
34 83
35 return jz_usb_start1(dev, 0xf4001800); 84 return jz_usb_start1(dev, X1000_SPL_EXEC_ADDR);
36} 85}
37 86
38static int run_stage2(jz_usbdev* dev, jz_buffer* buf) 87static int run_stage2(jz_usbdev* dev, jz_buffer* buf)
39{ 88{
40 int rc = jz_usb_send(dev, 0x80004000, buf->size, buf->data); 89 uint32_t load_addr = search_header(buf->data, buf->size, "LOAD");
90 if(!load_addr)
91 load_addr = X1000_STANDARD_DRAM_BASE;
92
93 int rc = jz_usb_send(dev, load_addr, buf->size, buf->data);
41 if(rc < 0) 94 if(rc < 0)
42 return rc; 95 return rc;
43 96
@@ -45,11 +98,16 @@ static int run_stage2(jz_usbdev* dev, jz_buffer* buf)
45 if(rc < 0) 98 if(rc < 0)
46 return rc; 99 return rc;
47 100
48 return jz_usb_start2(dev, 0x80004000); 101 return jz_usb_start2(dev, load_addr);
49} 102}
50 103
104enum {
105 F_DECOMPRESS = 0x01,
106 F_OPTIONAL = 0x02,
107};
108
51static int get_file(jz_context* jz, mtar_t* tar, const char* file, 109static int get_file(jz_context* jz, mtar_t* tar, const char* file,
52 bool decompress, jz_buffer** buf) 110 unsigned int flags, jz_buffer** buf)
53{ 111{
54 jz_buffer* buffer = NULL; 112 jz_buffer* buffer = NULL;
55 const mtar_header_t* h; 113 const mtar_header_t* h;
@@ -57,8 +115,9 @@ static int get_file(jz_context* jz, mtar_t* tar, const char* file,
57 115
58 rc = mtar_find(tar, file); 116 rc = mtar_find(tar, file);
59 if(rc != MTAR_ESUCCESS) { 117 if(rc != MTAR_ESUCCESS) {
60 jz_log(jz, JZ_LOG_ERROR, "can't find %s in boot file, tar error %d", file, rc); 118 if(!(flags & F_OPTIONAL))
61 return JZ_ERR_BAD_FILE_FORMAT; 119 jz_log(jz, JZ_LOG_ERROR, "can't find %s in boot file, tar error %d", file, rc);
120 return JZ_ERR_OPEN_FILE;
62 } 121 }
63 122
64 h = mtar_get_header(tar); 123 h = mtar_get_header(tar);
@@ -73,7 +132,7 @@ static int get_file(jz_context* jz, mtar_t* tar, const char* file,
73 return JZ_ERR_BAD_FILE_FORMAT; 132 return JZ_ERR_BAD_FILE_FORMAT;
74 } 133 }
75 134
76 if(decompress) { 135 if(flags & F_DECOMPRESS) {
77 uint32_t dst_len; 136 uint32_t dst_len;
78 jz_buffer* nbuf = jz_ucl_unpack(buffer->data, buffer->size, &dst_len); 137 jz_buffer* nbuf = jz_ucl_unpack(buffer->data, buffer->size, &dst_len);
79 jz_buffer_free(buffer); 138 jz_buffer_free(buffer);
@@ -139,9 +198,27 @@ int jz_x1000_boot(jz_usbdev* dev, jz_device_type type, const char* filename)
139 if(rc != JZ_SUCCESS) 198 if(rc != JZ_SUCCESS)
140 goto error; 199 goto error;
141 200
142 rc = get_file(dev->jz, &tar, "bootloader.ucl", true, &bootloader); 201 /* - A bootloader2.ucl binary should carry the LOAD header to define its
143 if(rc != JZ_SUCCESS) 202 * load address. This name must be used when the load address is not
203 * equal to 0x80004000 to ensure old jztools will not try to load it.
204 *
205 * - The bootloader.ucl name must only be used when the binary loads at
206 * 0x80004000 and can be booted by old versions of jztool.
207 */
208 const char* bl_files[2] = {"bootloader2.ucl", "bootloader.ucl"};
209 for(int i = 0; i < 2; ++i) {
210 rc = get_file(dev->jz, &tar, bl_files[i],
211 F_DECOMPRESS|F_OPTIONAL, &bootloader);
212 if(rc == JZ_SUCCESS)
213 break;
214 else if(rc != JZ_ERR_OPEN_FILE)
215 goto error;
216 }
217
218 if(rc != JZ_SUCCESS) {
219 jz_log(dev->jz, JZ_LOG_ERROR, "no bootloader binary found", filename);
144 goto error; 220 goto error;
221 }
145 222
146 rc = get_file(dev->jz, &tar, "bootloader-info.txt", false, &info_file); 223 rc = get_file(dev->jz, &tar, "bootloader-info.txt", false, &info_file);
147 if(rc != JZ_SUCCESS) 224 if(rc != JZ_SUCCESS)