From 2d049316fda7adf06b044e6617005d427e12da86 Mon Sep 17 00:00:00 2001 From: Raptor Engineering Development Team Date: Mon, 26 Mar 2018 04:08:42 -0500 Subject: Defer IPL completion notice until skiroot kernel has loaded Fix up general handling of IPL observation --- pyiplobserver/ipl_status_observer.py | 89 ++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 35 deletions(-) (limited to 'pyiplobserver') diff --git a/pyiplobserver/ipl_status_observer.py b/pyiplobserver/ipl_status_observer.py index 890dd61..cc12511 100644 --- a/pyiplobserver/ipl_status_observer.py +++ b/pyiplobserver/ipl_status_observer.py @@ -43,6 +43,12 @@ IPL_COMPLETE_ISTEP_MINOR = 3 SKIBOOT_RUNNING_ISTEP_MAJOR = 22 SKIBOOT_RUNNING_ISTEP_MINOR = 0 +KERNEL_RUNNING_ISTEP_MAJOR = 23 +KERNEL_RUNNING_ISTEP_MINOR = 0 + +KERNEL_COMPLETE_ISTEP_MAJOR = 23 +KERNEL_COMPLETE_ISTEP_MINOR = 1 + class IPLStatus(DbusProperties, DbusObjectManager): def __init__(self, bus, obj_name): super(IPLStatus, self).__init__( @@ -73,19 +79,20 @@ class IPLStatus(DbusProperties, DbusObjectManager): signal_name="PropertiesChanged", path=u'/xyz/openbmc_project/state/host0') - gobject.timeout_add(100, self.readIPLStatus) + gobject.timeout_add(1, self.readIPLStatus) print "IPLStatus Init Done" - # BMC bits OEM1 and OEM2 are the signalling flags + # BMC bits OEM1, OEM2, and OEM3 are the signalling flags # OEM1 is unconditionally set at skiboot completion and is only cleared by the BMC IPL monitor # OEM2 is used as a persistent state indicator, and is only set and cleared by the BMC IPL monitor + # OEM3 is unconditionally set at kernel boot completion and is only cleared by the BMC IPL monitor def getSkibootBootFlags(self): result = 0 try: - proc = subprocess.Popen(["devmem", "0x1e789060", "8"], stdout=subprocess.PIPE, stderr=open(os.devnull, 'wb'), shell=False) + proc = subprocess.Popen(["devmem", "0x1e789060", "16"], stdout=subprocess.PIPE, stderr=open(os.devnull, 'wb'), shell=False) (out, err) = proc.communicate() - result = (int(out, 16) & 12) >> 2 + result = (int(out, 16) & 28) >> 2 except: pass @@ -93,13 +100,13 @@ class IPLStatus(DbusProperties, DbusObjectManager): def setSkibootBootFlags(self, value): try: - proc = subprocess.Popen(["devmem", "0x1e789060", "8"], stdout=subprocess.PIPE, stderr=open(os.devnull, 'wb'), shell=False) + proc = subprocess.Popen(["devmem", "0x1e789060", "16"], stdout=subprocess.PIPE, stderr=open(os.devnull, 'wb'), shell=False) (out, err) = proc.communicate() - reg_data = (int(out, 16) & (~12)) | ((value & 3) << 2) - proc = subprocess.Popen(["devmem", "0x1e789060", "8", str(reg_data)], stdout=subprocess.PIPE, stderr=open(os.devnull, 'wb'), shell=False) + reg_data = (int(out, 16) & (~28)) | ((value & 7) << 2) + proc = subprocess.Popen(["devmem", "0x1e789060", "16", str(reg_data)], stdout=subprocess.PIPE, stderr=open(os.devnull, 'wb'), shell=False) (out, err) = proc.communicate() except: - print "IPLStatus unable to reset skiboot flags!" + print "IPLStatus unable to reset skiboot / kernel flags!" pass def readIPLStatus(self): @@ -122,11 +129,12 @@ class IPLStatus(DbusProperties, DbusObjectManager): self.Set(DBUS_NAME, "current_status", current_status) self.IPLStatusChanged(current_status) self.last_status = current_status + self.setSkibootBootFlags(0) if (self.last_istep != current_istep): self.Set(DBUS_NAME, "current_istep", current_istep) self.IPLStepChanged(current_istep) self.last_istep = current_istep - self.setSkibootBootFlags(0) + self.setSkibootBootFlags(0) return True; @@ -204,14 +212,23 @@ class IPLStatus(DbusProperties, DbusObjectManager): current_status = "OFFLINE" if ((current_istep_major > 0) or (current_istep_minor > 0 )): current_status = "IPL_RUNNING" - if ((current_istep_major == IPL_COMPLETE_ISTEP_MAJOR) and (current_istep_minor == IPL_COMPLETE_ISTEP_MINOR)): - if (self.getSkibootBootFlags() == 0): + if (current_istep_major >= IPL_COMPLETE_ISTEP_MAJOR): + skiboot_flags = self.getSkibootBootFlags() + if (skiboot_flags == 0): current_status = "IPL_RUNNING" current_istep_major = SKIBOOT_RUNNING_ISTEP_MAJOR current_istep_minor = SKIBOOT_RUNNING_ISTEP_MINOR current_istep = str(current_istep_major) + "," + str(current_istep_minor) + elif (skiboot_flags == 1): + current_status = "IPL_RUNNING" + current_istep_major = KERNEL_RUNNING_ISTEP_MAJOR + current_istep_minor = KERNEL_RUNNING_ISTEP_MINOR + current_istep = str(current_istep_major) + "," + str(current_istep_minor) else: current_status = "IPL_COMPLETE" + current_istep_major = KERNEL_COMPLETE_ISTEP_MAJOR + current_istep_minor = KERNEL_COMPLETE_ISTEP_MINOR + current_istep = str(current_istep_major) + "," + str(current_istep_minor) # Reset failure counter self.prev_access_fail_count = 0 @@ -220,36 +237,38 @@ class IPLStatus(DbusProperties, DbusObjectManager): if (self.prev_access_fail_count < 255): self.prev_access_fail_count += 1 - if (self.last_status != current_status): - if (current_status == "IPL_COMPLETE"): - # Set skiboot completion flag - self.setSkibootBootFlags(2) - - # Signal systemd that IPL is complete - try: - with open(IPL_FLAG_DIR + IPL_FLAG_FILE, 'a'): - os.utime(IPL_FLAG_DIR + IPL_FLAG_FILE, None) - - systemd_emit_dev = self.bus.get_object("org.freedesktop.systemd1", u"/org/freedesktop/systemd1") - systemd_emit_iface = dbus.Interface(systemd_emit_dev, 'org.freedesktop.systemd1.Manager') - systemd_emit_function = getattr(systemd_emit_iface, 'StartUnit') - systemd_emit_function.call_async('obmc-host-ipl-complete@0.target', 'replace') - except Exception as e: - pass - else: - try: - os.remove(IPL_FLAG_DIR + IPL_FLAG_FILE) - except: - pass - if (current_istep_major < IPL_COMPLETE_ISTEP_MAJOR): - self.setSkibootBootFlags(0) - # Since it is extremely unlikely that both fetches will fail unless the host is offline, simply check that both fetches passed or failed before continuing if (sbe_fetch_failed == hostboot_fetch_failed): # Check error results multiple times before signalling unexpected offline status if ((current_status == "OFFLINE") and (self.prev_access_fail_count < 10)): return True + # Check for status changes + if (self.last_status != current_status): + if (current_status == "IPL_COMPLETE"): + # Set skiboot completion flag + self.setSkibootBootFlags(2) + + # Signal systemd that IPL is complete + try: + with open(IPL_FLAG_DIR + IPL_FLAG_FILE, 'a'): + os.utime(IPL_FLAG_DIR + IPL_FLAG_FILE, None) + + systemd_emit_dev = self.bus.get_object("org.freedesktop.systemd1", u"/org/freedesktop/systemd1") + systemd_emit_iface = dbus.Interface(systemd_emit_dev, 'org.freedesktop.systemd1.Manager') + systemd_emit_function = getattr(systemd_emit_iface, 'StartUnit') + systemd_emit_function.call_async('obmc-host-ipl-complete@0.target', 'replace') + except Exception as e: + pass + else: + try: + os.remove(IPL_FLAG_DIR + IPL_FLAG_FILE) + except: + pass + if (current_status == "IPL_RUNNING"): + if (current_istep_major < IPL_COMPLETE_ISTEP_MAJOR): + self.setSkibootBootFlags(0) + # Publish status if (self.last_status != current_status): self.Set(DBUS_NAME, "current_status", current_status) -- cgit v1.2.1