]> git.zerfleddert.de Git - rsbs2/blame - src/filesystem.c
fix firmware extraction
[rsbs2] / src / filesystem.c
CommitLineData
1f1fa7b6
MG
1#include <sys/stat.h>
2#include <sys/types.h>
3#include <limits.h>
4#include <fcntl.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <strings.h>
8#include <string.h>
9#include <unistd.h>
10#include <errno.h>
11#include <libgen.h>
12#include "rsb-lz.h"
e8563c43 13#include "filesystem.h"
1f1fa7b6 14
81a1093d
MG
15struct file_entry* get_next_file(unsigned char *fw, int len)
16{
17 static unsigned char *pos;
b5163e0d 18 static unsigned char *start;
81a1093d
MG
19 static unsigned char *end;
20 static struct file_entry fent;
21 int name_length;
22
23 if (fw != NULL && len != 0) {
24 pos = fw + 0x28;
25
8658e967 26#if 0
81a1093d 27 printf("Start of filesystem: 0x%08x\n", *((unsigned int*)pos));
8658e967 28#endif
b5163e0d 29 start = fw;
81a1093d
MG
30 pos = fw + *((unsigned int*)pos);
31 end = fw + len;
32 }
33
34 fent.unknown = *pos;
35 pos++;
36
b5163e0d
MG
37 if (fent.unknown == 0x00) {
38 /* EOF */
39 int fill = (4 - ((pos - start) % 4)) % 4;
40 int i;
41
42 for (i = 0; i < fill; i++) {
43 if (*pos != 0xff) {
44 fprintf(stderr, "Wrong fill byte after EOF: 0x%02x, aborting!\n", *pos);
45 exit(1);
46 }
47 pos++;
48 }
49
50 if (pos != end) {
51 fprintf(stderr, "EOF marker not at end-of-file %p <-> %p, aborting!\n", pos, end);
52 exit(1);
53 }
54
55 return NULL;
56 }
57
58
81a1093d
MG
59 name_length = *((unsigned int*)pos);
60 pos += 4;
61
62 fent.length = *((unsigned int*)pos);
63 pos += 4;
64
65 if ((fent.length > (end - pos)) ||
66 (name_length > (end - pos))) {
b5163e0d
MG
67 printf("EOF reached without hitting EOF marker, aborting "
68 "(unknown: 0x%02x, namelen: 0x%08x, contentlen: 0x%08x!\n",
69 fent.unknown, name_length, fent.length);
70 exit(1);
81a1093d
MG
71 }
72
73 fent.name = (char*)pos;
74 pos += name_length;
75
76 fent.start = pos;
77 pos += fent.length;
78
79 return &fent;
80}
81
1f1fa7b6
MG
82void extract_files(unsigned char *fw, int len)
83{
81a1093d 84 struct file_entry *fent;
358935b6 85
81a1093d
MG
86 fent = get_next_file(fw, len);
87
88 while (fent) {
3de486ae 89 printf("%s: unknown: 0x%02x, length: %d, ",
81a1093d 90 fent->name, fent->unknown, fent->length);
1f1fa7b6 91
81a1093d 92 if (fent->length > 0) {
3de486ae 93 write_file(extracted_file(fent->name), fent->start, fent->length);
81a1093d 94 if (*((unsigned int*)fent->start) == LZ_MAGIC) {
1f1fa7b6 95 char *lzname;
e726b380
MG
96 unsigned char *outbuf;
97 unsigned int outlen;
1f1fa7b6 98
81a1093d 99 if ((lzname = strdup(fent->name)) == NULL) {
1f1fa7b6
MG
100 perror("strdup");
101 exit(1);
102 }
103
104 if (!strcmp(lzname + strlen(lzname) - 4 , ".lz")) {
105 fprintf(stderr, "Ugh, can't derive filename...\n");
106 exit(1);
107 }
108 lzname[strlen(lzname) - 3] = 0x00;
109
3de486ae 110 printf("%s: packed file found, ", lzname);
1f1fa7b6 111
e726b380
MG
112 outbuf = extract_lz_file(fent->start, &outlen, 0);
113 write_file(extracted_file((char*)lzname), outbuf, outlen);
114
115 free(outbuf);
1f1fa7b6 116 free(lzname);
81a1093d 117 } else if (!strcmp(fent->name, "firmware")) {
1f1fa7b6
MG
118 unsigned char *lzpos;
119 char lzname[128];
120
121 bzero(lzname, sizeof(lzname));
122 strcpy(lzname, "firmware.");
123
81a1093d 124 lzpos = fent->start + *((unsigned int*)(fent->start + 0x20));
1f1fa7b6
MG
125 memcpy(lzname + strlen(lzname), lzpos - 4, 4);
126 lzpos += 4;
127 if (*((unsigned int*)(lzpos)) == LZ_MAGIC) {
e726b380
MG
128 unsigned char *outbuf;
129 unsigned int outlen;
130
131 printf("%s: compressed firmware part found", lzname);
132 outbuf = extract_lz_file(lzpos, &outlen, 1);
133 printf(", ");
134 write_file(extracted_file((char*)lzname), outbuf, outlen);
135
136 free(outbuf);
1f1fa7b6
MG
137 }
138 }
395daefd
MG
139 } else {
140 printf(", ignoring...\n");
1f1fa7b6 141 }
81a1093d 142 fent = get_next_file(NULL, 0);
1f1fa7b6
MG
143 }
144}
145
505ad254
MG
146void replace_add_file(unsigned char *fw, int len, char *fwname, char *lname)
147{
148 fprintf(stderr, "%s: Implement me!\n", __func__);
149 exit(1);
150}
151
e5be7964
MG
152void list_files(unsigned char *fw, int len)
153{
154 struct file_entry *fent;
155
156 for (fent = get_next_file(fw, len); fent != NULL; fent = get_next_file(NULL, 0)) {
157 printf("0x%x %8d %s\n", fent->unknown, fent->length, fent->name);
158 }
159
160}
161
1f1fa7b6
MG
162void mkdir_p(char *dir)
163{
62b8ccf0 164 char *parent;
1f1fa7b6
MG
165
166 if ((dir == NULL) || (!strcmp(dir, ".")))
167 return;
168
62b8ccf0
MG
169 parent = strdup(dirname(dir));
170 if (parent == NULL) {
1f1fa7b6
MG
171 perror("strdup");
172 exit(1);
173 }
62b8ccf0 174
1f1fa7b6
MG
175 mkdir_p(parent);
176
177 errno = 0;
178 if (mkdir(dir, 0755) == -1) {
179 if (errno != EEXIST) {
180 fprintf(stderr, "%s: ", dir);
181 perror("mkdir");
182 exit(1);
183 }
184 }
62b8ccf0 185 free(parent);
1f1fa7b6
MG
186}
187
188void write_file(char *fname, unsigned char *buf, int len)
189{
1f1fa7b6
MG
190 char *filename_c, *dirn;
191 int fd;
192 int remaining;
193 int ret;
194
3de486ae 195 if ((filename_c = strdup(fname)) == NULL) {
1f1fa7b6
MG
196 perror("strdup");
197 exit(1);
198 }
62b8ccf0
MG
199 dirn = strdup(dirname(filename_c));
200 if (dirn == NULL) {
201 perror("strdup");
202 exit(1);
203 }
1f1fa7b6 204 mkdir_p(dirn);
62b8ccf0 205 free(dirn);
1f1fa7b6
MG
206 free(filename_c);
207
3de486ae
MG
208 if ((fd = open(fname, O_WRONLY|O_CREAT, 0644)) == -1) {
209 fprintf(stderr, "%s: ", fname);
1f1fa7b6
MG
210 perror("open");
211 exit(1);
212 }
213
214 remaining = len;
215
216 while(remaining) {
217 ret = write(fd, buf + (len - remaining), remaining);
218 if (ret < 0) {
219 perror("write");
220 exit(1);
221 }
222 remaining -= ret;
223 }
224
3de486ae 225 printf("%s written.\n", fname);
1f1fa7b6
MG
226
227 close(fd);
228}
3de486ae
MG
229
230char *extracted_file(char *fname)
231{
232 static char filename[PATH_MAX];
233
234 strcpy(filename, "extracted/");
235 strcat(filename, fname);
236
237 return filename;
238}
Impressum, Datenschutz