diff --git a/app/src/main/java/org/akuatech/ksupatcher/viewmodel/MainViewModel.kt b/app/src/main/java/org/akuatech/ksupatcher/viewmodel/MainViewModel.kt index e0b471f..a82cae7 100644 --- a/app/src/main/java/org/akuatech/ksupatcher/viewmodel/MainViewModel.kt +++ b/app/src/main/java/org/akuatech/ksupatcher/viewmodel/MainViewModel.kt @@ -301,6 +301,7 @@ class MainViewModel( val workDir = getWorkDir() val boot = _state.value.patchState.bootImagePath val kmi = _state.value.patchState.kmi + val bootName = _state.value.patchState.bootImageName if (boot.isNullOrBlank()) { _state.update { @@ -310,7 +311,25 @@ class MainViewModel( } viewModelScope.launch { - _state.update { it.copy(patchState = it.patchState.copy(isPatching = true, status = "Downloading binaries...")) } + _state.update { it.copy(patchState = it.patchState.copy(isPatching = true, status = "Checking device requirements...")) } + + if (bootName != null && bootName.contains("boot", ignoreCase = true) && !bootName.contains("init", ignoreCase = true)) { + if (hasInitBoot()) { + val msg = "Bail out: This device uses an init_boot partition. Patching a regular boot image will cause ksud to incorrectly create a ramdisk. Please patch init_boot.img instead." + publishStreamingLog(msg, updatePatch = true) + _state.update { + it.copy( + patchState = it.patchState.copy( + isPatching = false, + status = "Requires init_boot.img" + ) + ) + } + return@launch + } + } + + _state.update { it.copy(patchState = it.patchState.copy(status = "Downloading binaries...")) } val prepare = ensureBinaries() if (prepare.isFailure) { _state.update { @@ -1010,6 +1029,29 @@ class MainViewModel( } } + private suspend fun hasInitBoot(): Boolean { + return withContext(Dispatchers.IO) { + try { + val getpropProc = ProcessBuilder("getprop").start() + val props = getpropProc.inputStream.bufferedReader().use { it.readText() } + if (props.contains("init_boot", ignoreCase = true)) { // ro.boot.init_boot_device or ro.boot.init_boot_cmdline + return@withContext true + } + + val release = android.system.Os.uname().release + val versionParts = release.substringBefore("-").split(".") + val major = versionParts.getOrNull(0)?.toIntOrNull() ?: 0 + val minor = versionParts.getOrNull(1)?.toIntOrNull() ?: 0 + if (major > 5 || (major == 5 && minor >= 15)) { + return@withContext true // >= 5.15 kernels have init_boot + } + } catch (e: Throwable) { + // Ignore + } + false + } + } + private companion object { val httpClient = okhttp3.OkHttpClient() const val MAX_LOG_CHARS = 64_000