blob: 837815b845ab4d50999ad816da269128573dc6c5 [file] [log] [blame]
/*
* Copyright 2009 Luc Verhaegen <libv@skynet.be>
*
* This program 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, or (at your option)
* any later version.
*
* This program 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 this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define _GNU_SOURCE /* memmem is useful */
#include <stdio.h>
#include <inttypes.h>
#include <errno.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include "compat.h"
#include "bios_extract.h"
static void HelpPrint(char *name)
{
printf("\n");
printf("Program to extract compressed modules from BIOS images.\n");
printf("Supports AMI, Award, Asus and Phoenix BIOSes.\n");
printf("\n");
printf("Usage:\n\t%s <filename>\n", name);
}
unsigned char *MMapOutputFile(char *filename, int size)
{
unsigned char *Buffer;
char *tmp;
int fd;
/* all slash signs '/' in filenames will be replaced by a backslash sign '\' */
tmp = filename;
while ((tmp = strchr(tmp, '/')) != NULL)
tmp[0] = '\\';
fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd < 0) {
fprintf(stderr, "Error: unable to open %s: %s\n\n", filename,
strerror(errno));
return NULL;
}
/* grow file */
if (lseek(fd, size - 1, SEEK_SET) == -1) {
fprintf(stderr, "Error: Failed to grow \"%s\": %s\n", filename,
strerror(errno));
close(fd);
return NULL;
}
if (write(fd, "", 1) != 1) {
fprintf(stderr, "Error: Failed to write to \"%s\": %s\n",
filename, strerror(errno));
close(fd);
return NULL;
}
Buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (Buffer == ((void *)-1)) {
fprintf(stderr, "Error: Failed to mmap %s: %s\n", filename,
strerror(errno));
close(fd);
return NULL;
}
close(fd);
return Buffer;
}
/* TODO: Make bios identification more flexible */
static struct {
char *String1;
char *String2;
Bool(*Handler) (unsigned char *Image, int ImageLength, int ImageOffset,
uint32_t Offset1, uint32_t Offset2);
} BIOSIdentification[] = {
{
"AMIBOOT ROM", "AMIBIOSC", AMI95Extract}, {
"$ASUSAMI$", "AMIBIOSC", AMI95Extract}, {
"AMIEBBLK", "AMIBIOSC", AMI95Extract}, {
"BootBlock SIO Table", "AMIBIOSC", AMI95Extract}, {
"Award BootBlock", "= Award Decompression Bios =", AwardExtract}, {
"Award Modular BIOS", "Award Software Inc", AwardExtract}, {
"Phoenix FirstBIOS", "BCPSEGMENT", PhoenixExtract}, {
"PhoenixBIOS 4.0", "BCPSEGMENT", PhoenixExtract}, {
"PhoenixBIOS Version", "BCPSEGMENT", PhoenixExtract}, {
"Phoenix ServerBIOS 3", "BCPSEGMENT", PhoenixExtract}, {
"Phoenix TrustedCore", "BCPSEGMENT", PhoenixExtract}, {
"Phoenix SecureCore", "BCPSEGMENT", PhoenixExtract}, {
NULL, NULL, NULL},};
int main(int argc, char *argv[])
{
int FileLength = 0;
uint32_t BIOSOffset = 0;
unsigned char *BIOSImage = NULL;
int fd;
uint32_t Offset1, Offset2;
int i, len;
unsigned char *tmp;
if ((argc != 2) || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
HelpPrint(argv[0]);
return 1;
}
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Error: Failed to open %s: %s\n", argv[1],
strerror(errno));
return 1;
}
FileLength = lseek(fd, 0, SEEK_END);
if (FileLength < 0) {
fprintf(stderr, "Error: Failed to lseek \"%s\": %s\n", argv[1],
strerror(errno));
return 1;
}
BIOSOffset = (0x100000 - FileLength) & 0xFFFFF;
BIOSImage = mmap(NULL, FileLength, PROT_READ, MAP_PRIVATE, fd, 0);
if (BIOSImage < 0) {
fprintf(stderr, "Error: Failed to mmap %s: %s\n", argv[1],
strerror(errno));
return 1;
}
printf("Using file \"%s\" (%ukB)\n", argv[1], FileLength >> 10);
for (i = 0; BIOSIdentification[i].Handler; i++) {
len = strlen(BIOSIdentification[i].String1);
tmp =
memmem(BIOSImage, FileLength - len,
BIOSIdentification[i].String1, len);
if (!tmp)
continue;
Offset1 = tmp - BIOSImage;
len = strlen(BIOSIdentification[i].String2);
tmp =
memmem(BIOSImage, FileLength - len,
BIOSIdentification[i].String2, len);
if (!tmp)
continue;
Offset2 = tmp - BIOSImage;
if (BIOSIdentification[i].Handler
(BIOSImage, FileLength, BIOSOffset, Offset1, Offset2))
return 0;
else
return 1;
}
fprintf(stderr, "Error: Unable to detect BIOS Image type.\n");
return 1;
}