summaryrefslogtreecommitdiffstats
path: root/ffs/test
diff options
context:
space:
mode:
authorBrad Bishop <bradleyb@us.ibm.com>2014-06-30 22:10:16 -0500
committerPatrick Williams <iawillia@us.ibm.com>2014-07-02 22:49:29 -0500
commitbf4630076762d9c20c16c80c1c791f352b046dd1 (patch)
treeefc67bad010a28fd1abf5aeeefda2a969514fd97 /ffs/test
downloadffs-bf4630076762d9c20c16c80c1c791f352b046dd1.tar.gz
ffs-bf4630076762d9c20c16c80c1c791f352b046dd1.zip
Port FFS tools over from Building Block repository.
Diffstat (limited to 'ffs/test')
-rw-r--r--ffs/test/Makefile8
-rwxr-xr-xffs/test/ffs_tool_test.sh244
-rwxr-xr-xffs/test/libffs_test.sh248
-rw-r--r--ffs/test/test_libffs.c654
-rw-r--r--ffs/test/test_libffs.h45
5 files changed, 1199 insertions, 0 deletions
diff --git a/ffs/test/Makefile b/ffs/test/Makefile
new file mode 100644
index 0000000..37a4d0d
--- /dev/null
+++ b/ffs/test/Makefile
@@ -0,0 +1,8 @@
+DEPTH = ../../..
+include $(DEPTH)/integration/Rules.mk
+include $(DEPTH)/integration/Rules.ppc.mk
+
+ARCH=ppc
+TEST_LIBFFS_INSTALL = $(INST_TESTS)
+
+include ../Rules.test.mk
diff --git a/ffs/test/ffs_tool_test.sh b/ffs/test/ffs_tool_test.sh
new file mode 100755
index 0000000..37f5fe0
--- /dev/null
+++ b/ffs/test/ffs_tool_test.sh
@@ -0,0 +1,244 @@
+#!/bin/bash
+# ffs_tool_test.sh
+#
+# Test case to perform tests for supported options in ffs tool
+#
+# Author: Shekar Babu <shekbabu@in.ibm.com>
+#
+
+FFS_TOOL="ffs"
+NOR_IMAGE="/tmp/pnor"
+OFFSET="0x3F0000"
+SIZE="8MiB"
+BLOCK="64KiB"
+LOGICAL="logical"
+DATA="data"
+PAD="0xFF"
+
+create_dummy_file() {
+ echo Creating a dummy file $1 of size $2 with sample data $3
+ yes $3 | head -$2 > $1
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, creating dummy file $1
+ exit $RC
+ fi
+ echo Success, creating $1
+}
+
+create_nor_image() {
+
+ # Check if nor image already exist
+ if [ -f $1 ];then
+ rm $1
+ fi
+ echo Creating nor image $1
+ $FFS_TOOL --create $1 -p $2 -s $3 -b $4
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, creating $1 image
+ exit $RC
+ fi
+ echo Success, creating $1 image
+}
+
+add_logical_partition() {
+ echo Adding logical partition $3
+ echo $FFS_TOOL --add $1 -O $2 --flags 0x0 --pad $PAD -n $3 -t $4
+ $FFS_TOOL --add $1 -O $2 --flags 0x0 --pad $PAD -n $3 -t $4
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, adding $4 partition $3
+ exit $RC
+ fi
+ echo Success, adding $4 partition $3
+}
+
+add_data_partition() {
+ echo Adding data partition $3
+ echo $FFS_TOOL --add $1 -O $2 --flags 0x0 --pad $PAD -s $5 -o $6 -n $3 -t $4
+ $FFS_TOOL --add $1 -O $2 --flags 0x0 --pad $PAD -s $5 -o $6 -n $3 -t $4
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, adding $4 partition $3
+ exit $RC
+ fi
+ echo Success, adding $4 partition $3
+}
+
+read_partition_entry() {
+ echo Reading partition entry $3
+ echo $FFS_TOOL --read $1 -O $2 --name $3 -d $4 --force
+ $FFS_TOOL --read $1 -O $2 --name $3 -d $4 --force
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, reading partition entry $3
+ exit $RC
+ fi
+ echo Success, reading partition entry $3
+}
+
+write_partition_entry() {
+ echo Writing to partition entry $3
+ echo $FFS_TOOL --write $1 -O $2 --name $3 -d $4 --force
+ $FFS_TOOL --write $1 -O $2 --name $3 -d $4 --force
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, writing to partition entry $3
+ exit $RC
+ fi
+ echo Success, writing to partition entry $3
+}
+
+list_partition_table_entries() {
+ echo Listing partition table entries in $1
+ echo $FFS_TOOL --list $1 -O $2
+ $FFS_TOOL --list $1 -O $2
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, Listing partition table entries in $1
+ exit $RC
+ fi
+ echo Success, Listing partition table entries in $1
+}
+hexdump_partition_entry() {
+ echo Hexdump partition entry $3 into $4
+ echo "$FFS_TOOL --hexdump $1 -O $2 --name $3 > $4"
+ $FFS_TOOL --hexdump $1 -O $2 --name $3 > $4
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, hexdump partition entry $3 into $4
+ exit $RC
+ fi
+ echo Success, hexdump partition entry $3 into $4
+}
+
+delete_partition_entry() {
+ echo Delete partition entry $3
+ echo $FFS_TOOL --delete $1 -O $2 --name $3
+ $FFS_TOOL --delete $1 -O $2 --name $3
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, deleting partition entry $3
+ exit $RC
+ fi
+ echo Success, deleting partition entry $3
+}
+
+get_partition_entry_user_word() {
+ echo Get user word from partition entry $3
+ echo $FFS_TOOL --modify $1 -O $2 --name $3 -u $4
+ $FFS_TOOL --modify $1 -O $2 --name $3 -u $4 > /tmp/GETUW
+ sed 's/^\(.\)\{7\}//g' /tmp/GETUW > /tmp/chop_GETUW
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, Getting user word from partition entry $3
+ exit $RC
+ fi
+ echo Success, Getting user word from partition entry $3
+}
+
+put_partition_entry_user_word() {
+ echo Put user word to partition entry $3
+ echo $5 > /tmp/PUTUW
+ echo $FFS_TOOL --modify $1 -O $2 --name $3 -u $4 --value $5
+ $FFS_TOOL --modify $1 -O $2 --name $3 -u $4 --value $5
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, Putting user word to partition entry $3
+ exit $RC
+ fi
+ echo Success, Putting user word to partition entry $3
+}
+
+read_write_part_entry() {
+ write_partition_entry $1 $2 $3 $4
+ read_partition_entry $1 $2 $3 $5
+ cmp $4 $5 > /dev/null
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo FAIL, data read/write mismatch -- entry $3
+ exit $RC
+ fi
+ echo PASS, data read/write matches -- entry $3
+}
+
+get_put_user_word() {
+ put_partition_entry_user_word $1 $2 $3 $4 $5
+ get_partition_entry_user_word $1 $2 $3 $4
+ cmp /tmp/chop_GETUW /tmp/PUTUW > /dev/null
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo FAIL, user word get/put mismatch -- entry $3
+ exit $RC
+ fi
+ echo PASS, user word get/put matches -- entry $3
+ rm /tmp/GETUW /tmp/PUTUW /tmp/chop_GETUW
+}
+
+compare_hexdump() {
+ hexdump_partition_entry $1 $2 $3 $4
+ HEXFILE=/tmp/hex_sz0
+ stat -c %s $4 > $HEXFILE
+ if [[ -s $HEXFILE ]] ; then
+ echo PASS, hexdump test on entry $3
+ else
+ echo FAIL, hexdump test on entry $3
+ exit $RC
+ fi
+ rm $4 $HEXFILE
+}
+
+clean_data() {
+ rm $NOR_IMAGE /tmp/in_file /tmp/out_file
+ exit 0
+}
+
+# Main program starts
+
+# Create a dummy file as 'filename size data'
+create_dummy_file /tmp/in_file 131072 WELCOME
+
+# Create nor image
+create_nor_image $NOR_IMAGE $OFFSET $SIZE $BLOCK
+
+# Add logical partition
+add_logical_partition $NOR_IMAGE $OFFSET boot0 $LOGICAL
+
+# Creating data partition
+add_data_partition $NOR_IMAGE $OFFSET boot0/bootenv $DATA 1MiB 0M
+add_data_partition $NOR_IMAGE $OFFSET boot0/ipl $DATA 1MiB 2M
+add_data_partition $NOR_IMAGE $OFFSET boot0/spl $DATA 960K 3M
+# Add logical partition
+add_logical_partition $NOR_IMAGE $OFFSET boot1 $LOGICAL
+# Creating data partition
+add_data_partition $NOR_IMAGE $OFFSET boot1/uboot $DATA 1MiB 4M
+add_data_partition $NOR_IMAGE $OFFSET boot1/fsp $DATA 1MiB 6M
+add_data_partition $NOR_IMAGE $OFFSET boot1/bootfsp $DATA 960K 7M
+# Listing all created partition entries (logical+data)
+list_partition_table_entries $NOR_IMAGE $OFFSET
+
+# Perform read and write operations on all partition entries
+read_write_part_entry $NOR_IMAGE $OFFSET boot0/bootenv /tmp/in_file /tmp/out_file
+read_write_part_entry $NOR_IMAGE $OFFSET boot0/ipl /tmp/in_file /tmp/out_file
+read_write_part_entry $NOR_IMAGE $OFFSET boot1/uboot /tmp/in_file /tmp/out_file
+read_write_part_entry $NOR_IMAGE $OFFSET boot1/fsp /tmp/in_file /tmp/out_file
+
+# Perform get and put user words on all partition entries
+get_put_user_word $NOR_IMAGE $OFFSET boot0/bootenv 0 0x0000000a
+get_put_user_word $NOR_IMAGE $OFFSET boot0/ipl 1 0x0000000b
+get_put_user_word $NOR_IMAGE $OFFSET boot0/spl 2 0x0000000c
+get_put_user_word $NOR_IMAGE $OFFSET boot1/uboot 3 0x0000000d
+get_put_user_word $NOR_IMAGE $OFFSET boot1/fsp 4 0x0000000f
+
+# Hexdump partition entry
+compare_hexdump $NOR_IMAGE $OFFSET boot0/bootenv /tmp/hexdump
+
+# Delete a partition entry
+delete_partition_entry $NOR_IMAGE $OFFSET boot0/bootenv
+
+# Listing all created partition entries (logical+data)
+list_partition_table_entries $NOR_IMAGE $OFFSET
+
+# Clean/remove all temporary files
+clean_data
diff --git a/ffs/test/libffs_test.sh b/ffs/test/libffs_test.sh
new file mode 100755
index 0000000..a7e3adc
--- /dev/null
+++ b/ffs/test/libffs_test.sh
@@ -0,0 +1,248 @@
+#!/bin/bash
+# libffs_test.sh
+#
+# Test case to perform unit tests for all api's in libffs.so
+#
+# Author: Shekar Babu <shekbabu@in.ibm.com>
+#
+
+
+NOR_IMAGE=/tmp/sunray2.nor
+OFFSET=0
+#OFFSET=4128768
+SIZE=8388608
+#SIZE=67108864 #For 64MB nor
+BLOCK=65536
+LOGICAL=logical
+DATA=data
+
+create_dummy_file() {
+ echo Creating a dummy file $1 of size $2 with sample data $3
+ yes $3 | head -$2 > $1
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, creating dummy file $1
+ exit $RC
+ fi
+ echo Success, creating $1
+}
+
+create_nor_image() {
+ echo Creating nor image $1
+ echo test_libffs -c $1 -O $2 -s $3 -b $4
+ ./test_libffs -c $1 -O $2 -s $3 -b $4
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, creating $1 image
+ exit $RC
+ fi
+ echo Success, creating $1 image
+}
+
+add_logical_partition() {
+ echo Adding logical partition $3
+ echo test_libffs -a $1 -O $2 -n $3 -t $4
+ ./test_libffs -a $1 -O $2 -n $3 -t $4
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, adding $4 partition $3
+ exit $RC
+ fi
+ echo Success, adding $4 partition $3
+}
+
+add_data_partition() {
+ echo Adding data partition $3
+ echo test_libffs -a $1 -O $2 -n $3 -t $4 -s $5 -o $6
+ ./test_libffs -a $1 -O $2 -n $3 -t $4 -s $5 -o $6
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, adding $4 partition $3
+ exit $RC
+ fi
+ echo Success, adding $4 partition $3
+}
+
+read_partition_entry() {
+ echo Reading partition entry $3
+ echo test_libffs -r $1 -O $2 -n $3 -o $4
+ ./test_libffs -r $1 -O $2 -n $3 -o $4
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, reading partition entry $3
+ exit $RC
+ fi
+ echo Success, reading partition entry $3
+}
+
+write_partition_entry() {
+ echo Writing to partition entry $3
+ echo test_libffs -w $1 -O $2 -n $3 -i $4
+ ./test_libffs -w $1 -O $2 -n $3 -i $4 > /dev/null
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, writing to partition entry $3
+ exit $RC
+ fi
+ echo Success, writing to partition entry $3
+}
+
+list_partition_table_entries() {
+ echo Listing partition table entries in $1
+ echo test_libffs -l $1 -O $2
+ ./test_libffs -l $1 -O $2
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, Listing partition table entries in $1
+ exit $RC
+ fi
+ echo Success, Listing partition table entries in $1
+}
+hexdump_partition_entry() {
+ echo Hexdump partition entry $3 into $4
+ echo "test_libffs -h $1 -O $2 -n $3 > $4"
+ ./test_libffs -h $1 -O $2 -n $3 > $4
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, hexdump partition entry $3 into $4
+ exit $RC
+ fi
+ echo Success, hexdump partition entry $3 into $4
+}
+
+delete_partition_entry() {
+ echo Delete partition entry $3
+ echo test_libffs -d $1 -O $2 -n $3
+ ./test_libffs -d $1 -O $2 -n $3
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, deleting partition entry $3
+ exit $RC
+ fi
+ echo Success, deleting partition entry $3
+}
+
+get_partition_entry_user_word() {
+ echo Get user word from partition entry $3
+ echo test_libffs -m $1 -O $2 -n $3 -u $4 -g
+ ./test_libffs -m $1 -O $2 -n $3 -u $4 -g > /tmp/GETUW
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, Getting user word from partition entry $3
+ exit $RC
+ fi
+ echo Success, Getting user word from partition entry $3
+}
+
+put_partition_entry_user_word() {
+ echo Put user word to partition entry $3
+ echo test_libffs -m $1 -O $2 -n $3 -u $4 -p -v $5
+ ./test_libffs -m $1 -O $2 -n $3 -u $4 -p -v $5 > /tmp/PUTUW
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo Error, Putting user word to partition entry $3
+ exit $RC
+ fi
+ echo Success, Putting user word to partition entry $3
+}
+
+read_write_part_entry() {
+ write_partition_entry $1 $2 $3 $4
+ read_partition_entry $1 $2 $3 $5
+ cmp $4 $5 > /dev/null
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo FAIL, data read/write mismatch -- entry $3
+ exit $RC
+ fi
+ echo PASS, data read/write matches -- entry $3
+}
+
+get_put_user_word() {
+ put_partition_entry_user_word $1 $2 $3 $4 $5
+ get_partition_entry_user_word $1 $2 $3 $4
+ cmp /tmp/GETUW /tmp/PUTUW > /dev/null
+ RC=$?
+ if [ $RC -ne 0 ]; then
+ echo FAIL, user word get/put mismatch -- entry $3
+ exit $RC
+ fi
+ echo PASS, user word get/put matches -- entry $3
+ rm /tmp/GETUW /tmp/PUTUW
+}
+
+compare_hexdump() {
+ hexdump_partition_entry $1 $2 $3 $4
+ HEXFILE=/tmp/hex_sz0
+ stat -c %s $4 > $HEXFILE
+ if [[ -s $HEXFILE ]] ; then
+ echo PASS, hexdump test on entry $3
+ else
+ echo FAIL, hexdump test on entry $3
+ exit $RC
+ fi
+ rm $4 $HEXFILE
+}
+
+clean_data() {
+ rm $NOR_IMAGE /tmp/in_file /tmp/out_file
+ exit 0
+}
+
+# Main program starts
+
+# Create a dummy file as 'filename size data'
+create_dummy_file /tmp/in_file 131072 WELCOME
+
+# Create nor image
+create_nor_image $NOR_IMAGE $OFFSET $SIZE $BLOCK
+
+# Add logical partition
+add_logical_partition $NOR_IMAGE $OFFSET boot0 $LOGICAL
+# Creating data partition
+add_data_partition $NOR_IMAGE $OFFSET boot0/bootenv $DATA 1048576 65536
+add_data_partition $NOR_IMAGE $OFFSET boot0/ipl $DATA 1048576 2097152
+add_data_partition $NOR_IMAGE $OFFSET boot0/spl $DATA 1048576 3145728
+# Add logical partition
+add_logical_partition $NOR_IMAGE $OFFSET boot1 $LOGICAL
+# Creating data partition
+add_data_partition $NOR_IMAGE $OFFSET boot1/uboot $DATA 1048576 4194304
+add_data_partition $NOR_IMAGE $OFFSET boot1/fsp $DATA 1048576 5242880
+# Add logical partition
+add_logical_partition $NOR_IMAGE $OFFSET linux0 $LOGICAL
+# Creating data partition
+add_data_partition $NOR_IMAGE $OFFSET linux0/vpd $DATA 1048576 6291456
+add_data_partition $NOR_IMAGE $OFFSET linux0/hostboot $DATA 1048576 7340032
+
+# Listing all created partition entries (logical+data)
+list_partition_table_entries $NOR_IMAGE $OFFSET
+
+# Perform read and write operations on all partition entries
+read_write_part_entry $NOR_IMAGE $OFFSET boot0/bootenv /tmp/in_file /tmp/out_file
+read_write_part_entry $NOR_IMAGE $OFFSET boot0/ipl /tmp/in_file /tmp/out_file
+read_write_part_entry $NOR_IMAGE $OFFSET boot0/spl /tmp/in_file /tmp/out_file
+read_write_part_entry $NOR_IMAGE $OFFSET boot1/uboot /tmp/in_file /tmp/out_file
+read_write_part_entry $NOR_IMAGE $OFFSET boot1/fsp /tmp/in_file /tmp/out_file
+read_write_part_entry $NOR_IMAGE $OFFSET linux0/vpd /tmp/in_file /tmp/out_file
+read_write_part_entry $NOR_IMAGE $OFFSET linux0/hostboot /tmp/in_file /tmp/out_file
+
+# Perform get and put user words on all partition entries
+get_put_user_word $NOR_IMAGE $OFFSET boot0/bootenv 0 28
+get_put_user_word $NOR_IMAGE $OFFSET boot0/ipl 1 56
+get_put_user_word $NOR_IMAGE $OFFSET boot0/spl 2 96
+get_put_user_word $NOR_IMAGE $OFFSET boot1/uboot 3 16
+get_put_user_word $NOR_IMAGE $OFFSET boot1/fsp 4 84
+get_put_user_word $NOR_IMAGE $OFFSET linux0/vpd 8 64
+get_put_user_word $NOR_IMAGE $OFFSET linux0/hostboot 15 42
+
+# Hexdump partition entry
+compare_hexdump $NOR_IMAGE $OFFSET boot0/bootenv /tmp/hexdump
+
+# Delete a partition entry
+delete_partition_entry $NOR_IMAGE $OFFSET boot0/bootenv
+
+# Listing all created partition entries (logical+data)
+list_partition_table_entries $NOR_IMAGE $OFFSET
+
+# Clean/remove all temporary files
+clean_data
diff --git a/ffs/test/test_libffs.c b/ffs/test/test_libffs.c
new file mode 100644
index 0000000..f8c7966
--- /dev/null
+++ b/ffs/test/test_libffs.c
@@ -0,0 +1,654 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2012
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * File: test_libffs.c
+ * Author: Shekar Babu S <shekbabu@in.ibm.com>
+ * Descr: unit test tool for api's in libffs.so
+ * Date: 06/26/2012
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <clib/exception.h>
+#include <clib/attribute.h>
+#include <clib/assert.h>
+#include <clib/min.h>
+#include <sys/xattr.h>
+
+#include <clib/bb_trace.h>
+
+#include "test_libffs.h"
+
+FILE*
+log_open(void) {
+
+ FILE *logfile = NULL;
+ logfile = fopen("test_libffs.log", "w");
+ if (logfile == NULL) {
+ perror("logfile");
+ exit(EXIT_FAILURE);
+ }
+ setvbuf(logfile, NULL, _IOLBF, 0);
+ return logfile;
+}
+
+void
+create_regular_file(ffs_ops_t *ffs_ops) {
+ int rc = 0;
+ size_t size = ffs_ops->device_size;
+ mode_t mode = (S_IRUSR | S_IWUSR) | (S_IRGRP | S_IRGRP) | S_IROTH;
+
+ fprintf(ffs_ops->log, "%s: Creating regular file\n", __func__);
+
+ int fd = open(ffs_ops->nor_image, O_RDWR | O_CREAT | O_TRUNC, mode);
+ if (fd == -1) {
+ fprintf(ffs_ops->log, "%s: Error creating regular file '%s'",
+ __func__, ffs_ops->nor_image);
+ rc = FFS_ERROR;
+ return;
+ }
+
+ if (ftruncate(fd, size) != 0) {
+ fprintf(ffs_ops->log, "%s: Error truncating '%s'",
+ __func__, ffs_ops->nor_image);
+ rc = FFS_ERROR;
+ return;
+ }
+
+ uint32_t page_size = sysconf(_SC_PAGESIZE);
+ char buf[page_size];
+ memset(buf, 0xFF, page_size);
+
+ while (0 < size) {
+ ssize_t rc = write(fd, buf, min(sizeof(buf), size));
+ if (rc == -1) {
+ fprintf(ffs_ops->log, "%s: Error writing to '%s'",
+ __func__, ffs_ops->nor_image);
+ rc = FFS_ERROR;
+ return;
+ } else if(rc == 0) {
+ break;
+ }
+ size -= rc;
+ }
+
+ if(fd == 0) {
+ close(fd);
+ }
+}
+
+int
+create_partition(ffs_ops_t *ffs_ops) {
+
+ uint32_t rc = 0;
+ ffs_t *ffs = NULL;
+
+ create_regular_file(ffs_ops);
+
+ ffs = __ffs_create(ffs_ops->nor_image, ffs_ops->part_off,
+ ffs_ops->blk_sz,
+ ffs_ops->device_size / ffs_ops->blk_sz);
+
+ if(ffs != NULL) {
+ __ffs_close(ffs);
+ fprintf(ffs_ops->log, "%s: Creating pnor image '%s' success\n",
+ __func__, ffs_ops->nor_image);
+ } else {
+ fprintf(ffs_ops->log, "%s: Creating pnor image '%s' failed\n",
+ __func__, ffs_ops->nor_image);
+ rc = FFS_ERROR;
+ }
+
+ return rc;
+}
+
+int
+add_partition_entry(ffs_ops_t *ffs_ops) {
+
+ uint32_t rc = 0;
+ ffs_t *ffs = NULL;
+ ffs = __ffs_open(ffs_ops->nor_image, ffs_ops->part_off);
+ if(ffs != NULL) {
+ __ffs_entry_add(ffs, ffs_ops->part_entry, ffs_ops->entry_off,
+ ffs_ops->entry_sz, ffs_ops->type, 0x00);
+ __ffs_close(ffs);
+ fprintf(ffs_ops->log, "%s: Adding partition entry '%s' "
+ "success\n", __func__, ffs_ops->part_entry);
+ } else {
+ fprintf(ffs_ops->log, "%s: Adding partition entry '%s' "
+ "failed\n", __func__, ffs_ops->part_entry);
+ }
+ return rc;
+}
+
+uint32_t
+read_partition(ffs_ops_t *ffs_ops) {
+
+ uint32_t rc = 0;
+ ffs_t *ffs = NULL;
+
+ FILE *fp = fopen(ffs_ops->o_file, "w+");
+ if (fp == NULL) {
+ fprintf(ffs_ops->log, "%s: Error opening file '%s'", __func__,
+ ffs_ops->o_file);
+ rc = FFS_ERROR;
+ goto error;
+ }
+
+ ffs = __ffs_open(ffs_ops->nor_image, ffs_ops->part_off);
+ if(ffs == NULL) {
+ fprintf(ffs_ops->log, "%s: Error, opening nor "
+ "image '%s'\n", __func__, ffs_ops->nor_image);
+ rc = FFS_ERROR;
+ goto error;
+ }
+ fprintf(ffs_ops->log, "%s: Successfully opened "
+ "nor image\n", __func__);
+ ffs_entry_t entry;
+
+ if (__ffs_entry_find(ffs, ffs_ops->part_entry, &entry) == false) {
+ fprintf(ffs_ops->log, "%s: Error, '%s' not found\n", __func__,
+ ffs_ops->part_entry);
+ rc = FFS_ERROR;
+ goto error;
+ }
+
+ if(false) {
+error:
+ if(fp != NULL)
+ fclose(fp);
+ if(ffs != NULL)
+ __ffs_close(ffs);
+ return rc;
+ }
+
+ fprintf(ffs_ops->log, "%s: Finding entry '%s' success\n", __func__,
+ ffs_ops->part_entry);
+
+ uint32_t block_size = ffs->hdr->block_size;
+ char block[block_size];
+ memset(block, 0, block_size);
+
+ if (setvbuf(fp, NULL, _IOFBF, block_size) != 0) {
+ fprintf(ffs_ops->log, "%s: Error, setvbuf failed "
+ "%s (errno=%d)", __func__, strerror(errno), errno);
+ rc = FFS_ERROR;
+ goto out;
+ }
+
+ for (uint32_t i=0; i<entry.size; i++) {
+ size_t rc = __ffs_entry_read(ffs, ffs_ops->part_entry, block,
+ i * block_size, block_size);
+ if(rc != block_size) {
+ fprintf(ffs_ops->log, "%s: Error, ffs_entry_read"
+ " '%s'\n", __func__, ffs_ops->part_entry);
+ rc = FFS_ERROR;
+ goto out;
+ }
+
+ rc = fwrite(block, rc, 1, fp);
+ if (rc != 1) {
+ fprintf(ffs_ops->log, "%s: Error, fwrite "
+ "%s (errno=%d)\n", __func__,
+ strerror(ferror(fp)), ferror(fp));
+ rc = FFS_ERROR;
+ goto out;
+ }
+ else if (rc == 0)
+ break;
+ }
+
+ uint32_t bytes_read = entry.size * block_size;
+
+ fprintf(ffs_ops->log, "%s: Read %d bytes from partition '%s' Success\n",
+ __func__, bytes_read, ffs_ops->part_entry);
+
+ if (fclose(fp) == EOF) {
+ fprintf(ffs_ops->log, "%s: Error, flose '%s' "
+ "=> %s (errno=%d)", __func__, ffs_ops->o_file,
+ strerror(errno), errno);
+ fp = NULL;
+ rc = FFS_ERROR;
+ goto out;
+ }
+
+ __ffs_close(ffs);
+
+ fprintf(ffs_ops->log, "%s: Writing %d bytes from partition '%s' to "
+ "file '%s' Success\n", __func__, bytes_read,
+ ffs_ops->part_entry, ffs_ops->o_file);
+
+ if(false) {
+out:
+ if(fp != NULL)
+ fclose(fp);
+ if(ffs != NULL)
+ __ffs_close(ffs);
+ }
+ return rc;
+}
+
+uint32_t
+write_partition(ffs_ops_t * ffs_ops) {
+
+ struct stat st;
+ uint32_t rc = 0;
+ ffs_t * ffs = NULL;
+
+
+ if (stat(ffs_ops->i_file, &st) != 0) {
+ fprintf(ffs_ops->log, "%s: '%s' => %s (errno=%d)", __func__,
+ ffs_ops->i_file, strerror(errno), errno);
+ rc = FFS_ERROR;
+ goto error;
+ }
+
+ ffs = __ffs_open(ffs_ops->nor_image, ffs_ops->part_off);
+ if(ffs == NULL) {
+ fprintf(ffs_ops->log, "%s: Error, opening nor "
+ "image '%s'\n", __func__, ffs_ops->nor_image);
+ rc = FFS_ERROR;
+ goto error;
+ }
+
+ fprintf(ffs_ops->log, "%s: Successfully opened nor image '%s' for "
+ "writing\n", __func__, ffs_ops->nor_image);
+
+ ffs_entry_t entry;
+ if (__ffs_entry_find(ffs, ffs_ops->part_entry, &entry) == false) {
+ fprintf(ffs_ops->log, "%s: Error, '%s' not found\n", __func__,
+ ffs_ops->part_entry);
+ rc = FFS_ERROR;
+ goto error;
+ }
+
+ size_t entry_size = entry.size * ffs->hdr->block_size;
+
+
+ fprintf(ffs_ops->log, "%s: Found entry '%s' with size=%d\n", __func__,
+ ffs_ops->part_entry, entry_size);
+
+ if (entry_size < st.st_size) {
+ fprintf(ffs_ops->log, "%s: '%s' of size '%lld' too big for "
+ "partition '%s' of size '%d'\n", __func__,
+ ffs_ops->i_file, st.st_size, ffs_ops->nor_image,
+ entry_size);
+ rc = FFS_ERROR;
+ goto error;
+ }
+
+ FILE * fp = fopen(ffs_ops->i_file, "r+");
+ if (fp == NULL) {
+ fprintf(ffs_ops->log, "%s: Error opening file '%s'", __func__,
+ ffs_ops->i_file);
+ rc = FFS_ERROR;
+ goto error;
+ }
+
+ if(false) {
+error:
+ if(ffs != NULL)
+ __ffs_close(ffs);
+ return rc;
+ }
+
+ uint32_t block_size = ffs->hdr->block_size;
+ char block[block_size];
+
+ if (setvbuf(fp, NULL, _IOFBF, block_size) != 0) {
+ fprintf(ffs_ops->log, "%s: Error, setvbuf failed "
+ "%s (errno=%d)", __func__, strerror(errno), errno);
+ rc = FFS_ERROR;
+ goto out;
+ }
+
+ fprintf(ffs_ops->log, "%s: Writing data file into partition\n",
+ __func__);
+
+ for (uint32_t j=0; j<entry.size; j++) {
+ clearerr(fp);
+
+ size_t bytes_read = fread(block, 1, block_size, fp);
+ __ffs_entry_write(ffs, ffs_ops->part_entry, block,
+ j * block_size, bytes_read);
+ if (bytes_read == 0) {
+ int err = ferror(fp);
+ if (err) {
+ fprintf(ffs_ops->log, "%s: Error, setvbuf "
+ "failed %s (errno=%d)", __func__,
+ strerror(errno), errno);
+ rc = FFS_ERROR;
+ goto out;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ if (fclose(fp) == EOF) {
+ fprintf(ffs_ops->log, "%s: Error, flose '%s' "
+ "=> %s (errno=%d)", __func__, ffs_ops->o_file,
+ strerror(errno), errno);
+ fp = NULL;
+ rc = FFS_ERROR;
+ goto out;
+ }
+ fprintf(ffs_ops->log, "%s: Writing to partition '%s' from data file "
+ "'%s' Success\n", __func__, ffs_ops->part_entry,
+ ffs_ops->i_file);
+
+ if(false) {
+out:
+ __ffs_close(ffs);
+ }
+ return rc;
+}
+
+uint32_t
+list_partition(ffs_ops_t * ffs_ops) {
+
+ uint32_t rc = 0;
+ ffs_t * ffs = NULL;
+
+ ffs = __ffs_open(ffs_ops->nor_image, ffs_ops->part_off);
+ if(ffs == NULL) {
+ fprintf(ffs_ops->log, "%s: Error, opening nor "
+ "image '%s'\n", __func__, ffs_ops->nor_image);
+ fprintf(ffs_ops->log, "%s: Listing partition entries in '%s'"
+ " image failed\n", __func__, ffs_ops->nor_image);
+ rc = FFS_ERROR;
+ return rc;
+ }
+ //!< List all entries in the partition table
+ __ffs_list_entries(ffs, ".*", true, stdout);
+ fprintf(ffs_ops->log, "%s: Listing partition entries in '%s' image "
+ "success\n", __func__, ffs_ops->nor_image);
+
+ __ffs_close(ffs);
+
+ return rc;
+}
+
+uint32_t
+hexdump_entry(ffs_ops_t * ffs_ops) {
+
+ uint32_t rc = 0;
+ ffs_t * ffs = NULL;
+
+ ffs = __ffs_open(ffs_ops->nor_image, ffs_ops->part_off);
+ if(ffs == NULL) {
+ fprintf(ffs_ops->log, "%s: Error, opening nor "
+ "image '%s'\n", __func__, ffs_ops->nor_image);
+ fprintf(ffs_ops->log, "%s: Hexdump of partition entries in '%s'"
+ " image failed\n", __func__, ffs_ops->nor_image);
+ rc = FFS_ERROR;
+ return rc;
+ }
+ //!< Hexdump the entry in the partition table
+ __ffs_entry_hexdump(ffs, ffs_ops->part_entry, stdout);
+ fprintf(ffs_ops->log, "%s: Hexdump of partition entries in '%s' image "
+ "success\n", __func__, ffs_ops->nor_image);
+ __ffs_close(ffs);
+
+ return rc;
+}
+
+uint32_t
+delete_entry(ffs_ops_t * ffs_ops) {
+
+ uint32_t rc = 0;
+ ffs_t * ffs = NULL;
+
+ ffs = __ffs_open(ffs_ops->nor_image, ffs_ops->part_off);
+ if(ffs == NULL) {
+ fprintf(ffs_ops->log, "%s: Error, opening nor "
+ "image '%s'\n", __func__, ffs_ops->nor_image);
+ fprintf(ffs_ops->log, "%s: Delete entry '%s' failed\n",
+ __func__, ffs_ops->part_entry);
+ rc = FFS_ERROR;
+ return rc;
+ }
+ //!< Delete the entry from the partition table
+ __ffs_entry_delete(ffs, ffs_ops->part_entry);
+ fprintf(ffs_ops->log, "%s: Delete entry '%s' success\n", __func__,
+ ffs_ops->part_entry);
+
+ __ffs_close(ffs);
+
+ return rc;
+}
+
+uint32_t
+modify_entry_get(ffs_ops_t * ffs_ops) {
+
+ uint32_t rc = 0;
+ uint32_t value = 0;
+ ffs_t * ffs = NULL;
+
+ ffs = __ffs_open(ffs_ops->nor_image, ffs_ops->part_off);
+ if(ffs == NULL) {
+ fprintf(ffs_ops->log, "%s: Error, opening nor "
+ "image '%s'\n", __func__, ffs_ops->nor_image);
+ fprintf(ffs_ops->log, "%s: Get user word at '%d' failed\n",
+ __func__, ffs_ops->user);
+ rc = FFS_ERROR;
+ return rc;
+ }
+ //!< Get the user word at index
+ __ffs_entry_user_get(ffs, ffs_ops->part_entry, ffs_ops->user, &value);
+ fprintf(ffs_ops->log, "%s: Get user word at '%d' --> %x success\n",
+ __func__, ffs_ops->user, value);
+ //!< Required to check what is put
+ fprintf(stdout, "UW: %d-->%d\n", ffs_ops->user, value);
+
+ __ffs_close(ffs);
+
+ return rc;
+}
+
+uint32_t
+modify_entry_put(ffs_ops_t * ffs_ops) {
+
+ uint32_t rc = 0;
+ ffs_t * ffs = NULL;
+
+ ffs = __ffs_open(ffs_ops->nor_image, ffs_ops->part_off);
+ if(ffs == NULL) {
+ fprintf(ffs_ops->log, "%s: Error, opening nor "
+ "image '%s'\n", __func__, ffs_ops->nor_image);
+ fprintf(ffs_ops->log, "%s: Put user word at '%d' failed\n",
+ __func__, ffs_ops->user);
+ rc = FFS_ERROR;
+ return rc;
+ }
+ //!< Put the user word at index
+ __ffs_entry_user_put(ffs, ffs_ops->part_entry, ffs_ops->user,
+ ffs_ops->value);
+ fprintf(ffs_ops->log, "%s: Put user word at '%d' --> %d success\n",
+ __func__, ffs_ops->user, ffs_ops->value);
+ //!< Required to check what is get
+ fprintf(stdout, "UW: %d-->%d\n", ffs_ops->user, ffs_ops->value);
+
+ __ffs_close(ffs);
+
+ return rc;
+}
+
+void
+usage(void) {
+ printf("This program is a unit test tool, its callers responsibility "
+ "to pass the correct parameters.\nNote: No usage errors are "
+ "displayed, any mistake in params may result in unexpected "
+ "results\n");
+}
+
+int
+main(int argc, char * argv[]) {
+
+ int32_t rc = 0;
+ ffs_ops_t ffs_ops;
+
+ memset(&ffs_ops, 0, sizeof(ffs_ops_t));
+ ffs_ops.part_off = PART_OFFSET;
+ ffs_ops.log = log_open();
+
+ while ((argc > 1) && (argv[1][0] == '-'))
+ {
+ switch (argv[1][1])
+ {
+
+//test_libffs -c pnor -O part_offset -s dev_size -b block size
+//test_libffs -c pnor -O 4128768 -s 67108864 -b 65536
+ case 'c':
+ ffs_ops.nor_image = argv[2]; //!< nor image
+ ffs_ops.part_off = atoll(argv[4]);
+ ffs_ops.device_size = atoi(argv[6]);
+ ffs_ops.blk_sz = atoi(argv[8]);
+ rc = create_partition(&ffs_ops);
+ if(rc == FFS_ERROR) {
+ goto out;
+ }
+ break;
+//test_libffs -a pnor -O part_offset -n part_name -t part_type
+//test_libffs -a sunray.pnor -O 4128768 -n boot0 -t logical
+//test_libffs -a pnor -O part_off -n part_name -t type -s size -o entry_off
+//test_libffs -a sunray.pnor -O 4128768 -n boot0/bootenv -t data -s 1048576 -o 0
+ case 'a':
+ ffs_ops.nor_image = argv[2]; //!< nor image
+ ffs_ops.part_off = atoll(argv[4]);
+ ffs_ops.part_entry = argv[6];
+ if (!strcasecmp(argv[8], "logical")) {
+ ffs_ops.type = FFS_TYPE_LOGICAL;
+ ffs_ops.entry_sz = 0;
+ ffs_ops.entry_off = 0;
+ }
+ else if (!strcasecmp(argv[8], "data")) {
+ ffs_ops.type = FFS_TYPE_DATA;
+ ffs_ops.entry_sz = atol(argv[10]);
+ ffs_ops.entry_off = atoll(argv[12]);
+ }
+ rc = add_partition_entry(&ffs_ops);
+ if(rc == FFS_ERROR) {
+ goto out;
+ }
+ break;
+//test_libffs -r pnor -O part_off -n part_name -o out_file
+//test_libffs -r sunray.pnor -O 4128768 -n boot0/bootenv -o out_file
+ case 'r':
+ ffs_ops.nor_image = argv[2]; //!< nor image
+ ffs_ops.part_off = atoll(argv[4]);
+ ffs_ops.part_entry = argv[6]; //!< part entry
+ ffs_ops.o_file = argv[8]; //!< out put file
+ ffs_ops.i_file = NULL;
+ rc = read_partition(&ffs_ops);
+ if(rc == FFS_ERROR) {
+ goto out;
+ }
+ break;
+//test_libffs -w pnor -O part_off -n part_name -i in_file
+//test_libffs -w sunray.pnor -O 4128768 -n boot0/bootenv -i in_file
+ case 'w':
+ ffs_ops.nor_image = argv[2]; //!< nor image
+ ffs_ops.part_off = atoll(argv[4]);
+ ffs_ops.part_entry = argv[6]; //!< part entry
+ ffs_ops.i_file = argv[8]; //!< out put file
+ ffs_ops.o_file = NULL;
+ rc = write_partition(&ffs_ops);
+ if(rc == FFS_ERROR) {
+ goto out;
+ }
+//test_libffs -l pnor -O part_off
+//test_libffs -l sunray.pnor -O 4128768
+ case 'l':
+ ffs_ops.nor_image = argv[2]; //!< nor image
+ ffs_ops.part_off = atoll(argv[4]);
+ rc = list_partition(&ffs_ops);
+ if(rc == FFS_ERROR) {
+ goto out;
+ }
+ break;
+//test_libffs -h pnor -O part_off -n part_entry
+//test_libffs -h sunray.pnor -O 4128768 -n boot0/bootenv
+ case 'h':
+ ffs_ops.nor_image = argv[2]; //!< nor image
+ ffs_ops.part_off = atoll(argv[4]);
+ ffs_ops.part_entry = argv[6]; //!< part entry
+ rc = hexdump_entry(&ffs_ops);
+ if(rc == FFS_ERROR) {
+ goto out;
+ }
+ break;
+//test_libffs -d pnor -O part_off -n part_entry
+//test_libffs -d sunray.pnor -O 4128768 -n boot0/bootenv
+ case 'd':
+ ffs_ops.nor_image = argv[2]; //!< nor image
+ ffs_ops.part_off = atoll(argv[4]);
+ ffs_ops.part_entry = argv[6]; //!< part entry
+ rc = delete_entry(&ffs_ops);
+ if(rc == FFS_ERROR) {
+ goto out;
+ }
+ break;
+//test_libffs -m pnor -O part_off -n part_name -u index -g
+//test_libffs -m sunray.pnor -O 4128768 -n boot0/bootenv -u 0 -g
+//test_libffs -m pnor -O part_off -n part_name -u index -p -v some_value
+//test_libffs -m sunray.pnor -O 4128768 -n boot0/bootenv -u 0 -p -v 1024
+ case 'm':
+ ffs_ops.nor_image = argv[2]; //!< nor image
+ ffs_ops.part_off = atoll(argv[4]);
+ ffs_ops.part_entry = argv[6]; //!< part entry
+ ffs_ops.user = atol(argv[8]);
+ if(!strcmp(argv[9], "-g")) {
+ rc = modify_entry_get(&ffs_ops);
+ if(rc == FFS_ERROR) {
+ goto out;
+ }
+ } else if(!strcmp(argv[9], "-p")) {
+ ffs_ops.value = atol(argv[11]);
+ rc = modify_entry_put(&ffs_ops);
+ if(rc == FFS_ERROR) {
+ goto out;
+ }
+ }
+ break;
+ default:
+ usage();
+ break;
+ }
+ break;
+ }
+
+out:
+ if(ffs_ops.log != NULL) {
+ fclose(ffs_ops.log);
+ }
+ return rc;
+}
diff --git a/ffs/test/test_libffs.h b/ffs/test/test_libffs.h
new file mode 100644
index 0000000..c9ec613
--- /dev/null
+++ b/ffs/test/test_libffs.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2012
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * File: test_libffs.c
+ * Author: Shekar Babu S <shekbabu@in.ibm.com>
+ * Descr: unit test tool for api's in libffs.so
+ * Date: 06/26/2012
+ */
+
+#include "libffs.h"
+
+#define FFS_ERROR -1
+#define PART_OFFSET 0x3F0000
+
+typedef struct ffs_operations{
+ const char * nor_image; //!< Path to nor image special/regular file
+ const char * part_entry; //!< Logical partition/entry name
+ const char * i_file; //!< Input file
+ const char * o_file; //!< Output file
+ FILE * log; //!< Log file
+ size_t device_size;//!< Size of the nor flash
+ off_t part_off; //!< Offset of partition table
+ size_t blk_sz; //!< Block size
+ size_t entry_sz; //!< Partition entry size
+ off_t entry_off; //!< Offset of partition entry
+ uint32_t user; //!< Index to user word in any entry
+ uint32_t value; //!< User word at index in entry
+ ffs_type_t type; //!< Partition type
+} ffs_ops_t;
OpenPOWER on IntegriCloud