From 2c20f4e44123ef31fa63db923fc41dc96cbe1f19 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Fri, 15 Apr 2022 21:35:20 -0300 Subject: [PATCH] bios_extract: Handle Intel compressed option ROMs --- bios_extract/src/bios_extract.c | 38 ++++++++++++++++++++++----------- biostools/extractors.py | 24 +++++++++++++++------ 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/bios_extract/src/bios_extract.c b/bios_extract/src/bios_extract.c index bfbb069..ddd7890 100644 --- a/bios_extract/src/bios_extract.c +++ b/bios_extract/src/bios_extract.c @@ -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; } diff --git a/biostools/extractors.py b/biostools/extractors.py index 978b0d4..7068e1b 100644 --- a/biostools/extractors.py +++ b/biostools/extractors.py @@ -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