1 /* 2 * (C) Copyright 2010-2016 Freescale Semiconductor, Inc. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 /* #define DEBUG */ 8 9 #include <common.h> 10 11 #include <command.h> 12 #include <environment.h> 13 #include <linux/stddef.h> 14 #include <errno.h> 15 #include <memalign.h> 16 #include <sata.h> 17 #include <search.h> 18 19 #if defined(CONFIG_ENV_SIZE_REDUND) || defined(CONFIG_ENV_OFFSET_REDUND) 20 #error ENV REDUND not supported 21 #endif 22 23 #if !defined(CONFIG_ENV_OFFSET) || !defined(CONFIG_ENV_SIZE) 24 #error CONFIG_ENV_OFFSET or CONFIG_ENV_SIZE not defined 25 #endif 26 27 char *env_name_spec = "SATA"; 28 29 DECLARE_GLOBAL_DATA_PTR; 30 31 __weak int sata_get_env_dev(void) 32 { 33 return CONFIG_SYS_SATA_ENV_DEV; 34 } 35 36 int env_init(void) 37 { 38 /* use default */ 39 gd->env_addr = (ulong)&default_environment[0]; 40 gd->env_valid = ENV_VALID; 41 42 return 0; 43 } 44 45 #ifdef CONFIG_CMD_SAVEENV 46 static inline int write_env(struct blk_desc *sata, unsigned long size, 47 unsigned long offset, void *buffer) 48 { 49 uint blk_start, blk_cnt, n; 50 51 blk_start = ALIGN(offset, sata->blksz) / sata->blksz; 52 blk_cnt = ALIGN(size, sata->blksz) / sata->blksz; 53 54 n = blk_dwrite(sata, blk_start, blk_cnt, buffer); 55 56 return (n == blk_cnt) ? 0 : -1; 57 } 58 59 int saveenv(void) 60 { 61 ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); 62 struct blk_desc *sata = NULL; 63 int env_sata, ret; 64 65 if (sata_initialize()) 66 return 1; 67 68 env_sata = sata_get_env_dev(); 69 70 sata = sata_get_dev(env_sata); 71 if (sata == NULL) { 72 printf("Unknown SATA(%d) device for environment!\n", 73 env_sata); 74 return 1; 75 } 76 77 ret = env_export(env_new); 78 if (ret) 79 return 1; 80 81 printf("Writing to SATA(%d)...", env_sata); 82 if (write_env(sata, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, &env_new)) { 83 puts("failed\n"); 84 return 1; 85 } 86 87 puts("done\n"); 88 return 0; 89 } 90 #endif /* CONFIG_CMD_SAVEENV */ 91 92 static inline int read_env(struct blk_desc *sata, unsigned long size, 93 unsigned long offset, void *buffer) 94 { 95 uint blk_start, blk_cnt, n; 96 97 blk_start = ALIGN(offset, sata->blksz) / sata->blksz; 98 blk_cnt = ALIGN(size, sata->blksz) / sata->blksz; 99 100 n = blk_dread(sata, blk_start, blk_cnt, buffer); 101 102 return (n == blk_cnt) ? 0 : -1; 103 } 104 105 void env_relocate_spec(void) 106 { 107 ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); 108 struct blk_desc *sata = NULL; 109 int env_sata; 110 111 if (sata_initialize()) 112 return; 113 114 env_sata = sata_get_env_dev(); 115 116 sata = sata_get_dev(env_sata); 117 if (sata == NULL) { 118 printf("Unknown SATA(%d) device for environment!\n", 119 env_sata); 120 return; 121 } 122 123 if (read_env(sata, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, buf)) 124 return set_default_env(NULL); 125 126 env_import(buf, 1); 127 } 128