1+ #!/usr/bin/env python3
2+ import argparse
3+ import sys
4+ import os
5+
6+ CHIP_SIZE = 16 * 1024 * 1024 # 16MB
7+
8+ def main ():
9+ parser = argparse .ArgumentParser (
10+ description = 'Extract BIOS from Synology PAT file and prepare for flashing'
11+ )
12+ parser .add_argument ('-i' , '--input' , required = True ,
13+ help = 'Input bios.ROM from PAT file' )
14+ parser .add_argument ('-o' , '--output' , default = 'flash.bin' ,
15+ help = 'Output file (16MB, default: flash.bin)' )
16+ args = parser .parse_args ()
17+
18+ # Read input file
19+ try :
20+ with open (args .input , 'rb' ) as f :
21+ data = f .read ()
22+ except IOError as e :
23+ print (f"Error reading file: { e } " )
24+ sys .exit (1 )
25+
26+ print (f"Input: { len (data )} bytes ({ len (data )/ (1024 * 1024 ):.2f} MB)\n " )
27+
28+ # Find header signature
29+ header_sig = b'$_IFLASH_BIOSIMG'
30+ header_idx = data .find (header_sig )
31+ if header_idx == - 1 :
32+ print ("Error: $_IFLASH_BIOSIMG signature not found" )
33+ sys .exit (1 )
34+ print (f"Found header at: 0x{ header_idx :X} " )
35+
36+ header_idx += len (header_sig )+ 8
37+
38+ # Find footer signature
39+ footer_sig = b'$_IFLASH_INI_IMG'
40+ footer_idx = data .find (footer_sig )
41+ if footer_idx == - 1 :
42+ print ("Error: $_IFLASH_INI_IMG signature not found" )
43+ sys .exit (1 )
44+ print (f"Found footer at: 0x{ footer_idx :X} " )
45+
46+ # Extract BIOS data between signatures
47+ bios_data = data [header_idx :footer_idx ]
48+ bios_size = len (bios_data )
49+ print (f"\n Extracted BIOS: { bios_size } bytes ({ bios_size / (1024 * 1024 ):.2f} MB)" )
50+
51+ # Calculate padding
52+ pad_size = CHIP_SIZE - bios_size
53+ if pad_size < 0 :
54+ print (f"Error: BIOS too large ({ bios_size } > { CHIP_SIZE } )" )
55+ sys .exit (1 )
56+ print (f"Padding needed: { pad_size } bytes ({ pad_size / (1024 * 1024 ):.2f} MB)" )
57+
58+ # Show structure
59+ print (f"\n Structure:" )
60+ print (f" 0x{ 0 :08X} - 0x{ bios_size - 1 :08X} : BIOS code" )
61+ print (f" 0x{ bios_size :08X} - 0x{ CHIP_SIZE - 1 :08X} : Zero padding" )
62+
63+ # Write output: [BIOS] + [zeros]
64+ try :
65+ with open (args .output , 'wb' ) as f :
66+ # Write BIOS data
67+ f .write (bios_data )
68+
69+ # Write zero padding
70+ f .write (b'\x00 ' * pad_size )
71+ except IOError as e :
72+ print (f"Error writing file: { e } " )
73+ sys .exit (1 )
74+
75+ print (f"\n ✓ Created: { args .output } ({ CHIP_SIZE } bytes)" )
76+ print ("\n Flash with: CH341A + 1.8V adapter" )
77+ print ("IMPORTANT: Leave pins 3(WP) and 7(HOLD) disconnected" )
78+
79+ if __name__ == '__main__' :
80+ main ()
0 commit comments