mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 10:26:10 +01:00 
			
		
		
		
	env: Drop the env_name_spec global
Add a name to the driver and use that instead of the global variable declared by each driver. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Tom Rini <trini@konsulko.com>
This commit is contained in:
		| @@ -706,7 +706,9 @@ ulong getenv_ulong(const char *name, int base, ulong default_val) | |||||||
| static int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, | static int do_env_save(cmd_tbl_t *cmdtp, int flag, int argc, | ||||||
| 		       char * const argv[]) | 		       char * const argv[]) | ||||||
| { | { | ||||||
| 	printf("Saving Environment to %s...\n", env_name_spec); | 	struct env_driver *env = env_driver_lookup_default(); | ||||||
|  |  | ||||||
|  | 	printf("Saving Environment to %s...\n", env->name); | ||||||
|  |  | ||||||
| 	return saveenv() ? 1 : 0; | 	return saveenv() ? 1 : 0; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								env/dataflash.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								env/dataflash.c
									
									
									
									
										vendored
									
									
								
							| @@ -16,8 +16,6 @@ DECLARE_GLOBAL_DATA_PTR; | |||||||
|  |  | ||||||
| env_t *env_ptr; | env_t *env_ptr; | ||||||
|  |  | ||||||
| char *env_name_spec = "dataflash"; |  | ||||||
|  |  | ||||||
| static unsigned char env_dataflash_get_char(int index) | static unsigned char env_dataflash_get_char(int index) | ||||||
| { | { | ||||||
| 	uchar c; | 	uchar c; | ||||||
| @@ -70,6 +68,7 @@ static int env_dataflash_save(void) | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(dataflash) = { | U_BOOT_ENV_LOCATION(dataflash) = { | ||||||
| 	.location	= ENVL_DATAFLASH, | 	.location	= ENVL_DATAFLASH, | ||||||
|  | 	ENV_NAME("dataflash") | ||||||
| 	.get_char	= env_dataflash_get_char, | 	.get_char	= env_dataflash_get_char, | ||||||
| 	.load		= env_dataflash_load, | 	.load		= env_dataflash_load, | ||||||
| 	.save		= env_save_ptr(env_dataflash_save), | 	.save		= env_save_ptr(env_dataflash_save), | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								env/eeprom.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								env/eeprom.c
									
									
									
									
										vendored
									
									
								
							| @@ -23,8 +23,6 @@ DECLARE_GLOBAL_DATA_PTR; | |||||||
|  |  | ||||||
| env_t *env_ptr; | env_t *env_ptr; | ||||||
|  |  | ||||||
| char *env_name_spec = "EEPROM"; |  | ||||||
|  |  | ||||||
| static int eeprom_bus_read(unsigned dev_addr, unsigned offset, | static int eeprom_bus_read(unsigned dev_addr, unsigned offset, | ||||||
| 			   uchar *buffer, unsigned cnt) | 			   uchar *buffer, unsigned cnt) | ||||||
| { | { | ||||||
| @@ -233,6 +231,7 @@ static int env_eeprom_save(void) | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(eeprom) = { | U_BOOT_ENV_LOCATION(eeprom) = { | ||||||
| 	.location	= ENVL_EEPROM, | 	.location	= ENVL_EEPROM, | ||||||
|  | 	ENV_NAME("EEPROM") | ||||||
| 	.get_char	= env_eeprom_get_char, | 	.get_char	= env_eeprom_get_char, | ||||||
| 	.load		= env_eeprom_load, | 	.load		= env_eeprom_load, | ||||||
| 	.save		= env_save_ptr(env_eeprom_save), | 	.save		= env_save_ptr(env_eeprom_save), | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								env/env.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								env/env.c
									
									
									
									
										vendored
									
									
								
							| @@ -54,7 +54,7 @@ static enum env_location env_get_default_location(void) | |||||||
| 		return ENVL_UNKNOWN; | 		return ENVL_UNKNOWN; | ||||||
| } | } | ||||||
|  |  | ||||||
| static struct env_driver *env_driver_lookup_default(void) | struct env_driver *env_driver_lookup_default(void) | ||||||
| { | { | ||||||
| 	enum env_location loc = env_get_default_location(); | 	enum env_location loc = env_get_default_location(); | ||||||
| 	struct env_driver *drv; | 	struct env_driver *drv; | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								env/ext4.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								env/ext4.c
									
									
									
									
										vendored
									
									
								
							| @@ -31,8 +31,6 @@ | |||||||
| #include <ext4fs.h> | #include <ext4fs.h> | ||||||
| #include <mmc.h> | #include <mmc.h> | ||||||
|  |  | ||||||
| char *env_name_spec = "EXT4"; |  | ||||||
|  |  | ||||||
| env_t *env_ptr; | env_t *env_ptr; | ||||||
|  |  | ||||||
| DECLARE_GLOBAL_DATA_PTR; | DECLARE_GLOBAL_DATA_PTR; | ||||||
| @@ -121,6 +119,7 @@ err_env_relocate: | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(ext4) = { | U_BOOT_ENV_LOCATION(ext4) = { | ||||||
| 	.location	= ENVL_EXT4, | 	.location	= ENVL_EXT4, | ||||||
|  | 	ENV_NAME("EXT4") | ||||||
| 	.load		= env_ext4_load, | 	.load		= env_ext4_load, | ||||||
| 	.save		= env_save_ptr(env_ext4_save), | 	.save		= env_save_ptr(env_ext4_save), | ||||||
| }; | }; | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								env/fat.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								env/fat.c
									
									
									
									
										vendored
									
									
								
							| @@ -31,8 +31,6 @@ | |||||||
| # endif | # endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| char *env_name_spec = "FAT"; |  | ||||||
|  |  | ||||||
| env_t *env_ptr; | env_t *env_ptr; | ||||||
|  |  | ||||||
| DECLARE_GLOBAL_DATA_PTR; | DECLARE_GLOBAL_DATA_PTR; | ||||||
| @@ -116,6 +114,7 @@ err_env_relocate: | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(fat) = { | U_BOOT_ENV_LOCATION(fat) = { | ||||||
| 	.location	= ENVL_FAT, | 	.location	= ENVL_FAT, | ||||||
|  | 	ENV_NAME("FAT") | ||||||
| #ifdef LOADENV | #ifdef LOADENV | ||||||
| 	.load		= env_fat_load, | 	.load		= env_fat_load, | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								env/flash.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								env/flash.c
									
									
									
									
										vendored
									
									
								
							| @@ -45,8 +45,6 @@ DECLARE_GLOBAL_DATA_PTR; | |||||||
| #define INITENV | #define INITENV | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| char *env_name_spec = "Flash"; |  | ||||||
|  |  | ||||||
| #ifdef ENV_IS_EMBEDDED | #ifdef ENV_IS_EMBEDDED | ||||||
| env_t *env_ptr = &environment; | env_t *env_ptr = &environment; | ||||||
|  |  | ||||||
| @@ -359,6 +357,7 @@ static void env_flash_load(void) | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(flash) = { | U_BOOT_ENV_LOCATION(flash) = { | ||||||
| 	.location	= ENVL_FLASH, | 	.location	= ENVL_FLASH, | ||||||
|  | 	ENV_NAME("Flash") | ||||||
| #ifdef LOADENV | #ifdef LOADENV | ||||||
| 	.load		= env_flash_load, | 	.load		= env_flash_load, | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								env/mmc.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								env/mmc.c
									
									
									
									
										vendored
									
									
								
							| @@ -23,8 +23,6 @@ | |||||||
| #error CONFIG_ENV_SIZE_REDUND should be the same as CONFIG_ENV_SIZE | #error CONFIG_ENV_SIZE_REDUND should be the same as CONFIG_ENV_SIZE | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| char *env_name_spec = "MMC"; |  | ||||||
|  |  | ||||||
| #ifdef ENV_IS_EMBEDDED | #ifdef ENV_IS_EMBEDDED | ||||||
| env_t *env_ptr = &environment; | env_t *env_ptr = &environment; | ||||||
| #else /* ! ENV_IS_EMBEDDED */ | #else /* ! ENV_IS_EMBEDDED */ | ||||||
| @@ -318,6 +316,7 @@ err: | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(mmc) = { | U_BOOT_ENV_LOCATION(mmc) = { | ||||||
| 	.location	= ENVL_MMC, | 	.location	= ENVL_MMC, | ||||||
|  | 	ENV_NAME("MMC") | ||||||
| 	.load		= env_mmc_load, | 	.load		= env_mmc_load, | ||||||
| #ifndef CONFIG_SPL_BUILD | #ifndef CONFIG_SPL_BUILD | ||||||
| 	.save		= env_save_ptr(env_mmc_save), | 	.save		= env_save_ptr(env_mmc_save), | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								env/nand.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								env/nand.c
									
									
									
									
										vendored
									
									
								
							| @@ -40,8 +40,6 @@ | |||||||
| #define CONFIG_ENV_RANGE	CONFIG_ENV_SIZE | #define CONFIG_ENV_RANGE	CONFIG_ENV_SIZE | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| char *env_name_spec = "NAND"; |  | ||||||
|  |  | ||||||
| #if defined(ENV_IS_EMBEDDED) | #if defined(ENV_IS_EMBEDDED) | ||||||
| env_t *env_ptr = &environment; | env_t *env_ptr = &environment; | ||||||
| #elif defined(CONFIG_NAND_ENV_DST) | #elif defined(CONFIG_NAND_ENV_DST) | ||||||
| @@ -398,6 +396,7 @@ static void env_nand_load(void) | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(nand) = { | U_BOOT_ENV_LOCATION(nand) = { | ||||||
| 	.location	= ENVL_NAND, | 	.location	= ENVL_NAND, | ||||||
|  | 	ENV_NAME("NAND") | ||||||
| 	.load		= env_nand_load, | 	.load		= env_nand_load, | ||||||
| #if defined(CMD_SAVEENV) | #if defined(CMD_SAVEENV) | ||||||
| 	.save		= env_save_ptr(env_nand_save), | 	.save		= env_save_ptr(env_nand_save), | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								env/nowhere.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								env/nowhere.c
									
									
									
									
										vendored
									
									
								
							| @@ -19,4 +19,5 @@ env_t *env_ptr; | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(nowhere) = { | U_BOOT_ENV_LOCATION(nowhere) = { | ||||||
| 	.location	= ENVL_NOWHERE, | 	.location	= ENVL_NOWHERE, | ||||||
|  | 	ENV_NAME("nowhere") | ||||||
| }; | }; | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								env/nvram.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								env/nvram.c
									
									
									
									
										vendored
									
									
								
							| @@ -41,8 +41,6 @@ env_t *env_ptr; | |||||||
| env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR; | env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| char *env_name_spec = "NVRAM"; |  | ||||||
|  |  | ||||||
| #ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE | #ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE | ||||||
| static uchar env_nvram_get_char(int index) | static uchar env_nvram_get_char(int index) | ||||||
| { | { | ||||||
| @@ -115,6 +113,7 @@ static int env_nvram_init(void) | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(nvram) = { | U_BOOT_ENV_LOCATION(nvram) = { | ||||||
| 	.location	= ENVL_NVRAM, | 	.location	= ENVL_NVRAM, | ||||||
|  | 	ENV_NAME("NVRAM") | ||||||
| #ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE | #ifdef CONFIG_SYS_NVRAM_ACCESS_ROUTINE | ||||||
| 	.get_char	= env_nvram_get_char, | 	.get_char	= env_nvram_get_char, | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								env/onenand.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								env/onenand.c
									
									
									
									
										vendored
									
									
								
							| @@ -21,8 +21,6 @@ | |||||||
| #include <linux/mtd/mtd.h> | #include <linux/mtd/mtd.h> | ||||||
| #include <linux/mtd/onenand.h> | #include <linux/mtd/onenand.h> | ||||||
|  |  | ||||||
| char *env_name_spec = "OneNAND"; |  | ||||||
|  |  | ||||||
| #define ONENAND_MAX_ENV_SIZE	CONFIG_ENV_SIZE | #define ONENAND_MAX_ENV_SIZE	CONFIG_ENV_SIZE | ||||||
| #define ONENAND_ENV_SIZE(mtd)	(ONENAND_MAX_ENV_SIZE - ENV_HEADER_SIZE) | #define ONENAND_ENV_SIZE(mtd)	(ONENAND_MAX_ENV_SIZE - ENV_HEADER_SIZE) | ||||||
|  |  | ||||||
| @@ -108,6 +106,7 @@ static int env_onenand_save(void) | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(onenand) = { | U_BOOT_ENV_LOCATION(onenand) = { | ||||||
| 	.location	= ENVL_ONENAND, | 	.location	= ENVL_ONENAND, | ||||||
|  | 	ENV_NAME("OneNAND") | ||||||
| 	.load		= env_onenand_load, | 	.load		= env_onenand_load, | ||||||
| 	.save		= env_save_ptr(env_onenand_save), | 	.save		= env_save_ptr(env_onenand_save), | ||||||
| }; | }; | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								env/remote.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								env/remote.c
									
									
									
									
										vendored
									
									
								
							| @@ -11,8 +11,6 @@ | |||||||
| #include <environment.h> | #include <environment.h> | ||||||
| #include <linux/stddef.h> | #include <linux/stddef.h> | ||||||
|  |  | ||||||
| char *env_name_spec = "Remote"; |  | ||||||
|  |  | ||||||
| #ifdef ENV_IS_EMBEDDED | #ifdef ENV_IS_EMBEDDED | ||||||
| env_t *env_ptr = &environment; | env_t *env_ptr = &environment; | ||||||
| #else /* ! ENV_IS_EMBEDDED */ | #else /* ! ENV_IS_EMBEDDED */ | ||||||
| @@ -57,6 +55,7 @@ static void env_remote_load(void) | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(remote) = { | U_BOOT_ENV_LOCATION(remote) = { | ||||||
| 	.location	= ENVL_REMOTE, | 	.location	= ENVL_REMOTE, | ||||||
|  | 	ENV_NAME("Remote") | ||||||
| 	.load		= env_remote_load, | 	.load		= env_remote_load, | ||||||
| 	.save		= env_save_ptr(env_remote_save), | 	.save		= env_save_ptr(env_remote_save), | ||||||
| 	.init		= env_remote_init, | 	.init		= env_remote_init, | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								env/sata.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								env/sata.c
									
									
									
									
										vendored
									
									
								
							| @@ -24,8 +24,6 @@ | |||||||
| #error CONFIG_ENV_OFFSET or CONFIG_ENV_SIZE not defined | #error CONFIG_ENV_OFFSET or CONFIG_ENV_SIZE not defined | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| char *env_name_spec = "SATA"; |  | ||||||
|  |  | ||||||
| DECLARE_GLOBAL_DATA_PTR; | DECLARE_GLOBAL_DATA_PTR; | ||||||
|  |  | ||||||
| __weak int sata_get_env_dev(void) | __weak int sata_get_env_dev(void) | ||||||
| @@ -119,6 +117,7 @@ static void env_sata_load(void) | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(sata) = { | U_BOOT_ENV_LOCATION(sata) = { | ||||||
| 	.location	= ENVL_ESATA, | 	.location	= ENVL_ESATA, | ||||||
|  | 	ENV_NAME("SATA") | ||||||
| 	.load		= env_sata_load, | 	.load		= env_sata_load, | ||||||
| 	.save		= env_save_ptr(env_sata_save), | 	.save		= env_save_ptr(env_sata_save), | ||||||
| }; | }; | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								env/sf.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								env/sf.c
									
									
									
									
										vendored
									
									
								
							| @@ -48,8 +48,6 @@ static ulong env_new_offset	= CONFIG_ENV_OFFSET_REDUND; | |||||||
|  |  | ||||||
| DECLARE_GLOBAL_DATA_PTR; | DECLARE_GLOBAL_DATA_PTR; | ||||||
|  |  | ||||||
| char *env_name_spec = "SPI Flash"; |  | ||||||
|  |  | ||||||
| static struct spi_flash *env_flash; | static struct spi_flash *env_flash; | ||||||
|  |  | ||||||
| static int setup_flash_device(void) | static int setup_flash_device(void) | ||||||
| @@ -346,6 +344,7 @@ out: | |||||||
|  |  | ||||||
| U_BOOT_ENV_LOCATION(sf) = { | U_BOOT_ENV_LOCATION(sf) = { | ||||||
| 	.location	= ENVL_SPI_FLASH, | 	.location	= ENVL_SPI_FLASH, | ||||||
|  | 	ENV_NAME("SPI Flash") | ||||||
| 	.load		= env_sf_load, | 	.load		= env_sf_load, | ||||||
| #ifdef CMD_SAVEENV | #ifdef CMD_SAVEENV | ||||||
| 	.save		= env_save_ptr(env_sf_save), | 	.save		= env_save_ptr(env_sf_save), | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								env/ubi.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								env/ubi.c
									
									
									
									
										vendored
									
									
								
							| @@ -16,8 +16,6 @@ | |||||||
| #include <ubi_uboot.h> | #include <ubi_uboot.h> | ||||||
| #undef crc32 | #undef crc32 | ||||||
|  |  | ||||||
| char *env_name_spec = "UBI"; |  | ||||||
|  |  | ||||||
| env_t *env_ptr; | env_t *env_ptr; | ||||||
|  |  | ||||||
| DECLARE_GLOBAL_DATA_PTR; | DECLARE_GLOBAL_DATA_PTR; | ||||||
|   | |||||||
| @@ -143,10 +143,6 @@ extern unsigned long nand_env_oob_offset; | |||||||
| # define ENV_HEADER_SIZE	(sizeof(uint32_t)) | # define ENV_HEADER_SIZE	(sizeof(uint32_t)) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE) |  | ||||||
| extern char *env_name_spec; |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #ifdef CONFIG_ENV_AES | #ifdef CONFIG_ENV_AES | ||||||
| /* Make sure the payload is multiple of AES block size */ | /* Make sure the payload is multiple of AES block size */ | ||||||
| #define ENV_SIZE ((CONFIG_ENV_SIZE - ENV_HEADER_SIZE) & ~(16 - 1)) | #define ENV_SIZE ((CONFIG_ENV_SIZE - ENV_HEADER_SIZE) & ~(16 - 1)) | ||||||
| @@ -224,6 +220,7 @@ enum env_location { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| struct env_driver { | struct env_driver { | ||||||
|  | 	const char *name; | ||||||
| 	enum env_location location; | 	enum env_location location; | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -269,6 +266,13 @@ struct env_driver { | |||||||
| #define U_BOOT_ENV_LOCATION(__name)					\ | #define U_BOOT_ENV_LOCATION(__name)					\ | ||||||
| 	ll_entry_declare(struct env_driver, __name, env_driver) | 	ll_entry_declare(struct env_driver, __name, env_driver) | ||||||
|  |  | ||||||
|  | /* Declare the name of a location */ | ||||||
|  | #ifdef CONFIG_CMD_SAVEENV | ||||||
|  | #define ENV_NAME(_name) .name = _name, | ||||||
|  | #else | ||||||
|  | #define ENV_NAME(_name) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #ifdef CONFIG_CMD_SAVEENV | #ifdef CONFIG_CMD_SAVEENV | ||||||
| #define env_save_ptr(x) x | #define env_save_ptr(x) x | ||||||
| #else | #else | ||||||
| @@ -303,6 +307,13 @@ int env_export(env_t *env_out); | |||||||
| int env_import_redund(const char *buf1, const char *buf2); | int env_import_redund(const char *buf1, const char *buf2); | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * env_driver_lookup_default() - Look up the default environment driver | ||||||
|  |  * | ||||||
|  |  * @return pointer to driver, or NULL if none (which should not happen) | ||||||
|  |  */ | ||||||
|  | struct env_driver *env_driver_lookup_default(void); | ||||||
|  |  | ||||||
| #endif /* DO_DEPS_ONLY */ | #endif /* DO_DEPS_ONLY */ | ||||||
|  |  | ||||||
| #endif /* _ENVIRONMENT_H_ */ | #endif /* _ENVIRONMENT_H_ */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user