blob: fc42cb4b402c517535979f194d20646ecc1834fe [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 Bishopf6c85682016-06-27 11:56:39 -04006#include <openbmc_intf.h>
7#include <openbmc.h>
Brad Bishop77390492016-04-13 10:47:19 -04008
9/* ------------------------------------------------------------------------- */
10static const gchar* dbus_object_path = "/org/openbmc/control/flash";
11static const gchar* dbus_name = "org.openbmc.control.Flash";
12static const gchar* FLASHER_BIN = "flasher.exe";
Brad Bishop77390492016-04-13 10:47:19 -040013
14static GDBusObjectManagerServer *manager = NULL;
15
16void
17catch_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
26int
27update(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
44static gboolean
45on_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
68static gboolean
69on_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
90static gboolean
91on_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
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);
110 return TRUE;
111}
112
113static gboolean
114on_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
138static gboolean
139on_error(Flash *flash,
140 GDBusMethodInvocation *invocation,
141 gchar* error_msg,
142 gpointer user_data)
143{
Brad Bishop77390492016-04-13 10:47:19 -0400144 SharedResource *lock = object_get_shared_resource((Object*)user_data);
Brad Bishop0c82c602016-04-13 13:36:49 -0400145 shared_resource_get_lock(lock);
Brad Bishop77390492016-04-13 10:47:19 -0400146 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
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);
Brad Bishop0c82c602016-04-13 13:36:49 -0400162 shared_resource_get_lock(lock);
Brad Bishop77390492016-04-13 10:47:19 -0400163 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
178static gboolean
179on_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
212static 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);
Brad Bishop0c82c602016-04-13 13:36:49 -0400222 object_get_shared_resource((Object*)user_data);
Brad Bishop77390492016-04-13 10:47:19 -0400223 GVariantIter *iter = g_variant_iter_new(parameters);
Brad Bishop0c82c602016-04-13 13:36:49 -0400224 g_variant_iter_next_value(iter);
Brad Bishop77390492016-04-13 10:47:19 -0400225 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
235static void
Brad Bishop77390492016-04-13 10:47:19 -0400236on_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));
Brad Bishop0c82c602016-04-13 13:36:49 -0400248 gchar *flasher_file = NULL;
Brad Bishop77390492016-04-13 10:47:19 -0400249 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
Brad Bishop77390492016-04-13 10:47:19 -0400277 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) */
Brad Bishop58e694d2016-04-13 16:04:32 -0400342 g_dbus_object_manager_server_set_connection(manager, connection);
Brad Bishop77390492016-04-13 10:47:19 -0400343 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
344 g_object_unref(object);
345 }
346 g_free(flasher_file);
Brad Bishop77390492016-04-13 10:47:19 -0400347}
348
349static void
350on_name_acquired(GDBusConnection *connection,
351 const gchar *name,
352 gpointer user_data)
353{
354 // g_print ("Acquired the name %s\n", name);
355}
356
357static void
358on_name_lost(GDBusConnection *connection,
359 const gchar *name,
360 gpointer user_data)
361{
362 //g_print ("Lost the name %s\n", name);
363}
364
365gint
366main(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}