xref: /openbmc/u-boot/env/ubi.c (revision 3ab9598d)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (c) Copyright 2012 by National Instruments,
4  *        Joe Hershberger <joe.hershberger@ni.com>
5  */
6 
7 #include <common.h>
8 
9 #include <command.h>
10 #include <environment.h>
11 #include <errno.h>
12 #include <malloc.h>
13 #include <memalign.h>
14 #include <search.h>
15 #include <ubi_uboot.h>
16 #undef crc32
17 
18 DECLARE_GLOBAL_DATA_PTR;
19 
20 #ifdef CONFIG_CMD_SAVEENV
21 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
22 static int env_ubi_save(void)
23 {
24 	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
25 	int ret;
26 
27 	ret = env_export(env_new);
28 	if (ret)
29 		return ret;
30 
31 	if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
32 		printf("\n** Cannot find mtd partition \"%s\"\n",
33 		       CONFIG_ENV_UBI_PART);
34 		return 1;
35 	}
36 
37 	if (gd->env_valid == ENV_VALID) {
38 		puts("Writing to redundant UBI... ");
39 		if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME_REDUND,
40 				     (void *)env_new, CONFIG_ENV_SIZE)) {
41 			printf("\n** Unable to write env to %s:%s **\n",
42 			       CONFIG_ENV_UBI_PART,
43 			       CONFIG_ENV_UBI_VOLUME_REDUND);
44 			return 1;
45 		}
46 	} else {
47 		puts("Writing to UBI... ");
48 		if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME,
49 				     (void *)env_new, CONFIG_ENV_SIZE)) {
50 			printf("\n** Unable to write env to %s:%s **\n",
51 			       CONFIG_ENV_UBI_PART,
52 			       CONFIG_ENV_UBI_VOLUME);
53 			return 1;
54 		}
55 	}
56 
57 	puts("done\n");
58 
59 	gd->env_valid = gd->env_valid == ENV_REDUND ? ENV_VALID : ENV_REDUND;
60 
61 	return 0;
62 }
63 #else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */
64 static int env_ubi_save(void)
65 {
66 	ALLOC_CACHE_ALIGN_BUFFER(env_t, env_new, 1);
67 	int ret;
68 
69 	ret = env_export(env_new);
70 	if (ret)
71 		return ret;
72 
73 	if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
74 		printf("\n** Cannot find mtd partition \"%s\"\n",
75 		       CONFIG_ENV_UBI_PART);
76 		return 1;
77 	}
78 
79 	if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new,
80 			     CONFIG_ENV_SIZE)) {
81 		printf("\n** Unable to write env to %s:%s **\n",
82 		       CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
83 		return 1;
84 	}
85 
86 	puts("done\n");
87 	return 0;
88 }
89 #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */
90 #endif /* CONFIG_CMD_SAVEENV */
91 
92 #ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT
93 static int env_ubi_load(void)
94 {
95 	ALLOC_CACHE_ALIGN_BUFFER(char, env1_buf, CONFIG_ENV_SIZE);
96 	ALLOC_CACHE_ALIGN_BUFFER(char, env2_buf, CONFIG_ENV_SIZE);
97 	int read1_fail, read2_fail;
98 	env_t *tmp_env1, *tmp_env2;
99 
100 	/*
101 	 * In case we have restarted u-boot there is a chance that buffer
102 	 * contains old environment (from the previous boot).
103 	 * If UBI volume is zero size, ubi_volume_read() doesn't modify the
104 	 * buffer.
105 	 * We need to clear buffer manually here, so the invalid CRC will
106 	 * cause setting default environment as expected.
107 	 */
108 	memset(env1_buf, 0x0, CONFIG_ENV_SIZE);
109 	memset(env2_buf, 0x0, CONFIG_ENV_SIZE);
110 
111 	tmp_env1 = (env_t *)env1_buf;
112 	tmp_env2 = (env_t *)env2_buf;
113 
114 	if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
115 		printf("\n** Cannot find mtd partition \"%s\"\n",
116 		       CONFIG_ENV_UBI_PART);
117 		set_default_env(NULL, 0);
118 		return -EIO;
119 	}
120 
121 	read1_fail = ubi_volume_read(CONFIG_ENV_UBI_VOLUME, (void *)tmp_env1,
122 				     CONFIG_ENV_SIZE);
123 	if (read1_fail)
124 		printf("\n** Unable to read env from %s:%s **\n",
125 		       CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
126 
127 	read2_fail = ubi_volume_read(CONFIG_ENV_UBI_VOLUME_REDUND,
128 				     (void *)tmp_env2, CONFIG_ENV_SIZE);
129 	if (read2_fail)
130 		printf("\n** Unable to read redundant env from %s:%s **\n",
131 		       CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND);
132 
133 	return env_import_redund((char *)tmp_env1, read1_fail, (char *)tmp_env2,
134 							 read2_fail);
135 }
136 #else /* ! CONFIG_SYS_REDUNDAND_ENVIRONMENT */
137 static int env_ubi_load(void)
138 {
139 	ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
140 
141 	/*
142 	 * In case we have restarted u-boot there is a chance that buffer
143 	 * contains old environment (from the previous boot).
144 	 * If UBI volume is zero size, ubi_volume_read() doesn't modify the
145 	 * buffer.
146 	 * We need to clear buffer manually here, so the invalid CRC will
147 	 * cause setting default environment as expected.
148 	 */
149 	memset(buf, 0x0, CONFIG_ENV_SIZE);
150 
151 	if (ubi_part(CONFIG_ENV_UBI_PART, NULL)) {
152 		printf("\n** Cannot find mtd partition \"%s\"\n",
153 		       CONFIG_ENV_UBI_PART);
154 		set_default_env(NULL, 0);
155 		return -EIO;
156 	}
157 
158 	if (ubi_volume_read(CONFIG_ENV_UBI_VOLUME, buf, CONFIG_ENV_SIZE)) {
159 		printf("\n** Unable to read env from %s:%s **\n",
160 		       CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME);
161 		set_default_env(NULL, 0);
162 		return -EIO;
163 	}
164 
165 	return env_import(buf, 1);
166 }
167 #endif /* CONFIG_SYS_REDUNDAND_ENVIRONMENT */
168 
169 U_BOOT_ENV_LOCATION(ubi) = {
170 	.location	= ENVL_UBI,
171 	.load		= env_ubi_load,
172 	.save		= env_save_ptr(env_ubi_save),
173 };
174