blob: 108ef1ed4758dcf5499f48e7a20b1621f7d53702 [file] [log] [blame]
Luc Verhaegen838fe242009-06-17 00:48:02 +02001/*
2 * Decompression utility for AMI BIOSes.
3 *
4 * Copyright 2009 Luc Verhaegen <libv@skynet.be>
5 * Copyright 2000-2006 Anthony Borisow
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING. If not, write to
19 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#include <stdio.h>
23#include <inttypes.h>
24#include <errno.h>
25#include <string.h>
26#include <sys/mman.h>
27#include <sys/stat.h>
28#include <fcntl.h>
29#include <unistd.h>
30
31#include "bios_extract.h"
32#include "lh5_extract.h"
33
34struct AMI95ModuleName
35{
36 uint8_t Id;
37 char *Name;
38};
39
40static struct AMI95ModuleName
41AMI95ModuleNames[] = {
42 {0x00, "POST"},
43 {0x01, "Setup Server"},
44 {0x02, "RunTime"},
45 {0x03, "DIM"},
46 {0x04, "Setup Client"},
47 {0x05, "Remote Server"},
48 {0x06, "DMI Data"},
49 {0x07, "Green PC"},
50 {0x08, "Interface"},
51 {0x09, "MP"},
52 {0x0A, "Notebook"},
53 {0x0B, "Int-10"},
54 {0x0C, "ROM-ID"},
55 {0x0D, "Int-13"},
56 {0x0E, "OEM Logo"},
57 {0x0F, "ACPI Table"},
58 {0x10, "ACPI AML"},
59 {0x11, "P6 Microcode"},
60 {0x12, "Configuration"},
61 {0x13, "DMI Code"},
62 {0x14, "System Health"},
63 {0x15, "Memory Sizing"},
64 {0x16, "Memory Test"},
65 {0x17, "Debug"},
66 {0x18, "ADM (Display MGR)"},
67 {0x19, "ADM Font"},
68 {0x1A, "Small Logo"},
69 {0x1B, "SLAB"},
70 {0x20, "PCI AddOn ROM"},
71 {0x21, "Multilanguage"},
72 {0x22, "UserDefined"},
73 {0x23, "ASCII Font"},
74 {0x24, "BIG5 Font"},
75 {0x25, "OEM Logo"},
76 {0x2A, "User ROM"},
77 {0x2B, "PXE Code"},
78 {0x2C, "AMI Font"},
79 {0x2E, "User ROM"},
80 {0x2D, "Battery Refresh"},
81 {0x30, "Font Database"},
82 {0x31, "OEM Logo Data"},
83 {0x32, "Graphic Logo Code"},
84 {0x33, "Graphic Logo Data"},
85 {0x34, "Action Logo Code"},
86 {0x35, "Action Logo Data"},
87 {0x36, "Virus"},
88 {0x37, "Online Menu"},
89 {0x38, "Lang1 as ROM"},
90 {0x39, "Lang2 as ROM"},
91 {0x3A, "Lang3 as ROM"},
92 {0x70, "OSD Bitmaps"},
93 {0, NULL}
94};
95
96static char *
Luc Verhaegen15587352009-06-26 10:00:29 +020097AMI95ModuleNameGet(uint8_t ID)
Luc Verhaegen838fe242009-06-17 00:48:02 +020098{
99 int i;
100
101 for (i = 0; AMI95ModuleNames[i].Name; i++)
102 if (AMI95ModuleNames[i].Id == ID)
103 return AMI95ModuleNames[i].Name;
104
Luc Verhaegen15587352009-06-26 10:00:29 +0200105 return NULL;
Luc Verhaegen838fe242009-06-17 00:48:02 +0200106}
107
108/*
109 *
110 */
111Bool
Luc Verhaegen15587352009-06-26 10:00:29 +0200112AMI95Extract(unsigned char *BIOSImage, int BIOSLength, int BIOSOffset,
Luc Verhaegen838fe242009-06-17 00:48:02 +0200113 uint32_t AMIBOffset, uint32_t ABCOffset)
114{
115 Bool Compressed;
116 uint32_t Offset;
117 char Date[9];
118 int i;
119
120 struct abc {
121 const char AMIBIOSC[8];
122 const char Version[4];
123 const uint16_t CRCLen;
124 const uint32_t CRC32;
125 const uint16_t BeginLo;
126 const uint16_t BeginHi;
127 } *abc;
128
129 struct part {
130 /* When Previous Part Address is 0xFFFFFFFF, then this is the last part. */
131 const uint16_t PrePartLo; /* Previous part low word */
132 const uint16_t PrePartHi; /* Previous part high word */
133 const uint16_t CSize; /* Header length */
134 const uint8_t PartID; /* ID for this header */
135 const uint8_t IsComprs; /* 0x80 -> compressed */
136 const uint32_t RealCS; /* Real Address in RAM where to expand to */
137 const uint32_t ROMSize; /* Compressed Length */
138 const uint32_t ExpSize; /* Expanded Length */
139 } *part;
140
141 if (!ABCOffset) {
142 if ((BIOSImage[8] == '1') && (BIOSImage[9] == '0') &&
143 (BIOSImage[11] == '1') && (BIOSImage[12] == '0'))
144 fprintf(stderr, "Error: This is an AMI '94 (1010) BIOS Image.\n");
145 else
146 fprintf(stderr, "Error: This is an AMI '94 BIOS Image.\n");
147 return FALSE;
148 }
149
Luc Verhaegen15587352009-06-26 10:00:29 +0200150 /* now the individual modules */
151 abc = (struct abc *) (BIOSImage + ABCOffset);
152
153 /* Get Date */
154 memcpy(Date, BIOSImage + BIOSLength - 11, 8);
155 Date[8] = 0;
156
157 printf("AMI95 Version\t: %.4s (%s)\n", abc->Version, Date);
158
Luc Verhaegen838fe242009-06-17 00:48:02 +0200159 /* First, the boot rom */
Luc Verhaegen15587352009-06-26 10:00:29 +0200160 {
161 uint32_t BootOffset;
Luc Verhaegen838fe242009-06-17 00:48:02 +0200162 int fd;
163
Luc Verhaegen15587352009-06-26 10:00:29 +0200164 BootOffset = AMIBOffset & 0xFFFF0000;
165
166 printf("0x%05X (%6d bytes) -> amiboot.rom\n", BootOffset, BIOSLength - BootOffset);
Luc Verhaegen838fe242009-06-17 00:48:02 +0200167
168 fd = open("amiboot.rom", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
169 if (fd < 0) {
170 fprintf(stderr, "Error: unable to open %s: %s\n\n",
171 "amiboot.rom", strerror(errno));
172 return FALSE;
173 }
174
Luc Verhaegen15587352009-06-26 10:00:29 +0200175 write(fd, BIOSImage + BootOffset, BIOSLength - BootOffset);
Luc Verhaegen838fe242009-06-17 00:48:02 +0200176 close(fd);
177 }
178
Luc Verhaegen15587352009-06-26 10:00:29 +0200179 /* now dump the individual modules */
Luc Verhaegen838fe242009-06-17 00:48:02 +0200180 Offset = (abc->BeginHi << 4) + abc->BeginLo;
Luc Verhaegen838fe242009-06-17 00:48:02 +0200181
182 for (i = 0; i < 0x80; i++) {
Luc Verhaegen15587352009-06-26 10:00:29 +0200183 char filename[64], *ModuleName;
184 static uint8_t Multiple = 0; /* For the case of multiple 0x20 modules */
185 unsigned char *Buffer;
186 int BufferSize;
187
Luc Verhaegen838fe242009-06-17 00:48:02 +0200188 part = (struct part *) (BIOSImage + (Offset - BIOSOffset));
189
190 if (part->IsComprs == 0x80)
191 Compressed = FALSE;
192 else
193 Compressed = TRUE;
194
Luc Verhaegen15587352009-06-26 10:00:29 +0200195 if (part->PartID == 0x20)
196 sprintf(filename, "amipci_%02X_%02X.rom", Multiple++, part->PartID);
197 else
198 sprintf(filename, "amibody_%02x.rom", part->PartID);
Luc Verhaegen838fe242009-06-17 00:48:02 +0200199
Luc Verhaegen15587352009-06-26 10:00:29 +0200200 if (Compressed)
201 printf("0x%05X (%6d bytes)", Offset - BIOSOffset + 0x14, part->ROMSize);
202 else
203 printf("0x%05X (%6d bytes)", Offset - BIOSOffset + 0x0C, part->CSize);
Luc Verhaegen838fe242009-06-17 00:48:02 +0200204
Luc Verhaegen15587352009-06-26 10:00:29 +0200205 printf(" -> %s", filename);
206 if (part->PartID != 0x20)
207 printf(" ");
208 if (Compressed)
209 printf(" (%5d bytes)", part->ExpSize);
210 else
211 printf("\t\t");
Luc Verhaegen838fe242009-06-17 00:48:02 +0200212
Luc Verhaegen15587352009-06-26 10:00:29 +0200213 ModuleName = AMI95ModuleNameGet(part->PartID);
214 if (ModuleName)
215 printf(" \"%s\"\n", ModuleName);
216 else
217 printf("\n");
Luc Verhaegen838fe242009-06-17 00:48:02 +0200218
Luc Verhaegen15587352009-06-26 10:00:29 +0200219 if (Compressed)
220 BufferSize = part->ExpSize;
221 else
222 BufferSize = part->CSize;
Luc Verhaegen838fe242009-06-17 00:48:02 +0200223
Luc Verhaegen15587352009-06-26 10:00:29 +0200224 Buffer = MMapOutputFile(filename, BufferSize);
225 if (!Buffer)
226 return FALSE;
Luc Verhaegen838fe242009-06-17 00:48:02 +0200227
Luc Verhaegen15587352009-06-26 10:00:29 +0200228 if (Compressed)
229 LH5Decode(BIOSImage + (Offset - BIOSOffset) + 0x14, part->ROMSize,
230 Buffer, BufferSize);
231 else
232 memcpy(Buffer, BIOSImage + (Offset - BIOSOffset) + 0x0C, BufferSize);
233
234 munmap(Buffer, BufferSize);
Luc Verhaegen838fe242009-06-17 00:48:02 +0200235
236 if ((part->PrePartHi == 0xFFFF) || (part->PrePartLo == 0xFFFF))
237 break;
238 Offset = (part->PrePartHi << 4) + part->PrePartLo;
239 }
240
241 return TRUE;
242}