1 | #!/bin/bash␊ |
2 | ␊ |
3 | diskloader="/usr/standalone/i386/boot0"␊ |
4 | partitionloader="/usr/standalone/i386/boot1h"␊ |
5 | filesystemloader="/usr/standalone/i386/boot"␊ |
6 | bootervolumename="EFI"␊ |
7 | booterextensions="Extra/Extensions"␊ |
8 | ␊ |
9 | bootresources="${0%/*}"␊ |
10 | ␊ |
11 | diskmicrocodetype[1]="GRUB,47525542"␊ |
12 | diskmicrocodetype[2]="LILO,4c494c4f"␊ |
13 | ␊ |
14 | start ()␊ |
15 | {␊ |
16 | # $1 volume␊ |
17 | ␊ |
18 | osxvolume="${@}"␊ |
19 | ␊ |
20 | if [ -z "${osxvolume}" ]; then␊ |
21 | ␉echo␊ |
22 | ␉echo "Cannot find the volume. Exiting."␊ |
23 | ␉exit␊ |
24 | fi␊ |
25 | ␊ |
26 | bootdev=$( df "${osxvolume}" | sed -n '2p' | awk '{print $1}' )␊ |
27 | ␊ |
28 | if [ "${bootdev}" = "${bootdev#*disk*s}" ]; then␊ |
29 | ␉echo␊ |
30 | ␉echo "ERROR Volume does not use slices."␊ |
31 | ␉echo "Volume may be stored on a RAID array."␊ |
32 | ␉echo␊ |
33 | ␉exit␊ |
34 | fi␊ |
35 | ␊ |
36 | partitiontable=$( dd 2>/dev/null if=${bootdev%s*} count=1 skip=1 | dd 2>/dev/null count=8 bs=1 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' )␊ |
37 | if [ "${partitiontable:0:16}" == "4546492050415254" ]; then␉␊ |
38 | ␉partitiontable=$( dd 2>/dev/null if=${bootdev%s*} count=1 | dd 2>/dev/null count=64 bs=1 skip=446 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' )␊ |
39 | ␉if [ "${partitiontable:8:2}" == "ee" ]; then␊ |
40 | ␉␉if [ "${partitiontable:40:2}" == "00" ] && [ "${partitiontable:72:2}" == "00" ] && [ "${partitiontable:104:2}" == "00" ]; then␊ |
41 | ␉␉␉partitiontable="GPT"␊ |
42 | ␉ ␉else␊ |
43 | ␉␉␉partitiontable="GPT/MBR"␊ |
44 | ␉␉fi␊ |
45 | ␉fi␊ |
46 | else␊ |
47 | ␉echo␊ |
48 | ␉echo "ERROR Volume is not on a GPT partitioned disc."␊ |
49 | ␉echo␊ |
50 | ␉exit␊ |
51 | fi␊ |
52 | ␊ |
53 | echo "${partitiontable} found."␊ |
54 | ␊ |
55 | echo "OS X Volume is ${osxvolume}"␊ |
56 | echo "OX X Volume device is ${bootdev}"␊ |
57 | ␊ |
58 | bootvolume="/Volumes/$bootervolumename"␊ |
59 | bootdev=${bootdev%s*}s1␊ |
60 | bootrdev=${bootdev/disk/rdisk}␊ |
61 | bootdisk=${bootdev%s*}␊ |
62 | bootrdisk=${bootdisk/disk/rdisk}␊ |
63 | bootslice=${bootdev#*disk*s}␊ |
64 | ␊ |
65 | echo "EFI Volume device is ${bootdev}"␊ |
66 | echo "EFI Volume raw device is ${bootrdev}"␊ |
67 | echo "EFI Volume slice is ${bootslice}"␊ |
68 | echo "Disk device is ${bootdisk}"␊ |
69 | echo "Disk raw device is ${bootrdisk}"␊ |
70 | echo "Disk loader is ${diskloader}"␊ |
71 | echo "Partition loader is ${partitionloader}"␊ |
72 | echo "Filesystem loader is ${filesystemloader}"␊ |
73 | ␊ |
74 | }␊ |
75 | ␊ |
76 | checkdiskmicrocodetype ()␊ |
77 | {␊ |
78 | diskmicrocode=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=1 bs=437 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' )␊ |
79 | ␊ |
80 | diskmicrocodetypecounter=0␊ |
81 | while [ ${diskmicrocodetypecounter} -lt ${#diskmicrocodetype[@]} ]; do␊ |
82 | diskmicrocodetypecounter=$(( ${diskmicrocodetypecounter} + 1 ))␊ |
83 | diskmicrocodetypeid=${diskmicrocodetype[${diskmicrocodetypecounter}]#*,}␊ |
84 | if [ ! "${diskmicrocode}" = "${diskmicrocode/${diskmicrocodetypeid}/}" ]; then␊ |
85 | echo "${diskmicrocodetype[${diskmicrocodetypecounter}]%,*} found."␊ |
86 | fi␊ |
87 | done␊ |
88 | }␊ |
89 | ␊ |
90 | checkdiskmicrocode ()␊ |
91 | {␊ |
92 | # 1 action ( check or set )␊ |
93 | ␊ |
94 | diskmicrocode=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=1 bs=437 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' )␊ |
95 | diskmicrocodemd5=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=1 bs=437 | md5 )␊ |
96 | ␊ |
97 | if [ $( echo "${diskmicrocode}" | awk -F0 '{print NF-1}' ) = 874 ]; then␊ |
98 | ␉if [ "${1}" = "set" ]; then␊ |
99 | ␉␉echo "No disk microcode found. Updating."␊ |
100 | ␉␉diskupdate=true␊ |
101 | ␉else␊ |
102 | ␉␉echo "No disk microcode found."␊ |
103 | ␉fi␊ |
104 | else␊ |
105 | ␉if [ ${1} = set ]; then␊ |
106 | ␉␉echo "Disk microcode found. Preserving."␊ |
107 | ␉else␊ |
108 | ␉␉echo "Disk microcode found."␊ |
109 | ␉fi␊ |
110 | ␉echo "Disk microcode MD5 is ${diskmicrocodemd5}"␊ |
111 | fi␊ |
112 | }␊ |
113 | ␊ |
114 | checkdisksignature ()␊ |
115 | {␊ |
116 | disksignature=$( dd 2>/dev/null if=${bootdisk} count=1 | dd 2>/dev/null count=4 bs=1 skip=440 | perl -ne '@a=split"";for(@a){printf"%02x",ord}' )␊ |
117 | ␊ |
118 | if [ $( echo "${disksignature}" | awk -F0 '{print NF-1}' ) = 8 ]; then␊ |
119 | ␉echo "No disk signature found."␊ |
120 | else␊ |
121 | ␉echo "Disk signature found."␊ |
122 | ␉echo "Disk signature is 0x${disksignature}"␊ |
123 | fi␊ |
124 | }␊ |
125 | ␊ |
126 | checkpartitionbootcode ()␊ |
127 | {␊ |
128 | # 1 action ( check or set )␊ |
129 | ␊ |
130 | partitionbootcode=$( dd if=${bootrdev} count=1 2>/dev/null | perl -ne '@a=split"";for(@a){printf"%02x",ord}' )␊ |
131 | partitionbootcodeextended=$( dd if=${bootrdev} count=1 skip=1 2>/dev/null | perl -ne '@a=split"";for(@a){printf"%02x",ord}' )␊ |
132 | ␊ |
133 | if [ $( echo "${partitionbootcode}" | awk -F0 '{print NF-1}' ) = 1024 ]; then␊ |
134 | ␉if [ "${1}" = "set" ]; then␊ |
135 | ␉␉echo "No partition bootcode found. Updating."␊ |
136 | ␉else␊ |
137 | ␉␉echo "No partition bootcode found."␊ |
138 | ␉fi␊ |
139 | else␊ |
140 | ␉if [ "${1}" = "set" ]; then␊ |
141 | ␉␉echo "Partition bootcode found. Overwriting."␊ |
142 | ␉else␊ |
143 | ␉␉echo "Partition bootcode found."␊ |
144 | ␉fi␊ |
145 | ␉if [ $( echo "${partitionbootcodeextended}" | awk -F0 '{print NF-1}' ) = 1024 ]; then␊ |
146 | ␉␉partitionbootcodemd5=$( dd 2>/dev/null if=${bootrdev} count=1 | md5 )␊ |
147 | ␉else␊ |
148 | ␉␉partitionbootcodemd5=$( dd 2>/dev/null if=${bootrdev} count=2 | md5 )␊ |
149 | ␉␉echo "Partition bootcode is dual sector."␊ |
150 | ␉fi␊ |
151 | ␉echo "Partition bootcode MD5 is ${partitionbootcodemd5}"␊ |
152 | fi␊ |
153 | }␊ |
154 | ␊ |
155 | checkpartitionactive ()␊ |
156 | {␊ |
157 | partitionactive=$( fdisk -d ${bootrdisk} | grep -n "*" | awk -F: '{print $1}')␊ |
158 | ␊ |
159 | if [ -n "${partitionactive}" ]; then ␊ |
160 | ␉echo "Partition flagged active is ${partitionactive}"␊ |
161 | else␊ |
162 | ␉echo "No partition flagged active."␊ |
163 | fi␊ |
164 | ␊ |
165 | }␊ |
166 | ␊ |
167 | start ${3}␊ |
168 | ␊ |
169 | if [ "$( df | grep ${bootdev} )" ]; then␊ |
170 | ␉umount -f ${bootdev}␊ |
171 | fi ␊ |
172 | ␊ |
173 | if ! [ "$( fstyp ${bootdev} | grep hfs )" ]; then␊ |
174 | ␉echo "${bootdev} isn't a HFS partition"␊ |
175 | ␉echo "Executing command: newfs_hfs -v ${bootervolumename} ${bootdev}"␊ |
176 | ␉newfs_hfs -v "${bootervolumename}" "${bootdev}"␊ |
177 | else␊ |
178 | ␉echo "${bootdev} is already a HFS partition (skipping)"␊ |
179 | fi␊ |
180 | ␊ |
181 | diskupdate=false␊ |
182 | checkdiskmicrocodetype␊ |
183 | checkdiskmicrocode set␊ |
184 | checkdisksignature␊ |
185 | checkpartitionbootcode set␊ |
186 | checkpartitionactive␊ |
187 | ␊ |
188 | if ${diskupdate}; then␊ |
189 | ␉echo "Executing command: fdisk -u -f ${diskloader} -y ${bootdisk}"␊ |
190 | ␉fdisk -u -f "${osxvolume}/${diskloader}" -y ${bootdisk}␊ |
191 | fi␊ |
192 | ␊ |
193 | echo "Executing command: dd if=${partitionloader} of=${bootrdev}"␊ |
194 | dd if="${osxvolume}/${partitionloader}" of=${bootrdev}␊ |
195 | ␊ |
196 | # If table is GPT make the first partition active (BadAxe compatibility).␊ |
197 | [ "${partitiontable}" = "GPT" ] && bootslice=1␊ |
198 | if [[ "${partitiontable}" = "GPT" ]]; then␊ |
199 | ␉fdisk -e ${bootdisk} <<-MAKEACTIVE␊ |
200 | ␉print␊ |
201 | ␉flag ${bootslice}␊ |
202 | ␉write␊ |
203 | ␉y␊ |
204 | ␉quit␊ |
205 | ␉MAKEACTIVE␊ |
206 | fi␊ |
207 | ␊ |
208 | checkdiskmicrocode check␊ |
209 | checkdisksignature␊ |
210 | checkpartitionbootcode check␊ |
211 | checkpartitionactive␊ |
212 | ␊ |
213 | [ -d "${bootvolume}" ] || mkdir -p "${bootvolume}"␊ |
214 | echo "Executing command: mount_hfs ${bootdev} ${bootvolume}"␊ |
215 | mount_hfs "${bootdev}" "${bootvolume}"␊ |
216 | ␊ |
217 | echo "Executing command: cp ${osxvolume}${filesystemloader} ${bootvolume}/boot"␊ |
218 | cp "${osxvolume}${filesystemloader}" "${bootvolume}/boot"␊ |
219 | ␊ |
220 | if ! [ -d "${bootvolume}/Extra/Extensions" ]; then␊ |
221 | ␉echo "Executing command: mkdir -p ${bootvolume}/Extra/Extensions"␊ |
222 | ␉mkdir -p "${bootvolume}/Extra/Extensions"␊ |
223 | fi␊ |
224 | # unpack any existing Extensions.mkext already on the booter volume␊ |
225 | if [ -e "${bootvolume}/Extra/Extensions.mkext" ]; then␊ |
226 | ␉echo "Executing command: mkextunpack -d ${bootvolume}/Extra/Extensions ${bootvolume}/Extra/Extensions.mkext"␊ |
227 | ␉mkextunpack -d "${bootvolume}/Extra/Extensions" "${bootvolume}/Extra/Extensions.mkext"␊ |
228 | ␉echo "Executing command: rm -R -f ${bootvolume}/Extra/Extensions.mkext"␊ |
229 | ␉rm -R -f "${bootvolume}/Extra/Extensions.mkext"␊ |
230 | fi␉␊ |
231 | ␊ |
232 | # copy existing /Extra␊ |
233 | if [ -d "${2}/Extra" ]; then␊ |
234 | ␉[ -d "${bootvolume}/Extra/Extensions" ] || mkdir -p "${bootvolume}/Extra/Extensions"␊ |
235 | ␉echo "Executing command: find ${2}/Extra -name '*.plist' -depth 1 -exec cp -f {} ${bootvolume}/Extra \;"␊ |
236 | ␉find "${2}/Extra" -name '*.plist' -depth 1 -exec cp -f {} "${bootvolume}/Extra/" \;␊ |
237 | ␉if [ -f "${2}/Extra/Extensions.mkext" ]; then␊ |
238 | ␉␉echo "Executing command: mkextunpack -d ${2}/Extra/Extensions ${2}/Extra/Extensions.mkext"␊ |
239 | ␉␉mkextunpack -d "${bootvolume}/Extra/Extensions" "${2}/Extra/Extensions.mkext"␊ |
240 | ␉fi␊ |
241 | ␉if [ -d "${2}/Extra/Extensions" ]; then␊ |
242 | ␉␉echo "Executing command: find ${2}/Extra/Extensions -name '*.kext' -depth 1 -exec cp -R {} ${bootvolume}/Extra/Extensions \;"␊ |
243 | ␉␉find "${2}/Extra/Extensions" -name '*.kext' -depth 1 -exec cp -R {} "${bootvolume}/Extra/Extensions" \;␊ |
244 | ␉fi␊ |
245 | fi␊ |
246 | ␊ |
247 | # setup link for extras␊ |
248 | [ -h "${2}/.Chameleon" ] && unlink "${2}/.Chameleon"␊ |
249 | echo "Executing command: ln -s /Volumes/${bootervolumename} ${2}/.Chameleon"␊ |
250 | ln -s "/Volumes/${bootervolumename}" "${2}/.Chameleon"␊ |
251 | ␊ |
252 | exit␊ |
253 | |