summaryrefslogtreecommitdiffstats
path: root/src/fiasco.c
blob: 4c49911786741d8ab6803930301be604ddeafa7b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * Copyright (C) 2007
 *       pancake <pancake@youterm.com>
 *
 * 0xFFFF is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 0xFFFF is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with 0xFFFF; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#warning The FIASCO format is not yet fully implemented.

off_t piece_header_to_size(unsigned char *header)
{
	off_t sz = 0;
	sz += header[0x15+3];
	sz += header[0x15+2] << 8;
	sz += header[0x15+1] << 16;
	sz += header[0x15+0] << 24;
	return sz;
}

int piece_header_is_valid(unsigned char *header)
{
	if (header[0]=='T' && header[1]=='\x02')
		return 1;
	return 0;
}

#define piece_header_to_name(x) x+0x9;

/*
 * Teh Fiasco firmware parser lives here!
 */
int fiasco_read_image(char *file)
{
	int fd;
	unsigned char header[5];
	unsigned char version[55];
	char *version2;

	fd = open(file, O_RDONLY);

	printf("WARNING: Fiasco firmware is not yet fully supported. Don't relay on it ATM.\n");

	if (fd == -1) {
		printf("Cannot open fiasco image.\n");
		return -1;
	}

	// b4 00 00 00 00 36
	if (read(fd, header, 5) != 5) {
		printf("Error reading fiasco header\n");
		goto __fiasco_read_image_end;
	}

	if (header[0] != 0xb4) {
		printf("Invalid fiasco signature.\n");
		goto __fiasco_read_image_end;
	}
	// skip 6 bytes
	read(fd, version, 6);

	// print version header
	if (read(fd, version, 55) != 55) {
		printf("Error reading fiasco version.\n");
		goto __fiasco_read_image_end;
	}

	printf("# Fiasco header information:\n");
	printf("# ==========================\n");
	printf("# firmware type:    %s\n", version);
	version2 = version+strlen((char *)version)+3;
	if (*version2=='.')
		printf("firmware version: (null) (old firmware? no version string found?)\n");
	else printf("firmware version: %s\n", version2);

	// pieces:
	// after the version2 string starts the header-body loop love
	lseek(fd, 0xf + strlen(version2) + strlen(version), SEEK_SET);
	do {
		char piece_header[30];
		char description[256];
		unsigned char desc_len;
		char *name;
		off_t size;
		off_t tmp = lseek(fd, 0, SEEK_CUR);

		size = read(fd, piece_header, 30);
		if (size != 30) {
			fprintf(stderr, "Unexpected end of file\n");
			break;
		}
		dump_bytes(piece_header,30);
		if (!piece_header_is_valid(piece_header)) {
			fprintf(stderr, "Oops. Invalid piece header.\n");
			break;
		}
		size = piece_header_to_size(piece_header);
		name = piece_header_to_name(piece_header);
		printf("# %s is %lld bytes\n", name, size);

		read(fd, description, 255);
		printf("#   version: %s\n", description);
		/* lseek foreach subimage */
		lseek(fd, tmp, SEEK_SET);
		lseek(fd, strlen(description) + 0x20, SEEK_CUR);
		printf("rsc '%s' %lld '%s.bin' 0 %lld\n", file, lseek(fd,0,SEEK_CUR), name, size);
		lseek(fd, size, SEEK_CUR);
	} while(1);

	//printf("Image '%s', size %d bytes.\n", image, size);

__fiasco_read_image_end:
	close(fd);
	return 0;
}