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