diff options
Diffstat (limited to 'rbutil/jztool/src/x1000.c')
-rw-r--r-- | rbutil/jztool/src/x1000.c | 209 |
1 files changed, 0 insertions, 209 deletions
diff --git a/rbutil/jztool/src/x1000.c b/rbutil/jztool/src/x1000.c deleted file mode 100644 index 1a12340316..0000000000 --- a/rbutil/jztool/src/x1000.c +++ /dev/null | |||
@@ -1,209 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2021 Aidan MacDonald | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "jztool_private.h" | ||
23 | #include "../../../firmware/target/mips/ingenic_x1000/spl-x1000-defs.h" | ||
24 | #include "../../../firmware/target/mips/ingenic_x1000/nand-x1000-err.h" | ||
25 | #include <string.h> | ||
26 | |||
27 | static uint32_t to_le32(uint32_t x) | ||
28 | { | ||
29 | union { uint32_t u; uint8_t p[4]; } f; | ||
30 | f.p[0] = x & 0xff; | ||
31 | f.p[1] = (x >> 8) & 0xff; | ||
32 | f.p[2] = (x >> 16) & 0xff; | ||
33 | f.p[3] = (x >> 24) & 0xff; | ||
34 | return f.u; | ||
35 | } | ||
36 | |||
37 | static uint32_t from_le32(uint32_t x) | ||
38 | { | ||
39 | union { uint32_t u; uint8_t p[4]; } f; | ||
40 | f.u = x; | ||
41 | return f.p[0] | (f.p[1] << 8) | (f.p[2] << 16) | (f.p[3] << 24); | ||
42 | } | ||
43 | |||
44 | static const char* jz_x1000_nand_strerror(int rc) | ||
45 | { | ||
46 | switch(rc) { | ||
47 | case NANDERR_CHIP_UNSUPPORTED: | ||
48 | return "Chip unsupported"; | ||
49 | case NANDERR_WRITE_PROTECTED: | ||
50 | return "Operation forbidden by write-protect"; | ||
51 | case NANDERR_UNALIGNED_ADDRESS: | ||
52 | return "Improperly aligned address"; | ||
53 | case NANDERR_UNALIGNED_LENGTH: | ||
54 | return "Improperly aligned length"; | ||
55 | case NANDERR_READ_FAILED: | ||
56 | return "Read operation failed"; | ||
57 | case NANDERR_ECC_FAILED: | ||
58 | return "Uncorrectable ECC error on read"; | ||
59 | case NANDERR_ERASE_FAILED: | ||
60 | return "Erase operation failed"; | ||
61 | case NANDERR_PROGRAM_FAILED: | ||
62 | return "Program operation failed"; | ||
63 | case NANDERR_COMMAND_FAILED: | ||
64 | return "NAND command failed"; | ||
65 | default: | ||
66 | return "Unknown NAND error"; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | |||
71 | static int jz_x1000_send_args(jz_usbdev* dev, struct x1000_spl_arguments* args) | ||
72 | { | ||
73 | args->command = to_le32(args->command); | ||
74 | args->param1 = to_le32(args->param1); | ||
75 | args->param2 = to_le32(args->param2); | ||
76 | args->flags = to_le32(args->flags); | ||
77 | return jz_usb_send(dev, SPL_ARGUMENTS_ADDRESS, sizeof(*args), args); | ||
78 | } | ||
79 | |||
80 | static int jz_x1000_recv_status(jz_usbdev* dev, struct x1000_spl_status* status) | ||
81 | { | ||
82 | int rc = jz_usb_recv(dev, SPL_STATUS_ADDRESS, sizeof(*status), status); | ||
83 | if(rc < 0) | ||
84 | return rc; | ||
85 | |||
86 | status->err_code = from_le32(status->err_code); | ||
87 | status->reserved = from_le32(status->reserved); | ||
88 | return JZ_SUCCESS; | ||
89 | } | ||
90 | |||
91 | int jz_x1000_setup(jz_usbdev* dev, size_t spl_len, const void* spl_data) | ||
92 | { | ||
93 | int rc = jz_identify_x1000_spl(spl_data, spl_len); | ||
94 | if(rc < 0) | ||
95 | return JZ_ERR_BAD_FILE_FORMAT; | ||
96 | if(spl_len > SPL_MAX_SIZE) | ||
97 | return JZ_ERR_BAD_FILE_FORMAT; | ||
98 | |||
99 | rc = jz_usb_send(dev, SPL_LOAD_ADDRESS, spl_len, spl_data); | ||
100 | if(rc < 0) | ||
101 | return rc; | ||
102 | |||
103 | struct x1000_spl_arguments args; | ||
104 | args.command = SPL_CMD_BOOT; | ||
105 | args.param1 = SPL_BOOTOPT_NONE; | ||
106 | args.param2 = 0; | ||
107 | args.flags = 0; | ||
108 | rc = jz_x1000_send_args(dev, &args); | ||
109 | if(rc < 0) | ||
110 | return rc; | ||
111 | |||
112 | rc = jz_usb_start1(dev, SPL_EXEC_ADDRESS); | ||
113 | if(rc < 0) | ||
114 | return rc; | ||
115 | |||
116 | jz_sleepms(100); | ||
117 | |||
118 | struct x1000_spl_status status; | ||
119 | rc = jz_x1000_recv_status(dev, &status); | ||
120 | if(rc < 0) | ||
121 | return rc; | ||
122 | |||
123 | if(status.err_code != 0) { | ||
124 | jz_log(dev->jz, JZ_LOG_ERROR, "X1000 device init error: %d", status.err_code); | ||
125 | return JZ_ERR_OTHER; | ||
126 | } | ||
127 | |||
128 | return JZ_SUCCESS; | ||
129 | } | ||
130 | |||
131 | int jz_x1000_read_flash(jz_usbdev* dev, uint32_t addr, size_t len, void* data) | ||
132 | { | ||
133 | struct x1000_spl_arguments args; | ||
134 | args.command = SPL_CMD_FLASH_READ; | ||
135 | args.param1 = addr; | ||
136 | args.param2 = len; | ||
137 | args.flags = SPL_FLAG_SKIP_INIT; | ||
138 | int rc = jz_x1000_send_args(dev, &args); | ||
139 | if(rc < 0) | ||
140 | return rc; | ||
141 | |||
142 | rc = jz_usb_start1(dev, SPL_EXEC_ADDRESS); | ||
143 | if(rc < 0) | ||
144 | return rc; | ||
145 | |||
146 | jz_sleepms(500); | ||
147 | |||
148 | struct x1000_spl_status status; | ||
149 | rc = jz_x1000_recv_status(dev, &status); | ||
150 | if(rc < 0) | ||
151 | return rc; | ||
152 | |||
153 | if(status.err_code != 0) { | ||
154 | jz_log(dev->jz, JZ_LOG_ERROR, "X1000 flash read error: %s", | ||
155 | jz_x1000_nand_strerror(status.err_code)); | ||
156 | return JZ_ERR_FLASH_ERROR; | ||
157 | } | ||
158 | |||
159 | return jz_usb_recv(dev, SPL_BUFFER_ADDRESS, len, data); | ||
160 | } | ||
161 | |||
162 | int jz_x1000_write_flash(jz_usbdev* dev, uint32_t addr, size_t len, const void* data) | ||
163 | { | ||
164 | int rc = jz_usb_send(dev, SPL_BUFFER_ADDRESS, len, data); | ||
165 | if(rc < 0) | ||
166 | return rc; | ||
167 | |||
168 | struct x1000_spl_arguments args; | ||
169 | args.command = SPL_CMD_FLASH_WRITE; | ||
170 | args.param1 = addr; | ||
171 | args.param2 = len; | ||
172 | args.flags = SPL_FLAG_SKIP_INIT; | ||
173 | rc = jz_x1000_send_args(dev, &args); | ||
174 | if(rc < 0) | ||
175 | return rc; | ||
176 | |||
177 | rc = jz_usb_start1(dev, SPL_EXEC_ADDRESS); | ||
178 | if(rc < 0) | ||
179 | return rc; | ||
180 | |||
181 | jz_sleepms(500); | ||
182 | |||
183 | struct x1000_spl_status status; | ||
184 | rc = jz_x1000_recv_status(dev, &status); | ||
185 | if(rc < 0) | ||
186 | return rc; | ||
187 | |||
188 | if(status.err_code != 0) { | ||
189 | jz_log(dev->jz, JZ_LOG_ERROR, "X1000 flash write error: %s", | ||
190 | jz_x1000_nand_strerror(status.err_code)); | ||
191 | return JZ_ERR_FLASH_ERROR; | ||
192 | } | ||
193 | |||
194 | return JZ_SUCCESS; | ||
195 | } | ||
196 | |||
197 | int jz_x1000_boot_rockbox(jz_usbdev* dev) | ||
198 | { | ||
199 | struct x1000_spl_arguments args; | ||
200 | args.command = SPL_CMD_BOOT; | ||
201 | args.param1 = SPL_BOOTOPT_ROCKBOX; | ||
202 | args.param2 = 0; | ||
203 | args.flags = 0; | ||
204 | int rc = jz_x1000_send_args(dev, &args); | ||
205 | if(rc < 0) | ||
206 | return rc; | ||
207 | |||
208 | return jz_usb_start1(dev, SPL_EXEC_ADDRESS); | ||
209 | } | ||