Mercurial > ecos
changeset 1740:0031b615f51c
Add support for reverse endianess of fis and config data
| author | msalter |
|---|---|
| date | Wed, 01 Sep 2004 21:21:30 +0000 |
| parents | 5ee8bd19b4f5 |
| children | 3480e423c3a2 |
| files | packages/redboot/current/ChangeLog packages/redboot/current/cdl/redboot.cdl packages/redboot/current/include/redboot.h packages/redboot/current/src/fconfig.c packages/redboot/current/src/flash.c packages/redboot/current/src/main.c |
| diffstat | 6 files changed, 188 insertions(+), 33 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/redboot/current/ChangeLog +++ b/packages/redboot/current/ChangeLog @@ -1,3 +1,14 @@ +2004-09-01 Mark Salter <msalter@redhat.com> + + * cdl/redboot.cdl (CYGOPT_REDBOOT_FLASH_BYTEORDER): New option. + * include/redboot.h: Define FLASH_{READ,PROGRAM} macros. + Define REDBOOT_FLASH_REVERSE_BYTEORDER if appropriate. + * src/flash.c: Add support for CYGOPT_REDBOOT_FLASH_BYTEORDER. + Use FLASH_{READ,PROGRAM} macros instead of flash driver api. + * src/fconfig.c: Ditto. + + * src/main.c (do_version): Update copyright message. + 2004-08-31 Jonathan Larmour <jifl@eCosCentric.com> * src/flash.c (fis_init): Avoid potentially unnecessary erase
--- a/packages/redboot/current/cdl/redboot.cdl +++ b/packages/redboot/current/cdl/redboot.cdl @@ -574,6 +574,16 @@ cdl_package CYGPKG_REDBOOT { into memory for execution or executed in place." compile -library=libextras.a flash.c + cdl_option CYGOPT_REDBOOT_FLASH_BYTEORDER { + display "Byte order used to store info in flash." + flavor data + default_value { "NATURAL" } + legal_values {"NATURAL" "MSBFIRST" "LSBFIRST" } + description " + This option controls the byte ordering used to store + the FIS directory info and flash config info." + } + cdl_option CYGOPT_REDBOOT_FIS { display "RedBoot Flash Image System support" default_value 1
--- a/packages/redboot/current/include/redboot.h +++ b/packages/redboot/current/include/redboot.h @@ -8,7 +8,7 @@ //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc. // Copyright (C) 2002, 2003, 2004 Gary Thomas // // eCos is free software; you can redistribute it and/or modify it under @@ -60,6 +60,7 @@ #include <pkgconf/hal.h> #include <cyg/hal/hal_if.h> #include <cyg/hal/hal_tables.h> +#include <cyg/hal/hal_endian.h> #include <cyg/infra/diag.h> #include <cyg/crc/crc.h> #include <string.h> @@ -481,4 +482,27 @@ isalnum(int c) #endif // CYGSEM_REDBOOT_BSP_SYSCALLS + +//---------------------------------------------------------------------------- +// Allow HAL to override RedBoot flash read/program operations. +#ifdef HAL_FLASH_READ +#define FLASH_READ(f, r, l, e) HAL_FLASH_READ((f),(r),(l),(e)) +#else +#define FLASH_READ(f, r, l, e) flash_read((f), (r), (l), (e)) +#endif + +#ifdef HAL_FLASH_PROGRAM +#define FLASH_PROGRAM(f, r, l, e) HAL_FLASH_PROGRAM((f),(r),(l),(e)) +#else +#define FLASH_PROGRAM(f, r, l, e) flash_program((f), (r), (l), (e)) +#endif + + +// Define REDBOOT_FLASH_REVERSE_BYTEORDER if config and fis info is stored in flash +// with byte ordering opposite from CYG_BYTEORDER. +#if (defined(CYGOPT_REDBOOT_FLASH_BYTEORDER_MSBFIRST) && (CYG_BYTEORDER != CYG_MSBFIRST)) || \ + (defined(CYGOPT_REDBOOT_FLASH_BYTEORDER_LSBFIRST) && (CYG_BYTEORDER != CYG_LSBFIRST)) +#define REDBOOT_FLASH_REVERSE_BYTEORDER +#endif + #endif // _REDBOOT_H_
--- a/packages/redboot/current/src/fconfig.c +++ b/packages/redboot/current/src/fconfig.c @@ -8,7 +8,7 @@ //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. // Copyright (C) 2003 Gary Thomas // // eCos is free software; you can redistribute it and/or modify it under @@ -54,12 +54,14 @@ //========================================================================== #include <redboot.h> +#include <cyg/io/flash.h> #ifdef CYGOPT_REDBOOT_FIS #include <fis.h> #endif #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG // Note horrid intertwining of functions, to save precious FLASH +externC void fis_read_directory(void); externC void fis_update_directory(void); #endif @@ -191,6 +193,60 @@ extern struct config_option __CONFIG_opt #define LIST_OPT_DUMBTERM (8) static void config_init(void); +static int config_length(int type); + +// Change endianness of config data +void +conf_endian_fixup(void *ptr) +{ +#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER + struct _config *p = (struct _config *)ptr; + unsigned char *dp = p->config_data; + void *val_ptr; + int len; + cyg_uint16 u16; + cyg_uint32 u32; + + p->len = CYG_SWAP32(p->len); + p->key1 = CYG_SWAP32(p->key1); + p->key2 = CYG_SWAP32(p->key2); + p->cksum = CYG_SWAP32(p->cksum); + + while (dp < &p->config_data[sizeof(config->config_data)]) { + len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) + + config_length(CONFIG_OBJECT_TYPE(dp)); + val_ptr = (void *)CONFIG_OBJECT_VALUE(dp); + + switch (CONFIG_OBJECT_TYPE(dp)) { + // Note: the data may be unaligned in the configuration data + case CONFIG_BOOL: + if (sizeof(bool) == 2) { + memcpy(&u16, val_ptr, 2); + u16 = CYG_SWAP16(u16); + memcpy(val_ptr, &u16, 2); + } else if (sizeof(bool) == 4) { + memcpy(&u32, val_ptr, 4); + u32 = CYG_SWAP32(u32); + memcpy(val_ptr, &u32, 4); + } + break; + case CONFIG_INT: + if (sizeof(unsigned long) == 2) { + memcpy(&u16, val_ptr, 2); + u16 = CYG_SWAP16(u16); + memcpy(val_ptr, &u16, 2); + } else if (sizeof(unsigned long) == 4) { + memcpy(&u32, val_ptr, 4); + u32 = CYG_SWAP32(u32); + memcpy(val_ptr, &u32, 4); + } + break; + } + + dp += len; + } +#endif +} static int get_config(unsigned char *dp, char *title, int list_opt, char *newvalue ) @@ -683,6 +739,28 @@ flash_lookup_alias(char *alias, char *al #endif // CYGSEM_REDBOOT_FLASH_ALIASES +cyg_uint32 +flash_crc(struct _config *conf) +{ + cyg_uint32 crc; +#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER + int swabbed = 0; + + if (conf->key1 == CONFIG_KEY1 && conf->key2 == CONFIG_KEY2) { + swabbed = 1; + conf_endian_fixup(conf); + } +#endif + + crc = cyg_crc32((unsigned char *)conf, sizeof(*conf)-sizeof(conf->cksum)); + +#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER + if (swabbed) + conf_endian_fixup(conf); +#endif + return crc; +} + // // Write the in-memory copy of the configuration data to the flash device. // @@ -699,11 +777,11 @@ flash_write_config(bool prompt) config->len = sizeof(struct _config); config->key1 = CONFIG_KEY1; config->key2 = CONFIG_KEY2; - config->cksum = cyg_crc32((unsigned char *)config, sizeof(struct _config)-sizeof(config->cksum)); + config->cksum = flash_crc(config); if (!prompt || verify_action("Update RedBoot non-volatile configuration")) { #ifdef CYGHWR_REDBOOT_FLASH_CONFIG_MEDIA_FLASH #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG - flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); + fis_read_directory(); fis_update_directory(); #else #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL @@ -713,11 +791,12 @@ flash_write_config(bool prompt) if ((stat = flash_erase(cfg_base, cfg_size, (void **)&err_addr)) != 0) { diag_printf(" initialization failed at %p: %s\n", err_addr, flash_errmsg(stat)); } else { - if ((stat = flash_program(cfg_base, (void *)config, sizeof(struct _config), - (void **)&err_addr)) != 0) { + conf_endian_fixup(config); + if ((stat = FLASH_PROGRAM(cfg_base, config, sizeof(struct _config), (void **)&err_addr)) != 0) { diag_printf("Error writing config data at %p: %s\n", err_addr, flash_errmsg(stat)); } + conf_endian_fixup(config); } #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL // Insure [quietly] that the config data is locked after the update @@ -828,13 +907,11 @@ flash_get_config(char *key, void *val, i // Check to see if the config data is valid, if not, revert to // readonly mode, by setting config to readonly_config. We // will set it back before we leave this function. - if ( (config != readonly_config) && ((cyg_crc32((unsigned char *)config, - sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) || + if ( (config != readonly_config) && ((flash_crc(config) != config->cksum) || (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2))) { save_config = config; config = readonly_config; - if ((cyg_crc32((unsigned char *)config, - sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) || + if ((flash_crc(config) != config->cksum) || (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2)) { diag_printf("FLASH configuration checksum error or invalid key\n"); config = save_config; @@ -1076,15 +1153,15 @@ load_flash_config(void) _rup(_rup((CYGNUM_REDBOOT_FLASH_CONFIG_BLOCK*flash_block_size), cfg_size), flash_block_size)); } #endif - flash_read((void *)cfg_base, (void *)config, sizeof(struct _config), (void **)&err_addr); + FLASH_READ(cfg_base, config, sizeof(struct _config), &err_addr); + conf_endian_fixup(config); #else read_eeprom(config, sizeof(struct _config)); // into 'config' #endif #ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK memcpy(readonly_config, config, sizeof(struct _config)); #endif - if ((cyg_crc32((unsigned char *)config, - sizeof(struct _config)-sizeof(config->cksum)) != config->cksum) || + if ((flash_crc(config) != config->cksum) || (config->key1 != CONFIG_KEY1)|| (config->key2 != CONFIG_KEY2)) { diag_printf("**Warning** FLASH configuration checksum error or invalid key\n"); diag_printf("Use 'fconfig -i' to [re]initialize database\n");
--- a/packages/redboot/current/src/flash.c +++ b/packages/redboot/current/src/flash.c @@ -8,7 +8,7 @@ //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. // Copyright (C) 2003, 2004 Gary Thomas // // eCos is free software; you can redistribute it and/or modify it under @@ -61,6 +61,7 @@ #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG // Note horrid intertwining of functions, to save precious FLASH +extern void conf_endian_fixup(void *p); #endif // Round a quantity up @@ -191,14 +192,45 @@ static void } #ifdef CYGOPT_REDBOOT_FIS + +// fis_endian_fixup() is used to swap endianess if required. +// +static inline void fis_endian_fixup(void *addr) +{ +#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER + struct fis_image_desc *p = addr; + int cnt = fisdir_size / sizeof(struct fis_image_desc); + + while (cnt-- > 0) { + p->flash_base = CYG_SWAP32(p->flash_base); + p->mem_base = CYG_SWAP32(p->mem_base); + p->size = CYG_SWAP32(p->size); + p->entry_point = CYG_SWAP32(p->entry_point); + p->data_length = CYG_SWAP32(p->data_length); + p->desc_cksum = CYG_SWAP32(p->desc_cksum); + p->file_cksum = CYG_SWAP32(p->file_cksum); + p++; + } +#endif +} + +void +fis_read_directory(void) +{ + void *err_addr; + + FLASH_READ(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); + fis_endian_fixup(fis_work_block); +} + struct fis_image_desc * fis_lookup(char *name, int *num) { int i; struct fis_image_desc *img; - void *err_addr; - flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); + fis_read_directory(); + img = (struct fis_image_desc *)fis_work_block; for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { if ((img->name[0] != (unsigned char)0xFF) && @@ -216,8 +248,10 @@ fis_update_directory(void) int stat; void *err_addr; + fis_endian_fixup(fis_work_block); #ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG memcpy((char *)fis_work_block+fisdir_size, config, cfg_size); + conf_endian_fixup((char *)fis_work_block+fisdir_size); #endif #ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL // Ensure [quietly] that the directory is unlocked before trying to update @@ -226,8 +260,8 @@ fis_update_directory(void) if ((stat = flash_erase(fis_addr, flash_block_size, (void **)&err_addr)) != 0) { diag_printf("Error erasing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat)); } else { - if ((stat = flash_program(fis_addr, fis_work_block, flash_block_size, - (void **)&err_addr)) != 0) { + if ((stat = FLASH_PROGRAM(fis_addr, fis_work_block, + flash_block_size, (void **)&err_addr)) != 0) { diag_printf("Error writing FIS directory at %p: %s\n", err_addr, flash_errmsg(stat)); } @@ -236,6 +270,7 @@ fis_update_directory(void) // Ensure [quietly] that the directory is locked after the update flash_lock((void *)fis_addr, flash_block_size, (void **)&err_addr); #endif + fis_endian_fixup(fis_work_block); } static void @@ -450,7 +485,6 @@ fis_list(int argc, char *argv[]) bool show_cksums = false; bool show_datalen = false; struct option_info opts[2]; - void *err_addr; unsigned long last_addr, lowest_addr; bool image_found; @@ -473,7 +507,8 @@ fis_list(int argc, char *argv[]) if (!scan_opts(argc, argv, 2, opts, i, 0, 0, "")) { return; } - flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); + fis_read_directory(); + // Let diag_printf do the formatting in both cases, rather than counting // cols by hand.... diag_printf("%-16s %-10s %-10s %-10s %-s\n", @@ -523,7 +558,6 @@ static int find_free(struct free_chunk *chunks) { CYG_ADDRESS *fis_ptr, *fis_end; - void *err_addr; struct fis_image_desc *img; int i, idx; int num_chunks = 1; @@ -535,7 +569,7 @@ find_free(struct free_chunk *chunks) fis_end = (CYG_ADDRESS *)flash_end; chunks[num_chunks-1].start = (CYG_ADDRESS)fis_ptr; chunks[num_chunks-1].end = (CYG_ADDRESS)fis_end; - flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); + fis_read_directory(); img = (struct fis_image_desc *) fis_work_block; for (i = 0; i < fisdir_size/sizeof(*img); i++, img++) { if (img->name[0] != (unsigned char)0xFF) { @@ -728,7 +762,7 @@ fis_create(int argc, char *argv[]) return; } - flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); + fis_read_directory(); defaults_assumed = false; if (name) { // Search existing files to acquire defaults for params not specified: @@ -888,7 +922,7 @@ fis_create(int argc, char *argv[]) } if (prog_ok) { // Now program it - if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) { + if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, img_size, (void **)&err_addr)) != 0) { diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat)); prog_ok = false; } @@ -1056,8 +1090,8 @@ fis_load(int argc, char *argv[]) load_address = mem_addr; load_address_end = (unsigned long)p->out_buf; - // Reload fis directory - flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); + // Reload fis directory + fis_read_directory(); } else // dangling block #endif { @@ -1156,7 +1190,7 @@ fis_write(int argc, char *argv[]) } if (prog_ok) { // Now program it - if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) { + if ((stat = FLASH_PROGRAM((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) { diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat)); prog_ok = false; } @@ -1227,7 +1261,7 @@ fis_lock(int argc, char *argv[]) (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, (void *)&length, (bool *)&length_set, "length"); - if (!scan_opts(argc, argv, 2, opts, 2, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) + if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name")) { fis_usage("invalid arguments"); return; @@ -1274,7 +1308,7 @@ fis_unlock(int argc, char *argv[]) (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address"); init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM, (void *)&length, (bool *)&length_set, "length"); - if (!scan_opts(argc, argv, 2, opts, 2, (void **)&name, OPTION_ARG_TYPE_STR, "image name")) + if (!scan_opts(argc, argv, 2, opts, 2, &name, OPTION_ARG_TYPE_STR, "image name")) { fis_usage("invalid arguments"); return; @@ -1321,7 +1355,6 @@ bool do_flash_init(void) { int stat; - void *err_addr; if (!__flash_init) { __flash_init = 1; @@ -1357,7 +1390,7 @@ do_flash_init(void) diag_printf("FIS directory doesn't fit\n"); return false; } - flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr); + fis_read_directory(); #endif } return true;
--- a/packages/redboot/current/src/main.c +++ b/packages/redboot/current/src/main.c @@ -8,7 +8,7 @@ //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. // Copyright (C) 2002, 2003, 2004 Gary Thomas // // eCos is free software; you can redistribute it and/or modify it under @@ -178,7 +178,7 @@ do_version(int argc, char *argv[]) #ifdef HAL_PLATFORM_CPU diag_printf("Platform: %s (%s) %s\n", HAL_PLATFORM_BOARD, HAL_PLATFORM_CPU, HAL_PLATFORM_EXTRA); #endif - diag_printf("Copyright (C) 2000, 2001, 2002, Red Hat, Inc.\n\n"); + diag_printf("Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.\n\n"); diag_printf("RAM: %p-%p, ", (void*)ram_start, (void*)ram_end); diag_printf("[%p-%p]", mem_segments[0].start, mem_segments[0].end); diag_printf(" available\n");
