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