misc/172301: CRC32 feature in FreeBSD's boot loader

Boris Astardzhiev boris.astardzhiev at gmail.com
Wed Oct 3 11:00:24 UTC 2012


>Number:         172301
>Category:       misc
>Synopsis:       CRC32 feature in FreeBSD's boot loader
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Wed Oct 03 11:00:23 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator:     Boris Astardzhiev
>Release:        10.0-CURRENT
>Organization:
Smartcom Bulgaria AD
>Environment:
FreeBSD 10.0-CURRENT FreeBSD 10.0-CURRENT #0: Wed Jun 20 19:12:00 EEST 2012 /usr/obj/usr/src/sys/NANDFS i386
>Description:
I would like to contribute a new feature for the FreeBSD boot loader - a
command that calculates the CRC32 of a specified file name. It uses libz's CRC32
implementation.

While attempting to make libstand's nandfs to work adequately I've
experienced NAND flash page/block misreadings from U-Boot's API side. Therefore I was in a need of a tool that could prove that a file had been read correctly in this very stage of the FreeBSD boot process. So here it is.

In addition to the CRC calculation the size of the stipulated file is
printed as well.

Any comments will be appreciated - http://lists.freebsd.org/pipermail/freebsd-fs/2012-October/015288.html
>How-To-Repeat:
-
>Fix:
See patch.

Patch attached with submission follows:

diff --git a/lib/libstand/Makefile b/lib/libstand/Makefile
index fd720a9..4e77487 100644
--- a/lib/libstand/Makefile
+++ b/lib/libstand/Makefile
@@ -38,7 +38,7 @@ CFLAGS+=	-msoft-float -D_STANDALONE
 .endif
 
 # standalone components and stuff we have modified locally
-SRCS+=	gzguts.h zutil.h __main.c assert.c bcd.c bswap.c environment.c getopt.c gets.c \
+SRCS+=	gzguts.h zutil.h __main.c assert.c bcd.c bswap.c crc.c environment.c getopt.c gets.c \
 	globals.c pager.c printf.c strdup.c strerror.c strtol.c random.c \
 	sbrk.c twiddle.c zalloc.c zalloc_malloc.c
 
diff --git a/lib/libstand/crc.c b/lib/libstand/crc.c
new file mode 100644
index 0000000..331d390
--- /dev/null
+++ b/lib/libstand/crc.c
@@ -0,0 +1,125 @@
+/*-
+ * Copyright (c) 2012 Boris Astardzhiev / Smartcom Bulgaria AD
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Simple CRC calculation of a file.
+ */
+
+#include <sys/cdefs.h>
+#include "stand.h"
+#include <string.h>
+#include "../libz/zlib.h"
+
+/*
+ * Display checksum.
+ */
+
+int
+crc32_file(const char *fname)
+{
+	unsigned long 	crc = 0UL;
+	char 		buf[80];
+	size_t 		bytes;
+	int		fd;
+	int		res;
+	off_t 		end_off;
+	struct	stat 	st;
+
+	res = 0;
+	fd = open(fname, O_RDONLY);
+	if (fd == -1) {
+		printf("can't open '%s': %s\n", fname, strerror(errno));
+		res = -1;
+		return (res);
+	}
+	
+	/*
+	 * Check if it is a regular file.
+	 */
+	memset(&st, 0, sizeof(st));
+	if (fstat(fd, &st) == -1) {
+		printf("can't get statistics of '%s': %s\n", fname,
+		    strerror(errno));
+		close(fd);
+		res = -1;
+		return (res);
+	}
+
+	if (!(S_ISREG(st.st_mode))) {
+		printf("'%s' is not a regular file\n", fname);
+		close(fd);
+		res = -1;
+		return (res);
+	}
+
+	/* 
+	 * Grab file size. 
+	 */	
+	end_off = lseek(fd, 0, SEEK_END);
+	if (end_off == -1) {
+		printf("can't get end of '%s': %s\n", fname, strerror(errno));
+		close(fd);
+		res = -1;
+		return (res);
+	}
+	
+	if (lseek(fd, 0, SEEK_SET) == -1) {
+		printf("can't set offset to '%s': %s\n", fname,
+		    strerror(errno));
+		close(fd);
+		res = -1;
+		return (res);
+	}
+
+	/* 
+	 * Calculate checksum.
+	 */
+	crc = crc32(crc, 0, 0);
+	for (;;) {
+		bytes = read(fd, buf, sizeof(buf));
+		if (bytes < 0) {
+			res = -1;
+			break;
+		}
+
+		if (!bytes)
+			break;
+
+		crc = crc32(crc, buf, bytes);
+	}
+
+	if (!res) {
+		printf("file:   %s\n", fname);
+		printf("\t size: %llu\n", end_off);
+		printf("\tcrc32: 0x%08lx\n", crc);
+	} else
+		printf("can't calculate crc32 of '%s'\n", fname);
+
+	close(fd);
+
+	return (res);
+}
+
diff --git a/lib/libstand/stand.h b/lib/libstand/stand.h
index 10bb829..ff75bed 100644
--- a/lib/libstand/stand.h
+++ b/lib/libstand/stand.h
@@ -265,6 +265,9 @@ extern char	*optarg;			/* getopt(3) external variables */
 extern int	optind, opterr, optopt, optreset;
 extern int	getopt(int, char * const [], const char *);
 
+/* crc.c */
+extern int	crc32_file(const char *fname);
+
 /* pager.c */
 extern void	pager_open(void);
 extern void	pager_close(void);
diff --git a/sys/boot/common/commands.c b/sys/boot/common/commands.c
index 7fba019..c445d71 100644
--- a/sys/boot/common/commands.c
+++ b/sys/boot/common/commands.c
@@ -497,3 +497,20 @@ command_lsdev(int argc, char *argv[])
     return(CMD_OK);
 }
 
+/*
+ * Calculate CRC32 of a file.
+ */
+COMMAND_SET(crc32, "crc32", "calculate crc32 of a file", command_crc32);
+
+static int
+command_crc32(int argc, char *argv[])
+{
+    int i, res;
+
+    res = 0;
+    for (i = 1; (i < argc) && !res; i++)
+    	res |= crc32_file(argv[i]);
+
+    return (!res ? (CMD_OK) : (CMD_ERROR));
+}
+
diff --git a/sys/boot/common/loader.8 b/sys/boot/common/loader.8
index 7386f72..8ec9143 100644
--- a/sys/boot/common/loader.8
+++ b/sys/boot/common/loader.8
@@ -174,6 +174,8 @@ The behavior of this builtin is changed if
 .Xr loader.4th 8
 is loaded.
 .Pp
+.It Ic crc32
+Calculate CRC32 of a specified file.
 .It Ic echo Xo
 .Op Fl n
 .Op Aq message


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list