[U-Boot-Users] [PATCH 8/11] Add support for environment storage in SystemACE

The patch below adds support for storing the U-Boot environment in a Compact FLASH card attached to a Xilinx SystemACE controller. The ability to store the environment in a CF card is useful in situations where conventional board-mounted FLASH memory is unavailable. Note that this option requires SystemACE CF write support which is presently not in U-Boot.
I will submit a patch to Wolfgang Denk directly (due to list attachment size limits) which provides board-specific (ant2 board) support for CF writes.
diff --git a/CHANGELOG b/CHANGELOG index c774dd0..d26e65f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,11 @@ Changes since U-Boot 1.1.4: ======================================================================
+* Add support for storing environment on a Compact Flash card managed + by a Xilinx SystemACE controller. The environment is stored on a + dedicated, unformatted partition on the card. + Patch by Keith Outwater, 04 May 2006 + * Coding Style cleanup
* Write RTC seconds first to maintain settings integrity per diff --git a/CREDITS b/CREDITS index f91fa3e..0ff1ef2 100644 --- a/CREDITS +++ b/CREDITS @@ -326,8 +326,9 @@ E: torkun@nextio.com D: Support for Cogent CSB272 & CSB472 boards
N: Keith Outwater -E: keith_outwater@mvis.com +E: outwater4@comcast.net D: Support for generic/custom MPC860T boards (GEN860T, GEN860T_SC) +D: Support for environment storage in SystemACE Compact FLASH
N: Frank Panno E: fpanno@delphintech.com diff --git a/README b/README index 3ffef62..e1ba798 100644 --- a/README +++ b/README @@ -1535,6 +1535,15 @@ The following options need to be configu When SystemACE support is added, the "ace" device type becomes available to the fat commands, i.e. fatls.
+ CFG_USE_BSP_SYSACE_DRIVER + + Defining this option selects board specific functions + for accessing the CF card attached to the SystemACE + controller. Typically the drivers would be based on the + Xilinx drivers generated by the Xilinx EDK tool. + The Xilinx driver can handle both 8 and 16 bit databus + interfaces to the SystemACE controller. + - TFTP Fixed UDP Port: CONFIG_TFTP_PORT
@@ -1995,6 +2004,27 @@ to save the current settings. to a block boundary, and CFG_ENV_SIZE must be a multiple of the NAND devices block size.
+- CFG_ENV_IS_IN_SYSACE: + + Define this if you have a Compact Flash (CF) card connected to a + Xilinx SystemACE controller in which you wish to store the environment. + + - CFG_SYSTEMACE_ENV_DEV: + The device (instance) number of the SystemACE device you wich to use. + This is normally zero for a system with a single SystemACE. + + - CFG_ENV_SIZE: + The size of the environment in bytes. Note that presently this must + be a multiple of the CF card sector size (512 bytes). + + - CFG_SYSTEMACE_ENV_PART: + The partiton number of the partition dedicated to U-Boot environment + storage. You need to insure that the partiton includes enough + sectors to store the environment. The partition must be a primary + partition and the partition must be used exclusively for the + environment. + + - CFG_SPI_INIT_OFFSET
Defines offset to the initial SPI buffer area in DPRAM. The diff --git a/common/Makefile b/common/Makefile index eb0b5da..04b5b9b 100644 --- a/common/Makefile +++ b/common/Makefile @@ -44,7 +44,7 @@ COBJS = main.o ACEX1K.o altera.o bedbug. command.o console.o devices.o dlmalloc.o docecc.o \ environment.o env_common.o \ env_nand.o env_dataflash.o env_flash.o env_eeprom.o \ - env_nvram.o env_nowhere.o \ + env_nvram.o env_sysace.o env_nowhere.o \ exports.o \ flash.o fpga.o ft_build.o \ hush.o kgdb.o lcd.o lists.o lynxkdi.o \ diff --git a/common/cmd_ace.c b/common/cmd_ace.c index b6d6105..ba6d0fe 100644 --- a/common/cmd_ace.c +++ b/common/cmd_ace.c @@ -32,6 +32,13 @@ #ident "$Id:$" * description that has all the bits needed for FAT support to * read sectors. * + * If CFG_USE_BSP_SYSACE_DRIVER is defined, use a board + * specific SystemACE driver to access the CF card. Typically + * the BSP driver would use the Xilinx driver code generated by + * the Xilinx EDK tool. The Xilinx SystemACE driver + * automatically handles endian conversion and 8 or 16 bit + * SystemACE databus widths. + * * According to Xilinx technical support, before accessing the * SystemACE CF you need to set the following control bits: * FORCECFGMODE : 1 @@ -45,7 +52,8 @@ # include <systemace.h> # include <part.h> # include <asm/io.h>
-#ifdef CONFIG_SYSTEMACE +#if defined(CONFIG_SYSTEMACE) +#if !defined(CFG_USE_BSP_SYSACE_DRIVER)
/* * The ace_readw and writew functions read/write 16bit words, but the @@ -264,4 +272,5 @@ #endif
return blkcnt; } -#endif /* CONFIG_SYSTEMACE */ +#endif /* !defined(CFG_USE_BSP_SYSACE_DRIVER) */ +#endif /* defined(CONFIG_SYSTEMACE) */ diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 6257fbd..0985509 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -57,6 +57,7 @@ #if !defined(CFG_ENV_IS_IN_NVRAM) && \ !defined(CFG_ENV_IS_IN_FLASH) && \ !defined(CFG_ENV_IS_IN_DATAFLASH) && \ !defined(CFG_ENV_IS_IN_NAND) && \ + !defined(CFG_ENV_IS_IN_SYSTEMACE) && \ !defined(CFG_ENV_IS_NOWHERE) # error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|NOWHERE} #endif @@ -530,7 +531,9 @@ int getenv_r (char *name, char *buf, uns return (-1); }
-#if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) || \ +#if defined(CFG_ENV_IS_IN_NVRAM) || \ + defined(CFG_ENV_IS_IN_EEPROM) || \ + defined(CFG_ENV_IS_IN_SYSTEMACE) || \ ((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_FLASH)) == \ (CFG_CMD_ENV|CFG_CMD_FLASH)) || \ ((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_NAND)) == \ @@ -588,7 +591,9 @@ U_BOOT_CMD( " - delete environment variable 'name'\n" );
-#if defined(CFG_ENV_IS_IN_NVRAM) || defined(CFG_ENV_IS_IN_EEPROM) || \ +#if defined(CFG_ENV_IS_IN_NVRAM) || \ + defined(CFG_ENV_IS_IN_EEPROM) || \ + defined(CFG_ENV_IS_IN_SYSTEMACE) || \ ((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_FLASH)) == \ (CFG_CMD_ENV|CFG_CMD_FLASH)) || \ ((CONFIG_COMMANDS & (CFG_CMD_ENV|CFG_CMD_NAND)) == \ diff --git a/common/env_common.c b/common/env_common.c index eb33422..492f979 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -141,7 +141,8 @@ #endif "\0" };
-#if defined(CFG_ENV_IS_IN_NAND) /* Environment is in Nand Flash */ +/* Environment is in Nand Flash or in CF card attached to a SystemACE*/ +#if defined(CFG_ENV_IS_IN_NAND) || defined (CFG_ENV_IS_IN_SYSTEMACE) int default_environment_size = sizeof(default_environment); #endif
diff --git a/common/env_sysace.c b/common/env_sysace.c new file mode 100644 index 0000000..616519c --- /dev/null +++ b/common/env_sysace.c @@ -0,0 +1,268 @@ +/*-------------------------------------------------------------------- + * (C) Copyright 2005 + * Keith Outwater, outwater4@comcast.net + * + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Support for saving the U-Boot environment in a CompactFlash card connected + * to a Xilinx SystemACE FPGA configuration engine. + * + * The basic approach used here is to get just enough of a default + * environment to be able to get the console serial port baud rate set up + * and then get the full environment after U-Boot relocates into main memory. + * After relocation, there is a full C environment available, so we can use + * the existing code to load/store the environment onto a dedicated partition + * on the CF card. If we had FAT filesystem code to do writes instead of just + * reads, we could even store the environment as a regular DOS file. Alas, + * we do not have that code... + */ + +#include <common.h> + +#if defined(CFG_ENV_IS_IN_SYSTEMACE) + +#if !defined(CFG_SYSTEMACE_ENV_DEV) +#error "You must specify the SystemACE device instance" +#endif + +#if !defined(CFG_SYSTEMACE_ENV_PART) +#error "You must specify a primary partition 1-4 for the environment" +#endif + +#include <command.h> +#include <environment.h> +#include <linux/stddef.h> +#include <malloc.h> +#include "../disk/part_dos.h" /* ugly, but it's not in ../include! */ + +/* + * This function can be either board-specific or U-Boot builtin + */ +extern unsigned long systemace_read(int dev, unsigned long start, + lbaint_t blkcnt, + unsigned long *buffer); + +/* + * Presently this function is board-specific only (ant2) + */ +extern unsigned long systemace_write(int dev, unsigned long start, + lbaint_t blkcnt, + unsigned long *buffer); + +/* + * In env_common.c + */ +extern uchar default_environment[]; +extern int default_environment_size; + +env_t *env_ptr = NULL; +char *env_name_spec = "SystemACE"; + +#define CF_SECT_SIZE 512 +#define CF_ENV_SECTS (CFG_ENV_SIZE / CF_SECT_SIZE) + +uchar +env_get_char_spec(int index) +{ + DECLARE_GLOBAL_DATA_PTR; + + return ( *((uchar *)(gd->env_addr + index)) ); +} + +static inline int +le32_to_int(unsigned char *le32) +{ + return ((le32[3] << 24) + (le32[2] << 16) + (le32[1] << 8) + le32[0]); +} + +/* + * Read the CF card partition table and determine the absolute starting + * sector for the partition and the size in sectors of the partition. + * Return 1 on error, 0 on success. + */ +static int +read_env_partition(int *start) +{ + int start_sect; + int sect_size; + u_char buffer[CF_SECT_SIZE]; + dos_partition_t *pt; + + /* + * Read the partition table and get the first sector of the environment + * partition. + */ + if (systemace_read(CFG_SYSTEMACE_ENV_DEV, 0, 1, + (unsigned long *)buffer) != 1) { + puts("Error reading partiton table\n"); + return 1; + } + +#if (CFG_SYSTEMACE_ENV_PART < 1) || (CFG_SYSTEMACE_ENV_PART > 4) +#error "The partition number must be between 1 and 4" +#endif + + /* + * Index into the partition table to get to the partition reserved for + * the U-Boot environment as specified in the board configuration. + */ + pt = (dos_partition_t *)(buffer + DOS_PART_TBL_OFFSET + + (sizeof(dos_partition_t) * (CFG_SYSTEMACE_ENV_PART - 1))); + + start_sect = le32_to_int(pt->start4); + sect_size = le32_to_int(pt->size4); + + /* + * Basic sanity check: is the starting sector greator than zero and is + * the number of sectors in the partition enough to hold the environment? + */ + if (start_sect <= 0) { + puts("Error: Starting sector in partition is not positive\n"); + return 1; + } + + if ((CF_ENV_SECTS) > sect_size) { + printf("Error: Sectors in partition (%d) less than required (%d)\n", + sect_size, CF_ENV_SECTS); + return 1; + } + + *start = start_sect; + return 0; +} + +/* + * Copy the default environment into the environment. + */ +static void +use_default_env(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + puts("Using default environment\n"); + + if (default_environment_size > CFG_ENV_SIZE){ + puts("Error: Default environment is too large\n"); + return; + } + + memset (env_ptr, 0, sizeof(env_t)); + memcpy (env_ptr->data, default_environment, default_environment_size); + env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE); + gd->env_valid = 1; +} + +/* + * This is where we get the "real" environment loaded from the CF card. + * We are running in a normal C environemnt at this point (i.e. this is + * post U-Boot relocation). + */ +void +env_relocate_spec(void) +{ + int start_sect; + + if (read_env_partition(&start_sect) != 0) { + puts("Error: CF card partition table read failed; "); + return use_default_env(); + } + + /* + * Read the partition table and get the first sector of the environment + * partition. + */ + if (systemace_read(CFG_SYSTEMACE_ENV_DEV, (unsigned long) start_sect, + CF_ENV_SECTS, + (unsigned long *)env_ptr) != CF_ENV_SECTS) { + puts("Error: CF card read failed; "); + return use_default_env(); + } + +#ifdef DEBUG + printf("%s:%d: Start sector = %d\n", __FUNCTION__, __LINE__, start_sect); +#endif + + /* + * If crc fails, use the default environment. + */ + if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) { + puts("Error: CRC failed; "); + return use_default_env(); + } +} + +int +saveenv(void) +{ + int start_sect; + + if (read_env_partition(&start_sect) != 0) { + return 1; + } + +#ifdef DEBUG + printf("%s:%d: Start sector = %d\n", __FUNCTION__, __LINE__, start_sect); +#endif + + /* + * We know the absolute start sector on the CF card, so now simply + * write the environment to the card. + * NOTE that we require the environment to be an integer number of CF + * card sectors! It doesn't have to be, but it's convenient and it's + * not like we'll run out of space on the card... + */ + if (systemace_write(CFG_SYSTEMACE_ENV_DEV, (unsigned long)start_sect, + CF_ENV_SECTS, + (unsigned long *)env_ptr) != CF_ENV_SECTS) { + puts("Error: CF card write failed\n"); + return 1; + } + else { + puts("Done.\n"); + } + + return 0; +} + +/* + * Initialize the environment. + * Still in a "ROM" environment, so just use the default environment. + * When env_relocate_spec() gets called from env_relocate() + * located in env_common.c, the execution environment will be a + * "normal" C environment and we can then read the full environment + * from the SystemACE CF card. Using the default environment will + * get us talking to the UART. + */ +int +env_init(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; + return 0; +} + +#endif /* CFG_ENV_IS_IN_SYSTEMACE */ +/* vim: set ts=4 tw=80 sw=4 cindent fo=tcroq: */
Signed-off-by: Keith Outwater outwater4@comcast.net
participants (1)
-
Keith J Outwater