summaryrefslogtreecommitdiffstats
path: root/rbutil/mkrk27boot/mkrk27boot.c
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil/mkrk27boot/mkrk27boot.c')
-rw-r--r--rbutil/mkrk27boot/mkrk27boot.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/rbutil/mkrk27boot/mkrk27boot.c b/rbutil/mkrk27boot/mkrk27boot.c
new file mode 100644
index 0000000000..4b51e281c7
--- /dev/null
+++ b/rbutil/mkrk27boot/mkrk27boot.c
@@ -0,0 +1,281 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id:$
+ *
+ * Copyright (C) 2012 by Andrew Ryabinin
+ *
+ * based on firmware/test/fat/main.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <errno.h>
+#include "disk.h"
+#include "dir.h"
+#include "file.h"
+#include "ata.h"
+#include "storage.h"
+#include "mkrk27boot.h"
+
+
+const char *img_filename;
+static char mkrk27_error_msg[256];
+
+static void mkrk27_set_error(const char *msg, ...) {
+ va_list ap;
+ va_start(ap, msg);
+ snprintf(mkrk27_error_msg, sizeof(mkrk27_error_msg), msg, ap);
+ va_end(ap);
+ return;
+}
+
+
+
+/* Extracts in_file from FAT image to out_file */
+static int extract_file(const char *in_file, const char* out_file) {
+ char buf[81920];
+ int nread;
+
+ int fd = open(in_file, O_RDONLY);
+ if (fd < 0) {
+ mkrk27_set_error("Failed to open file %s. ", in_file);
+ return -1;
+ }
+
+ FILE *file = fopen(out_file, "wb");
+ if (!file) {
+ mkrk27_set_error("Failed to open file %s. ", out_file);
+ close(fd);
+ return -1;
+ }
+
+ while (nread = read(fd, buf, sizeof buf), nread > 0) {
+ char *out_ptr = buf;
+ int nwritten;
+
+ do {
+ nwritten = fwrite(buf, 1, nread, file);
+
+ if (nwritten >= 0) {
+ nread -= nwritten;
+ out_ptr += nwritten;
+ } else if (errno != EINTR) {
+ mkrk27_set_error("Writting to file %s failed.", out_file);
+ goto exit;
+ }
+ } while(nread > 0);
+ }
+
+ if (nread == 0) {
+ fclose(file);
+ close(fd);
+ return 0;
+ } else {
+ mkrk27_set_error("Copy from %s to %s failed.", out_file, in_file);
+ }
+exit:
+ fclose(file);
+ close(fd);
+ return -1;
+}
+
+/* Replace out_file in FAT image with in_file */
+static int replace_file(const char *in_file, const char *out_file) {
+ char buf[81920];
+ int fd;
+ int nread;
+
+ fd = creat(out_file, 0666);
+ if (fd < 0) {
+ mkrk27_set_error("Failed to open file %s. ", out_file);
+ return -1;
+ }
+
+ FILE *file = fopen(in_file, "rb");
+ if (!file) {
+ mkrk27_set_error("Failed to open file %s. ", in_file);
+ close(fd);
+ return -1;
+ }
+
+ while (nread = fread(buf, 1, sizeof buf, file), nread > 0) {
+ char *out_ptr = buf;
+ int nwritten;
+
+ do {
+ nwritten = write(fd, buf, nread);
+ if (nwritten >= 0) {
+ nread -= nwritten;
+ out_ptr += nwritten;
+ } else {
+ mkrk27_set_error("Writting to file %s failed.", out_file);
+ goto exit;
+ }
+ } while(nread > 0);
+ }
+
+ if (nread == 0) {
+ fclose(file);
+ close(fd);
+ return 0;
+ } else {
+ mkrk27_set_error("Replacing %s with %s failed.", out_file, in_file);
+ }
+
+exit:
+ fclose(file);
+ close(fd);
+ return -1;
+}
+
+static int mkrk27_init(const char *filename) {
+ int i;
+ int rc;
+ srand(clock());
+
+ img_filename = filename;
+
+ if(ata_init()) {
+ mkrk27_set_error("Warning! The disk is uninitialized\n");
+ return -1;
+ }
+
+ struct partinfo *pinfo = disk_init();
+
+ if (!pinfo) {
+ mkrk27_set_error("Failed reading partitions\n");
+ return -1;
+ }
+
+ for ( i=0; i<4; i++ ) {
+ if ( pinfo[i].type == PARTITION_TYPE_FAT32
+#ifdef HAVE_FAT16SUPPORT
+ || pinfo[i].type == PARTITION_TYPE_FAT16
+#endif
+ ) {
+ rc = fat_mount(IF_MV2(0,) IF_MD2(0,) pinfo[i].start);
+ if(rc) {
+ mkrk27_set_error("mount: %d",rc);
+ return -1;
+ }
+ break;
+ }
+ }
+ if ( i==4 ) {
+ if(fat_mount(IF_MV2(0,) IF_MD2(0,) 0)) {
+ mkrk27_set_error("FAT32 partition!");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+extern void ata_exit(void);
+
+static void mkrk27_deinit(void) {
+ ata_exit();
+}
+
+/* copy file */
+static int copy(const char *to, const char *from) {
+ FILE* fd_to, *fd_from;
+ char buf[4096];
+ ssize_t nread;
+
+ if (to == from) {
+ return 0;
+ }
+
+ fd_from = fopen(from, "rb");
+ if (!fd_from) {
+ mkrk27_set_error("Failed to open file %s.", from);
+ return -1;
+ }
+
+ fd_to = fopen(to, "wb");
+ if (!fd_to) {
+ mkrk27_set_error("Failed to open file %s.", to);
+ goto out_error;
+ }
+
+ while (nread = fread(buf, 1, sizeof buf, fd_from), nread > 0) {
+ char *out_ptr = buf;
+ ssize_t nwritten;
+
+ do {
+ nwritten = fwrite(out_ptr, 1, nread, fd_to);
+
+ if (nwritten >= 0)
+ {
+ nread -= nwritten;
+ out_ptr += nwritten;
+ }
+ else if (errno != EINTR)
+ {
+ mkrk27_set_error( "Writing to file %s failed.", to);
+ goto out_error;
+ }
+ } while (nread > 0);
+ }
+
+ if (nread == 0) {
+ fclose(fd_to);
+ fclose(fd_from);
+ return 0;
+ } else {
+ mkrk27_set_error("Copy from %s to %s failed.", from, to);
+ }
+
+out_error:
+
+ fclose(fd_from);
+ fclose(fd_to);
+
+ return -1;
+}
+
+char* mkrk27_get_error(void) {
+ return mkrk27_error_msg;
+}
+
+
+/* Patch rk27 firmware.
+ - img_file - original FAT image file, containing OF,
+ - rkw_file - rkw file which will replace BASE.RKW from OF,
+ - out_img_file - patched img file,
+ - out_rkw_file - BASE.RKW extracted from OF.
+*/
+int mkrk27_patch(const char* img_file, const char* rkw_file, const char* out_img_file, const char* out_rkw_file) {
+ if (copy(out_img_file, img_file)) {
+ return -1;
+ }
+ if (mkrk27_init(out_img_file)) {
+ return -1;
+ }
+ if (extract_file("/SYSTEM/BASE.RKW", out_rkw_file)) {
+ return -1;
+ }
+ if (replace_file(rkw_file, "/SYSTEM/BASE.RKW") ||
+ replace_file(rkw_file, "/SYSTEM00/BASE.RKW")) {
+ return -1;
+ }
+ mkrk27_deinit();
+ return 0;
+}