summaryrefslogtreecommitdiff
path: root/tools/mknkboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/mknkboot.c')
-rw-r--r--tools/mknkboot.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/tools/mknkboot.c b/tools/mknkboot.c
new file mode 100644
index 0000000000..c5e89f6834
--- /dev/null
+++ b/tools/mknkboot.c
@@ -0,0 +1,210 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Dave Chapman
11 *
12 * Based on merge0.cpp by James Espinoza, but completely rewritten.
13 *
14 * All files in this archive are subject to the GNU General Public License.
15 * See the file COPYING in the source tree root for full license agreement.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27#include <unistd.h>
28#include <inttypes.h>
29
30/*
31
32Description of nk.bin from
33
34http://www.xs4all.nl/~itsme/projects/xda/wince-flashfile-formats.html
35
36these files contain most information, several non-contigouos blocks
37may be present and an entrypoint in the code.
38
39 1. a 7 character signature "B000FF\n" ( that is with 3 zeroes, and
40 ending in a linefeed )
41 2. DWORD for image start
42 3. DWORD for image length
43 4. followd by several records of this format:
44 1. DWORD with address where this block is to be flashed to
45 2. DWORD with the length of this block
46 3. DWORD with the 32 bit checksum of this block, in perl:
47 unpack("%32C*", $data);
48 4. followed by <length> bytes of data
49 5. the last record has address ZERO, in the length the entrypoint
50 into the rom, and ZERO as checksum.
51
52
53NOTE: The Gigabeat-S nk.bin contains 171 records, plus the EOF record.
54
55mknkboot.c appends two images:
56
571) A "Disable" image which overwrites a word in the EBoot image
582) Our bootloader image, which has the same load address as nk.exe
59
60*/
61
62/* win32 compatibility */
63
64#ifndef O_BINARY
65#define O_BINARY 0
66#endif
67
68
69#define DISABLE_ADDR 0x88065A10 /* in EBoot */
70#define DISABLE_INSN 0xe3a00001
71#define DISABLE_SUM (0xe3+0xa0+0x00+0x01)
72
73static void put_uint32le(uint32_t x, unsigned char* p)
74{
75 p[0] = x & 0xff;
76 p[1] = (x >> 8) & 0xff;
77 p[2] = (x >> 16) & 0xff;
78 p[3] = (x >> 24) & 0xff;
79}
80
81static void usage(void)
82{
83 printf("Usage: mknkboot <firmware file> <boot file> <output file>\n");
84
85 exit(1);
86}
87
88static off_t filesize(int fd) {
89 struct stat buf;
90
91 if (fstat(fd,&buf) < 0) {
92 perror("[ERR] Checking filesize of input file");
93 return -1;
94 } else {
95 return(buf.st_size);
96 }
97}
98
99
100int main(int argc, char *argv[])
101{
102 char *infile, *bootfile, *outfile;
103 int fdin, fdboot,fdout;
104 int i,n;
105 int inlength,bootlength,newlength;
106 unsigned char* buf;
107 unsigned char* boot;
108 unsigned char* disable;
109 uint32_t sum;
110
111 if(argc < 3) {
112 usage();
113 }
114
115 infile = argv[1];
116 bootfile = argv[2];
117 outfile = argv[3];
118
119 fdin = open(infile, O_RDONLY|O_BINARY);
120 if (fdin < 0)
121 {
122 perror(infile);
123 }
124
125 fdboot = open(bootfile, O_RDONLY|O_BINARY);
126 if (fdboot < 0)
127 {
128 perror(bootfile);
129 }
130
131 inlength = filesize(fdin);
132
133 bootlength = filesize(fdboot);
134
135 /* Create buffer for original nk.bin, plus our bootloader (with 12
136 byte header), plus the 16-byte "disable record" */
137
138 newlength = inlength + (bootlength + 12) + 16;
139 buf = malloc(newlength);
140
141 if (buf==NULL)
142 {
143 printf("[ERR] Could not allocate memory, aborting\n");
144 return 1;
145 }
146
147 /****** STEP 1 - Read original nk.bin into buffer */
148
149 n = read(fdin, buf, inlength);
150 if (n != inlength)
151 {
152 printf("[ERR] Could not read from %s\n",infile);
153 return 2;
154 }
155
156 /****** STEP 2 - Move EOF record to the new EOF */
157 memcpy(buf + newlength - 12, buf + inlength - 12, 12);
158
159
160 /****** STEP 3 - Create a record to disable the firmware signature
161 check in EBoot */
162 disable = buf + inlength - 12;
163
164 put_uint32le(DISABLE_ADDR, disable);
165 put_uint32le(4, disable + 4);
166 put_uint32le(DISABLE_SUM, disable + 8);
167 put_uint32le(DISABLE_INSN, disable + 12);
168
169 /****** STEP 4 - Read the bootloader binary */
170 boot = disable + 16;
171 n = read(fdboot, boot + 12, bootlength);
172 if (n != bootlength)
173 {
174 printf("[ERR] Could not read from %s\n",bootfile);
175 return 3;
176 }
177
178 /****** STEP 5 - Create header for bootloader record */
179
180 /* Calculate simple checksum */
181 sum = 0;
182 for (i = 0; i < bootlength; i++) {
183 sum += boot[12 + i];
184 }
185
186 put_uint32le(0x88201000, boot); /* nk.exe start address */
187 put_uint32le(bootlength, boot + 4);
188 put_uint32le(sum, boot + 8);
189
190 /****** STEP 6 - Now write the output file */
191
192 fdout = open(outfile, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644);
193 if (fdout < 0)
194 {
195 perror(outfile);
196 }
197
198 n = write(fdout, buf, newlength);
199 if (n != newlength)
200 {
201 printf("[ERR] Could not write output file %s\n",outfile);
202 return 3;
203 }
204
205 close(fdin);
206 close(fdboot);
207 close(fdout);
208
209 return 0;
210}