1 #include <stdio.h>
2 #include <stdbool.h>
3 #include <string.h>
4 #include <sys/wait.h>
5 #include <sys/types.h>
6 #include <openbmc_intf.h>
7 #include <openbmc.h>
8
9 /* ------------------------------------------------------------------------- */
10 static const gchar* dbus_object_path = "/org/openbmc/control/flash";
11 static const gchar* dbus_name = "org.openbmc.control.Flash";
12 static const gchar* FLASHER_BIN = "flasher.exe";
13
14 static GDBusObjectManagerServer *manager = NULL;
15
16 void
catch_child(int sig_num)17 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 int
update(Flash * flash,const char * obj_path)27 update(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* name = flash_get_flasher_name(flash);
35 const gchar* inst = flash_get_flasher_instance(flash);
36 const gchar* filename = flash_get_filename(flash);
37 status = execlp(name, name, inst, filename, obj_path, NULL);
38 return status;
39 }
40 return 0;
41 }
42
43 static gboolean
on_init(Flash * f,GDBusMethodInvocation * invocation,gpointer user_data)44 on_init(Flash *f,
45 GDBusMethodInvocation *invocation,
46 gpointer user_data)
47 {
48 flash_complete_init(f,invocation);
49
50 //tune flash
51 if(strcmp(flash_get_flasher_instance(f),"bios") == 0)
52 {
53 flash_set_filename(f,"");
54 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data);
55 int rc = update(f,obj_path);
56 if(rc==-1)
57 {
58 printf("ERROR FlashControl: Unable to init\n");
59 }
60 sleep(3);
61 rc = update(f,obj_path);
62
63 }
64 return TRUE;
65 }
66
67 static gboolean
on_lock(SharedResource * lock,GDBusMethodInvocation * invocation,gchar * name,gpointer user_data)68 on_lock(SharedResource *lock,
69 GDBusMethodInvocation *invocation,
70 gchar* name,
71 gpointer user_data)
72 {
73 gboolean locked = shared_resource_get_lock(lock);
74 if(locked)
75 {
76 const gchar* name = shared_resource_get_name(lock);
77 printf("ERROR: BIOS Flash is already locked: %s\n",name);
78 }
79 else
80 {
81 printf("Locking BIOS Flash: %s\n",name);
82 shared_resource_set_lock(lock,true);
83 shared_resource_set_name(lock,name);
84 }
85 shared_resource_complete_lock(lock,invocation);
86 return TRUE;
87 }
88
89 static gboolean
on_is_locked(SharedResource * lock,GDBusMethodInvocation * invocation,gpointer user_data)90 on_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 static gboolean
on_unlock(SharedResource * lock,GDBusMethodInvocation * invocation,gpointer user_data)101 on_unlock(SharedResource *lock,
102 GDBusMethodInvocation *invocation,
103 gpointer user_data)
104 {
105 printf("Unlocking BIOS Flash\n");
106 shared_resource_set_lock(lock,false);
107 shared_resource_set_name(lock,"");
108 shared_resource_complete_unlock(lock,invocation);
109 return TRUE;
110 }
111
112 static gboolean
on_update_via_tftp(Flash * flash,GDBusMethodInvocation * invocation,gchar * url,gchar * write_file,gpointer user_data)113 on_update_via_tftp(Flash *flash,
114 GDBusMethodInvocation *invocation,
115 gchar* url,
116 gchar* write_file,
117 gpointer user_data)
118 {
119 SharedResource *lock = object_get_shared_resource((Object*)user_data);
120 gboolean locked = shared_resource_get_lock(lock);
121 flash_complete_update_via_tftp(flash,invocation);
122 if(locked)
123 {
124 const gchar* name = shared_resource_get_name(lock);
125 printf("BIOS Flash is locked: %s\n",name);
126 }
127 else
128 {
129 printf("Flashing BIOS from TFTP: %s,%s\n",url,write_file);
130 flash_set_filename(flash,write_file);
131 flash_emit_download(flash,url,write_file);
132 flash_set_status(flash,"Downloading");
133 }
134 return TRUE;
135 }
136
137 static gboolean
on_error(Flash * flash,GDBusMethodInvocation * invocation,gchar * error_msg,gpointer user_data)138 on_error(Flash *flash,
139 GDBusMethodInvocation *invocation,
140 gchar* error_msg,
141 gpointer user_data)
142 {
143 SharedResource *lock = object_get_shared_resource((Object*)user_data);
144 shared_resource_get_lock(lock);
145 flash_set_status(flash, error_msg);
146 flash_complete_error(flash,invocation);
147 printf("ERROR: %s. Clearing locks\n",error_msg);
148 shared_resource_set_lock(lock,false);
149 shared_resource_set_name(lock,"");
150
151 return TRUE;
152 }
153
154 static gboolean
on_done(Flash * flash,GDBusMethodInvocation * invocation,gpointer user_data)155 on_done(Flash *flash,
156 GDBusMethodInvocation *invocation,
157 gpointer user_data)
158 {
159 int rc = 0;
160 SharedResource *lock = object_get_shared_resource((Object*)user_data);
161 shared_resource_get_lock(lock);
162 flash_set_status(flash, "Flash Done");
163 flash_complete_done(flash,invocation);
164 printf("Flash Done. Clearing locks\n");
165 shared_resource_set_lock(lock,false);
166 shared_resource_set_name(lock,"");
167 const gchar* filename = flash_get_filename(flash);
168 rc = unlink(filename);
169 if(rc != 0 )
170 {
171 printf("ERROR: Unable to delete file %s (%d)\n",filename,rc);
172 }
173
174 return TRUE;
175 }
176
177 static gboolean
on_update(Flash * flash,GDBusMethodInvocation * invocation,gchar * write_file,gpointer user_data)178 on_update(Flash *flash,
179 GDBusMethodInvocation *invocation,
180 gchar* write_file,
181 gpointer user_data)
182 {
183 int rc = 0;
184 SharedResource *lock = object_get_shared_resource((Object*)user_data);
185 gboolean locked = shared_resource_get_lock(lock);
186 flash_set_status(flash,"Flashing");
187 flash_complete_update(flash,invocation);
188 if(locked)
189 {
190 const gchar* name = shared_resource_get_name(lock);
191 printf("BIOS Flash is locked: %s\n",name);
192 }
193 else
194 {
195 printf("Flashing BIOS from: %s\n",write_file);
196 flash_set_status(flash, "Flashing");
197 shared_resource_set_lock(lock,true);
198 shared_resource_set_name(lock,dbus_object_path);
199 flash_set_filename(flash,write_file);
200 const gchar* obj_path = g_dbus_object_get_object_path((GDBusObject*)user_data);
201 rc = update(flash,obj_path);
202 if(!rc)
203 {
204 shared_resource_set_lock(lock,false);
205 shared_resource_set_name(lock,"");
206 }
207 }
208 return TRUE;
209 }
210
211 static void
on_flash_progress(GDBusConnection * connection,const gchar * sender_name,const gchar * object_path,const gchar * interface_name,const gchar * signal_name,GVariant * parameters,gpointer user_data)212 on_flash_progress(GDBusConnection* connection,
213 const gchar* sender_name,
214 const gchar* object_path,
215 const gchar* interface_name,
216 const gchar* signal_name,
217 GVariant* parameters,
218 gpointer user_data)
219 {
220 Flash *flash = object_get_flash((Object*)user_data);
221 object_get_shared_resource((Object*)user_data);
222 GVariantIter *iter = g_variant_iter_new(parameters);
223 g_variant_iter_next_value(iter);
224 GVariant* v_progress = g_variant_iter_next_value(iter);
225
226 uint8_t progress = g_variant_get_byte(v_progress);
227
228 gchar *s;
229 s = g_strdup_printf("Flashing: %d%%",progress);
230 flash_set_status(flash,s);
231 g_free(s);
232 }
233
234 static void
on_bus_acquired(GDBusConnection * connection,const gchar * name,gpointer user_data)235 on_bus_acquired(GDBusConnection *connection,
236 const gchar *name,
237 gpointer user_data)
238 {
239 ObjectSkeleton *object;
240 cmdline *cmd = user_data;
241 manager = g_dbus_object_manager_server_new(dbus_object_path);
242 int i=0;
243
244 gchar *flasher_file = g_strdup_printf("%s", FLASHER_BIN);
245
246 const char* inst[] = {"bios"};
247 for(i=0;i<1;i++)
248 {
249 gchar* s;
250 s = g_strdup_printf("%s/%s",dbus_object_path,inst[i]);
251 object = object_skeleton_new(s);
252 g_free(s);
253
254 Flash* flash = flash_skeleton_new();
255 object_skeleton_set_flash(object, flash);
256 g_object_unref(flash);
257
258 SharedResource* lock = shared_resource_skeleton_new();
259 object_skeleton_set_shared_resource(object, lock);
260 g_object_unref(lock);
261
262 shared_resource_set_lock(lock,false);
263 shared_resource_set_name(lock,"");
264
265 flash_set_flasher_name(flash,FLASHER_BIN);
266 flash_set_flasher_instance(flash,inst[i]);
267 //g_free (s);
268
269
270 //define method callbacks here
271 g_signal_connect(lock,
272 "handle-lock",
273 G_CALLBACK(on_lock),
274 NULL); /* user_data */
275 g_signal_connect(lock,
276 "handle-unlock",
277 G_CALLBACK(on_unlock),
278 NULL); /* user_data */
279 g_signal_connect(lock,
280 "handle-is-locked",
281 G_CALLBACK(on_is_locked),
282 NULL); /* user_data */
283
284 g_signal_connect(flash,
285 "handle-update",
286 G_CALLBACK(on_update),
287 object); /* user_data */
288
289 g_signal_connect(flash,
290 "handle-error",
291 G_CALLBACK(on_error),
292 object); /* user_data */
293
294 g_signal_connect(flash,
295 "handle-done",
296 G_CALLBACK(on_done),
297 object); /* user_data */
298
299 g_signal_connect(flash,
300 "handle-update-via-tftp",
301 G_CALLBACK(on_update_via_tftp),
302 object); /* user_data */
303
304 g_signal_connect(flash,
305 "handle-init",
306 G_CALLBACK(on_init),
307 object); /* user_data */
308
309 s = g_strdup_printf("/org/openbmc/control/%s",inst[i]);
310 g_dbus_connection_signal_subscribe(connection,
311 NULL,
312 "org.openbmc.FlashControl",
313 "Progress",
314 s,
315 NULL,
316 G_DBUS_SIGNAL_FLAGS_NONE,
317 (GDBusSignalCallback) on_flash_progress,
318 object,
319 NULL );
320
321 g_free(s);
322
323
324 flash_set_filename(flash,"");
325 /* Export the object (@manager takes its own reference to @object) */
326 g_dbus_object_manager_server_set_connection(manager, connection);
327 g_dbus_object_manager_server_export(manager, G_DBUS_OBJECT_SKELETON(object));
328 g_object_unref(object);
329 }
330 g_free(flasher_file);
331 }
332
333 static void
on_name_acquired(GDBusConnection * connection,const gchar * name,gpointer user_data)334 on_name_acquired(GDBusConnection *connection,
335 const gchar *name,
336 gpointer user_data)
337 {
338 // g_print ("Acquired the name %s\n", name);
339 }
340
341 static void
on_name_lost(GDBusConnection * connection,const gchar * name,gpointer user_data)342 on_name_lost(GDBusConnection *connection,
343 const gchar *name,
344 gpointer user_data)
345 {
346 //g_print ("Lost the name %s\n", name);
347 }
348
349 gint
main(gint argc,gchar * argv[])350 main(gint argc, gchar *argv[])
351 {
352 GMainLoop *loop;
353 cmdline cmd;
354 cmd.argc = argc;
355 cmd.argv = argv;
356 guint id;
357 loop = g_main_loop_new(NULL, FALSE);
358
359 signal(SIGCHLD, catch_child);
360 id = g_bus_own_name(DBUS_TYPE,
361 dbus_name,
362 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
363 G_BUS_NAME_OWNER_FLAGS_REPLACE,
364 on_bus_acquired,
365 on_name_acquired,
366 on_name_lost,
367 &cmd,
368 NULL);
369
370 g_main_loop_run(loop);
371
372 g_bus_unown_name(id);
373 g_main_loop_unref(loop);
374 return 0;
375 }
376