Use magiskboot to repack the boot partition

Set TW_INCLUDE_REPACKTOOLS := true

Must also have:
AB_OTA_UPDATER := true

Use magiskboot and provide GUI options to allow users to repack
their existing boot image to install TWRP (or kernels) so we can
stop having to provide installation zips for AB devices. There is
also an option to try to fix a recovery bootloop if the kernel
has been patched to always boot the ramdisk for root, etc.

You will need to pull the below repo into external/magisk-prebuilt
https://github.com/TeamWin/external_magisk-prebuilt

Change-Id: I74196cc6f095a7576d61886dc96cbc18deba9b04
diff --git a/partitions.hpp b/partitions.hpp
index c124457..4071b94 100644
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -29,6 +29,9 @@
 
 #define MAX_FSTAB_LINE_LENGTH 2048
 
+#define REPACK_ORIG_DIR "/tmp/repackorig/"
+#define REPACK_NEW_DIR "/tmp/repacknew/"
+
 using namespace std;
 
 // BasePartition is used for overriding so we can run custom, device
@@ -72,6 +75,19 @@
 	char* fstab_line;
 };
 
+enum Repack_Type {
+	REPLACE_NONE = 0,
+	REPLACE_RAMDISK = 1,
+	REPLACE_KERNEL = 2,
+};
+
+struct Repack_Options_struct {
+	Repack_Type Type;
+	bool Backup_First;
+	bool Disable_Verity;
+	bool Disable_Force_Encrypt;
+};
+
 enum PartitionManager_Op {                                                    // PartitionManager Restore Mode for Raw_Read_Write()
 	PM_BACKUP = 0,
 	PM_RESTORE = 1,
@@ -300,7 +316,7 @@
 	int Mount_Settings_Storage(bool Display_Error);                           // Mounts the settings file storage location (usually internal)
 	TWPartition* Find_Partition_By_Path(const string& Path);                  // Returns a pointer to a partition based on path
 	TWPartition* Find_Partition_By_Block_Device(const string& Block_Device);  // Returns a pointer to a partition based on block device
-	int Check_Backup_Name(bool Display_Error);                                // Checks the current backup name to ensure that it is valid
+	int Check_Backup_Name(const std::string& Backup_Name, bool Display_Error, bool Must_Be_Unique); // Checks the current backup name to ensure that it is valid and optionally that a backup with that name doesn't already exist
 	int Run_Backup(bool adbbackup);                                           // Initiates a backup in the current storage
 	int Run_Restore(const string& Restore_Name);                              // Restores a backup
 	bool Write_ADB_Stream_Header(uint64_t partition_count);                   // Write ADB header over twrpbu FIFO
@@ -361,6 +377,9 @@
 	void read_uevent();                                                       // Reads uevent data into a buffer
 	void close_uevent();                                                      // Closes the uevent netlink socket
 	void Add_Partition(TWPartition* Part);                                    // Adds a new partition to the Partitions vector
+	bool Prepare_Repack(TWPartition* Part, const std::string& Temp_Folder_Destination, const bool Create_Backup, const std::string& Backup_Name); // Prepares an image for repacking by unpacking it to the temp folder destination
+	bool Prepare_Repack(const std::string& Source_Path, const std::string& Temp_Folder_Destination, const bool Copy_Source, const bool Create_Destination = true); // Prepares an image for repacking by unpacking it to the temp folder destination
+	bool Repack_Images(const std::string& Target_Image, const struct Repack_Options_struct& Repack_Options); // Repacks the boot image with a new kernel or a new ramdisk
 
 private:
 	void Setup_Settings_Storage_Partition(TWPartition* Part);                 // Sets up settings storage
@@ -373,6 +392,7 @@
 	void Post_Decrypt(const string& Block_Device);                            // Completes various post-decrypt tasks
 	void Coldboot_Scan(std::vector<string> *sysfs_entries, const string& Path, int depth); // Scans subfolders to find matches to the paths stored in sysfs_entries so we can trigger the uevent system to "re-add" devices
 	void Coldboot();                                                          // Starts the scan of the /sys/block folder
+	bool Prepare_Empty_Folder(const std::string& Folder);                     // Creates an empty folder at Folder. If the folder already exists, the folder is deleted, then created
 	pid_t mtppid;
 	bool mtp_was_enabled;
 	int mtp_write_fd;