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