first version compatible with Windows 10

pull/53/head
cfig 5 years ago
parent 0dbf161ce8
commit b108110dbd
No known key found for this signature in database
GPG Key ID: B104C307F0FDABB7

@ -1,3 +1,7 @@
branches:
only:
- master
- dev
language: java language: java
os: os:
- linux - linux

@ -2,27 +2,18 @@
[![Build Status](https://travis-ci.org/cfig/Android_boot_image_editor.svg?branch=master)](https://travis-ci.org/cfig/Android_boot_image_editor) [![Build Status](https://travis-ci.org/cfig/Android_boot_image_editor.svg?branch=master)](https://travis-ci.org/cfig/Android_boot_image_editor)
[![License](http://img.shields.io/:license-apache-blue.svg?style=flat-square)](http://www.apache.org/licenses/LICENSE-2.0.html) [![License](http://img.shields.io/:license-apache-blue.svg?style=flat-square)](http://www.apache.org/licenses/LICENSE-2.0.html)
A tool for reverse engineering Android ROM images. (working on ![Linux](doc/linux24.png)(Ubuntu 18.04+) and ![Mac](doc/apple24.png)) A tool for reverse engineering Android ROM images.
## Getting Started ## Getting Started
#### Installation #### install required packages
* install required packages
```bash Mac: `brew install lz4 xz`
sudo apt install device-tree-compiler lz4 xz zlib1g-dev
```
* get the tool Linux: `sudo apt install device-tree-compiler lz4 xz zlib1g-dev openjdk-11-jdk`
```bash
git clone https://github.com/cfig/Android_boot_image_editor.git --depth=1
```
or clone it from mirror: Windows: Make sure you have `python3`, `JDK9+` and `openssl` properly installed.
An easy way is to install [Anaconda](https://www.anaconda.com/products/individual#windows) and [Oracle JDK 11](https://www.oracle.com/java/technologies/javase-jdk11-downloads.html), then run the program under anaconda PowerShell.
```bash
git clone https://gitee.com/cfig/Android_boot_image_editor.git --depth=1
```
#### Parsing and packing #### Parsing and packing

@ -63,9 +63,9 @@ class EnvironmentVerifier {
} catch (e: Exception) { } catch (e: Exception) {
log.warn("'dtc' not installed. Please install it manually to analyze DTB files") log.warn("'dtc' not installed. Please install it manually to analyze DTB files")
if (isMacOS) { if (isMacOS) {
log.warn("For Mac OS: \n\n\tbrew install dtc\n") log.warn("For Mac OS: \n\tbrew install dtc\n")
} else { } else if (isLinux) {
log.warn("Like this: \n\n\t$ sudo apt install device-tree-compiler") log.warn("Like this: \n\t$ sudo apt install device-tree-compiler")
} }
return false return false
} }
@ -75,6 +75,12 @@ class EnvironmentVerifier {
val isMacOS: Boolean val isMacOS: Boolean
get() = System.getProperty("os.name").contains("Mac") get() = System.getProperty("os.name").contains("Mac")
val isLinux: Boolean
get() = System.getProperty("os.name").contains("Linux")
val isWindows: Boolean
get() = System.getProperty("os.name").contains("Windows")
private fun getJavaVersion(): Int { private fun getJavaVersion(): Int {
return System.getProperty("java.version").let { version -> return System.getProperty("java.version").let { version ->
if (version.startsWith("1.")) { if (version.startsWith("1.")) {

@ -340,7 +340,7 @@ class Avb {
} }
fun verifyAVBIntegrity(fileName: String, avbtool: String) { fun verifyAVBIntegrity(fileName: String, avbtool: String) {
val cmdline = "$avbtool verify_image --image $fileName" val cmdline = "python $avbtool verify_image --image $fileName"
log.info(cmdline) log.info(cmdline)
try { try {
DefaultExecutor().execute(CommandLine.parse(cmdline)) DefaultExecutor().execute(CommandLine.parse(cmdline))

@ -14,6 +14,8 @@ import org.slf4j.LoggerFactory
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.File import java.io.File
import java.nio.file.Files
import java.nio.file.Paths
import java.io.FileInputStream import java.io.FileInputStream
import java.lang.NumberFormatException import java.lang.NumberFormatException
import java.nio.ByteBuffer import java.nio.ByteBuffer
@ -119,12 +121,16 @@ class Common {
Helper.extractFile(s.srcFile, s.dumpFile, s.offset.toLong(), s.length) Helper.extractFile(s.srcFile, s.dumpFile, s.offset.toLong(), s.length)
when { when {
ZipHelper.isGZ(s.dumpFile) -> { ZipHelper.isGZ(s.dumpFile) -> {
File(s.dumpFile).renameTo(File(s.dumpFile + ".gz")) Files.move(
Paths.get(s.dumpFile), Paths.get(s.dumpFile + ".gz"),
java.nio.file.StandardCopyOption.REPLACE_EXISTING)
ZipHelper.unGnuzipFile(s.dumpFile + ".gz", s.dumpFile) ZipHelper.unGnuzipFile(s.dumpFile + ".gz", s.dumpFile)
} }
ZipHelper.isLZ4(s.dumpFile) -> { ZipHelper.isLZ4(s.dumpFile) -> {
log.info("ramdisk is compressed lz4") log.info("ramdisk is compressed lz4")
File(s.dumpFile).renameTo(File(s.dumpFile + ".lz4")) Files.move(
Paths.get(s.dumpFile), Paths.get(s.dumpFile + ".lz4"),
java.nio.file.StandardCopyOption.REPLACE_EXISTING)
ZipHelper.decompressLZ4Ext(s.dumpFile + ".lz4", s.dumpFile) ZipHelper.decompressLZ4Ext(s.dumpFile + ".lz4", s.dumpFile)
ret = "lz4" ret = "lz4"
} }

@ -10,6 +10,7 @@ import org.apache.commons.exec.CommandLine
import org.apache.commons.exec.DefaultExecutor import org.apache.commons.exec.DefaultExecutor
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.io.File import java.io.File
import cfig.EnvironmentVerifier
class Signer { class Signer {
@OptIn(ExperimentalUnsignedTypes::class) @OptIn(ExperimentalUnsignedTypes::class)
@ -30,7 +31,8 @@ class Signer {
partition_name = bootDesc.partition_name, partition_name = bootDesc.partition_name,
newAvbInfo = newAvbInfo) newAvbInfo = newAvbInfo)
//original signer //original signer
CommandLine.parse("$avbtool add_hash_footer").apply { val cmdPrefix = if (EnvironmentVerifier().isWindows) "python " else ""
CommandLine.parse(cmdPrefix + "$avbtool add_hash_footer").apply {
addArguments("--image ${output}.signed2") addArguments("--image ${output}.signed2")
addArguments("--partition_size ${imageSize}") addArguments("--partition_size ${imageSize}")
addArguments("--salt ${Helper.toHexString(bootDesc.salt)}") addArguments("--salt ${Helper.toHexString(bootDesc.salt)}")

@ -1,6 +1,7 @@
package cfig.bootimg.cpio package cfig.bootimg.cpio
import cfig.helper.Helper import cfig.helper.Helper
import cfig.EnvironmentVerifier
import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream
@ -37,8 +38,12 @@ class AndroidCpio {
} }
} }
} else { //later visit } else { //later visit
log.debug(item.path + " ~ " + root.path) val newOutname = if (EnvironmentVerifier().isWindows) {
val newOutname = item.path.substring(root.path.length + 1) //remove leading slash item.path.substring(root.path.length + 1).replace("\\", "/")
} else {
item.path.substring(root.path.length + 1) //remove leading slash
}
log.debug(item.path + " ~ " + root.path + " => " + newOutname)
val entry = when { val entry = when {
Files.isSymbolicLink(item.toPath()) -> { Files.isSymbolicLink(item.toPath()) -> {
val target = Files.readSymbolicLink(Paths.get(item.path)) val target = Files.readSymbolicLink(Paths.get(item.path))
@ -202,23 +207,35 @@ class AndroidCpio {
when { when {
entry.isSymbolicLink -> { entry.isSymbolicLink -> {
entryInfo.note = ("LNK " + entryInfo.note) entryInfo.note = ("LNK " + entryInfo.note)
Files.createSymbolicLink(Paths.get(outEntryName), Paths.get(String(buffer))) if (EnvironmentVerifier().isWindows) {
File(outEntryName).writeBytes(buffer)
} else {
Files.createSymbolicLink(Paths.get(outEntryName), Paths.get(String(buffer)))
}
} }
entry.isRegularFile -> { entry.isRegularFile -> {
entryInfo.note = ("REG " + entryInfo.note) entryInfo.note = ("REG " + entryInfo.note)
File(outEntryName).writeBytes(buffer) File(outEntryName).writeBytes(buffer)
Files.setPosixFilePermissions( if (EnvironmentVerifier().isWindows) {
Paths.get(outEntryName), //Windows: Posix not supported
Helper.modeToPermissions((entry.mode and 0xfff).toInt()) } else {
) Files.setPosixFilePermissions(
Paths.get(outEntryName),
Helper.modeToPermissions((entry.mode and 0xfff).toInt())
)
}
} }
entry.isDirectory -> { entry.isDirectory -> {
entryInfo.note = ("DIR " + entryInfo.note) entryInfo.note = ("DIR " + entryInfo.note)
File(outEntryName).mkdir() File(outEntryName).mkdir()
Files.setPosixFilePermissions( if (!EnvironmentVerifier().isWindows) {
Paths.get(outEntryName), Files.setPosixFilePermissions(
Helper.modeToPermissions((entry.mode and 0xfff).toInt()) Paths.get(outEntryName),
) Helper.modeToPermissions((entry.mode and 0xfff).toInt())
)
} else {
//Windows
}
} }
else -> throw IllegalArgumentException("??? type unknown") else -> throw IllegalArgumentException("??? type unknown")
} }

@ -404,7 +404,8 @@ data class BootV2(
} }
private fun toCommandLine(): CommandLine { private fun toCommandLine(): CommandLine {
val ret = CommandLine(Helper.prop("mkbootimg")) val ret = CommandLine("python")
ret.addArgument(Helper.prop("mkbootimg"))
ret.addArgument(" --header_version ") ret.addArgument(" --header_version ")
ret.addArgument(info.headerVersion.toString()) ret.addArgument(info.headerVersion.toString())
ret.addArgument(" --base ") ret.addArgument(" --base ")
@ -467,7 +468,8 @@ data class BootV2(
} }
fun sign(): BootV2 { fun sign(): BootV2 {
val avbtool = String.format(Helper.prop("avbtool"), if (Common.parseOsMajor(info.osVersion.toString()) > 10) "v1.2" else "v1.1") //unify with v1.1/v1.2 avbtool
val avbtool = String.format(Helper.prop("avbtool"), "v1.2")
if (info.verify == "VB2.0") { if (info.verify == "VB2.0") {
Signer.signAVB(info.output, this.info.imageSize, avbtool) Signer.signAVB(info.output, this.info.imageSize, avbtool)
log.info("Adding hash_footer with verified-boot 2.0 style") log.info("Adding hash_footer with verified-boot 2.0 style")

@ -204,7 +204,8 @@ data class BootV3(var info: MiscInfo = MiscInfo(),
} }
private fun toCommandLine(): CommandLine { private fun toCommandLine(): CommandLine {
return CommandLine(Helper.prop("mkbootimg")).let { ret -> return CommandLine("python").let { ret ->
ret.addArgument(Helper.prop("mkbootimg"))
ret.addArgument("--header_version") ret.addArgument("--header_version")
ret.addArgument(info.headerVersion.toString()) ret.addArgument(info.headerVersion.toString())
if (kernel.size > 0) { if (kernel.size > 0) {

@ -16,6 +16,7 @@ import java.io.FileOutputStream
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
import cfig.bootimg.Common as C import cfig.bootimg.Common as C
import cfig.EnvironmentVerifier
@OptIn(ExperimentalUnsignedTypes::class) @OptIn(ExperimentalUnsignedTypes::class)
data class VendorBoot(var info: MiscInfo = MiscInfo(), data class VendorBoot(var info: MiscInfo = MiscInfo(),
@ -215,17 +216,19 @@ data class VendorBoot(var info: MiscInfo = MiscInfo(),
} }
private fun toCommandLine(): CommandLine { private fun toCommandLine(): CommandLine {
return CommandLine(Helper.prop("mkbootimg")) val cmdPrefix = if (EnvironmentVerifier().isWindows) "python " else ""
.addArgument("--vendor_ramdisk").addArgument(ramdisk.file) return CommandLine.parse(cmdPrefix + Helper.prop("mkbootimg")).apply {
.addArgument("--dtb").addArgument(dtb.file) addArgument("--vendor_ramdisk").addArgument(ramdisk.file)
.addArgument("--vendor_cmdline").addArgument(info.cmdline, false) addArgument("--dtb").addArgument(dtb.file)
.addArgument("--header_version").addArgument(info.headerVersion.toString()) addArgument("--vendor_cmdline").addArgument(info.cmdline, false)
.addArgument("--base").addArgument("0") addArgument("--header_version").addArgument(info.headerVersion.toString())
.addArgument("--tags_offset").addArgument(info.tagsLoadAddr.toString()) addArgument("--base").addArgument("0")
.addArgument("--kernel_offset").addArgument(info.kernelLoadAddr.toString()) addArgument("--tags_offset").addArgument(info.tagsLoadAddr.toString())
.addArgument("--ramdisk_offset").addArgument(ramdisk.loadAddr.toString()) addArgument("--kernel_offset").addArgument(info.kernelLoadAddr.toString())
.addArgument("--dtb_offset").addArgument(dtb.loadAddr.toString()) addArgument("--ramdisk_offset").addArgument(ramdisk.loadAddr.toString())
.addArgument("--pagesize").addArgument(info.pageSize.toString()) addArgument("--dtb_offset").addArgument(dtb.loadAddr.toString())
.addArgument("--vendor_boot") addArgument("--pagesize").addArgument(info.pageSize.toString())
addArgument("--vendor_boot")
}
} }
} }

@ -64,6 +64,7 @@ data class BootloaderMsg(//offset 0, size 2k
this.recovery = info[2] as String this.recovery = info[2] as String
this.stage = info[3] as String this.stage = info[3] as String
this.reserved = info[4] as ByteArray this.reserved = info[4] as ByteArray
fis.close()
} else { } else {
log.info("$miscFile missing") log.info("$miscFile missing")
} }

@ -226,7 +226,10 @@ class ZipHelper {
fun isGZ(compressedFile: String): Boolean { fun isGZ(compressedFile: String): Boolean {
return try { return try {
GZIPInputStream(FileInputStream(compressedFile)).use { } FileInputStream(compressedFile).use { fis ->
GZIPInputStream(fis).use {
}
}
true true
} catch (e: ZipException) { } catch (e: ZipException) {
false false
@ -235,7 +238,10 @@ class ZipHelper {
fun isXZ(compressedFile: String): Boolean { fun isXZ(compressedFile: String): Boolean {
return try { return try {
XZCompressorInputStream(FileInputStream(compressedFile)).use { } FileInputStream(compressedFile).use { fis ->
XZCompressorInputStream(fis).use {
}
}
true true
} catch (e: ZipException) { } catch (e: ZipException) {
false false

@ -20,7 +20,8 @@ class KernelExtractor {
val ret: MutableList<String> = mutableListOf() val ret: MutableList<String> = mutableListOf()
val kernelVersionFile = Helper.prop("kernelVersionFile") val kernelVersionFile = Helper.prop("kernelVersionFile")
val kernelConfigFile = Helper.prop("kernelConfigFile") val kernelConfigFile = Helper.prop("kernelConfigFile")
val cmd = CommandLine.parse(Helper.prop("kernelExtracter")).let { val cmd = CommandLine.parse("python").let {
it.addArgument(Helper.prop("kernelExtracter"))
it.addArgument("--input") it.addArgument("--input")
it.addArgument(fileName) it.addArgument(fileName)
it.addArgument("--output-configs") it.addArgument("--output-configs")

@ -36,8 +36,11 @@ class DtboParser(val workDir: File) : IPackable {
} }
execInDirectory(cmd, this.workDir) execInDirectory(cmd, this.workDir)
val props = Properties() val props = Properties().apply {
props.load(FileInputStream(File(headerPath))) FileInputStream(File(headerPath)).use { fis ->
load(fis)
}
}
if (envv.hasDtc) { if (envv.hasDtc) {
for (i in 0 until Integer.parseInt(props.getProperty("dt_entry_count"))) { for (i in 0 until Integer.parseInt(props.getProperty("dt_entry_count"))) {
val inputDtb = "$dtbPath.$i" val inputDtb = "$dtbPath.$i"
@ -56,8 +59,11 @@ class DtboParser(val workDir: File) : IPackable {
} }
val headerPath = File("${outDir}/dtbo.header").path val headerPath = File("${outDir}/dtbo.header").path
val props = Properties() val props = Properties().apply {
props.load(FileInputStream(File(headerPath))) FileInputStream(File(headerPath)).use { fis ->
load(fis)
}
}
val cmd = CommandLine.parse("$dtboMaker create $fileName.clear").let { val cmd = CommandLine.parse("$dtboMaker create $fileName.clear").let {
it.addArguments("--version=1") it.addArguments("--version=1")
for (i in 0 until Integer.parseInt(props.getProperty("dt_entry_count"))) { for (i in 0 until Integer.parseInt(props.getProperty("dt_entry_count"))) {

@ -11,13 +11,13 @@ import java.io.File
@OptIn(ExperimentalUnsignedTypes::class) @OptIn(ExperimentalUnsignedTypes::class)
class BootloaderMsgTest { class BootloaderMsgTest {
private val log = LoggerFactory.getLogger(BootloaderMsgTest::class.java)
@After @After
fun tearDown() { fun tearDown() {
File(BootloaderMsg.miscFile).deleleIfExists() File(BootloaderMsg.miscFile).deleleIfExists()
} }
private val log = LoggerFactory.getLogger(BootloaderMsgTest::class.java)
@Test @Test
fun writeRebootBootloaderTest() { fun writeRebootBootloaderTest() {
val msg = BootloaderMsg() val msg = BootloaderMsg()

@ -1,12 +1,20 @@
package init package init
import cfig.bootloader_message.BootloaderMsg
import cfig.init.Reboot
import org.junit.Test import org.junit.Test
import org.junit.After
import java.io.File
import java.util.* import java.util.*
import cfig.bootloader_message.BootloaderMsg
import cfig.init.Reboot
import cfig.bootimg.Common.Companion.deleleIfExists
@OptIn(ExperimentalUnsignedTypes::class) @OptIn(ExperimentalUnsignedTypes::class)
class RebootTest { class RebootTest {
@After
fun tearDown() {
File(BootloaderMsg.miscFile).deleleIfExists()
}
@Test @Test
fun testDifferentModes() { fun testDifferentModes() {
Reboot.handlePowerctlMessage("reboot,recovery") Reboot.handlePowerctlMessage("reboot,recovery")

@ -83,9 +83,11 @@ tasks {
if (System.getProperty("os.name").contains("Mac")) { if (System.getProperty("os.name").contains("Mac")) {
unpackTask.dependsOn("aosp:libsparse:simg2img:installReleaseMacos") unpackTask.dependsOn("aosp:libsparse:simg2img:installReleaseMacos")
packTask.dependsOn("aosp:libsparse:img2simg:installReleaseMacos") packTask.dependsOn("aosp:libsparse:img2simg:installReleaseMacos")
} else { } else if (System.getProperty("os.name").contains("Linux")) {
unpackTask.dependsOn("aosp:libsparse:simg2img:installReleaseLinux") unpackTask.dependsOn("aosp:libsparse:simg2img:installReleaseLinux")
packTask.dependsOn("aosp:libsparse:img2simg:installReleaseLinux") packTask.dependsOn("aosp:libsparse:img2simg:installReleaseLinux")
} else {
logger.info("Disable C++ modules on Window$")
} }
} }

@ -64,3 +64,16 @@ place 'ramdisk.img.gz' in directory, delete "root/", program will use it as preb
## cpio ## cpio
decompress cpio with commandline `cpio -idmv -F <file>` decompress cpio with commandline `cpio -idmv -F <file>`
### cpio on windows
* got `java.nio.file.FileSystemException` and says "A required privilege is not held by the client"
```
java.base/java.nio.file.Files.createSymbolicLink(Files.java:1058)
```
Solution:
Avoid using this feature on Windows, create regular file instead.
* File.renameTo() is problematic, use Files.move() instead.
* remember to close File streams to avoid any potential problems

3
gradlew.bat vendored

@ -21,6 +21,9 @@
@rem @rem
@rem ########################################################################## @rem ##########################################################################
@rem set path for lz4
@IF EXIST tools\bin SET PATH=%PATH%;tools\bin
@rem Set local scope for the variables with windows NT shell @rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal if "%OS%"=="Windows_NT" setlocal

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import shutil, os.path, json, subprocess, hashlib, glob import shutil, os.path, json, subprocess, hashlib, glob
import unittest, logging, sys, lzma import unittest, logging, sys, lzma, time
successLogo = """ successLogo = """
+----------------------------------+ +----------------------------------+
@ -24,8 +24,14 @@ def hashFile(fileName):
return hasher.hexdigest() return hasher.hexdigest()
def deleteIfExists(inFile): def deleteIfExists(inFile):
if os.path.isfile(inFile): for i in range(3):
os.remove(inFile) try:
if os.path.isfile(inFile):
os.remove(inFile)
return
except Exception as e:
log.warn("Exception in cleaning up %s" % inFile)
time.sleep(3)
def cleanUp(): def cleanUp():
log.info("clean up ...") log.info("clean up ...")
@ -62,8 +68,12 @@ def verifySingleJson(jsonFile):
decompressXZ(it + ".xz", v) decompressXZ(it + ".xz", v)
else: else:
raise raise
subprocess.check_call("./gradlew unpack", shell = True) if sys.platform == "win32":
subprocess.check_call("./gradlew pack", shell = True) gradleWrapper = "gradlew.bat"
else:
gradleWrapper = "./gradlew"
subprocess.check_call(gradleWrapper + " unpack", shell = True)
subprocess.check_call(gradleWrapper + " pack", shell = True)
for k, v in verifyItems["hash"].items(): for k, v in verifyItems["hash"].items():
log.info("%s : %s" % (k, v)) log.info("%s : %s" % (k, v))
unittest.TestCase().assertEqual(v, hashFile(k)) unittest.TestCase().assertEqual(v, hashFile(k))
@ -81,7 +91,11 @@ def verifySingleDir(inResourceDir, inImageDir):
for pyFile in pyFiles: for pyFile in pyFiles:
cleanUp() cleanUp()
log.warning("calling %s" % pyFile) log.warning("calling %s" % pyFile)
subprocess.check_call(pyFile, shell = True) if sys.platform == "win32":
theCmd = "python " + pyFile
else:
theCmd = pyFile
subprocess.check_call(theCmd, shell = True)
cleanUp() cleanUp()
log.info("Leave %s" % os.path.join(resDir, imgDir)) log.info("Leave %s" % os.path.join(resDir, imgDir))
@ -91,6 +105,14 @@ def decompressXZ(inFile, outFile):
with open(outFile, "wb") as f2: with open(outFile, "wb") as f2:
f2.write(file_content) f2.write(file_content)
def seekedCopy(inFile, outFile, offset):
print(inFile + " -> " + outFile)
with open(inFile, "rb") as reader:
reader.seek(offset)
content = reader.read()
with open(outFile, "wb") as writer:
writer.write(content)
def main(): def main():
# from volunteers # from volunteers
verifySingleDir(resDir, "recovery_image_from_s-trace") verifySingleDir(resDir, "recovery_image_from_s-trace")
@ -102,11 +124,13 @@ def main():
verifySingleDir(resDir, "6.0.0_bullhead_mda89e") verifySingleDir(resDir, "6.0.0_bullhead_mda89e")
# 7.0 special boot # 7.0 special boot
cleanUp() cleanUp()
subprocess.check_call("dd if=%s/7.1.1_volantis_n9f27m/boot.img of=boot.img bs=256 skip=1" % resDir, shell = True) #subprocess.check_call("dd if=%s/7.1.1_volantis_n9f27m/boot.img of=boot.img bs=256 skip=1" % resDir, shell = True)
verifySingleJson("%s/7.1.1_volantis_n9f27m/boot.json" % resDir) seekedCopy(os.path.join(resDir, "7.1.1_volantis_n9f27m", "boot.img"), "boot.img", 256)
verifySingleJson(resDir + "/7.1.1_volantis_n9f27m/boot.json")
# 7.0 special recovery # 7.0 special recovery
cleanUp() cleanUp()
subprocess.check_call("dd if=%s/7.1.1_volantis_n9f27m/recovery.img of=recovery.img bs=256 skip=1" % resDir, shell = True) #subprocess.check_call("dd if=%s/7.1.1_volantis_n9f27m/recovery.img of=recovery.img bs=256 skip=1" % resDir, shell = True)
seekedCopy(os.path.join(resDir, "7.1.1_volantis_n9f27m", "recovery.img"), "recovery.img", 256)
verifySingleJson("%s/7.1.1_volantis_n9f27m/recovery.json" % resDir) verifySingleJson("%s/7.1.1_volantis_n9f27m/recovery.json" % resDir)
# 8.0 # 8.0
verifySingleDir(resDir, "8.0.0_fugu_opr2.170623.027") verifySingleDir(resDir, "8.0.0_fugu_opr2.170623.027")

@ -1 +1 @@
Subproject commit 5ff0d54252367d6bae8c8448dc0100c98823a212 Subproject commit 35fd7989555769a3cca47537798df28fc733479f

@ -2,7 +2,6 @@
# release.mk # release.mk
# yu, 2020-12-20 00:19 # yu, 2020-12-20 00:19
# #
define gw define gw
#!/usr/bin/env sh\n #!/usr/bin/env sh\n
if [ "x$$1" = "xassemble" ]; then\n if [ "x$$1" = "xassemble" ]; then\n
@ -20,7 +19,12 @@ fi\n
java -jar bbootimg/bbootimg.jar $$* java -jar bbootimg/bbootimg.jar $$*
endef endef
export gw
define gw_win
@IF EXIST tools\\bin SET PATH=%PATH%;tools\\bin\n
@java -jar bbootimg/bbootimg.jar %*
endef
export gw gw_win
all: all:
cd ../bbootimg && gradle build cd ../bbootimg && gradle build
cp ../bbootimg/build/libs/bbootimg.jar . cp ../bbootimg/build/libs/bbootimg.jar .
@ -33,7 +37,9 @@ all:
mkdir ../bbootimg && mv bbootimg.jar ../bbootimg/ mkdir ../bbootimg && mv bbootimg.jar ../bbootimg/
echo $$gw > gradlew echo $$gw > gradlew
chmod 755 gradlew chmod 755 gradlew
echo $$gw_win > gradlew.bat
mv gradlew ../ mv gradlew ../
mv gradlew.bat ../
# vim:ft=make # vim:ft=make
# #

Loading…
Cancel
Save