[Atrix 4G General] samcripp:
ROM Factory Magic

Random Facts​

Developing ROM Factory took, 4 months, cost 743$, hard bricked one device :( and the finish product uses android, java zip, and the under laying linux. Its in continues research. With ever changing phones, ever changing ROM Factory. Because of the way the app is design only Phones with BML partition system can use it. Mostly high end devices.​

ROM Factory does not create a nandroid back up.​

​

Understanding how ROM Factory works.​

The Device Library​

In the library I began to create a list of devices. This list contains a device name, and some specifics about the device. Such as /system partition location, and storage options.

The main function for it is to identify the device and provide the info. Looks something like this:

if(Phone.contentEquals("olympus")) //moto atrix

{
if(OS.contentEquals("2.3.4"))
{
zStorage = "/sdcard-ext";
} else if(OS.contentEquals("2.3.5")) {
zStorage = "/sdcard-ext";
} else if(OS.contentEquals("2.3.6")) {
zStorage = "/sdcard-ext";
} else {
zStorage = Environment.getExternalStorageDirectory().getAbsolutePath();
}
RName = "Atrix 4G";
appRun = true;
DataPart = "/dev/block/mmcblk0p07";
BootPart = "/dev/block/mmcblk0p11";
SysPart = "/dev/block/mmcblk0p12";
}

The SU Class​

In the class I build a custom set of methods to handle the super user commands require to create the back ups.

Looks something like this:

public void cmdSU(String suCmd){
DataOutputStream suShell = new DataOutputStream(user.getOutputStream());
try{
suShell.writeBytes(suCmd + "\n");
suShell.writeBytes("wait\n");
suShell.writeBytes("exit\n");
suShell.flush();
try { user.waitFor();
if (user.exitValue() != 255) { } else { }
} catch (InterruptedException e) { Log.e("SU", e.getMessage()); }
} catch (IOException e) { Log.e("SU", e.getMessage()); }
}

The Script Engine​

I still very much consider this a work in progress.​

In the class I build a custom set of methods to handle the creation of the edify script required by Recovery to install a ROM. To save time and resources instead of creating a new file, the app simply echos a new one through the SU class. The script engine also detects some of the phone settigns and prepares the script

Looks something like this:

// Script Engine v0.6 * By Samuel Rivera "SamCripp"
//
// This code is constantly evolving. So if you use this on your project please keep an eye on the repository the code came from.
//
// http://zombidev.com * http://fcm.zombidev.com * http://repo.zombidev.com
//
// This code is the intellectual property of Samuel Rivera, 2011-2012. I, Samuel Rivera, grant you the following rights.
// 1. You may modify and redistribute this code. 2. You may compile and redistribute this code. 3. You may use this code in personal or educational projects.
//
// With that said, here is a list of rights revoked.
// 1. You may not use this code on commercial projects. 2. You may not use this code on corporate environment.
// 3. You may not use the code in any malicious way. 4. You may not use it for profit.
//
// Conditions:
// 1. Any project utilizing this code, whether close or open source, must always provide the latest version of this code, including all modifications.
// 2. Any project utilizing this code, must provide a link back to http://fcm.zombidev.com and http://repo.zombidev.com.
// 3. Any project utilizing this code, must provide credit to Samuel Rivera as original author of code. ie:
// Script Engine v0.6 - Original Author: Samuel Rivera "SamCripp"
//
// Thanks for following this simple rules.

package com.samcripp.romff;

public class ScriptEng {
String SEVersion = new String("--Script Engine v0.6");
String boot = new String();
String system = new String();
String os = new String();
String romName = new String();
String devName = new String();
String device = new String();
String formatType = new String();
boolean SndInit = false;
boolean NormalM = false;
boolean AdvMode = false;
boolean AppMode = false;
boolean backupMode = false;
String TheScript = new String();

String sym = "\"";
String beginCmd = "(";
String endCmd = ") > ";
String echo = "echo "+ sym;
String and = " && ";
String pend = ");" + sym;
String prog = "show_progress(";
String sprog = "set_progress(";
String ui_print = "ui_print(\\" + sym;
String ui_end = "\\" + sym + ");"+ sym;
String warning = "--This script is generated automatically--";
String line = "- - - - - - - - - - - - - - - - - - - - - - -";
String pkgexb = "package_extract_file(\\" + sym + "/boot.img" + "\\" + sym + "," + "\\" + sym + boot + "\\" + sym + ");" + sym;
String pkgexs = "package_extract_file(\\" + sym + "/system.img" + "\\" + sym + "," + "\\" + sym + system + "\\" + sym + ");" + sym;
String fdlexs = "package_extract_dir(\\" + sym + "system" + "\\" + sym + "," + "\\" + sym + "/system" + "\\" + sym + ");" + sym;
String fdlexaa = "package_extract_dir(\\" + sym + "apps" + "\\" + sym + "," + "\\" + sym + "/tmp/apps" + "\\" + sym + ");" + sym;
String fdlexdd = "package_extract_dir(\\" + sym + "data" + "\\" + sym + "," + "\\" + sym + "/tmp/data" + "\\" + sym + ");" + sym;
String fdlexa = "run_program(\\" + sym + "/system/xbin/busybox" + "\\" + sym + ", " + "\\" + sym + "cp -R" + "\\" + sym + ", " + "\\" + sym + "/tmp/apps" +", " + "\\" + sym + "/data/app" + "\\" + sym + ");" + sym;
String busymount = "run_program(\\" + sym + "/system/xbin/busybox" + "\\" + sym + ", " + "\\" + sym + "mount" + "\\" + sym + ", " + "\\" + sym + "/data" + "\\" + sym + ");" + sym;
String busydata = "run_program(\\" + sym + "/system/xbin/busybox" + "\\" + sym + ", " + "\\" + sym + "cp -R" + "\\" + sym + ", " + "\\" + sym + "/tmp/data" +", " + "\\" + sym + "/data" + "\\" + sym + ");" + sym;

String umountS = "unmount(\\" + sym + "/system" + "\\" + sym + ");" + sym;

public ScriptEng(boolean Init, String dev, String dName, String deviceN, String bootL, String sysL, String rom, String romversion,String dOs){

boot = bootL;
system = sysL;
romName = rom + " " + romversion;
devName = dev;
os = dOs;
device = dName + " " + deviceN;
SndInit = Init;
//	AdvMode = adv;
//	AppMode = app;
//	backupMode = backup;
}

public void Make(){

String formatS = new String();
String mountS = new String();

if(formatType == "ext4"){
formatS = "format(\\" + sym + "ext4" + "\\" + sym + "," + "\\" + sym + "EMMC" + "\\" + sym + "," + "\\" + sym + system + "\\" + sym + ");" + sym;
mountS = "mount(\\" + sym + "ext4" + "\\" + sym + "," + "\\" + sym + "EMMC" + "\\" + sym + "," + "\\" + sym + system + "\\" + sym + "," + "\\" + sym + "/system" + "\\" + sym + ");" + sym;
} else if(formatType == "yaffs"){
formatS = "format(\\" + sym;
}else{
formatS = "format(\\" + sym + "ext3" + "\\" + sym + "," + "\\" + sym + "EMMC" + "\\" + sym + "," + "\\" + sym + system + "\\" + sym + ");" + sym;
mountS = "mount(\\" + sym + "ext3" + "\\" + sym + "," + "\\" + sym + "EMMC" + "\\" + sym + "," + "\\" + sym + system + "\\" + sym + "," + "\\" + sym + "/system" + "\\" + sym + ");" + sym;
}

if(SndInit == true){
NormalM = false;
}else{
NormalM = true;
}

if(NormalM == true && SndInit == false && AdvMode == false && AppMode == false){

// good old normal phone
TheScript = beginCmd + echo + prog + "1.000000, 0" + pend + and + echo + ui_print + warning + ui_end
+ and + echo + ui_print + SEVersion + ui_end + and + echo + ui_print + "--Rom Name: "+ romName + ui_end
+ and + echo + ui_print + "--Rom Developer: " + devName + ui_end + and + echo + ui_print
+ "--Rom Base: " + os + ui_end + and + echo + ui_print + "--Device Name: " + device + ui_end
+ and + echo + ui_print + line + ui_end + and + echo + ui_print + "--Installing Boot" + ui_end
+ and + echo + sprog + "0.300000" + pend + and + echo + pkgexb
+ and + echo + ui_print + "--Installing System" + ui_end
+ and + echo + sprog + "0.650000" + pend + and + echo + pkgexs + and + echo + ui_print + line
+ ui_end + and + echo + ui_print + "--Don't forget to format data and cache" + ui_end
+ and + echo + sprog + "1.000000" + pend + endCmd;

} if(NormalM == false && SndInit == true && AdvMode == false && AppMode == false){

// normal second init
TheScript = beginCmd + echo + prog + "1.000000, 0" + pend + and + echo + ui_print + warning + ui_end
+ and + echo + ui_print + SEVersion + ui_end + and + echo + ui_print + "--Rom Name: "+ romName + ui_end
+ and + echo + ui_print + "--Rom Developer: " + devName + ui_end + and + echo + ui_print
+ "--Rom Base: " + os + ui_end + and + echo + ui_print + "--Device Name: " + device + ui_end
+ and + echo + ui_print + line + ui_end + and + echo + ui_print + "--Installing System" + ui_end
+ and + echo + sprog + "0.650000" + pend + and + echo + pkgexs + and + echo + ui_print + line
+ ui_end + and + echo + ui_print + "--Don't forget to format data and cache" + ui_end
+ and + echo + sprog + "1.000000" + pend + endCmd;
} if(NormalM == true && SndInit == false && AdvMode == true && AppMode == false && backupMode == false){

// normal device with advance mode
TheScript = beginCmd + echo + prog + "1.000000, 0" + pend + and + echo + ui_print + warning + ui_end
+ and + echo + ui_print + SEVersion + ui_end + and + echo + ui_print + "--Rom Name: "+ romName + ui_end
+ and + echo + ui_print + "--Rom Developer: " + devName + ui_end + and + echo + ui_print
+ "--Rom Base: " + os + ui_end + and + echo + ui_print + "--Device Name: " + device + ui_end
+ and + echo + ui_print + line + ui_end + and + echo + ui_print + "--Installing Boot" + ui_end
+ and + echo + sprog + "0.300000" + pend + and + echo + pkgexb
+ and + echo + ui_print + "--Formating System" + ui_end
+ and + echo + sprog + "0.550000" + pend + and + echo + formatS
+ and + echo + ui_print + "--Installing System" + ui_end
+ and + echo + sprog + "0.600000" + pend + and + echo + pkgexs
+ and + echo + ui_print + "--Mounting System" + ui_end
+ and + echo + sprog + "0.900000" + pend + and + echo + mountS
+ and + echo + ui_print + "--Extracting System Mods" + ui_end
+ and + echo + sprog + "0.950000" + pend + and + echo + fdlexs
+ and + echo + ui_print + "--UnMounting System" + ui_end
+ and + echo + sprog + "0.990000" + pend + and + echo + umountS
+ and + echo + ui_print + line
+ ui_end + and + echo + ui_print + "--Don't forget to format data and cache" + ui_end
+ and + echo + sprog + "1.000000" + pend + endCmd;
} if(NormalM == false && SndInit == true && AdvMode == true && AppMode == false && backupMode == false){

// second init device with advance mode
TheScript = beginCmd + echo + prog + "1.000000, 0" + pend + and + echo + ui_print + warning + ui_end
+ and + echo + ui_print + SEVersion + ui_end + and + echo + ui_print + "--Rom Name: "+ romName + ui_end
+ and + echo + ui_print + "--Rom Developer: " + devName + ui_end + and + echo + ui_print
+ "--Rom Base: " + os + ui_end + and + echo + ui_print + "--Device Name: " + device + ui_end
+ and + echo + ui_print + line + ui_end + and + echo + ui_print + "--Formating System" + ui_end
+ and + echo + sprog + "0.550000" + pend + and + echo + formatS
+ and + echo + ui_print + "--Installing System" + ui_end
+ and + echo + sprog + "0.600000" + pend + and + echo + pkgexs
+ and + echo + ui_print + "--Mounting System" + ui_end
+ and + echo + sprog + "0.900000" + pend + and + echo + mountS
+ and + echo + ui_print + "--Extracting System Mods" + ui_end
+ and + echo + sprog + "0.950000" + pend + and + echo + fdlexs
+ and + echo + ui_print + "--UnMounting System" + ui_end
+ and + echo + sprog + "0.990000" + pend + and + echo + umountS
+ and + echo + ui_print + line
+ ui_end + and + echo + ui_print + "--Don't forget to format data and cache" + ui_end
+ and + echo + sprog + "1.000000" + pend + endCmd;
} if(NormalM == true && SndInit == false && AdvMode == false && AppMode == true && backupMode == false){

// normal device with apps mode
TheScript = beginCmd + echo + prog + "1.000000, 0" + pend + and + echo + ui_print + warning + ui_end
+ and + echo + ui_print + SEVersion + ui_end + and + echo + ui_print + "--Rom Name: "+ romName + ui_end
+ and + echo + ui_print + "--Rom Developer: " + devName + ui_end + and + echo + ui_print
+ "--Rom Base: " + os + ui_end + and + echo + ui_print + "--Device Name: " + device + ui_end
+ and + echo + ui_print + line + ui_end + and + echo + ui_print + "--Installing Boot" + ui_end
+ and + echo + sprog + "0.300000" + pend + and + echo + pkgexb
+ and + echo + ui_print + "--Formating System" + ui_end
+ and + echo + sprog + "0.550000" + pend + and + echo + formatS
+ and + echo + ui_print + "--Installing System" + ui_end
+ and + echo + sprog + "0.600000" + pend + and + echo + pkgexs
+ and + echo + ui_print + "--Mounting System" + ui_end
+ and + echo + sprog + "0.900000" + pend + and + echo + mountS
+ and + echo + ui_print + "--Extracting Apps" + ui_end
+ and + echo + sprog + "0.930000" + pend + and + echo + fdlexaa
+ and + echo + sprog + "0.950000" + pend + and + echo + fdlexa
+ and + echo + ui_print + "--UnMounting System" + ui_end
+ and + echo + sprog + "0.990000" + pend + and + echo + umountS
+ and + echo + ui_print + line
+ ui_end + and + echo + ui_print + "--Don't forget to format data and cache" + ui_end
+ and + echo + sprog + "1.000000" + pend + endCmd;
} if(NormalM == false && SndInit == true && AdvMode == false && AppMode == true && backupMode == false){

// second init device with apps mode
TheScript = beginCmd + echo + prog + "1.000000, 0" + pend + and + echo + ui_print + warning + ui_end
+ and + echo + ui_print + SEVersion + ui_end + and + echo + ui_print + "--Rom Name: "+ romName + ui_end
+ and + echo + ui_print + "--Rom Developer: " + devName + ui_end + and + echo + ui_print
+ "--Rom Base: " + os + ui_end + and + echo + ui_print + "--Device Name: " + device + ui_end
+ and + echo + ui_print + line + ui_end + and + echo + ui_print + "--Formating System" + ui_end
+ and + echo + sprog + "0.550000" + pend + and + echo + formatS
+ and + echo + ui_print + "--Installing System" + ui_end
+ and + echo + sprog + "0.600000" + pend + and + echo + pkgexs
+ and + echo + ui_print + "--Mounting System" + ui_end
+ and + echo + sprog + "0.900000" + pend + and + echo + mountS
+ and + echo + ui_print + "--Extracting Apps" + ui_end
+ and + echo + sprog + "0.930000" + pend + and + echo + fdlexaa
+ and + echo + sprog + "0.950000" + pend + and + echo + fdlexa
+ and + echo + ui_print + "--UnMounting System" + ui_end
+ and + echo + sprog + "0.990000" + pend + and + echo + umountS
+ and + echo + ui_print + line
+ ui_end + and + echo + ui_print + "--Don't forget to format data and cache" + ui_end
+ and + echo + sprog + "1.000000" + pend + endCmd;
} if(NormalM == true && SndInit == false && AdvMode == false && AppMode == false && backupMode == true){

// normal device with back up mode
TheScript = beginCmd + echo + prog + "1.000000, 0" + pend + and + echo + ui_print + warning + ui_end
+ and + echo + ui_print + SEVersion + ui_end + and + echo + ui_print + "--Rom Name: "+ romName + ui_end
+ and + echo + ui_print + "--Rom Developer: " + devName + ui_end + and + echo + ui_print
+ "--Rom Base: " + os + ui_end + and + echo + ui_print + "--Device Name: " + device + ui_end
+ and + echo + ui_print + line + ui_end + and + echo + ui_print + "--Installing Boot" + ui_end
+ and + echo + sprog + "0.300000" + pend + and + echo + pkgexb
+ and + echo + ui_print + "--Formating System" + ui_end
+ and + echo + sprog + "0.550000" + pend + and + echo + formatS
+ and + echo + ui_print + "--Installing System" + ui_end
+ and + echo + sprog + "0.600000" + pend + and + echo + pkgexs
+ and + echo + ui_print + "--Mounting Data" + ui_end
+ and + echo + sprog + "0.900000" + pend + and + echo + busymount
+ and + echo + ui_print + "--Extracting Back Up" + ui_end
+ and + echo + sprog + "0.930000" + pend + and + echo + fdlexdd
+ and + echo + sprog + "0.950000" + pend + and + echo + busydata
+ and + echo + ui_print + line
+ ui_end + and + echo + ui_print + "--Don't forget to format data and cache" + ui_end
+ and + echo + sprog + "1.000000" + pend + endCmd;
} if(NormalM == false && SndInit == true && AdvMode == false && AppMode == false && backupMode == true){

// second init device with apps mode
TheScript = beginCmd + echo + prog + "1.000000, 0" + pend + and + echo + ui_print + warning + ui_end
+ and + echo + ui_print + SEVersion + ui_end + and + echo + ui_print + "--Rom Name: "+ romName + ui_end
+ and + echo + ui_print + "--Rom Developer: " + devName + ui_end + and + echo + ui_print
+ "--Rom Base: " + os + ui_end + and + echo + ui_print + "--Device Name: " + device + ui_end
+ and + echo + ui_print + line + ui_end + and + echo + ui_print + "--Formating System" + ui_end
+ and + echo + sprog + "0.550000" + pend + and + echo + formatS
+ and + echo + ui_print + "--Installing System" + ui_end
+ and + echo + sprog + "0.600000" + pend + and + echo + pkgexs
+ and + echo + ui_print + "--Mounting Data" + ui_end
+ and + echo + sprog + "0.900000" + pend + and + echo + busymount
+ and + echo + ui_print + "--Extracting Back Up" + ui_end
+ and + echo + sprog + "0.930000" + pend + and + echo + fdlexdd
+ and + echo + sprog + "0.950000" + pend + and + echo + busydata
+ and + echo + ui_print + line
+ ui_end + and + echo + ui_print + "--Don't forget to format data and cache" + ui_end
+ and + echo + sprog + "1.000000" + pend + endCmd;
}
}
public String Script(){
return TheScript;
}
}

And finally Linux!​

Pay attention, here is where the magic happens. The apps sends a simple "dd" command to linux to create a "live image" of your emmc contents.

Looks something like this:

// creates system
new Thread(new Runnable() {
public void run() {
upBar(35);
log.V("Creating the system image");
log.V("Command: " + "dd if=" + device.System() + " of=" + device.Storage() + "/romf/workdir/system.img");
UBER.requestSU();
UBER.cmdSU("dd if=" + device.System() + " of=" + device.Storage() + "/romf/workdir/system.img");

endCreateSystem.sendEmptyMessage(0);
}
})
.start();

Making it all work together​

Step 1: App loads and detects device. (First install downloads a payload zip with the update.bin)

Step 2: User begins the rom creation triggering...

Step 3: Generates the script and echo it through linux, with the device info. (su class use)

Step 4: Then the back ups are created using dd through linux. (su class use)

Step 5: Some good old java zip takes care of packaging, the update.bin, the system.img, and boot.img.

Ta da, creating a rom through android.​

Why don't they files corrupt using this method​

The data does not corrupt using my method because instead of copying directly changing files, im copying the latest "modified" version. also because of the image is ext3 or ext4 the files can be fixed during the dd if the change.​

ROM Factory 2 is going to use a new approach, instead of a list of devices, that class will be redesign to work with vold.fstab, and other methods of detecting the phones absolute partition location.​