comparison packages/redboot/current/src/flash.c @ 1740:0031b615f51c

Add support for reverse endianess of fis and config data
author msalter
date Wed, 01 Sep 2004 21:21:30 +0000
parents 9091309eb665
children ecd76f498508
comparison
equal deleted inserted replaced
1739:5ee8bd19b4f5 1740:0031b615f51c
6 // 6 //
7 //========================================================================== 7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN#### 8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // ------------------------------------------- 9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System. 10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. 11 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
12 // Copyright (C) 2003, 2004 Gary Thomas 12 // Copyright (C) 2003, 2004 Gary Thomas
13 // 13 //
14 // eCos is free software; you can redistribute it and/or modify it under 14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free 15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version. 16 // Software Foundation; either version 2 or (at your option) any later version.
59 #include <sib.h> 59 #include <sib.h>
60 #include <cyg/infra/cyg_ass.h> // assertion macros 60 #include <cyg/infra/cyg_ass.h> // assertion macros
61 61
62 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG 62 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
63 // Note horrid intertwining of functions, to save precious FLASH 63 // Note horrid intertwining of functions, to save precious FLASH
64 extern void conf_endian_fixup(void *p);
64 #endif 65 #endif
65 66
66 // Round a quantity up 67 // Round a quantity up
67 #define _rup(n,s) ((((n)+(s-1))/s)*s) 68 #define _rup(n,s) ((((n)+(s-1))/s)*s)
68 69
189 diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat)); 190 diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
190 diag_printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end); 191 diag_printf(" valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
191 } 192 }
192 193
193 #ifdef CYGOPT_REDBOOT_FIS 194 #ifdef CYGOPT_REDBOOT_FIS
195
196 // fis_endian_fixup() is used to swap endianess if required.
197 //
198 static inline void fis_endian_fixup(void *addr)
199 {
200 #ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
201 struct fis_image_desc *p = addr;
202 int cnt = fisdir_size / sizeof(struct fis_image_desc);
203
204 while (cnt-- > 0) {
205 p->flash_base = CYG_SWAP32(p->flash_base);
206 p->mem_base = CYG_SWAP32(p->mem_base);
207 p->size = CYG_SWAP32(p->size);
208 p->entry_point = CYG_SWAP32(p->entry_point);
209 p->data_length = CYG_SWAP32(p->data_length);
210 p->desc_cksum = CYG_SWAP32(p->desc_cksum);
211 p->file_cksum = CYG_SWAP32(p->file_cksum);
212 p++;
213 }
214 #endif
215 }
216
217 void
218 fis_read_directory(void)
219 {
220 void *err_addr;
221
222 FLASH_READ(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
223 fis_endian_fixup(fis_work_block);
224 }
225
194 struct fis_image_desc * 226 struct fis_image_desc *
195 fis_lookup(char *name, int *num) 227 fis_lookup(char *name, int *num)
196 { 228 {
197 int i; 229 int i;
198 struct fis_image_desc *img; 230 struct fis_image_desc *img;
199 void *err_addr; 231
200 232 fis_read_directory();
201 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); 233
202 img = (struct fis_image_desc *)fis_work_block; 234 img = (struct fis_image_desc *)fis_work_block;
203 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { 235 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
204 if ((img->name[0] != (unsigned char)0xFF) && 236 if ((img->name[0] != (unsigned char)0xFF) &&
205 (strcasecmp(name, img->name) == 0)) { 237 (strcasecmp(name, img->name) == 0)) {
206 if (num) *num = i; 238 if (num) *num = i;
214 fis_update_directory(void) 246 fis_update_directory(void)
215 { 247 {
216 int stat; 248 int stat;
217 void *err_addr; 249 void *err_addr;
218 250
251 fis_endian_fixup(fis_work_block);
219 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG 252 #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
220 memcpy((char *)fis_work_block+fisdir_size, config, cfg_size); 253 memcpy((char *)fis_work_block+fisdir_size, config, cfg_size);
254 conf_endian_fixup((char *)fis_work_block+fisdir_size);
221 #endif 255 #endif
222 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL 256 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
223 // Ensure [quietly] that the directory is unlocked before trying to update 257 // Ensure [quietly] that the directory is unlocked before trying to update
224 flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr); 258 flash_unlock((void *)fis_addr, flash_block_size, (void **)&err_addr);
225 #endif 259 #endif
226 if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) { 260 if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) {
227 diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat)); 261 diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat));
228 } else { 262 } else {
229 if ((stat = flash_program(fis_addr, fis_work_block, flash_block_size, 263 if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block,
230 (void **)&err_addr)) != 0) { 264 flash_block_size, (void **)&err_addr)) != 0) {
231 diag_printf("Error writing FIS directory at %p: %s\n", 265 diag_printf("Error writing FIS directory at %p: %s\n",
232 err_addr, flash_errmsg(stat)); 266 err_addr, flash_errmsg(stat));
233 } 267 }
234 } 268 }
235 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL 269 #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
236 // Ensure [quietly] that the directory is locked after the update 270 // Ensure [quietly] that the directory is locked after the update
237 flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr); 271 flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr);
238 #endif 272 #endif
273 fis_endian_fixup(fis_work_block);
239 } 274 }
240 275
241 static void 276 static void
242 fis_init(int argc, char *argv[]) 277 fis_init(int argc, char *argv[])
243 { 278 {
448 struct fis_image_desc *img; 483 struct fis_image_desc *img;
449 int i, image_indx; 484 int i, image_indx;
450 bool show_cksums = false; 485 bool show_cksums = false;
451 bool show_datalen = false; 486 bool show_datalen = false;
452 struct option_info opts[2]; 487 struct option_info opts[2];
453 void *err_addr;
454 unsigned long last_addr, lowest_addr; 488 unsigned long last_addr, lowest_addr;
455 bool image_found; 489 bool image_found;
456 490
457 #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB 491 #ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB
458 // FIXME: this is somewhat half-baked 492 // FIXME: this is somewhat half-baked
471 i = 1; 505 i = 1;
472 #endif 506 #endif
473 if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) { 507 if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) {
474 return; 508 return;
475 } 509 }
476 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); 510 fis_read_directory();
511
477 // Let diag_printf do the formatting in both cases, rather than counting 512 // Let diag_printf do the formatting in both cases, rather than counting
478 // cols by hand.... 513 // cols by hand....
479 diag_printf("%-16s %-10s %-10s %-10s %-s\n", 514 diag_printf("%-16s %-10s %-10s %-10s %-s\n",
480 "Name","FLASH addr", 515 "Name","FLASH addr",
481 show_cksums ? "Checksum" : "Mem addr", 516 show_cksums ? "Checksum" : "Mem addr",
521 556
522 static int 557 static int
523 find_free(struct free_chunk *chunks) 558 find_free(struct free_chunk *chunks)
524 { 559 {
525 CYG_ADDRESS *fis_ptr, *fis_end; 560 CYG_ADDRESS *fis_ptr, *fis_end;
526 void *err_addr;
527 struct fis_image_desc *img; 561 struct fis_image_desc *img;
528 int i, idx; 562 int i, idx;
529 int num_chunks = 1; 563 int num_chunks = 1;
530 564
531 // Do not search the area reserved for pre-RedBoot systems: 565 // Do not search the area reserved for pre-RedBoot systems:
533 CYGNUM_REDBOOT_FLASH_RESERVED_BASE + 567 CYGNUM_REDBOOT_FLASH_RESERVED_BASE +
534 CYGBLD_REDBOOT_MIN_IMAGE_SIZE); 568 CYGBLD_REDBOOT_MIN_IMAGE_SIZE);
535 fis_end = (CYG_ADDRESS *)flash_end; 569 fis_end = (CYG_ADDRESS *)flash_end;
536 chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr; 570 chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr;
537 chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end; 571 chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end;
538 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); 572 fis_read_directory();
539 img = (struct fis_image_desc *) fis_work_block; 573 img = (struct fis_image_desc *) fis_work_block;
540 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { 574 for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) {
541 if (img->name[0] != (unsigned char)0xFF) { 575 if (img->name[0] != (unsigned char)0xFF) {
542 // Figure out which chunk this is in and split it 576 // Figure out which chunk this is in and split it
543 for (idx = 0; idx < num_chunks; idx++) { 577 for (idx = 0; idx < num_chunks; idx++) {
726 { 760 {
727 fis_usage("invalid arguments"); 761 fis_usage("invalid arguments");
728 return; 762 return;
729 } 763 }
730 764
731 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); 765 fis_read_directory();
732 defaults_assumed = false; 766 defaults_assumed = false;
733 if (name) { 767 if (name) {
734 // Search existing files to acquire defaults for params not specified: 768 // Search existing files to acquire defaults for params not specified:
735 img = fis_lookup(name, NULL); 769 img = fis_lookup(name, NULL);
736 if (img) { 770 if (img) {
886 prog_ok = false; 920 prog_ok = false;
887 } 921 }
888 } 922 }
889 if (prog_ok) { 923 if (prog_ok) {
890 // Now program it 924 // Now program it
891 if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) { 925 if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) {
892 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat)); 926 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
893 prog_ok = false; 927 prog_ok = false;
894 } 928 }
895 } 929 }
896 } 930 }
1054 1088
1055 // Set load address/top 1089 // Set load address/top
1056 load_address = mem_addr; 1090 load_address = mem_addr;
1057 load_address_end = (unsigned long)p->out_buf; 1091 load_address_end = (unsigned long)p->out_buf;
1058 1092
1059 // Reload fis directory 1093 // Reload fis directory
1060 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); 1094 fis_read_directory();
1061 } else // dangling block 1095 } else // dangling block
1062 #endif 1096 #endif
1063 { 1097 {
1064 flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr); 1098 flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr);
1065 1099
1154 prog_ok = false; 1188 prog_ok = false;
1155 } 1189 }
1156 } 1190 }
1157 if (prog_ok) { 1191 if (prog_ok) {
1158 // Now program it 1192 // Now program it
1159 if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) { 1193 if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) {
1160 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat)); 1194 diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
1161 prog_ok = false; 1195 prog_ok = false;
1162 } 1196 }
1163 } 1197 }
1164 } 1198 }
1225 1259
1226 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, 1260 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
1227 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); 1261 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
1228 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, 1262 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
1229 (void *)&length, (bool *)&length_set, "length"); 1263 (void *)&length, (bool *)&length_set, "length");
1230 if (!scan_opts(argc, argv, 2, opts, 2, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) 1264 if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name"))
1231 { 1265 {
1232 fis_usage("invalid arguments"); 1266 fis_usage("invalid arguments");
1233 return; 1267 return;
1234 } 1268 }
1235 1269
1272 1306
1273 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM, 1307 init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
1274 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); 1308 (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
1275 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, 1309 init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
1276 (void *)&length, (bool *)&length_set, "length"); 1310 (void *)&length, (bool *)&length_set, "length");
1277 if (!scan_opts(argc, argv, 2, opts, 2, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) 1311 if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name"))
1278 { 1312 {
1279 fis_usage("invalid arguments"); 1313 fis_usage("invalid arguments");
1280 return; 1314 return;
1281 } 1315 }
1282 1316
1319 1353
1320 bool 1354 bool
1321 do_flash_init(void) 1355 do_flash_init(void)
1322 { 1356 {
1323 int stat; 1357 int stat;
1324 void *err_addr;
1325 1358
1326 if (!__flash_init) { 1359 if (!__flash_init) {
1327 __flash_init = 1; 1360 __flash_init = 1;
1328 if ((stat = flash_init(diag_printf)) != 0) { 1361 if ((stat = flash_init(diag_printf)) != 0) {
1329 diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat)); 1362 diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
1355 } 1388 }
1356 if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) { 1389 if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
1357 diag_printf("FIS directory doesn't fit\n"); 1390 diag_printf("FIS directory doesn't fit\n");
1358 return false; 1391 return false;
1359 } 1392 }
1360 flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); 1393 fis_read_directory();
1361 #endif 1394 #endif
1362 } 1395 }
1363 return true; 1396 return true;
1364 } 1397 }
1365 1398