2 * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
4 * See file CREDITS for list of people who contributed to this
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * @brief Environment handling support (host and target)
25 * Important: This file will also be used on the host to create
26 * the default environment when building the U-Boot binary. So
27 * do not add any new U-Boot related functions here!
41 #include <environment.h>
43 # define errno_str(x) ("void")
44 #define EXPORT_SYMBOL(x)
47 int file_size_action(const char *filename
, struct stat
*statbuf
,
48 void *userdata
, int depth
)
50 struct action_data
*data
= userdata
;
52 data
->writep
+= sizeof(struct envfs_inode
);
53 data
->writep
+= PAD4(strlen(filename
) + 1 - strlen(data
->base
));
54 data
->writep
+= PAD4(statbuf
->st_size
);
58 int file_save_action(const char *filename
, struct stat
*statbuf
,
59 void *userdata
, int depth
)
61 struct action_data
*data
= userdata
;
62 struct envfs_inode
*inode
;
64 int namelen
= strlen(filename
) + 1 - strlen(data
->base
);
66 debug("handling file %s size %ld namelen %d\n", filename
+ strlen(data
->base
),
67 statbuf
->st_size
, namelen
);
69 inode
= (struct envfs_inode
*)data
->writep
;
70 inode
->magic
= ENVFS_32(ENVFS_INODE_MAGIC
);
71 inode
->namelen
= ENVFS_32(namelen
);
72 inode
->size
= ENVFS_32(statbuf
->st_size
);
73 data
->writep
+= sizeof(struct envfs_inode
);
75 strcpy(data
->writep
, filename
+ strlen(data
->base
));
76 data
->writep
+= PAD4(namelen
);
78 fd
= open(filename
, O_RDONLY
);
80 printf("Open %s %s\n", filename
, errno_str());
84 if (read(fd
, data
->writep
, statbuf
->st_size
) < statbuf
->st_size
) {
90 data
->writep
+= PAD4(statbuf
->st_size
);
97 * Make the current environment persistent
98 * @param[in] filename where to store
99 * @param[in] dirname what to store (all files in this dir)
100 * @return 0 on success, anything else in case of failure
102 * Note: This function will also be used on the host! See note in the header
105 int envfs_save(char *filename
, char *dirname
)
107 struct envfs_super
*super
;
108 int envfd
, size
, ret
;
109 struct action_data data
;
115 /* first pass: calculate size */
116 recursive_action(dirname
, ACTION_RECURSE
, file_size_action
,
119 size
= (unsigned long)data
.writep
;
121 buf
= xzalloc(size
+ sizeof(struct envfs_super
));
122 data
.writep
= buf
+ sizeof(struct envfs_super
);
124 super
= (struct envfs_super
*)buf
;
125 super
->magic
= ENVFS_32(ENVFS_MAGIC
);
126 super
->size
= ENVFS_32(size
);
128 /* second pass: copy files to buffer */
129 recursive_action(dirname
, ACTION_RECURSE
, file_save_action
,
132 super
->crc
= ENVFS_32(crc32(0, buf
+ sizeof(struct envfs_super
), size
));
133 super
->sb_crc
= ENVFS_32(crc32(0, buf
, sizeof(struct envfs_super
) - 4));
135 envfd
= open(filename
, O_WRONLY
| O_CREAT
, S_IRUSR
| S_IWUSR
);
137 printf("Open %s %s\n", filename
, errno_str());
142 if (write(envfd
, buf
, size
+ sizeof(struct envfs_super
)) <
143 sizeof(struct envfs_super
)) {
145 ret
= -1; /* FIXME */
157 EXPORT_SYMBOL(envfs_save
);
160 * Restore the last environment into the current one
161 * @param[in] filename from where to restore
162 * @param[in] dir where to store the last content
163 * @return 0 on success, anything else in case of failure
165 * Note: This function will also be used on the host! See note in the header
168 int envfs_load(char *filename
, char *dir
)
170 struct envfs_super super
;
171 void *buf
= NULL
, *buf_free
= NULL
;
178 envfd
= open(filename
, O_RDONLY
);
180 printf("Open %s %s\n", filename
, errno_str());
184 /* read superblock */
185 ret
= read(envfd
, &super
, sizeof(struct envfs_super
));
186 if ( ret
< sizeof(struct envfs_super
)) {
192 if ( ENVFS_32(super
.magic
) != ENVFS_MAGIC
) {
193 printf("envfs: wrong magic on %s\n", filename
);
198 if (crc32(0, (unsigned char *)&super
, sizeof(struct envfs_super
) - 4)
199 != ENVFS_32(super
.sb_crc
)) {
200 printf("wrong crc on env superblock\n");
204 size
= ENVFS_32(super
.size
);
207 ret
= read(envfd
, buf
, size
);
213 if (crc32(0, (unsigned char *)buf
, size
)
214 != ENVFS_32(super
.crc
)) {
215 printf("wrong crc on env\n");
220 struct envfs_inode
*inode
;
221 uint32_t inode_size
,inode_namelen
;
223 inode
= (struct envfs_inode
*)buf
;
225 if (ENVFS_32(inode
->magic
) != ENVFS_INODE_MAGIC
) {
226 printf("envfs: wrong magic on %s\n", filename
);
230 inode_size
= ENVFS_32(inode
->size
);
231 inode_namelen
= ENVFS_32(inode
->namelen
);
233 debug("loading %s size %d namelen %d\n", inode
->data
,
234 inode_size
, inode_namelen
);
236 str
= concat_path_file(dir
, inode
->data
);
238 make_directory(dirname(tmp
));
241 fd
= open(str
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0644);
244 printf("Open %s\n", errno_str());
249 namelen_full
= PAD4(inode_namelen
);
250 ret
= write(fd
, buf
+ namelen_full
+ sizeof(struct envfs_inode
),
252 if (ret
< inode_size
) {
259 buf
+= PAD4(inode_namelen
) + PAD4(inode_size
) +
260 sizeof(struct envfs_inode
);
261 size
-= PAD4(inode_namelen
) + PAD4(inode_size
) +
262 sizeof(struct envfs_inode
);