blob: bbd1c5587be3251b3e0c5a4d717d6904eddb1b6b [file] [log] [blame]
Norman James18998182015-10-11 21:54:53 -05001#include <stdio.h>
2#include <stdbool.h>
3#include <string.h>
Norman James362a80f2015-09-14 14:04:39 -05004#include "interfaces/openbmc_intf.h"
Norman James10ff6a32015-08-27 14:24:17 -05005#include "openbmc.h"
Norman Jamescfc2b442015-10-31 17:31:46 -05006#include "object_mapper.h"
Norman Jamese2765102015-08-19 22:00:55 -05007
8/* ---------------------------------------------------------------------------------------------------- */
Norman James166acf42015-10-22 07:11:51 -05009static const gchar* dbus_object_path = "/org/openbmc/control/flash";
10static const gchar* dbus_name = "org.openbmc.control.Flash";
Norman James18998182015-10-11 21:54:53 -050011static const gchar* FLASHER_BIN = "flasher.exe";
12static const gchar* DLOAD_BUS = "org.openbmc.managers.Download";
13static const gchar* DLOAD_OBJ = "/org/openbmc/managers/Download";
Norman Jamese2765102015-08-19 22:00:55 -050014
15static GDBusObjectManagerServer *manager = NULL;
Norman Jamese2765102015-08-19 22:00:55 -050016
Norman Jamesc8719dd2015-11-01 07:38:02 -060017void 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
Norman James166acf42015-10-22 07:11:51 -050027int update(Flash* flash, const char* obj_path)
Norman Jamesf066e872015-10-07 15:29:51 -050028{
Norman James18998182015-10-11 21:54:53 -050029 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);
Norman James166acf42015-10-22 07:11:51 -050038 status = execl(path, name, inst, filename, obj_path, NULL);
Norman Jamesa3e47c42015-10-18 14:43:10 -050039 return status;
Norman Jamesf066e872015-10-07 15:29:51 -050040 }
Norman Jamesa3e47c42015-10-18 14:43:10 -050041 return 0;
Norman Jamesf066e872015-10-07 15:29:51 -050042}
43
Norman Jamese2765102015-08-19 22:00:55 -050044static gboolean
Norman James471ab592015-08-30 22:29:40 -050045on_init (Flash *f,
46 GDBusMethodInvocation *invocation,
47 gpointer user_data)
48{
Norman James65a295a2015-09-26 22:21:10 -050049 flash_complete_init(f,invocation);
Norman James068efb32015-10-06 16:52:28 -050050
Norman James18998182015-10-11 21:54:53 -050051 //tune flash
Norman James166acf42015-10-22 07:11:51 -050052 if (strcmp(flash_get_flasher_instance(f),"bios") == 0)
Norman James18998182015-10-11 21:54:53 -050053 {
Norman James166acf42015-10-22 07:11:51 -050054 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 }
Norman Jamesd1f41c72015-11-01 20:30:13 -060061 sleep(3);
62 rc = update(f,obj_path);
63
Norman James18998182015-10-11 21:54:53 -050064 }
65 return TRUE;
66}
Norman James068efb32015-10-06 16:52:28 -050067
Norman James18998182015-10-11 21:54:53 -050068static gboolean
69on_lock (SharedResource *lock,
70 GDBusMethodInvocation *invocation,
71 gchar* name,
72 gpointer user_data)
73{
Norman Jamesa3e47c42015-10-18 14:43:10 -050074 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 }
Norman James18998182015-10-11 21:54:53 -050086 shared_resource_complete_lock(lock,invocation);
87 return TRUE;
88}
89static gboolean
90on_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
101static gboolean
102on_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);
Norman James65a295a2015-09-26 22:21:10 -0500110 return TRUE;
Norman James471ab592015-08-30 22:29:40 -0500111}
112
113static gboolean
Norman Jamesf066e872015-10-07 15:29:51 -0500114on_update_via_tftp (Flash *flash,
115 GDBusMethodInvocation *invocation,
116 gchar* url,
117 gchar* write_file,
118 gpointer user_data)
119{
Norman James18998182015-10-11 21:54:53 -0500120 SharedResource *lock = object_get_shared_resource((Object*)user_data);
121 gboolean locked = shared_resource_get_lock(lock);
Norman Jamesf066e872015-10-07 15:29:51 -0500122 flash_complete_update_via_tftp(flash,invocation);
Norman James18998182015-10-11 21:54:53 -0500123 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);
Norman James18998182015-10-11 21:54:53 -0500131 flash_set_filename(flash,write_file);
132 flash_emit_download(flash,url,write_file);
Norman James166acf42015-10-22 07:11:51 -0500133 flash_set_status(flash,"Downloading");
Norman James18998182015-10-11 21:54:53 -0500134 }
Norman Jamesf066e872015-10-07 15:29:51 -0500135 return TRUE;
136}
137
138static gboolean
Norman James166acf42015-10-22 07:11:51 -0500139on_error (Flash *flash,
140 GDBusMethodInvocation *invocation,
141 gchar* error_msg,
142 gpointer user_data)
143{
144 int rc = 0;
145 SharedResource *lock = object_get_shared_resource((Object*)user_data);
146 gboolean locked = shared_resource_get_lock(lock);
147 flash_set_status(flash, error_msg);
148 flash_complete_error(flash,invocation);
149 printf("ERROR: %s. Clearing locks\n",error_msg);
150 shared_resource_set_lock(lock,false);
151 shared_resource_set_name(lock,"");
152
153 return TRUE;
154}
155static gboolean
156on_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 gboolean locked = 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,"");
Norman James8af7d4a2016-01-06 14:09:08 -0600168 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 }
Norman James166acf42015-10-22 07:11:51 -0500174
175 return TRUE;
176}
177
178
179static gboolean
Norman Jamesf066e872015-10-07 15:29:51 -0500180on_update (Flash *flash,
Norman Jamese2765102015-08-19 22:00:55 -0500181 GDBusMethodInvocation *invocation,
182 gchar* write_file,
183 gpointer user_data)
184{
Norman James18998182015-10-11 21:54:53 -0500185 int rc = 0;
186 SharedResource *lock = object_get_shared_resource((Object*)user_data);
187 gboolean locked = shared_resource_get_lock(lock);
Norman James166acf42015-10-22 07:11:51 -0500188 flash_set_status(flash,"Flashing");
Norman Jamesf066e872015-10-07 15:29:51 -0500189 flash_complete_update(flash,invocation);
Norman James18998182015-10-11 21:54:53 -0500190 if (locked)
191 {
192 const gchar* name = shared_resource_get_name(lock);
193 printf("BIOS Flash is locked: %s\n",name);
194 }
195 else
196 {
197 printf("Flashing BIOS from: %s\n",write_file);
Norman James166acf42015-10-22 07:11:51 -0500198 flash_set_status(flash, "Flashing");
Norman James18998182015-10-11 21:54:53 -0500199 shared_resource_set_lock(lock,true);
200 shared_resource_set_name(lock,dbus_object_path);
201 flash_set_filename(flash,write_file);
Norman James166acf42015-10-22 07:11:51 -0500202 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data);
203 rc = update(flash,obj_path);
Norman James18998182015-10-11 21:54:53 -0500204 if (!rc)
205 {
206 shared_resource_set_lock(lock,false);
207 shared_resource_set_name(lock,"");
208 }
209 }
Norman James068efb32015-10-06 16:52:28 -0500210 return TRUE;
Norman Jamese2765102015-08-19 22:00:55 -0500211}
Norman James18998182015-10-11 21:54:53 -0500212static void
213on_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 SharedResource *lock = object_get_shared_resource((Object*)user_data);
223 GVariantIter *iter = g_variant_iter_new(parameters);
224 GVariant* v_filename = g_variant_iter_next_value(iter);
225 GVariant* v_progress = g_variant_iter_next_value(iter);
Norman Jamesf066e872015-10-07 15:29:51 -0500226
Norman James18998182015-10-11 21:54:53 -0500227 uint8_t progress = g_variant_get_byte(v_progress);
Norman James166acf42015-10-22 07:11:51 -0500228
229 gchar *s;
230 s = g_strdup_printf ("Flashing: %d%%",progress);
231 flash_set_status(flash,s);
232 g_free(s);
Norman James18998182015-10-11 21:54:53 -0500233}
234
235static void
236on_flash_done (GDBusConnection* connection,
237 const gchar* sender_name,
238 const gchar* object_path,
239 const gchar* interface_name,
240 const gchar* signal_name,
241 GVariant* parameters,
242 gpointer user_data)
243{
244 Flash *flash = object_get_flash((Object*)user_data);
245 SharedResource *lock = object_get_shared_resource((Object*)user_data);
246 printf("Flash succeeded; unlocking flash\n");
247 shared_resource_set_lock(lock,false);
248 shared_resource_set_name(lock,"");
Norman James166acf42015-10-22 07:11:51 -0500249 flash_set_status(flash,"Flash Done");
Norman James18998182015-10-11 21:54:53 -0500250}
251
252static void
253on_flash_error (GDBusConnection* connection,
254 const gchar* sender_name,
255 const gchar* object_path,
256 const gchar* interface_name,
257 const gchar* signal_name,
258 GVariant* parameters,
259 gpointer user_data)
260{
261 Flash *flash = object_get_flash((Object*)user_data);
262 SharedResource *lock = object_get_shared_resource((Object*)user_data);
263 printf("Flash Error; unlocking flash\n");
264 shared_resource_set_lock(lock,false);
265 shared_resource_set_name(lock,"");
266}
267
268static void
269on_download_error (GDBusConnection* connection,
270 const gchar* sender_name,
271 const gchar* object_path,
272 const gchar* interface_name,
273 const gchar* signal_name,
274 GVariant* parameters,
275 gpointer user_data)
276{
277 Flash *flash = object_get_flash((Object*)user_data);
278 SharedResource *lock = object_get_shared_resource((Object*)user_data);
279 printf("ERROR: FlashBios: Download error; clearing flash lock\n");
280 shared_resource_set_lock(lock,false);
281 shared_resource_set_name(lock,"");
Norman Jamesf066e872015-10-07 15:29:51 -0500282}
283
Norman Jamese2765102015-08-19 22:00:55 -0500284static void
285on_bus_acquired (GDBusConnection *connection,
286 const gchar *name,
287 gpointer user_data)
288{
Norman James10ff6a32015-08-27 14:24:17 -0500289 ObjectSkeleton *object;
Norman James10ff6a32015-08-27 14:24:17 -0500290 cmdline *cmd = user_data;
Norman James10ff6a32015-08-27 14:24:17 -0500291 manager = g_dbus_object_manager_server_new (dbus_object_path);
292 int i=0;
Norman James166acf42015-10-22 07:11:51 -0500293
294 //TODO: don't use fixed buffer
295 char flasher_path[512];
296 memset(flasher_path, '\0', sizeof(flasher_path));
297 bool found = false;
298 gchar *flasher_file;
299 int c = strlen(cmd->argv[0]);
300 while(c>0)
301 {
302 if (cmd->argv[0][c] == '/')
303 {
304 strncpy(flasher_path,cmd->argv[0],c);
305 flasher_file = g_strdup_printf ("%s/%s",flasher_path,FLASHER_BIN);
306 break;
307 }
308 c--;
309 }
310
Norman James15aaa802015-10-28 06:54:48 -0500311 const char* inst[] = {"bios","bmc","bmc_ramdisk","bmc_kernel"};
312 for (i=0;i<4;i++)
Norman James10ff6a32015-08-27 14:24:17 -0500313 {
Norman James166acf42015-10-22 07:11:51 -0500314 gchar* s;
315 s = g_strdup_printf ("%s/%s",dbus_object_path,inst[i]);
Norman James10ff6a32015-08-27 14:24:17 -0500316 object = object_skeleton_new (s);
317 g_free (s);
Norman Jamese2765102015-08-19 22:00:55 -0500318
Norman James10ff6a32015-08-27 14:24:17 -0500319 Flash* flash = flash_skeleton_new ();
320 object_skeleton_set_flash (object, flash);
321 g_object_unref (flash);
Norman Jamese2765102015-08-19 22:00:55 -0500322
Norman James18998182015-10-11 21:54:53 -0500323 SharedResource* lock = shared_resource_skeleton_new ();
324 object_skeleton_set_shared_resource (object, lock);
325 g_object_unref (lock);
326
Norman Jamescfc2b442015-10-31 17:31:46 -0500327 ObjectMapper* mapper = object_mapper_skeleton_new ();
328 object_skeleton_set_object_mapper (object, mapper);
329 g_object_unref (mapper);
330
Norman James18998182015-10-11 21:54:53 -0500331 shared_resource_set_lock(lock,false);
332 shared_resource_set_name(lock,"");
333
Norman James166acf42015-10-22 07:11:51 -0500334 flash_set_flasher_path(flash,flasher_file);
335 flash_set_flasher_name(flash,FLASHER_BIN);
336 flash_set_flasher_instance(flash,inst[i]);
337 //g_free (s);
Norman James18998182015-10-11 21:54:53 -0500338
339
Norman James10ff6a32015-08-27 14:24:17 -0500340 //define method callbacks here
Norman James18998182015-10-11 21:54:53 -0500341 g_signal_connect (lock,
342 "handle-lock",
343 G_CALLBACK (on_lock),
344 NULL); /* user_data */
345 g_signal_connect (lock,
346 "handle-unlock",
347 G_CALLBACK (on_unlock),
348 NULL); /* user_data */
349 g_signal_connect (lock,
350 "handle-is-locked",
351 G_CALLBACK (on_is_locked),
352 NULL); /* user_data */
353
Norman James10ff6a32015-08-27 14:24:17 -0500354 g_signal_connect (flash,
Norman James8c6d8382015-10-06 07:47:16 -0500355 "handle-update",
356 G_CALLBACK (on_update),
Norman James18998182015-10-11 21:54:53 -0500357 object); /* user_data */
Norman James166acf42015-10-22 07:11:51 -0500358
359 g_signal_connect (flash,
360 "handle-error",
361 G_CALLBACK (on_error),
362 object); /* user_data */
363
364 g_signal_connect (flash,
365 "handle-done",
366 G_CALLBACK (on_done),
367 object); /* user_data */
368
Norman Jamesf066e872015-10-07 15:29:51 -0500369 g_signal_connect (flash,
370 "handle-update-via-tftp",
371 G_CALLBACK (on_update_via_tftp),
Norman James18998182015-10-11 21:54:53 -0500372 object); /* user_data */
Norman Jamesf066e872015-10-07 15:29:51 -0500373
Norman James471ab592015-08-30 22:29:40 -0500374 g_signal_connect (flash,
375 "handle-init",
376 G_CALLBACK (on_init),
Norman James166acf42015-10-22 07:11:51 -0500377 object); /* user_data */
Norman James471ab592015-08-30 22:29:40 -0500378
Norman James166acf42015-10-22 07:11:51 -0500379 s = g_strdup_printf ("/org/openbmc/control/%s",inst[i]);
Norman James18998182015-10-11 21:54:53 -0500380 g_dbus_connection_signal_subscribe(connection,
381 NULL,
382 "org.openbmc.FlashControl",
383 "Progress",
384 s,
385 NULL,
386 G_DBUS_SIGNAL_FLAGS_NONE,
387 (GDBusSignalCallback) on_flash_progress,
388 object,
389 NULL );
390
391 g_free (s);
Norman Jamesf066e872015-10-07 15:29:51 -0500392
Norman James471ab592015-08-30 22:29:40 -0500393
Norman James18998182015-10-11 21:54:53 -0500394 flash_set_filename(flash,"");
Norman James10ff6a32015-08-27 14:24:17 -0500395 /* Export the object (@manager takes its own reference to @object) */
396 g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
397 g_object_unref (object);
398 }
Norman James166acf42015-10-22 07:11:51 -0500399 g_free(flasher_file);
Norman James10ff6a32015-08-27 14:24:17 -0500400 /* Export all objects */
401 g_dbus_object_manager_server_set_connection (manager, connection);
Norman Jamescfc2b442015-10-31 17:31:46 -0500402 emit_object_added((GDBusObjectManager*)manager);
Norman Jamese2765102015-08-19 22:00:55 -0500403}
404
405static void
406on_name_acquired (GDBusConnection *connection,
407 const gchar *name,
408 gpointer user_data)
409{
Norman James362a80f2015-09-14 14:04:39 -0500410// g_print ("Acquired the name %s\n", name);
Norman Jamese2765102015-08-19 22:00:55 -0500411}
412
413static void
414on_name_lost (GDBusConnection *connection,
415 const gchar *name,
416 gpointer user_data)
417{
Norman James362a80f2015-09-14 14:04:39 -0500418 //g_print ("Lost the name %s\n", name);
Norman Jamese2765102015-08-19 22:00:55 -0500419}
420
421gint
422main (gint argc, gchar *argv[])
423{
424 GMainLoop *loop;
Norman James952b38d2015-08-27 21:30:06 -0500425 cmdline cmd;
426 cmd.argc = argc;
427 cmd.argv = argv;
Norman Jamese2765102015-08-19 22:00:55 -0500428 guint id;
Norman Jamese2765102015-08-19 22:00:55 -0500429 loop = g_main_loop_new (NULL, FALSE);
430
Norman Jamesd1f41c72015-11-01 20:30:13 -0600431 //signal(SIGCHLD, catch_child);
Norman James5e792e32015-10-07 17:36:17 -0500432 id = g_bus_own_name (DBUS_TYPE,
Norman James26072c02015-08-25 07:14:29 -0500433 dbus_name,
Norman Jamese2765102015-08-19 22:00:55 -0500434 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
435 G_BUS_NAME_OWNER_FLAGS_REPLACE,
436 on_bus_acquired,
437 on_name_acquired,
438 on_name_lost,
Norman James952b38d2015-08-27 21:30:06 -0500439 &cmd,
Norman Jamese2765102015-08-19 22:00:55 -0500440 NULL);
441
442 g_main_loop_run (loop);
443
444 g_bus_unown_name (id);
445 g_main_loop_unref (loop);
446 return 0;
447}