Last active
May 26, 2024 11:07
-
-
Save kukrimate/ca0eb9b3222d45ab54a8b9310460144d to your computer and use it in GitHub Desktop.
Extract Lenovo UEFI update ISOs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# SPDX-License-Identifier: GPL-2.0-only | |
import struct | |
import sys | |
import binascii | |
# ISO9660 block size | |
iso_blocksize = 0x800 | |
# El Torito block | |
torito_block = 0x11 | |
if len(sys.argv) < 2: | |
print 'usage: extorito.py <input file> <output file>' | |
exit(1) | |
ifile_name = sys.argv[1] | |
ofile_name = sys.argv[2] | |
ifile = open(ifile_name, 'rb') | |
ofile = open(ofile_name, 'wb') | |
ifile.seek(iso_blocksize * torito_block, 0) | |
torito_data = ifile.read(iso_blocksize) | |
# hdr | |
ind, iso, ver, toritospec = struct.unpack('<B5sB32s', torito_data[0:39]) | |
if ind != 0 or iso != 'CD001' or ver != 1 \ | |
or toritospec != 'EL TORITO SPECIFICATION\x00\x00\x00\x00\x00\x00\x00\x00\x00': | |
print 'Not a valid El Torito image' | |
exit(1) | |
# catalog offset | |
ifile.seek(iso_blocksize * torito_block + 71, 0) | |
catalog_offset = struct.unpack('<H', ifile.read(2))[0] | |
# catalog | |
ifile.seek(iso_blocksize * catalog_offset, 0) | |
catalog = ifile.read(iso_blocksize) | |
# validation entry | |
hdr_id, platform, oem_str, checksum, key = struct.unpack('<BBxx24shH', catalog[0:32]) | |
if hdr_id != 1 or key != 0xaa55: | |
print 'Invalid boot catalog' | |
exit(1) | |
if platform != 0: | |
print 'Warning! This image is not for x86' | |
# initial entry | |
boot_ind, media, segm, system, sector_cnt, load_rba = \ | |
struct.unpack('<BBHBxHI', catalog[32:44]) | |
if boot_ind != 0x88: | |
print 'Warning! Not-bootable image' | |
if media != 4: | |
print 'Currently only HDD emulation images are supported!' | |
exit(1) | |
# Do NOT care about the sector count, | |
# because that is usually not specified in production images | |
ifile.seek(iso_blocksize * load_rba, 0) | |
disk_mbr = ifile.read(512) | |
mbrfile = open('mbr.bin', 'wb') | |
mbrfile.write(disk_mbr) | |
mbrfile.close() | |
# extract partition number 1 | |
bootflag, head, sect_cyl, sysid, end_head, end_sec_cyl, lba, sector_cnt = \ | |
struct.unpack('<BBHBBHII', disk_mbr[446:462]) | |
ifile.seek(iso_blocksize * load_rba + lba * 512) | |
ofile.write(ifile.read(sector_cnt * 512)) | |
ifile.close() | |
ofile.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment