blob: 1ddc1095213aad8447e6cd88ac6eee2fecb0c2ad [file] [log] [blame]
Luc Verhaegen838fe242009-06-17 00:48:02 +02001/*
2 * Copyright 2009 Luc Verhaegen <libv@skynet.be>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; see the file COPYING. If not, write to
16 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
Anton Kochkov8f9427f2013-04-07 13:20:30 +040019#define _GNU_SOURCE /* memmem is useful */
Luc Verhaegen838fe242009-06-17 00:48:02 +020020
21#include <stdio.h>
22#include <inttypes.h>
23#include <errno.h>
24#include <string.h>
25#include <sys/mman.h>
26#include <fcntl.h>
27#include <unistd.h>
Stefan Reinauer6ed57e52010-04-24 01:15:17 +020028#include "compat.h"
Luc Verhaegen838fe242009-06-17 00:48:02 +020029#include "bios_extract.h"
30
Anton Kochkov8f9427f2013-04-07 13:20:30 +040031static void HelpPrint(char *name)
Luc Verhaegen838fe242009-06-17 00:48:02 +020032{
Anton Kochkov8f9427f2013-04-07 13:20:30 +040033 printf("\n");
34 printf("Program to extract compressed modules from BIOS images.\n");
35 printf("Supports AMI, Award, Asus and Phoenix BIOSes.\n");
36 printf("\n");
37 printf("Usage:\n\t%s <filename>\n", name);
Luc Verhaegen838fe242009-06-17 00:48:02 +020038}
39
Anton Kochkov8f9427f2013-04-07 13:20:30 +040040unsigned char *MMapOutputFile(char *filename, int size)
Luc Verhaegen838fe242009-06-17 00:48:02 +020041{
Anton Kochkov8f9427f2013-04-07 13:20:30 +040042 unsigned char *Buffer;
43 char *tmp;
44 int fd;
Luc Verhaegen838fe242009-06-17 00:48:02 +020045
Anton Kochkov8f9427f2013-04-07 13:20:30 +040046 /* all slash signs '/' in filenames will be replaced by a backslash sign '\' */
47 tmp = filename;
48 while ((tmp = strchr(tmp, '/')) != NULL)
49 tmp[0] = '\\';
Peter Lemenkovd65284d2010-12-07 12:40:50 +010050
Anton Kochkov8f9427f2013-04-07 13:20:30 +040051 fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
52 if (fd < 0) {
53 fprintf(stderr, "Error: unable to open %s: %s\n\n", filename,
54 strerror(errno));
55 return NULL;
56 }
Luc Verhaegen838fe242009-06-17 00:48:02 +020057
Anton Kochkov8f9427f2013-04-07 13:20:30 +040058 /* grow file */
59 if (lseek(fd, size - 1, SEEK_SET) == -1) {
60 fprintf(stderr, "Error: Failed to grow \"%s\": %s\n", filename,
61 strerror(errno));
62 close(fd);
63 return NULL;
64 }
65
66 if (write(fd, "", 1) != 1) {
67 fprintf(stderr, "Error: Failed to write to \"%s\": %s\n",
68 filename, strerror(errno));
69 close(fd);
70 return NULL;
71 }
72
73 Buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
74 if (Buffer == ((void *)-1)) {
75 fprintf(stderr, "Error: Failed to mmap %s: %s\n", filename,
76 strerror(errno));
77 close(fd);
78 return NULL;
79 }
80
Luc Verhaegen838fe242009-06-17 00:48:02 +020081 close(fd);
Luc Verhaegen838fe242009-06-17 00:48:02 +020082
Anton Kochkov8f9427f2013-04-07 13:20:30 +040083 return Buffer;
Luc Verhaegen838fe242009-06-17 00:48:02 +020084}
85
Anton Kochkovb09d0ef2012-12-21 07:17:56 +040086/* TODO: Make bios identification more flexible */
87
Luc Verhaegen838fe242009-06-17 00:48:02 +020088static struct {
Anton Kochkov8f9427f2013-04-07 13:20:30 +040089 char *String1;
90 char *String2;
91 Bool(*Handler) (unsigned char *Image, int ImageLength, int ImageOffset,
92 uint32_t Offset1, uint32_t Offset2);
Luc Verhaegen838fe242009-06-17 00:48:02 +020093} BIOSIdentification[] = {
Anton Kochkov8f9427f2013-04-07 13:20:30 +040094 {
95 "AMIBOOT ROM", "AMIBIOSC", AMI95Extract}, {
96 "$ASUSAMI$", "AMIBIOSC", AMI95Extract}, {
97 "AMIEBBLK", "AMIBIOSC", AMI95Extract}, {
98 "Award BootBlock", "= Award Decompression Bios =", AwardExtract}, {
Peter Lemenkov92b6e292009-08-02 14:30:05 +040099 "Award Modular BIOS", "Award Software Inc", AwardExtract}, {
Anton Kochkov8f9427f2013-04-07 13:20:30 +0400100 "Phoenix FirstBIOS", "BCPSEGMENT", PhoenixExtract}, {
101 "PhoenixBIOS 4.0", "BCPSEGMENT", PhoenixExtract}, {
102 "PhoenixBIOS Version", "BCPSEGMENT", PhoenixExtract}, {
103 "Phoenix ServerBIOS 3", "BCPSEGMENT", PhoenixExtract}, {
104 "Phoenix TrustedCore", "BCPSEGMENT", PhoenixExtract}, {
105 "Phoenix SecureCore", "BCPSEGMENT", PhoenixExtract}, {
106NULL, NULL, NULL},};
Luc Verhaegen838fe242009-06-17 00:48:02 +0200107
Anton Kochkov8f9427f2013-04-07 13:20:30 +0400108int main(int argc, char *argv[])
Luc Verhaegen838fe242009-06-17 00:48:02 +0200109{
Anton Kochkov8f9427f2013-04-07 13:20:30 +0400110 int FileLength = 0;
111 uint32_t BIOSOffset = 0;
112 unsigned char *BIOSImage = NULL;
113 int fd;
114 uint32_t Offset1, Offset2;
115 int i, len;
116 unsigned char *tmp;
Luc Verhaegen838fe242009-06-17 00:48:02 +0200117
Anton Kochkov8f9427f2013-04-07 13:20:30 +0400118 if ((argc != 2) || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
119 HelpPrint(argv[0]);
120 return 1;
121 }
122
123 fd = open(argv[1], O_RDONLY);
124 if (fd < 0) {
125 fprintf(stderr, "Error: Failed to open %s: %s\n", argv[1],
126 strerror(errno));
127 return 1;
128 }
129
130 FileLength = lseek(fd, 0, SEEK_END);
131 if (FileLength < 0) {
132 fprintf(stderr, "Error: Failed to lseek \"%s\": %s\n", argv[1],
133 strerror(errno));
134 return 1;
135 }
136
137 BIOSOffset = (0x100000 - FileLength) & 0xFFFFF;
138
139 BIOSImage = mmap(NULL, FileLength, PROT_READ, MAP_PRIVATE, fd, 0);
140 if (BIOSImage < 0) {
141 fprintf(stderr, "Error: Failed to mmap %s: %s\n", argv[1],
142 strerror(errno));
143 return 1;
144 }
145
146 printf("Using file \"%s\" (%ukB)\n", argv[1], FileLength >> 10);
147
148 for (i = 0; BIOSIdentification[i].Handler; i++) {
149 len = strlen(BIOSIdentification[i].String1);
150 tmp =
151 memmem(BIOSImage, FileLength - len,
152 BIOSIdentification[i].String1, len);
153 if (!tmp)
154 continue;
155 Offset1 = tmp - BIOSImage;
156
157 len = strlen(BIOSIdentification[i].String2);
158 tmp =
159 memmem(BIOSImage, FileLength - len,
160 BIOSIdentification[i].String2, len);
161 if (!tmp)
162 continue;
163 Offset2 = tmp - BIOSImage;
164
165 if (BIOSIdentification[i].Handler
166 (BIOSImage, FileLength, BIOSOffset, Offset1, Offset2))
167 return 0;
168 else
169 return 1;
170 }
171
172 fprintf(stderr, "Error: Unable to detect BIOS Image type.\n");
Luc Verhaegen838fe242009-06-17 00:48:02 +0200173 return 1;
Luc Verhaegen838fe242009-06-17 00:48:02 +0200174}