@@ -21,9 +21,7 @@ def __init__(self, context):
2121 self .bin_dir = Path ("bin" ).resolve ()
2222
2323 if not self .ctx .tools .magiskboot .exists ():
24- self .logger .error (
25- f"magiskboot binary not found at { self .ctx .tools .magiskboot } "
26- )
24+ self .logger .error (f"magiskboot binary not found at { self .ctx .tools .magiskboot } " )
2725 return
2826
2927 self .assets_dir = self .bin_dir .parent / "assets"
@@ -39,9 +37,7 @@ def __init__(self, context):
3937
4038 # Make these values configurable via device config
4139 if hasattr (self .ctx , "device_config" ) and self .ctx .device_config :
42- self .repo_owner = self .ctx .device_config .get (
43- "ksu_repo_owner" , self .repo_owner
44- )
40+ self .repo_owner = self .ctx .device_config .get ("ksu_repo_owner" , self .repo_owner )
4541 self .repo_name = self .ctx .device_config .get ("ksu_repo_name" , self .repo_name )
4642 self .ksu_config_url_template = self .ctx .device_config .get (
4743 "ksu_gh_api_url_template" ,
@@ -62,15 +58,8 @@ def run(self):
6258 kmi_version = self ._get_kmi_version ()
6359 if kmi_version :
6460 self .logger .info (f"Detected KMI Version: { kmi_version } " )
65- if kmi_version == "android16-6.12" :
66- self .logger .info (
67- "KMI android16-6.12 detected. Skipping vbmeta patching and modifying vendor_boot fstab instead."
68- )
69- self ._patch_vendor_boot_fstab ()
70- else :
71- self ._patch_vbmeta ()
72- else :
73- self ._patch_vbmeta ()
61+
62+ self ._patch_vbmeta ()
7463
7564 if getattr (self .ctx , "enable_ksu" , False ):
7665 self ._patch_ksu (kmi_version )
@@ -94,195 +83,33 @@ def _get_kmi_version(self) -> Optional[str]:
9483
9584 return self ._analyze_kmi (analysis_target )
9685
97- def _patch_vendor_boot_fstab (self ):
98- """Modify fstab in vendor_boot to disable AVB for KMI 6.12."""
99- self .logger .info ("Patching vendor_boot fstab..." )
100- vendor_boot = self .ctx .repack_images_dir / "vendor_boot.img"
101- if not vendor_boot .exists ():
102- self .logger .warning ("vendor_boot.img not found, skipping fstab patch." )
103- return
104-
105- with tempfile .TemporaryDirectory (prefix = "vendor_boot_patch_" ) as tmp :
106- tmp_path = Path (tmp )
107- shutil .copy (vendor_boot , tmp_path / "vendor_boot.img" )
108-
109- try :
110- self .shell .run (
111- [str (self .ctx .tools .magiskboot ), "unpack" , "vendor_boot.img" ],
112- cwd = tmp_path ,
113- )
114- except Exception as e :
115- self .logger .error (f"Failed to unpack vendor_boot.img: { e } " )
116- return
117-
118- ramdisk = tmp_path / "ramdisk.cpio"
119- if not ramdisk .exists ():
120- self .logger .error ("ramdisk.cpio not found in vendor_boot" )
121- return
122-
123- # Attempt to decompress the ramdisk explicitly, as 'raw' format in v4 images
124- # might still be compressed in a way magiskboot cpio doesn't auto-detect.
125- try :
126- self .shell .run (
127- [
128- str (self .ctx .tools .magiskboot ),
129- "decompress" ,
130- "ramdisk.cpio" ,
131- "ramdisk.cpio.dec" ,
132- ],
133- cwd = tmp_path ,
134- )
135- if (tmp_path / "ramdisk.cpio.dec" ).exists ():
136- shutil .move (tmp_path / "ramdisk.cpio.dec" , ramdisk )
137- self .logger .info ("Successfully decompressed vendor_boot ramdisk." )
138- except Exception :
139- # If decompression fails, it might actually be raw, so we continue
140- pass
141-
142- # Extract all files to find fstab using system cpio if magiskboot fails
143- extract_dir = tmp_path / "extracted_ramdisk"
144- extract_dir .mkdir (parents = True , exist_ok = True )
145- try :
146- # Try system cpio first as it is often more robust for extraction
147- self .shell .run (
148- f"cpio -id < { ramdisk } " ,
149- cwd = extract_dir ,
150- shell = True
151- )
152- except Exception as e :
153- self .logger .warning (f"System cpio failed, trying magiskboot cpio: { e } " )
154- try :
155- self .shell .run (
156- [str (self .ctx .tools .magiskboot ), "cpio" , "ramdisk.cpio" , "extract" ],
157- cwd = extract_dir ,
158- )
159- except Exception as e2 :
160- self .logger .error (f"Both cpio methods failed: { e2 } " )
161- return
162-
163- fstab_files = list (extract_dir .rglob ("fstab.*" ))
164- if not fstab_files :
165- self .logger .info ("No fstab files found in vendor_boot ramdisk." )
166-
167- patched = False
168- for fstab_path in fstab_files :
169- # Use relative path for entry name in cpio
170- fstab_entry_name = str (fstab_path .relative_to (extract_dir ))
171- self .logger .info (f"Checking { fstab_entry_name } in vendor_boot ramdisk..." )
172-
173- with open (fstab_path , "r" ) as f :
174- content = f .read ()
175-
176- new_content = self ._disable_avb_verify (content )
177-
178- if new_content != content :
179- with open (fstab_path , "w" ) as f :
180- f .write (new_content )
181-
182- # Add back to ramdisk
183- # magiskboot cpio <cpio> 'add MODE ENTRY INFILE'
184- self .shell .run (
185- [
186- str (self .ctx .tools .magiskboot ),
187- "cpio" ,
188- "ramdisk.cpio" ,
189- f"add 0644 { fstab_entry_name } { fstab_path } " ,
190- ],
191- cwd = tmp_path ,
192- )
193- patched = True
194- self .logger .info (f"Successfully patched { fstab_entry_name } in vendor_boot." )
195-
196- # Also patch DTB if it exists
197- dtb_file = tmp_path / "dtb"
198- if dtb_file .exists ():
199- self .logger .info ("Found DTB in vendor_boot, attempting optional fstab patch..." )
200- # Note: magiskboot dtb patch might fail if it doesn't find fstab nodes,
201- # we set check=False to avoid error logs in ShellRunner.
202- try :
203- res = self .shell .run (
204- [str (self .ctx .tools .magiskboot ), "dtb" , "dtb" , "patch" ],
205- cwd = tmp_path ,
206- check = False ,
207- capture_output = True
208- )
209- if res .returncode == 0 :
210- patched = True
211- self .logger .info ("DTB fstab nodes patched successfully." )
212- else :
213- self .logger .info ("No patchable fstab nodes found in DTB, skipping." )
214- except Exception as e :
215- self .logger .debug (f"Optional DTB patch failed: { e } " )
216-
217- if patched :
218- self .logger .info ("Repacking vendor_boot.img..." )
219- # magiskboot repack will automatically compress ramdisk.cpio
220- # based on the format detected in the original vendor_boot.img
221- try :
222- self .shell .run (
223- [str (self .ctx .tools .magiskboot ), "repack" , "vendor_boot.img" ],
224- cwd = tmp_path ,
225- )
226- new_img = tmp_path / "new-boot.img"
227- if new_img .exists ():
228- shutil .move (new_img , vendor_boot )
229- self .logger .info ("vendor_boot.img repacked with patched fstab." )
230- else :
231- self .logger .error ("Failed to repack vendor_boot.img: new-boot.img not found" )
232- except Exception as e :
233- self .logger .error (f"Failed to repack vendor_boot.img: { e } " )
234-
235- def _disable_avb_verify (self , content : str ) -> str :
236- """Port of the shell function disable_avb_verify.
237-
238- Original logic:
239- sed -i "s/,avb_keys=.*avbpubkey//g" $fstab
240- sed -i "s/,avb=vbmeta_system//g" $fstab
241- sed -i "s/,avb=vbmeta_vendor//g" $fstab
242- sed -i "s/,avb=vbmeta//g" $fstab
243- sed -i "s/,avb//g" $fstab
244- """
245- # Remove avb_keys pattern
246- content = re .sub (r",avb_keys=[^, \n]*avbpubkey" , "" , content )
247- # Remove specific avb flags
248- content = re .sub (r",avb=vbmeta_system" , "" , content )
249- # Handle some variations that might exist
250- content = re .sub (r",avb=vbmeta_vendor" , "" , content )
251- content = re .sub (r",avb=vbmeta" , "" , content )
252- content = re .sub (r",avb" , "" , content )
253-
254- return content
255-
25686 def _patch_vbmeta (self ):
257- """Patch vbmeta images to disable AVB."""
258- self .logger .info ("Patching vbmeta images (Disabling AVB)..." )
87+ """Patch vbmeta.img to disable AVB."""
88+ self .logger .info ("Patching vbmeta.img (Disabling AVB)..." )
25989
260- vbmeta_images = list ( self .ctx .target_dir . rglob ( " vbmeta* .img"))
90+ vbmeta_img = self .ctx .target_dir / "repack_images" / " vbmeta.img"
26191
262- if not vbmeta_images :
263- self .logger .warning ("No vbmeta images found in target directory." )
92+ if not vbmeta_img . exists () :
93+ self .logger .warning ("vbmeta.img not found in repack_images directory." )
26494 return
26595
26696 AVB_MAGIC = b"AVB0"
26797 FLAGS_OFFSET = 123
26898 FLAGS_TO_SET = b"\x03 "
26999
270- for img_path in vbmeta_images :
271- try :
272- with open (img_path , "r+b" ) as f :
273- magic = f .read (4 )
274- if magic != AVB_MAGIC :
275- self .logger .warning (
276- f"Skipping { img_path .name } : Invalid AVB Magic"
277- )
278- continue
279-
280- f .seek (FLAGS_OFFSET )
281- f .write (FLAGS_TO_SET )
282- self .logger .info (f"Successfully patched: { img_path .name } " )
100+ try :
101+ with open (vbmeta_img , "r+b" ) as f :
102+ magic = f .read (4 )
103+ if magic != AVB_MAGIC :
104+ self .logger .warning (f"Skipping { vbmeta_img .name } : Invalid AVB Magic" )
105+ return
283106
284- except Exception as e :
285- self .logger .error (f"Failed to patch { img_path .name } : { e } " )
107+ f .seek (FLAGS_OFFSET )
108+ f .write (FLAGS_TO_SET )
109+ self .logger .info (f"Successfully patched: { vbmeta_img .name } " )
110+
111+ except Exception as e :
112+ self .logger .error (f"Failed to patch { vbmeta_img .name } : { e } " )
286113
287114 def _patch_ksu (self , kmi_version : Optional [str ] = None ):
288115 """Patch KernelSU into boot image."""
@@ -298,19 +125,15 @@ def _patch_ksu(self, kmi_version: Optional[str] = None):
298125 patch_target = target_boot
299126
300127 if not patch_target :
301- self .logger .warning (
302- "Neither init_boot.img nor boot.img found, skipping KSU patch."
303- )
128+ self .logger .warning ("Neither init_boot.img nor boot.img found, skipping KSU patch." )
304129 return
305130
306131 if not self .ctx .tools .magiskboot .exists ():
307132 self .logger .error ("magiskboot binary not found!" )
308133 return
309134
310135 if not kmi_version :
311- kmi_version = self ._analyze_kmi (
312- target_boot if target_boot .exists () else patch_target
313- )
136+ kmi_version = self ._analyze_kmi (target_boot if target_boot .exists () else patch_target )
314137
315138 if not kmi_version :
316139 self .logger .error ("Failed to determine KMI version." )
@@ -331,9 +154,7 @@ def _analyze_kmi(self, boot_img: Path) -> Optional[str]:
331154 shutil .copy (boot_img , tmp_path / "boot.img" )
332155
333156 try :
334- self .shell .run (
335- [str (self .ctx .tools .magiskboot ), "unpack" , "boot.img" ], cwd = tmp_path
336- )
157+ self .shell .run ([str (self .ctx .tools .magiskboot ), "unpack" , "boot.img" ], cwd = tmp_path )
337158 except Exception as e :
338159 self .logger .debug (f"Magiskboot unpack failed: { e } " )
339160 return None
@@ -378,15 +199,11 @@ def _prepare_ksu_assets(self, kmi_version):
378199 ko_file_expected = self .ctx .device_config .get (
379200 "ksu_module_filename" , f"{ kmi_version } _kernelsu.ko"
380201 )
381- init_file_expected = self .ctx .device_config .get (
382- "ksu_init_filename" , "ksuinit"
383- )
202+ init_file_expected = self .ctx .device_config .get ("ksu_init_filename" , "ksuinit" )
384203 ko_asset_name_pattern = self .ctx .device_config .get (
385204 "ksu_module_asset_pattern" , f"{ kmi_version } _kernelsu.ko"
386205 )
387- init_asset_name = self .ctx .device_config .get (
388- "ksu_init_asset_name" , "ksuinit"
389- )
206+ init_asset_name = self .ctx .device_config .get ("ksu_init_asset_name" , "ksuinit" )
390207 else :
391208 ko_file_expected = f"{ kmi_version } _kernelsu.ko"
392209 init_file_expected = "ksuinit"
@@ -451,9 +268,7 @@ def _apply_ksu_patch(self, target_img, kmi_version):
451268 tmp_path = Path (tmp )
452269 shutil .copy (target_img , tmp_path / "boot.img" )
453270
454- self .shell .run (
455- [str (self .ctx .tools .magiskboot ), "unpack" , "boot.img" ], cwd = tmp_path
456- )
271+ self .shell .run ([str (self .ctx .tools .magiskboot ), "unpack" , "boot.img" ], cwd = tmp_path )
457272
458273 ramdisk = tmp_path / "ramdisk.cpio"
459274 if not ramdisk .exists ():
@@ -492,15 +307,11 @@ def _apply_ksu_patch(self, target_img, kmi_version):
492307 cwd = tmp_path ,
493308 )
494309
495- self .shell .run (
496- [str (self .ctx .tools .magiskboot ), "repack" , "boot.img" ], cwd = tmp_path
497- )
310+ self .shell .run ([str (self .ctx .tools .magiskboot ), "repack" , "boot.img" ], cwd = tmp_path )
498311
499312 new_img = tmp_path / "new-boot.img"
500313 if new_img .exists ():
501314 shutil .move (new_img , target_img )
502- self .logger .info (
503- f"KernelSU injected successfully into { target_img .name } ."
504- )
315+ self .logger .info (f"KernelSU injected successfully into { target_img .name } ." )
505316 else :
506317 self .logger .error (f"Failed to repack { target_img .name } " )
0 commit comments