blob: cd87ee8db0ad385798a87af7f6281b7180f9e45f [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
19#define _GNU_SOURCE /* memmem is useful */
20
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
31static void
32HelpPrint(char *name)
33{
Luc Verhaegen17ca1c52009-07-13 16:19:25 +020034 printf("\n");
35 printf("Program to extract compressed modules from BIOS images.\n");
36 printf("Supports AMI, Award, Asus and Phoenix BIOSes.\n");
37 printf("\n");
38 printf("Usage:\n\t%s <filename>\n", name);
Luc Verhaegen838fe242009-06-17 00:48:02 +020039}
40
41unsigned char *
42MMapOutputFile(char *filename, int size)
43{
44 unsigned char* Buffer;
45 int fd;
46
47 fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
48 if (fd < 0) {
49 fprintf(stderr, "Error: unable to open %s: %s\n\n",
50 filename, strerror(errno));
51 return NULL;
52 }
53
54 /* grow file */
55 if (lseek(fd, size - 1, SEEK_SET) == -1) {
56 fprintf(stderr, "Error: Failed to grow \"%s\": %s\n",
57 filename, strerror(errno));
58 close(fd);
59 return NULL;
60 }
61
62 if (write(fd, "", 1) != 1) {
63 fprintf(stderr, "Error: Failed to write to \"%s\": %s\n",
64 filename, strerror(errno));
65 close(fd);
66 return NULL;
67 }
68
69 Buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
70 if (Buffer == ((void *) -1)) {
71 fprintf(stderr, "Error: Failed to mmap %s: %s\n",
72 filename, strerror(errno));
73 close(fd);
74 return NULL;
75 }
76
77 close(fd);
78
79 return Buffer;
80}
81
82static struct {
83 char *String1;
84 char *String2;
85 Bool (*Handler) (unsigned char *Image, int ImageLength, int ImageOffset,
Luc Verhaegen15587352009-06-26 10:00:29 +020086 uint32_t Offset1, uint32_t Offset2);
Luc Verhaegen838fe242009-06-17 00:48:02 +020087} BIOSIdentification[] = {
88 {"AMIBOOT ROM", "AMIBIOSC", AMI95Extract},
Luc Verhaegen8ff3ebf2009-12-17 13:27:51 +010089 {"$ASUSAMI$", "AMIBIOSC", AMI95Extract},
Luc Verhaegena794e6b2009-12-21 11:37:19 +010090 {"AMIEBBLK", "AMIBIOSC", AMI95Extract},
Luc Verhaegen5c343ad2009-07-13 11:46:37 +020091 {"Award BootBlock", "= Award Decompression Bios =", AwardExtract},
Luc Verhaegen15587352009-06-26 10:00:29 +020092 {"Phoenix FirstBIOS", "BCPSEGMENT", PhoenixExtract},
Luc Verhaegen038e6a52009-06-24 14:18:29 +020093 {"PhoenixBIOS 4.0", "BCPSEGMENT", PhoenixExtract},
Luc Verhaegendd939162009-12-17 15:17:36 +010094 {"Phoenix TrustedCore", "BCPSEGMENT", PhoenixTrustedExtract},
Luc Verhaegen838fe242009-06-17 00:48:02 +020095 {NULL, NULL, NULL},
96};
97
98/*
99 *
100 */
101int
102main(int argc, char *argv[])
103{
Luc Verhaegen838fe242009-06-17 00:48:02 +0200104 int FileLength = 0;
105 uint32_t BIOSOffset = 0;
106 unsigned char *BIOSImage = NULL;
107 int fd;
108 uint32_t Offset1, Offset2;
109 int i, len;
110 unsigned char *tmp;
111
Luc Verhaegen17ca1c52009-07-13 16:19:25 +0200112 if ((argc != 2) || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
Luc Verhaegen838fe242009-06-17 00:48:02 +0200113 HelpPrint(argv[0]);
114 return 1;
115 }
116
Luc Verhaegen15587352009-06-26 10:00:29 +0200117 fd = open(argv[1], O_RDONLY);
Luc Verhaegen838fe242009-06-17 00:48:02 +0200118 if (fd < 0) {
119 fprintf(stderr, "Error: Failed to open %s: %s\n",
Luc Verhaegen15587352009-06-26 10:00:29 +0200120 argv[1], strerror(errno));
Luc Verhaegen838fe242009-06-17 00:48:02 +0200121 return 1;
122 }
123
124 FileLength = lseek(fd, 0, SEEK_END);
125 if (FileLength < 0) {
126 fprintf(stderr, "Error: Failed to lseek \"%s\": %s\n",
Luc Verhaegen15587352009-06-26 10:00:29 +0200127 argv[1], strerror(errno));
Luc Verhaegen838fe242009-06-17 00:48:02 +0200128 return 1;
129 }
Luc Verhaegena794e6b2009-12-21 11:37:19 +0100130
131 BIOSOffset = (0x100000 - FileLength) & 0xFFFFF;
Luc Verhaegen838fe242009-06-17 00:48:02 +0200132
133 BIOSImage = mmap(NULL, FileLength, PROT_READ, MAP_PRIVATE, fd, 0);
134 if (BIOSImage < 0) {
135 fprintf(stderr, "Error: Failed to mmap %s: %s\n",
Luc Verhaegen15587352009-06-26 10:00:29 +0200136 argv[1], strerror(errno));
Luc Verhaegen838fe242009-06-17 00:48:02 +0200137 return 1;
138 }
139
Luc Verhaegen15587352009-06-26 10:00:29 +0200140 printf("Using file \"%s\" (%ukB)\n", argv[1], FileLength >> 10);
Luc Verhaegen838fe242009-06-17 00:48:02 +0200141
142 for (i = 0; BIOSIdentification[i].Handler; i++) {
143 len = strlen(BIOSIdentification[i].String1);
144 tmp = memmem(BIOSImage, FileLength - len, BIOSIdentification[i].String1, len);
145 if (!tmp)
146 continue;
147 Offset1 = tmp - BIOSImage;
148
149 len = strlen(BIOSIdentification[i].String2);
150 tmp = memmem(BIOSImage, FileLength - len, BIOSIdentification[i].String2, len);
151 if (!tmp)
152 continue;
153 Offset2 = tmp - BIOSImage;
154
Luc Verhaegen15587352009-06-26 10:00:29 +0200155 if (BIOSIdentification[i].Handler(BIOSImage, FileLength, BIOSOffset,
Luc Verhaegen838fe242009-06-17 00:48:02 +0200156 Offset1, Offset2))
157 return 0;
158 else
159 return 1;
160 }
161
162 fprintf(stderr, "Error: Unable to detect BIOS Image type.\n");
163 return 1;
164}