Repository navigation
Expand file tree
/
Copy pathpack_kernelcache.py
More file actions
93 lines (77 loc) · 3.24 KB
/
Copy pathpack_kernelcache.py
File metadata and controls
93 lines (77 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
pack_kernelcache.py — упаковка kernelcache.raw в IMG4 с оптимальным сжатием.
Пробует LZFSE (лучшее сжатие), потом LZSS (совместимость).
"""
import sys
from pathlib import Path
try:
from pyimg4 import Compression, IMG4, IM4M, IM4P, PayloadProperty
except ImportError:
print("ERROR: pyimg4 не установлен. pip3 install pyimg4", file=sys.stderr)
sys.exit(1)
def try_compress(payload, method_name, method):
try:
payload.compress(method)
return True
except Exception as e:
print(f" {method_name} failed: {e}", file=sys.stderr)
return False
def main():
if len(sys.argv) != 5:
print(__doc__, file=sys.stderr)
sys.exit(1)
raw_path, out_path, orig_path, im4m_path = map(Path, sys.argv[1:])
raw_data = raw_path.read_bytes()
original = IM4P(orig_path.read_bytes())
# Проверяем, какой compression был в оригинале
orig_comp = None
if original.properties:
for prop in original.properties:
fc = prop.fourcc.decode() if isinstance(prop.fourcc, bytes) else prop.fourcc
if fc in ('lzss', 'lzfse', 'lz4', 'lzbitmap'):
orig_comp = fc
print(f" оригинал compression: {fc}")
break
print(f" читаю raw: {raw_path} ({len(raw_data):,} байт)")
# Пробуем в порядке: LZFSE → LZSS → LZ4
for method_name, method in [
('LZFSE', Compression.LZFSE),
('LZSS', Compression.LZSS),
('LZ4', getattr(Compression, 'LZ4', None)),
]:
if method is None:
continue
image = IM4P(fourcc="rkrn",
description=original.description,
payload=raw_data)
if original.properties:
for prop in original.properties:
image.add_property(PayloadProperty(fourcc=prop.fourcc,
value=prop.value))
print(f" пробую {method_name}...")
if not try_compress(image.payload, method_name, method):
continue
im4m = IM4M(im4m_path.read_bytes())
img4 = IMG4(im4p=image, im4m=im4m)
out_data = img4.output()
# Если результат заметно меньше 30 MB — принимаем
if len(out_data) < 30_000_000:
out_path.write_bytes(out_data)
pct = len(out_data) * 100 // len(raw_data)
print(f" IMG4 ({method_name}): {len(out_data):,} байт ({pct}% от raw)")
return 0
else:
print(f" {method_name} дал {len(out_data):,} — пробую следующий")
# Fallback без сжатия
print(f" ⚠️ ни один метод не дал хорошего сжатия — пакуем как есть",
file=sys.stderr)
image = IM4P(fourcc="rkrn",
description=original.description,
payload=raw_data)
im4m = IM4M(im4m_path.read_bytes())
out_path.write_bytes(IMG4(im4p=image, im4m=im4m).output())
return 0
if __name__ == '__main__':
sys.exit(main())