blob: b3af308211ec81e2b919045f35c588c5658fd9d8 [file] [log] [blame]
Bo Lv72d0e902023-01-02 14:27:34 +00001// 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 Wu6f3d40e2023-04-22 01:10:27 +080010#include <env_internal.h>
Bo Lv72d0e902023-01-02 14:27:34 +000011#include <cli.h>
12#include <errno.h>
13#include <malloc.h>
14#include <linux/stddef.h>
Sam Wu083c4852023-04-25 19:37:54 +080015#include <u-boot/crc.h>
Bo Lv72d0e902023-01-02 14:27:34 +000016#include <asm/byteorder.h>
Sam Wu6f3d40e2023-04-22 01:10:27 +080017#include <amlogic/store_wrapper.h>
Bo Lv72d0e902023-01-02 14:27:34 +000018
19static const char* const temp_for_compile[] = {"__test1","__test2","__test3",NULL};
20extern const char * const _env_args_reserve_[0] __attribute__((weak, alias("temp_for_compile")));
Sam Wua93fc392024-01-03 16:58:46 +080021extern const char * const _aml_env_reserv_array[0] __attribute__((weak, alias("temp_for_compile")));
yihui wu648297d2024-12-18 01:14:14 +080022extern const char * const _aml_env_reserv_array1[0] __attribute__((weak, alias("temp_for_compile")));
Sam Wua93fc392024-01-03 16:58:46 +080023extern const char * const _board_env_reserv_array0[0] __attribute__((weak, alias("temp_for_compile")));
24extern const char * const _board_env_reserv_array1[0] __attribute__((weak, alias("temp_for_compile")));
25extern const char * const _board_env_reserv_array2[0] __attribute__((weak, alias("temp_for_compile")));
Bo Lv72d0e902023-01-02 14:27:34 +000026
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 Wua93fc392024-01-03 16:58:46 +080032enum DEF_ENV_RESERV_ARRAY {
33 BIT_ENV_RESERV_ARRAY_AML_COMMON, //-c, common aml env array_aml_env_reserv_array
yihui wu648297d2024-12-18 01:14:14 +080034 BIT_ENV_RESERV_ARRAY_AML_COMMON1, //-c, common aml env array_aml_env_reserv_array
Sam Wua93fc392024-01-03 16:58:46 +080035 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 Lv72d0e902023-01-02 14:27:34 +000043static 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 Wua93fc392024-01-03 16:58:46 +0800115static int _do_defenv_reserv(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Bo Lv72d0e902023-01-02 14:27:34 +0000116{
Sam Wua93fc392024-01-03 16:58:46 +0800117 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 Lv72d0e902023-01-02 14:27:34 +0000125
Sam Wua93fc392024-01-03 16:58:46 +0800126 if (!envListNum) {
127 envListArr = (const char **)_env_args_reserve_;
128 const char **pArr = (const char **)envListArr;
Bo Lv72d0e902023-01-02 14:27:34 +0000129
Sam Wua93fc392024-01-03 16:58:46 +0800130 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 Lv72d0e902023-01-02 14:27:34 +0000135
Sam Wua93fc392024-01-03 16:58:46 +0800136 _aml_env_reserv_[BIT_ENV_RESERV_ARRAY_AML_COMMON] = _aml_env_reserv_array;
yihui wu648297d2024-12-18 01:14:14 +0800137 _aml_env_reserv_[BIT_ENV_RESERV_ARRAY_AML_COMMON1] = _aml_env_reserv_array1;
Sam Wua93fc392024-01-03 16:58:46 +0800138 _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 wu648297d2024-12-18 01:14:14 +0800146 if (*++arg) {
Sam Wua93fc392024-01-03 16:58:46 +0800147 switch (*arg) {
148 case 'b':{//board env
149 const int bd = *++arg - '0';
Bo Lv72d0e902023-01-02 14:27:34 +0000150
Sam Wua93fc392024-01-03 16:58:46 +0800151 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 wu648297d2024-12-18 01:14:14 +0800158 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 Wua93fc392024-01-03 16:58:46 +0800170 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 Lv72d0e902023-01-02 14:27:34 +0000209}
210
Sam Wua93fc392024-01-03 16:58:46 +0800211U_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
219static 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
228U_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 Lv72d0e902023-01-02 14:27:34 +0000247);
248
249/*
Sam Wu6f3d40e2023-04-22 01:10:27 +0800250 * 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 Lv72d0e902023-01-02 14:27:34 +0000258 */
259#if CONFIG_IS_ENABLED(AML_UPDATE_ENV)
260static 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 Wu6f3d40e2023-04-22 01:10:27 +0800267 const int BUF_SZ = CONFIG_ENV_SIZE * 2;
Bo Lv72d0e902023-01-02 14:27:34 +0000268 char *env_part_buf = NULL;
Sam Wu6f3d40e2023-04-22 01:10:27 +0800269 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 Lv72d0e902023-01-02 14:27:34 +0000278
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 Lv72d0e902023-01-02 14:27:34 +0000305 continue;
306 }
Sam Wu6f3d40e2023-04-22 01:10:27 +0800307 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 Lv72d0e902023-01-02 14:27:34 +0000309 return CMD_RET_FAILURE;
310 }
311 }
Bo Lv72d0e902023-01-02 14:27:34 +0000312 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 Wu6f3d40e2023-04-22 01:10:27 +0800317 new_env_buf = env_part_buf + CONFIG_ENV_SIZE;
Bo Lv72d0e902023-01-02 14:27:34 +0000318
Sam Wu6f3d40e2023-04-22 01:10:27 +0800319 //#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 Lv72d0e902023-01-02 14:27:34 +0000323 env_set("_temp_env_", argv[i]);
Sam Wu6f3d40e2023-04-22 01:10:27 +0800324 run_command("env set _update_env_list ${_update_env_list} ${_temp_env_}", 0);
Bo Lv72d0e902023-01-02 14:27:34 +0000325 }
Sam Wu6f3d40e2023-04-22 01:10:27 +0800326 env_set("_temp_env_", NULL);
327 if (!silent) //print env list which updated in part env if not same
Bo Lv72d0e902023-01-02 14:27:34 +0000328 MsgP("_update_env_list: %s\n", env_get("_update_env_list"));
Sam Wu6f3d40e2023-04-22 01:10:27 +0800329
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 Lv72d0e902023-01-02 14:27:34 +0000333 ret = CMD_RET_FAILURE; goto _update_env_part_err;
334 }
Sam Wu083c4852023-04-25 19:37:54 +0800335 if (store_rsv_read(RSV_ENV, CONFIG_ENV_SIZE, env_part_buf)) {
Sam Wu6f3d40e2023-04-22 01:10:27 +0800336 errorP("fail read env from storage\n");
Bo Lv72d0e902023-01-02 14:27:34 +0000337 ret = CMD_RET_FAILURE; goto _update_env_part_err;
Sam Wu6f3d40e2023-04-22 01:10:27 +0800338 } 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 Lv72d0e902023-01-02 14:27:34 +0000347 }
Bo Lv72d0e902023-01-02 14:27:34 +0000348
Sam Wu6f3d40e2023-04-22 01:10:27 +0800349 //#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 Lv72d0e902023-01-02 14:27:34 +0000360
Sam Wu6f3d40e2023-04-22 01:10:27 +0800361 //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 Lv72d0e902023-01-02 14:27:34 +0000365
Sam Wu6f3d40e2023-04-22 01:10:27 +0800366 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 Lv72d0e902023-01-02 14:27:34 +0000372 break;
373 }
Sam Wu6f3d40e2023-04-22 01:10:27 +0800374 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 Lv72d0e902023-01-02 14:27:34 +0000387
Sam Wu6f3d40e2023-04-22 01:10:27 +0800388 //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 wu453c8572024-11-08 11:19:04 +0800391 int sz_flash_env = 0;
Sam Wu6f3d40e2023-04-22 01:10:27 +0800392
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 wu453c8572024-11-08 11:19:04 +0800398 sz_flash_env = s_env_v - current_kv - 1;
Sam Wu6f3d40e2023-04-22 01:10:27 +0800399 //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 wu453c8572024-11-08 11:19:04 +0800405 const int sz_usr_env = strlen(usr_env);
Sam Wu6f3d40e2023-04-22 01:10:27 +0800406
yihui wu453c8572024-11-08 11:19:04 +0800407 if (sz_flash_env != sz_usr_env)
408 continue;
409 if (strncmp(current_kv, usr_env, sz_usr_env))
Sam Wu6f3d40e2023-04-22 01:10:27 +0800410 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 Lv72d0e902023-01-02 14:27:34 +0000415 need_update_env = 1;
416 break;
417 }
Sam Wu6f3d40e2023-04-22 01:10:27 +0800418 if (strcmp(usr_env_val, s_env_v)) {//need modify env in flash
419 MsgP("store env %s need modify\n", usr_env);
Bo Lv72d0e902023-01-02 14:27:34 +0000420 need_update_env = 1;
Sam Wu6f3d40e2023-04-22 01:10:27 +0800421 break;
Bo Lv72d0e902023-01-02 14:27:34 +0000422 }
Sam Wu6f3d40e2023-04-22 01:10:27 +0800423 debugP("store env %s NOT need update\n", usr_env);
424 ++n_same_env;
Bo Lv72d0e902023-01-02 14:27:34 +0000425 }
426 }
Sam Wu6f3d40e2023-04-22 01:10:27 +0800427 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 Lv72d0e902023-01-02 14:27:34 +0000443 }
444
Sam Wu6f3d40e2023-04-22 01:10:27 +0800445 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 Lv72d0e902023-01-02 14:27:34 +0000452
Sam Wu6f3d40e2023-04-22 01:10:27 +0800453 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 Wuf2107472024-02-23 19:58:09 +0800467 new_end += cp_len - 1, left_len -= cp_len;
Sam Wu6f3d40e2023-04-22 01:10:27 +0800468 *new_end = '=', --left_len;//cpy '='
Sam Wuf2107472024-02-23 19:58:09 +0800469 cp_len = strlcpy(++new_end, val, left_len);//cp val
470 new_end += cp_len - 1, left_len -= cp_len;
Sam Wu6f3d40e2023-04-22 01:10:27 +0800471 }
472 if (left_len == CONFIG_ENV_SIZE - env_len) {
473 errorP("exception\n");
Bo Lv72d0e902023-01-02 14:27:34 +0000474 ret = CMD_RET_FAILURE; goto _update_env_part_err;
475 }
Sam Wu6f3d40e2023-04-22 01:10:27 +0800476 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 yu552746a2023-07-28 14:16:48 +0800484 char *new_kv = new_env_buf + 4; //skip crc
Sam Wu6f3d40e2023-04-22 01:10:27 +0800485 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 wu453c8572024-11-08 11:19:04 +0800501 int sz_flash_env = 0;
Sam Wu6f3d40e2023-04-22 01:10:27 +0800502
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 wu453c8572024-11-08 11:19:04 +0800508 sz_flash_env = s_env_v - current_kv - 1;
Sam Wu6f3d40e2023-04-22 01:10:27 +0800509 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 wu453c8572024-11-08 11:19:04 +0800513 int sz_usr_env = 0;
Sam Wu6f3d40e2023-04-22 01:10:27 +0800514
515 if (!usr_env)
516 continue;//disposed
yihui wu453c8572024-11-08 11:19:04 +0800517 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 Wu6f3d40e2023-04-22 01:10:27 +0800521 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 Lv72d0e902023-01-02 14:27:34 +0000581 }
582
Sam Wu6f3d40e2023-04-22 01:10:27 +0800583_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 Lv72d0e902023-01-02 14:27:34 +0000595 ret = CMD_RET_FAILURE; goto _update_env_part_err;
596 }
Sam Wu6f3d40e2023-04-22 01:10:27 +0800597 debugP("ok update env addr 0x%p\n", env_part_buf);
Bo Lv72d0e902023-01-02 14:27:34 +0000598
599_update_env_part_err:
600 free(env_part_buf);
601 return ret;
602}
603
604U_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