c15b445
diff --git a/oz.cfg b/oz.cfg
c15b445
index 5be1cb0..8913f9d 100644
c15b445
--- a/oz.cfg
c15b445
+++ b/oz.cfg
c15b445
@@ -19,3 +19,9 @@ jeos = no
c15b445
 
c15b445
 [icicle]
c15b445
 safe_generation = no
c15b445
+
c15b445
+[timeouts]
c15b445
+install = 1200
c15b445
+inactivity = 300
c15b445
+boot = 300
c15b445
+shutdown = 90
c15b445
diff --git a/oz/Guest.py b/oz/Guest.py
c15b445
index 54a0e8c..22c93c4 100644
c15b445
--- a/oz/Guest.py
c15b445
+++ b/oz/Guest.py
c15b445
@@ -203,6 +203,16 @@ class Guest(object):
c15b445
                                                                 'safe_generation',
c15b445
                                                                 False)
c15b445
 
c15b445
+        # configuration of 'timeouts' section
c15b445
+        self.default_install_timeout = int(oz.ozutil.config_get_key(config, 'timeouts',
c15b445
+                                                                            'install', 1200))
c15b445
+        self.inactivity_timeout = int(oz.ozutil.config_get_key(config, 'timeouts',
c15b445
+                                                               'inactivity', 300))
c15b445
+        self.boot_timeout = int(oz.ozutil.config_get_key(config, 'timeouts',
c15b445
+                                                                 'boot', 300))
c15b445
+        self.shutdown_timeout = int(oz.ozutil.config_get_key(config, 'timeouts',
c15b445
+                                                                     'shutdown', 90))
c15b445
+
c15b445
         # only pull a cached JEOS if it was built with the correct image type
c15b445
         jeos_extension = self.image_type
c15b445
         if self.image_type == 'raw':
c15b445
@@ -471,6 +481,10 @@ class Guest(object):
c15b445
             if self.tdl.arch == "armv7l":
c15b445
                 cmdline += " console=ttyAMA0"
c15b445
             self.lxml_subelement(osNode, "cmdline", cmdline)
c15b445
+        if self.tdl.arch == "aarch64":
c15b445
+            loader,nvram = oz.ozutil.find_uefi_firmware(self.tdl.arch)
c15b445
+            self.lxml_subelement(osNode, "loader", loader, {'readonly': 'yes', 'type': 'pflash'})
c15b445
+            self.lxml_subelement(osNode, "nvram", None, {'template': nvram})
c15b445
         # poweroff, reboot, crash
c15b445
         self.lxml_subelement(domain, "on_poweroff", "destroy")
c15b445
         self.lxml_subelement(domain, "on_reboot", "destroy")
c15b445
@@ -761,8 +775,7 @@ class Guest(object):
c15b445
                 # the passed in exception was None, just raise a generic error
c15b445
                 raise oz.OzException.OzException("Unknown libvirt error")
c15b445
 
c15b445
-    def _wait_for_install_finish(self, libvirt_dom, count,
c15b445
-                                 inactivity_timeout=300):
c15b445
+    def _wait_for_install_finish(self, libvirt_dom, count):
c15b445
         """
c15b445
         Method to wait for an installation to finish.  This will wait around
c15b445
         until either the VM has gone away (at which point it is assumed the
c15b445
@@ -774,7 +787,7 @@ class Guest(object):
c15b445
 
c15b445
         last_disk_activity = 0
c15b445
         last_network_activity = 0
c15b445
-        inactivity_countdown = inactivity_timeout
c15b445
+        inactivity_countdown = self.inactivity_timeout
c15b445
         origcount = count
c15b445
         saved_exception = None
c15b445
         while count > 0 and inactivity_countdown > 0:
c15b445
@@ -809,7 +822,7 @@ class Guest(object):
c15b445
                 inactivity_countdown -= 1
c15b445
             else:
c15b445
                 # if we did see some activity, then we can reset the timer
c15b445
-                inactivity_countdown = inactivity_timeout
c15b445
+                inactivity_countdown = self.inactivity_timeout
c15b445
 
c15b445
             last_disk_activity = total_disk_req
c15b445
             last_network_activity = total_net_bytes
c15b445
@@ -826,18 +839,19 @@ class Guest(object):
c15b445
             # if we saw no disk or network activity in the countdown window,
c15b445
             # we presume the install has hung.  Fail here
c15b445
             screenshot_text = self._capture_screenshot(libvirt_dom)
c15b445
-            raise oz.OzException.OzException("No disk activity in %d seconds, failing.  %s" % (inactivity_timeout, screenshot_text))
c15b445
+            raise oz.OzException.OzException("No disk activity in %d seconds, failing.  %s" % (self.inactivity_timeout, screenshot_text))
c15b445
 
c15b445
         # We get here only if we got a libvirt exception
c15b445
         self._wait_for_clean_shutdown(libvirt_dom, saved_exception)
c15b445
 
c15b445
         self.log.info("Install of %s succeeded", self.tdl.name)
c15b445
 
c15b445
-    def _wait_for_guest_shutdown(self, libvirt_dom, count=90):
c15b445
+    def _wait_for_guest_shutdown(self, libvirt_dom):
c15b445
         """
c15b445
         Method to wait around for orderly shutdown of a running guest.  Returns
c15b445
         True if the guest shutdown in the specified time, False otherwise.
c15b445
         """
c15b445
+        count = self.shutdown_timeout
c15b445
         origcount = count
c15b445
         saved_exception = None
c15b445
         while count > 0:
c15b445
@@ -1235,12 +1249,12 @@ class Guest(object):
c15b445
             sock.connect(('127.0.0.1', self.listen_port))
c15b445
 
c15b445
             addr = None
c15b445
-            count = 300
c15b445
+            count = self.boot_timeout
c15b445
             data = ''
c15b445
             while count > 0:
c15b445
                 do_sleep = True
c15b445
                 if count % 10 == 0:
c15b445
-                    self.log.debug("Waiting for guest %s to boot, %d/300", self.tdl.name, count)
c15b445
+                    self.log.debug("Waiting for guest %s to boot, %d/%d", self.tdl.name, count, self.boot_timeout)
c15b445
                 try:
c15b445
                     # note that we have to build the data up here, since there
c15b445
                     # is no guarantee that we will get the whole write in one go
c15b445
diff --git a/oz/RedHat.py b/oz/RedHat.py
c15b445
index aaa102c..896edb7 100644
c15b445
--- a/oz/RedHat.py
c15b445
+++ b/oz/RedHat.py
c15b445
@@ -334,6 +334,11 @@ label customiso
c15b445
         # part 4; make sure the guest announces itself
c15b445
         self.log.debug("Step 4: Guest announcement")
c15b445
 
c15b445
+        if self.tdl.arch in [ 'ppc64', 'ppc64le' ]:
c15b445
+            announce_device = '/dev/hvc1'
c15b445
+        else:
c15b445
+            announce_device = '/dev/ttyS1'
c15b445
+
c15b445
         scriptfile = os.path.join(self.icicle_tmp, "script")
c15b445
 
c15b445
         if g_handle.exists("/etc/NetworkManager/dispatcher.d"):
c15b445
@@ -342,9 +347,9 @@ label customiso
c15b445
 #!/bin/bash
c15b445
 
c15b445
 if [ "$1" = "eth0" -a "$2" = "up" ]; then
c15b445
-    echo -n "!$DHCP4_IP_ADDRESS,%s!" > /dev/ttyS1
c15b445
+    echo -n "!$DHCP4_IP_ADDRESS,%s!" > %s
c15b445
 fi
c15b445
-""" % (self.uuid))
c15b445
+""" % (self.uuid, announce_device))
c15b445
 
c15b445
             try:
c15b445
                 g_handle.upload(scriptfile,
c15b445
@@ -364,8 +369,8 @@ DEV=$(/bin/awk '{if ($2 == 0) print $1}' /proc/net/route) &&
c15b445
 [ -z "$DEV" ] && exit 0
c15b445
 ADDR=$(/sbin/ip -4 -o addr show dev $DEV | /bin/awk '{print $4}' | /bin/cut -d/ -f1) &&
c15b445
 [ -z "$ADDR" ] && exit 0
c15b445
-echo -n "!$ADDR,%s!" > /dev/ttyS1
c15b445
-""" % (self.uuid))
c15b445
+echo -n "!$ADDR,%s!" > %s
c15b445
+""" % (self.uuid, announce_device))
c15b445
 
c15b445
         try:
c15b445
             g_handle.upload(scriptfile, '/root/reportip')
c15b445
diff --git a/oz/ozutil.py b/oz/ozutil.py
c15b445
index eb4cd6f..775576b 100644
c15b445
--- a/oz/ozutil.py
c15b445
+++ b/oz/ozutil.py
c15b445
@@ -970,3 +970,45 @@ def recursively_add_write_bit(inputdir):
c15b445
             except OSError as err:
c15b445
                 if err.errno != errno.ENOENT:
c15b445
                     raise
c15b445
+
c15b445
+def find_uefi_firmware(arch):
c15b445
+    # Yuck.  Finding the UEFI firmware to start certain guests (like aarch64)
c15b445
+    # is a really nasty process.  While slightly out of date, this blog post
c15b445
+    # describes the mess: http://blog.wikichoon.com/2016/01/uefi-support-in-virt-install-and-virt.html
c15b445
+    # Here, we replicate what libguestfs is doing here, which is to essentially
c15b445
+    # hardcode paths where UEFI firmware can be found on popular distributions.
c15b445
+    # I verified that these files exist on both Fedora/RHEL and Ubuntu.
c15b445
+    # Hopefully there will be a nicer way to do this in the future.
c15b445
+    class UEFI(object):
c15b445
+        def __init__(self, loader, nvram):
c15b445
+            self.loader = loader
c15b445
+            self.nvram = nvram
c15b445
+
c15b445
+        def exists(self):
c15b445
+            if os.path.exists(self.loader) and os.path.exists(self.nvram):
c15b445
+                return True
c15b445
+            return False
c15b445
+
c15b445
+    if arch in ['i386', 'i486', 'i586', 'i686']:
c15b445
+        uefi_list = [UEFI('/usr/share/edk2.git/ovmf-ia32/OVMF_CODE-pure-efi.fd',
c15b445
+                          '/usr/share/edk2.git/ovmf-ia32/OVMF_VARS-pure-efi.fd')]
c15b445
+    elif arch in ['x86_64']:
c15b445
+        uefi_list = [UEFI('/usr/share/OVMF/OVMF_CODE.fd',
c15b445
+                          '/usr/share/OVMF/OVMF_VARS.fd'),
c15b445
+                     UEFI('/usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd',
c15b445
+                          '/usr/share/edk2.git/ovmf-x64/OVMF_VARS-pure-efi.fd')]
c15b445
+    elif arch in ['aarch64']:
c15b445
+        uefi_list = [UEFI('/usr/share/AAVMF/AAVMF_CODE.fd',
c15b445
+                          '/usr/share/AAVMF/AAVMF_VARS.fd'),
c15b445
+                     UEFI('/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw',
c15b445
+                          '/usr/share/edk2/aarch64/vars-template-pflash.raw'),
c15b445
+                     UEFI('/usr/share/edk2.git/aarch64/QEMU_EFI-pflash.raw',
c15b445
+                          '/usr/share/edk2.git/aarch64/vars-template-pflash.raw')]
c15b445
+    else:
c15b445
+        raise Exception("Invalid arch for UEFI firmware")
c15b445
+
c15b445
+    for uefi in uefi_list:
c15b445
+        if uefi.exists():
c15b445
+            return uefi.loader,uefi.nvram
c15b445
+
c15b445
+    raise Exception("UEFI firmware is not installed!")