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