1 #include <stdio.h> 2 #include <stdbool.h> 3 #include <string.h> 4 #include <sys/wait.h> 5 #include <sys/types.h> 6 #include <openbmc_intf.h> 7 #include <openbmc.h> 8 9 /* ------------------------------------------------------------------------- */ 10 static const gchar* dbus_object_path = "/org/openbmc/control/flash"; 11 static const gchar* dbus_name = "org.openbmc.control.Flash"; 12 static const gchar* FLASHER_BIN = "flasher.exe"; 13 14 static GDBusObjectManagerServer *manager = NULL; 15 16 void 17 catch_child(int sig_num) 18 { 19 /* when we get here, we know there's a zombie child waiting */ 20 int child_status; 21 22 wait(&child_status); 23 printf("flasher exited.\n"); 24 } 25 26 int 27 update(Flash* flash, const char* obj_path) 28 { 29 pid_t pid; 30 int status=-1; 31 pid = fork(); 32 if(pid == 0) 33 { 34 const gchar* name = flash_get_flasher_name(flash); 35 const gchar* inst = flash_get_flasher_instance(flash); 36 const gchar* filename = flash_get_filename(flash); 37 status = execlp(name, name, inst, filename, obj_path, NULL); 38 return status; 39 } 40 return 0; 41 } 42 43 static gboolean 44 on_init(Flash *f, 45 GDBusMethodInvocation *invocation, 46 gpointer user_data) 47 { 48 flash_complete_init(f,invocation); 49 50 //tune flash 51 if(strcmp(flash_get_flasher_instance(f),"bios") == 0) 52 { 53 flash_set_filename(f,""); 54 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data); 55 int rc = update(f,obj_path); 56 if(rc==-1) 57 { 58 printf("ERROR FlashControl: Unable to init\n"); 59 } 60 sleep(3); 61 rc = update(f,obj_path); 62 63 } 64 return TRUE; 65 } 66 67 static gboolean 68 on_lock(SharedResource *lock, 69 GDBusMethodInvocation *invocation, 70 gchar* name, 71 gpointer user_data) 72 { 73 gboolean locked = shared_resource_get_lock(lock); 74 if(locked) 75 { 76 const gchar* name = shared_resource_get_name(lock); 77 printf("ERROR: BIOS Flash is already locked: %s\n",name); 78 } 79 else 80 { 81 printf("Locking BIOS Flash: %s\n",name); 82 shared_resource_set_lock(lock,true); 83 shared_resource_set_name(lock,name); 84 } 85 shared_resource_complete_lock(lock,invocation); 86 return TRUE; 87 } 88 89 static gboolean 90 on_is_locked(SharedResource *lock, 91 GDBusMethodInvocation *invocation, 92 gpointer user_data) 93 { 94 gboolean locked = shared_resource_get_lock(lock); 95 const gchar* name = shared_resource_get_name(lock); 96 shared_resource_complete_is_locked(lock,invocation,locked,name); 97 return TRUE; 98 } 99 100 static gboolean 101 on_unlock(SharedResource *lock, 102 GDBusMethodInvocation *invocation, 103 gpointer user_data) 104 { 105 printf("Unlocking BIOS Flash\n"); 106 shared_resource_set_lock(lock,false); 107 shared_resource_set_name(lock,""); 108 shared_resource_complete_unlock(lock,invocation); 109 return TRUE; 110 } 111 112 static gboolean 113 on_update_via_tftp(Flash *flash, 114 GDBusMethodInvocation *invocation, 115 gchar* url, 116 gchar* write_file, 117 gpointer user_data) 118 { 119 SharedResource *lock = object_get_shared_resource((Object*)user_data); 120 gboolean locked = shared_resource_get_lock(lock); 121 flash_complete_update_via_tftp(flash,invocation); 122 if(locked) 123 { 124 const gchar* name = shared_resource_get_name(lock); 125 printf("BIOS Flash is locked: %s\n",name); 126 } 127 else 128 { 129 printf("Flashing BIOS from TFTP: %s,%s\n",url,write_file); 130 flash_set_filename(flash,write_file); 131 flash_emit_download(flash,url,write_file); 132 flash_set_status(flash,"Downloading"); 133 } 134 return TRUE; 135 } 136 137 static gboolean 138 on_error(Flash *flash, 139 GDBusMethodInvocation *invocation, 140 gchar* error_msg, 141 gpointer user_data) 142 { 143 SharedResource *lock = object_get_shared_resource((Object*)user_data); 144 shared_resource_get_lock(lock); 145 flash_set_status(flash, error_msg); 146 flash_complete_error(flash,invocation); 147 printf("ERROR: %s. Clearing locks\n",error_msg); 148 shared_resource_set_lock(lock,false); 149 shared_resource_set_name(lock,""); 150 151 return TRUE; 152 } 153 154 static gboolean 155 on_done(Flash *flash, 156 GDBusMethodInvocation *invocation, 157 gpointer user_data) 158 { 159 int rc = 0; 160 SharedResource *lock = object_get_shared_resource((Object*)user_data); 161 shared_resource_get_lock(lock); 162 flash_set_status(flash, "Flash Done"); 163 flash_complete_done(flash,invocation); 164 printf("Flash Done. Clearing locks\n"); 165 shared_resource_set_lock(lock,false); 166 shared_resource_set_name(lock,""); 167 const gchar* filename = flash_get_filename(flash); 168 rc = unlink(filename); 169 if(rc != 0 ) 170 { 171 printf("ERROR: Unable to delete file %s (%d)\n",filename,rc); 172 } 173 174 return TRUE; 175 } 176 177 static gboolean 178 on_update(Flash *flash, 179 GDBusMethodInvocation *invocation, 180 gchar* write_file, 181 gpointer user_data) 182 { 183 int rc = 0; 184 SharedResource *lock = object_get_shared_resource((Object*)user_data); 185 gboolean locked = shared_resource_get_lock(lock); 186 flash_set_status(flash,"Flashing"); 187 flash_complete_update(flash,invocation); 188 if(locked) 189 { 190 const gchar* name = shared_resource_get_name(lock); 191 printf("BIOS Flash is locked: %s\n",name); 192 } 193 else 194 { 195 printf("Flashing BIOS from: %s\n",write_file); 196 flash_set_status(flash, "Flashing"); 197 shared_resource_set_lock(lock,true); 198 shared_resource_set_name(lock,dbus_object_path); 199 flash_set_filename(flash,write_file); 200 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data); 201 rc = update(flash,obj_path); 202 if(!rc) 203 { 204 shared_resource_set_lock(lock,false); 205 shared_resource_set_name(lock,""); 206 } 207 } 208 return TRUE; 209 } 210 211 static void 212 on_flash_progress(GDBusConnection* connection, 213 const gchar* sender_name, 214 const gchar* object_path, 215 const gchar* interface_name, 216 const gchar* signal_name, 217 GVariant* parameters, 218 gpointer user_data) 219 { 220 Flash *flash = object_get_flash((Object*)user_data); 221 object_get_shared_resource((Object*)user_data); 222 GVariantIter *iter = g_variant_iter_new(parameters); 223 g_variant_iter_next_value(iter); 224 GVariant* v_progress = g_variant_iter_next_value(iter); 225 226 uint8_t progress = g_variant_get_byte(v_progress); 227 228 gchar *s; 229 s = g_strdup_printf("Flashing: %d%%",progress); 230 flash_set_status(flash,s); 231 g_free(s); 232 } 233 234 static void 235 on_bus_acquired(GDBusConnection *connection, 236 const gchar *name, 237 gpointer user_data) 238 { 239 ObjectSkeleton *object; 240 cmdline *cmd = user_data; 241 manager = g_dbus_object_manager_server_new(dbus_object_path); 242 int i=0; 243 244 gchar *flasher_file = g_strdup_printf("%s", FLASHER_BIN); 245 246 const char* inst[] = {"bios"}; 247 for(i=0;i<1;i++) 248 { 249 gchar* s; 250 s = g_strdup_printf("%s/%s",dbus_object_path,inst[i]); 251 object = object_skeleton_new(s); 252 g_free(s); 253 254 Flash* flash = flash_skeleton_new(); 255 object_skeleton_set_flash(object, flash); 256 g_object_unref(flash); 257 258 SharedResource* lock = shared_resource_skeleton_new(); 259 object_skeleton_set_shared_resource(object, lock); 260 g_object_unref(lock); 261 262 shared_resource_set_lock(lock,false); 263 shared_resource_set_name(lock,""); 264 265 flash_set_flasher_name(flash,FLASHER_BIN); 266 flash_set_flasher_instance(flash,inst[i]); 267 //g_free (s); 268 269 270 //define method callbacks here 271 g_signal_connect(lock, 272 "handle-lock", 273 G_CALLBACK(on_lock), 274 NULL); /* user_data */ 275 g_signal_connect(lock, 276 "handle-unlock", 277 G_CALLBACK(on_unlock), 278 NULL); /* user_data */ 279 g_signal_connect(lock, 280 "handle-is-locked", 281 G_CALLBACK(on_is_locked), 282 NULL); /* user_data */ 283 284 g_signal_connect(flash, 285 "handle-update", 286 G_CALLBACK(on_update), 287 object); /* user_data */ 288 289 g_signal_connect(flash, 290 "handle-error", 291 G_CALLBACK(on_error), 292 object); /* user_data */ 293 294 g_signal_connect(flash, 295 "handle-done", 296 G_CALLBACK(on_done), 297 object); /* user_data */ 298 299 g_signal_connect(flash, 300 "handle-update-via-tftp", 301 G_CALLBACK(on_update_via_tftp), 302 object); /* user_data */ 303 304 g_signal_connect(flash, 305 "handle-init", 306 G_CALLBACK(on_init), 307 object); /* user_data */ 308 309 s = g_strdup_printf("/org/openbmc/control/%s",inst[i]); 310 g_dbus_connection_signal_subscribe(connection, 311 NULL, 312 "org.openbmc.FlashControl", 313 "Progress", 314 s, 315 NULL, 316 G_DBUS_SIGNAL_FLAGS_NONE, 317 (GDBusSignalCallback) on_flash_progress, 318 object, 319 NULL ); 320 321 g_free(s); 322 323 324 flash_set_filename(flash,""); 325 /* Export the object (@manager takes its own reference to @object) */ 326 g_dbus_object_manager_server_set_connection(manager, connection); 327 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object)); 328 g_object_unref(object); 329 } 330 g_free(flasher_file); 331 } 332 333 static void 334 on_name_acquired(GDBusConnection *connection, 335 const gchar *name, 336 gpointer user_data) 337 { 338 // g_print ("Acquired the name %s\n", name); 339 } 340 341 static void 342 on_name_lost(GDBusConnection *connection, 343 const gchar *name, 344 gpointer user_data) 345 { 346 //g_print ("Lost the name %s\n", name); 347 } 348 349 gint 350 main(gint argc, gchar *argv[]) 351 { 352 GMainLoop *loop; 353 cmdline cmd; 354 cmd.argc = argc; 355 cmd.argv = argv; 356 guint id; 357 loop = g_main_loop_new(NULL, FALSE); 358 359 signal(SIGCHLD, catch_child); 360 id = g_bus_own_name(DBUS_TYPE, 361 dbus_name, 362 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | 363 G_BUS_NAME_OWNER_FLAGS_REPLACE, 364 on_bus_acquired, 365 on_name_acquired, 366 on_name_lost, 367 &cmd, 368 NULL); 369 370 g_main_loop_run(loop); 371 372 g_bus_unown_name(id); 373 g_main_loop_unref(loop); 374 return 0; 375 } 376