Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 1 | // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| 2 | /* |
| 3 | * Copyright (c) 2019 Amlogic, Inc. All rights reserved. |
| 4 | */ |
| 5 | |
| 6 | #include <config.h> |
| 7 | #include <common.h> |
| 8 | #include <command.h> |
| 9 | #include <env.h> |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 10 | #include <env_internal.h> |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 11 | #include <cli.h> |
| 12 | #include <errno.h> |
| 13 | #include <malloc.h> |
| 14 | #include <linux/stddef.h> |
Sam Wu | 083c485 | 2023-04-25 19:37:54 +0800 | [diff] [blame] | 15 | #include <u-boot/crc.h> |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 16 | #include <asm/byteorder.h> |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 17 | #include <amlogic/store_wrapper.h> |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 18 | |
| 19 | static const char* const temp_for_compile[] = {"__test1","__test2","__test3",NULL}; |
| 20 | extern const char * const _env_args_reserve_[0] __attribute__((weak, alias("temp_for_compile"))); |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 21 | extern const char * const _aml_env_reserv_array[0] __attribute__((weak, alias("temp_for_compile"))); |
yihui wu | 648297d | 2024-12-18 01:14:14 +0800 | [diff] [blame] | 22 | extern const char * const _aml_env_reserv_array1[0] __attribute__((weak, alias("temp_for_compile"))); |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 23 | extern const char * const _board_env_reserv_array0[0] __attribute__((weak, alias("temp_for_compile"))); |
| 24 | extern const char * const _board_env_reserv_array1[0] __attribute__((weak, alias("temp_for_compile"))); |
| 25 | extern const char * const _board_env_reserv_array2[0] __attribute__((weak, alias("temp_for_compile"))); |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 26 | |
| 27 | #define debugP(fmt...) //printf("dbg[ENV]" fmt) |
| 28 | #define errorP(fmt...) do {printf("ERR[ENV]L%d:", __LINE__); printf(fmt); } while (0) |
| 29 | #define wrnP(fmt...) printf("WRN[ENV]" fmt) |
| 30 | #define MsgP(fmt...) printf("MSG[ENV]" fmt) |
| 31 | |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 32 | enum DEF_ENV_RESERV_ARRAY { |
| 33 | BIT_ENV_RESERV_ARRAY_AML_COMMON, //-c, common aml env array_aml_env_reserv_array |
yihui wu | 648297d | 2024-12-18 01:14:14 +0800 | [diff] [blame] | 34 | BIT_ENV_RESERV_ARRAY_AML_COMMON1, //-c, common aml env array_aml_env_reserv_array |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 35 | BIT_ENV_RESERV_ARRAY_USER_INPUT, //input env1/env2/env3... |
| 36 | BIT_ENV_RESERV_ARRAY_BOARD_DEFINE0, //-b0, board env array _board_env_reserv_array0 |
| 37 | BIT_ENV_RESERV_ARRAY_BOARD_DEFINE1, //-b1, board env array _board_env_reserv_array1 |
| 38 | BIT_ENV_RESERV_ARRAY_BOARD_DEFINE2, //-b2, board env array _board_env_reserv_array2 |
| 39 | |
| 40 | DEF_ENV_RESERV_ARRAY_COUNT, |
| 41 | }; |
| 42 | |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 43 | static int _reserve_env_list_after_defenv(const int reservNum, const char* const reservNameList[]) |
| 44 | { |
| 45 | int ret = 0; |
| 46 | int index = 0; |
| 47 | unsigned sumOfEnvVal = 0;//sum of strlen(getenv(env_i)) |
| 48 | const int MaxReservNum = CONFIG_SYS_MAXARGS - 1; |
| 49 | const char* valListBuf[MaxReservNum];//store at most 64 envs |
| 50 | char* tmpEnvBuf = NULL; |
| 51 | |
| 52 | if (reservNum > MaxReservNum) { |
| 53 | errorP("max reserved env list num %d < wanted %d\n", MaxReservNum, reservNum); |
| 54 | return __LINE__; |
| 55 | } |
| 56 | //1, cal the total buf size needed to save the envs |
| 57 | for (index = 0; index < reservNum; ++index) |
| 58 | { |
| 59 | const char* cfgEnvKey = reservNameList[index]; |
| 60 | const char* cfgEnvVal = env_get(cfgEnvKey); |
| 61 | |
| 62 | if (cfgEnvVal) { |
| 63 | sumOfEnvVal += strlen(cfgEnvVal) + 1; |
| 64 | } |
| 65 | valListBuf[index] = cfgEnvVal; |
| 66 | } |
| 67 | |
| 68 | //2, transfer the env values to buffer |
| 69 | if (sumOfEnvVal) |
| 70 | { |
| 71 | tmpEnvBuf = (char*)malloc(sumOfEnvVal); |
| 72 | if (!tmpEnvBuf) { |
| 73 | errorP("Fail in malloc(%d)\n", sumOfEnvVal); |
| 74 | return __LINE__; |
| 75 | } |
| 76 | memset(tmpEnvBuf, 0, sumOfEnvVal); |
| 77 | |
| 78 | char* tmpbuf = tmpEnvBuf; |
| 79 | for (index = 0; index < reservNum; ++index ) |
| 80 | { |
| 81 | const char* valBeforeDef = valListBuf[index]; |
| 82 | |
| 83 | if (!valBeforeDef) continue; |
| 84 | |
| 85 | const unsigned thisValLen = strlen(valBeforeDef) + 1; |
| 86 | memcpy(tmpbuf, valBeforeDef, thisValLen); |
| 87 | valListBuf[index] = tmpbuf; |
| 88 | tmpbuf += thisValLen ; |
| 89 | debugP("tmpEnvBuf=%p, tmpbuf=%p, thisValLen=%d\n", tmpEnvBuf, tmpbuf, thisValLen); |
| 90 | debugP("cp:k[%s]%s-->%s\n", reservNameList[index], valBeforeDef, tmpEnvBuf); |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | env_set_default("## defenv_reserve ##", 0); |
| 95 | |
| 96 | if (sumOfEnvVal) |
| 97 | { |
| 98 | for (index = 0; index < reservNum; ++index) |
| 99 | { |
| 100 | const char* cfgEnvKey = reservNameList[index]; |
| 101 | const char* valAftDef = valListBuf[index]; |
| 102 | |
| 103 | if (valAftDef) |
| 104 | { |
| 105 | env_set(cfgEnvKey, valAftDef); |
| 106 | debugP("set[%s=%s]\n", cfgEnvKey, valAftDef); |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | if (tmpEnvBuf) free(tmpEnvBuf) ; |
| 112 | return ret; |
| 113 | } |
| 114 | |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 115 | static int _do_defenv_reserv(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 116 | { |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 117 | int envListNum = argc - 1; |
| 118 | const char **envListArr = (const char **)(argv + 1); |
| 119 | unsigned int rsv_flags = 0; |
| 120 | const int MAX_RSV_NUM = CONFIG_SYS_MAXARGS - 1; |
| 121 | const char *rsv_env_list[MAX_RSV_NUM];//store at most 64 envs |
| 122 | int rsv_env_num = 0; |
| 123 | int ret = 0, i = 0, k = 0; |
| 124 | const char *tmp = NULL; |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 125 | |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 126 | if (!envListNum) { |
| 127 | envListArr = (const char **)_env_args_reserve_; |
| 128 | const char **pArr = (const char **)envListArr; |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 129 | |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 130 | while (*pArr++) |
| 131 | ++envListNum; |
| 132 | } else if (*argv[1] == '-') { |
| 133 | char *arg = NULL; |
| 134 | const char * const*_aml_env_reserv_[DEF_ENV_RESERV_ARRAY_COUNT]; |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 135 | |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 136 | _aml_env_reserv_[BIT_ENV_RESERV_ARRAY_AML_COMMON] = _aml_env_reserv_array; |
yihui wu | 648297d | 2024-12-18 01:14:14 +0800 | [diff] [blame] | 137 | _aml_env_reserv_[BIT_ENV_RESERV_ARRAY_AML_COMMON1] = _aml_env_reserv_array1; |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 138 | _aml_env_reserv_[BIT_ENV_RESERV_ARRAY_USER_INPUT] = temp_for_compile; |
| 139 | _aml_env_reserv_[BIT_ENV_RESERV_ARRAY_BOARD_DEFINE0] = _board_env_reserv_array0; |
| 140 | _aml_env_reserv_[BIT_ENV_RESERV_ARRAY_BOARD_DEFINE1] = _board_env_reserv_array1; |
| 141 | _aml_env_reserv_[BIT_ENV_RESERV_ARRAY_BOARD_DEFINE2] = _board_env_reserv_array2; |
| 142 | debugP("argc %d\n", argc); |
| 143 | while (argc > 1 && **(argv + 1) == '-') { |
| 144 | arg = *++argv; |
| 145 | --argc; |
yihui wu | 648297d | 2024-12-18 01:14:14 +0800 | [diff] [blame] | 146 | if (*++arg) { |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 147 | switch (*arg) { |
| 148 | case 'b':{//board env |
| 149 | const int bd = *++arg - '0'; |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 150 | |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 151 | if (bd > 2 || bd < 0) { |
| 152 | errorP("Invalid option -%s\n", arg - 1); |
| 153 | return CMD_RET_USAGE; |
| 154 | } |
| 155 | debugP("board reserv _board_env_reserv_array%d\n", bd); |
| 156 | rsv_flags |= 1 << (BIT_ENV_RESERV_ARRAY_BOARD_DEFINE0 + bd); |
| 157 | } break; |
yihui wu | 648297d | 2024-12-18 01:14:14 +0800 | [diff] [blame] | 158 | case 'c': {//common env |
| 159 | int icmn = arg[1]; |
| 160 | |
| 161 | if (icmn > '0') { |
| 162 | errorP("invalid cmn para %s\n", arg); |
| 163 | return CMD_RET_FAILURE; |
| 164 | } |
| 165 | if (icmn) |
| 166 | icmn = 1; |
| 167 | MsgP("common reserv para: %s\n", arg); |
| 168 | rsv_flags |= 1 << (BIT_ENV_RESERV_ARRAY_AML_COMMON + icmn); |
| 169 | } break; |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 170 | default: |
| 171 | errorP("Invalid para -%s\n", arg); |
| 172 | return CMD_RET_USAGE; |
| 173 | } |
| 174 | } |
| 175 | } |
| 176 | MsgP("argc %d, rsv_flags 0x%x\n", argc, rsv_flags); |
| 177 | if (argc > 1) { |
| 178 | MsgP("rsv usr env: "); |
| 179 | for (i = 1; i < argc; ++i) { |
| 180 | printf("%s, ", argv[i]); |
| 181 | rsv_env_list[i - 1] = argv[i]; |
| 182 | } |
| 183 | rsv_env_num = argc - 1; |
| 184 | printf("\n"); |
| 185 | } |
| 186 | for (i = 0; i < DEF_ENV_RESERV_ARRAY_COUNT; ++i) { |
| 187 | if (!(rsv_flags & (1 << i))) |
| 188 | continue; |
| 189 | debugP("rsv %d\n", i); |
| 190 | envListArr = (const char **)_aml_env_reserv_[i]; |
| 191 | for (k = 0, tmp = envListArr[k]; tmp && *tmp; tmp = envListArr[++k]) { |
| 192 | debugP("rsv[%d][%d] = %s\n", i, k, tmp); |
| 193 | if (rsv_env_num >= MAX_RSV_NUM) { |
| 194 | errorP("too long rsv num %d, max %d\n", |
| 195 | rsv_env_num, MAX_RSV_NUM - 1); |
| 196 | return CMD_RET_FAILURE; |
| 197 | } |
| 198 | rsv_env_list[rsv_env_num++] = tmp; |
| 199 | } |
| 200 | } |
| 201 | debugP("rsv_env_num %d\n", rsv_env_num); |
| 202 | rsv_env_list[rsv_env_num] = NULL; |
| 203 | envListNum = rsv_env_num; |
| 204 | envListArr = rsv_env_list; |
| 205 | } |
| 206 | |
| 207 | ret = _reserve_env_list_after_defenv(envListNum, envListArr); |
| 208 | return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS; |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 209 | } |
| 210 | |
Sam Wu | a93fc39 | 2024-01-03 16:58:46 +0800 | [diff] [blame] | 211 | U_BOOT_CMD(_aml_defenv_reserve, //command name |
| 212 | CONFIG_SYS_MAXARGS, //maxargs |
| 213 | 0, //repeatable |
| 214 | _do_defenv_reserv, //command function |
| 215 | "reserve some specified envs after defaulting env", //description |
| 216 | " see help defenv_reserve for usage\n" //usage |
| 217 | ); |
| 218 | |
| 219 | static int do_defenv_reserv(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| 220 | { |
| 221 | if (argc > 1) |
| 222 | return _do_defenv_reserv(cmdtp, flag, argc, argv); |
| 223 | //no para |
| 224 | return run_command("echo defenv_para $defenv_para;" |
| 225 | "_aml_defenv_reserve ${defenv_para}", flag); |
| 226 | } |
| 227 | |
| 228 | U_BOOT_CMD_COMPLETE(defenv_reserve, //command name |
| 229 | CONFIG_SYS_MAXARGS, //maxargs |
| 230 | 0, //repeatable |
| 231 | do_defenv_reserv, //command function |
| 232 | "reserve some specified envs after defaulting env", //description |
| 233 | " argv: defenv_reserve <-c> <-b1> <-b2> <-b3> <env1 env2 env3 ...>\n" //usage |
| 234 | " - e.g. \n" |
| 235 | " defenv_reserve :\n" //usage |
| 236 | " old mode, NO env list , reserv cfg array '_env_args_reserve_' in <board>.c\n" |
| 237 | " defenv_reserve reserv_en0, reserv_env1, ...\n" //usage |
| 238 | " old mode, reserve user env list\n" //usage |
| 239 | " defenv_reserve <-c> <-b1> <-b2> <-b3> <env1 env2 env3 ...> ...\n" //usage |
| 240 | " new mode, default all env except \n" |
| 241 | " -c, amlogic Common env array _aml_env_reserv_array\n" |
| 242 | " -b0, <board>.c env array _board_env_reserv_array0\n" |
| 243 | " -b1, <board>.c env array _board_env_reserv_array1\n" |
| 244 | " -b2, <board>.c env array _board_env_reserv_array2\n" |
| 245 | " <env1 env2 env3 ...>\n", |
| 246 | var_complete |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 247 | ); |
| 248 | |
| 249 | /* |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 250 | * update_env_part, update env in flash |
| 251 | * usage: update_env_part <options -f/-s/-p> env1 env2 env3 ... |
| 252 | * Just add/update/delete env in flash, not replace all env like saveenv |
| 253 | * updaete include any of add/update/delete |
| 254 | * Reasons to replace saveenv with update_env_part |
| 255 | * >>Usually only save env u need, not include others like bootdelay |
| 256 | * >>Most cases, we need update env iff changed, and need speed up as save env to flash cost time |
| 257 | * todo: check not arg duplicated in argv |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 258 | */ |
| 259 | #if CONFIG_IS_ENABLED(AML_UPDATE_ENV) |
| 260 | static int do_update_env_part(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| 261 | { |
| 262 | int i = 0; |
| 263 | int ret = CMD_RET_SUCCESS; |
| 264 | int silent = 0;//don't tell empty env, 0 will print which env isnot exist |
| 265 | int force = 0;//when 1, even no all env list exist will update env part |
| 266 | int print = 0;//print env name/value after update env part |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 267 | const int BUF_SZ = CONFIG_ENV_SIZE * 2; |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 268 | char *env_part_buf = NULL; |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 269 | char *new_env_buf = NULL; |
| 270 | env_t *ep = NULL; |
| 271 | unsigned char *pdata = NULL; |
| 272 | uint32_t crc; |
| 273 | uint32_t n_env_in_flash = 0;//0 if all env not in flash, argc -1 if all env in flash |
| 274 | int need_update_env = 0; |
| 275 | const char *env_end = NULL;//current last kv's \0 |
| 276 | unsigned long env_len = 0; |
| 277 | unsigned int save_buf = 0;//1 if need save new_env_buf |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 278 | |
| 279 | if (argc < 2) { |
| 280 | MsgP("Need at least one env specify to update\n"); |
| 281 | return CMD_RET_USAGE; |
| 282 | } |
| 283 | while (argc > 1 && **(argv + 1) == '-') { |
| 284 | char *arg = *++argv; |
| 285 | |
| 286 | --argc; |
| 287 | while (*++arg) { |
| 288 | switch (*arg) { |
| 289 | case 'p':/* print */ |
| 290 | print = true; |
| 291 | break; |
| 292 | case 's':/* silent */ |
| 293 | silent = true; |
| 294 | break; |
| 295 | case 'f':/* force */ |
| 296 | force = true; |
| 297 | break; |
| 298 | default: |
| 299 | return CMD_RET_USAGE; |
| 300 | } |
| 301 | } |
| 302 | } |
| 303 | for (i = 1; i < argc; ++i) { |
| 304 | if (env_get(argv[i])) { |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 305 | continue; |
| 306 | } |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 307 | if (!force) {//force mode allow update env part even some env not exist |
| 308 | MsgP("env %s NOT exist and not -f, so cannot update flash env\n", argv[i]); |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 309 | return CMD_RET_FAILURE; |
| 310 | } |
| 311 | } |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 312 | env_part_buf = malloc(BUF_SZ); |
| 313 | if (!env_part_buf) { |
| 314 | errorP("Fail malloc buf sz 0x%x\n", BUF_SZ); |
| 315 | return CMD_RET_FAILURE; |
| 316 | } |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 317 | new_env_buf = env_part_buf + CONFIG_ENV_SIZE; |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 318 | |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 319 | //#1> record env list need to update |
| 320 | debugP("argc %d, argv[1] %s\n", argc, argv[1]); |
| 321 | env_set("_update_env_list", NULL); |
| 322 | for (i = 1; i < argc; ++i) { |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 323 | env_set("_temp_env_", argv[i]); |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 324 | run_command("env set _update_env_list ${_update_env_list} ${_temp_env_}", 0); |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 325 | } |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 326 | env_set("_temp_env_", NULL); |
| 327 | if (!silent) //print env list which updated in part env if not same |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 328 | MsgP("_update_env_list: %s\n", env_get("_update_env_list")); |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 329 | |
| 330 | //#2> read env and check if valid |
| 331 | if (store_get_type() == BOOT_NONE) { |
| 332 | errorP("env_storage: must init before load\n"); |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 333 | ret = CMD_RET_FAILURE; goto _update_env_part_err; |
| 334 | } |
Sam Wu | 083c485 | 2023-04-25 19:37:54 +0800 | [diff] [blame] | 335 | if (store_rsv_read(RSV_ENV, CONFIG_ENV_SIZE, env_part_buf)) { |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 336 | errorP("fail read env from storage\n"); |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 337 | ret = CMD_RET_FAILURE; goto _update_env_part_err; |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 338 | } else { |
| 339 | ep = (env_t *)env_part_buf; |
| 340 | pdata = ep->data; |
| 341 | memcpy(&crc, &ep->crc, sizeof(crc)); |
| 342 | if (crc32(0, pdata, ENV_SIZE) != crc) { |
| 343 | errorP("bad CRC in storage, so directly save all env to storage\n"); |
| 344 | ret = env_save(); |
| 345 | goto _update_env_part_err; |
| 346 | } |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 347 | } |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 348 | |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 349 | //#3> parse storage env and check if need update, most cases true |
| 350 | //compare if all env vars are same in flash |
| 351 | //case 1: usr env and store env both exist, but value not same (include usr env val empty) |
| 352 | //case 2: usr env not exist on store, but usr env val not empty |
| 353 | if (!pdata) { |
| 354 | errorP("err pdata\n"); |
| 355 | ret = CMD_RET_FAILURE; goto _update_env_part_err; |
| 356 | } else { |
| 357 | const char *current_kv = (char *)pdata;//env1=val\0 |
| 358 | unsigned int n_same_env = 0; |
| 359 | const char *kvsep = "="; |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 360 | |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 361 | //3.1>get the true end postion |
| 362 | for (env_end = (char *)pdata; env_end < (char *)pdata + ENV_SIZE;) { |
| 363 | const char *p = |
| 364 | env_end + strnlen(env_end, (char *)pdata + ENV_SIZE - env_end); |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 365 | |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 366 | if (*p != '\0') { |
| 367 | errorP("env need end with 0 but %c\n", *p); |
| 368 | ret = CMD_RET_FAILURE; goto _update_env_part_err; |
| 369 | } |
| 370 | if (++p - (char *)pdata >= ENV_SIZE) { |
| 371 | env_end = --p; |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 372 | break; |
| 373 | } |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 374 | if (*p == '\0') { |
| 375 | env_end = --p; |
| 376 | break; |
| 377 | } |
| 378 | env_end = p; |
| 379 | } |
| 380 | env_len = env_end - (char *)pdata; |
| 381 | if (*env_end || env_len < 1024) { |
| 382 | errorP("too short env or env end %c err\n", *env_end); |
| 383 | ret = CMD_RET_FAILURE; goto _update_env_part_err; |
| 384 | } |
| 385 | debugP("part env addr 0x%p, end 0x%p, sz %lx\n", |
| 386 | env_part_buf, env_end, env_end - env_part_buf); |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 387 | |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 388 | //3.2> check if NOT need update flash, which is most used case |
| 389 | for (; current_kv < env_end; current_kv += strlen(current_kv) + 1) { |
| 390 | const char *s_env_v = strpbrk(current_kv, kvsep);//storage env value |
yihui wu | 453c857 | 2024-11-08 11:19:04 +0800 | [diff] [blame] | 391 | int sz_flash_env = 0; |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 392 | |
| 393 | if (!s_env_v) { |
| 394 | errorP("err env in storage, not k=v fmt\n%s\n", current_kv); |
| 395 | ret = CMD_RET_FAILURE; goto _update_env_part_err; |
| 396 | } |
| 397 | ++s_env_v;//skip '=' |
yihui wu | 453c857 | 2024-11-08 11:19:04 +0800 | [diff] [blame] | 398 | sz_flash_env = s_env_v - current_kv - 1; |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 399 | //case 1, usr val == storage env val, skip |
| 400 | //case 2, usr val empty, del it if exist in storage |
| 401 | //case 2, usr val not empty, del it if exist in storage, append new to end |
| 402 | for (i = 1; i < argc; ++i) { |
| 403 | const char *usr_env = argv[i]; |
| 404 | const char *usr_env_val = env_get(usr_env); |
yihui wu | 453c857 | 2024-11-08 11:19:04 +0800 | [diff] [blame] | 405 | const int sz_usr_env = strlen(usr_env); |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 406 | |
yihui wu | 453c857 | 2024-11-08 11:19:04 +0800 | [diff] [blame] | 407 | if (sz_flash_env != sz_usr_env) |
| 408 | continue; |
| 409 | if (strncmp(current_kv, usr_env, sz_usr_env)) |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 410 | continue; |
| 411 | //Found key |
| 412 | ++n_env_in_flash; |
| 413 | if (!usr_env_val) {//need delete env in flash |
| 414 | MsgP("store env %s need remove\n", usr_env); |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 415 | need_update_env = 1; |
| 416 | break; |
| 417 | } |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 418 | if (strcmp(usr_env_val, s_env_v)) {//need modify env in flash |
| 419 | MsgP("store env %s need modify\n", usr_env); |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 420 | need_update_env = 1; |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 421 | break; |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 422 | } |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 423 | debugP("store env %s NOT need update\n", usr_env); |
| 424 | ++n_same_env; |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 425 | } |
| 426 | } |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 427 | if (!need_update_env) {//old user env not changed |
| 428 | need_update_env = n_same_env < argc - 1; |
| 429 | debugP("usr env num %d, not need update %d\n", argc - 1, n_same_env); |
| 430 | } |
| 431 | //if all env not in flash, not need update if all env not exist |
| 432 | if (n_env_in_flash == 0) {//all env not in flash |
| 433 | int all_env_empty = 1;//all env not exist in flash, and in memory |
| 434 | |
| 435 | for (i = 1; i < argc && all_env_empty; ++i) |
| 436 | if (env_get(argv[i])) |
| 437 | all_env_empty = 0; |
| 438 | if (all_env_empty) |
| 439 | if (!silent) |
| 440 | MsgP("all env not exist in env and flash\n"); |
| 441 | need_update_env = !all_env_empty; |
| 442 | } |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 443 | } |
| 444 | |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 445 | if (print) |
| 446 | run_command("printenv ${_update_env_list}", 0); |
| 447 | env_set("_update_env_list", NULL); |
| 448 | if (!need_update_env) { |
| 449 | MsgP("all env NOT need update\n"); |
| 450 | ret = CMD_RET_SUCCESS; goto _update_env_part_err; |
| 451 | } |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 452 | |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 453 | if (!n_env_in_flash) {//append all env to last as all not in env part |
| 454 | char *new_end = (char *)env_end; |
| 455 | unsigned int left_len = CONFIG_ENV_SIZE - env_len; |
| 456 | |
| 457 | for (i = 1; i < argc && left_len > 0; ++i) { |
| 458 | char *usr_env = argv[i]; |
| 459 | char *val = env_get(usr_env); |
| 460 | int cp_len = 0; |
| 461 | |
| 462 | if (!val) |
| 463 | continue; |
| 464 | if (!silent) |
| 465 | MsgP("append new env %s\n", usr_env); |
| 466 | cp_len = strlcpy(++new_end, usr_env, left_len);//cp key |
Sam Wu | f210747 | 2024-02-23 19:58:09 +0800 | [diff] [blame] | 467 | new_end += cp_len - 1, left_len -= cp_len; |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 468 | *new_end = '=', --left_len;//cpy '=' |
Sam Wu | f210747 | 2024-02-23 19:58:09 +0800 | [diff] [blame] | 469 | cp_len = strlcpy(++new_end, val, left_len);//cp val |
| 470 | new_end += cp_len - 1, left_len -= cp_len; |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 471 | } |
| 472 | if (left_len == CONFIG_ENV_SIZE - env_len) { |
| 473 | errorP("exception\n"); |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 474 | ret = CMD_RET_FAILURE; goto _update_env_part_err; |
| 475 | } |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 476 | env_len = CONFIG_ENV_SIZE - left_len; |
| 477 | env_end = env_part_buf + env_len; |
| 478 | |
| 479 | save_buf = 0; goto _update_env_save_; |
| 480 | } else {//not all env in flash |
| 481 | //copy flash env to new buf, and skip env need modify/delete |
| 482 | const char *current_kv = (char *)pdata;//env1=val\0 |
| 483 | const char *kvsep = "="; |
Meng yu | 552746a | 2023-07-28 14:16:48 +0800 | [diff] [blame] | 484 | char *new_kv = new_env_buf + 4; //skip crc |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 485 | unsigned int new_env_len = 0; |
| 486 | int env_need_update = 0; |
| 487 | |
| 488 | memset(new_env_buf, 0, CONFIG_ENV_SIZE); |
| 489 | save_buf = 1; |
| 490 | |
| 491 | /* 1, if current k=v\0 not in usr input list, just copy it to new buffer |
| 492 | * 2, else if in input list but no value, skip it |
| 493 | * 3, else if value not change, just copy it to new buffer |
| 494 | * 4, else if in the usr input list but value changed, use input key value instead |
| 495 | */ |
| 496 | for (; current_kv < env_end; current_kv += strlen(current_kv) + 1) { |
| 497 | const char *s_env_v = strpbrk(current_kv, kvsep);//storage env value |
| 498 | const char *next = NULL;//next k=v |
| 499 | int s_env_v_len = 1; |
| 500 | unsigned int kv_len = 0; |
yihui wu | 453c857 | 2024-11-08 11:19:04 +0800 | [diff] [blame] | 501 | int sz_flash_env = 0; |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 502 | |
| 503 | if (!s_env_v) { |
| 504 | errorP("err env in flash, not k=v fmt\n%s\n", current_kv); |
| 505 | ret = CMD_RET_FAILURE; goto _update_env_part_err; |
| 506 | } |
| 507 | ++s_env_v;//skip '=' |
yihui wu | 453c857 | 2024-11-08 11:19:04 +0800 | [diff] [blame] | 508 | sz_flash_env = s_env_v - current_kv - 1; |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 509 | s_env_v_len = strnlen(s_env_v, env_end - s_env_v); |
| 510 | next = s_env_v + s_env_v_len + 1;//next k=v\0 |
| 511 | for (i = 1; i < argc; ++i) { |
| 512 | const char *usr_env = argv[i]; |
yihui wu | 453c857 | 2024-11-08 11:19:04 +0800 | [diff] [blame] | 513 | int sz_usr_env = 0; |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 514 | |
| 515 | if (!usr_env) |
| 516 | continue;//disposed |
yihui wu | 453c857 | 2024-11-08 11:19:04 +0800 | [diff] [blame] | 517 | sz_usr_env = strlen(usr_env); |
| 518 | if (sz_flash_env != sz_usr_env) |
| 519 | continue; |
| 520 | if (!strncmp(current_kv, usr_env, sz_usr_env)) |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 521 | break; |
| 522 | } |
| 523 | kv_len = (unsigned long)(next - current_kv); |
| 524 | if (i == argc) {//this store env not in user input, so not need change |
| 525 | memcpy(new_kv, current_kv, kv_len); |
| 526 | new_kv += kv_len; |
| 527 | new_env_len += kv_len; |
| 528 | } else { |
| 529 | const char *usr_env = argv[i]; |
| 530 | const char *usr_env_val = env_get(usr_env); |
| 531 | |
| 532 | if (!usr_env_val) {//2, in the input list but no value |
| 533 | MsgP("store env %s will removed\n", usr_env); |
| 534 | env_need_update = 1; |
| 535 | continue; |
| 536 | } else if (!strcmp(usr_env_val, s_env_v)) {//in input && not change |
| 537 | MsgP("store env %s not need changed\n", usr_env); |
| 538 | memcpy(new_kv, current_kv, kv_len); |
| 539 | new_kv += kv_len; |
| 540 | new_env_len += kv_len; |
| 541 | } else {//4, in the list and value changed |
| 542 | unsigned int cp_len = kv_len - 1 - s_env_v_len; |
| 543 | |
| 544 | MsgP("store env %s DO need changed\n", usr_env); |
| 545 | env_need_update = 1; |
| 546 | memcpy(new_kv, current_kv, cp_len);//copy k= |
| 547 | new_kv += cp_len; |
| 548 | new_env_len += cp_len; |
| 549 | |
| 550 | cp_len = strlen(usr_env_val) + 1; |
| 551 | memcpy(new_kv, usr_env_val, cp_len);//copy k= |
| 552 | new_kv += cp_len; |
| 553 | new_env_len += cp_len; |
| 554 | } |
| 555 | //argv[i] = NULL;//mark as disposed |
| 556 | *((char **)argv + i) = NULL;//mark as disposed |
| 557 | } |
| 558 | } //end to traverse all flash env |
| 559 | |
| 560 | for (i = 1; i < argc; ++i) { |
| 561 | const char *usr_env = argv[i]; |
| 562 | char *usr_env_val = usr_env ? env_get(usr_env) : NULL; |
| 563 | unsigned int left_len = 0; |
| 564 | |
| 565 | if (!usr_env) |
| 566 | continue; |
| 567 | if (!usr_env_val) { |
| 568 | MsgP("new env %s NULL so skip\n", usr_env); |
| 569 | } else { |
| 570 | env_need_update = 1; |
| 571 | left_len = CONFIG_ENV_SIZE - new_env_len - 1; |
| 572 | snprintf(new_kv, left_len, "%s=%s", usr_env, usr_env_val); |
| 573 | MsgP("new store env %s\n", new_kv); |
| 574 | new_kv += strnlen(new_kv, left_len) + 1; |
| 575 | } |
| 576 | } |
| 577 | if (!env_need_update) { |
| 578 | MsgP("store env same, new env NULL, so not need update\n"); |
| 579 | ret = CMD_RET_SUCCESS; goto _update_env_part_err; |
| 580 | } |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 581 | } |
| 582 | |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 583 | _update_env_save_: |
| 584 | ep = (env_t *)(env_part_buf + save_buf * CONFIG_ENV_SIZE); |
| 585 | pdata = ep->data; |
| 586 | debugP("crc before update 0x%x\n", ep->crc); |
| 587 | |
| 588 | //ep->crc = crc32(0, pdata, ENV_SIZE);//not work... |
| 589 | crc = crc32(0, pdata, ENV_SIZE); |
| 590 | memcpy(&ep->crc, &crc, sizeof(crc)); |
| 591 | if (!silent) |
| 592 | MsgP("new env part crc 0x%x\n", ep->crc); |
| 593 | if (store_rsv_write(RSV_ENV, CONFIG_ENV_SIZE, ep)) { |
| 594 | errorP("Fail to update env part\n"); |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 595 | ret = CMD_RET_FAILURE; goto _update_env_part_err; |
| 596 | } |
Sam Wu | 6f3d40e | 2023-04-22 01:10:27 +0800 | [diff] [blame] | 597 | debugP("ok update env addr 0x%p\n", env_part_buf); |
Bo Lv | 72d0e90 | 2023-01-02 14:27:34 +0000 | [diff] [blame] | 598 | |
| 599 | _update_env_part_err: |
| 600 | free(env_part_buf); |
| 601 | return ret; |
| 602 | } |
| 603 | |
| 604 | U_BOOT_CMD_COMPLETE(update_env_part, //command name |
| 605 | CONFIG_SYS_MAXARGS, //maxargs |
| 606 | 0, //repeatable |
| 607 | do_update_env_part, //command function |
| 608 | "update env part with argv list", //usage |
| 609 | " argv: update_env_part <-p> <-f> <-s> env0 env1 env2 ...\n" |
| 610 | " -p print, will print env value\n" |
| 611 | " -f force, will allow to update env part even some specified env vars not exist\n" |
| 612 | " -s silent, least log if specify -s\n" |
| 613 | " - e.g.\n" |
| 614 | " update_env_part -p lock:\n" |
| 615 | " update env var lock if it's diff in flash\n" |
| 616 | " update_env_part -f -p lock lock1:\n" |
| 617 | " update env var lock if it's diff and even lock1 is not exist\n", |
| 618 | var_complete |
| 619 | ); |
| 620 | #endif //#if CONFIG_IS_ENABLED(AML_UPDATE_ENV) |
| 621 | |