blob: e951d635e00bd8586cce9f9d172d5a075cde1106 [file] [log] [blame]
Norman Jamesc0d94e02015-10-13 10:06:12 -05001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <fcntl.h>
5#include <sys/mman.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <unistd.h>
9#include <byteswap.h>
10#include <stdint.h>
11#include <stdbool.h>
12#include <getopt.h>
13#include <limits.h>
14#include <arpa/inet.h>
15#include <assert.h>
16
17#include <libflash/libflash.h>
18#include <libflash/libffs.h>
19#include "progress.h"
20#include "io.h"
21#include "ast.h"
22#include "sfc-ctrl.h"
23#include "interfaces/openbmc_intf.h"
24#include "includes/openbmc.h"
25
26static const gchar* dbus_object_path = "/org/openbmc/control";
27static const gchar* dbus_object_name = "Flasher_0";
28static const gchar* dbus_name = "org.openbmc.control.Flasher";
29
30static GDBusObjectManagerServer *manager = NULL;
31
32#define __aligned(x) __attribute__((aligned(x)))
33
34#define PFLASH_VERSION "0.8.6"
35
36static bool must_confirm = false;
37static bool dummy_run;
38static bool need_relock;
39static bool bmc_flash;
40#ifdef __powerpc__
41static bool using_sfc;
42#endif
43
44#define FILE_BUF_SIZE 0x10000
45static uint8_t file_buf[FILE_BUF_SIZE] __aligned(0x1000);
46
47static struct spi_flash_ctrl *fl_ctrl;
48static struct flash_chip *fl_chip;
49static struct ffs_handle *ffsh;
50static uint32_t fl_total_size, fl_erase_granule;
51static const char *fl_name;
52static int32_t ffs_index = -1;
53
54
55static int erase_chip(void)
56{
57 int rc = 0;
58
59 printf("Erasing... (may take a while !) ");
60 fflush(stdout);
61
62 rc = flash_erase_chip(fl_chip);
63 if (rc) {
64 fprintf(stderr, "Error %d erasing chip\n", rc);
65 return(rc);
66 }
67
68 printf("done !\n");
69 return (rc);
70}
71
72static int program_file(FlashControl* flash_control, const char *file, uint32_t start, uint32_t size)
73{
74 int fd, rc;
75 ssize_t len;
76 uint32_t actual_size = 0;
77
78 fd = open(file, O_RDONLY);
79 if (fd == -1) {
80 perror("Failed to open file");
81 return(fd);
82 }
83 printf("About to program \"%s\" at 0x%08x..0x%08x !\n",
84 file, start, size);
85
86 printf("Programming & Verifying...\n");
87 //progress_init(size >> 8);
88 unsigned int save_size = size;
89 uint8_t last_progress = 0;
90 while(size) {
91 len = read(fd, file_buf, FILE_BUF_SIZE);
92 if (len < 0) {
93 perror("Error reading file");
94 return(1);
95 }
96 if (len == 0)
97 break;
98 if (len > size)
99 len = size;
100 size -= len;
101 actual_size += len;
102 rc = flash_write(fl_chip, start, file_buf, len, true);
103 if (rc) {
104 if (rc == FLASH_ERR_VERIFY_FAILURE)
105 fprintf(stderr, "Verification failed for"
106 " chunk at 0x%08x\n", start);
107 else
108 fprintf(stderr, "Flash write error %d for"
109 " chunk at 0x%08x\n", rc, start);
110 return(rc);
111 }
112 start += len;
113 unsigned int percent = (100*actual_size/save_size);
114 uint8_t progress = (uint8_t) (percent);
115 if (progress != last_progress) {
116 flash_control_emit_progress(flash_control,file,progress);
117 last_progress = progress;
118 }
119 }
120 close(fd);
121
122 /* If this is a flash partition, adjust its size */
123 if (ffsh && ffs_index >= 0) {
124 printf("Updating actual size in partition header...\n");
125 ffs_update_act_size(ffsh, ffs_index, actual_size);
126 }
127 return(0);
128}
129
130static void do_read_file(const char *file, uint32_t start, uint32_t size)
131{
132 int fd, rc;
133 ssize_t len;
134 uint32_t done = 0;
135
136 fd = open(file, O_WRONLY | O_TRUNC | O_CREAT, 00666);
137 if (fd == -1) {
138 perror("Failed to open file");
139 exit(1);
140 }
141 printf("Reading to \"%s\" from 0x%08x..0x%08x !\n",
142 file, start, size);
143
144 progress_init(size >> 8);
145 while(size) {
146 len = size > FILE_BUF_SIZE ? FILE_BUF_SIZE : size;
147 rc = flash_read(fl_chip, start, file_buf, len);
148 if (rc) {
149 fprintf(stderr, "Flash read error %d for"
150 " chunk at 0x%08x\n", rc, start);
151 exit(1);
152 }
153 rc = write(fd, file_buf, len);
154 if (rc < 0) {
155 perror("Error writing file");
156 exit(1);
157 }
158 start += len;
159 size -= len;
160 done += len;
161 progress_tick(done >> 8);
162 }
163 progress_end();
164 close(fd);
165}
166static void flash_access_cleanup_bmc(void)
167{
168 if (ffsh)
169 ffs_close(ffsh);
170 flash_exit(fl_chip);
171 ast_sf_close(fl_ctrl);
172 close_devs();
173}
174
175static void flash_access_setup_bmc(bool use_lpc, bool need_write)
176{
177 int rc;
178
179 /* Open and map devices */
180 open_devs(use_lpc, true);
181
182 /* Create the AST flash controller */
183 rc = ast_sf_open(AST_SF_TYPE_BMC, &fl_ctrl);
184 if (rc) {
185 fprintf(stderr, "Failed to open controller\n");
186 exit(1);
187 }
188
189 /* Open flash chip */
190 rc = flash_init(fl_ctrl, &fl_chip);
191 if (rc) {
192 fprintf(stderr, "Failed to open flash chip\n");
193 exit(1);
194 }
195
196 /* Setup cleanup function */
197 atexit(flash_access_cleanup_bmc);
198}
199
200static void flash_access_cleanup_pnor(void)
201{
202 /* Re-lock flash */
203 if (need_relock)
204 set_wrprotect(true);
205
206 if (ffsh)
207 ffs_close(ffsh);
208 flash_exit(fl_chip);
209#ifdef __powerpc__
210 if (using_sfc)
211 sfc_close(fl_ctrl);
212 else
213 ast_sf_close(fl_ctrl);
214#else
215 ast_sf_close(fl_ctrl);
216#endif
217 close_devs();
218}
219
220static void flash_access_setup_pnor(bool use_lpc, bool use_sfc, bool need_write)
221{
222 int rc;
223
224 /* Open and map devices */
225 open_devs(use_lpc, false);
226
227#ifdef __powerpc__
228 if (use_sfc) {
229 /* Create the SFC flash controller */
230 rc = sfc_open(&fl_ctrl);
231 if (rc) {
232 fprintf(stderr, "Failed to open controller\n");
233 exit(1);
234 }
235 using_sfc = true;
236 } else {
237#endif
238 /* Create the AST flash controller */
239 rc = ast_sf_open(AST_SF_TYPE_PNOR, &fl_ctrl);
240 if (rc) {
241 fprintf(stderr, "Failed to open controller\n");
242 exit(1);
243 }
244#ifdef __powerpc__
245 }
246#endif
247
248 /* Open flash chip */
249 rc = flash_init(fl_ctrl, &fl_chip);
250 if (rc) {
251 fprintf(stderr, "Failed to open flash chip\n");
252 exit(1);
253 }
254
255 /* Unlock flash (PNOR only) */
256 if (need_write)
257 need_relock = set_wrprotect(false);
258
259 /* Setup cleanup function */
260 atexit(flash_access_cleanup_pnor);
261}
262
263int flash(FlashControl* flash_control,bool bmc_flash, char* write_file)
264{
265 bool has_sfc = false, has_ast = false, use_lpc = true;
266 bool erase = true, program = true;
267 uint32_t address = 0;
268 int rc;
269
270#ifdef __arm__
271 /* Check platform */
272 check_platform(&has_sfc, &has_ast);
273
274 /* Prepare for access */
275 if (bmc_flash) {
276 if (!has_ast) {
277 fprintf(stderr, "No BMC on this platform\n");
278 flash_control_emit_error(flash_control,write_file);
279 return;
280 }
281 flash_access_setup_bmc(use_lpc, erase || program);
282 } else {
283 if (!has_ast && !has_sfc) {
284 fprintf(stderr, "No BMC nor SFC on this platform\n");
285 flash_control_emit_error(flash_control,write_file);
286 return;
287 }
288 flash_access_setup_pnor(use_lpc, has_sfc, erase || program);
289 }
290
291 rc = flash_get_info(fl_chip, &fl_name,
292 &fl_total_size, &fl_erase_granule);
293 if (rc) {
294 fprintf(stderr, "Error %d getting flash info\n", rc);
295 flash_control_emit_error(flash_control,write_file);
296 return;
297 }
298#endif
299 if (strcmp(write_file,"")!=0)
300 {
301 // If file specified but not size, get size from file
302 struct stat stbuf;
303 if (stat(write_file, &stbuf)) {
304 perror("Failed to get file size");
305 flash_control_emit_error(flash_control,write_file);
306 return;
307 }
308 uint32_t write_size = stbuf.st_size;
309#ifdef __arm__
310 rc = erase_chip();
311 if (rc) {
312 flash_control_emit_error(flash_control,write_file);
313 return;
314 }
315 rc = program_file(flash_control, write_file, address, write_size);
316 if (rc) {
317 flash_control_emit_error(flash_control,write_file);
318 return;
319 }
320#endif
321
322 flash_control_emit_done(flash_control,write_file);
323 //flash_control_emit_error(flash_control,write_file);
324 printf("Flash done\n");
325 }
326 else
327 {
328 flash_control_emit_done(flash_control,write_file);
329 printf("Flash tuned\n");
330 }
331}
332
333static void
334on_bus_acquired (GDBusConnection *connection,
335 const gchar *name,
336 gpointer user_data)
337{
338
339 cmdline *cmd = user_data;
340 if (cmd->argc < 2)
341 {
342 g_print("No objects created. Put object name and filename on command line\n");
343 return;
344 }
345 printf("Starting flasher\n");
346 ObjectSkeleton *object;
347 manager = g_dbus_object_manager_server_new (dbus_object_path);
348 gchar *s;
349 s = g_strdup_printf ("%s/%s",dbus_object_path,cmd->argv[1]);
350
351 object = object_skeleton_new (s);
352 g_free (s);
353
354 FlashControl* flash_control = flash_control_skeleton_new ();
355 object_skeleton_set_flash_control (object, flash_control);
356 g_object_unref (flash_control);
357
358 /* Export the object (@manager takes its own reference to @object) */
359 g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
360 g_object_unref (object);
361
362 /* Export all objects */
363 g_dbus_object_manager_server_set_connection (manager, connection);
364 flash(flash_control,false,cmd->argv[2]);
365
366 //Object exits when done flashing
367 g_main_loop_quit(cmd->loop);
368}
369
370int main(int argc, char *argv[])
371{
372
373 GMainLoop *loop;
374 cmdline cmd;
375 cmd.argc = argc;
376 cmd.argv = argv;
377
378 guint id;
379 loop = g_main_loop_new (NULL, FALSE);
380 cmd.loop = loop;
381
382 id = g_bus_own_name (DBUS_TYPE,
383 dbus_name,
384 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
385 G_BUS_NAME_OWNER_FLAGS_REPLACE,
386 on_bus_acquired,
387 NULL,
388 NULL,
389 &cmd,
390 NULL);
391
392 g_main_loop_run (loop);
393
394 g_bus_unown_name (id);
395 g_main_loop_unref (loop);
396
397 return 0;
398}