summaryrefslogtreecommitdiff
path: root/rbutil/jztool/src/x1000.c
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-07-17 19:35:09 +0100
committerAidan MacDonald <amachronic@protonmail.com>2021-07-20 14:56:58 +0000
commit740a50687f67f3684e4b5698f8f30e3adebb8f6e (patch)
treecc2afcc989f0ca89e849338ad136e4042acd6bc1 /rbutil/jztool/src/x1000.c
parent6f042e91dd8730bf72b423248aa2c520708f03c5 (diff)
downloadrockbox-740a50687f67f3684e4b5698f8f30e3adebb8f6e.tar.gz
rockbox-740a50687f67f3684e4b5698f8f30e3adebb8f6e.zip
jztool: add support for Shanling Q1 and Eros Qbootloader_shanlingq1_v1
Change-Id: I8e93162d1a9d82e9d132219f2803b1856d24ae6c
Diffstat (limited to 'rbutil/jztool/src/x1000.c')
-rw-r--r--rbutil/jztool/src/x1000.c179
1 files changed, 179 insertions, 0 deletions
diff --git a/rbutil/jztool/src/x1000.c b/rbutil/jztool/src/x1000.c
new file mode 100644
index 0000000000..aacad0ef01
--- /dev/null
+++ b/rbutil/jztool/src/x1000.c
@@ -0,0 +1,179 @@
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.h"
23#include "jztool_private.h"
24#include "microtar.h"
25#include <stdbool.h>
26#include <string.h>
27
28/* TODO: these functions could be refactored to be CPU-agnostic */
29static int run_stage1(jz_usbdev* dev, jz_buffer* buf)
30{
31 int rc = jz_usb_send(dev, 0xf4001000, buf->size, buf->data);
32 if(rc < 0)
33 return rc;
34
35 return jz_usb_start1(dev, 0xf4001800);
36}
37
38static int run_stage2(jz_usbdev* dev, jz_buffer* buf)
39{
40 int rc = jz_usb_send(dev, 0x80004000, buf->size, buf->data);
41 if(rc < 0)
42 return rc;
43
44 rc = jz_usb_flush_caches(dev);
45 if(rc < 0)
46 return rc;
47
48 return jz_usb_start2(dev, 0x80004000);
49}
50
51static int get_file(jz_context* jz, mtar_t* tar, const char* file,
52 bool decompress, jz_buffer** buf)
53{
54 jz_buffer* buffer = NULL;
55 mtar_header_t h;
56 int rc;
57
58 rc = mtar_find(tar, file, &h);
59 if(rc != MTAR_ESUCCESS) {
60 jz_log(jz, JZ_LOG_ERROR, "can't find %s in boot file, tar error %d", file, rc);
61 return JZ_ERR_BAD_FILE_FORMAT;
62 }
63
64 buffer = jz_buffer_alloc(h.size, NULL);
65 if(!buffer)
66 return JZ_ERR_OUT_OF_MEMORY;
67
68 rc = mtar_read_data(tar, buffer->data, buffer->size);
69 if(rc != MTAR_ESUCCESS) {
70 jz_buffer_free(buffer);
71 jz_log(jz, JZ_LOG_ERROR, "can't read %s in boot file, tar error %d", file, rc);
72 return JZ_ERR_BAD_FILE_FORMAT;
73 }
74
75 if(decompress) {
76 uint32_t dst_len;
77 jz_buffer* nbuf = jz_ucl_unpack(buffer->data, buffer->size, &dst_len);
78 jz_buffer_free(buffer);
79 if(!nbuf) {
80 jz_log(jz, JZ_LOG_ERROR, "error decompressing %s in boot file", file);
81 return JZ_ERR_BAD_FILE_FORMAT;
82 }
83
84 /* for simplicity just forget original size of buffer */
85 nbuf->size = dst_len;
86 buffer = nbuf;
87 }
88
89 *buf = buffer;
90 return JZ_SUCCESS;
91}
92
93static int show_version(jz_context* jz, jz_buffer* info_file)
94{
95 /* Extract the version string and log it for informational purposes */
96 char* boot_version = (char*)info_file->data;
97 char* endpos = memchr(boot_version, '\n', info_file->size);
98 if(!endpos) {
99 jz_log(jz, JZ_LOG_ERROR, "invalid metadata in boot file");
100 return JZ_ERR_BAD_FILE_FORMAT;
101 }
102
103 *endpos = 0;
104 jz_log(jz, JZ_LOG_NOTICE, "Rockbox bootloader version: %s", boot_version);
105 return JZ_SUCCESS;
106}
107
108/** \brief Load the Rockbox bootloader on an X1000 device
109 * \param dev USB device freshly returned by jz_usb_open()
110 * \param filename Path to the "bootloader.target" file
111 * \return either JZ_SUCCESS or an error code
112 */
113int jz_x1000_boot(jz_usbdev* dev, jz_device_type type, const char* filename)
114{
115 const jz_device_info* dev_info;
116 char spl_filename[32];
117 jz_buffer* spl = NULL, *bootloader = NULL, *info_file = NULL;
118 mtar_t tar;
119 int rc;
120
121 /* In retrospect using a model-dependent archive format was not a good
122 * idea, but it's not worth fixing just yet... */
123 dev_info = jz_get_device_info(type);
124 if(!dev_info)
125 return JZ_ERR_OTHER;
126 /* use of sprintf is safe since file_ext is short */
127 sprintf(spl_filename, "spl.%s", dev_info->file_ext);
128
129 /* Now open the archive */
130 rc = mtar_open(&tar, filename, "r");
131 if(rc != MTAR_ESUCCESS) {
132 jz_log(dev->jz, JZ_LOG_ERROR, "cannot open file %s (tar error: %d)", filename, rc);
133 return JZ_ERR_OPEN_FILE;
134 }
135
136 /* Extract all necessary files */
137 rc = get_file(dev->jz, &tar, spl_filename, false, &spl);
138 if(rc != JZ_SUCCESS)
139 goto error;
140
141 rc = get_file(dev->jz, &tar, "bootloader.ucl", true, &bootloader);
142 if(rc != JZ_SUCCESS)
143 goto error;
144
145 rc = get_file(dev->jz, &tar, "bootloader-info.txt", false, &info_file);
146 if(rc != JZ_SUCCESS)
147 goto error;
148
149 /* Display the version string */
150 rc = show_version(dev->jz, info_file);
151 if(rc != JZ_SUCCESS)
152 goto error;
153
154 /* Stage1 boot of SPL to set up hardware */
155 rc = run_stage1(dev, spl);
156 if(rc != JZ_SUCCESS)
157 goto error;
158
159 /* Need a bit of time for SPL to handle init */
160 jz_sleepms(500);
161
162 /* Stage2 boot into the bootloader's recovery menu
163 * User has to take manual action from there */
164 rc = run_stage2(dev, bootloader);
165 if(rc != JZ_SUCCESS)
166 goto error;
167
168 rc = JZ_SUCCESS;
169
170 error:
171 if(spl)
172 jz_buffer_free(spl);
173 if(bootloader)
174 jz_buffer_free(bootloader);
175 if(info_file)
176 jz_buffer_free(info_file);
177 mtar_close(&tar);
178 return rc;
179}