Prepare new maemo release
[maemo-rb.git] / rbutil / mkrk27boot / mkrk27boot.c
blob4b51e281c799300ad96d14714c07f0438d83b8e3
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id:$
10 * Copyright (C) 2012 by Andrew Ryabinin
12 * based on firmware/test/fat/main.c
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <time.h>
29 #include <errno.h>
30 #include "disk.h"
31 #include "dir.h"
32 #include "file.h"
33 #include "ata.h"
34 #include "storage.h"
35 #include "mkrk27boot.h"
38 const char *img_filename;
39 static char mkrk27_error_msg[256];
41 static void mkrk27_set_error(const char *msg, ...) {
42 va_list ap;
43 va_start(ap, msg);
44 snprintf(mkrk27_error_msg, sizeof(mkrk27_error_msg), msg, ap);
45 va_end(ap);
46 return;
51 /* Extracts in_file from FAT image to out_file */
52 static int extract_file(const char *in_file, const char* out_file) {
53 char buf[81920];
54 int nread;
56 int fd = open(in_file, O_RDONLY);
57 if (fd < 0) {
58 mkrk27_set_error("Failed to open file %s. ", in_file);
59 return -1;
62 FILE *file = fopen(out_file, "wb");
63 if (!file) {
64 mkrk27_set_error("Failed to open file %s. ", out_file);
65 close(fd);
66 return -1;
69 while (nread = read(fd, buf, sizeof buf), nread > 0) {
70 char *out_ptr = buf;
71 int nwritten;
73 do {
74 nwritten = fwrite(buf, 1, nread, file);
76 if (nwritten >= 0) {
77 nread -= nwritten;
78 out_ptr += nwritten;
79 } else if (errno != EINTR) {
80 mkrk27_set_error("Writting to file %s failed.", out_file);
81 goto exit;
83 } while(nread > 0);
86 if (nread == 0) {
87 fclose(file);
88 close(fd);
89 return 0;
90 } else {
91 mkrk27_set_error("Copy from %s to %s failed.", out_file, in_file);
93 exit:
94 fclose(file);
95 close(fd);
96 return -1;
99 /* Replace out_file in FAT image with in_file */
100 static int replace_file(const char *in_file, const char *out_file) {
101 char buf[81920];
102 int fd;
103 int nread;
105 fd = creat(out_file, 0666);
106 if (fd < 0) {
107 mkrk27_set_error("Failed to open file %s. ", out_file);
108 return -1;
111 FILE *file = fopen(in_file, "rb");
112 if (!file) {
113 mkrk27_set_error("Failed to open file %s. ", in_file);
114 close(fd);
115 return -1;
118 while (nread = fread(buf, 1, sizeof buf, file), nread > 0) {
119 char *out_ptr = buf;
120 int nwritten;
122 do {
123 nwritten = write(fd, buf, nread);
124 if (nwritten >= 0) {
125 nread -= nwritten;
126 out_ptr += nwritten;
127 } else {
128 mkrk27_set_error("Writting to file %s failed.", out_file);
129 goto exit;
131 } while(nread > 0);
134 if (nread == 0) {
135 fclose(file);
136 close(fd);
137 return 0;
138 } else {
139 mkrk27_set_error("Replacing %s with %s failed.", out_file, in_file);
142 exit:
143 fclose(file);
144 close(fd);
145 return -1;
148 static int mkrk27_init(const char *filename) {
149 int i;
150 int rc;
151 srand(clock());
153 img_filename = filename;
155 if(ata_init()) {
156 mkrk27_set_error("Warning! The disk is uninitialized\n");
157 return -1;
160 struct partinfo *pinfo = disk_init();
162 if (!pinfo) {
163 mkrk27_set_error("Failed reading partitions\n");
164 return -1;
167 for ( i=0; i<4; i++ ) {
168 if ( pinfo[i].type == PARTITION_TYPE_FAT32
169 #ifdef HAVE_FAT16SUPPORT
170 || pinfo[i].type == PARTITION_TYPE_FAT16
171 #endif
173 rc = fat_mount(IF_MV2(0,) IF_MD2(0,) pinfo[i].start);
174 if(rc) {
175 mkrk27_set_error("mount: %d",rc);
176 return -1;
178 break;
181 if ( i==4 ) {
182 if(fat_mount(IF_MV2(0,) IF_MD2(0,) 0)) {
183 mkrk27_set_error("FAT32 partition!");
184 return -1;
187 return 0;
190 extern void ata_exit(void);
192 static void mkrk27_deinit(void) {
193 ata_exit();
196 /* copy file */
197 static int copy(const char *to, const char *from) {
198 FILE* fd_to, *fd_from;
199 char buf[4096];
200 ssize_t nread;
202 if (to == from) {
203 return 0;
206 fd_from = fopen(from, "rb");
207 if (!fd_from) {
208 mkrk27_set_error("Failed to open file %s.", from);
209 return -1;
212 fd_to = fopen(to, "wb");
213 if (!fd_to) {
214 mkrk27_set_error("Failed to open file %s.", to);
215 goto out_error;
218 while (nread = fread(buf, 1, sizeof buf, fd_from), nread > 0) {
219 char *out_ptr = buf;
220 ssize_t nwritten;
222 do {
223 nwritten = fwrite(out_ptr, 1, nread, fd_to);
225 if (nwritten >= 0)
227 nread -= nwritten;
228 out_ptr += nwritten;
230 else if (errno != EINTR)
232 mkrk27_set_error( "Writing to file %s failed.", to);
233 goto out_error;
235 } while (nread > 0);
238 if (nread == 0) {
239 fclose(fd_to);
240 fclose(fd_from);
241 return 0;
242 } else {
243 mkrk27_set_error("Copy from %s to %s failed.", from, to);
246 out_error:
248 fclose(fd_from);
249 fclose(fd_to);
251 return -1;
254 char* mkrk27_get_error(void) {
255 return mkrk27_error_msg;
259 /* Patch rk27 firmware.
260 - img_file - original FAT image file, containing OF,
261 - rkw_file - rkw file which will replace BASE.RKW from OF,
262 - out_img_file - patched img file,
263 - out_rkw_file - BASE.RKW extracted from OF.
265 int mkrk27_patch(const char* img_file, const char* rkw_file, const char* out_img_file, const char* out_rkw_file) {
266 if (copy(out_img_file, img_file)) {
267 return -1;
269 if (mkrk27_init(out_img_file)) {
270 return -1;
272 if (extract_file("/SYSTEM/BASE.RKW", out_rkw_file)) {
273 return -1;
275 if (replace_file(rkw_file, "/SYSTEM/BASE.RKW") ||
276 replace_file(rkw_file, "/SYSTEM00/BASE.RKW")) {
277 return -1;
279 mkrk27_deinit();
280 return 0;