1 | #!/bin/bash␊ |
2 | ␊ |
3 | echo "==============================================="␊ |
4 | echo "Check Previous Chameleon: Will there be problems?"␊ |
5 | echo "***********************************************"␊ |
6 | ␊ |
7 | # Checks for another existing Chameleon installation on the same disk␊ |
8 | # and tries to make sure the user doesn't end up with an un-bootable␊ |
9 | # system due to having installed Chameleon previously elsewhere.␊ |
10 | ␊ |
11 | # Called from the Standard/postinstall and EFI/postinstall scripts␊ |
12 | # /Volumes/EFI should already be mounted before this is called.␊ |
13 | ␊ |
14 | # Receives targetDisk: for example, /dev/disk3.␊ |
15 | # Receives targetDeviceRaw: for example, /dev/rdisk3s1.␊ |
16 | # Receives targetDevice: Stores device number, for example /dev/disk2s1.␊ |
17 | # Receives installerVolume: Volume to write the installer log to.␊ |
18 | # Receives scriptDir: The location of the main script dir.␊ |
19 | ␊ |
20 | if [ "$#" -eq 5 ]; then␊ |
21 | ␉targetDisk="$1"␊ |
22 | ␉targetDeviceRaw="$2"␊ |
23 | ␉targetDevice="$3"␊ |
24 | ␉installerVolume="$4"␊ |
25 | ␉scriptDir="$5"␊ |
26 | ␉echo "DEBUG: passed argument for targetDisk = $targetDisk"␊ |
27 | ␉echo "DEBUG: passed argument for targetDeviceRaw = $targetDeviceRaw"␊ |
28 | ␉echo "DEBUG: passed argument for targetDevice = $targetDevice"␊ |
29 | ␉echo "DEBUG: passed argument for installerVolume = $installerVolume"␊ |
30 | ␉echo "DEBUG: passed argument for scriptDir = $scriptDir"␊ |
31 | else␊ |
32 | ␉echo "Error - wrong number of values passed"␊ |
33 | ␉exit 9␊ |
34 | fi␊ |
35 | ␊ |
36 | ␊ |
37 | # ===============================================␊ |
38 | # Prepare some vars␊ |
39 | # ===============================================␊ |
40 | sliceNumber=$( echo ${targetDeviceRaw#*disk*s} )␊ |
41 | ␊ |
42 | # strip slice from end␊ |
43 | targetDiskRawNoSlice=$( echo ${targetDeviceRaw%$sliceNumber} )␊ |
44 | ␊ |
45 | # Are there any other partitions on the disk?␊ |
46 | # How many actual partitions are there?␊ |
47 | numSlices=$(( $( diskutil list | grep $( echo ${targetDisk#/dev/} ) | sed -n '$=' ) -2 ))␊ |
48 | ␊ |
49 | ␊ |
50 | # ===============================================␊ |
51 | # Checking the disk for existing Chameleon installations␊ |
52 | # if there is more than one partition on the disk.␊ |
53 | # ===============================================␊ |
54 | if [ $numSlices -gt 1 ]; then ␊ |
55 | ␉"$scriptDir"InstallLog.sh "${installerVolume}" "LineBreak"␊ |
56 | ␉"$scriptDir"InstallLog.sh "${installerVolume}" "Checking for previous chameleon installations on ${targetDisk#/dev/}"␊ |
57 | ␊ |
58 | ␉# Check the disk's MBR for existing stage 0 boot code (code from CheckDiskMicrocode.sh script)␊ |
59 | ␉stage0type=$( dd 2>/dev/null if="$targetDisk" count=3 bs=1 skip=105 | xxd | awk '{print $2$3}' )␊ |
60 | ␉if [ "${stage0type}" == "0a803c" ] || [ "${stage0type}" == "ee7505" ] || [ "${stage0type}" == "742b80" ]; then␊ |
61 | ␉␉stage0type=2␊ |
62 | ␉elif [ "${stage0type}" == "0b807c" ]; then␊ |
63 | ␉␉stage0type=1␊ |
64 | ␉fi␊ |
65 | ␉␊ |
66 | ␉#Scan all partitions for Chameleon code␊ |
67 | ␉for (( i=1; i <= $numSlices; i++ ));␊ |
68 | ␉do␊ |
69 | ␉␉if [ $stage0type == 1 ] || [ $stage0type == 2 ]; then␊ |
70 | ␉␉␉stagesFound=1␊ |
71 | ␉␉else␊ |
72 | ␉␉␉stagesFound=0␊ |
73 | ␉␉fi␊ |
74 | ␉␉stage1Existence="NONE"␊ |
75 | ␉␉stage2Existence=0␊ |
76 | ␉␉targetDiskRaw=$targetDiskRawNoSlice$i␊ |
77 | ␉␉␉␉␉␊ |
78 | ␉␉# Check for existence of a bootable partition boot sector containing either boot1h or boot1f32␊ |
79 | ␉␉boot1Search=$( dd 2>/dev/null if="$targetDiskRaw" count=1 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' )␊ |
80 | ␉␉if [ "${boot1Search:0:16}" == "fa31c08ed0bcf0ff" ] && [ "${boot1Search:1020:2}" == "55" ]; then␊ |
81 | ␉␉␉(( stagesFound++ ))␊ |
82 | ␉␉␉stage1Existence="boot1h"␊ |
83 | ␉␉elif [ "${boot1Search:0:4}" == "e962" ] && [ "${boot1Search:180:12}" == "424f4f542020" ] && [ "${boot1Search:1020:2}" == "55" ]; then␊ |
84 | ␉␉␉(( stagesFound++ ))␊ |
85 | ␉␉␉stage1Existence="boot1f32"␊ |
86 | ␉␉fi␊ |
87 | ␉␉␊ |
88 | ␉␉# Check for existing stage 2 boot file.␊ |
89 | ␉␉# Include checking the EFI system partition if it exists and is mounted.␊ |
90 | ␉␉if [ -e "$( df | grep ${targetDisk}s${i} | awk '{ print $6 }' )"/boot ]; then␊ |
91 | ␉␉␉(( stagesFound++ ))␊ |
92 | ␉␉␉stage2Existence=1␊ |
93 | ␉␉fi␊ |
94 | ␉␉␉␉␉␊ |
95 | ␉␉if [ $stagesFound -ge 2 ] && [ "$stage1Existence" != "NONE" ] && [ $i -ne $sliceNumber ]; then␊ |
96 | ␉␉␉# There is previous Chameleon stage 1 code on a partition boot sector,␊ |
97 | ␉␉␉# and either a complete or incomplete installation (ie. boot0 or boot are missing).␊ |
98 | ␉␉␉␊ |
99 | ␉␉␉if [ $stagesFound == 3 ] && [ $i -lt $sliceNumber ]; then␊ |
100 | ␉␉␉␉# Exisitng installation found which will still be default.␊ |
101 | ␉␉␉␉message="************************** TAKE NOTE *****************************␊ |
102 | **** There is an existing Chameleon installation on $targetDiskRaw␊ |
103 | **** and that installation will still be the default loader as it's␊ |
104 | **** on an earlier partition. If you want this new installation on␊ |
105 | **** $installerVolume to be default then you will need to remove the␊ |
106 | **** boot file from $targetDiskRaw and re-run this installer.␊ |
107 | **************************************************************"␊ |
108 | ␉␉␉␉"$scriptDir"InstallLog.sh "${installerVolume}" "${message}"␊ |
109 | ␉␉␉fi␊ |
110 | ␉␉␉if [ $stagesFound == 3 ] && [ $i -gt $sliceNumber ]; then␊ |
111 | ␉␉␉␉# Exisitng installation found which will no longer be default.␊ |
112 | ␉␉␉␉message="NOTE: There is an existing Chameleon installation on $targetDiskRaw␊ |
113 | NOTE: but this installation on $targetDevice will be the default loader␊ |
114 | NOTE: because you're installing to an earlier partition on the disk."␊ |
115 | ␉␉␉␉"$scriptDir"InstallLog.sh "${installerVolume}" "${message}"␊ |
116 | ␉␉␉fi␊ |
117 | ␉␉␉␊ |
118 | ␉␉␉␊ |
119 | ␉␉␉# User could see a b1f:error or boot0:error if the following conditions are true:␊ |
120 | ␉␉␉# A) Boot0hfs, Boot0md or Boot0md (dmazar's Boot0workV2) is being used.␊ |
121 | ␉␉␉# B) The previous stage 1 code is on a lower partiton than the one being installed to now.␊ |
122 | ␉␉␉# C) boot is missing from that partition.␊ |
123 | ␊ |
124 | ␉␉␉if [ $stagesFound == 2 ] && [ $stage2Existence == 0 ]; then␊ |
125 | ␉␉␉␉# Exisitng boot0 and boot1 only found - missing boot␊ |
126 | ␉␉␉␉"$scriptDir"InstallLog.sh "${installerVolume}" "INFO: Found $stage1Existence installed to ${targetDisk}s${i}"␊ |
127 | ␉␉␉␉␉␉␉␊ |
128 | ␉␉␉␉# stage0type=2 is used to know if 'A' is true.␊ |
129 | ␉␉␉␉if [ $stage0type == 2 ]; then␊ |
130 | ␉␉␉␉␉# i = current slice we're checking, slicenumber = slice trying to install to.␊ |
131 | ␉␉␉␉␉if [ $i -lt $sliceNumber ]; then␊ |
132 | ␉␉␉␉␉␉"$scriptDir"InstallLog.sh "${installerVolume}" "WARN: Conditions point to the possibility of a boot failure"␊ |
133 | ␊ |
134 | ␉␉␉␉␉␉# Fix by making previous parition bootsector un-bootable␉␊ |
135 | ␉␉␉␉␉␉message="---␊ |
136 | FIX: Make ${targetDisk}s${i} boot sector un-bootable by changing byte 1FEh to 00.␊ |
137 | NOTE: Any Extra folder you had there will still be there. If you want to use␊ |
138 | NOTE: ${targetDisk}s${i} again as your boot partition then re-run this installer␊ |
139 | NOTE: selecting it as the target, ONLY choosing the 'Chameleon Bootloader' option␊ |
140 | NOTE: and NONE of the other options.␊ |
141 | ---"␊ |
142 | ␉␉␉␉␉␉"$scriptDir"InstallLog.sh "${installerVolume}" "${message}"␊ |
143 | ␉␉␉␉␉␉␊ |
144 | ␉␉␉␉␉␉# /Volumes/EFI needs unmounting before changing partition boot sector␊ |
145 | ␉␉␉␉␉␉if [ $i == 1 ]; then␊ |
146 | ␉␉␉␉␉␉␉umount /Volumes/EFI␊ |
147 | ␉␉␉␉␉␉else␊ |
148 | ␉␉␉␉␉␉␉diskutil unmount "${targetDisk}"s${i}␊ |
149 | ␉␉␉␉␉␉fi␊ |
150 | ␉␉␉␉␉␉␉␉␉␉␉␉␊ |
151 | ␉␉␉␉␉␉# Change Byte 01FExh to 00 (510 decimal)␊ |
152 | ␉␉␉␉␉␉# Same code can be used for HFS or FAT32␊ |
153 | ␉␉␉␉␉␉dd if=${targetDisk}s${i} count=1 bs=512 of=/tmp/originalBootSector␊ |
154 | ␉␉␉␉␉␉cp /tmp/originalBootSector /tmp/newBootSector␊ |
155 | ␉␉␉␉␉␉dd if="$scriptDir/patch" of=/tmp/newBootSector bs=1 count=1 seek=510 conv=notrunc␊ |
156 | ␉␉␉␉␉␉dd if=/tmp/newBootSector of=${targetDisk}s${i} count=1 bs=512␊ |
157 | ␉␉␉␉␉␉␊ |
158 | ␉␉␉␉␉␉# /Volumes/EFI needs re-mounting so EFI/postinstall script can use it.␊ |
159 | ␉␉␉␉␉␉# Don't check for a GPT as wouldn't have got here if it wasn't␊ |
160 | ␉␉␉␉␉␉if [ $i == 1 ]; then␊ |
161 | ␉␉␉␉␉␉␉"$scriptDir"MountESP.sh "${targetDisk}" "${installerVolume}" "${scriptDir}"␊ |
162 | ␉␉␉␉␉␉else␊ |
163 | ␉␉␉␉␉␉␉diskutil mount "${targetDisk}"s${i}␊ |
164 | ␉␉␉␉␉␉fi␊ |
165 | ␉␉␉␉␉␉␊ |
166 | ␉␉␉␉␉else␊ |
167 | ␉␉␉␉␉␉"$scriptDir"InstallLog.sh "${installerVolume}" "INFO: but won't interfere as you're installing to an earlier partition."␊ |
168 | ␉␉␉␉␉fi␊ |
169 | ␉␉␉␉elif [ $stage0type == 1 ]; then␊ |
170 | ␉␉␉␉␉# boot0 was found which looks for boot1 on the first active partition.␊ |
171 | ␉␉␉␉␉"$scriptDir"InstallLog.sh "${installerVolume}" "NOTE: so select to boot that partition (if used) with active flag."␊ |
172 | ␉␉␉␉#else␊ |
173 | ␉␉␉␉␉#echo "DEBUG: Boot0 not found"␊ |
174 | ␉␉␉␉fi␊ |
175 | ␉␉␉fi␊ |
176 | ␉␉fi␊ |
177 | ␉␉␊ |
178 | ␉done␊ |
179 | #else␊ |
180 | ␉#echo "DEBUG: Just one slice"␊ |
181 | fi␊ |
182 | ␊ |
183 | exit 0 |