1#/bin/sh -e
2
3# Currently, this TESTME script is capable of generating command lines
4# that can be copied and pasted.
5
6# re-launch a copy from /tmp
7tmprun="${TMP:-/tmp}/kt.TESTME"
8if [ "$0" != "$tmprun" ]; then
9    cp "$0" "$tmprun"
10    exec "$tmprun"
11fi
12
13usage() {
14    echo "Usage: TESTME [-h]"
15    exit "$1"
16}
17
18[ "$1" = "-h" ] && usage 0
19
20die() {
21    echo `basename "$0"`: "$@"
22    exit 1
23}
24
25unset raiddisk raidvol
26unset csdisk csvol
27unset fdedisk fdevol
28MOUNTPOINTAWKBITS="{
29    if (index(\$0, \"/Volumes\")) {
30        print substr(\$0, index(\$0,\"/Volumes\"), length(\$0))
31    } else {
32        print \$NF
33    }
34}"
35
36isOSvol() {
37    [ -s "$1"/System/Library/CoreServices/Finder.app ]
38}
39
40# only looks at first one
41findRAIDos() {
42    raiddisk=$(diskutil ar list | awk '/^Device Node:/ { print $NF; exit 0 }')
43    [ -z "$raiddisk" ] && return 1
44
45    raidvol=$(df -lh | awk "/$raiddisk / $MOUNTPOINTAWKBITS")
46    isOSvol "$raidvol" && echo "$raidvol"
47}
48
49findCSos() {
50    searchstr="Logical Volume [0-9A-F]"
51    [ "$1" ] && searchstr="$1"
52    csdisks=$(diskutil cs list | sed -n "/$searchstr/,/Disk:/ {
53        /Disk:.*disk/ {
54            s/^[^D]*Disk:[^d]*//
55            p
56        }
57        }")
58    [ -z "$csdisks" ] && return 1
59
60    for csdisk in $csdisks; do
61        csvol=$(df -lh | awk "/$csdisk/ $MOUNTPOINTAWKBITS")
62        isOSvol "$csvol" && echo "$csvol" && return
63    done
64}
65
66findFDEos() {
67    findCSos "Encryption Type:.*AES-XTS"
68}
69
70getHelper() {
71    bless -verbose -info "$1" 2>&1 >/dev/null | awk '/Aux.*Part/ { getline; print $1 }'
72}
73
74[ "$kextcache" ] || kextcache=/usr/sbin/kextcache
75brtest=/usr/local/bin/brtest
76[ -x "$brtest" ] || brtest=./brtest
77[ -d "$bros" ] || bros=$(findRAIDos)
78[ -d "$csos" ] || csos=$(findCSos);
79if ! [ -d "$bros" ]; then
80    if [ -d "$csos" ]; then
81        echo "WARNING: no RAID OS found; substituting CoreStorage volume $csos" >&2
82        sleep 2
83        bros=$csos
84    else
85        echo "WARNING: no Boot!=Root OS volumes found..." >&2
86        sleep 5
87        bros="[unknown!]"
88    fi
89fi
90[ -d "$fdeos" ] || fdeos=$(findFDEos)
91if ! [ -d "$fdeos" ]; then
92    echo "WARNING: no FDE OS volumes found..." >&2
93    diskutil cs list | grep -q -- "Encryptions Status:.*Locked" && \
94         echo "(there appears to be one offline)" >&2
95    sleep 5
96fi
97
98unset brhelper cshelper fdehelper 
99brhelper=$(getHelper "$bros")
100cshelper=$(getHelper "$csos")
101fdehelper=$(getHelper "$fdeos")
102
103
104# dump commands (yes, the next round will start executing some of them :)
105${PAGER:-less} <<TESTME_TEXT
106    Targets:
107        all                     - default desktop target (most targets ship)
108            kextcache
109-- To TEST --
110# basic Boot!=Root tests
111sudo touch /System/Library/Extensions && sudo time "$kextcache" -v -u /; echo \$?
112sudo touch "$bros"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist && \
113    sudo "$kextcache" -v -u "$bros"; echo \$?
114sudo touch /System/Library/Extensions && \
115    (sleep 6; sudo time "$kextcache" -vu /; echo \$?)  # let kextd do it
116sudo rm "$fdeos"/System/Library/Caches/com.apple.corestorage/EncryptedRoot.plist.wipekey && \
117    sudo "$kextcache" -v -u "$fdeos"; echo \$?
118
119# early-boot -> reboot if needed (later tests use this for reporting)
120sudo "$kextcache" -U "$bros"; echo \$?        # should be 0
121sudo touch "$bros"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist \
122    && sudo "$kextcache" -U "$bros"; echo \$?        # should be EX_OSFILE (72)
123
124# installer test (mid-way, non-FDE: should not rebuild EFILoginLocalizations)
125sudo rm -rf "$bros"/System/Library/Caches/com.apple.kext.caches/Startup/kernelcache \
126    "$bros"/System/Library/Caches/com.apple.corestorage/EFILoginLocalizations \
127    "$bros"/System/Library/Caches/com.apple.corestorage/EncryptedRoot.plist.wipekey \
128    "$bros"/System/Library/CoreServices/boot.efi \
129    && sudo "$kextcache" -v -Installer -u "$bros"; echo \$?
130sudo bless -folder "$bros"/System/Library/CoreServices -bootefi  # restore boot.efi
131
132# and at the end
133# background kextcache -vU success w/9567748 fixed
134(sleep 2 && sudo kextcache -vU "$bros"; echo \$?) & \
135sudo rm -rf "$bros"/System/Library/Caches/com.apple.kext.caches/Startup/kernelcache \
136    "$bros"/System/Library/Caches/com.apple.corestorage/EFILoginLocalizations \
137    && sudo "$kextcache" -v -Installer -u "$bros"; echo \$?
138
139# now targetting an FDE volume (should rebuild EFILoginLocalizations)
140sudo rm -rf "$fdeos"/System/Library/Caches/com.apple.corestorage/EFILoginLocalizations \
141    "$fdeos"/System/Library/Caches/com.apple.corestorage/EncryptedRoot.plist.wipekey \
142    && sudo "$kextcache" -v -Installer -u "$fdeos"; echo \$?
143
144# -caches-only
145# background kextcache -vU should only update the helpers
146(sleep 2 && sudo kextcache -vU "$bros"; echo \$?) & \
147sudo rm -rf "$bros"/System/Library/Caches/com.apple.kext.caches/Startup/kernelcache \
148    "$bros"/System/Library/Caches/com.apple.corestorage/EFILoginLocalizations \
149    && sudo "$kextcache" -v -caches-only -u "$bros"; echo \$?
150
151# enable FDE on root volume (or use GUI)
152[ "$bros" = / ] && echo "/ appears to already be using Boot!=Root"
153[ "$fdeos" = / ] && echo "/ is already running FDE"
154[ "$csos" = / ] && echo "/ appears may be unencrypted CoreStorage (use 'diskutil cs encryptVolume')"
155sudo diskutil cs convert / -passphrase test && sudo reboot 
156echo EFI Login should come up on reboot.
157echo "----- AFTER REBOOT -----"
158diskutil mount $fdehelper
159ls -l /Volumes/Rec*             # should have com.apple.boot.[RPS]
160bless -info /Volumes/Rec*       # finderinfo[0] -> /S/L/CoreServices
161                                # finderinfo[1] -> /S/L/CoreServices/boot.efi
162                                # finderinfo[3] -> com.apple.recovery.boot
163echo feel free to turn off FDE, either w/SecPref or diskutil cs decrypt
164
165# kextcache -u -f tested below w/brtest
166
167[...need to fill in lots more...]
168-- end TEST --
169
170            kextd
171            kextfind
172            kextlibs
173            kextload
174            kextstat
175            kextunload
176            kextutil
177            kextsymboltool      - /usr/local/bin
178            mkextunpack
179
180            libBootRoot
181            brtest
182-- To TEST --
183# run through the verbs
184"$brtest" listboots "$bros"
185
186sudo "$brtest" erasefiles "$fdeos" $fdehelper -f  # temporarily make unbootable
187diskutil mount "$fdehelper"                     # check disable FDE case
188bless -info /Volumes/Recovery*                  # Recovery should be blessed
189ls -la /Volumes/Recovery*                       # no cruft
190
191sudo "$kextcache" -vu "$fdeos"                  # '/' should look clean
192sudo $brtest update "$fdeos"                    # shouldn't update
193diskutil mount "$fdehelper"
194ls -la /Volumes/Recovery*                       # check still empty
195
196sudo "$brtest" copyfiles "$fdeos" $fdehelper    # update one of them
197diskutil mount "$fdehelper"                     # check copied
198bless -info /Volumes/Recovery*                  # Boot!=Root should be blessed
199ls -la /Volumes/Recovery*                       # Boot!=Root back
200
201sudo "$brtest" erasefiles "$fdeos" $fdehelper -f  # nuke $brhelper again
202sudo "$brtest" update "$fdeos" -f               # should update all
203diskutil mount "$fdehelper"                     # check everything is back
204bless -info /Volumes/Recovery*
205ls -la /Volumes/Recovery*
206
207# try w/multi-PV FDE, try w/unencrypted CoreStorage
208sudo "$brtest" erasefiles "$csos" $cshelper -f   # temporarily make unbootable :)
209sudo "$kextcache" -vu "$csos" -f                 # should update everything
210
211# set up non-functional dmg-booting inputs
212diskutil mount "$fdehelper"
213sudo ln -fs /Volumes/Rec*/com.apple.recovery.boot/BaseSystem.dmg "$fdeos"
214hdid "$fdeos"/BaseSystem.dmg
215
216# InstallAssistant[.app] on an encrypted volume
217sudo "$brtest" copyfiles "/Volumes/Mac OS X Internal Base System" "$fdeos" /BaseSystem.dmg "$fdehelper" 
218sudo cat /Volumes/Recovery*/com.apple.boot.?/Library/Preferences/SystemConfiguration/com.apple.Boot.plist 
219# should have root-dmg referring to BaseSystem.dmg (.dmg keeps A_B mounted :)
220
221# Time Machine making an encrypted backup bootable
222sudo mkdir /Volumes/Recovery\ HD/testdir
223sudo "$brtest" copyfiles "/Volumes/Mac OS X Internal Base System" "$fdeos" /BaseSystem.dmg "$fdehelper"/testdir 
224cat /Volumes/Recovery*/testdir/com.apple.Boot.plist 
225# confirm root-dmg + Kernel Cache
226
227# clean up
228df -lh
229# eject Internal System
230diskutil unmount "$fdehelper"
231
232
233-- end TEST --
234
235            setsegname          - /usr/local/bin
236            Create system cache folders     - script
237
238        embedded                - built for the device (no tools ship)?
239            Create system cache folders     - script
240            kextunload
241            kextstat
242
243        embedded-host           - for internal SDK (to build kernel caches)
244            kextcache-embedded-host
245            kextsymboltool-embedded-host
246            setsegname
247-- To TEST --
248# mountebuild.sh
249sudo ditto -v ~rc/Software/$IOSTRAIN/Updates/Current$IOSTRAIN/Roots/MacOSXSDKInternal10_7/ /
250if [ "$kxld_changed" ]; then
251    sudo ~rc/bin/buildit xnu -release "$IOSTRAIN" -project libkxld_host -arch i386 -arch x86_64 -noinstallsrc -noverify -merge /
252fi
253if [ "$kxldAPI_changed" -o "$IOKit_Kext_changed" ]; then
254    sudo ~rc/bin/buildit IOKitUser -release "$IOSTRAIN" -project IOKitUser_host -arch i386 -arch x86_64 -target libkext -noinstallsrc -noverify -merge /
255fi
256# libkxld_host and IOKitUser_host both build static libs that end up in /Developer/SDKs/iPhoneHostSideTools.sparse.sdk/
257sudo ~rc/bin/buildit kext_tools -release "$IOSTRAIN" -project kext_tools_host -arch i386 -arch x86_64 -target embedded-host -noinstallsrc -noverify # -merge /
258# kext_tools_host builds the tools used during development (e.g. kcgen)
259-- end TEST --
260
261
262
263        KextUserAgent           - inactive?
264
265    Build Configurations:
266        Development             - maximal debugging; only build current arch
267        Deployment              - optimized code; will build multiple archs
268(If no build configuration is specified "Deployment" is used by desktop B&I.)
269        Analyze                 - run analyzer on optimized code
270
271A number of Build settings are mirrored amongst these configurations
272(-D__MigTypeCheck=1 anyone?) and should be moved to the top level.
273TESTME_TEXT
274