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