#include #include #include #include #include #include #include /* ------------------------------------------------------------------------- */ static const gchar* dbus_object_path = "/org/openbmc/control/flash"; static const gchar* dbus_name = "org.openbmc.control.Flash"; static const gchar* FLASHER_BIN = "flasher.exe"; static GDBusObjectManagerServer *manager = NULL; void catch_child(int sig_num) { /* when we get here, we know there's a zombie child waiting */ int child_status; wait(&child_status); printf("flasher exited.\n"); } int update(Flash* flash, const char* obj_path) { pid_t pid; int status=-1; pid = fork(); if(pid == 0) { const gchar* name = flash_get_flasher_name(flash); const gchar* inst = flash_get_flasher_instance(flash); const gchar* filename = flash_get_filename(flash); status = execlp(name, name, inst, filename, obj_path, NULL); return status; } return 0; } static gboolean on_init(Flash *f, GDBusMethodInvocation *invocation, gpointer user_data) { flash_complete_init(f,invocation); //tune flash if(strcmp(flash_get_flasher_instance(f),"bios") == 0) { flash_set_filename(f,""); const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data); int rc = update(f,obj_path); if(rc==-1) { printf("ERROR FlashControl: Unable to init\n"); } sleep(3); rc = update(f,obj_path); } return TRUE; } static gboolean on_lock(SharedResource *lock, GDBusMethodInvocation *invocation, gchar* name, gpointer user_data) { gboolean locked = shared_resource_get_lock(lock); if(locked) { const gchar* name = shared_resource_get_name(lock); printf("ERROR: BIOS Flash is already locked: %s\n",name); } else { printf("Locking BIOS Flash: %s\n",name); shared_resource_set_lock(lock,true); shared_resource_set_name(lock,name); } shared_resource_complete_lock(lock,invocation); return TRUE; } static gboolean on_is_locked(SharedResource *lock, GDBusMethodInvocation *invocation, gpointer user_data) { gboolean locked = shared_resource_get_lock(lock); const gchar* name = shared_resource_get_name(lock); shared_resource_complete_is_locked(lock,invocation,locked,name); return TRUE; } static gboolean on_unlock(SharedResource *lock, GDBusMethodInvocation *invocation, gpointer user_data) { printf("Unlocking BIOS Flash\n"); shared_resource_set_lock(lock,false); shared_resource_set_name(lock,""); shared_resource_complete_unlock(lock,invocation); return TRUE; } static gboolean on_update_via_tftp(Flash *flash, GDBusMethodInvocation *invocation, gchar* url, gchar* write_file, gpointer user_data) { SharedResource *lock = object_get_shared_resource((Object*)user_data); gboolean locked = shared_resource_get_lock(lock); flash_complete_update_via_tftp(flash,invocation); if(locked) { const gchar* name = shared_resource_get_name(lock); printf("BIOS Flash is locked: %s\n",name); } else { printf("Flashing BIOS from TFTP: %s,%s\n",url,write_file); flash_set_filename(flash,write_file); flash_emit_download(flash,url,write_file); flash_set_status(flash,"Downloading"); } return TRUE; } static gboolean on_error(Flash *flash, GDBusMethodInvocation *invocation, gchar* error_msg, gpointer user_data) { SharedResource *lock = object_get_shared_resource((Object*)user_data); shared_resource_get_lock(lock); flash_set_status(flash, error_msg); flash_complete_error(flash,invocation); printf("ERROR: %s. Clearing locks\n",error_msg); shared_resource_set_lock(lock,false); shared_resource_set_name(lock,""); return TRUE; } static gboolean on_done(Flash *flash, GDBusMethodInvocation *invocation, gpointer user_data) { int rc = 0; SharedResource *lock = object_get_shared_resource((Object*)user_data); shared_resource_get_lock(lock); flash_set_status(flash, "Flash Done"); flash_complete_done(flash,invocation); printf("Flash Done. Clearing locks\n"); shared_resource_set_lock(lock,false); shared_resource_set_name(lock,""); const gchar* filename = flash_get_filename(flash); rc = unlink(filename); if(rc != 0 ) { printf("ERROR: Unable to delete file %s (%d)\n",filename,rc); } return TRUE; } static gboolean on_update(Flash *flash, GDBusMethodInvocation *invocation, gchar* write_file, gpointer user_data) { int rc = 0; SharedResource *lock = object_get_shared_resource((Object*)user_data); gboolean locked = shared_resource_get_lock(lock); flash_set_status(flash,"Flashing"); flash_complete_update(flash,invocation); if(locked) { const gchar* name = shared_resource_get_name(lock); printf("BIOS Flash is locked: %s\n",name); } else { printf("Flashing BIOS from: %s\n",write_file); flash_set_status(flash, "Flashing"); shared_resource_set_lock(lock,true); shared_resource_set_name(lock,dbus_object_path); flash_set_filename(flash,write_file); const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data); rc = update(flash,obj_path); if(!rc) { shared_resource_set_lock(lock,false); shared_resource_set_name(lock,""); } } return TRUE; } static void on_flash_progress(GDBusConnection* connection, const gchar* sender_name, const gchar* object_path, const gchar* interface_name, const gchar* signal_name, GVariant* parameters, gpointer user_data) { Flash *flash = object_get_flash((Object*)user_data); object_get_shared_resource((Object*)user_data); GVariantIter *iter = g_variant_iter_new(parameters); g_variant_iter_next_value(iter); GVariant* v_progress = g_variant_iter_next_value(iter); uint8_t progress = g_variant_get_byte(v_progress); gchar *s; s = g_strdup_printf("Flashing: %d%%",progress); flash_set_status(flash,s); g_free(s); } static void on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) { ObjectSkeleton *object; cmdline *cmd = user_data; manager = g_dbus_object_manager_server_new(dbus_object_path); int i=0; gchar *flasher_file = g_strdup_printf("%s", FLASHER_BIN); const char* inst[] = {"bios"}; for(i=0;i<1;i++) { gchar* s; s = g_strdup_printf("%s/%s",dbus_object_path,inst[i]); object = object_skeleton_new(s); g_free(s); Flash* flash = flash_skeleton_new(); object_skeleton_set_flash(object, flash); g_object_unref(flash); SharedResource* lock = shared_resource_skeleton_new(); object_skeleton_set_shared_resource(object, lock); g_object_unref(lock); shared_resource_set_lock(lock,false); shared_resource_set_name(lock,""); flash_set_flasher_name(flash,FLASHER_BIN); flash_set_flasher_instance(flash,inst[i]); //g_free (s); //define method callbacks here g_signal_connect(lock, "handle-lock", G_CALLBACK(on_lock), NULL); /* user_data */ g_signal_connect(lock, "handle-unlock", G_CALLBACK(on_unlock), NULL); /* user_data */ g_signal_connect(lock, "handle-is-locked", G_CALLBACK(on_is_locked), NULL); /* user_data */ g_signal_connect(flash, "handle-update", G_CALLBACK(on_update), object); /* user_data */ g_signal_connect(flash, "handle-error", G_CALLBACK(on_error), object); /* user_data */ g_signal_connect(flash, "handle-done", G_CALLBACK(on_done), object); /* user_data */ g_signal_connect(flash, "handle-update-via-tftp", G_CALLBACK(on_update_via_tftp), object); /* user_data */ g_signal_connect(flash, "handle-init", G_CALLBACK(on_init), object); /* user_data */ s = g_strdup_printf("/org/openbmc/control/%s",inst[i]); g_dbus_connection_signal_subscribe(connection, NULL, "org.openbmc.FlashControl", "Progress", s, NULL, G_DBUS_SIGNAL_FLAGS_NONE, (GDBusSignalCallback) on_flash_progress, object, NULL ); g_free(s); flash_set_filename(flash,""); /* Export the object (@manager takes its own reference to @object) */ g_dbus_object_manager_server_set_connection(manager, connection); g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object)); g_object_unref(object); } g_free(flasher_file); } static void on_name_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data) { // g_print ("Acquired the name %s\n", name); } static void on_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data) { //g_print ("Lost the name %s\n", name); } gint main(gint argc, gchar *argv[]) { GMainLoop *loop; cmdline cmd; cmd.argc = argc; cmd.argv = argv; guint id; loop = g_main_loop_new(NULL, FALSE); signal(SIGCHLD, catch_child); id = g_bus_own_name(DBUS_TYPE, dbus_name, G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | G_BUS_NAME_OWNER_FLAGS_REPLACE, on_bus_acquired, on_name_acquired, on_name_lost, &cmd, NULL); g_main_loop_run(loop); g_bus_unown_name(id); g_main_loop_unref(loop); return 0; }