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 __weak int sata_get_env_dev(void) 28 { 29 return CONFIG_SYS_SATA_ENV_DEV; 30 } 31 32 #ifdef CONFIG_CMD_SAVEENV 33 static inline int write_env(struct blk_desc *sata, unsigned long size, 34 unsigned long offset, void *buffer) 35 { 36 uint blk_start, blk_cnt, n; 37 38 blk_start = ALIGN(offset, sata->blksz) / sata->blksz; 39 blk_cnt = ALIGN(size, sata->blksz) / sata->blksz; 40 41 n = blk_dwrite(sata, blk_start, blk_cnt, buffer); 42 43 return (n == blk_cnt) ? 0 : -1; 44 } 45 46 static int env_sata_save(void) 47 { 48 ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1); 49 struct blk_desc *sata = NULL; 50 int env_sata, ret; 51 52 if (sata_initialize()) 53 return 1; 54 55 env_sata = sata_get_env_dev(); 56 57 sata = sata_get_dev(env_sata); 58 if (sata == NULL) { 59 printf("Unknown SATA(%d) device for environment!\n", 60 env_sata); 61 return 1; 62 } 63 64 ret = env_export(env_new); 65 if (ret) 66 return 1; 67 68 printf("Writing to SATA(%d)...", env_sata); 69 if (write_env(sata, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, &env_new)) { 70 puts("failed\n"); 71 return 1; 72 } 73 74 puts("done\n"); 75 return 0; 76 } 77 #endif /* CONFIG_CMD_SAVEENV */ 78 79 static inline int read_env(struct blk_desc *sata, unsigned long size, 80 unsigned long offset, void *buffer) 81 { 82 uint blk_start, blk_cnt, n; 83 84 blk_start = ALIGN(offset, sata->blksz) / sata->blksz; 85 blk_cnt = ALIGN(size, sata->blksz) / sata->blksz; 86 87 n = blk_dread(sata, blk_start, blk_cnt, buffer); 88 89 return (n == blk_cnt) ? 0 : -1; 90 } 91 92 static void env_sata_load(void) 93 { 94 ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); 95 struct blk_desc *sata = NULL; 96 int env_sata; 97 98 if (sata_initialize()) 99 return -EIO; 100 101 env_sata = sata_get_env_dev(); 102 103 sata = sata_get_dev(env_sata); 104 if (sata == NULL) { 105 printf("Unknown SATA(%d) device for environment!\n", env_sata); 106 return -EIO; 107 } 108 109 if (read_env(sata, CONFIG_ENV_SIZE, CONFIG_ENV_OFFSET, buf)) { 110 set_default_env(NULL); 111 return -EIO; 112 } 113 114 return env_import(buf, 1); 115 } 116 117 U_BOOT_ENV_LOCATION(sata) = { 118 .location = ENVL_ESATA, 119 ENV_NAME("SATA") 120 .load = env_sata_load, 121 .save = env_save_ptr(env_sata_save), 122 }; 123