2 * Copyright (c) 2012 Department of Software Engineering,
3 * University of Szeged, Hungary
4 * Copyright (c) 2012 Tamas Toth <ttoth@inf.u-szeged.hu>
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by the Department of Software Engineering, University of Szeged, Hungary
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
36 #include <sys/param.h>
52 #include "chfs_makefs.h"
57 #include "chfs/chfs_mkfs.h"
59 static uint32_t img_ofs
= 0;
60 static uint64_t version
= 0;
61 static uint64_t max_serial
= 0;
62 static int lebnumber
= 0;
64 static const unsigned char ffbuf
[16] = {
65 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
70 buf_write(fsinfo_t
*fsopts
, const void *buf
, size_t len
)
73 const char *charbuf
= buf
;
76 retval
= write(fsopts
->fd
, charbuf
, len
);
79 err(EXIT_FAILURE
, "ERROR while writing");
89 padblock(fsinfo_t
*fsopts
)
91 chfs_opt_t
*chfs_opts
= fsopts
->fs_specific
;
92 while (img_ofs
% chfs_opts
->eraseblock
) {
93 buf_write(fsopts
, ffbuf
, MIN(sizeof(ffbuf
),
94 chfs_opts
->eraseblock
- (img_ofs
% chfs_opts
->eraseblock
)));
99 padword(fsinfo_t
*fsopts
)
102 buf_write(fsopts
, ffbuf
, 4 - img_ofs
% 4);
107 pad_block_if_less_than(fsinfo_t
*fsopts
, int req
)
109 chfs_opt_t
*chfs_opts
= fsopts
->fs_specific
;
110 if ((img_ofs
% chfs_opts
->eraseblock
) + req
>
111 (uint32_t)chfs_opts
->eraseblock
) {
113 write_eb_header(fsopts
);
118 write_eb_header(fsinfo_t
*fsopts
)
121 struct chfs_eb_hdr ebhdr
;
124 opts
= fsopts
->fs_specific
;
126 #define MINSIZE MAX(MAX(CHFS_EB_EC_HDR_SIZE, CHFS_EB_HDR_NOR_SIZE), \
127 CHFS_EB_HDR_NAND_SIZE)
128 if ((uint32_t)opts
->pagesize
< MINSIZE
)
129 errx(EXIT_FAILURE
, "pagesize cannot be less than %zu", MINSIZE
);
130 buf
= emalloc(opts
->pagesize
);
131 memset(buf
, 0xFF, opts
->pagesize
);
133 ebhdr
.ec_hdr
.magic
= htole32(CHFS_MAGIC_BITMASK
);
134 ebhdr
.ec_hdr
.erase_cnt
= htole32(1);
135 ebhdr
.ec_hdr
.crc_ec
= htole32(crc32(0,
136 (uint8_t *)&ebhdr
.ec_hdr
+ 8, 4));
138 memcpy(buf
, &ebhdr
.ec_hdr
, CHFS_EB_EC_HDR_SIZE
);
140 buf_write(fsopts
, buf
, opts
->pagesize
);
142 memset(buf
, 0xFF, opts
->pagesize
);
144 if (opts
->mediatype
== TYPE_NAND
) {
145 ebhdr
.u
.nand_hdr
.lid
= htole32(lebnumber
++);
146 ebhdr
.u
.nand_hdr
.serial
= htole64(++(max_serial
));
147 ebhdr
.u
.nand_hdr
.crc
= htole32(crc32(0,
148 (uint8_t *)&ebhdr
.u
.nand_hdr
+ 4,
149 CHFS_EB_HDR_NAND_SIZE
- 4));
150 memcpy(buf
, &ebhdr
.u
.nand_hdr
, CHFS_EB_HDR_NAND_SIZE
);
152 ebhdr
.u
.nor_hdr
.lid
= htole32(lebnumber
++);
153 ebhdr
.u
.nor_hdr
.crc
= htole32(crc32(0,
154 (uint8_t *)&ebhdr
.u
.nor_hdr
+ 4,
155 CHFS_EB_HDR_NOR_SIZE
- 4));
156 memcpy(buf
, &ebhdr
.u
.nor_hdr
, CHFS_EB_HDR_NOR_SIZE
);
159 buf_write(fsopts
, buf
, opts
->pagesize
);
164 write_vnode(fsinfo_t
*fsopts
, fsnode
*node
)
166 struct chfs_flash_vnode fvnode
;
167 memset(&fvnode
, 0, sizeof(fvnode
));
169 fvnode
.magic
= htole16(CHFS_FS_MAGIC_BITMASK
);
170 fvnode
.type
= htole16(CHFS_NODETYPE_VNODE
);
171 fvnode
.length
= htole32(CHFS_PAD(sizeof(fvnode
)));
172 fvnode
.hdr_crc
= htole32(crc32(0, (uint8_t *)&fvnode
,
173 CHFS_NODE_HDR_SIZE
- 4));
174 fvnode
.vno
= htole64(node
->inode
->ino
);
175 fvnode
.version
= htole64(version
++);
176 fvnode
.mode
= htole32(node
->inode
->st
.st_mode
);
177 fvnode
.dn_size
= htole32(node
->inode
->st
.st_size
);
178 fvnode
.atime
= htole32(node
->inode
->st
.st_atime
);
179 fvnode
.ctime
= htole32(node
->inode
->st
.st_ctime
);
180 fvnode
.mtime
= htole32(node
->inode
->st
.st_mtime
);
181 fvnode
.gid
= htole32(node
->inode
->st
.st_uid
);
182 fvnode
.uid
= htole32(node
->inode
->st
.st_gid
);
183 fvnode
.node_crc
= htole32(crc32(0, (uint8_t *)&fvnode
,
184 sizeof(fvnode
) - 4));
186 pad_block_if_less_than(fsopts
, sizeof(fvnode
));
187 buf_write(fsopts
, &fvnode
, sizeof(fvnode
));
192 write_dirent(fsinfo_t
*fsopts
, fsnode
*node
)
194 struct chfs_flash_dirent_node fdirent
;
197 name
= emalloc(strlen(node
->name
));
198 memcpy(name
, node
->name
, strlen(node
->name
));
200 memset(&fdirent
, 0, sizeof(fdirent
));
201 fdirent
.magic
= htole16(CHFS_FS_MAGIC_BITMASK
);
202 fdirent
.type
= htole16(CHFS_NODETYPE_DIRENT
);
203 fdirent
.length
= htole32(CHFS_PAD(sizeof(fdirent
) + strlen(name
)));
204 fdirent
.hdr_crc
= htole32(crc32(0, (uint8_t *)&fdirent
,
205 CHFS_NODE_HDR_SIZE
- 4));
206 fdirent
.vno
= htole64(node
->inode
->ino
);
207 if (node
->parent
!= NULL
) {
208 fdirent
.pvno
= htole64(node
->parent
->inode
->ino
);
210 fdirent
.pvno
= htole64(node
->inode
->ino
);
213 fdirent
.version
= htole64(version
++);
215 fdirent
.nsize
= htole32(strlen(name
));
216 fdirent
.dtype
= htole32(IFTOCHT(node
->type
& S_IFMT
));
217 fdirent
.name_crc
= htole32(crc32(0, (uint8_t *)name
, fdirent
.nsize
));
218 fdirent
.node_crc
= htole32(crc32(0, (uint8_t *)&fdirent
,
219 sizeof(fdirent
) - 4));
221 pad_block_if_less_than(fsopts
, sizeof(fdirent
) + fdirent
.nsize
);
222 buf_write(fsopts
, &fdirent
, sizeof(fdirent
));
223 buf_write(fsopts
, name
, fdirent
.nsize
);
228 write_file(fsinfo_t
*fsopts
, fsnode
*node
, const char *dir
)
232 char *name
= node
->name
;
235 uint32_t fileofs
= 0;
237 opts
= fsopts
->fs_specific
;
238 buf
= emalloc(opts
->pagesize
);
239 if (node
->type
== S_IFREG
|| node
->type
== S_IFSOCK
) {
241 if (asprintf(&longname
, "%s/%s", dir
, name
) == 1)
244 fd
= open(longname
, O_RDONLY
, 0444);
246 err(EXIT_FAILURE
, "Cannot open `%s'", longname
);
248 while ((len
= read(fd
, buf
, opts
->pagesize
))) {
250 warn("ERROR while reading %s", longname
);
257 write_data(fsopts
, node
, buf
, len
, fileofs
);
262 } else if (node
->type
== S_IFLNK
) {
263 len
= strlen(node
->symlink
);
264 memcpy(buf
, node
->symlink
, len
);
265 write_data(fsopts
, node
, buf
, len
, 0);
266 } else if (node
->type
== S_IFCHR
|| node
->type
== S_IFBLK
||
267 node
->type
== S_IFIFO
) {
269 memcpy(buf
, &(node
->inode
->st
.st_rdev
), len
);
270 write_data(fsopts
, node
, buf
, len
, 0);
276 err(EXIT_FAILURE
, "Memory allocation failed");
280 write_data(fsinfo_t
*fsopts
, fsnode
*node
, unsigned char *buf
, size_t len
,
283 struct chfs_flash_data_node fdata
;
285 memset(&fdata
, 0, sizeof(fdata
));
290 pad_block_if_less_than(fsopts
, sizeof(fdata
) + len
);
292 fdata
.magic
= htole16(CHFS_FS_MAGIC_BITMASK
);
293 fdata
.type
= htole16(CHFS_NODETYPE_DATA
);
294 fdata
.length
= htole32(CHFS_PAD(sizeof(fdata
) + len
));
295 fdata
.hdr_crc
= htole32(crc32(0, (uint8_t *)&fdata
,
296 CHFS_NODE_HDR_SIZE
- 4));
297 fdata
.vno
= htole64(node
->inode
->ino
);
298 fdata
.data_length
= htole32(len
);
299 fdata
.offset
= htole32(ofs
);
300 fdata
.data_crc
= htole32(crc32(0, (uint8_t *)buf
, len
));
301 fdata
.node_crc
= htole32(crc32(0,
302 (uint8_t *)&fdata
, sizeof(fdata
) - 4));
304 buf_write(fsopts
, &fdata
, sizeof(fdata
));
305 buf_write(fsopts
, buf
, len
);