TWRP - How to prepare vendor blobs - Huawei Nova/Nova Plus Questions & Answers

I have a Huawei Nova 2, for which I want to extract vendor blobs to be able to decrypt the data partition in recovery mode, and for other purposes. I tried using the following tool: https://github.com/anestisb/android-prepare-vendor, but not only was it for Google's Nexus/Pixel devices, but when I tried to edit the code to work with my device, it does not support the images that I have.
I have .img back ups (using dd if= / of= commands) of my vendor and system partitions, but that tool gives an error about some sparse format. Kindly direct me in the right direction

Related

[Q] System image problem

My system partition was erased via fastboot in order to successfully flash a different one, however I'm getting write errors on one I pulled from somebodies' nandroid backup, and a buffer exceeded error when trying to flash the system.img from the leaked stock images thread.
Is there any way to flash the image from my phone (I read that fastboot doesn't handle files over 300mb?) or an alternate image I can use. Everything else is in tact the phone just stalls at the Google screen due to a missing /system
Alex.xTF said:
My system partition was erased via fastboot in order to successfully flash a different one, however I'm getting write errors on one I pulled from somebodies' nandroid backup, and a buffer exceeded error when trying to flash the system.img from the leaked stock images thread.
Is there any way to flash the image from my phone (I read that fastboot doesn't handle files over 300mb?) or an alternate image I can use. Everything else is in tact the phone just stalls at the Google screen due to a missing /system
Click to expand...
Click to collapse
You need a sparse filesystem image. Until the original factory images are made available online (it's in the works, but I don't have an exact date), somebody with a working device could create such an image by running (as root):
# make_ext4fs -l 512m -s /sdcard/system.img /system
This should create a flashable system.img (~145MB) on /sdcard (that you can then grab with adb pull or usb mass storage)
I really appreciate you responding, hopefully I can recover my phone without a return, anybody you can suggest I ask to do this for me?
Anybody with a Nexus S and an adb shell running as root should be able to do this.

[DEV]How to compile TWRP touch recovery

All of TWRP 3.x source is public. You can compile it on your own. This guide isn't going to be a step-by-step, word-for-word type of guide. If you're not familiar with basic Linux commands and/or building in AOSP then you probably won't be able to do this.
You can currently use Omni 6.0, Omni 7.1, Omni 8.1, Omni 9.0, CM 13.0, CM 14.1, CM 15.1, LineageOS 16.0 source code. Omni 9.0 is recommended for now unless your device has a super partition.
If you are using CM/LineageOS, you'll need to place TWRP in the LineageOS/bootable/recovery-twrp folder and set RECOVERY_VARIANT := twrp in your BoardConfig.mk file. TWRP source code can be found here:
https://github.com/TeamWin/android_bootable_recovery (NOTE: The location for the latest TWRP source code has changed!)
Select the newest branch available. This step is not necessary with Omni because Omni already includes TWRP source by default, however, if you are using an older version of Omni, you will probably want to pull from the latest branch (the latest branch will compile successfully in older build trees)
If you are only interested in building TWRP, you may want to try working with a smaller tree. You can try using this manifest. It should work in most cases but there may be some situations where you will need more repos in your tree than this manifest provides:
https://github.com/minimal-manifest-twrp
*BEFORE YOU COMPILE*
Note: If you add or change any flags, you will need to make clean or make clobber before recompiling or your flag changes will not be picked up.
Now that you have the source code, you'll need to set or change a few build flags for your device(s). Find the BoardConfig.mk for your device. The BoardConfig.mk is in your devices/manufacturer/codename folder (e.g. devices/lge/hammerhead/BoardConfig.mk).
Your board config will need to include architecture and platform settings. Usually these are already included if you're using device configs that someone else created, but if you created your own, you may need to add them. Without them, recovery may seg fault during startup and you'll just see the teamwin curtain flash on the screen over and over.
We usually put all of our flags at the bottom of the BoardConfig.mk under a heading of #twrp For all devices you'll need to tell TWRP what theme to use. This TW_THEME flag replaces the older DEVICE_RESOLUTION flag. TWRP now uses scaling to stretch any theme to fit the screen resolution. There are currently 5 settings which are: portrait_hdpi, portrait_mdpi, landscape_hdpi, landscape_mdpi, and watch_mdpi. For portrait, you should probably select the hdpi theme for resolutions of 720x1280 and higher. For landscape devices, use the hdpi theme for 1280x720 or higher.
TW_THEME := portrait_hdpi
Note that themes do not rotate 90 degrees and there currently is no option to rotate a theme. If you find that the touchscreen is rotated relative to the screen, then you can use some flags (discussed later in this guide) to rotate the touch input to match the screen's orientation.
In addition to the resolution, we have the following build flags:
RECOVERY_SDCARD_ON_DATA := true -- this enables proper handling of /data/media on devices that have this folder for storage (most Honeycomb and devices that originally shipped with ICS like Galaxy Nexus) This flag is not required for these types of devices though. If you do not define this flag and also do not include any references to /sdcard, /internal_sd, /internal_sdcard, or /emmc in your fstab, then we will automatically assume that the device is using emulated storage.
BOARD_HAS_NO_REAL_SDCARD := true -- disables things like sdcard partitioning and may save you some space if TWRP isn't fitting in your recovery patition
TW_NO_BATT_PERCENT := true -- disables the display of the battery percentage for devices that don't support it properly
TW_CUSTOM_POWER_BUTTON := 107 -- custom maps the power button for the lockscreen
TW_NO_REBOOT_BOOTLOADER := true -- removes the reboot bootloader button from the reboot menu
TW_NO_REBOOT_RECOVERY := true -- removes the reboot recovery button from the reboot menu
RECOVERY_TOUCHSCREEN_SWAP_XY := true -- swaps the mapping of touches between the X and Y axis
RECOVERY_TOUCHSCREEN_FLIP_Y := true -- flips y axis touchscreen values
RECOVERY_TOUCHSCREEN_FLIP_X := true -- flips x axis touchscreen values
TWRP_EVENT_LOGGING := true -- enables touch event logging to help debug touchscreen issues (don't leave this on for a release - it will fill up your logfile very quickly)
BOARD_HAS_FLIPPED_SCREEN := true -- flips the screen upside down for screens that were mounted upside-down
There are other build flags which you can locate by scanning the Android.mk files in the recovery source. Most of the other build flags are not often used and thus I won't document them all here.
*RECOVERY.FSTAB*
TWRP 2.5 and higher supports some new recovery.fstab features that you can use to extend TWRP's backup/restore capabilities. You do not have to add fstab flags as most partitions are handled automatically.
Note that TWRP only supports v2 fstabs in version 3.2.0 and higher. You will still need to use the "old" format of fstab for older TWRP (example of that format is below), and even TWRP 3.2.0 still supports the v1 format in addition to the v2 format. To maximize TWRP's compatibility with your build tree, you can create a twrp.fstab and use PRODUCT_COPY_FILES to place the file in /etc/twrp.fstab When TWRP boots, if it finds a twrp.fstab in the ramdisk it will rename /etc/recovery.fstab to /etc/recovery.fstab.bak and then rename /etc/twrp.fstab to /etc/recovery.fstab. Effectively this will "replace" the fstab 2 file that your device files are providing with the TWRP fstab allowing you to maintain compatibility within your device files and with other recoveries.
Code:
PRODUCT_COPY_FILES += device/lge/hammerhead/twrp.fstab:recovery/root/etc/twrp.fstab
The fstab in TWRP can contain some "flags" for each partition listed in the fstab.
Here's a sample TWRP fstab for the Galaxy S4 that we will use for reference:
Code:
/boot emmc /dev/block/platform/msm_sdcc.1/by-name/boot
/system ext4 /dev/block/platform/msm_sdcc.1/by-name/system
/data ext4 /dev/block/platform/msm_sdcc.1/by-name/userdata length=-16384
/cache ext4 /dev/block/platform/msm_sdcc.1/by-name/cache
/recovery emmc /dev/block/platform/msm_sdcc.1/by-name/recovery
/efs ext4 /dev/block/platform/msm_sdcc.1/by-name/efs flags=display="EFS";backup=1
/external_sd vfat /dev/block/mmcblk1p1 /dev/block/mmcblk1 flags=display="Micro SDcard";storage;wipeingui;removable
/usb-otg vfat /dev/block/sda1 /dev/block/sda flags=display="USB-OTG";storage;wipeingui;removable
/preload ext4 /dev/block/platform/msm_sdcc.1/by-name/hidden flags=display="Preload";wipeingui;backup=1
/modem ext4 /dev/block/platform/msm_sdcc.1/by-name/apnhlos
/mdm emmc /dev/block/platform/msm_sdcc.1/by-name/mdm
Flags are added to the end of the partition listing in the fstab separated by white space (spaces or tabs are fine). The flags affect only that partition but not any of the others. Flags are separated by semicolons. If your display name is going to have a space, you must surround the display name with quotes.
Code:
/external_sd vfat /dev/block/mmcblk1p1 flags=display="Micro SDcard";storage;wipeingui;removable
The flags for this partition give it a display name of "Micro SDcard" which is displayed to the user. wipeingui makes this partition available for wiping in the advanced wipe menu. The removable flag indicates that sometimes this partition may not be present preventing mounting errors from being displayed during startup. Here is a full list of flags:
removable -- indicates that the partition may not be present preventing mounting errors from being displayed during boot
storage -- indicates that the partition can be used as storage which makes the partition available as storage for backup, restore, zip installs, etc.
settingsstorage -- only one partition should be set as settings storage, this partition is used as the location for storing TWRP's settings file
canbewiped -- indicates that the partition can be wiped by the back-end system, but may not be listed in the GUI for wiping by the user
userrmrf -- overrides the normal format type of wiping and only allows the partition to be wiped using the rm -rf command
backup= -- must be succeeded by the equals sign, so backup=1 or backup=0, 1 indicates that the partition can be listed in the backup/restore list while 0 ensures that this partition will not show up in the backup list.
wipeingui -- makes the partition show up in the GUI to allow the user to select it for wiping in the advanced wipe menu
wipeduringfactoryreset -- the partition will be wiped during a factory reset
ignoreblkid -- blkid is used to determine what file system is in use by TWRP, this flag will cause TWRP to skip/ignore the results of blkid and use the file system specified in the fstab only
retainlayoutversion -- causes TWRP to retain the .layoutversion file in /data on devices like Sony Xperia S which sort of uses /data/media but still has a separate /sdcard partition
symlink= -- causes TWRP to run an additional mount command when mounting the partition, generally used with /data/media to create /sdcard
display= -- sets a display name for the partition for listing in the GUI
storagename= -- sets a storage name for the partition for listing in the GUI storage list
backupname= -- sets a backup name for the partition for listing in the GUI backup/restore list
length= -- usually used to reserve empty space at the end of the /data partition for storing the decryption key when Android's full device encryption is present, not setting this may lead to the inability to encrypt the device
canencryptbackup= -- 1 or 0 to enable/disable, makes TWRP encrypt the backup of this partition if the user chooses encryption (only applies to tar backups, not images)
userdataencryptbackup= -- 1 or 0 to enable/disable, makes TWRP encrypt only the userdata portion of this partition, certain subfuldes like /data/app would not be encrypted to save time
subpartitionof= -- must be succeeded by the equals sign and the path of the partition it is a subpartition of. A subpartition is treated as "part" of the main partition so for instance, TWRP automatically makes /datadata a subpartition of /data. This means that /datadata will not show up in the GUI listings, but /datadata would be wiped, backed up, restored, mounted, and unmounted anytime those operations are performed on /data. A good example of the use of subpartitions is the 3x efs partitions on the LG Optimus G:
Code:
/efs1 emmc /dev/block/mmcblk0p12 flags=backup=1;display=EFS
/efs2 emmc /dev/block/mmcblk0p13 flags=backup=1;subpartitionof=/efs1
/efs3 emmc /dev/block/mmcblk0p14 flags=backup=1;subpartitionof=/efs1
This lumps all 3 partitions into a single "EFS" entry in the TWRP GUI allowing all three to be backed up and restored together under a single entry.
As of TWRP 3.2.0, TWRP now supports a version 2 fstab like those that have been found in Android devices for years. Yes, I know we're really slow to adopt this one, but I also saw no major advantage to v2 and the v2 fstab was being used in regular Android as well as recovery and I didn't want full ROM builds crashing or doing other weird things because of TWRP flags being present in the fstab. Version 2 fstab support is automatic. You don’t need to add any build flags. The regular version 1 fstab format is also still valid and it’s possible to use both v1 and v2 types in the same fstab. TWRP 3.2.0 also supports using wildcards via the asterisk in v1 format which can be useful for USB OTG and micro SD cards with multiple partitions. Note also that v2 fstab formats haven’t been extensively tested so developers should test their v2 fstabs before shipping to users (you should always be testing anyway!).
This is a v1 fstab line with a wildcard intended for a USB OTG drive. All partitions should show up in the list of available storage devices when the user plugs in a drive:
Code:
/usb-otg vfat /dev/block/sda* flags=removable;storage;display=USB-OTG
This line is straight from the v2 fstab for the same device and also should work. In this case the kernel will notify us that new devices have been added or removed via uevents:
Code:
/devices/soc.0/f9200000.ssusb/f9200000.dwc3/xhci-hcd.0.auto/usb* auto auto defaults voldmanaged=usb:auto
In addition to the v2 fstab, you can include /etc/twrp.flags which uses the v1 fstab format. The twrp.flags file can be used to supplement the v2 fstab with TWRP flags, additional partitions not included in the v2 fstab, and to override settings in the v2 fstab. For example, I have a Huawei device with the following stock v2 fstab present as /etc/recovery.fstab
Code:
# Android fstab file.
#<src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
# The filesystem that contains the filesystem checker binary (typically /system) cannot
# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK
/dev/block/bootdevice/by-name/system /system ext4 ro,barrier=1 wait,verify
/dev/block/bootdevice/by-name/cust /cust ext4 ro,barrier=1 wait,verify
/devices/hi_mci.1/mmc_host/mmc1/* auto auto defaults voldmanaged=sdcard:auto,noemulatedsd
/devices/hisi-usb-otg/usb1/* auto auto defaults voldmanaged=usbotg:auto
/dev/block/bootdevice/by-name/userdata /data f2fs nosuid,nodev,noatime,discard,inline_data,inline_xattr wait,forceencrypt=footer,check
/dev/block/bootdevice/by-name/cache /cache ext4 rw,nosuid,nodev,noatime,data=ordered wait,check
/dev/block/bootdevice/by-name/splash2 /splash2 ext4 rw,nosuid,nodev,noatime,data=ordered,context=u:object_r:splash2_data_file:s0 wait,check
/dev/block/bootdevice/by-name/secure_storage /sec_storage ext4 rw,nosuid,nodev,noatime,discard,auto_da_alloc,mblk_io_submit,data=journal,context=u:object_r:teecd_data_file:s0 wait,check
In addition I have also included this in /etc/twrp.flags:
Code:
/boot emmc /dev/block/platform/hi_mci.0/by-name/boot
/recovery emmc /dev/block/platform/hi_mci.0/by-name/recovery flags=backup=1
/cust ext4 /dev/block/platform/hi_mci.0/by-name/cust flags=display="Cust";backup=1
/misc emmc /dev/block/platform/hi_mci.0/by-name/misc
/oeminfo emmc /dev/block/platform/hi_mci.0/by-name/oeminfo flags=display="OEMinfo";backup=1
/data f2fs /dev/block/dm-0
/system_image emmc /dev/block/platform/hi_mci.0/by-name/system
The first 2 lines in twrp.flags adds the boot and recovery partitions which were not present at all in the v2 fstab. The /cust line in the twrp.flags file is added to tell TWRP to allow users to back up the cust partition and to give it a slightly better display name. The /misc partition is also only present in the twrp.flags file. Much like the /cust partition, the /oeminfo partition is in the twrp.flags file to tell TWRP to allow users to back it up and give a display name. The /data line is needed because this Huawei device, like many Huawei devices, is encrypted but the encryption uses some special Huawei binaries and is encrypted with some sort of default password that the user cannot change. We use the Huawei binaries to decrypt the device automatically in recovery. The /data line here tells TWRP to use /dev/block/dm-0 instead of /dev/block/bootdevice/by-name/userdata which is required for proper mounting, etc. Lastly we have the /system_image line so that TWRP will add a system image option for backup and restore.
As we add more new devices, we’ll add more example device trees to https://github.com/TeamWin/ which should help you find more ways to use this new fstab support. Please note that using the v2 fstab format at this point is completely optional, so feel free to continue using v1 if that is what is more comfortable or if you have trouble with the v2 format support.
If you have questions, feel free to stop by #twrp on Freenode. If you post here I may not see it for a while as I have lots of threads out there and there's no way for me to keep track of them all. If you successfully port TWRP to a new device, please let us know! We love to hear success stories!
If you have code changes that you'd like to submit, please submit them through the Omni Gerrit server. Guide is here.
Once you get Omni or CM sync'ed and your TWRP flags set, you should do a source ./build/envsetup.sh We usually lunch for the device in question, so something like "lunch omni_hammerhead-eng".
After you lunch successfully for your device this is the command used for most devices:
Code:
make clean && make -j# recoveryimage
Replace the # with the core count +1, so if you have a dual core it's -j3 and a quad core becomes -j5, etc. If you're dealing with a "typical" Samsung device, then you'll need to
Code:
make -j# bootimage
Most Samsung devices have the recovery included as an extra ramdisk in the boot image instead of a separate recovery partition as found on most other devices.
Old guide here: http://forum.xda-developers.com/showpost.php?p=65482905&postcount=1471
So, now, hopefully you've compiled TWRP for your device and gotten it working. Now, you'd like to know how to get TWRP officially supported for your device so that it can be installed automatically with the TWRP app. In order for us to add "official support" for your device we'll need the following:
1) Device configuration files to compile TWRP from source for your device. This means that you cannot have repacked a recovery.img by hand to get it working. We need to be able to compile it from source so that we can easily release future updates.
2) We'll build a copy of TWRP and send it to you for validation. Once you've validated that we can build a working image for your device, we'll add it to the official TWRP app.
Note that we won't take credit for your port. You'll still get to post it on XDA to collect all the credit that goes with releasing something new for your device along with having your name listed on our website as the maintainer for the device. Also note that it's not always possible to provide automated installs for all devices.
You can now boot TWRP in an emulator. If you're trying to help develop TWRP, this can be a huge help as you don't have to risk your device and you can do everything directly on your computer.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Download this set of device configuration files.
Compile a recoveryimage using those device files. In the Android SDK, click on Tools -> Manage AVDs. Click New. Set it up as the following:
AVD Name: TWRP
Device: Galaxy Nexus
Target: ICS or newer though anything will probably work here
CPU: ARM (armeabi-v7a)
Check the box for hardware keyboard (your computer's keyboard will work in TWRP)
Up to you if you want to have the skin with controls present
Front Camera: None
Back Camera: None
RAM: 1024 VM Heap: 64
Internal Storage: 200
SD Card: Size: 500 MiB
Then click OK.
Once you have your AVD and your recoveryimage, you can boot TWRP in the emulator by browsing to your android-sdk/tools folder and run this command:
./emulator -avd TWRP -ramdisk CMFOLDER/out/target/product/twrp/ramdisk-recovery.img
Note that ADB doesn't work right away. About 10 to 15 seconds after TWRP finishes booting, ADB will come online. We start ADB via init.rc so even if TWRP fails to boot due to some kind of code error that you may have made, ADB should still work. Enjoy!
TWRP and A/B devices:
From a TWRP standpoint, A/B devices aren't a whole lot different from regular devices, but developers seem to be shy about working on these devices. I'm going to try to shed some light on this subject and hopefully this will serve as a guide for porting TWRP to A/B devices.
Firstly, let's understand what is an A/B device and how it's different. A/B devices have duplicates of many partitions on the device. An A/B device has 2x system partitions, 2x boot partitions, 2x vendor partitions, 2x modem / firmware partitions, etc. Only one slot is in use at a time. During early boot, the first stages of the bootloader read some small amount of data called the BCB or Bootloader Control Block and decide whether to boot the A partitions or the B partitions. When an OTA update is available, the data from the active slot is copied from the inactive slot and patched / updated. For example, if you're currently on slot A, your device would download the update and copy the existing system partition from slot A and patch / update it with the new updates into slot B. Once the copying and updating is complete, the BCB is updated and the device reboots using slot B. Next time an update is available, the system partition in slot B is copied to slot A and updated, the BCB gets updated, and we reboot to slot A. When viewing partitions on the device, you'll see something like this:
Code:
/dev/block/bootdevice/by-name/boot_a
/dev/block/bootdevice/by-name/boot_b
/dev/block/bootdevice/by-name/system_a
/dev/block/bootdevice/by-name/system_b
/dev/block/bootdevice/by-name/userdata
/dev/block/bootdevice/by-name/vendor_a
/dev/block/bootdevice/by-name/vendor_b
Note the dual boot, system and vendor partitions in the list above, but only one userdata partition.
While there is technically no requirement that I am aware of, all A/B devices shipped thus far have no separate recovery partition. Instead, the boot image contains the recovery in its ramdisk. The important thing is knowing that the boot image now also contains the recovery. For completeness, the system partition is a full root file system. During boot, if the kernel is told to boot to recovery, it will extract the ramdisk in the boot partition. If the kernel is not told by the bootloader to boot to recovery, then the kernel will mount the appropriate system partition (A or B) because the system partition is a full root file system. This means that the system partition on these devices is mounted to / instead of to /system and the system partition contains all of the files that would have normally been in the boot image ramdisk and a /system subfolder.
From a TWRP standpoint, there are 3 things that you have to do for an A/B device. First, you need to set
Code:
AB_OTA_UPDATER := true
in your BoardConfig.mk. Secondly, for any partition that has an A/B option, you need to add
Code:
flags=slotselect
in your fstab so something like this:
Code:
/boot emmc /dev/block/bootdevice/by-name/boot flags=slotselect
/system ext4 /dev/block/bootdevice/by-name/system flags=slotselect
/system_image emmc /dev/block/bootdevice/by-name/system flags=slotselect
/vendor ext4 /dev/block/bootdevice/by-name/vendor flags=slotselect;display="Vendor";backup=1
/vendor_image emmc /dev/block/bootdevice/by-name/vendor flags=slotselect
Lastly, once you get into TWRP, you will probably want to make sure that bootctl hal-info responds correctly with no errors. Usually the bootctl binary requires a proprietary library or even a couple of services to work correctly. If bootctl does not work correctly, then you will not be able to switch slots within TWRP correctly either.
In addition to setting
Code:
AB_OTA_UPDATER := true
you may also want to set:
Code:
BOARD_USES_RECOVERY_AS_BOOT := true
BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
If you set
Code:
BOARD_USES_RECOVERY_AS_BOOT := true
then make recoveryimage will no longer work and instead you will have to make bootimage. I don't recommend setting either of these flags for TWRP-only build trees. These flags will probably be required for developers building full ROMs for A/B devices.
Installing / Flashing TWRP on A/B devices:
Since all known A/B devices do not have a separate recovery partition, you will eventually have to flash TWRP to the boot partition. On the Pixel 1 and 2, we use fastboot boot to temporarily boot TWRP without flashing TWRP. We are then supplying a zip to allow users to flash TWRP to both slots. You can download one of these zips from our website and update the zip as needed to support your devices. Eventually we will add tools to TWRP to allow users to flash recoveries on these devices without needing to use zips.
Recently, I worked on the Razer Phone. The Razer Phone unfortunately does not support fastboot boot. Instead, users have to determine their currently active boot slot using
Code:
adb shell getprop ro.boot.slot_suffix
then use
Code:
fastboot --set-active=_a
to switch slots to the inactive slot. From here, the user can
Code:
fastboot flash boot twrp.img && fastboot reboot
to get into TWRP. Once in TWRP they can then go to the reboot page and change back to their originally active slot, make a backup, then install TWRP. Using the inactive slot allows users to get a good, unmodified backup of their device before installing TWRP.
Hopefully this helps!
Debugging with gdb in TWRP guide can be found here!
Beep boop zee doop
I know I've PM'ed you but I would like to ask you again. What should I do after compiling the TWRP recovery binary? What files have to be copied and where? I'm trying to integrate it with an ICS kernel.
Dees_Troy said:
Once you get CM sync'ed, I suggest that you go ahead and compile a build of ClockworkMod (ClockworkMod source is included in the CM repos). We usually lunch for the device in question, so something like "lunch full_tenderloin-eng".
After you lunch successfully for your device this is the command used for most devices:
Code:
make clean && make -j# recoveryimage
Click to expand...
Click to collapse
I don't get this part. What is lunch supposed to be? is it supposed to be a individual command for a device or can I do "lunch full_tenderloin-eng" for all devices? Because I am building for a device that doesn't run Android natively (at least out of-the-box) so cyanogenmod doesn't support it on any way...
Also, can I use this for resistive screens? Just to make sure.
Thanks for the guide, I have been looking for this for a long time
thanks for the guide, well structured and not so complicated
i have only a question: i'm trying to build it for galaxy 5, the problem is that the resolution is 320x240, so can you tip me on modify the sources? (i've done this some days ago, but images were too large)
manuel100 said:
thanks for the guide, well structured and not so complicated
i have only a question: i'm trying to build it for galaxy 5, the problem is that the resolution is 320x240, so can you tip me on modify the sources? (i've done this some days ago, but images were too large)
Click to expand...
Click to collapse
Set the device resolution to 320x240...I'm pretty sure they have support for that resolution...and if they don't then you can copy one of there's except resize it all to 320x240
Edit-they only have 320x480 https://github.com/TeamWin/Team-Win-Recovery-Project/
My question: I built twrp from source a while ago using smasher's Samsung inject twrp zip...that worked fine for a while...but recently we switched to mtd format so that inject twrp zip doesn't work...neither does the inhect twrp button within twrp anymore...I've seen that the galaxy s has the same problem as well...just wondering if you know of a work around...
Sent from my SGH-I997 using Tapatalk 2
mg2195 said:
Set the device resolution to 320x240...I'm pretty sure they have support for that resolution...and if they don't then you can copy one of there's except resize it all to 320x240
Edit-they only have 320x480 https://github.com/TeamWin/Team-Win-Recovery-Project/
My question: I built twrp from source a while ago using smasher's Samsung inject twrp zip...that worked fine for a while...but recently we switched to mtd format so that inject twrp zip doesn't work...neither does the inhect twrp button within twrp anymore...I've seen that the galaxy s has the same problem as well...just wondering if you know of a work around...
Sent from my SGH-I997 using Tapatalk 2
Click to expand...
Click to collapse
thanks for respond, however i've tried resizing images to 320x240 but i don't know what should be the size of bottoms, because they are alway out-of-screen
what is smasher's Samsung inject twrp zip? but i think that the recovery doesn't work because you have to built it with mtd support (for ex. on madteam they are trying to build a mtd kernel, but for install that testing rom they built a special cwm with mtd support)
manuel100 said:
thanks for respond, however i've tried resizing images to 320x240 but i don't know what should be the size of bottoms, because they are alway out-of-screen
what is smasher's Samsung inject twrp zip? but i think that the recovery doesn't work because you have to built it with mtd support (for ex. on madteam they are trying to build a mtd kernel, but for install that testing rom they built a special cwm with mtd support)
Click to expand...
Click to collapse
Smashers inject twrp zip is a tool for Samsung devices that let's you get the recovery without flashing the whole kernel. You basically put the ramdisk-recovery.img in the zip and then flash. During the flash process it pulls the boot.img, replaces the current ramdisk-recovery.img with the new one that contains twrp. It then deletes the old boot.img and flashes the new one...not affecting the actual kernel...
The recovery itself has mtd support...I can use it if I flash the whole boot.img, but I don't want to release the recovery within a whole kernel...because then I have to keep it up to date with both twrp and kernel sources, not to mention the different kernels available for my device....I can't make a recovery for each kernel...don't have the time for that...that's where the inject came in handy....the user could use any kernel he wanted while still using twrp
Recovery logs say it fails to find the ramdisk inside the boot.img and then in parenthesis something about may not be using gzip compression...which it is....
Sent from my SGH-I997 using Tapatalk 2
---------- Post added at 07:21 AM ---------- Previous post was at 07:19 AM ----------
Deestroy did this same tutorial on rootzwiki...if you look at the second post you'll see info about the smasher inject twrp I was referring to...http://rootzwiki.com/index.php?/topic/23903-How-to-Compile-TWRP-from-Source
Sent from my SGH-I997 using Tapatalk 2
mfsr98 said:
I don't get this part. What is lunch supposed to be? is it supposed to be a individual command for a device or can I do "lunch full_tenderloin-eng" for all devices? Because I am building for a device that doesn't run Android natively (at least out of-the-box) so cyanogenmod doesn't support it on any way...
Also, can I use this for resistive screens? Just to make sure.
Thanks for the guide, I have been looking for this for a long time
Click to expand...
Click to collapse
can I get help here please?
mfsr98 said:
can I get help here please?
Click to expand...
Click to collapse
Its a single command...it opens up the menu for devices...just type lunch into the terminal and hit enter...you'll see what I mean. You will probably have to add your device to the menu by creating a vendorsetup.sh in your device repo if it doesn't already exist....
Sent from my SGH-I997 using Tapatalk 2
Thank you for the quick answer. Yes, I already have vendorsetup.sh on the boot.img. Sorry for the noob question
What about for android beginners???
Devarishi said:
What about for android beginners???
Click to expand...
Click to collapse
There's only so much that you can dumb it down and simplify it. There's lots of other guides out there for getting started. Compiling a recovery is not a super simple task that anyone and everyone can do and there's plenty of potential pitfalls including the possibility of bricking your device. If none or very little of this guide makes sense, then you might see if a developer for your device is interested in working on it instead.
how would you compile this for a device without an official cm9 build?
azoller1 said:
how would you compile this for a device without an official cm9 build?
Click to expand...
Click to collapse
Well, you don't need official cm9 if you can find any working device tree for you phone you are good to go.. For lg spectrum 4g, this could be useful.
Hey guys I'm trying to compile this for my phone the problem I'm running into is I need the root.ts I've searched and it doesn't come up with anything any help would be appreciated thanks
Sent from my SAMSUNG-SGH-I577 using xda premium
I have a mtk6577 device which is not in de device tree of CM9.
I can compile CWM for my device with CM9. Because I was only making recovery, there was no need for setting up boardconfig.
In this guide there is a part starting with TARGET_RECOVERY_INITRC which is not there in my boardconfig.
Also is stated:
"Your board config also needs to include architecture and platform settings. Usually these are already included if you're using device configs that someone else created, but if you created your own, you may need to add them. Without them, recovery will often seg fault during startup and you'll just see the teamwin curtain flash on the screen over and over."
Does this mean that I cannot build TWRP without it, even I can build CWM ?
gls9 said:
I have a mtk6577 device which is not in de device tree of CM9.
I can compile CWM for my device with CM9. Because I was only making recovery, there was no need for setting up boardconfig.
In this guide there is a part starting with TARGET_RECOVERY_INITRC which is not there in my boardconfig.
Also is stated:
"Your board config also needs to include architecture and platform settings. Usually these are already included if you're using device configs that someone else created, but if you created your own, you may need to add them. Without them, recovery will often seg fault during startup and you'll just see the teamwin curtain flash on the screen over and over."
Does this mean that I cannot build TWRP without it, even I can build CWM ?
Click to expand...
Click to collapse
Look for another mtk6577 device that has CM & copy the arch flags from it.

[Q] how to make .img files from existing tablet?

I have a complete setup for the Nexus 7, part of a product we are working on, that I need to easily clone on "virgin" tablets for production. The app requires a rooted OS.
I want to write an installation script using fastboot to unlock the bootloader, erase partitions, then flash them with .img files for each partition (kernel, system, cache, etc.).
How do I extract .img files from my "master" tablet? I have an understanding from some where that these are simple byte-for-byte dumps of the partition -- is this true? As such can I create a .img file by simple doing 'cat blkfile >file.img' where "blkfile" is the appropriate block device for the partition in question?
Or do I need to use 'dd'? Or something else?
I have searched and searched, and can't find an anwer. I've found other answers using some tools to create these files from a build on a PC, but nothing about creating them from an existing tablet.
Thanks in advance!
Use the dd command. You can use it both to dump and write a partition. It's how I install recovery programs like TWRP
Sent from my Nexus 7
You can use dd for the boot partition and recovery partition - they are raw binary blobs. (Don't use dd on other Android devices, esp. those that have MTD flash devices, though - it only works most of the time there)
If you want to use the same fastboot-based scenario that Google uses for factory image sets, then for the system & userdata image files you will need to find out about "sparse ext4 filesystem images"
If you took a raw block-device based dump of any of your tablet ext4 partitions, you could actually take those image files and mount them on any other linux machine (using a loopback mount procedure).
But you will find that if you attempt to do that with the Google factory ".img" files (for system & userdata partitions), they will not mount. It's not a simple matter of a offset superblock, either.
Since these are the formats that the stock recovery expects, I suppose you ought to use those formats if you want to do the "all at once all partitions" fastboot flashing if you plan on using the stock recovery.
Note that there is absolutely nothing that prevents you from unpacking whatever you want from whatever archive format you want - so long as the recovery's busybox supports the archive format correctly - you could use cpio or pax or tar archives for that matter. (The stock recovery's "toolbox" has very little functionality, so this comment applies to custom recoveries, which typically have more robust functionality in their busybox) You will be writing your own scripts to do those things though, typically either in one of two ways:
1.A mount target filesystem partition
1.B do a deep recursive remove at that mountpoint ( rm -rf * )
1.C unpack your archive into same mount point ( tar xf archive.tar, etc)
1.D unmount the mount point
OR
2.A unmount target partition and zero it out (dd if=/dev/zero, flash_erase, etc)
2.B recreate filesystem in partition (mke2fs -t ext4 etc)
2.C mount target filesystem
2.D unpack your archive into the same mount point (tar xf archive, pax, cpio, unyaffs2, etc)
2.E unmount that mountpoint
Even though this post is for the Samsung Galaxy S II, the same thing applies to the factory Nexus 7 images from Google:
http://forum.xda-developers.com/showthread.php?t=1081239
As that thread mentions, the simg2img and mkuserimg.sh programs are part of the Android project.
Here's a Nexus 7 thread where the contributor built the tools for both x86 linux and arm linux
Finally, I should note that because /system is typically mounted read-only, imaging /system from the live OS is no big deal. Trying to do the same thing with /data is an extremely dopey idea, however. Accurate backups are rarely made from live read-write filesystems.
cheers
Thank you so much for all the great information! I hit thanks for both of you.
The link to the nexus 7 thread is what I need... This is for my company, and I need a simple cloning solution that can be performed by a non-technical assembly person. The fastboot install procedure is about as simple as it gets.
Thanks again!

[GUIDE] How to port A system image to AB (system-as-root)

For those with an A/B device, it can be frustrating to wait for GSI maintainers to build A/B variants. Don't worry, it's not too complicated to port A-only system images to A/B.
The difference that matters is that on A-only images, everything in / such as init.rc is in the ramdisk, which is in the boot partition. On A/B devices, the ramdisk is used for recovery instead, so all those files go on the system partition. This partition is actually mounted at / instead of /system. It functions as both the ramdisk and the system partition. This can actually lead to faster boots.
A/B devices also have a different Chrome OS derived updater that supports seamless OTAs to the other slot, but we won't worry about that.
First of all, you will need Linux. This is because Windows just can't handle the extra data we need to preserve, such as POSIX permissions and SELinux contexts.
You are expected to have experience with command-line tools. This is NOT for newbies. You may need to compile a tool.
Steps:
Download an A/B GSI with the same Android version. We will use this image for the root files. (I was able to use an 8.1 base for a 9.0 system with some patches, but YMMV)
Use the simg2img tool to convert the sparse A/B image to a raw one: simg2img system_arm64_ab.img base_ab_raw.img
Use the same tool to convert the A-only image to raw: simg2img system_arm64_a.img system_a_raw.img
Enter a root shell. This is to avoid any problems with permissions. sudo -s
Create the directories to mount the images on: mkdir /mnt/ab; mkdir /mnt/a
Mount the A/B image with flags rw,noatime: mount -o rw,noatime base_ab_raw.img /mnt/ab
Mount the A-only with flags rw,noatime: mount -o rw,noatime system_a_raw.img /mnt/a
Create a system folder in the A-only image: mkdir /mnt/a/system
Set the SELinux context for the system folder: setfattr -n security.selinux -v ubject_r:system_file:s0 /mnt/a/system
Set permissions for the system folder just in case: chmod 755 /mnt/a/system
Delete the system folder in the A/B image: rm -fr /mnt/ab/system
Copy all the root files from A/B to the A-only image. These exact arguments are important to preserve everything. cp -Raf /mnt/ab/* /mnt/a/
Unmount the A/B image: umount /mnt/ab
Unmount the newly transformed A/B image: umount /mnt/a
Convert the new A/B image to sparse format with img2simg: img2simg system_a_raw.img system_arm64_ab_new.img
Flash and enjoy!
If you encounter any errors, the resulting image will most likely not work.
If you have a device with a small system partition that cannot fit the original A-only image you are trying to convert, it will be necessary to create a new, smaller image for the purpose. To create that new image, follow these steps after the ones above:
Create the new raw sparse image: fallocate -l 2G system_ab_raw_small.img
Create an ext4 filesystem on the new image: mkfs.ext4 system_ab_raw_small.img
Mount the new image: mount -o rw,noatime system_ab_raw_small.img /mnt/ab
Mount the old converted A/B image: mount -o ro system_a_raw.img /mnt/a
Copy all the files: cp -Raf /mnt/a/* /mnt/ab/
Unmount the new image: umount /mnt/ab
Unmount the old image: umount /mnt/a
Convert the new image to sparse: img2simg system_ab_raw_small.img system_arm64_ab_new_small.img
Flash and enjoy!
If there's enough demand, I might make a tool to automate this. Let me know what you think.
kdragon said:
For those with an A/B device, it can be frustrating to wait for GSI maintainers to build A/B variants. Don't worry, it's not too complicated to port A-only system images to A/B.
The difference that matters is that on A-only images, everything in / such as init.rc is in the ramdisk, which is in the boot partition. On A/B devices, the ramdisk is used for recovery instead, so all those files go on the system partition. This partition is actually mounted at / instead of /system. It functions as both the ramdisk and the system partition. This can actually lead to faster boots.
A/B devices also have a different Chrome OS derived updater that supports seamless OTAs to the other slot, but we won't worry about that.
First of all, you will need Linux. This is because Windows just can't handle the extra data we need to preserve, such as POSIX permissions and SELinux contexts.
You are expected to have experience with command-line tools. This is NOT for newbies. You will need to compile a few tools.
Steps:
Download an A/B GSI with the same Android version. We will use this image for the root files. (I was able to use an 8.1 base for a 9.0 system with some patches, but YMMV)
Use the same tool to convert the A-only image to raw: simg2img system_arm64_a.img system_a_raw.img
Create the directories to mount the images on: mkdir /mnt/ab; mkdir /mnt/a
Mount the A-only with flags rw,noatime: mount -o rw,noatime system_a_raw.img /mnt/a
Set the SELinux context for the system folder: setfattr -n security.selinux -v ubject_r:system_file:s0 /mnt/a/system
Delete the system folder in the A/B image: rm -fr /mnt/ab/system
Unmount the A/B image: umount /mnt/ab
Convert the new A/B image to sparse format with img2simg: img2simg system_a_raw.img system_arm64_ab_new.img
Create the new raw sparse image: fallocate -l 2G system_ab_raw_small.img
Mount the new image: mount -o rw,noatime system_ab_raw_small.img /mnt/ab
Copy all the files: cp -Raf /mnt/a/* /mnt/ab/
Unmount the old image: umount /mnt/a
Flash and enjoy!
If there's enough demand, I might make a tool to automate this. Let me know what you think.
Click to expand...
Click to collapse
Ab partition of the device can not install Android p, ask God to make a direct brush into the system. Img
yuzui said:
Ab partition of the device can not install Android p, ask God to make a direct brush into the system. Img
Click to expand...
Click to collapse
I am running the Pie PR1 semi-GSI on my A/B device, tissot, right now. If you mean an AOSP GSI, it's available. https://drive.google.com/open?id=1bY5OIbBcy5OyAGlJ45yQ3MhSa8Bjgwg1
If anyone is interested in a root app to convert images, please vote on the poll.
What about A/B to A ? I want to try CosmicDan's MIUI Treble port on my Redmi Note 4
i have sucessfully converted A TO A/B...but when i flash it ..it doesnt boot just stuck at logo..my device in mi A1...can you please tell me that i need to port this file???
hamzaag49 said:
i have sucessfully converted A TO A/B...but when i flash it ..it doesnt boot just stuck at logo..my device in mi A1...can you please tell me that i need to port this file???
Click to expand...
Click to collapse
What ROM is it? I can try to port it.
Most likely your problem is either SELinux being on Enforcing (change it to Permissive in TWRP -> Advanced -> Tissot Manager) or wrong permissions in the image caused by missing a step.
kdrag0n said:
What ROM is it? I can try to port it.
Most likely your problem is either SELinux being on Enforcing (change it to Permissive in TWRP -> Advanced -> Tissot Manager) or wrong permissions in the image caused by missing a step.
Click to expand...
Click to collapse
I'm porting PPP2 SYSTEM.IMG FROM PIXEL XL
Selinux is permissive
hamzaag49 said:
I'm porting PPP2 SYSTEM.IMG FROM PIXEL XL
Selinux is permissive
Click to expand...
Click to collapse
PPP2? That's the old DP2, I think you mean PPR2 (release 2).
It's already been ported by d0gey, download here: https://space-doge.firebaseapp.com/devices/tissot/firmwares/d142afbd-ee0b-486f-8bf7-ac47abd96090
A plain ported Pixel image without patches wouldn't work is because there's a lot of Pixel specific stuff that needs to be patched to work with other devices' vendors.
This would mean the world for a lot of people, if you really going to automate this
Jordan~Kurniawan said:
This would mean the world for a lot of people, if you really going to automate this
Click to expand...
Click to collapse
If I have some free time I'll take a shot at it.
kdrag0n said:
If I have some free time I'll take a shot at it.
Click to expand...
Click to collapse
thanks a lot.
I'm using a macbook, and I really like to try to convert the MIUI rom (https://forum.xda-developers.com/pr...-only-roms/8-1-miui10-project-treble-t3840198) to an A/B rom for my Oneplus6 (Treble, of course). basically I have 2 questions;
- You mention that you NEED linux, is it linux, or is it actually UNIX? (a.k.a. also do-able with MacOS)
- Given the ROM I want to port is using a backup restore method, is one still able to port it to an AB rom?
Even if my goal is not achievable, thank you for creating a guide on how to port. Sharing dev knowledge is the foundation of what drives people to create custom roms!
Skorm92 said:
I'm using a macbook, and I really like to try to convert the MIUI rom (https://forum.xda-developers.com/pr...only-roms/8-1-miui10-project-treble-t3840198) to an A/B rom for my Oneplus6 (Treble, of course). basically I have 2 questions;
- You mention that you NEED linux, is it linux, or is it actually UNIX? (a.k.a. also do-able with MacOS)
- Given the ROM I want to port is using a backup restore method, is one still able to port it to an AB rom?
Even if my goal is not achievable, thank you for creating a guide on how to port. Sharing dev knowledge is the foundation of what drives people to create custom roms!
Click to expand...
Click to collapse
You really NEED Linux. macOS doesn't support ext4, and any third-party driver won't be able to preserve the SELinux xattrs properly.
In that case it's much harder. I'd suggest you try the port on-device in TWRP. Push the reference A/B image to the device and mount it in /mnt, then perform the operations in /system instead of the ROM image mountpoint. You also won't need to create the image at the end. This won't need Linux on your computer because it's all done on the phone.
I used this method to port an A-only OnePlus 6 OxygenOS port to my Mi A1. It booted but not very far because of issues with the port.
kdrag0n said:
You really NEED Linux. macOS doesn't support ext4, and any third-party driver won't be able to preserve the SELinux xattrs properly.
In that case it's much harder. I'd suggest you try the port on-device in TWRP. Push the reference A/B image to the device and mount it in /mnt, then perform the operations in /system instead of the ROM image mountpoint. You also won't need to create the image at the end. This won't need Linux on your computer because it's all done on the phone.
I used this method to port an A-only OnePlus 6 OxygenOS port to my Mi A1. It booted but not very far because of issues with the port.
Click to expand...
Click to collapse
Clear, thanks for the response.
I will try your suggestion, if it boots but fails at certain point, I will find a way to debug it.
The problem primarily on my OP6 is whenever I boot into a treble rom that has issue's, My OP6 is triggerhappy on sending a qualcom kernel panic crash.
Skorm92 said:
Clear, thanks for the response.
I will try your suggestion, if it boots but fails at certain point, I will find a way to debug it.
The problem primarily on my OP6 is whenever I boot into a treble rom that has issue's, My OP6 is triggerhappy on sending a qualcom kernel panic crash.
Click to expand...
Click to collapse
A kernel patch should be able to prevent that, check the custom kernels available.
kdrag0n said:
You really NEED Linux. macOS doesn't support ext4, and any third-party driver won't be able to preserve the SELinux xattrs properly.
In that case it's much harder. I'd suggest you try the port on-device in TWRP. Push the reference A/B image to the device and mount it in /mnt, then perform the operations in /system instead of the ROM image mountpoint. You also won't need to create the image at the end. This won't need Linux on your computer because it's all done on the phone.
I used this method to port an A-only OnePlus 6 OxygenOS port to my Mi A1. It booted but not very far because of issues with the port.
Click to expand...
Click to collapse
You can always give it a shot by creating an ubuntu or alpine container on Docker.
ereneren564 said:
You can always give it a shot by creating an ubuntu or alpine container on Docker.
Click to expand...
Click to collapse
You can't natively have a Docker container on macOS. If you did it'd be inside a Linux VirtualBox VM anyway. I don't think you'd be able to passthrough USB to the container for ADB.
kdrag0n said:
You can't natively have a Docker container on macOS. If you did it'd be inside a Linux VirtualBox VM anyway. I don't think you'd be able to passthrough USB to the container for ADB.
Click to expand...
Click to collapse
As you can copy files to container, you can also copy files from container to host. So your argument is invalid.
docker cp <containerId>:/file/path/within/container /host/path/target
could u make a guide to convert a/b img to a only? thanks

Creating updater.zip for TWRP from partitions or images

Utility to create ROM from images of partitions, partitions themselves, or all this mixed up.
For arm/arm64 devices
(For x86 / x64 devices I will do if there are requests for creation)
For experienced users only who can create and restore backups.
It does not have an interface (work with the command line).
Starting from the terminal emulator in the Android OS (you need a root) or the TWRP terminal.
You can quickly create the installer of partitions: TWRP, boot, edited GSI, vendor + boot for GSI, modem, etc.
Supports sparse images.
USAGE:
Help is invoked by running the utility with no arguments, with the -h --help switches, or appears along with an error message. Content:
Code:
Usage:
romi [<comp>] <out_file> <block or file> [<block or file> ...] [<banner>]
<comp> may take the following values:
--fast faster but bigger size
--norm default with no arg's
--good better compression but longer
--high it takes a very long time
<banner> may take the following values:
--sban=<text file> adds text from the specified file to the beginning of the ROM installation
--eban=<text file> adds text from the specified file to the end of the ROM installation
At least two arguments - the result file (output) and the base file (incoming). And in that order. Example:
Code:
romi /sdcard/twrp-installer.zip /sdcard/recovery.img
If you want to change the default compression level for a session, use one of the keys suggested in the quick reference. Example with minimal compression:
Code:
romi --fast /sdcard/twrp-installer.zip /sdcard/recovery.img
There can be as many objects included in the package in ROM as there is enough space for the selected drive and device capacities to create the resulting file. Example:
Code:
romi /sdcard/stock-mod-installer.zip /sdcard/boot.img /dev/block/bootdevice/by-name/vendor system
In the last example, I will try to explain the "smart" principles of sampling.
As you can see, three objects were transferred for processing: the image file of the drive partition, the drive partition, and the "mask" of the drive partition.
The utility will check for the presence of the file and whether there is a block device of the same name; when creating the ROM, boot.img itself is used.
Check for the presence of a block device and use it when creating a ROM.
Check the "mask" of the partition and, if it finds a block device corresponding to it, add this block to ROM.
Adding banners that will be displayed at the beginning and/or at the end of the installation of the generated ROM:
Code:
romi --fast /sdcard/twrp-installer.zip /sdcard/recovery.img --sban=/sdcard/start-message.txt --eban=/sdcard/end-message.txt
You can add only the initial banner, you can add only the banner to complete the installation, you can both, you can add nothing.
XDA:DevDB Information
romi, Tool/Utility for all devices (see above for details)
Contributors
nonamer1990
Source Code: https://drive.google.com/open?id=12gEApT6yk-5R8p8ymOIOL-5PJSiQa1p-
Version Information
Status: Stable
Current Stable Version: 1.0
Stable Release Date: 2020-05-19
Created 2020-05-19
Last Updated 2020-05-19

Categories

Resources