blob: a3f7ac40c1ad5a36406bf7bf4469bd9509af04ff [file] [log] [blame]
Brad Bishop77390492016-04-13 10:47:19 -04001#include <stdio.h>
2#include <stdbool.h>
3#include <string.h>
Brad Bishop0c82c602016-04-13 13:36:49 -04004#include <sys/wait.h>
5#include <sys/types.h>
Brad Bishop77390492016-04-13 10:47:19 -04006#include "interfaces/openbmc_intf.h"
7#include "openbmc.h"
8#include "object_mapper.h"
9
10/* ------------------------------------------------------------------------- */
11static const gchar* dbus_object_path = "/org/openbmc/control/flash";
12static const gchar* dbus_name = "org.openbmc.control.Flash";
13static const gchar* FLASHER_BIN = "flasher.exe";
Brad Bishop77390492016-04-13 10:47:19 -040014
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{
Brad Bishop77390492016-04-13 10:47:19 -0400145 SharedResource *lock = object_get_shared_resource((Object*)user_data);
Brad Bishop0c82c602016-04-13 13:36:49 -0400146 shared_resource_get_lock(lock);
Brad Bishop77390492016-04-13 10:47:19 -0400147 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}
155
156static gboolean
157on_done(Flash *flash,
158 GDBusMethodInvocation *invocation,
159 gpointer user_data)
160{
161 int rc = 0;
162 SharedResource *lock = object_get_shared_resource((Object*)user_data);
Brad Bishop0c82c602016-04-13 13:36:49 -0400163 shared_resource_get_lock(lock);
Brad Bishop77390492016-04-13 10:47:19 -0400164 flash_set_status(flash, "Flash Done");
165 flash_complete_done(flash,invocation);
166 printf("Flash Done. Clearing locks\n");
167 shared_resource_set_lock(lock,false);
168 shared_resource_set_name(lock,"");
169 const gchar* filename = flash_get_filename(flash);
170 rc = unlink(filename);
171 if(rc != 0 )
172 {
173 printf("ERROR: Unable to delete file %s (%d)\n",filename,rc);
174 }
175
176 return TRUE;
177}
178
179static gboolean
180on_update(Flash *flash,
181 GDBusMethodInvocation *invocation,
182 gchar* write_file,
183 gpointer user_data)
184{
185 int rc = 0;
186 SharedResource *lock = object_get_shared_resource((Object*)user_data);
187 gboolean locked = shared_resource_get_lock(lock);
188 flash_set_status(flash,"Flashing");
189 flash_complete_update(flash,invocation);
190 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);
198 flash_set_status(flash, "Flashing");
199 shared_resource_set_lock(lock,true);
200 shared_resource_set_name(lock,dbus_object_path);
201 flash_set_filename(flash,write_file);
202 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data);
203 rc = update(flash,obj_path);
204 if(!rc)
205 {
206 shared_resource_set_lock(lock,false);
207 shared_resource_set_name(lock,"");
208 }
209 }
210 return TRUE;
211}
212
213static void
214on_flash_progress(GDBusConnection* connection,
215 const gchar* sender_name,
216 const gchar* object_path,
217 const gchar* interface_name,
218 const gchar* signal_name,
219 GVariant* parameters,
220 gpointer user_data)
221{
222 Flash *flash = object_get_flash((Object*)user_data);
Brad Bishop0c82c602016-04-13 13:36:49 -0400223 object_get_shared_resource((Object*)user_data);
Brad Bishop77390492016-04-13 10:47:19 -0400224 GVariantIter *iter = g_variant_iter_new(parameters);
Brad Bishop0c82c602016-04-13 13:36:49 -0400225 g_variant_iter_next_value(iter);
Brad Bishop77390492016-04-13 10:47:19 -0400226 GVariant* v_progress = g_variant_iter_next_value(iter);
227
228 uint8_t progress = g_variant_get_byte(v_progress);
229
230 gchar *s;
231 s = g_strdup_printf("Flashing: %d%%",progress);
232 flash_set_status(flash,s);
233 g_free(s);
234}
235
236static void
Brad Bishop77390492016-04-13 10:47:19 -0400237on_bus_acquired(GDBusConnection *connection,
238 const gchar *name,
239 gpointer user_data)
240{
241 ObjectSkeleton *object;
242 cmdline *cmd = user_data;
243 manager = g_dbus_object_manager_server_new(dbus_object_path);
244 int i=0;
245
246 //TODO: don't use fixed buffer
247 char flasher_path[512];
248 memset(flasher_path, '\0', sizeof(flasher_path));
Brad Bishop0c82c602016-04-13 13:36:49 -0400249 gchar *flasher_file = NULL;
Brad Bishop77390492016-04-13 10:47:19 -0400250 int c = strlen(cmd->argv[0]);
251 while(c>0)
252 {
253 if(cmd->argv[0][c] == '/')
254 {
255 strncpy(flasher_path,cmd->argv[0],c);
256 flasher_file = g_strdup_printf("%s/%s",flasher_path,FLASHER_BIN);
257 break;
258 }
259 c--;
260 }
261
262 const char* inst[] = {"bios"};
263 for(i=0;i<1;i++)
264 {
265 gchar* s;
266 s = g_strdup_printf("%s/%s",dbus_object_path,inst[i]);
267 object = object_skeleton_new(s);
268 g_free(s);
269
270 Flash* flash = flash_skeleton_new();
271 object_skeleton_set_flash(object, flash);
272 g_object_unref(flash);
273
274 SharedResource* lock = shared_resource_skeleton_new();
275 object_skeleton_set_shared_resource(object, lock);
276 g_object_unref(lock);
277
278 ObjectMapper* mapper = object_mapper_skeleton_new();
279 object_skeleton_set_object_mapper(object, mapper);
280 g_object_unref(mapper);
281
282 shared_resource_set_lock(lock,false);
283 shared_resource_set_name(lock,"");
284
285 flash_set_flasher_path(flash,flasher_file);
286 flash_set_flasher_name(flash,FLASHER_BIN);
287 flash_set_flasher_instance(flash,inst[i]);
288 //g_free (s);
289
290
291 //define method callbacks here
292 g_signal_connect(lock,
293 "handle-lock",
294 G_CALLBACK(on_lock),
295 NULL); /* user_data */
296 g_signal_connect(lock,
297 "handle-unlock",
298 G_CALLBACK(on_unlock),
299 NULL); /* user_data */
300 g_signal_connect(lock,
301 "handle-is-locked",
302 G_CALLBACK(on_is_locked),
303 NULL); /* user_data */
304
305 g_signal_connect(flash,
306 "handle-update",
307 G_CALLBACK(on_update),
308 object); /* user_data */
309
310 g_signal_connect(flash,
311 "handle-error",
312 G_CALLBACK(on_error),
313 object); /* user_data */
314
315 g_signal_connect(flash,
316 "handle-done",
317 G_CALLBACK(on_done),
318 object); /* user_data */
319
320 g_signal_connect(flash,
321 "handle-update-via-tftp",
322 G_CALLBACK(on_update_via_tftp),
323 object); /* user_data */
324
325 g_signal_connect(flash,
326 "handle-init",
327 G_CALLBACK(on_init),
328 object); /* user_data */
329
330 s = g_strdup_printf("/org/openbmc/control/%s",inst[i]);
331 g_dbus_connection_signal_subscribe(connection,
332 NULL,
333 "org.openbmc.FlashControl",
334 "Progress",
335 s,
336 NULL,
337 G_DBUS_SIGNAL_FLAGS_NONE,
338 (GDBusSignalCallback) on_flash_progress,
339 object,
340 NULL );
341
342 g_free(s);
343
344
345 flash_set_filename(flash,"");
346 /* Export the object (@manager takes its own reference to @object) */
347 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
348 g_object_unref(object);
349 }
350 g_free(flasher_file);
351 /* Export all objects */
352 g_dbus_object_manager_server_set_connection(manager, connection);
353 emit_object_added((GDBusObjectManager*)manager);
354}
355
356static void
357on_name_acquired(GDBusConnection *connection,
358 const gchar *name,
359 gpointer user_data)
360{
361 // g_print ("Acquired the name %s\n", name);
362}
363
364static void
365on_name_lost(GDBusConnection *connection,
366 const gchar *name,
367 gpointer user_data)
368{
369 //g_print ("Lost the name %s\n", name);
370}
371
372gint
373main(gint argc, gchar *argv[])
374{
375 GMainLoop *loop;
376 cmdline cmd;
377 cmd.argc = argc;
378 cmd.argv = argv;
379 guint id;
380 loop = g_main_loop_new(NULL, FALSE);
381
382 //signal(SIGCHLD, catch_child);
383 id = g_bus_own_name(DBUS_TYPE,
384 dbus_name,
385 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
386 G_BUS_NAME_OWNER_FLAGS_REPLACE,
387 on_bus_acquired,
388 on_name_acquired,
389 on_name_lost,
390 &cmd,
391 NULL);
392
393 g_main_loop_run(loop);
394
395 g_bus_unown_name(id);
396 g_main_loop_unref(loop);
397 return 0;
398}