1 /* 2 * (C) Copyright 2000-2010 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> 6 * Andreas Heppel <aheppel@sysgo.de> 7 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11 #include <common.h> 12 #include <command.h> 13 #include <environment.h> 14 #include <linux/stddef.h> 15 #include <boot_rkimg.h> 16 #include <memalign.h> 17 18 DECLARE_GLOBAL_DATA_PTR; 19 20 #ifdef CONFIG_ENVF 21 /* 22 * example: ./tools/mkenvimage -s 0x8000 -p 0x0 -o envf.bin envf.txt 23 * 24 * - 0x8000: the value of CONFIG_ENV_SIZE. 25 * - env.txt: input file 26 */ 27 #define ENVF_MAX_ENTRY 64 28 #define ENVF_PART "envf" 29 #define ENVF_EMSG "error: please use \"bootargs_envf\" but not " \ 30 "\"bootargs\" in CONFIG_ENVF_LIST and envf.bin" 31 static char *envf_entry[ENVF_MAX_ENTRY]; 32 static u32 envf_num; 33 34 static int envf_extract_list(void) 35 { 36 char *tok, *p; 37 u32 i = 0; 38 39 tok = strdup(CONFIG_ENVF_LIST); 40 if (!tok) 41 return -ENOMEM; 42 43 p = strtok(tok, " "); 44 while (p && i < ENVF_MAX_ENTRY) { 45 if (!strcmp(p, "bootargs")) { 46 printf("%s\n", ENVF_EMSG); 47 run_command("download", 0); 48 } 49 envf_entry[i++] = p; 50 p = strtok(NULL, " "); 51 } 52 53 envf_num = i; 54 55 return 0; 56 } 57 58 /* allow failure, not stop boot */ 59 static int envf_load(void) 60 { 61 struct blk_desc *dev_desc; 62 disk_partition_t part; 63 env_t *envf; 64 u32 blk_cnt; 65 int ret = 0; 66 67 printf("ENVF: "); 68 69 dev_desc = rockchip_get_bootdev(); 70 if (!dev_desc) { 71 printf("dev_desc null!\n"); 72 return 0; 73 } 74 75 if (part_get_info_by_name(dev_desc, ENVF_PART, &part) < 0) { 76 printf("no %s partition\n", ENVF_PART); 77 return 0; 78 } 79 80 blk_cnt = DIV_ROUND_UP(ENV_SIZE, part.blksz); 81 envf = memalign(ARCH_DMA_MINALIGN, blk_cnt * part.blksz); 82 if (!envf) { 83 printf("no memory\n"); 84 return 0; 85 } 86 87 if (blk_dread(dev_desc, part.start, blk_cnt, (void *)envf) != blk_cnt) { 88 printf("io error\n"); 89 ret = -EIO; 90 goto out; 91 } 92 93 if (crc32(0, envf->data, ENV_SIZE) != envf->crc) { 94 printf("!bad CRC\n"); 95 ret = -EINVAL; 96 goto out; 97 } 98 99 envf_extract_list(); 100 101 if (!himport_r(&env_htab, (char *)envf->data, ENV_SIZE, '\0', 102 H_NOCLEAR, 0, envf_num, envf_entry)) 103 printf("himport error\n"); 104 105 printf("OK\n"); 106 107 out: 108 if (envf) 109 free(envf); 110 111 return ret; 112 } 113 114 static int envf_save(void) 115 { 116 ALLOC_CACHE_ALIGN_BUFFER(env_t, envf, 1); 117 struct blk_desc *dev_desc; 118 disk_partition_t part; 119 u32 blk_cnt; 120 ssize_t len; 121 char *res; 122 123 dev_desc = rockchip_get_bootdev(); 124 if (!dev_desc) { 125 printf("dev_desc null!\n"); 126 return -EINVAL; 127 } 128 129 if (part_get_info_by_name(dev_desc, ENVF_PART, &part) < 0) { 130 printf("envf: no partition\n"); 131 return -ENODEV; 132 } 133 134 blk_cnt = DIV_ROUND_UP(ENV_SIZE, part.blksz); 135 res = (char *)envf->data; 136 len = hexport_r(&env_htab, '\0', H_MATCH_KEY | H_MATCH_IDENT, 137 &res, ENV_SIZE, envf_num, envf_entry); 138 if (len < 0) { 139 printf("envf: hexpor errno: %d\n", errno); 140 return -EINVAL; 141 } 142 143 envf->crc = crc32(0, envf->data, ENV_SIZE); 144 if (blk_dwrite(dev_desc, part.start, blk_cnt, (char *)envf) != blk_cnt) { 145 printf("envf: io error\n"); 146 return -EIO; 147 } 148 149 return 0; 150 } 151 #endif 152 153 /* 154 * Because we only ever have the default environment available we must mark 155 * it as invalid. 156 */ 157 static int env_nowhere_init(void) 158 { 159 gd->env_addr = (ulong)&default_environment[0]; 160 gd->env_valid = ENV_INVALID; 161 162 return 0; 163 } 164 165 U_BOOT_ENV_LOCATION(nowhere) = { 166 .location = ENVL_NOWHERE, 167 .init = env_nowhere_init, 168 #ifdef CONFIG_ENVF 169 .load = envf_load, 170 .save = env_save_ptr(envf_save), 171 ENV_NAME("envf") 172 #else 173 ENV_NAME("nowhere") 174 #endif 175 }; 176