diff --git a/Makefile b/Makefile index 9d38945..91cec9b 100644 --- a/Makefile +++ b/Makefile @@ -96,6 +96,11 @@ $(BUILD_DIR)/compile_commands.json: @./tools/socks.compiledb +cd: $(BUILD_DIR)/socks-kernel.iso + +install-cd: $(BUILD_DIR)/socks-kernel.iso + @./tools/socks.install-cd + compile-db: $(BUILD_DIR)/compile_commands.json tools: diff --git a/tools/socks.install-cd b/tools/socks.install-cd new file mode 100755 index 0000000..657a40a --- /dev/null +++ b/tools/socks.install-cd @@ -0,0 +1,171 @@ +#!/usr/bin/env python3 +import sys +import os +import plistlib +import subprocess +from pprint import pprint + + +def disk_prewrite_darwin(dev_path): + diskutil = subprocess.Popen([ 'sudo', 'diskutil', 'unmountDisk', dev_path ]) + diskutil.communicate() + + if diskutil.returncode != 0: + print('Cannot unmount device {}'.format(dev_path)) + print(' diskutil returned error code {}'.format(diskutil.returncode)) + exit(-1) + + +def disk_prewrite(dev_path): + if sys.platform == 'darwin': + disk_prewrite_darwin(dev_path) + + +def disk_postwrite_darwin(dev_path): + sync = subprocess.Popen([ 'sync' ]) + sync.communicate() + + diskutil = subprocess.Popen([ 'sudo', 'diskutil', 'unmountDisk', dev_path ]) + diskutil.communicate() + + +def disk_postwrite_linux(dev_path): + sync = subprocess.Popen([ 'sync' ]) + sync.communicate() + + +def disk_postwrite(dev_path): + if sys.platform == 'darwin': + disk_postwrite_darwin(dev_path); + elif sys.platform == 'linux': + disk_postwrite_linux(dev_path) + + +def get_devices_darwin(): + diskutil = subprocess.Popen([ 'diskutil', 'list', '-plist' ], stdout=subprocess.PIPE) + (out, err) = diskutil.communicate() + + if diskutil.returncode != 0: + print('Cannot query storage devices') + print(' diskutil returned error code {}'.format(diskutil.returncode)) + print(err) + exit(-1) + + all_device_data = plistlib.loads(out) + device_names = [] + + for v in all_device_data['AllDisksAndPartitions']: + if v['OSInternal']: + continue + + device_names.append(v['DeviceIdentifier']) + + final_list = [] + + for dev in device_names: + diskutil = subprocess.Popen([ 'diskutil', 'info', '-plist', dev ], stdout=subprocess.PIPE) + (out, err) = diskutil.communicate() + + if diskutil.returncode != 0: + print('Cannot query device {}'.format(dev)) + print(' diskutil returned error code {}'.format(diskutil.returncode)) + print(err) + exit(-1) + + dev_info = plistlib.loads(out) + + if dev_info['BusProtocol'] != 'USB': + continue + + final_list.append(('/dev/r{}'.format(dev_info['DeviceIdentifier']), dev_info['MediaName'])) + + return final_list + + +def get_devices_linux(): + final_list = [] + dev_list = os.listdir('/sys/block') + + for dev_name in dev_list: + with open('/sys/block/{}/removable'.format(dev_name), 'r') as dev_removable: + is_removable = int(dev_removable.read(1)) + if is_removable != 1: + continue + + with open('/sys/block/{}/device/model'.format(dev_name)) as dev_model_name: + model_name = dev_model_name.read().strip() + final_list.append(('/dev/{}'.format(dev_name), model_name)) + + return final_list + + +def get_devices(): + if sys.platform == 'darwin': + return get_devices_darwin() + elif sys.platform == 'linux': + return get_devices_linux() + else: + print('This script cannot be used on {}'.format(sys.platform)) + exit(-1) + + +def choice_options(num_devices): + if num_devices == 1: + return '1' + + return '1-{}'.format(num_devices) + + +if not os.path.isfile('build/socks-kernel.iso'): + print('No system ISO image found.') + print('Please run \'make cd\' to generate an ISO image') + exit(-1) + +devices = get_devices() + +if len(devices) == 0: + print('No devices are available for installation') + print('Note: this script only considers removable USB drives for installation') + exit(-1) + +print('Available Devices:') +for i, dev in enumerate(devices): + print(' {}. {} ({})'.format(i + 1, dev[1], dev[0])) + +choice = 0 +while True: + print('Selection [{}]: '.format(choice_options(len(devices))), end='') + choice_str = input() + + try: + choice = int(choice_str) + except: + print(' {} is not a valid option'.format(choice_str)) + continue + + if choice < 1 or choice > len(devices): + print(' {} is not a valid option'.format(choice_str)) + continue + + choice -= 1 + break + +print('Installing to {} at {}'.format(devices[choice][1], devices[choice][0])) + +disk_prewrite(devices[choice][0]) + +dd_args = [ + 'sudo', + 'dd', + 'if=build/socks-kernel.iso', + 'of={}'.format(devices[choice][0]), + 'bs=1{}'.format('m' if sys.platform == 'darwin' else 'M') +] + +dd = subprocess.Popen(dd_args) +dd.communicate() +if dd.returncode != 0: + print('Cannot write ISO file to device {}'.format(devices[choice][0])) + print(' dd returned error code {}'.format(dd.returncode)) + +disk_postwrite(devices[choice][0])