summaryrefslogtreecommitdiff
path: root/rbutil/mkmpioboot/mkmpioboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil/mkmpioboot/mkmpioboot.c')
-rw-r--r--rbutil/mkmpioboot/mkmpioboot.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/rbutil/mkmpioboot/mkmpioboot.c b/rbutil/mkmpioboot/mkmpioboot.c
new file mode 100644
index 0000000000..6d52e53f09
--- /dev/null
+++ b/rbutil/mkmpioboot/mkmpioboot.c
@@ -0,0 +1,188 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id:$
9 *
10 * Copyright (C) 2010 by Marcin Bukat
11 *
12 * code taken mostly from mkboot.c
13 * Copyright (C) 2005 by Linus Nielsen Feltzing
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#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include "mkmpioboot.h"
28
29#define OF_FIRMWARE_LEN 0x100000 /* size of HD200_UPG.SYS file */
30#define MPIO_STRING_OFFSET 0xfffe0
31
32/* We support only 1.30.05 version of OF for now */
33static char *mpio_string = "HD200 HDD Audio Ver113005";
34
35/* MPIO HD200 firmware is plain binary image
36 * 4 bytes of initial SP (loaded on reset)
37 * 4 bytes of initial PC (loaded on reset)
38 * binary image with entry point 0x00000008
39 *
40 * We put our bootloader code at 0x000e0000
41 * and patch reset vector to jump directly
42 * into our code on reset
43 */
44
45static unsigned char image[OF_FIRMWARE_LEN];
46
47static unsigned int get_uint32be(unsigned char* p)
48{
49 return ((p[0] << 24) | (p[1] << 16) | (p[2]<<8) | p[3]);
50}
51
52static long checksum(unsigned char* buf, unsigned long length)
53{
54 unsigned long chksum = 69; /* MPIO HD200 model number */
55 unsigned long i;
56
57 if(buf == NULL)
58 return -1;
59
60 for (i = 0; i < length; i++)
61 {
62 chksum += *buf++;
63 }
64
65return chksum;
66}
67
68int mkmpioboot(const char* infile, const char* bootfile, const char* outfile, int origin)
69{
70 FILE *f;
71 int i;
72 int len;
73 unsigned long file_checksum;
74 unsigned char header_checksum[4];
75
76 memset(image, 0xff, sizeof(image));
77
78 /* First, read the mpio original firmware into the image */
79 f = fopen(infile, "rb");
80 if(!f) {
81 perror(infile);
82 return -1;
83 }
84
85 i = fread(image, 1, OF_FIRMWARE_LEN, f);
86 if(i < OF_FIRMWARE_LEN) {
87 perror(infile);
88 fclose(f);
89 return -2;
90 }
91
92 fclose(f);
93
94 /* Now check if we have OF file loaded based on presence
95 * of the version string in firmware
96 */
97
98 if (strcmp((char*)(image + MPIO_STRING_OFFSET),mpio_string) != 0)
99 {
100 perror("Loaded firmware file does not look like MPIO OF file!");
101 return -3;
102 }
103
104 /* Now, read the boot loader into the image */
105 f = fopen(bootfile, "rb");
106 if(!f) {
107 perror(bootfile);
108 fclose(f);
109 return -4;
110 }
111
112 /* get bootloader size
113 * excluding header
114 */
115 fseek(f, 0, SEEK_END);
116 len = ftell(f) - 8;
117
118 /* Now check if the place we want to put
119 * our bootloader is free
120 */
121 for(i=0;i<len;i++)
122 {
123 if (image[origin+i] != 0)
124 {
125 perror("Place for bootloader in OF file not empty");
126 return -5;
127 }
128 }
129
130 fseek(f, 0, SEEK_SET);
131
132 /* get bootloader checksum from the header*/
133 fread(header_checksum,1,4,f);
134
135 /* omit header */
136 fseek(f, 8, SEEK_SET);
137
138 i = fread(image + origin, 1, len, f);
139 if(i < len) {
140 perror(bootfile);
141 fclose(f);
142 return -6;
143 }
144
145 fclose(f);
146
147 /* calculate checksum and compare with data
148 * from header
149 */
150 file_checksum = checksum(image + origin, len);
151
152 if ( file_checksum != get_uint32be(header_checksum) )
153 {
154 printf("Bootloader checksum error\n");
155 return -7;
156 }
157
158 f = fopen(outfile, "wb");
159 if(!f) {
160 perror(outfile);
161 return -8;
162 }
163
164 /* Patch the stack pointer address */
165 image[0] = image[origin + 0];
166 image[1] = image[origin + 1];
167 image[2] = image[origin + 2];
168 image[3] = image[origin + 3];
169
170 /* Patch the reset vector to start the boot loader */
171 image[4] = image[origin + 4];
172 image[5] = image[origin + 5];
173 image[6] = image[origin + 6];
174 image[7] = image[origin + 7];
175
176 i = fwrite(image, 1, OF_FIRMWARE_LEN, f);
177 if(i < OF_FIRMWARE_LEN) {
178 perror(outfile);
179 fclose(f);
180 return -9;
181 }
182
183 printf("Wrote 0x%x bytes in %s\n", OF_FIRMWARE_LEN, outfile);
184
185 fclose(f);
186
187 return 0;
188}