# capfile # Capistrano recipes to simplify two-machine debugging for Mac OS X # # Based on Apple's Hello Debugger documentation # http://developer.apple.com/documentation/Darwin/Conceptual/KEXTConcept/KEXTConceptDebugger/hello_debugger.html # # Author: Dan Wilson (wilson_daniel@apple.com) # Copyright 2008-2014 # # Requires Capistrano Ruby gem v2.x # sudo gem install capistrano -v 2.15.5 # # To list recipes: # cap -f Scripts/capfile -T # # To set up target machine: # cap -f Scripts/capfile easyssh:enable # cap -f Scripts/capfile nvram:debug:enable # To copy headers: # cap -f Scripts/capfile usbx:headers # # To build, copy, and reboot target: # cap -f Scripts/capfile usbx:deploy # # Dynamically set variables # set(:target_machine) do result = ENV['target'] || "" if result.empty? result = Capistrano::CLI.ui.ask "Enter a SSH login for the debugging target, e.g. username@hostname: " puts "You can avoid this prompt by exporting 'target' in your environment.\n" end result end set(:ios_train) do result = ENV['IOSTRAIN'] || "" if result.empty? result = Capistrano::CLI.ui.ask "Enter iOS train name: " puts "You can avoid this prompt by exporting 'IOSTRAIN' in your environment.\n" end result end set(:bridgeos_train) do result = ENV['BRIDGEOSTRAIN'] || "" if result.empty? result = Capistrano::CLI.ui.ask "Enter bridgeOS train name: " puts "You can avoid this prompt by exporting 'BRIDGEOSTRAIN' in your environment.\n" end result end set(:watchos_train) do result = ENV['WATCHOSTRAIN'] || "" if result.empty? result = Capistrano::CLI.ui.ask "Enter WatchOS train name: " puts "You can avoid this prompt by exporting 'WATCHOSTRAIN' in your environment.\n" end result end set(:macos_train) do result = ENV['MACOSTRAIN'] || ENV['OSXTRAIN'] || "" if result.empty? result = Capistrano::CLI.ui.ask "Enter macOS train name: " puts "You can avoid this prompt by exporting 'MACOSTRAIN' in your environment.\n" end result end # # Recipe settings # # Use a pseudo-tty to prevent sudo from entering non-interactive mode. default_run_options[:pty] = true role :targets, "#{target_machine}" # # Tasks # namespace :easyssh do desc "Remove SSH key for target from .ssh/known_hosts" task :clean do system "cat ~/.ssh/known_hosts | grep -v `(echo $target | cut -f2 -d@)` > ~/.ssh/known_hosts" end desc "Enable no-password SSH on a remote system" task :enable, :roles => :targets do if not File.exist?("#{ENV['HOME']}/.ssh/id_rsa.pub") `ssh-keygen -t rsa` end upload "#{ENV['HOME']}/.ssh/id_rsa.pub", "/tmp/debugger_host_id_rsa.pub" run "mkdir ~/.ssh || echo Continuing anyway..." run "cat /tmp/debugger_host_id_rsa.pub >> ~/.ssh/authorized_keys" run "rm /tmp/debugger_host_id_rsa.pub" end end namespace :nvram do namespace :debug do desc "Enable debugging on a remote system and reboot it" task :enable, :roles => :targets do original_boot_args = capture("nvram boot-args") current_boot_args = original_boot_args current_boot_args.gsub!('boot-args', '') current_boot_args.strip! current_boot_args.gsub!(/(^|\s)debug=\S*/, '') current_boot_args.strip! current_boot_args.gsub!(/(^|\s)kdp_match_name=\S*/, '') current_boot_args.strip! current_boot_args.gsub!(/(^|\s)-v/,'') current_boot_args.strip! current_boot_args.gsub!(/(^|\s)kext-dev-mode=\S*/,'') current_boot_args.strip! current_boot_args.gsub!(/(^|\s)rootless=\S*/,'') current_boot_args.strip! current_boot_args += " debug=0x814e kdp_match_name=mojo -v kext-dev-mode=1 rootless=0" current_boot_args.strip! if current_boot_args != original_boot_args sudo "nvram boot-args='#{current_boot_args}'" sudo "reboot" end end desc "Disable debugging on a remote system and reboot it" task :disable, :roles => :targets do original_boot_args = capture("nvram boot-args") current_boot_args = original_boot_args current_boot_args.gsub!('boot-args', '') current_boot_args.strip! current_boot_args.gsub!(/(^|\s)debug=\S*/, '') current_boot_args.strip! current_boot_args.gsub!(/(^|\s)kdp_match_name=\S*/, '') current_boot_args.strip! current_boot_args.gsub!(/(^|\s)-v/,'') current_boot_args.strip! current_boot_args.gsub!(/(^|\s)kext-dev-mode=\S*/,'') current_boot_args.strip! current_boot_args.gsub!(/(^|\s)rootless=\S*/,'') current_boot_args.strip! if current_boot_args != original_boot_args sudo "nvram boot-args='#{current_boot_args}'" sudo "reboot" end end desc "Check current debug setting" task :status, :roles => :targets do current_boot_args = capture("nvram boot-args").gsub('boot-args', '').strip puts "boot-args #{current_boot_args}" end end end namespace :ios do desc "Copy IOPCIFamily headers for iOS" task :headers do system "sudo xbs buildit . -noinstall -noverify -arch arm -release #{ios_train} -project IOPCIFamily -mergeToSDKs" end desc "Build IOPCIFamily root for iOS" task :root do system "sudo xbs buildit . -release #{ios_train} -project IOPCIFamily -archive" end desc "Build IOPCIFamily for iOS" task :build do system "sudo xbs buildit . -release #{ios_train} -project IOPCIFamily" end end namespace :bridgeos do desc "Copy IOPCIFamily headers for bridgeOS" task :headers do system "sudo xbs buildit . -noinstall -noverify -arch arm -release #{bridgeos_train} -project IOPCIFamily -mergeToSDKs" end desc "Build IOPCIFamily root for bridgeOS" task :root do system "sudo xbs buildit . -release #{bridgeos_train} -project IOPCIFamily -archive" end desc "Build IOPCIFamily for bridgeOS" task :build do system "sudo xbs buildit . -release #{bridgeos_train} -project IOPCIFamily " end end namespace :watchos do desc "Copy IOPCIFamily headers for watchOS" task :headers do system "sudo xbs buildit . -noinstall -noverify -arch arm -release #{watchos_train} -project IOPCIFamily -mergeToSDKs" end desc "Build IOPCIFamily root for watchOS" task :root do system "sudo ~rc/bin/buildit . -release #{watchos_train} -project IOPCIFamily -archive" end desc "Build IOPCIFamily for watchOS" task :build do system "sudo ~rc/bin/buildit . -release #{watchos_train} -project IOPCIFamily" end end namespace :macos do desc "Copy IOPCIFamily headers for macOS" task :headers do system "sudo xbs buildit . -noverify -release #{macos_train} -project IOPCIFamily -buildAlias IOPCIFamily -noinstall -mergeToSDKs" end desc "Build IOPCIFamily root for macOS" task :root do buildSelect = fetch(:buildSelect, 'buildit') if buildSelect == 'xcode' system "sudo xcodebuild install -target IOPCIFamily_macOS -configuration Debug" system "tar -czf /tmp/Shared_XcodeBuild_IOPCIFamily_DSTROOT_osx.tar.gz -C /tmp/IOPCIFamily.dst/ System" else system "sudo xbs buildit . -noverify -release #{macos_train} -project IOPCIFamily -buildAlias IOPCIFamily -archive" end end desc "Build IOPCIFamily for macOS" task :build do system "sudo xbs buildit . -noverify -release #{macos_train} -project IOPCIFamily" end desc "Copy IOPCIFamily" task :copy, :roles => :targets do buildSelect = fetch(:buildSelect, 'buildit') if buildSelect == 'xcode' sourceFile = "/tmp/Shared_XcodeBuild_IOPCIFamily_DSTROOT_osx.tar.gz" else sourceFile = "/tmp/IOPCIFamily.roots/Archives/Shared_IOPCIFamily_DSTROOT_osx.tar.gz" end destFile = "/tmp/Shared_IOPCIFamily_DSTROOT_osx-#{Time.now.strftime('%Y%m%d-%H%M%S')}.tar.gz" upload sourceFile, destFile sudo "darwinup install #{destFile}" sudo "rm #{destFile}" sudo "kextcache -i /" end desc "Reboot target machine" task :reboot, :roles => :targets do sudo "reboot" end desc "Deploy and reboot IOPCIFamily to target" task :deploy do transaction do root copy reboot end end end namespace :driverkit do desc "Copy IOPCIFamily__driverkit headers for DriverKit" task :headers do system "sudo xbs buildit . -noinstall -noverify -release #{macos_train} -project IOPCIFamily -buildAlias IOPCIFamily__driverkit -mergeToSDKs" end desc "Build IOPCIFamily__driverkit root for DriverKit" task :root do buildSelect = fetch(:buildSelect, 'buildit') if buildSelect == 'xcode' system "sudo xcodebuild install -target IOPCIFamily_DriverKit -configuration Debug" system "tar -czf /tmp/Shared_XcodeBuild_IOPCIFamily_DSTROOT_osx.tar.gz -C /tmp/IOPCIFamily.dst/ System" else system "sudo xbs buildit . -noverify -release #{macos_train} -project IOPCIFamily -buildAlias IOPCIFamily__driverkit -archive -codesign" end end desc "Build IOPCIFamily__driverkit for DriverKit" task :build do system "sudo xbs buildit . -noverify -release #{macos_train} -project IOPCIFamily -sdkForPlatform macosx=macosx.internal" end desc "Copy IOPCIFamily__driverkit" task :copy, :roles => :targets do buildSelect = fetch(:buildSelect, 'buildit') if buildSelect == 'xcode' sourceFile = "/tmp/Shared_XcodeBuild_IOPCIFamily_DSTROOT_osx.tar.gz" else sourceFile = "/tmp/IOPCIFamily.roots/Archives/Shared_IOPCIFamily_DSTROOT_osx.tar.gz" end destFile = "/tmp/Shared_IOPCIFamily_DSTROOT_osx-#{Time.now.strftime('%Y%m%d-%H%M%S')}.tar.gz" upload sourceFile, destFile sudo "darwinup install #{destFile}" sudo "rm #{destFile}" sudo "sudo darwinup -p /System/Library/DriverExtensions/ install /AppleInternal/CoreOS/IOPCIFamily/PCIDriverKitTests/" sudo "kextcache -i /" end desc "Reboot target machine" task :reboot, :roles => :targets do sudo "reboot" end desc "Deploy and reboot IOPCIFamily to target" task :deploy do transaction do root copy reboot end end end namespace :pex8733 do desc "Build PCIDriverKitPEX8733 root for DriverKit" task :root do buildSelect = fetch(:buildSelect, 'buildit') if buildSelect == 'xcode' system "sudo xcodebuild install -target PCIDriverKitPEX8733 -configuration Debug" system "tar -czf /tmp/Shared_XcodeBuild_IOPCIFamily_DSTROOT_osx.tar.gz -C /tmp/IOPCIFamily.dst/ AppleInternal" else system "sudo xbs buildit . -noverify -release #{macos_train} -project IOPCIFamily -buildAlias IOPCIFamily__driverkit -target PCIDriverKitPEX8733 -archive -codesign" end end desc "Build PCIDriverKitPEX8733 for DriverKit" task :build do system "sudo xbs buildit . -noverify -release #{macos_train} -project IOPCIFamily -buildAlias IOPCIFamily__driverkit -target PCIDriverKitPEX8733" end desc "Copy PCIDriverKitPEX8733" task :copy, :roles => :targets do buildSelect = fetch(:buildSelect, 'buildit') if buildSelect == 'xcode' sourceFile = "/tmp/Shared_XcodeBuild_IOPCIFamily_DSTROOT_osx.tar.gz" else sourceFile = "/tmp/IOPCIFamily.roots/Archives/Shared_IOPCIFamily_DSTROOT_osx.tar.gz" end destFile = "/tmp/Shared_IOPCIFamily_DSTROOT_osx-#{Time.now.strftime('%Y%m%d-%H%M%S')}.tar.gz" upload sourceFile, destFile sudo "darwinup install #{destFile}" sudo "rm #{destFile}" sudo "sudo darwinup -p /System/Library/DriverExtensions/ install /AppleInternal/CoreOS/IOPCIFamily/PCIDriverKitTests/" sudo "kextcache -i /" end desc "Reboot target machine" task :reboot, :roles => :targets do sudo "reboot" end desc "Deploy and reboot PCIDriverKitPEX8733 to target" task :deploy do transaction do root copy reboot end end end