xref: /openbmc/skeleton/pyflashbmc/bmc_update.py (revision c8094109)
140a360c2SBrad Bishop#!/usr/bin/python -u
240a360c2SBrad Bishop
340a360c2SBrad Bishopimport gobject
440a360c2SBrad Bishopimport dbus
540a360c2SBrad Bishopimport dbus.service
640a360c2SBrad Bishopimport dbus.mainloop.glib
740a360c2SBrad Bishopimport shutil
840a360c2SBrad Bishopimport tarfile
940a360c2SBrad Bishopimport os
1040a360c2SBrad Bishopfrom obmc.dbuslib.bindings import get_dbus, DbusProperties, DbusObjectManager
1140a360c2SBrad Bishop
1240a360c2SBrad BishopDBUS_NAME = 'org.openbmc.control.BmcFlash'
1340a360c2SBrad BishopOBJ_NAME = '/org/openbmc/control/flash/bmc'
1440a360c2SBrad BishopFLASH_INTF = 'org.openbmc.Flash'
1540a360c2SBrad BishopDOWNLOAD_INTF = 'org.openbmc.managers.Download'
1640a360c2SBrad Bishop
1740a360c2SBrad BishopUPDATE_PATH = '/run/initramfs'
1840a360c2SBrad Bishop
1940a360c2SBrad Bishop
2040a360c2SBrad Bishopdef doExtract(members,files):
2140a360c2SBrad Bishop    for tarinfo in members:
2240a360c2SBrad Bishop        if files.has_key(tarinfo.name) == True:
2340a360c2SBrad Bishop            yield tarinfo
2440a360c2SBrad Bishop
2540a360c2SBrad Bishop
2640a360c2SBrad Bishopclass BmcFlashControl(DbusProperties,DbusObjectManager):
2740a360c2SBrad Bishop	def __init__(self,bus,name):
2840a360c2SBrad Bishop		self.dbus_objects = { }
2940a360c2SBrad Bishop		DbusProperties.__init__(self)
3040a360c2SBrad Bishop		DbusObjectManager.__init__(self)
3140a360c2SBrad Bishop		dbus.service.Object.__init__(self,bus,name)
3240a360c2SBrad Bishop
3340a360c2SBrad Bishop		self.Set(DBUS_NAME,"status","Idle")
3440a360c2SBrad Bishop		self.Set(DBUS_NAME,"filename","")
35*c8094109SMilton Miller		self.Set(DBUS_NAME,"preserve_network_settings",True)
3640a360c2SBrad Bishop		self.Set(DBUS_NAME,"restore_application_defaults",False)
3740a360c2SBrad Bishop		self.Set(DBUS_NAME,"update_kernel_and_apps",False)
3840a360c2SBrad Bishop		self.Set(DBUS_NAME,"clear_persistent_files",False)
3940a360c2SBrad Bishop
4040a360c2SBrad Bishop		bus.add_signal_receiver(self.download_error_handler,signal_name = "DownloadError")
4140a360c2SBrad Bishop		bus.add_signal_receiver(self.download_complete_handler,signal_name = "DownloadComplete")
4240a360c2SBrad Bishop
4340a360c2SBrad Bishop		self.InterfacesAdded(name,self.properties)
4440a360c2SBrad Bishop
4540a360c2SBrad Bishop
4640a360c2SBrad Bishop	@dbus.service.method(DBUS_NAME,
4740a360c2SBrad Bishop		in_signature='ss', out_signature='')
4840a360c2SBrad Bishop	def updateViaTftp(self,ip,filename):
4940a360c2SBrad Bishop		self.TftpDownload(ip,filename)
5040a360c2SBrad Bishop		self.Set(DBUS_NAME,"status","Downloading")
5140a360c2SBrad Bishop
5240a360c2SBrad Bishop	@dbus.service.method(DBUS_NAME,
5340a360c2SBrad Bishop		in_signature='s', out_signature='')
5440a360c2SBrad Bishop	def update(self,filename):
5540a360c2SBrad Bishop		self.Set(DBUS_NAME,"filename",filename)
5640a360c2SBrad Bishop		self.download_complete_handler(filename, filename)
5740a360c2SBrad Bishop
5840a360c2SBrad Bishop	@dbus.service.signal(DOWNLOAD_INTF,signature='ss')
5940a360c2SBrad Bishop	def TftpDownload(self,ip,filename):
6040a360c2SBrad Bishop		self.Set(DBUS_NAME,"filename",filename)
6140a360c2SBrad Bishop		pass
6240a360c2SBrad Bishop
6340a360c2SBrad Bishop
6440a360c2SBrad Bishop	## Signal handler
6540a360c2SBrad Bishop	def download_error_handler(self,filename):
6640a360c2SBrad Bishop		if (filename == self.Get(DBUS_NAME,"filename")):
6740a360c2SBrad Bishop			self.Set(DBUS_NAME,"status","Download Error")
6840a360c2SBrad Bishop
6940a360c2SBrad Bishop	def download_complete_handler(self,outfile,filename):
7040a360c2SBrad Bishop		## do update
7140a360c2SBrad Bishop		if (filename != self.Get(DBUS_NAME,"filename")):
7240a360c2SBrad Bishop			return
7340a360c2SBrad Bishop
7440a360c2SBrad Bishop		print "Download complete. Updating..."
7540a360c2SBrad Bishop
7640a360c2SBrad Bishop		self.Set(DBUS_NAME,"status","Download Complete")
7740a360c2SBrad Bishop		copy_files = {}
7840a360c2SBrad Bishop
7940a360c2SBrad Bishop		## determine needed files
8040a360c2SBrad Bishop		if (self.Get(DBUS_NAME,"update_kernel_and_apps") == False):
8140a360c2SBrad Bishop			copy_files["image-bmc"] = True
8240a360c2SBrad Bishop		else:
8340a360c2SBrad Bishop			copy_files["image-kernel"] = True
8440a360c2SBrad Bishop			copy_files["image-initramfs"] = True
8540a360c2SBrad Bishop			copy_files["image-rofs"] = True
8640a360c2SBrad Bishop
8740a360c2SBrad Bishop		if (self.Get(DBUS_NAME,"restore_application_defaults") == True):
8840a360c2SBrad Bishop			copy_files["image-rwfs"] = True
8940a360c2SBrad Bishop
9040a360c2SBrad Bishop
9140a360c2SBrad Bishop		## make sure files exist in archive
9240a360c2SBrad Bishop		try:
9340a360c2SBrad Bishop			tar = tarfile.open(outfile,"r")
9440a360c2SBrad Bishop			files = {}
9540a360c2SBrad Bishop			for f in tar.getnames():
9640a360c2SBrad Bishop				files[f] = True
9740a360c2SBrad Bishop			tar.close()
9840a360c2SBrad Bishop			for f in copy_files.keys():
9940a360c2SBrad Bishop				if (files.has_key(f) == False):
10040a360c2SBrad Bishop					raise Exception("ERROR: File not found in update archive: "+f)
10140a360c2SBrad Bishop
10240a360c2SBrad Bishop		except Exception as e:
10340a360c2SBrad Bishop			print e
10440a360c2SBrad Bishop			self.Set(DBUS_NAME,"status","Update Error")
10540a360c2SBrad Bishop			return
10640a360c2SBrad Bishop
10740a360c2SBrad Bishop		try:
10840a360c2SBrad Bishop			tar = tarfile.open(outfile,"r")
10940a360c2SBrad Bishop			tar.extractall(UPDATE_PATH,members=doExtract(tar,copy_files))
11040a360c2SBrad Bishop			tar.close()
11140a360c2SBrad Bishop
11240a360c2SBrad Bishop			if (self.Get(DBUS_NAME,"clear_persistent_files") == True):
11340a360c2SBrad Bishop				print "Removing persistent files"
11440a360c2SBrad Bishop				os.unlink(UPDATE_PATH+"/whitelist")
11540a360c2SBrad Bishop			if (self.Get(DBUS_NAME,"preserve_network_settings") == True):
11640a360c2SBrad Bishop				print "Preserving network settings"
117*c8094109SMilton Miller				shutil.copy2("/run/fw_env",UPDATE_PATH+"/image-u-boot-env")
11840a360c2SBrad Bishop
11940a360c2SBrad Bishop		except Exception as e:
12040a360c2SBrad Bishop			print e
12140a360c2SBrad Bishop			self.Set(DBUS_NAME,"status","Update Error")
12240a360c2SBrad Bishop
12340a360c2SBrad Bishop
12440a360c2SBrad Bishop
12540a360c2SBrad Bishop		self.Set(DBUS_NAME,"status","Update Success.  Please reboot.")
12640a360c2SBrad Bishop
12740a360c2SBrad Bishop
12840a360c2SBrad Bishopif __name__ == '__main__':
12940a360c2SBrad Bishop    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
13040a360c2SBrad Bishop
13140a360c2SBrad Bishop    bus = get_dbus()
13240a360c2SBrad Bishop    name = dbus.service.BusName(DBUS_NAME, bus)
13340a360c2SBrad Bishop    obj = BmcFlashControl(bus, OBJ_NAME)
13440a360c2SBrad Bishop    mainloop = gobject.MainLoop()
13540a360c2SBrad Bishop
13640a360c2SBrad Bishop    print "Running Bmc Flash Control"
13740a360c2SBrad Bishop    mainloop.run()
13840a360c2SBrad Bishop
139