Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * mkamsboot - a tool for merging bootloader code into an Sansa V2 |
| 11 | * (AMS) firmware file |
| 12 | * |
| 13 | * Copyright (C) 2008 Dave Chapman |
| 14 | * |
| 15 | * This program is free software; you can redistribute it and/or |
| 16 | * modify it under the terms of the GNU General Public License |
| 17 | * as published by the Free Software Foundation; either version 2 |
| 18 | * of the License, or (at your option) any later version. |
| 19 | * |
| 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 21 | * KIND, either express or implied. |
| 22 | * |
| 23 | ****************************************************************************/ |
| 24 | |
| 25 | #include <stdio.h> |
| 26 | #include <stdlib.h> |
| 27 | #include <stdint.h> |
| 28 | #include <sys/types.h> |
| 29 | #include <sys/stat.h> |
| 30 | #include <fcntl.h> |
| 31 | #include <unistd.h> |
| 32 | #include <string.h> |
| 33 | |
| 34 | #include <ucl/ucl.h> |
| 35 | |
| 36 | #include "mkamsboot.h" |
| 37 | |
| 38 | /* Header for ARM code binaries */ |
| 39 | #include "dualboot.h" |
| 40 | |
| 41 | /* Win32 compatibility */ |
| 42 | #ifndef O_BINARY |
| 43 | #define O_BINARY 0 |
| 44 | #endif |
| 45 | |
| 46 | /* standalone executable */ |
| 47 | int main(int argc, char* argv[]) |
| 48 | { |
| 49 | char *infile, *bootfile, *outfile; |
| 50 | int fdout; |
| 51 | off_t len; |
| 52 | uint32_t n; |
| 53 | unsigned char* buf; |
| 54 | int firmware_size; |
| 55 | int bootloader_size; |
| 56 | unsigned char* of_packed; |
| 57 | int of_packedsize; |
| 58 | unsigned char* rb_packed; |
| 59 | int rb_packedsize; |
Rafaël Carré | b6c20c1 | 2010-02-19 14:10:26 +0000 | [diff] [blame] | 60 | int patchable; |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 61 | int totalsize; |
Rafaël Carré | ff6b042 | 2010-05-24 10:06:52 +0000 | [diff] [blame] | 62 | int model; |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 63 | char errstr[200]; |
| 64 | struct md5sums sum; |
| 65 | char md5sum[33]; /* 32 digits + \0 */ |
| 66 | |
| 67 | sum.md5 = md5sum; |
| 68 | |
| 69 | /* VERSION comes frome the Makefile */ |
| 70 | fprintf(stderr, |
| 71 | "mkamsboot Version " VERSION "\n" |
| 72 | "This is free software; see the source for copying conditions. There is NO\n" |
| 73 | "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" |
| 74 | "\n"); |
| 75 | |
| 76 | if(argc != 4) { |
| 77 | printf("Usage: mkamsboot <firmware file> <boot file> <output file>\n"); |
| 78 | return 1; |
| 79 | } |
| 80 | |
| 81 | infile = argv[1]; |
| 82 | bootfile = argv[2]; |
| 83 | outfile = argv[3]; |
| 84 | |
Rafaël Carré | ff6b042 | 2010-05-24 10:06:52 +0000 | [diff] [blame] | 85 | /* Load bootloader file */ |
| 86 | rb_packed = load_rockbox_file(bootfile, &model, &bootloader_size, |
| 87 | &rb_packedsize, errstr, sizeof(errstr)); |
| 88 | if (rb_packed == NULL) { |
| 89 | fprintf(stderr, "%s", errstr); |
| 90 | fprintf(stderr, "[ERR] Could not load %s\n", bootfile); |
| 91 | return 1; |
| 92 | } |
| 93 | |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 94 | /* Load original firmware file */ |
Rafaël Carré | ff6b042 | 2010-05-24 10:06:52 +0000 | [diff] [blame] | 95 | buf = load_of_file(infile, model, &len, &sum, |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 96 | &firmware_size, &of_packed, &of_packedsize, errstr, sizeof(errstr)); |
| 97 | |
| 98 | if (buf == NULL) { |
Rafaël Carré | ff6b042 | 2010-05-24 10:06:52 +0000 | [diff] [blame] | 99 | free(rb_packed); |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 100 | fprintf(stderr, "%s", errstr); |
| 101 | fprintf(stderr, "[ERR] Could not load %s\n", infile); |
| 102 | return 1; |
| 103 | } |
| 104 | |
| 105 | fprintf(stderr, "[INFO] Original firmware MD5 checksum match\n"); |
| 106 | fprintf(stderr, "[INFO] Model: Sansa %s v%d - Firmware version: %s\n", |
Dominik Riebeling | 02dce45 | 2011-01-31 20:15:50 +0000 | [diff] [blame] | 107 | ams_identity[sum.model].model_name, |
| 108 | ams_identity[sum.model].hw_revision, sum.version); |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 109 | |
| 110 | |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 111 | printf("[INFO] Firmware patching has begun !\n\n"); |
| 112 | |
Rafaël Carré | bff5e3d | 2010-07-18 17:05:05 +0000 | [diff] [blame] | 113 | fprintf(stderr, "[INFO] Original firmware size: %8d bytes\n", |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 114 | firmware_size); |
Rafaël Carré | bff5e3d | 2010-07-18 17:05:05 +0000 | [diff] [blame] | 115 | fprintf(stderr, "[INFO] Packed OF size: %8d bytes\n", |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 116 | of_packedsize); |
Rafaël Carré | bff5e3d | 2010-07-18 17:05:05 +0000 | [diff] [blame] | 117 | fprintf(stderr, "[INFO] Bootloader size: %8d bytes\n", |
Rafaël Carré | 1a6172d | 2011-07-02 02:49:01 +0000 | [diff] [blame] | 118 | bootloader_size); |
Rafaël Carré | bff5e3d | 2010-07-18 17:05:05 +0000 | [diff] [blame] | 119 | fprintf(stderr, "[INFO] Packed bootloader size: %8d bytes\n", |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 120 | rb_packedsize); |
Rafaël Carré | bff5e3d | 2010-07-18 17:05:05 +0000 | [diff] [blame] | 121 | fprintf(stderr, "[INFO] Dual-boot function size: %8d bytes\n", |
Dominik Riebeling | 02dce45 | 2011-01-31 20:15:50 +0000 | [diff] [blame] | 122 | ams_identity[sum.model].bootloader_size); |
Rafaël Carré | 1a6172d | 2011-07-02 02:49:01 +0000 | [diff] [blame] | 123 | fprintf(stderr, "[INFO] UCL unpack function size: %8zu bytes\n", |
| 124 | sizeof(nrv2e_d8)); |
Rafaël Carré | bff5e3d | 2010-07-18 17:05:05 +0000 | [diff] [blame] | 125 | fprintf(stderr, "[INFO] Original firmware version: %8u bytes\n", |
| 126 | 0x200); |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 127 | |
Rafaël Carré | b6c20c1 | 2010-02-19 14:10:26 +0000 | [diff] [blame] | 128 | patchable = check_sizes(sum.model, rb_packedsize, bootloader_size, |
| 129 | of_packedsize, firmware_size, &totalsize, errstr, sizeof(errstr)); |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 130 | |
Rafaël Carré | bff5e3d | 2010-07-18 17:05:05 +0000 | [diff] [blame] | 131 | fprintf(stderr, "[INFO] Total size of new image: %8d bytes\n", totalsize); |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 132 | |
Rafaël Carré | b6c20c1 | 2010-02-19 14:10:26 +0000 | [diff] [blame] | 133 | if (!patchable) { |
| 134 | fprintf(stderr, "%s", errstr); |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 135 | free(buf); |
| 136 | free(of_packed); |
| 137 | free(rb_packed); |
| 138 | return 1; |
| 139 | } |
| 140 | |
Dominik Riebeling | 02dce45 | 2011-01-31 20:15:50 +0000 | [diff] [blame] | 141 | patch_firmware(sum.model, ams_identity[sum.model].fw_revision, |
| 142 | firmware_size, buf, len, of_packed, of_packedsize, rb_packed, |
| 143 | rb_packedsize); |
Dominik Riebeling | ea61780 | 2009-11-04 20:58:40 +0000 | [diff] [blame] | 144 | |
| 145 | /* Write the new firmware */ |
| 146 | fdout = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0666); |
| 147 | |
| 148 | if (fdout < 0) { |
| 149 | fprintf(stderr, "[ERR] Could not open %s for writing\n", outfile); |
| 150 | free(buf); |
| 151 | free(of_packed); |
| 152 | free(rb_packed); |
| 153 | return 1; |
| 154 | } |
| 155 | |
| 156 | n = write(fdout, buf, len); |
| 157 | |
| 158 | if (n != (unsigned)len) { |
| 159 | fprintf(stderr, "[ERR] Could not write firmware file\n"); |
| 160 | free(buf); |
| 161 | free(of_packed); |
| 162 | free(rb_packed); |
| 163 | return 1; |
| 164 | } |
| 165 | |
| 166 | close(fdout); |
| 167 | free(buf); |
| 168 | free(of_packed); |
| 169 | free(rb_packed); |
| 170 | fprintf(stderr, "\n[INFO] Patching succeeded!\n"); |
| 171 | |
| 172 | return 0; |
| 173 | } |
| 174 | |