blob: 2d8303f4cc9f064a3ff4ca8f6bdde46b061005a0 [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 James18998182015-10-11 21:54:53 -050061 }
62 return TRUE;
63}
Norman James068efb32015-10-06 16:52:28 -050064
Norman James18998182015-10-11 21:54:53 -050065static gboolean
66on_lock (SharedResource *lock,
67 GDBusMethodInvocation *invocation,
68 gchar* name,
69 gpointer user_data)
70{
Norman Jamesa3e47c42015-10-18 14:43:10 -050071 gboolean locked = shared_resource_get_lock(lock);
72 if (locked)
73 {
74 const gchar* name = shared_resource_get_name(lock);
75 printf("ERROR: BIOS Flash is already locked: %s\n",name);
76 }
77 else
78 {
79 printf("Locking BIOS Flash: %s\n",name);
80 shared_resource_set_lock(lock,true);
81 shared_resource_set_name(lock,name);
82 }
Norman James18998182015-10-11 21:54:53 -050083 shared_resource_complete_lock(lock,invocation);
84 return TRUE;
85}
86static gboolean
87on_is_locked (SharedResource *lock,
88 GDBusMethodInvocation *invocation,
89 gpointer user_data)
90{
91 gboolean locked = shared_resource_get_lock(lock);
92 const gchar* name = shared_resource_get_name(lock);
93 shared_resource_complete_is_locked(lock,invocation,locked,name);
94 return TRUE;
95}
96
97
98static gboolean
99on_unlock (SharedResource *lock,
100 GDBusMethodInvocation *invocation,
101 gpointer user_data)
102{
103 printf("Unlocking BIOS Flash\n");
104 shared_resource_set_lock(lock,false);
105 shared_resource_set_name(lock,"");
106 shared_resource_complete_unlock(lock,invocation);
Norman James65a295a2015-09-26 22:21:10 -0500107 return TRUE;
Norman James471ab592015-08-30 22:29:40 -0500108}
109
110static gboolean
Norman Jamesf066e872015-10-07 15:29:51 -0500111on_update_via_tftp (Flash *flash,
112 GDBusMethodInvocation *invocation,
113 gchar* url,
114 gchar* write_file,
115 gpointer user_data)
116{
Norman James18998182015-10-11 21:54:53 -0500117 SharedResource *lock = object_get_shared_resource((Object*)user_data);
118 gboolean locked = shared_resource_get_lock(lock);
Norman Jamesf066e872015-10-07 15:29:51 -0500119 flash_complete_update_via_tftp(flash,invocation);
Norman James18998182015-10-11 21:54:53 -0500120 if (locked)
121 {
122 const gchar* name = shared_resource_get_name(lock);
123 printf("BIOS Flash is locked: %s\n",name);
124 }
125 else
126 {
127 printf("Flashing BIOS from TFTP: %s,%s\n",url,write_file);
Norman James18998182015-10-11 21:54:53 -0500128 flash_set_filename(flash,write_file);
129 flash_emit_download(flash,url,write_file);
Norman James166acf42015-10-22 07:11:51 -0500130 flash_set_status(flash,"Downloading");
Norman James18998182015-10-11 21:54:53 -0500131 }
Norman Jamesf066e872015-10-07 15:29:51 -0500132 return TRUE;
133}
134
135static gboolean
Norman James166acf42015-10-22 07:11:51 -0500136on_error (Flash *flash,
137 GDBusMethodInvocation *invocation,
138 gchar* error_msg,
139 gpointer user_data)
140{
141 int rc = 0;
142 SharedResource *lock = object_get_shared_resource((Object*)user_data);
143 gboolean locked = shared_resource_get_lock(lock);
144 flash_set_status(flash, error_msg);
145 flash_complete_error(flash,invocation);
146 printf("ERROR: %s. Clearing locks\n",error_msg);
147 shared_resource_set_lock(lock,false);
148 shared_resource_set_name(lock,"");
149
150 return TRUE;
151}
152static gboolean
153on_done (Flash *flash,
154 GDBusMethodInvocation *invocation,
155 gpointer user_data)
156{
157 int rc = 0;
158 SharedResource *lock = object_get_shared_resource((Object*)user_data);
159 gboolean locked = shared_resource_get_lock(lock);
160 flash_set_status(flash, "Flash Done");
161 flash_complete_done(flash,invocation);
162 printf("Flash Done. Clearing locks\n");
163 shared_resource_set_lock(lock,false);
164 shared_resource_set_name(lock,"");
165
166 return TRUE;
167}
168
169
170static gboolean
Norman Jamesf066e872015-10-07 15:29:51 -0500171on_update (Flash *flash,
Norman Jamese2765102015-08-19 22:00:55 -0500172 GDBusMethodInvocation *invocation,
173 gchar* write_file,
174 gpointer user_data)
175{
Norman James18998182015-10-11 21:54:53 -0500176 int rc = 0;
177 SharedResource *lock = object_get_shared_resource((Object*)user_data);
178 gboolean locked = shared_resource_get_lock(lock);
Norman James166acf42015-10-22 07:11:51 -0500179 flash_set_status(flash,"Flashing");
Norman Jamesf066e872015-10-07 15:29:51 -0500180 flash_complete_update(flash,invocation);
Norman James18998182015-10-11 21:54:53 -0500181 if (locked)
182 {
183 const gchar* name = shared_resource_get_name(lock);
184 printf("BIOS Flash is locked: %s\n",name);
185 }
186 else
187 {
188 printf("Flashing BIOS from: %s\n",write_file);
Norman James166acf42015-10-22 07:11:51 -0500189 flash_set_status(flash, "Flashing");
Norman James18998182015-10-11 21:54:53 -0500190 shared_resource_set_lock(lock,true);
191 shared_resource_set_name(lock,dbus_object_path);
192 flash_set_filename(flash,write_file);
Norman James166acf42015-10-22 07:11:51 -0500193 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data);
194 rc = update(flash,obj_path);
Norman James18998182015-10-11 21:54:53 -0500195 if (!rc)
196 {
197 shared_resource_set_lock(lock,false);
198 shared_resource_set_name(lock,"");
199 }
200 }
Norman James068efb32015-10-06 16:52:28 -0500201 return TRUE;
Norman Jamese2765102015-08-19 22:00:55 -0500202}
Norman James18998182015-10-11 21:54:53 -0500203static void
204on_flash_progress (GDBusConnection* connection,
205 const gchar* sender_name,
206 const gchar* object_path,
207 const gchar* interface_name,
208 const gchar* signal_name,
209 GVariant* parameters,
210 gpointer user_data)
211{
212 Flash *flash = object_get_flash((Object*)user_data);
213 SharedResource *lock = object_get_shared_resource((Object*)user_data);
214 GVariantIter *iter = g_variant_iter_new(parameters);
215 GVariant* v_filename = g_variant_iter_next_value(iter);
216 GVariant* v_progress = g_variant_iter_next_value(iter);
Norman Jamesf066e872015-10-07 15:29:51 -0500217
Norman James18998182015-10-11 21:54:53 -0500218 uint8_t progress = g_variant_get_byte(v_progress);
Norman James166acf42015-10-22 07:11:51 -0500219
220 gchar *s;
221 s = g_strdup_printf ("Flashing: %d%%",progress);
222 flash_set_status(flash,s);
223 g_free(s);
Norman James18998182015-10-11 21:54:53 -0500224}
225
226static void
227on_flash_done (GDBusConnection* connection,
228 const gchar* sender_name,
229 const gchar* object_path,
230 const gchar* interface_name,
231 const gchar* signal_name,
232 GVariant* parameters,
233 gpointer user_data)
234{
235 Flash *flash = object_get_flash((Object*)user_data);
236 SharedResource *lock = object_get_shared_resource((Object*)user_data);
237 printf("Flash succeeded; unlocking flash\n");
238 shared_resource_set_lock(lock,false);
239 shared_resource_set_name(lock,"");
Norman James166acf42015-10-22 07:11:51 -0500240 flash_set_status(flash,"Flash Done");
Norman James18998182015-10-11 21:54:53 -0500241}
242
243static void
244on_flash_error (GDBusConnection* connection,
245 const gchar* sender_name,
246 const gchar* object_path,
247 const gchar* interface_name,
248 const gchar* signal_name,
249 GVariant* parameters,
250 gpointer user_data)
251{
252 Flash *flash = object_get_flash((Object*)user_data);
253 SharedResource *lock = object_get_shared_resource((Object*)user_data);
254 printf("Flash Error; unlocking flash\n");
255 shared_resource_set_lock(lock,false);
256 shared_resource_set_name(lock,"");
257}
258
259static void
260on_download_error (GDBusConnection* connection,
261 const gchar* sender_name,
262 const gchar* object_path,
263 const gchar* interface_name,
264 const gchar* signal_name,
265 GVariant* parameters,
266 gpointer user_data)
267{
268 Flash *flash = object_get_flash((Object*)user_data);
269 SharedResource *lock = object_get_shared_resource((Object*)user_data);
270 printf("ERROR: FlashBios: Download error; clearing flash lock\n");
271 shared_resource_set_lock(lock,false);
272 shared_resource_set_name(lock,"");
Norman Jamesf066e872015-10-07 15:29:51 -0500273}
274
Norman Jamese2765102015-08-19 22:00:55 -0500275static void
276on_bus_acquired (GDBusConnection *connection,
277 const gchar *name,
278 gpointer user_data)
279{
Norman James10ff6a32015-08-27 14:24:17 -0500280 ObjectSkeleton *object;
Norman James10ff6a32015-08-27 14:24:17 -0500281 cmdline *cmd = user_data;
Norman James10ff6a32015-08-27 14:24:17 -0500282 manager = g_dbus_object_manager_server_new (dbus_object_path);
283 int i=0;
Norman James166acf42015-10-22 07:11:51 -0500284
285 //TODO: don't use fixed buffer
286 char flasher_path[512];
287 memset(flasher_path, '\0', sizeof(flasher_path));
288 bool found = false;
289 gchar *flasher_file;
290 int c = strlen(cmd->argv[0]);
291 while(c>0)
292 {
293 if (cmd->argv[0][c] == '/')
294 {
295 strncpy(flasher_path,cmd->argv[0],c);
296 flasher_file = g_strdup_printf ("%s/%s",flasher_path,FLASHER_BIN);
297 break;
298 }
299 c--;
300 }
301
Norman James15aaa802015-10-28 06:54:48 -0500302 const char* inst[] = {"bios","bmc","bmc_ramdisk","bmc_kernel"};
303 for (i=0;i<4;i++)
Norman James10ff6a32015-08-27 14:24:17 -0500304 {
Norman James166acf42015-10-22 07:11:51 -0500305 gchar* s;
306 s = g_strdup_printf ("%s/%s",dbus_object_path,inst[i]);
Norman James10ff6a32015-08-27 14:24:17 -0500307 object = object_skeleton_new (s);
308 g_free (s);
Norman Jamese2765102015-08-19 22:00:55 -0500309
Norman James10ff6a32015-08-27 14:24:17 -0500310 Flash* flash = flash_skeleton_new ();
311 object_skeleton_set_flash (object, flash);
312 g_object_unref (flash);
Norman Jamese2765102015-08-19 22:00:55 -0500313
Norman James18998182015-10-11 21:54:53 -0500314 SharedResource* lock = shared_resource_skeleton_new ();
315 object_skeleton_set_shared_resource (object, lock);
316 g_object_unref (lock);
317
Norman Jamescfc2b442015-10-31 17:31:46 -0500318 ObjectMapper* mapper = object_mapper_skeleton_new ();
319 object_skeleton_set_object_mapper (object, mapper);
320 g_object_unref (mapper);
321
Norman James18998182015-10-11 21:54:53 -0500322 shared_resource_set_lock(lock,false);
323 shared_resource_set_name(lock,"");
324
Norman James166acf42015-10-22 07:11:51 -0500325 flash_set_flasher_path(flash,flasher_file);
326 flash_set_flasher_name(flash,FLASHER_BIN);
327 flash_set_flasher_instance(flash,inst[i]);
328 //g_free (s);
Norman James18998182015-10-11 21:54:53 -0500329
330
Norman James10ff6a32015-08-27 14:24:17 -0500331 //define method callbacks here
Norman James18998182015-10-11 21:54:53 -0500332 g_signal_connect (lock,
333 "handle-lock",
334 G_CALLBACK (on_lock),
335 NULL); /* user_data */
336 g_signal_connect (lock,
337 "handle-unlock",
338 G_CALLBACK (on_unlock),
339 NULL); /* user_data */
340 g_signal_connect (lock,
341 "handle-is-locked",
342 G_CALLBACK (on_is_locked),
343 NULL); /* user_data */
344
Norman James10ff6a32015-08-27 14:24:17 -0500345 g_signal_connect (flash,
Norman James8c6d8382015-10-06 07:47:16 -0500346 "handle-update",
347 G_CALLBACK (on_update),
Norman James18998182015-10-11 21:54:53 -0500348 object); /* user_data */
Norman James166acf42015-10-22 07:11:51 -0500349
350 g_signal_connect (flash,
351 "handle-error",
352 G_CALLBACK (on_error),
353 object); /* user_data */
354
355 g_signal_connect (flash,
356 "handle-done",
357 G_CALLBACK (on_done),
358 object); /* user_data */
359
Norman Jamesf066e872015-10-07 15:29:51 -0500360 g_signal_connect (flash,
361 "handle-update-via-tftp",
362 G_CALLBACK (on_update_via_tftp),
Norman James18998182015-10-11 21:54:53 -0500363 object); /* user_data */
Norman Jamesf066e872015-10-07 15:29:51 -0500364
Norman James471ab592015-08-30 22:29:40 -0500365 g_signal_connect (flash,
366 "handle-init",
367 G_CALLBACK (on_init),
Norman James166acf42015-10-22 07:11:51 -0500368 object); /* user_data */
Norman James471ab592015-08-30 22:29:40 -0500369
Norman James166acf42015-10-22 07:11:51 -0500370 s = g_strdup_printf ("/org/openbmc/control/%s",inst[i]);
Norman James18998182015-10-11 21:54:53 -0500371 g_dbus_connection_signal_subscribe(connection,
372 NULL,
373 "org.openbmc.FlashControl",
374 "Progress",
375 s,
376 NULL,
377 G_DBUS_SIGNAL_FLAGS_NONE,
378 (GDBusSignalCallback) on_flash_progress,
379 object,
380 NULL );
381
382 g_free (s);
Norman Jamesf066e872015-10-07 15:29:51 -0500383
Norman James471ab592015-08-30 22:29:40 -0500384
Norman James18998182015-10-11 21:54:53 -0500385 flash_set_filename(flash,"");
Norman James10ff6a32015-08-27 14:24:17 -0500386 /* Export the object (@manager takes its own reference to @object) */
387 g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
388 g_object_unref (object);
389 }
Norman James166acf42015-10-22 07:11:51 -0500390 g_free(flasher_file);
Norman James10ff6a32015-08-27 14:24:17 -0500391 /* Export all objects */
392 g_dbus_object_manager_server_set_connection (manager, connection);
Norman Jamescfc2b442015-10-31 17:31:46 -0500393 emit_object_added((GDBusObjectManager*)manager);
Norman Jamese2765102015-08-19 22:00:55 -0500394}
395
396static void
397on_name_acquired (GDBusConnection *connection,
398 const gchar *name,
399 gpointer user_data)
400{
Norman James362a80f2015-09-14 14:04:39 -0500401// g_print ("Acquired the name %s\n", name);
Norman Jamese2765102015-08-19 22:00:55 -0500402}
403
404static void
405on_name_lost (GDBusConnection *connection,
406 const gchar *name,
407 gpointer user_data)
408{
Norman James362a80f2015-09-14 14:04:39 -0500409 //g_print ("Lost the name %s\n", name);
Norman Jamese2765102015-08-19 22:00:55 -0500410}
411
412gint
413main (gint argc, gchar *argv[])
414{
415 GMainLoop *loop;
Norman James952b38d2015-08-27 21:30:06 -0500416 cmdline cmd;
417 cmd.argc = argc;
418 cmd.argv = argv;
Norman Jamese2765102015-08-19 22:00:55 -0500419 guint id;
Norman Jamese2765102015-08-19 22:00:55 -0500420 loop = g_main_loop_new (NULL, FALSE);
421
Norman Jamesc8719dd2015-11-01 07:38:02 -0600422 signal(SIGCHLD, catch_child);
Norman James5e792e32015-10-07 17:36:17 -0500423 id = g_bus_own_name (DBUS_TYPE,
Norman James26072c02015-08-25 07:14:29 -0500424 dbus_name,
Norman Jamese2765102015-08-19 22:00:55 -0500425 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
426 G_BUS_NAME_OWNER_FLAGS_REPLACE,
427 on_bus_acquired,
428 on_name_acquired,
429 on_name_lost,
Norman James952b38d2015-08-27 21:30:06 -0500430 &cmd,
Norman Jamese2765102015-08-19 22:00:55 -0500431 NULL);
432
433 g_main_loop_run (loop);
434
435 g_bus_unown_name (id);
436 g_main_loop_unref (loop);
437 return 0;
438}