1#!/usr/bin/python -u 2 3import gobject 4import dbus 5import dbus.service 6import dbus.mainloop.glib 7import shutil 8import tarfile 9import os 10from obmc.dbuslib.bindings import get_dbus, DbusProperties, DbusObjectManager 11 12DBUS_NAME = 'org.openbmc.control.BmcFlash' 13OBJ_NAME = '/org/openbmc/control/flash/bmc' 14FLASH_INTF = 'org.openbmc.Flash' 15DOWNLOAD_INTF = 'org.openbmc.managers.Download' 16 17UPDATE_PATH = '/run/initramfs' 18 19 20def doExtract(members,files): 21 for tarinfo in members: 22 if files.has_key(tarinfo.name) == True: 23 yield tarinfo 24 25 26class BmcFlashControl(DbusProperties,DbusObjectManager): 27 def __init__(self,bus,name): 28 self.dbus_objects = { } 29 DbusProperties.__init__(self) 30 DbusObjectManager.__init__(self) 31 dbus.service.Object.__init__(self,bus,name) 32 33 self.Set(DBUS_NAME,"status","Idle") 34 self.Set(DBUS_NAME,"filename","") 35 self.Set(DBUS_NAME,"preserve_network_settings",True) 36 self.Set(DBUS_NAME,"restore_application_defaults",False) 37 self.Set(DBUS_NAME,"update_kernel_and_apps",False) 38 self.Set(DBUS_NAME,"clear_persistent_files",False) 39 40 bus.add_signal_receiver(self.download_error_handler,signal_name = "DownloadError") 41 bus.add_signal_receiver(self.download_complete_handler,signal_name = "DownloadComplete") 42 43 self.InterfacesAdded(name,self.properties) 44 45 46 @dbus.service.method(DBUS_NAME, 47 in_signature='ss', out_signature='') 48 def updateViaTftp(self,ip,filename): 49 self.TftpDownload(ip,filename) 50 self.Set(DBUS_NAME,"status","Downloading") 51 52 @dbus.service.method(DBUS_NAME, 53 in_signature='s', out_signature='') 54 def update(self,filename): 55 self.Set(DBUS_NAME,"filename",filename) 56 self.download_complete_handler(filename, filename) 57 58 @dbus.service.signal(DOWNLOAD_INTF,signature='ss') 59 def TftpDownload(self,ip,filename): 60 self.Set(DBUS_NAME,"filename",filename) 61 pass 62 63 64 ## Signal handler 65 def download_error_handler(self,filename): 66 if (filename == self.Get(DBUS_NAME,"filename")): 67 self.Set(DBUS_NAME,"status","Download Error") 68 69 def download_complete_handler(self,outfile,filename): 70 ## do update 71 if (filename != self.Get(DBUS_NAME,"filename")): 72 return 73 74 print "Download complete. Updating..." 75 76 self.Set(DBUS_NAME,"status","Download Complete") 77 copy_files = {} 78 79 ## determine needed files 80 if (self.Get(DBUS_NAME,"update_kernel_and_apps") == False): 81 copy_files["image-bmc"] = True 82 else: 83 copy_files["image-kernel"] = True 84 copy_files["image-initramfs"] = True 85 copy_files["image-rofs"] = True 86 87 if (self.Get(DBUS_NAME,"restore_application_defaults") == True): 88 copy_files["image-rwfs"] = True 89 90 91 ## make sure files exist in archive 92 try: 93 tar = tarfile.open(outfile,"r") 94 files = {} 95 for f in tar.getnames(): 96 files[f] = True 97 tar.close() 98 for f in copy_files.keys(): 99 if (files.has_key(f) == False): 100 raise Exception("ERROR: File not found in update archive: "+f) 101 102 except Exception as e: 103 print e 104 self.Set(DBUS_NAME,"status","Update Error") 105 return 106 107 try: 108 tar = tarfile.open(outfile,"r") 109 tar.extractall(UPDATE_PATH,members=doExtract(tar,copy_files)) 110 tar.close() 111 112 if (self.Get(DBUS_NAME,"clear_persistent_files") == True): 113 print "Removing persistent files" 114 try: 115 os.unlink(UPDATE_PATH+"/whitelist") 116 except OSError as e: 117 if (e.errno == errno.EISDIR): 118 pass 119 elif (e.errno == errno.ENOENT): 120 pass 121 else: 122 raise 123 124 try: 125 wldir = UPDATE_PATH + "/whitelist.d" 126 127 for file in os.listdir(wldir): 128 os.unlink(os.path.join(wldir,file)) 129 except OSError as e: 130 if (e.errno == errno.EISDIR): 131 pass 132 else: 133 raise 134 135 if (self.Get(DBUS_NAME,"preserve_network_settings") == True): 136 print "Preserving network settings" 137 shutil.copy2("/run/fw_env",UPDATE_PATH+"/image-u-boot-env") 138 139 except Exception as e: 140 print e 141 self.Set(DBUS_NAME,"status","Update Error") 142 143 144 145 self.Set(DBUS_NAME,"status","Update Success. Please reboot.") 146 147 148if __name__ == '__main__': 149 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) 150 151 bus = get_dbus() 152 name = dbus.service.BusName(DBUS_NAME, bus) 153 obj = BmcFlashControl(bus, OBJ_NAME) 154 mainloop = gobject.MainLoop() 155 156 print "Running Bmc Flash Control" 157 mainloop.run() 158 159