diff options
author | Aidan MacDonald <amachronic@protonmail.com> | 2021-05-11 13:28:43 +0100 |
---|---|---|
committer | Aidan MacDonald <amachronic@protonmail.com> | 2021-05-12 10:35:20 +0000 |
commit | 3f26fcf34001197ed267fa1ad549095aae49c88e (patch) | |
tree | c81ab3298a349d1156e905d467492b603236f74d /firmware/target/mips/ingenic_x1000/fiiom3k | |
parent | cc22df198d0ccb64dfdfe0c2f247f7d86b7fd750 (diff) | |
download | rockbox-3f26fcf34001197ed267fa1ad549095aae49c88e.tar.gz rockbox-3f26fcf34001197ed267fa1ad549095aae49c88e.zip |
FiiO M3K: New bootloaderbootloader_fiiom3k_v1
SPL and UCL-compressed bootloader are now packed into one output,
bootloader.m3k, eliminating the separate SPL build phase.
The Rockbox bootloader now has a recovery menu, accessible by
holding VOL+ when booting, that lets you back up, restore, and
update the bootloader from the device.
Change-Id: I642c6e5fb83587a013ab2fbfd1adab439561ced2
Diffstat (limited to 'firmware/target/mips/ingenic_x1000/fiiom3k')
5 files changed, 313 insertions, 180 deletions
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/boot.make b/firmware/target/mips/ingenic_x1000/fiiom3k/boot.make new file mode 100644 index 0000000000..77b23167c2 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/boot.make | |||
@@ -0,0 +1,30 @@ | |||
1 | # __________ __ ___. | ||
2 | # Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
3 | # Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
4 | # Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
5 | # Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
6 | # \/ \/ \/ \/ \/ | ||
7 | # $Id$ | ||
8 | # | ||
9 | |||
10 | include $(ROOTDIR)/lib/microtar/microtar.make | ||
11 | |||
12 | .SECONDEXPANSION: | ||
13 | |||
14 | $(BUILDDIR)/spl.m3k: $(BUILDDIR)/spl.bin | ||
15 | $(call PRINTS,MKSPL $(@F))$(TOOLSDIR)/mkspl-x1000 -type=nand -ppb=2 -bpp=2 $< $@ | ||
16 | |||
17 | $(BUILDDIR)/bootloader.ucl: $(BUILDDIR)/bootloader.bin | ||
18 | $(call PRINTS,UCLPACK $(@F))$(TOOLSDIR)/uclpack --nrv2e -9 $< $@ >/dev/null | ||
19 | |||
20 | .PHONY: $(BUILDDIR)/bootloader-info.txt | ||
21 | $(BUILDDIR)/bootloader-info.txt: | ||
22 | $(call PRINTS,GEN $(@F))echo $(SVNVERSION) > $@ | ||
23 | |||
24 | $(BUILDDIR)/$(BINARY): $(BUILDDIR)/spl.m3k \ | ||
25 | $(BUILDDIR)/bootloader.ucl \ | ||
26 | $(BUILDDIR)/bootloader-info.txt | ||
27 | $(call PRINTS,TAR $(@F))tar -C $(BUILDDIR) \ | ||
28 | --numeric-owner --no-acls --no-xattrs --no-selinux \ | ||
29 | --mode=0644 --owner=0 --group=0 \ | ||
30 | -cf $@ $(call full_path_subst,$(BUILDDIR)/%,%,$^) | ||
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.c index 154785ee0b..10a58ace38 100644 --- a/firmware/target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.c +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.c | |||
@@ -19,192 +19,265 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | 21 | ||
22 | #include "installer.h" | 22 | #include "installer-fiiom3k.h" |
23 | #include "nand-x1000.h" | 23 | #include "nand-x1000.h" |
24 | #include "system.h" | 24 | #include "system.h" |
25 | #include "core_alloc.h" | 25 | #include "core_alloc.h" |
26 | #include "file.h" | 26 | #include "file.h" |
27 | #include "microtar.h" | ||
28 | #include <stdint.h> | ||
29 | #include <string.h> | ||
30 | #include <stdio.h> | ||
27 | 31 | ||
28 | #define INSTALL_SUCCESS 0 | 32 | #define IMAGE_SIZE (128 * 1024) |
29 | #define ERR_FLASH_OPEN_FAILED (-1) | 33 | #define TAR_SIZE (256 * 1024) |
30 | #define ERR_FLASH_ENABLE_WP_FAILED (-2) | 34 | |
31 | #define ERR_FLASH_DISABLE_WP_FAILED (-3) | 35 | static int flash_prepare(void) |
32 | #define ERR_FLASH_ERASE_FAILED (-4) | ||
33 | #define ERR_FLASH_WRITE_FAILED (-5) | ||
34 | #define ERR_FLASH_READ_FAILED (-6) | ||
35 | #define ERR_OUT_OF_MEMORY (-7) | ||
36 | #define ERR_CANNOT_READ_FILE (-8) | ||
37 | #define ERR_CANNOT_WRITE_FILE (-9) | ||
38 | #define ERR_WRONG_SIZE (-10) | ||
39 | |||
40 | #define BOOT_IMAGE_SIZE (128 * 1024) | ||
41 | |||
42 | static int install_from_buffer(const void* buf) | ||
43 | { | 36 | { |
44 | int status = INSTALL_SUCCESS; | ||
45 | int mf_id, dev_id; | 37 | int mf_id, dev_id; |
38 | int rc; | ||
39 | |||
40 | rc = nand_open(); | ||
41 | if(rc < 0) | ||
42 | return INSTALL_ERR_FLASH(NAND_OPEN, rc); | ||
46 | 43 | ||
47 | if(nand_open()) | 44 | rc = nand_identify(&mf_id, &dev_id); |
48 | return ERR_FLASH_OPEN_FAILED; | 45 | if(rc < 0) { |
49 | if(nand_identify(&mf_id, &dev_id)) { | 46 | nand_close(); |
50 | status = ERR_FLASH_OPEN_FAILED; | 47 | return INSTALL_ERR_FLASH(NAND_IDENTIFY, rc); |
51 | goto _exit; | ||
52 | } | 48 | } |
53 | 49 | ||
54 | if(nand_enable_writes(true)) { | 50 | return INSTALL_SUCCESS; |
55 | status = ERR_FLASH_DISABLE_WP_FAILED; | 51 | } |
56 | goto _exit; | 52 | |
53 | static void flash_finish(void) | ||
54 | { | ||
55 | /* Ensure writes are always disabled when we finish. | ||
56 | * Errors are safe to ignore here, there's nothing we could do anyway. */ | ||
57 | nand_enable_writes(false); | ||
58 | nand_close(); | ||
59 | } | ||
60 | |||
61 | static int flash_img_read(uint8_t* buffer) | ||
62 | { | ||
63 | int rc = flash_prepare(); | ||
64 | if(rc < 0) | ||
65 | goto error; | ||
66 | |||
67 | rc = nand_read(0, IMAGE_SIZE, buffer); | ||
68 | if(rc < 0) { | ||
69 | rc = INSTALL_ERR_FLASH(NAND_READ, rc); | ||
70 | goto error; | ||
57 | } | 71 | } |
58 | 72 | ||
59 | if(nand_erase(0, BOOT_IMAGE_SIZE)) { | 73 | error: |
60 | status = ERR_FLASH_ERASE_FAILED; | 74 | flash_finish(); |
61 | goto _exit; | 75 | return rc; |
76 | } | ||
77 | |||
78 | static int flash_img_write(const uint8_t* buffer) | ||
79 | { | ||
80 | int rc = flash_prepare(); | ||
81 | if(rc < 0) | ||
82 | goto error; | ||
83 | |||
84 | rc = nand_enable_writes(true); | ||
85 | if(rc < 0) { | ||
86 | rc = INSTALL_ERR_FLASH(NAND_ENABLE_WRITES, rc); | ||
87 | goto error; | ||
62 | } | 88 | } |
63 | 89 | ||
64 | if(nand_write(0, BOOT_IMAGE_SIZE, (const uint8_t*)buf)) { | 90 | rc = nand_erase(0, IMAGE_SIZE); |
65 | status = ERR_FLASH_WRITE_FAILED; | 91 | if(rc < 0) { |
66 | goto _exit; | 92 | rc = INSTALL_ERR_FLASH(NAND_ERASE, rc); |
93 | goto error; | ||
67 | } | 94 | } |
68 | 95 | ||
69 | if(nand_enable_writes(false)) { | 96 | rc = nand_write(0, IMAGE_SIZE, buffer); |
70 | status = ERR_FLASH_ENABLE_WP_FAILED; | 97 | if(rc < 0) { |
71 | goto _exit; | 98 | rc = INSTALL_ERR_FLASH(NAND_WRITE, rc); |
99 | goto error; | ||
72 | } | 100 | } |
73 | 101 | ||
74 | _exit: | 102 | error: |
75 | nand_close(); | 103 | flash_finish(); |
76 | return status; | 104 | return rc; |
77 | } | 105 | } |
78 | 106 | ||
79 | static int dump_to_buffer(void* buf) | 107 | static int patch_img(mtar_t* tar, uint8_t* buffer, const char* filename, |
108 | size_t patch_offset, size_t patch_size) | ||
80 | { | 109 | { |
81 | int status = INSTALL_SUCCESS; | 110 | /* Seek to file */ |
82 | int mf_id, dev_id; | 111 | mtar_header_t h; |
83 | 112 | int rc = mtar_find(tar, filename, &h); | |
84 | if(nand_open()) | 113 | if(rc != MTAR_ESUCCESS) { |
85 | return ERR_FLASH_OPEN_FAILED; | 114 | rc = INSTALL_ERR_MTAR(TAR_FIND, rc); |
86 | if(nand_identify(&mf_id, &dev_id)) { | 115 | return rc; |
87 | status = ERR_FLASH_OPEN_FAILED; | ||
88 | goto _exit; | ||
89 | } | 116 | } |
90 | 117 | ||
91 | if(nand_read(0, BOOT_IMAGE_SIZE, (uint8_t*)buf)) { | 118 | /* We need a normal file */ |
92 | status = ERR_FLASH_READ_FAILED; | 119 | if(h.type != 0 && h.type != MTAR_TREG) |
93 | goto _exit; | 120 | return INSTALL_ERR_BAD_FORMAT; |
121 | |||
122 | /* Check size does not exceed patch area */ | ||
123 | if(h.size > patch_size) | ||
124 | return INSTALL_ERR_BAD_FORMAT; | ||
125 | |||
126 | /* Read data directly into patch area, fill unused bytes with 0xff */ | ||
127 | memset(&buffer[patch_offset], 0xff, patch_size); | ||
128 | rc = mtar_read_data(tar, &buffer[patch_offset], h.size); | ||
129 | if(rc != MTAR_ESUCCESS) { | ||
130 | rc = INSTALL_ERR_MTAR(TAR_READ, rc); | ||
131 | return rc; | ||
94 | } | 132 | } |
95 | 133 | ||
96 | _exit: | 134 | return INSTALL_SUCCESS; |
97 | nand_close(); | ||
98 | return status; | ||
99 | } | 135 | } |
100 | 136 | ||
101 | int install_bootloader(const char* path) | 137 | int install_boot(const char* srcfile) |
102 | { | 138 | { |
103 | /* Allocate memory to hold image */ | 139 | int rc; |
104 | size_t bufsize = BOOT_IMAGE_SIZE + CACHEALIGN_SIZE - 1; | 140 | mtar_t* tar = NULL; |
105 | int handle = core_alloc("boot_image", bufsize); | 141 | int handle = -1; |
106 | if(handle < 0) | ||
107 | return ERR_OUT_OF_MEMORY; | ||
108 | |||
109 | int status = INSTALL_SUCCESS; | ||
110 | void* buffer = core_get_data(handle); | ||
111 | CACHEALIGN_BUFFER(buffer, bufsize); | ||
112 | 142 | ||
113 | /* Open the boot image */ | 143 | /* Allocate enough memory for image and tar state */ |
114 | int fd = open(path, O_RDONLY); | 144 | size_t bufsize = IMAGE_SIZE + sizeof(mtar_t) + 2*CACHEALIGN_SIZE; |
115 | if(fd < 0) { | 145 | handle = core_alloc("boot_image", bufsize); |
116 | status = ERR_CANNOT_READ_FILE; | 146 | if(handle < 0) { |
117 | goto _exit; | 147 | rc = INSTALL_ERR_OUT_OF_MEMORY; |
148 | goto error; | ||
118 | } | 149 | } |
119 | 150 | ||
120 | /* Check file size */ | 151 | uint8_t* buffer = core_get_data(handle); |
121 | off_t fsize = filesize(fd); | 152 | |
122 | if(fsize != BOOT_IMAGE_SIZE) { | 153 | /* Tar state alloc */ |
123 | status = ERR_WRONG_SIZE; | 154 | CACHEALIGN_BUFFER(buffer, bufsize); |
124 | goto _exit; | 155 | tar = (mtar_t*)buffer; |
125 | } | 156 | memset(tar, 0, sizeof(tar)); |
157 | |||
158 | /* Image buffer alloc */ | ||
159 | buffer += sizeof(mtar_t); | ||
160 | CACHEALIGN_BUFFER(buffer, bufsize); | ||
161 | |||
162 | /* Read the flash -- we need an existing image to patch */ | ||
163 | rc = flash_img_read(buffer); | ||
164 | if(rc < 0) | ||
165 | goto error; | ||
126 | 166 | ||
127 | /* Read the file into the buffer */ | 167 | /* Open the tarball */ |
128 | ssize_t cnt = read(fd, buffer, BOOT_IMAGE_SIZE); | 168 | rc = mtar_open(tar, srcfile, "r"); |
129 | if(cnt != BOOT_IMAGE_SIZE) { | 169 | if(rc != MTAR_ESUCCESS) { |
130 | status = ERR_CANNOT_READ_FILE; | 170 | rc = INSTALL_ERR_MTAR(TAR_OPEN, rc); |
131 | goto _exit; | 171 | goto error; |
132 | } | 172 | } |
133 | 173 | ||
134 | /* Perform the installation */ | 174 | /* Extract the needed files & patch 'em in */ |
135 | status = install_from_buffer(buffer); | 175 | rc = patch_img(tar, buffer, "spl.m3k", 0, 12 * 1024); |
176 | if(rc < 0) | ||
177 | goto error; | ||
136 | 178 | ||
137 | _exit: | 179 | rc = patch_img(tar, buffer, "bootloader.ucl", 0x6800, 102 * 1024); |
138 | if(fd >= 0) | 180 | if(rc < 0) |
139 | close(fd); | 181 | goto error; |
140 | core_free(handle); | 182 | |
141 | return status; | 183 | /* Flash the new image */ |
184 | rc = flash_img_write(buffer); | ||
185 | if(rc < 0) | ||
186 | goto error; | ||
187 | |||
188 | rc = INSTALL_SUCCESS; | ||
189 | |||
190 | error: | ||
191 | if(tar && tar->close) | ||
192 | mtar_close(tar); | ||
193 | if(handle >= 0) | ||
194 | core_free(handle); | ||
195 | return rc; | ||
142 | } | 196 | } |
143 | 197 | ||
144 | /* Dump the current bootloader to a file */ | 198 | int backup_boot(const char* destfile) |
145 | int dump_bootloader(const char* path) | ||
146 | { | 199 | { |
147 | /* Allocate memory to hold image */ | 200 | int rc; |
148 | size_t bufsize = BOOT_IMAGE_SIZE + CACHEALIGN_SIZE - 1; | 201 | int handle = -1; |
149 | int handle = core_alloc("boot_image", bufsize); | ||
150 | if(handle < 0) | ||
151 | return -1; | ||
152 | |||
153 | /* Read data from flash */ | ||
154 | int fd = -1; | 202 | int fd = -1; |
155 | void* buffer = core_get_data(handle); | 203 | size_t bufsize = IMAGE_SIZE + CACHEALIGN_SIZE - 1; |
204 | handle = core_alloc("boot_image", bufsize); | ||
205 | if(handle < 0) { | ||
206 | rc = INSTALL_ERR_OUT_OF_MEMORY; | ||
207 | goto error; | ||
208 | } | ||
209 | |||
210 | uint8_t* buffer = core_get_data(handle); | ||
156 | CACHEALIGN_BUFFER(buffer, bufsize); | 211 | CACHEALIGN_BUFFER(buffer, bufsize); |
157 | int status = dump_to_buffer(buffer); | ||
158 | if(status) | ||
159 | goto _exit; | ||
160 | 212 | ||
161 | /* Open file */ | 213 | rc = flash_img_read(buffer); |
162 | fd = open(path, O_CREAT|O_TRUNC|O_WRONLY); | 214 | if(rc < 0) |
215 | goto error; | ||
216 | |||
217 | fd = open(destfile, O_CREAT|O_TRUNC|O_WRONLY); | ||
163 | if(fd < 0) { | 218 | if(fd < 0) { |
164 | status = ERR_CANNOT_WRITE_FILE; | 219 | rc = INSTALL_ERR_FILE_IO; |
165 | goto _exit; | 220 | goto error; |
166 | } | 221 | } |
167 | 222 | ||
168 | /* Write data to file */ | 223 | ssize_t cnt = write(fd, buffer, IMAGE_SIZE); |
169 | ssize_t cnt = write(fd, buffer, BOOT_IMAGE_SIZE); | 224 | if(cnt != IMAGE_SIZE) { |
170 | if(cnt != BOOT_IMAGE_SIZE) { | 225 | rc = INSTALL_ERR_FILE_IO; |
171 | status = ERR_CANNOT_WRITE_FILE; | 226 | goto error; |
172 | goto _exit; | ||
173 | } | 227 | } |
174 | 228 | ||
175 | _exit: | 229 | error: |
176 | if(fd >= 0) | 230 | if(fd >= 0) |
177 | close(fd); | 231 | close(fd); |
178 | core_free(handle); | 232 | if(handle >= 0) |
179 | return status; | 233 | core_free(handle); |
234 | return rc; | ||
180 | } | 235 | } |
181 | 236 | ||
182 | const char* installer_strerror(int rc) | 237 | int restore_boot(const char* srcfile) |
183 | { | 238 | { |
184 | switch(rc) { | 239 | int rc; |
185 | case INSTALL_SUCCESS: | 240 | int handle = -1; |
186 | return "Success"; | 241 | int fd = -1; |
187 | case ERR_FLASH_OPEN_FAILED: | 242 | size_t bufsize = IMAGE_SIZE + CACHEALIGN_SIZE - 1; |
188 | return "Can't open flash device"; | 243 | handle = core_alloc("boot_image", bufsize); |
189 | case ERR_FLASH_ENABLE_WP_FAILED: | 244 | if(handle < 0) { |
190 | return "Couldn't re-enable write protect"; | 245 | rc = INSTALL_ERR_OUT_OF_MEMORY; |
191 | case ERR_FLASH_DISABLE_WP_FAILED: | 246 | goto error; |
192 | return "Can't disable write protect"; | ||
193 | case ERR_FLASH_ERASE_FAILED: | ||
194 | return "Flash erase failed"; | ||
195 | case ERR_FLASH_WRITE_FAILED: | ||
196 | return "Flash write error"; | ||
197 | case ERR_FLASH_READ_FAILED: | ||
198 | return "Flash read error"; | ||
199 | case ERR_OUT_OF_MEMORY: | ||
200 | return "Out of memory"; | ||
201 | case ERR_CANNOT_READ_FILE: | ||
202 | return "Error reading file"; | ||
203 | case ERR_CANNOT_WRITE_FILE: | ||
204 | return "Error writing file"; | ||
205 | case ERR_WRONG_SIZE: | ||
206 | return "Wrong file size"; | ||
207 | default: | ||
208 | return "Unknown error"; | ||
209 | } | 247 | } |
248 | |||
249 | uint8_t* buffer = core_get_data(handle); | ||
250 | CACHEALIGN_BUFFER(buffer, bufsize); | ||
251 | |||
252 | fd = open(srcfile, O_RDONLY); | ||
253 | if(fd < 0) { | ||
254 | rc = INSTALL_ERR_FILE_NOT_FOUND; | ||
255 | goto error; | ||
256 | } | ||
257 | |||
258 | off_t fsize = filesize(fd); | ||
259 | if(fsize != IMAGE_SIZE) { | ||
260 | rc = INSTALL_ERR_BAD_FORMAT; | ||
261 | goto error; | ||
262 | } | ||
263 | |||
264 | ssize_t cnt = read(fd, buffer, IMAGE_SIZE); | ||
265 | if(cnt != IMAGE_SIZE) { | ||
266 | rc = INSTALL_ERR_FILE_IO; | ||
267 | goto error; | ||
268 | } | ||
269 | |||
270 | close(fd); | ||
271 | fd = -1; | ||
272 | |||
273 | rc = flash_img_write(buffer); | ||
274 | if(rc < 0) | ||
275 | goto error; | ||
276 | |||
277 | error: | ||
278 | if(fd >= 0) | ||
279 | close(fd); | ||
280 | if(handle >= 0) | ||
281 | core_free(handle); | ||
282 | return rc; | ||
210 | } | 283 | } |
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.h b/firmware/target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.h new file mode 100644 index 0000000000..eb700e6689 --- /dev/null +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/installer-fiiom3k.h | |||
@@ -0,0 +1,51 @@ | |||
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 | #ifndef __INSTALLER_FIIOM3K_H__ | ||
23 | #define __INSTALLER_FIIOM3K_H__ | ||
24 | |||
25 | #include <stddef.h> | ||
26 | |||
27 | #define INSTALL_SUCCESS 0 | ||
28 | #define INSTALL_ERR_OUT_OF_MEMORY (-1) | ||
29 | #define INSTALL_ERR_FILE_NOT_FOUND (-2) | ||
30 | #define INSTALL_ERR_FILE_IO (-3) | ||
31 | #define INSTALL_ERR_BAD_FORMAT (-4) | ||
32 | #define INSTALL_ERR_NAND_OPEN (-5) | ||
33 | #define INSTALL_ERR_NAND_IDENTIFY (-6) | ||
34 | #define INSTALL_ERR_NAND_READ (-7) | ||
35 | #define INSTALL_ERR_NAND_ENABLE_WRITES (-8) | ||
36 | #define INSTALL_ERR_NAND_ERASE (-9) | ||
37 | #define INSTALL_ERR_NAND_WRITE (-10) | ||
38 | #define INSTALL_ERR_TAR_OPEN (-11) | ||
39 | #define INSTALL_ERR_TAR_FIND (-12) | ||
40 | #define INSTALL_ERR_TAR_READ (-13) | ||
41 | #define INSTALL_ERR_MTAR(x,y) ((INSTALL_ERR_##x)*100 + (y)) | ||
42 | #define INSTALL_ERR_FLASH(x,y) ((INSTALL_ERR_##x)*100 + (y)) | ||
43 | |||
44 | /* Install the Rockbox bootloader from a bootloader.m3k image */ | ||
45 | extern int install_boot(const char* srcfile); | ||
46 | |||
47 | /* Backup or restore the bootloader from a raw NAND image */ | ||
48 | extern int backup_boot(const char* destfile); | ||
49 | extern int restore_boot(const char* srcfile); | ||
50 | |||
51 | #endif /* __INSTALLER_FIIOM3K_H__ */ | ||
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c index bdd0ffc2e0..efea5aa323 100644 --- a/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c +++ b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c | |||
@@ -25,6 +25,11 @@ | |||
25 | #include "system.h" | 25 | #include "system.h" |
26 | #include <string.h> | 26 | #include <string.h> |
27 | 27 | ||
28 | /* Available boot options */ | ||
29 | #define BOOTOPTION_ROCKBOX 0 | ||
30 | #define BOOTOPTION_ORIG_FW 1 | ||
31 | #define BOOTOPTION_RECOVERY 2 | ||
32 | |||
28 | /* Boot select button state must remain stable for this duration | 33 | /* Boot select button state must remain stable for this duration |
29 | * before the choice will be accepted. Currently 100ms. | 34 | * before the choice will be accepted. Currently 100ms. |
30 | */ | 35 | */ |
@@ -56,7 +61,7 @@ const struct spl_boot_option spl_boot_options[] = { | |||
56 | */ | 61 | */ |
57 | .nand_addr = 0x6800, | 62 | .nand_addr = 0x6800, |
58 | .nand_size = 0x19800, | 63 | .nand_size = 0x19800, |
59 | .load_addr = X1000_DRAM_BASE - 8, /* first 8 bytes are bootloader ID */ | 64 | .load_addr = X1000_DRAM_END - 0x19800, |
60 | .exec_addr = X1000_DRAM_BASE, | 65 | .exec_addr = X1000_DRAM_BASE, |
61 | .cmdline = NULL, | 66 | .cmdline = NULL, |
62 | }, | 67 | }, |
@@ -80,7 +85,7 @@ const struct spl_boot_option spl_boot_options[] = { | |||
80 | 85 | ||
81 | void spl_error(void) | 86 | void spl_error(void) |
82 | { | 87 | { |
83 | const int pin = (1 << 24); | 88 | const uint32_t pin = (1 << 24); |
84 | 89 | ||
85 | /* Turn on button light */ | 90 | /* Turn on button light */ |
86 | jz_clr(GPIO_INT(GPIO_C), pin); | 91 | jz_clr(GPIO_INT(GPIO_C), pin); |
@@ -105,6 +110,10 @@ int spl_get_boot_option(void) | |||
105 | 110 | ||
106 | uint32_t pin = 1, lastpin = 0; | 111 | uint32_t pin = 1, lastpin = 0; |
107 | uint32_t deadline = 0; | 112 | uint32_t deadline = 0; |
113 | /* Iteration count guards against unlikely case of broken buttons | ||
114 | * which never stabilize; if this occurs, we always boot Rockbox. */ | ||
115 | int iter_count = 0; | ||
116 | const int max_iter_count = 30; | ||
108 | 117 | ||
109 | /* Configure the button GPIOs as inputs */ | 118 | /* Configure the button GPIOs as inputs */ |
110 | gpio_config(GPIO_A, pinmask, GPIO_INPUT); | 119 | gpio_config(GPIO_A, pinmask, GPIO_INPUT); |
@@ -116,19 +125,18 @@ int spl_get_boot_option(void) | |||
116 | if(pin != lastpin) { | 125 | if(pin != lastpin) { |
117 | /* This will always be set on the first iteration */ | 126 | /* This will always be set on the first iteration */ |
118 | deadline = __ost_read32() + BTN_STABLE_TIME; | 127 | deadline = __ost_read32() + BTN_STABLE_TIME; |
128 | iter_count += 1; | ||
119 | } | 129 | } |
120 | } while(__ost_read32() < deadline); | 130 | } while(iter_count < max_iter_count && __ost_read32() < deadline); |
121 | |||
122 | /* Play button boots original firmware */ | ||
123 | if(pin == (1 << 17)) | ||
124 | return SPL_BOOTOPT_ORIG_FW; | ||
125 | |||
126 | /* Volume up boots recovery */ | ||
127 | if(pin == (1 << 19)) | ||
128 | return SPL_BOOTOPT_RECOVERY; | ||
129 | 131 | ||
130 | /* Default is to boot Rockbox */ | 132 | if(iter_count < max_iter_count && (pin & (1 << 17))) { |
131 | return SPL_BOOTOPT_ROCKBOX; | 133 | if(pin & (1 << 19)) |
134 | return BOOTOPTION_RECOVERY; /* Play+Volume Up */ | ||
135 | else | ||
136 | return BOOTOPTION_ORIG_FW; /* Play */ | ||
137 | } else { | ||
138 | return BOOTOPTION_ROCKBOX; /* Volume Up or no buttons */ | ||
139 | } | ||
132 | } | 140 | } |
133 | 141 | ||
134 | void spl_handle_pre_boot(int bootopt) | 142 | void spl_handle_pre_boot(int bootopt) |
@@ -145,7 +153,7 @@ void spl_handle_pre_boot(int bootopt) | |||
145 | /* System clock setup -- common to Rockbox and FiiO firmware | 153 | /* System clock setup -- common to Rockbox and FiiO firmware |
146 | * ---- | 154 | * ---- |
147 | * CPU at 1 GHz, L2 cache at 500 MHz | 155 | * CPU at 1 GHz, L2 cache at 500 MHz |
148 | * AHB0 and AHB2 and 200 MHz | 156 | * AHB0 and AHB2 at 200 MHz |
149 | * PCLK at 100 MHz | 157 | * PCLK at 100 MHz |
150 | * DDR at 200 MHz | 158 | * DDR at 200 MHz |
151 | */ | 159 | */ |
@@ -153,7 +161,7 @@ void spl_handle_pre_boot(int bootopt) | |||
153 | clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) | CLKMUX_CPU(SCLK_A) | | 161 | clk_set_ccr_mux(CLKMUX_SCLK_A(APLL) | CLKMUX_CPU(SCLK_A) | |
154 | CLKMUX_AHB0(SCLK_A) | CLKMUX_AHB2(SCLK_A)); | 162 | CLKMUX_AHB0(SCLK_A) | CLKMUX_AHB2(SCLK_A)); |
155 | 163 | ||
156 | if(bootopt == SPL_BOOTOPT_ROCKBOX) { | 164 | if(bootopt == BOOTOPTION_ROCKBOX) { |
157 | /* We don't use MPLL in Rockbox, so switch DDR memory to APLL */ | 165 | /* We don't use MPLL in Rockbox, so switch DDR memory to APLL */ |
158 | clk_set_ddr(X1000_CLK_SCLK_A, 5); | 166 | clk_set_ddr(X1000_CLK_SCLK_A, 5); |
159 | 167 | ||
diff --git a/firmware/target/mips/ingenic_x1000/fiiom3k/spl-target.h b/firmware/target/mips/ingenic_x1000/fiiom3k/spl-target.h deleted file mode 100644 index ac90508f44..0000000000 --- a/firmware/target/mips/ingenic_x1000/fiiom3k/spl-target.h +++ /dev/null | |||
@@ -1,29 +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 | #ifndef __SPL_TARGET_H__ | ||
23 | #define __SPL_TARGET_H__ | ||
24 | |||
25 | #define SPL_DDR_MEMORYSIZE 64 | ||
26 | #define SPL_DDR_AUTOSR_EN 1 | ||
27 | #define SPL_DDR_NEED_BYPASS 1 | ||
28 | |||
29 | #endif /* __SPL_TARGET_H__ */ | ||