Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 2 Oct 2012 18:07:07 +0300
From:      Boris Astardzhiev <boris.astardzhiev@gmail.com>
To:        freebsd-fs@freebsd.org
Cc:        stanislav_galabov@smartcom.bg
Subject:   CRC32 feature in FreeBSD's boot loader
Message-ID:  <CAP=KkTx9x0WbTMUbxHKaGhnCj0vLWOSw15tD27KFbVdc6shefA@mail.gmail.com>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hello,

I'm not sure that this is the right mailing list but I couldn't find a
dedicated one.
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.

Greetings,
Boris Astardzhiev / Smartcom Bulgaria AD

[-- Attachment #2 --]
diff --git a/lib/libstand/Makefile b/lib/libstand/Makefile
index a26c51d..095f962 100644
--- a/lib/libstand/Makefile
+++ b/lib/libstand/Makefile
@@ -39,9 +39,9 @@ CFLAGS+=	-msoft-float -D_STANDALONE
 .endif
 
 # standalone components and stuff we have modified locally
-SRCS+=	zutil.h __main.c assert.c bcd.c bswap.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
+SRCS+=	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
 
 # private (pruned) versions of libc string functions
 SRCS+=	strcasecmp.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 20b717e..119c696 100644
--- a/lib/libstand/stand.h
+++ b/lib/libstand/stand.h
@@ -267,6 +267,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 b4fe118..fbbec66 100644
--- a/sys/boot/common/commands.c
+++ b/sys/boot/common/commands.c
@@ -496,3 +496,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 25d2270..95cc47b 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

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAP=KkTx9x0WbTMUbxHKaGhnCj0vLWOSw15tD27KFbVdc6shefA>