From 2e2be2ba45758e4f41513d99e2e6cb30e6079586 Mon Sep 17 00:00:00 2001 From: Jeremy Linton Date: Fri, 26 Oct 2018 16:00:30 -0500 Subject: [PATCH] Add aarch64 support, and more responsive qemu interaction The qemu commands to start a aarch64 guest vary slightly from the x86 version. Also, as the code to run the EFI binary in qemu tends to get hung up in the menus on aarch64 lets make it wait for the shell prompt before trying to start the binary. Signed-off-by: Jeremy Linton --- ovmf-vars-generator | 74 +++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 22 deletions(-) diff --git a/ovmf-vars-generator b/ovmf-vars-generator index d63e4cf..09c987a 100755 --- a/ovmf-vars-generator +++ b/ovmf-vars-generator @@ -20,18 +20,29 @@ import tempfile import shutil import string import subprocess - +import select def strip_special(line): return ''.join([c for c in str(line) if c in string.printable]) def generate_qemu_cmd(args, readonly, *extra_args): - if args.disable_smm: + is_x86 = True + new_args = [] + if os.path.basename(args.qemu_binary) == 'qemu-system-aarch64': + machinetype = 'virt' + new_args.extend(['-cpu', 'cortex-a57']) + is_x86 = False + elif args.disable_smm: machinetype = 'pc' else: machinetype = 'q35,smm=on' machinetype += ',accel=%s' % ('kvm' if args.enable_kvm else 'tcg') + if is_x86 == True: + new_args.extend(['-chardev', 'pty,id=charserial1', + '-device', 'isa-serial,chardev=charserial1,id=serial1', + '-global', 'driver=cfi.pflash01,property=secure,value=%s' % ( + 'off' if args.disable_smm else 'on')]) return [ args.qemu_binary, '-machine', machinetype, @@ -39,18 +50,14 @@ def generate_qemu_cmd(args, readonly, *extra_args): '-no-user-config', '-nodefaults', '-m', '256', - '-smp', '2,sockets=2,cores=1,threads=1', - '-chardev', 'pty,id=charserial1', - '-device', 'isa-serial,chardev=charserial1,id=serial1', - '-global', 'driver=cfi.pflash01,property=secure,value=%s' % ( - 'off' if args.disable_smm else 'on'), + '-smp', '1,sockets=1,cores=1,threads=1', '-drive', 'file=%s,if=pflash,format=raw,unit=0,readonly=on' % ( args.ovmf_binary), '-drive', 'file=%s,if=pflash,format=raw,unit=1,readonly=%s' % ( args.out_temp, 'on' if readonly else 'off'), - '-serial', 'stdio'] + list(extra_args) + '-serial', 'stdio'] + new_args + list(extra_args) def download(url, target, suffix, no_download): @@ -84,16 +91,16 @@ def enroll_keys(args): args, False, '-drive', - 'file=%s,format=raw,if=none,media=cdrom,id=drive-cd1,' - 'readonly=on' % args.uefi_shell_iso, - '-device', - 'ide-cd,drive=drive-cd1,id=cd1,' - 'bootindex=1') + 'file=%s,format=raw,if=virtio,media=cdrom,id=drive-cd1,' + 'readonly=on' % args.uefi_shell_iso) p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) logging.info('Performing enrollment') + pollobj = select.poll() + pollobj.register(p.stdout, select.POLLIN) + # Wait until the UEFI shell starts (first line is printed) read = p.stdout.readline() if b'char device redirected' in read: @@ -102,22 +109,45 @@ def enroll_keys(args): print(strip_special(read), end='') print() # Send the escape char to enter the UEFI shell early - p.stdin.write(b'\x1b') - p.stdin.flush() - # And then run the following three commands from the UEFI shell: - # change into the first file system device; install the default - # keys and certificates, and reboot - p.stdin.write(b'fs0:\r\n') - p.stdin.write(b'EnrollDefaultKeys.efi\r\n') - p.stdin.write(b'reset -s\r\n') + p.stdin.write(b'\r\n') p.stdin.flush() + Enrolled = False + wait_timeout = 100; while True: - read = p.stdout.readline() + poll_result = pollobj.poll(1000) + if poll_result: + # readline can get stuck in menus and other + # UI elements in uefi which don't respond + # with a CR the poll above doesn't help + # with that case. + read = p.stdout.readline() + else: + wait_timeout-=1 + if wait_timeout == 0: + logging.info('Failed enrollment') + # consider something stronger here + # as we can still get stuck in the p.wait() + break; + continue if args.print_output: print('OUT: %s' % strip_special(read), end='') print() + if b'seconds to skip' in read: + p.stdin.write(b'\r\n') + p.stdin.flush() if b'info: success' in read: break + if b'Shell>' in read: + # And then run the following three commands from the UEFI shell: + # change into the first file system device; install the default + # keys and certificates, and reboot + if Enrolled == False: + p.stdin.write(b'\r\nfs0:\r\n') + p.stdin.write(b'EnrollDefaultKeys.efi\r\n') + p.stdin.write(b'reset -s\r\n') + p.stdin.flush() + Enrolled = True; + p.wait() if args.print_output: print(strip_special(p.stdout.read()), end='')