diff options
author | Leah Rowe <leah@libreboot.org> | 2023-07-08 22:07:36 +0100 |
---|---|---|
committer | Leah Rowe <leah@libreboot.org> | 2023-07-08 22:09:58 +0100 |
commit | 2bbb4c839a8224b17c7929b7ea612085d1351d20 (patch) | |
tree | 2542dfe950ff5927fa0d2f3fb1782c262467953e /resources/blobs | |
parent | 6bc619db902015af208f2b3d2321708e1db9da11 (diff) |
remove blobutil and boards/utils needing/for blobs
delete all blobs. TODO: actually deblob coreboot/uboot
when downloading. i'll that in a little while, in an
upcoming commit.
yes.
purge it all, in fsf style. censor what the fsf doesn't like.
so that they can feel good about having less, because
ideological purity is better than helping more people
use coreboot, yes?
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'resources/blobs')
-rwxr-xr-x | resources/blobs/me7_update_parser.py | 616 | ||||
-rw-r--r-- | resources/blobs/sources | 76 |
2 files changed, 0 insertions, 692 deletions
diff --git a/resources/blobs/me7_update_parser.py b/resources/blobs/me7_update_parser.py deleted file mode 100755 index e3e91413..00000000 --- a/resources/blobs/me7_update_parser.py +++ /dev/null @@ -1,616 +0,0 @@ -#!/usr/bin/env python3 - -"""ME7 Update binary parser.""" - -# Copyright (C) 2020 Tom Hiller <thrilleratplay@gmail.com> -# Copyright (C) 2016-2018 Nicola Corna <nicola@corna.info> -# -# 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 3 of the License, 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. -# - -# Based on the amazing me_cleaner, https://github.com/corna/me_cleaner, parses -# the required signed partition from an ME update file to generate a valid -# flashable ME binary. -# -# This was written for Heads ROM, https://github.com/osresearch/heads -# to allow continuous integration reproducible builds for Lenovo xx20 models -# (X220, T420, T520, etc). -# -# A full model list can be found: -# https://download.lenovo.com/ibmdl/pub/pc/pccbbs/mobiles/83rf46ww.txt - - -from struct import pack, unpack -from typing import List -import argparse -import sys -import hashlib -import binascii -import os.path - -############################################################################# - -FTPR_END = 0x76000 -MINIFIED_FTPR_OFFSET = 0x400 # offset start of Factory Partition (FTPR) -ORIG_FTPR_OFFSET = 0xCC000 -PARTITION_HEADER_OFFSET = 0x30 # size of partition header - -DEFAULT_OUTPUT_FILE_NAME = "flashregion_2_intel_me.bin" - -############################################################################# - - -class EntryFlags: - """EntryFlag bitmap values.""" - - ExclBlockUse = 8192 - WOPDisable = 4096 - Logical = 2048 - Execute = 1024 - Write = 512 - Read = 256 - DirectAccess = 128 - Type = 64 - - -def generateHeader() -> bytes: - """Generate Header.""" - ROM_BYPASS_INSTR_0 = binascii.unhexlify("2020800F") - ROM_BYPASS_INSTR_1 = binascii.unhexlify("40000010") - ROM_BYPASS_INSTR_2 = pack("<I", 0) - ROM_BYPASS_INSTR_3 = pack("<I", 0) - - # $FPT Partition table header - HEADER_TAG = "$FPT".encode() - HEADER_NUM_PARTITIONS = pack("<I", 1) - HEADER_VERSION = b"\x20" # version 2.0 - HEADER_ENTRY_TYPE = b"\x10" - HEADER_LENGTH = b"\x30" - HEADER_CHECKSUM = pack("<B", 0) - HEADER_FLASH_CYCLE_LIFE = pack("<H", 7) - HEADER_FLASH_CYCLE_LIMIT = pack("<H", 100) - HEADER_UMA_SIZE = pack("<H", 32) - HEADER_FLAGS = binascii.unhexlify("000000FCFFFF") - HEADER_FITMAJOR = pack("<H", 0) - HEADER_FITMINOR = pack("<H", 0) - HEADER_FITHOTFIX = pack("<H", 0) - HEADER_FITBUILD = pack("<H", 0) - - FTPR_header_layout = bytearray( - ROM_BYPASS_INSTR_0 - + ROM_BYPASS_INSTR_1 - + ROM_BYPASS_INSTR_2 - + ROM_BYPASS_INSTR_3 - + HEADER_TAG - + HEADER_NUM_PARTITIONS - + HEADER_VERSION - + HEADER_ENTRY_TYPE - + HEADER_LENGTH - + HEADER_CHECKSUM - + HEADER_FLASH_CYCLE_LIFE - + HEADER_FLASH_CYCLE_LIMIT - + HEADER_UMA_SIZE - + HEADER_FLAGS - + HEADER_FITMAJOR - + HEADER_FITMINOR - + HEADER_FITHOTFIX - + HEADER_FITBUILD - ) - - # Update checksum - FTPR_header_layout[27] = (0x100 - sum(FTPR_header_layout) & 0xFF) & 0xFF - - return FTPR_header_layout - - -def generateFtpPartition() -> bytes: - """Partition table entry.""" - ENTRY_NAME = binascii.unhexlify("46545052") - ENTRY_OWNER = binascii.unhexlify("FFFFFFFF") # "None" - ENTRY_OFFSET = binascii.unhexlify("00040000") - ENTRY_LENGTH = binascii.unhexlify("00600700") - ENTRY_START_TOKENS = pack("<I", 1) - ENTRY_MAX_TOKENS = pack("<I", 1) - ENTRY_SCRATCH_SECTORS = pack("<I", 0) - ENTRY_FLAGS = pack( - "<I", - ( - EntryFlags.ExclBlockUse - + EntryFlags.Execute - + EntryFlags.Write - + EntryFlags.Read - + EntryFlags.DirectAccess - ), - ) - - partition = ( - ENTRY_NAME - + ENTRY_OWNER - + ENTRY_OFFSET - + ENTRY_LENGTH - + ENTRY_START_TOKENS - + ENTRY_MAX_TOKENS - + ENTRY_SCRATCH_SECTORS - + ENTRY_FLAGS - ) - - # offset of the partition - length of partition entry -length of header - pad_len = MINIFIED_FTPR_OFFSET - (len(partition) + PARTITION_HEADER_OFFSET) - padding = b"" - - for i in range(0, pad_len): - padding += b"\xFF" - - return partition + padding - - -############################################################################ - - -class OutOfRegionException(Exception): - """Out of Region Exception.""" - - pass - - -class clean_ftpr: - """Clean Factory Parition (FTPR).""" - - UNREMOVABLE_MODULES = ("ROMP", "BUP") - COMPRESSION_TYPE_NAME = ("uncomp.", "Huffman", "LZMA") - - def __init__(self, ftpr: bytes): - """Init.""" - self.orig_ftpr = ftpr - self.ftpr = ftpr - self.mod_headers: List[bytes] = [] - self.check_and_clean_ftpr() - - ##################################################################### - # tilities - ##################################################################### - def slice(self, offset: int, size: int) -> bytes: - """Copy data of a given size from FTPR starting from offset.""" - offset_end = offset + size - return self.ftpr[offset:offset_end] - - def unpack_next_int(self, offset: int) -> int: - """Sugar syntax for unpacking a little-endian UINT at offset.""" - return self.unpack_val(self.slice(offset, 4)) - - def unpack_val(self, data: bytes) -> int: - """Sugar syntax for unpacking a little-endian unsigned integer.""" - return unpack("<I", data)[0] - - def bytes_to_ascii(self, data: bytes) -> str: - """Decode bytes into ASCII.""" - return data.rstrip(b"\x00").decode("ascii") - - def clear_ftpr_data(self, start: int, end: int) -> None: - """Replace values in range with 0xFF.""" - empty_data = bytes() - - for i in range(0, end - start): - empty_data += b"\xff" - self.write_ftpr_data(start, empty_data) - - def write_ftpr_data(self, start: int, data: bytes) -> None: - """Replace data in FTPR starting at a given offset.""" - end = len(data) + start - - new_partition = self.ftpr[:start] - new_partition += data - - if end != FTPR_END: - new_partition += self.ftpr[end:] - - self.ftpr = new_partition - - ###################################################################### - # FTPR cleanig/checking functions - ###################################################################### - def get_chunks_offsets(self, llut: bytes): - """Calculate Chunk offsets from LLUT.""" - chunk_count = self.unpack_val(llut[0x04:0x08]) - huffman_stream_end = sum(unpack("<II", llut[0x10:0x18])) - nonzero_offsets = [huffman_stream_end] - offsets = [] - - for i in range(0, chunk_count): - llut_start = 0x40 + (i * 4) - llut_end = 0x44 + (i * 4) - - chunk = llut[llut_start:llut_end] - offset = 0 - - if chunk[3] != 0x80: - offset = self.unpack_val(chunk[0:3] + b"\x00") - - offsets.append([offset, 0]) - - if offset != 0: - nonzero_offsets.append(offset) - - nonzero_offsets.sort() - - for i in offsets: - if i[0] != 0: - i[1] = nonzero_offsets[nonzero_offsets.index(i[0]) + 1] - - return offsets - - def relocate_partition(self) -> int: - """Relocate partition.""" - new_offset = MINIFIED_FTPR_OFFSET - name = self.bytes_to_ascii(self.slice(PARTITION_HEADER_OFFSET, 4)) - - old_offset, partition_size = unpack( - "<II", self.slice(PARTITION_HEADER_OFFSET + 0x8, 0x8) - ) - - llut_start = 0 - for mod_header in self.mod_headers: - if (self.unpack_val(mod_header[0x50:0x54]) >> 4) & 7 == 0x01: - llut_start = self.unpack_val(mod_header[0x38:0x3C]) - llut_start += old_offset - break - - if self.mod_headers and llut_start != 0: - # Bytes 0x9:0xb of the LLUT (bytes 0x1:0x3 of the AddrBase) are - # added to the SpiBase (bytes 0xc:0x10 of the LLUT) to compute the - # final start of the LLUT. Since AddrBase is not modifiable, we can - # act only on SpiBase and here we compute the minimum allowed - # new_offset. - llut_start_corr = unpack("<H", self.slice(llut_start + 0x9, 2))[0] - new_offset = max( - new_offset, llut_start_corr - llut_start - 0x40 + old_offset - ) - new_offset = ((new_offset + 0x1F) // 0x20) * 0x20 - offset_diff = new_offset - old_offset - - print( - "Relocating {} from {:#x} - {:#x} to {:#x} - {:#x}...".format( - name, - old_offset, - old_offset + partition_size, - new_offset, - new_offset + partition_size, - ) - ) - - print(" Adjusting FPT entry...") - self.write_ftpr_data( - PARTITION_HEADER_OFFSET + 0x08, - pack("<I", new_offset), - ) - - if self.mod_headers: - if llut_start != 0: - if self.slice(llut_start, 4) == b"LLUT": - print(" Adjusting LUT start offset...") - llut_offset = pack( - "<I", llut_start + offset_diff + 0x40 - llut_start_corr - ) - self.write_ftpr_data(llut_start + 0x0C, llut_offset) - - print(" Adjusting Huffman start offset...") - old_huff_offset = self.unpack_next_int(llut_start + 0x14) - ftpr_offset_diff = MINIFIED_FTPR_OFFSET - ORIG_FTPR_OFFSET - self.write_ftpr_data( - llut_start + 0x14, - pack("<I", old_huff_offset + ftpr_offset_diff), - ) - - print(" Adjusting chunks offsets...") - chunk_count = self.unpack_next_int(llut_start + 0x4) - offset = llut_start + 0x40 - offset_end = chunk_count * 4 - chunks = bytearray(self.slice(offset, offset_end)) - - for i in range(0, offset_end, 4): - i_plus_3 = i + 3 - - if chunks[i_plus_3] != 0x80: - chunks[i:i_plus_3] = pack( - "<I", - self.unpack_val(chunks[i:i_plus_3] + b"\x00") - + (MINIFIED_FTPR_OFFSET - ORIG_FTPR_OFFSET), - )[0:3] - self.write_ftpr_data(offset, bytes(chunks)) - else: - sys.exit("Huffman modules present but no LLUT found!") - else: - print(" No Huffman modules found") - - print(" Moving data...") - partition_size = min(partition_size, FTPR_END - old_offset) - - if ( - old_offset + partition_size <= FTPR_END - and new_offset + partition_size <= FTPR_END - ): - for i in range(0, partition_size, 4096): - block_length = min(partition_size - i, 4096) - block = self.slice(old_offset + i, block_length) - self.clear_ftpr_data(old_offset + i, len(block)) - - self.write_ftpr_data(new_offset + i, block) - else: - raise OutOfRegionException() - - return new_offset - - def remove_modules(self) -> int: - """Remove modules.""" - unremovable_huff_chunks = [] - chunks_offsets = [] - base = 0 - chunk_size = 0 - end_addr = 0 - - for mod_header in self.mod_headers: - name = self.bytes_to_ascii(mod_header[0x04:0x14]) - offset = self.unpack_val(mod_header[0x38:0x3C]) - size = self.unpack_val(mod_header[0x40:0x44]) - flags = self.unpack_val(mod_header[0x50:0x54]) - comp_type = (flags >> 4) & 7 - comp_type_name = self.COMPRESSION_TYPE_NAME[comp_type] - - print(" {:<16} ({:<7}, ".format(name, comp_type_name), end="") - - # If compresion type uncompressed or LZMA - if comp_type == 0x00 or comp_type == 0x02: - offset_end = offset + size - range_msg = "0x{:06x} - 0x{:06x} ): " - print(range_msg.format(offset, offset_end), end="") - - if name in self.UNREMOVABLE_MODULES: - end_addr = max(end_addr, offset + size) - print("NOT removed, essential") - else: - offset_end = min(offset + size, FTPR_END) - self.clear_ftpr_data(offset, offset_end) - print("removed") - - # Else if compression type huffman - elif comp_type == 0x01: - if not chunks_offsets: - # Check if Local Look Up Table (LLUT) is present - if self.slice(offset, 4) == b"LLUT": - llut = self.slice(offset, 0x40) - - chunk_count = self.unpack_val(llut[0x4:0x8]) - base = self.unpack_val(llut[0x8:0xC]) + 0x10000000 - chunk_size = self.unpack_val(llut[0x30:0x34]) - - llut = self.slice(offset, (chunk_count * 4) + 0x40) - - # calculate offsets of chunks from LLUT - chunks_offsets = self.get_chunks_offsets(llut) - else: - no_llut_msg = "Huffman modules found," - no_llut_msg += "but LLUT is not present." - sys.exit(no_llut_msg) - - module_base = self.unpack_val(mod_header[0x34:0x38]) - module_size = self.unpack_val(mod_header[0x3C:0x40]) - first_chunk_num = (module_base - base) // chunk_size - last_chunk_num = first_chunk_num + module_size // chunk_size - huff_size = 0 - - chunk_length = last_chunk_num + 1 - for chunk in chunks_offsets[first_chunk_num:chunk_length]: - huff_size += chunk[1] - chunk[0] - - size_in_kiB = "~" + str(int(round(huff_size / 1024))) + " KiB" - print( - "fragmented data, {:<9}): ".format(size_in_kiB), - end="", - ) - - # Check if module is in the unremovable list - if name in self.UNREMOVABLE_MODULES: - print("NOT removed, essential") - - # add to list of unremovable chunks - for x in chunks_offsets[first_chunk_num:chunk_length]: - if x[0] != 0: - unremovable_huff_chunks.append(x) - else: - print("removed") - - # Else unknown compression type - else: - unkwn_comp_msg = " 0x{:06x} - 0x{:06x}): " - unkwn_comp_msg += "unknown compression, skipping" - print(unkwn_comp_msg.format(offset, offset + size), end="") - - if chunks_offsets: - removable_huff_chunks = [] - - for chunk in chunks_offsets: - # if chunk is not in a unremovable chunk, it must be removable - if all( - not ( - unremovable_chk[0] <= chunk[0] < unremovable_chk[1] - or unremovable_chk[0] < chunk[1] <= unremovable_chk[1] - ) - for unremovable_chk in unremovable_huff_chunks - ): - removable_huff_chunks.append(chunk) - - for removable_chunk in removable_huff_chunks: - if removable_chunk[1] > removable_chunk[0]: - chunk_start = removable_chunk[0] - ORIG_FTPR_OFFSET - chunk_end = removable_chunk[1] - ORIG_FTPR_OFFSET - self.clear_ftpr_data(chunk_start, chunk_end) - - end_addr = max( - end_addr, max(unremovable_huff_chunks, key=lambda x: x[1])[1] - ) - end_addr -= ORIG_FTPR_OFFSET - - return end_addr - - def find_mod_header_size(self) -> None: - """Find module header size.""" - self.mod_header_size = 0 - data = self.slice(0x290, 0x84) - - # check header size - if data[0x0:0x4] == b"$MME": - if data[0x60:0x64] == b"$MME" or self.num_modules == 1: - self.mod_header_size = 0x60 - elif data[0x80:0x84] == b"$MME": - self.mod_header_size = 0x80 - - def find_mod_headers(self) -> None: - """Find module headers.""" - data = self.slice(0x290, self.mod_header_size * self.num_modules) - - for i in range(0, self.num_modules): - header_start = i * self.mod_header_size - header_end = (i + 1) * self.mod_header_size - self.mod_headers.append(data[header_start:header_end]) - - def resize_partition(self, end_addr: int) -> None: - """Resize partition.""" - spared_blocks = 4 - if end_addr > 0: - end_addr = (end_addr // 0x1000 + 1) * 0x1000 - end_addr += spared_blocks * 0x1000 - - # partition header not added yet - # remove trailing data the same size as the header. - end_addr -= MINIFIED_FTPR_OFFSET - - me_size_msg = "The ME minimum size should be {0} " - me_size_msg += "bytes ({0:#x} bytes)" - print(me_size_msg.format(end_addr)) - print("Truncating file at {:#x}...".format(end_addr)) - self.ftpr = self.ftpr[:end_addr] - - def check_and_clean_ftpr(self) -> None: - """Check and clean FTPR (factory partition).""" - self.num_modules = self.unpack_next_int(0x20) - self.find_mod_header_size() - - if self.mod_header_size != 0: - self.find_mod_headers() - - # ensure all of the headers begin with b'$MME' - if all(hdr.startswith(b"$MME") for hdr in self.mod_headers): - end_addr = self.remove_modules() - new_offset = self.relocate_partition() - end_addr += new_offset - - self.resize_partition(end_addr) - - # flip bit - # XXX: I have no idea why this works and passes RSA signiture - self.write_ftpr_data(0x39, b"\x00") - else: - sys.exit( - "Found less modules than expected in the FTPR " - "partition; skipping modules removal and exiting." - ) - else: - sys.exit( - "Can't find the module header size; skipping modules" - "removal and exiting." - ) - - -########################################################################## - - -def check_partition_signature(f, offset) -> bool: - """check_partition_signature copied/shamelessly stolen from me_cleaner.""" - f.seek(offset) - header = f.read(0x80) - modulus = int(binascii.hexlify(f.read(0x100)[::-1]), 16) - public_exponent = unpack("<I", f.read(4))[0] - signature = int(binascii.hexlify(f.read(0x100)[::-1]), 16) - - header_len = unpack("<I", header[0x4:0x8])[0] * 4 - manifest_len = unpack("<I", header[0x18:0x1C])[0] * 4 - f.seek(offset + header_len) - - sha256 = hashlib.sha256() - sha256.update(header) - tmp = f.read(manifest_len - header_len) - sha256.update(tmp) - - decrypted_sig = pow(signature, public_exponent, modulus) - return "{:#x}".format(decrypted_sig).endswith(sha256.hexdigest()) # FIXME - - -########################################################################## - - -def generate_me_blob(input_file: str, output_file: str) -> None: - """Generate ME blob.""" - print("Starting ME 7.x Update parser.") - - orig_f = open(input_file, "rb") - cleaned_ftpr = clean_ftpr(orig_f.read(FTPR_END)) - orig_f.close() - - fo = open(output_file, "wb") - fo.write(generateHeader()) - fo.write(generateFtpPartition()) - fo.write(cleaned_ftpr.ftpr) - fo.close() - - -def verify_output(output_file: str) -> None: - """Verify Generated ME file.""" - file_verifiy = open(output_file, "rb") - - if check_partition_signature(file_verifiy, MINIFIED_FTPR_OFFSET): - print(output_file + " is VALID") - file_verifiy.close() - else: - print(output_file + " is INVALID!!") - file_verifiy.close() - sys.exit("The FTPR partition signature is not valid.") - - -if __name__ == "__main__": - parser = argparse.ArgumentParser( - description="Tool to remove as much code " - "as possible from Intel ME/TXE 7.x firmware " - "update and create paratition for a flashable ME parition." - ) - - -parser.add_argument("file", help="ME/TXE image or full dump") -parser.add_argument( - "-O", - "--output", - metavar="output_file", - help="save " - "save file name other than the default '" + DEFAULT_OUTPUT_FILE_NAME + "'", -) - -args = parser.parse_args() - -output_file_name = DEFAULT_OUTPUT_FILE_NAME if not args.output else args.output - -# Check if output file exists, ask to overwrite or exit -if os.path.isfile(output_file_name): - input_msg = output_file_name - input_msg += " exists. Do you want to overwrite? [y/N]: " - if not str(input(input_msg)).lower().startswith("y"): - sys.exit("Not overwriting file. Exiting.") - -generate_me_blob(args.file, output_file_name) -verify_output(output_file_name) diff --git a/resources/blobs/sources b/resources/blobs/sources deleted file mode 100644 index 1818c66d..00000000 --- a/resources/blobs/sources +++ /dev/null @@ -1,76 +0,0 @@ -# This file holds the download sources for various intel blobs -# board shortnames are listed and enclosed by '{}' followed by an opening -# and closing '{}' for all blobs available for the board. -# The board shortname must be the name of the board minus the trailing rom size. -# If you want to make additions, try to add a backup url for download links and -# list hashes as sha1 sums. - -{x230 x230t x230i x230edp t430 t530 w530}{ - DL_hash 039c89c6d44ae11ae2510cbd5fed756e97ed9a31 - DL_url https://download.lenovo.com/pccbbs/mobiles/g1rg24ww.exe - DL_url_bkup https://web.archive.org/web/20210706183911/https://download.lenovo.com/pccbbs/mobiles/g1rg24ww.exe -} - -{x220 x220t t420 t520 t420s}{ - DL_hash fa0f96c8f36646492fb8c57ad3296bf5f647d9c5 - DL_url https://download.lenovo.com/ibmdl/pub/pc/pccbbs/mobiles/83rf46ww.exe - DL_url_bkup https://web.archive.org/web/20220202201637/https://download.lenovo.com/ibmdl/pub/pc/pccbbs/mobiles/83rf46ww.exe -} - -{t440pmrc w541mrc t440plibremrc w541}{ - DL_hash b2f2a1baa1f0c8139e46b0d3e206386ff197bed5 - DL_url https://download.lenovo.com/pccbbs/mobiles/glrg22ww.exe - DL_url_bkup https://web.archive.org/web/20211120031520/https://download.lenovo.com/pccbbs/mobiles/glrg22ww.exe -} - -{hp8200sff}{ - DL_hash c59e693effc1862c38cc4caa15be0a6a92557e0b - DL_url https://ftp.ext.hp.com/pub/softpaq/sp96001-96500/sp96026.exe - DL_url_bkup https://web.archive.org/web/20220708171920/https://ftp.ext.hp.com/pub/softpaq/sp96001-96500/sp96026.exe -} - -{hp8300usdt}{ - DL_hash 039c89c6d44ae11ae2510cbd5fed756e97ed9a31 - DL_url https://download.lenovo.com/pccbbs/mobiles/g1rg24ww.exe - DL_url_bkup https://web.archive.org/web/20210706183911/https://download.lenovo.com/pccbbs/mobiles/g1rg24ww.exe -} - -{hp2560p}{ - DL_hash fa0f96c8f36646492fb8c57ad3296bf5f647d9c5 - DL_url https://download.lenovo.com/ibmdl/pub/pc/pccbbs/mobiles/83rf46ww.exe - DL_url_bkup https://web.archive.org/web/20220202201637/https://download.lenovo.com/ibmdl/pub/pc/pccbbs/mobiles/83rf46ww.exe - - EC_hash c1b1fb0a525cf90459bf024f407e302314bd981b - EC_url https://ftp.hp.com/pub/softpaq/sp85501-86000/sp85526.exe - EC_url_bkup https://web.archive.org/web/20230416125725/https://ftp.hp.com/pub/softpaq/sp85501-86000/sp85526.exe -} - -{hp2570p}{ - DL_hash 039c89c6d44ae11ae2510cbd5fed756e97ed9a31 - DL_url https://download.lenovo.com/pccbbs/mobiles/g1rg24ww.exe - DL_url_bkup https://web.archive.org/web/20210706183911/https://download.lenovo.com/pccbbs/mobiles/g1rg24ww.exe - - EC_hash a896ef72799e8abd4d0601ec415a2113b2a7f240 - EC_url https://ftp.hp.com/pub/softpaq/sp96001-96500/sp96085.exe - EC_url_bkup https://web.archive.org/web/20230610174558/https://ftp.hp.com/pub/softpaq/sp96001-96500/sp96085.exe -} - -{hp9470m}{ - DL_hash 039c89c6d44ae11ae2510cbd5fed756e97ed9a31 - DL_url https://download.lenovo.com/pccbbs/mobiles/g1rg24ww.exe - DL_url_bkup https://web.archive.org/web/20210706183911/https://download.lenovo.com/pccbbs/mobiles/g1rg24ww.exe - - EC_hash 1a03e985552060a9dfe7c40b5ea97ecfb2794583 - EC_url https://ftp.hp.com/pub/softpaq/sp96001-96500/sp96090.exe - EC_url_bkup http://web.archive.org/web/20220504072602/https://ftp.ext.hp.com/pub/softpaq/sp96001-96500/sp96090.exe -} - -# nvidia vga option rom for dgpu models of Dell Latitude E6400 -# for downloading the nvidia rom to pciroms/pci0x10de,0x06eb.rom -{e6400nvidia}{ - E6400_VGA_DL_hash a24ed919e80287b281e407d525af31f307746250 - E6400_VGA_DL_url https://dl.dell.com/FOLDER01530530M/1/E6400A34.exe - E6400_VGA_DL_url_bkup https://web.archive.org/web/20230506014903/https://dl.dell.com/FOLDER01530530M/1/E6400A34.exe - E6400_VGA_offset 274451 - E6400_VGA_romname mod_21.bin -} |