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