#!/bin/bash

echo "==============================================="
echo "Check Previous Chameleon: Will there be problems?"
echo "***********************************************"

# Checks for another existing Chameleon installation on the same disk
# and tries to make sure the user doesn't end up with an un-bootable
# system due to having installed Chameleon previously elsewhere.

# Called from the Standard/postinstall and EFI/postinstall scripts
# /Volumes/EFI should already be mounted before this is called.

# Receives targetDisk: for example, /dev/disk3.
# Receives targetDeviceRaw: for example, /dev/rdisk3s1.
# Receives targetDevice: Stores device number, for example /dev/disk2s1.
# Receives installerVolume: Volume to write the installer log to.
# Receives scriptDir: The location of the main script dir.

if [ "$#" -eq 5 ]; then
	targetDisk="$1"
	targetDeviceRaw="$2"
	targetDevice="$3"
	installerVolume="$4"
	scriptDir="$5"
	echo "DEBUG: passed argument for targetDisk = $targetDisk"
	echo "DEBUG: passed argument for targetDeviceRaw = $targetDeviceRaw"
	echo "DEBUG: passed argument for targetDevice = $targetDevice"
	echo "DEBUG: passed argument for installerVolume = $installerVolume"
	echo "DEBUG: passed argument for scriptDir = $scriptDir"
else
	echo "Error - wrong number of values passed"
	exit 9
fi


# ===============================================
# Prepare some vars
# ===============================================
sliceNumber=$( echo ${targetDeviceRaw#*disk*s} )

# strip slice from end
targetDiskRawNoSlice=$( echo ${targetDeviceRaw%$sliceNumber} )

# Are there any other partitions on the disk?
# How many actual partitions are there?
numSlices=$(( $( diskutil list | grep $( echo ${targetDisk#/dev/} ) | sed -n '$=' ) -2 ))


# ===============================================
# Checking the disk for existing Chameleon installations
# if there is more than one partition on the disk.
# ===============================================
if [ $numSlices -gt 1 ]; then 
	"$scriptDir"InstallLog.sh "${installerVolume}" "Checking ${targetDisk#/dev/}."

	# Check the disk's MBR for existing stage 0 boot code (code from CheckDiskMicrocode.sh script)
	stage0type=$( dd 2>/dev/null if="$targetDisk" count=3 bs=1 skip=105 | xxd | awk '{print $2$3}' )
	if [ "${stage0type}" == "0a803c" ] || [ "${stage0type}" == "ee7505" ] || [ "${stage0type}" == "742b80" ]; then
		stage0type=2
	elif [ "${stage0type}" == "0b807c" ]; then
		stage0type=1
	fi
	
	#Scan all partitions for Chameleon code
	cleanRun=1
	for (( i=1; i <= $numSlices; i++ ));
	do
		if [ $stage0type == 1 ] || [ $stage0type == 2 ]; then
			stagesFound=1
		else
			stagesFound=0
		fi
		stage1Existence="NONE"
		stage2Existence=0
		targetDiskRaw=$targetDiskRawNoSlice$i
					
		# Check for existence of a bootable partition boot sector containing either boot1h or boot1f32
		boot1Search=$( dd 2>/dev/null if="$targetDiskRaw" count=1 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' )
		if [ "${boot1Search:0:16}" == "fa31c08ed0bcf0ff" ] && [ "${boot1Search:1020:2}" == "55" ]; then
			(( stagesFound++ ))
			stage1Existence="boot1h"
		elif [ "${boot1Search:0:4}" == "e962" ] && [ "${boot1Search:180:12}" == "424f4f542020" ] && [ "${boot1Search:1020:2}" == "55" ]; then
			(( stagesFound++ ))
			stage1Existence="boot1f32"
		fi
		
		# Check for existing stage 2 boot file.
		# Include checking the EFI system partition if it exists and is mounted.
		if [ -e "$( df | grep ${targetDisk}s${i} | awk '{ print $6 }' )"/boot ]; then
			(( stagesFound++ ))
			stage2Existence=1
		fi
					
		if [ $stagesFound -ge 2 ] && [ "$stage1Existence" != "NONE" ] && [ $i -ne $sliceNumber ]; then
			# There is previous Chameleon stage 1 code on a partition boot sector,
			# and either a complete or incomplete installation (ie. boot0 or boot are missing).
			
			if [ $stagesFound == 3 ] && [ $i -lt $sliceNumber ]; then
				# Exisitng installation found which will still be default.
				message="************************** TAKE NOTE *****************************
**** There is an existing Chameleon installation on $targetDiskRaw
**** and that installation will still be the default loader as it's
**** on an earlier partition. If you want this new installation on
**** $installerVolume to be default then you will need to remove the
**** boot file from $targetDiskRaw and re-run this installer.
**************************************************************"
				"$scriptDir"InstallLog.sh "${installerVolume}" "${message}"
			fi
			if [ $stagesFound == 3 ] && [ $i -gt $sliceNumber ]; then
				# Existing installation found which will no longer be default.
				message="NOTE: There is an existing Chameleon installation on $targetDiskRaw
NOTE: but this installation on $targetDevice will be the default loader
NOTE: because you're installing to an earlier partition on the disk."
				"$scriptDir"InstallLog.sh "${installerVolume}" "${message}"
			fi
			
			
			# User could see a b1f:error or boot0:error if the following conditions are true:
			# A) Boot0hfs, Boot0md or Boot0md (dmazar's Boot0workV2) is being used.
			# B) The previous stage 1 code is on a lower partiton than the one being installed to now.
			# C) boot is missing from that partition.

			if [ $stagesFound == 2 ] && [ $stage2Existence == 0 ]; then
				# Exisitng boot0 and boot1 only found - missing boot
				"$scriptDir"InstallLog.sh "${installerVolume}" "INFO: Found $stage1Existence installed to ${targetDisk}s${i}"
							
				# stage0type=2 is used to know if 'A' is true.
				if [ $stage0type == 2 ]; then
					# i = current slice we're checking, slicenumber = slice trying to install to.
					if [ $i -lt $sliceNumber ]; then
						"$scriptDir"InstallLog.sh "${installerVolume}" "WARN: Conditions point to the possibility of a boot failure"

						# Fix by making previous parition bootsector un-bootable	
						message="---
FIX: Make ${targetDisk}s${i} boot sector un-bootable by changing byte 1FEh to 00.
NOTE: Any Extra folder you had there will still be there. If you want to use
NOTE: ${targetDisk}s${i} again as your boot partition then re-run this installer
NOTE: selecting it as the target, ONLY choosing the 'Chameleon Bootloader' option
NOTE: and NONE of the other options.
---"
						"$scriptDir"InstallLog.sh "${installerVolume}" "${message}"
						
						# /Volumes/EFI needs unmounting before changing partition boot sector
						if [ $i == 1 ]; then
							umount /Volumes/EFI
						else
							diskutil unmount "${targetDisk}"s${i}
						fi
												
						# Change Byte 01FExh to 00 (510 decimal)
						# Same code can be used for HFS or FAT32
						dd if=${targetDisk}s${i} count=1 bs=512 of=/tmp/originalBootSector
						cp /tmp/originalBootSector /tmp/newBootSector
						dd if="$scriptDir/patch" of=/tmp/newBootSector bs=1 count=1 seek=510 conv=notrunc
						dd if=/tmp/newBootSector of=${targetDisk}s${i} count=1 bs=512
						
						# /Volumes/EFI needs re-mounting so EFI/postinstall script can use it.
						# Don't check for a GPT as wouldn't have got here if it wasn't
						if [ $i == 1 ]; then
							"$scriptDir"MountESP.sh "${targetDisk}" "${installerVolume}" "${scriptDir}"
						else
							diskutil mount "${targetDisk}"s${i}
						fi
						
					else
						"$scriptDir"InstallLog.sh "${installerVolume}" "INFO: but won't interfere as you're installing to an earlier partition."
					fi
				elif [ $stage0type == 1 ]; then
					# boot0 was found which looks for boot1 on the first active partition.
					"$scriptDir"InstallLog.sh "${installerVolume}" "NOTE: so select to boot that partition (if used) with active flag."
				#else
					#echo "DEBUG: Boot0 not found"
				fi
			fi
		else
			(( cleanRun++ ))
		fi
	done
	if [[ $cleanRun == $i ]]; then
		"$scriptDir"InstallLog.sh "${installerVolume}" "Nothing found that could cause any problems."
	fi
else
	"$scriptDir"InstallLog.sh "${installerVolume}" "Nothing to check as there's only one partition."
fi

exit 0
