blob: afdc37628c806400f21fdbbbc1eb99bfe4d21b7f [file] [log] [blame]
Luc Verhaegen038e6a52009-06-24 14:18:29 +02001/*
2 * Copyright 2009 Luc Verhaegen <libv@skynet.be>
3 * Copyright 2000-2003 Anthony Borisow
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#include <stdio.h>
21#include <inttypes.h>
22#include <string.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <fcntl.h>
26#include <errno.h>
27#include <sys/stat.h>
28#include <sys/mman.h>
29
30#include "bios_extract.h"
31#include "lh5_extract.h"
32
33struct PhoenixModuleName
34{
35 char Id;
36 char *Name;
37};
38
39static struct PhoenixModuleName
40PhoenixModuleNames[] = {
41 {'A', "acpi"},
42 {'B', "bioscode"},
43 {'C', "update"},
44 {'D', "display"},
45 {'E', "setup"},
46 {'F', "font"},
47 {'G', "decompcode"},
48 {'I', "bootblock"},
49 {'L', "logo"},
50 {'M', "miser"},
51 {'N', "rompilotload"},
52 {'O', "network"},
53 {'P', "rompilotinit"},
54 {'R', "oprom"},
55 {'S', "strings"},
56 {'T', "template"},
57 {'U', "user"},
58 {'X', "romexec"},
59 {'W', "wav"},
60 {'H', "tcpa_H"}, /* TCPA (Trusted Computing), USBKCLIB? */
61 {'K', "tcpa_K"}, /* TCPA (Trusted Computing), "AUTH"? */
62 {'Q', "tcpa_Q"}, /* TCPA (Trusted Computing), "SROM"? */
63 {'<', "tcpa_<"},
64 {'*', "tcpa_*"},
65 {'?', "tcpa_?"},
66 {'J', "SmartCardPAS"},
67};
68
69static char *
70PhoenixModuleNameGet(char Id)
71{
72 int i;
73
74 for (i = 0; PhoenixModuleNames[i].Name; i++)
75 if (PhoenixModuleNames[i].Id == Id)
76 return PhoenixModuleNames[i].Name;
77
78 return NULL;
79}
80
81static int
82PhoenixModule(unsigned char *BIOSImage, int BIOSLength, int Offset)
83{
84 struct PhoenixModule {
85 uint32_t Previous;
86 uint8_t Signature[3];
87 uint8_t Id;
88 uint8_t Type;
89 uint8_t HeadLen;
90 uint8_t Compression;
91 uint16_t Offset;
92 uint16_t Segment;
93 uint32_t ExpLen1;
94 uint32_t Packed1;
95 uint32_t Packed2;
96 uint32_t ExpLen2;
97 } *Module;
98 char *filename, *ModuleName;
99 unsigned char *Buffer;
100 int fd;
101
102 Module = (struct PhoenixModule *) (BIOSImage + Offset);
103
104 if (Module->Signature[0] || (Module->Signature[1] != 0x31) ||
105 (Module->Signature[2] != 0x31)) {
106 fprintf(stderr, "Error: Invalid module signature at 0x%05X\n",
107 Offset);
108 return 0;
109 }
110
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400111 if ((Offset + Module->HeadLen + 4 + le32toh(Module->Packed1)) > BIOSLength) {
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200112 fprintf(stderr, "Error: Module overruns buffer at 0x%05X\n",
113 Offset);
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400114 return le32toh(Module->Previous);
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200115 }
116
117 ModuleName = PhoenixModuleNameGet(Module->Type);
118 if (ModuleName) {
119 filename = malloc(strlen(ModuleName) + 7);
120 sprintf(filename, "%s_%1d.rom", ModuleName, Module->Id);
121 } else {
122 filename = malloc(9);
123 sprintf(filename, "%02X_%1d.rom", Module->Type, Module->Id);
124 }
125
126 fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
127 if (fd < 0) {
128 fprintf(stderr, "Error: unable to open %s: %s\n\n",
129 filename, strerror(errno));
130 free(filename);
131 return Module->Previous;
132 }
133
134 switch (Module->Compression) {
135 case 5: /* LH5 */
136 printf("0x%05X (%6d bytes) -> %s\t(%d bytes)", Offset + Module->HeadLen + 4,
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400137 le32toh(Module->Packed1), filename, le32toh(Module->ExpLen1));
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200138
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400139 Buffer = MMapOutputFile(filename, le32toh(Module->ExpLen1));
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200140 if (!Buffer)
141 break;
142
143 LH5Decode(BIOSImage + Offset + Module->HeadLen + 4,
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400144 le32toh(Module->Packed1), Buffer, le32toh(Module->ExpLen1));
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200145
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400146 munmap(Buffer, le32toh(Module->ExpLen1));
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200147
148 break;
149 /* case 3 */ /* LZSS */
150 case 0: /* not compressed at all */
151 /* why do we not use the full header here? */
152 printf("0x%05X (%6d bytes) -> %s", Offset + Module->HeadLen,
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400153 le32toh(Module->Packed1), filename);
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200154
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400155 write(fd, BIOSImage + Offset + Module->HeadLen, le32toh(Module->Packed1));
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200156 break;
157 default:
158 fprintf(stderr, "Unsupported compression type for %s: %d\n",
159 filename, Module->Compression);
160 printf("0x%05X (%6d bytes) -> %s\t(%d bytes)", Offset + Module->HeadLen + 4,
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400161 le32toh(Module->Packed1), filename, le32toh(Module->ExpLen1));
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200162
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400163 write(fd, BIOSImage + Offset + Module->HeadLen + 4, le32toh(Module->Packed1));
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200164 break;
165 }
166
167 close(fd);
168 free(filename);
169
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400170 if (le16toh(Module->Offset) || le16toh(Module->Segment)) {
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200171 if (!Module->Compression)
172 printf("\t\t");
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400173 printf("\t [0x%04X:0x%04X]\n", le16toh(Module->Segment) << 12, le16toh(Module->Offset));
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200174 } else
175 printf("\n");
176
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400177 return le32toh(Module->Previous);
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200178}
179
180/*
181 *
182 */
183Bool
184PhoenixExtract(unsigned char *BIOSImage, int BIOSLength, int BIOSOffset,
Luc Verhaegen15587352009-06-26 10:00:29 +0200185 uint32_t Offset1, uint32_t BCPSegmentOffset)
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200186{
187 struct PhoenixID {
188 char Name[6];
189 uint16_t Flags;
190 uint16_t Length;
191 } *ID;
192 uint32_t Offset;
193
194 printf("Found Phoenix BIOS \"%s\"\n", (char *) (BIOSImage + Offset1));
195
196 for (ID = (struct PhoenixID *) (BIOSImage + BCPSegmentOffset + 10);
197 ((void *) ID < (void *) (BIOSImage + BIOSLength)) && ID->Name[0];
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400198 ID = (struct PhoenixID *) (((unsigned char *) ID) + le16toh(ID->Length))) {
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200199#if 0
200 printf("PhoenixID: Name %c%c%c%c%c%c, Flags 0x%04X, Length %d\n",
201 ID->Name[0], ID->Name[1], ID->Name[2], ID->Name[3],
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400202 ID->Name[4], ID->Name[5], le16toh(ID->Flags), le16toh(ID->Length));
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200203#endif
204 if (!strncmp(ID->Name, "BCPSYS", 6))
205 break;
206 }
207
208 if (!ID->Name[0] || ((void *) ID >= (void *) (BIOSImage + BIOSLength))) {
209 fprintf(stderr, "Error: Failed to locate BCPSYS offset.\n");
210 return FALSE;
211 }
212
213 /* Get some info */
214 {
215 char Date[9], Time[9], Version[9];
216
217 strncpy(Date, ((char *) ID) + 0x0F, 8);
218 Date[8] = 0;
219 strncpy(Time, ((char *) ID) + 0x18, 8);
220 Time[8] = 0;
221 strncpy(Version, ((char *) ID) + 0x37, 8);
222 Version[8] = 0;
223
224 printf("Version \"%s\", created on %s at %s.\n", Version, Date, Time);
225 }
226
Peter Lemenkovfec24c92009-07-23 23:46:34 +0400227 Offset = le32toh(*((uint32_t *) (((char *) ID) + 0x77)));
Luc Verhaegen038e6a52009-06-24 14:18:29 +0200228 Offset &= (BIOSLength - 1);
229 if (!Offset) {
230 fprintf(stderr, "Error: retrieved invalid Modules offset.\n");
231 return FALSE;
232 }
233
234 while (Offset) {
235 Offset = PhoenixModule(BIOSImage, BIOSLength, Offset);
236 Offset &= BIOSLength - 1;
237 }
238
239 return TRUE;
240}
Luc Verhaegendd939162009-12-17 15:17:36 +0100241
242/*
243 *
244 */
245Bool
246PhoenixTrustedExtract(unsigned char *BIOSImage, int BIOSLength, int BIOSOffset,
247 uint32_t Offset1, uint32_t BCPSegmentOffset)
248{
249 fprintf(stderr, "ERROR: Phoenix TrustedCore images are not supported.\n");
250 printf("Feel free to RE the decompression routine :)\n");
251
252 return FALSE;
253}