FS#12662 by Manuel Flury - update French translation
[maemo-rb.git] / utils / MTP / beastpatcher / beastpatcher.c
blobb266079af5c4610b3fb37374da373bad9005d202
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * $Id$
11 * Copyright (c) 2009, Dave Chapman
12 * All rights reserved.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met:
18 * * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
21 * * Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials provided
24 * with the distribution.
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 ****************************************************************************/
40 #include <stdio.h>
41 #if !defined(_MSC_VER)
42 #include <unistd.h>
43 #include <fcntl.h>
44 #endif
45 #include <string.h>
46 #include <stdlib.h>
47 #if !defined(_MSC_VER)
48 #include <inttypes.h>
49 #else
50 #include "pstdint.h"
51 #endif
52 #include <sys/types.h>
53 #include <sys/stat.h>
55 #include "mtp_common.h"
56 #include "bootimg.h"
57 #include "mknkboot.h"
59 /* Code to create a single-boot bootloader.
60 Based on tools/gigabeats.c by Will Robertson.
63 /* Entry point (and load address) for the main Rockbox bootloader */
64 #define BL_ENTRY_POINT 0x8a000000
66 static void put_uint32le(uint32_t x, unsigned char* p)
68 p[0] = (unsigned char)(x & 0xff);
69 p[1] = (unsigned char)((x >> 8) & 0xff);
70 p[2] = (unsigned char)((x >> 16) & 0xff);
71 p[3] = (unsigned char)((x >> 24) & 0xff);
74 static uint32_t calc_csum(const unsigned char* pb, int cb)
76 uint32_t l = 0;
77 while (cb--)
78 l += *pb++;
79 return l;
82 static void create_single_boot(unsigned char* boot, int bootlen,
83 unsigned char** fwbuf, off_t* fwsize)
85 unsigned char* buf;
87 /* 15 bytes for header, 16 for signature bypass,
88 * 12 for record header, size of bootloader, 12 for footer */
89 *fwsize = 15 + 16 + 12 + bootlen + 12;
90 *fwbuf = malloc(*fwsize);
92 if(fwbuf == NULL) {
93 fprintf(stderr, "[ERR] Cannot allocate memory.\n" );
94 *fwbuf = NULL;
95 *fwsize = 0;
96 return;
99 buf = *fwbuf;
101 /* Copy bootloader image. */
102 memcpy(buf + 43, boot, bootlen);
104 /* Step 2: Create the file header */
105 sprintf((char *)buf, "B000FF\n");
106 put_uint32le(0x88200000, buf+7);
108 /* If the value below is too small, the update will attempt to flash.
109 * Be careful when changing this (leaving it as is won't cause issues) */
110 put_uint32le(0xCC0CD8, buf+11);
112 /* Step 3: Add the signature bypass record */
113 put_uint32le(0x88065A10, buf+15);
114 put_uint32le(4, buf+19);
115 put_uint32le(0xE3A00001, buf+27);
116 put_uint32le(calc_csum(buf+27,4), buf+23);
118 /* Step 4: Create a record for the actual code */
119 put_uint32le(BL_ENTRY_POINT, buf+31);
120 put_uint32le(bootlen, buf+35);
121 put_uint32le(calc_csum(buf + 43, bootlen), buf+39);
123 /* Step 5: Write the footer */
124 put_uint32le(0, buf+*fwsize-12);
125 put_uint32le(BL_ENTRY_POINT, buf+*fwsize-8);
126 put_uint32le(0, buf+*fwsize-4);
128 return;
131 static int readfile(const char* filename, struct filebuf *buf)
133 int res;
134 FILE* fp;
135 size_t bread;
136 #ifdef _LARGEFILE64_SOURCE
137 struct stat64 sb;
138 res = stat64(filename, &sb);
139 #else
140 struct stat sb;
141 res = stat(filename, &sb);
142 #endif
143 if(res == -1) {
144 fprintf(stderr, "[ERR] Getting firmware file size failed!\n");
145 return 1;
147 buf->len = sb.st_size;
148 buf->buf = (unsigned char*)malloc(buf->len);
149 /* load firmware binary to memory. */
150 fp = fopen(filename, "rb");
151 bread = fread(buf->buf, sizeof(unsigned char), buf->len, fp);
152 if((off_t)(bread * sizeof(unsigned char)) != buf->len) {
153 fprintf(stderr, "[ERR] Error reading file %s!\n", filename);
154 return 1;
156 fclose(fp);
157 return 0;
161 int beastpatcher(const char* bootfile, const char* firmfile, int interactive)
163 char yesno[4];
164 struct mtp_info_t mtp_info;
165 struct filebuf bootloader;
166 struct filebuf firmware;
167 struct filebuf fw;
168 bootloader.buf = bootimg;
169 bootloader.len = LEN_bootimg;
171 if (bootfile) {
172 if(readfile(bootfile, &bootloader) != 0) {
173 fprintf(stderr,"[ERR] Reading bootloader file failed.\n");
174 return 1;
177 if (firmfile) {
178 if(readfile(firmfile, &firmware) != 0) {
179 fprintf(stderr,"[ERR] Reading firmware file failed.\n");
180 return 1;
184 if (mtp_init(&mtp_info) < 0) {
185 fprintf(stderr,"[ERR] Can not init MTP\n");
186 return 1;
189 /* Scan for attached MTP devices. */
190 if (mtp_scan(&mtp_info) < 0)
192 fprintf(stderr,"[ERR] No devices found\n");
193 return 1;
196 printf("[INFO] Found device \"%s - %s\"\n", mtp_info.manufacturer,
197 mtp_info.modelname);
198 printf("[INFO] Device version: \"%s\"\n",mtp_info.version);
200 if (interactive) {
201 if(firmfile) {
202 printf("\nEnter i to install the Rockbox dualboot bootloader or c "
203 "to cancel and do nothing (i/c): ");
205 else {
206 printf("\nEnter i to install the Rockbox bootloader or c to cancel "
207 "and do nothing (i/c): ");
209 fgets(yesno,4,stdin);
212 if (!interactive || yesno[0]=='i')
214 if(firmfile) {
215 /* if a firmware file is given create a dualboot image. */
216 if(mknkboot(&firmware, &bootloader, &fw))
218 fprintf(stderr,"[ERR] Creating dualboot firmware failed.\n");
219 return 1;
222 else {
223 /* Create a single-boot bootloader from the embedded bootloader */
224 create_single_boot(bootloader.buf, bootloader.len, &fw.buf, &fw.len);
227 if (fw.buf == NULL)
229 fprintf(stderr,"[ERR] Creating the bootloader failed.\n");
230 return 1;
233 if (mtp_send_firmware(&mtp_info, fw.buf, fw.len) == 0)
235 fprintf(stderr,"[INFO] Bootloader installed successfully.\n");
237 else
239 fprintf(stderr,"[ERR] Bootloader install failed.\n");
242 /* We are now done with the firmware image */
243 free(fw.buf);
245 else
247 fprintf(stderr,"[INFO] Installation cancelled.\n");
249 if(bootfile) {
250 free(bootloader.buf);
252 if(firmfile) {
253 free(firmware.buf);
256 mtp_finished(&mtp_info);
258 return 0;
262 int sendfirm(const char* filename)
264 struct mtp_info_t mtp_info;
266 if (mtp_init(&mtp_info) < 0) {
267 fprintf(stderr,"[ERR] Can not init MTP\n");
268 return 1;
271 /* Scan for attached MTP devices. */
272 if (mtp_scan(&mtp_info) < 0)
274 fprintf(stderr,"[ERR] No devices found\n");
275 return 1;
278 printf("[INFO] Found device \"%s - %s\"\n", mtp_info.manufacturer,
279 mtp_info.modelname);
280 printf("[INFO] Device version: \"%s\"\n",mtp_info.version);
282 mtp_send_file(&mtp_info, filename);
284 mtp_finished(&mtp_info);
285 return 0;