xref: /openbmc/u-boot/env/sata.c (revision 43a6a1ec9055a53a11d6d735f11cceea13912bbe)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
20649cd0dSSimon Glass /*
30649cd0dSSimon Glass  * (C) Copyright 2010-2016 Freescale Semiconductor, Inc.
40649cd0dSSimon Glass  */
50649cd0dSSimon Glass 
60649cd0dSSimon Glass /* #define DEBUG */
70649cd0dSSimon Glass 
80649cd0dSSimon Glass #include <common.h>
90649cd0dSSimon Glass 
100649cd0dSSimon Glass #include <command.h>
110649cd0dSSimon Glass #include <environment.h>
120649cd0dSSimon Glass #include <linux/stddef.h>
130649cd0dSSimon Glass #include <errno.h>
140649cd0dSSimon Glass #include <memalign.h>
150649cd0dSSimon Glass #include <sata.h>
160649cd0dSSimon Glass #include <search.h>
170649cd0dSSimon Glass 
180649cd0dSSimon Glass #if defined(CONFIG_ENV_SIZE_REDUND) || defined(CONFIG_ENV_OFFSET_REDUND)
190649cd0dSSimon Glass #error ENV REDUND not supported
200649cd0dSSimon Glass #endif
210649cd0dSSimon Glass 
220649cd0dSSimon Glass #if !defined(CONFIG_ENV_OFFSET) || !defined(CONFIG_ENV_SIZE)
230649cd0dSSimon Glass #error CONFIG_ENV_OFFSET or CONFIG_ENV_SIZE not defined
240649cd0dSSimon Glass #endif
250649cd0dSSimon Glass 
sata_get_env_dev(void)260649cd0dSSimon Glass __weak int sata_get_env_dev(void)
270649cd0dSSimon Glass {
280649cd0dSSimon Glass 	return CONFIG_SYS_SATA_ENV_DEV;
290649cd0dSSimon Glass }
300649cd0dSSimon Glass 
310649cd0dSSimon Glass #ifdef CONFIG_CMD_SAVEENV
write_env(struct blk_desc * sata,unsigned long size,unsigned long offset,void * buffer)320649cd0dSSimon Glass static inline int write_env(struct blk_desc *sata, unsigned long size,
330649cd0dSSimon Glass 			    unsigned long offset, void *buffer)
340649cd0dSSimon Glass {
350649cd0dSSimon Glass 	uint blk_start, blk_cnt, n;
360649cd0dSSimon Glass 
370649cd0dSSimon Glass 	blk_start = ALIGN(offset, sata->blksz) / sata->blksz;
380649cd0dSSimon Glass 	blk_cnt   = ALIGN(size, sata->blksz) / sata->blksz;
390649cd0dSSimon Glass 
400649cd0dSSimon Glass 	n = blk_dwrite(sata, blk_start, blk_cnt, buffer);
410649cd0dSSimon Glass 
420649cd0dSSimon Glass 	return (n == blk_cnt) ? 0 : -1;
430649cd0dSSimon Glass }
440649cd0dSSimon Glass 
env_sata_save(void)45e5bce247SSimon Glass static int env_sata_save(void)
460649cd0dSSimon Glass {
470649cd0dSSimon Glass 	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
480649cd0dSSimon Glass 	struct blk_desc *sata = NULL;
490649cd0dSSimon Glass 	int env_sata, ret;
500649cd0dSSimon Glass 
510649cd0dSSimon Glass 	if (sata_initialize())
520649cd0dSSimon Glass 		return 1;
530649cd0dSSimon Glass 
540649cd0dSSimon Glass 	env_sata = sata_get_env_dev();
550649cd0dSSimon Glass 
560649cd0dSSimon Glass 	sata = sata_get_dev(env_sata);
570649cd0dSSimon Glass 	if (sata == NULL) {
580649cd0dSSimon Glass 		printf("Unknown SATA(%d) device for environment!\n",
590649cd0dSSimon Glass 		       env_sata);
600649cd0dSSimon Glass 		return 1;
610649cd0dSSimon Glass 	}
620649cd0dSSimon Glass 
630649cd0dSSimon Glass 	ret = env_export(env_new);
640649cd0dSSimon Glass 	if (ret)
650649cd0dSSimon Glass 		return 1;
660649cd0dSSimon Glass 
670649cd0dSSimon Glass 	printf("Writing to SATA(%d)...", env_sata);
68*17be909aSYe Li 	if (write_env(sata, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, (u_char *)env_new)) {
690649cd0dSSimon Glass 		puts("failed\n");
700649cd0dSSimon Glass 		return 1;
710649cd0dSSimon Glass 	}
720649cd0dSSimon Glass 
730649cd0dSSimon Glass 	puts("done\n");
740649cd0dSSimon Glass 	return 0;
750649cd0dSSimon Glass }
760649cd0dSSimon Glass #endif /* CONFIG_CMD_SAVEENV */
770649cd0dSSimon Glass 
read_env(struct blk_desc * sata,unsigned long size,unsigned long offset,void * buffer)780649cd0dSSimon Glass static inline int read_env(struct blk_desc *sata, unsigned long size,
790649cd0dSSimon Glass 			   unsigned long offset, void *buffer)
800649cd0dSSimon Glass {
810649cd0dSSimon Glass 	uint blk_start, blk_cnt, n;
820649cd0dSSimon Glass 
830649cd0dSSimon Glass 	blk_start = ALIGN(offset, sata->blksz) / sata->blksz;
840649cd0dSSimon Glass 	blk_cnt   = ALIGN(size, sata->blksz) / sata->blksz;
850649cd0dSSimon Glass 
860649cd0dSSimon Glass 	n = blk_dread(sata, blk_start, blk_cnt, buffer);
870649cd0dSSimon Glass 
880649cd0dSSimon Glass 	return (n == blk_cnt) ? 0 : -1;
890649cd0dSSimon Glass }
900649cd0dSSimon Glass 
env_sata_load(void)91e5bce247SSimon Glass static void env_sata_load(void)
920649cd0dSSimon Glass {
930649cd0dSSimon Glass 	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
940649cd0dSSimon Glass 	struct blk_desc *sata = NULL;
950649cd0dSSimon Glass 	int env_sata;
960649cd0dSSimon Glass 
970649cd0dSSimon Glass 	if (sata_initialize())
98c5951991SSimon Glass 		return -EIO;
990649cd0dSSimon Glass 
1000649cd0dSSimon Glass 	env_sata = sata_get_env_dev();
1010649cd0dSSimon Glass 
1020649cd0dSSimon Glass 	sata = sata_get_dev(env_sata);
1030649cd0dSSimon Glass 	if (sata == NULL) {
104c5951991SSimon Glass 		printf("Unknown SATA(%d) device for environment!\n", env_sata);
105c5951991SSimon Glass 		return -EIO;
1060649cd0dSSimon Glass 	}
1070649cd0dSSimon Glass 
108c5951991SSimon Glass 	if (read_env(sata, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, buf)) {
109c5d548a9SYaniv Levinsky 		set_default_env(NULL, 0);
110c5951991SSimon Glass 		return -EIO;
111c5951991SSimon Glass 	}
1120649cd0dSSimon Glass 
1132166ebf7SSimon Goldschmidt 	return env_import(buf, 1);
1140649cd0dSSimon Glass }
1154415f1d1SSimon Glass 
1164415f1d1SSimon Glass U_BOOT_ENV_LOCATION(sata) = {
1174415f1d1SSimon Glass 	.location	= ENVL_ESATA,
118ac358bebSSimon Glass 	ENV_NAME("SATA")
119e5bce247SSimon Glass 	.load		= env_sata_load,
120e5bce247SSimon Glass 	.save		= env_save_ptr(env_sata_save),
1214415f1d1SSimon Glass };
122