diff options
author | Brad Bishop <bradleyb@us.ibm.com> | 2014-06-30 22:10:16 -0500 |
---|---|---|
committer | Patrick Williams <iawillia@us.ibm.com> | 2014-07-02 22:49:29 -0500 |
commit | bf4630076762d9c20c16c80c1c791f352b046dd1 (patch) | |
tree | efc67bad010a28fd1abf5aeeefda2a969514fd97 /ffs/test | |
download | ffs-bf4630076762d9c20c16c80c1c791f352b046dd1.tar.gz ffs-bf4630076762d9c20c16c80c1c791f352b046dd1.zip |
Port FFS tools over from Building Block repository.
Diffstat (limited to 'ffs/test')
-rw-r--r-- | ffs/test/Makefile | 8 | ||||
-rwxr-xr-x | ffs/test/ffs_tool_test.sh | 244 | ||||
-rwxr-xr-x | ffs/test/libffs_test.sh | 248 | ||||
-rw-r--r-- | ffs/test/test_libffs.c | 654 | ||||
-rw-r--r-- | ffs/test/test_libffs.h | 45 |
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; |