bios_extract: Handle Intel compressed option ROMs

This commit is contained in:
RichardG867
2022-04-15 21:35:20 -03:00
parent 466c075d0b
commit 2c20f4e441
2 changed files with 44 additions and 18 deletions

View File

@@ -127,7 +127,7 @@ int main(int argc, char *argv[])
int FileLength = 0;
uint32_t BIOSOffset = 0;
unsigned char *BIOSImage = NULL,
IntelAMI[256], /* just 13 bytes needed, but LH5Decode overflows the buffer */
IntelAMI[256], /* could be shorter if not for LH5Decode overflowing the buffer */
*Buffer = NULL;
int fd;
uint32_t Offset1 = 0, Offset2 = 0;
@@ -199,30 +199,44 @@ int main(int argc, char *argv[])
}
/* Bruteforce Intel AMI Color fork LH5. */
for (i = 0; i < (FileLength - 10); i += 0x4000) {
BIOSOffset = i;
Offset2 = 1;
for (Offset1 = 0; Offset1 < (FileLength - 10); Offset1 += 0x4000) {
BIOSOffset = Offset1;
CopyrightOffset:if ((LH5Decode(BIOSImage + BIOSOffset, FileLength - BIOSOffset, IntelAMI, 13) > -1) &&
!memcmp(IntelAMI, "AMIBIOS(C)AMI", 13)) {
printf("Found Intel AMIBIOS.\nOffset: %X\n", BIOSOffset);
(!memcmp(IntelAMI, "AMIBIOS(C)AMI", 13) || ((IntelAMI[0] == 0x55) && (IntelAMI[1] == 0xaa)))) {
if (Offset2 == 1) {
printf("Found potential Intel AMIBIOS.\n");
Offset2 = 86; /* magic exit code if no main body found */
}
Buffer = MMapOutputFile("intelbody.bin", 65536);
if (IntelAMI[0] == 0x55) {
len = IntelAMI[2] * 512;
sprintf((char *) IntelAMI, "intelopt_%05X.bin", BIOSOffset);
} else {
len = 65536;
sprintf((char *) IntelAMI, "intelbody_%05X.bin", BIOSOffset);
Offset2 = 0; /* main body found, all good */
}
printf("0x%05X -> %s\t(%d bytes)\n",
BIOSOffset, IntelAMI, len);
Buffer = MMapOutputFile((char *) IntelAMI, len);
if (!Buffer)
return 1;
i = 65536;
i = len;
while ((LH5Decode(BIOSImage + BIOSOffset, FileLength - BIOSOffset, Buffer, i) == -1) &&
(i > 16))
i--;
munmap(Buffer, 65536);
return 0;
munmap(Buffer, len);
} else if (!(BIOSOffset & 0xff)) {
BIOSOffset += 0x44;
goto CopyrightOffset;
}
}
fprintf(stderr, "Error: Unable to detect BIOS Image type.\n");
return 1;
if (Offset2)
fprintf(stderr, "Error: Unable to detect BIOS Image type.\n");
return Offset2;
}

View File

@@ -327,6 +327,7 @@ class BIOSExtractor(Extractor):
except:
# Bad data can cause infinite loops.
proc = None
self.debug_print('Processing timed out on:', file_path)
# Assume failure if nothing was extracted. A lone boot block file also counts as a failure,
# as the extractors produce them before attempting to extract any actual BIOS modules.
@@ -336,11 +337,23 @@ class BIOSExtractor(Extractor):
return False
elif num_files_extracted == 1 and dest_dir_files[0] in ('amiboot.rom', 'ssboot.rom'):
# Remove boot block file so that the destination directory can be rmdir'd later.
try:
os.remove(os.path.join(dest_dir_0, dest_dir_files[0]))
except:
pass
util.remove_all(dest_dir_files, lambda x: os.path.join(dest_dir_0, x))
return False
elif proc and proc.returncode == 86:
# We received the magic exit code indicating the Intel pipeline found
# an option ROM but not the main body. This could indicate a non-Intel
# BIOS with LH5-compressed option ROMs. Check the files just in case.
have_intelopt = have_intelbody = False
for dest_dir_file in dest_dir_files:
if dest_dir_file[:9] == 'intelopt_':
have_intelopt = True
elif dest_dir_file[:10] == 'intelbody_':
have_intelbody = True
break
if have_intelopt and not have_intelbody:
# Remove all files so that the destination directory can be rmdir'd later.
util.remove_all(dest_dir_files, lambda x: os.path.join(dest_dir_0, x))
return False
# Extract Award BIOS PhoenixNet ROS filesystem.
if not proc or b'Found Award BIOS.' in proc.stdout:
@@ -1404,7 +1417,6 @@ class IntelExtractor(Extractor):
if bootblock_offset < 0:
bootblock_offset = 0
dest_offset += bootblock_offset
self.debug_print('bbo', hex(bootblock_offset), 'do', hex(dest_offset))
out_f.seek(dest_offset)
# Copy data.
@@ -1461,7 +1473,7 @@ class IntelExtractor(Extractor):
out_f = open(dest_file_path + '.padded', 'wb')
# Write padding.
self.debug_print('Padding by', hex(padding_size))
self.debug_print('Adding', padding_size, 'bytes of initial padding')
while padding_size > 0:
out_f.write(b'\xFF' * min(padding_size, 1048576))
padding_size -= 1048576