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