Skip to content

Instantly share code, notes, and snippets.

@kukrimate
Last active May 26, 2024 11:07
Show Gist options
  • Save kukrimate/ca0eb9b3222d45ab54a8b9310460144d to your computer and use it in GitHub Desktop.
Save kukrimate/ca0eb9b3222d45ab54a8b9310460144d to your computer and use it in GitHub Desktop.
Extract Lenovo UEFI update ISOs
# 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