diff --git a/patches/barebox/v2014.04/0011-lib-sdb-and-sdb.h-from-fpga-config-space-sdbfs-commi.patch b/patches/barebox/v2014.04/0011-lib-sdb-and-sdb.h-from-fpga-config-space-sdbfs-commi.patch new file mode 100644 index 0000000000000000000000000000000000000000..dd70d9ff70085bd1b9185045b3029c866a6180d5 --- /dev/null +++ b/patches/barebox/v2014.04/0011-lib-sdb-and-sdb.h-from-fpga-config-space-sdbfs-commi.patch @@ -0,0 +1,827 @@ +From 5a35bbb8b324be0fe2b40113c26e1c1d9ca1374b Mon Sep 17 00:00:00 2001 +From: Alessandro Rubini <rubini@gnudd.com> +Date: Mon, 15 Sep 2014 09:54:24 +0200 +Subject: [PATCH 11/13] lib/sdb and sdb.h: from fpga-config-space/sdbfs, + commit 17445a2 + +Signed-off-by: Alessandro Rubini <rubini@gnudd.com> +--- + include/sdb.h | 159 ++++++++++++++++++++++++++ + lib/sdb/Makefile | 43 +++++++ + lib/sdb/Makefile.arch | 58 ++++++++++ + lib/sdb/access.c | 60 ++++++++++ + lib/sdb/check-endian | 24 ++++ + lib/sdb/glue.c | 234 +++++++++++++++++++++++++++++++++++++++ + lib/sdb/libsdbfs-freestanding.h | 19 ++++ + lib/sdb/libsdbfs-kernel.h | 35 ++++++ + lib/sdb/libsdbfs-user.h | 15 +++ + lib/sdb/libsdbfs.h | 87 +++++++++++++++ + 10 files changed, 734 insertions(+) + create mode 100644 include/sdb.h + create mode 100644 lib/sdb/Makefile + create mode 100644 lib/sdb/Makefile.arch + create mode 100644 lib/sdb/access.c + create mode 100755 lib/sdb/check-endian + create mode 100644 lib/sdb/glue.c + create mode 100644 lib/sdb/libsdbfs-freestanding.h + create mode 100644 lib/sdb/libsdbfs-kernel.h + create mode 100644 lib/sdb/libsdbfs-user.h + create mode 100644 lib/sdb/libsdbfs.h + +diff --git a/include/sdb.h b/include/sdb.h +new file mode 100644 +index 0000000..fbb76a4 +--- /dev/null ++++ b/include/sdb.h +@@ -0,0 +1,159 @@ ++/* ++ * This is the official version 1.1 of sdb.h ++ */ ++#ifndef __SDB_H__ ++#define __SDB_H__ ++#ifdef __KERNEL__ ++#include <linux/types.h> ++#else ++#include <stdint.h> ++#endif ++ ++/* ++ * All structures are 64 bytes long and are expected ++ * to live in an array, one for each interconnect. ++ * Most fields of the structures are shared among the ++ * various types, and most-specific fields are at the ++ * beginning (for alignment reasons, and to keep the ++ * magic number at the head of the interconnect record ++ */ ++ ++/* Product, 40 bytes at offset 24, 8-byte aligned ++ * ++ * device_id is vendor-assigned; version is device-specific, ++ * date is hex (e.g 0x20120501), name is UTF-8, blank-filled ++ * and not terminated with a 0 byte. ++ */ ++struct sdb_product { ++ uint64_t vendor_id; /* 0x18..0x1f */ ++ uint32_t device_id; /* 0x20..0x23 */ ++ uint32_t version; /* 0x24..0x27 */ ++ uint32_t date; /* 0x28..0x2b */ ++ uint8_t name[19]; /* 0x2c..0x3e */ ++ uint8_t record_type; /* 0x3f */ ++}; ++ ++/* ++ * Component, 56 bytes at offset 8, 8-byte aligned ++ * ++ * The address range is first to last, inclusive ++ * (for example 0x100000 - 0x10ffff) ++ */ ++struct sdb_component { ++ uint64_t addr_first; /* 0x08..0x0f */ ++ uint64_t addr_last; /* 0x10..0x17 */ ++ struct sdb_product product; /* 0x18..0x3f */ ++}; ++ ++/* Type of the SDB record */ ++enum sdb_record_type { ++ sdb_type_interconnect = 0x00, ++ sdb_type_device = 0x01, ++ sdb_type_bridge = 0x02, ++ sdb_type_integration = 0x80, ++ sdb_type_repo_url = 0x81, ++ sdb_type_synthesis = 0x82, ++ sdb_type_empty = 0xFF, ++}; ++ ++/* Type 0: interconnect (first of the array) ++ * ++ * sdb_records is the length of the table including this first ++ * record, version is 1. The bus type is enumerated later. ++ */ ++#define SDB_MAGIC 0x5344422d /* "SDB-" */ ++struct sdb_interconnect { ++ uint32_t sdb_magic; /* 0x00-0x03 */ ++ uint16_t sdb_records; /* 0x04-0x05 */ ++ uint8_t sdb_version; /* 0x06 */ ++ uint8_t sdb_bus_type; /* 0x07 */ ++ struct sdb_component sdb_component; /* 0x08-0x3f */ ++}; ++ ++/* Type 1: device ++ * ++ * class is 0 for "custom device", other values are ++ * to be standardized; ABI version is for the driver, ++ * bus-specific bits are defined by each bus (see below) ++ */ ++struct sdb_device { ++ uint16_t abi_class; /* 0x00-0x01 */ ++ uint8_t abi_ver_major; /* 0x02 */ ++ uint8_t abi_ver_minor; /* 0x03 */ ++ uint32_t bus_specific; /* 0x04-0x07 */ ++ struct sdb_component sdb_component; /* 0x08-0x3f */ ++}; ++ ++/* Type 2: bridge ++ * ++ * child is the address of the nested SDB table ++ */ ++struct sdb_bridge { ++ uint64_t sdb_child; /* 0x00-0x07 */ ++ struct sdb_component sdb_component; /* 0x08-0x3f */ ++}; ++ ++/* Type 0x80: integration ++ * ++ * all types with bit 7 set are meta-information, so ++ * software can ignore the types it doesn't know. Here we ++ * just provide product information for an aggregate device ++ */ ++struct sdb_integration { ++ uint8_t reserved[24]; /* 0x00-0x17 */ ++ struct sdb_product product; /* 0x08-0x3f */ ++}; ++ ++/* Type 0x81: Top module repository url ++ * ++ * again, an informative field that software can ignore ++ */ ++struct sdb_repo_url { ++ uint8_t repo_url[63]; /* 0x00-0x3e */ ++ uint8_t record_type; /* 0x3f */ ++}; ++ ++/* Type 0x82: Synthesis tool information ++ * ++ * this informative record ++ */ ++struct sdb_synthesis { ++ uint8_t syn_name[16]; /* 0x00-0x0f */ ++ uint8_t commit_id[16]; /* 0x10-0x1f */ ++ uint8_t tool_name[8]; /* 0x20-0x27 */ ++ uint32_t tool_version; /* 0x28-0x2b */ ++ uint32_t date; /* 0x2c-0x2f */ ++ uint8_t user_name[15]; /* 0x30-0x3e */ ++ uint8_t record_type; /* 0x3f */ ++}; ++ ++/* Type 0xff: empty ++ * ++ * this allows keeping empty slots during development, ++ * so they can be filled later with minimal efforts and ++ * no misleading description is ever shipped -- hopefully. ++ * It can also be used to pad a table to a desired length. ++ */ ++struct sdb_empty { ++ uint8_t reserved[63]; /* 0x00-0x3e */ ++ uint8_t record_type; /* 0x3f */ ++}; ++ ++/* The type of bus, for bus-specific flags */ ++enum sdb_bus_type { ++ sdb_wishbone = 0x00, ++ sdb_data = 0x01, ++}; ++ ++#define SDB_WB_WIDTH_MASK 0x0f ++#define SDB_WB_ACCESS8 0x01 ++#define SDB_WB_ACCESS16 0x02 ++#define SDB_WB_ACCESS32 0x04 ++#define SDB_WB_ACCESS64 0x08 ++#define SDB_WB_LITTLE_ENDIAN 0x80 ++ ++#define SDB_DATA_READ 0x04 ++#define SDB_DATA_WRITE 0x02 ++#define SDB_DATA_EXEC 0x01 ++ ++#endif /* __SDB_H__ */ +diff --git a/lib/sdb/Makefile b/lib/sdb/Makefile +new file mode 100644 +index 0000000..4699673 +--- /dev/null ++++ b/lib/sdb/Makefile +@@ -0,0 +1,43 @@ ++ ++LINUX ?= /lib/modules/$(shell uname -r)/build ++ ++# If we compile for the kernel, we need to include real kernel headers. ++# The thing is enough a mess that I moved it to a different file ++include Makefile.arch ++ ++ ++AS = $(CROSS_COMPILE)as ++LD = $(CROSS_COMPILE)ld ++CC = $(CROSS_COMPILE)gcc ++CPP = $(CC) -E ++AR = $(CROSS_COMPILE)ar ++NM = $(CROSS_COMPILE)nm ++STRIP = $(CROSS_COMPILE)strip ++OBJCOPY = $(CROSS_COMPILE)objcopy ++OBJDUMP = $(CROSS_COMPILE)objdump ++ ++# calculate endianness at compile time ++ENDIAN := $(shell ./check-endian $(CC)) ++ ++CFLAGS = -Wall -ggdb -O2 ++CFLAGS += -I../include/linux -I../include # for <sdb.h> ++CFLAGS += -ffunction-sections -fdata-sections ++CFLAGS += -Wno-pointer-sign ++CFLAGS += $(ENDIAN) $(LINUXINCLUDE) ++ ++ ++LIB = libsdbfs.a ++OBJS = glue.o access.o ++ ++all: $(LIB) ++ ++$(OBJS): $(wildcard *.h) ++ ++$(LIB): $(OBJS) ++ $(AR) r $@ $(OBJS) ++ ++clean: ++ rm -f $(OBJS) $(LIB) *~ core ++ ++# add the other unused targets, so the rule in ../Makefile works ++modules install modules_install: +diff --git a/lib/sdb/Makefile.arch b/lib/sdb/Makefile.arch +new file mode 100644 +index 0000000..12ca01c +--- /dev/null ++++ b/lib/sdb/Makefile.arch +@@ -0,0 +1,58 @@ ++ ++srctree = $(LINUX) ++ ++# ++# This set of contortions comes from the kernel Makefile. We need this ++# in order to properly compile libsdbfs for the kernel without being ++# in a kernel build environment (for example, to check for compile errors). ++# ++ ++ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ ++ -e s/arm.*/arm/ -e s/sa110/arm/ \ ++ -e s/s390x/s390/ -e s/parisc64/parisc/ \ ++ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ ++ -e s/sh[234].*/sh/ ) ++ ++SRCARCH := $(ARCH) ++ ++# Additional ARCH settings for x86 ++ifeq ($(ARCH),i386) ++ SRCARCH := x86 ++endif ++ifeq ($(ARCH),x86_64) ++ SRCARCH := x86 ++endif ++ ++# Additional ARCH settings for sparc ++ifeq ($(ARCH),sparc32) ++ SRCARCH := sparc ++endif ++ifeq ($(ARCH),sparc64) ++ SRCARCH := sparc ++endif ++ ++# Additional ARCH settings for sh ++ifeq ($(ARCH),sh64) ++ SRCARCH := sh ++endif ++ ++# Additional ARCH settings for tile ++ifeq ($(ARCH),tilepro) ++ SRCARCH := tile ++endif ++ifeq ($(ARCH),tilegx) ++ SRCARCH := tile ++endif ++ ++# Where to locate arch specific headers ++hdr-arch := $(SRCARCH) ++ ++ifeq ($(ARCH),m68knommu) ++ hdr-arch := m68k ++endif ++ ++# Use LINUXINCLUDE when you must reference the include/ directory. ++# Needed to be compatible with the O= option ++LINUXINCLUDE := -I$(srctree)/arch/$(hdr-arch)/include \ ++ -Iarch/$(hdr-arch)/include/generated \ ++ -I$(srctree)/include +diff --git a/lib/sdb/access.c b/lib/sdb/access.c +new file mode 100644 +index 0000000..93b5696 +--- /dev/null ++++ b/lib/sdb/access.c +@@ -0,0 +1,60 @@ ++/* ++ * Copyright (C) 2012,2013 CERN (www.cern.ch) ++ * Author: Alessandro Rubini <rubini@gnudd.com> ++ * ++ * Released according to the GNU GPL, version 2 or any later version. ++ * ++ * This work is part of the White Rabbit project, a research effort led ++ * by CERN, the European Institute for Nuclear Research. ++ */ ++ ++/* To avoid many #ifdef and associated mess, all headers are included there */ ++#include "libsdbfs.h" ++ ++int sdbfs_fstat(struct sdbfs *fs, struct sdb_device *record_return) ++{ ++ if (!fs->currentp) ++ return -ENOENT; ++ memcpy(record_return, fs->currentp, sizeof(*record_return)); ++ return 0; ++} ++ ++int sdbfs_fread(struct sdbfs *fs, int offset, void *buf, int count) ++{ ++ int ret; ++ ++ if (!fs->currentp) ++ return -ENOENT; ++ if (offset < 0) ++ offset = fs->read_offset; ++ if (offset + count > fs->f_len) ++ count = fs->f_len - offset; ++ ret = count; ++ if (fs->data) ++ memcpy(buf, fs->data + fs->f_offset + offset, count); ++ else ++ ret = fs->read(fs, fs->f_offset + offset, buf, count); ++ if (ret > 0) ++ fs->read_offset = offset + ret; ++ return ret; ++} ++ ++int sdbfs_fwrite(struct sdbfs *fs, int offset, void *buf, int count) ++{ ++ int ret; ++ ++ if (!fs->currentp) ++ return -ENOENT; ++ if (offset < 0) ++ offset = fs->read_offset; ++ if (offset + count > fs->f_len) ++ count = fs->f_len - offset; ++ ret = count; ++ if (fs->data) ++ memcpy(buf, fs->data + fs->f_offset + offset, count); ++ else ++ ret = fs->write(fs, fs->f_offset + offset, buf, count); ++ if (ret > 0) ++ fs->read_offset = offset + ret; ++ return ret; ++} +diff --git a/lib/sdb/check-endian b/lib/sdb/check-endian +new file mode 100755 +index 0000000..0c2acff +--- /dev/null ++++ b/lib/sdb/check-endian +@@ -0,0 +1,24 @@ ++#!/bin/bash ++ ++# Check endianness at compile time, so we can pass the -D to CFLAGS ++ ++CC=$1 ++if [ "x$CC" == "x" ]; then ++ echo "$0: pass the compiler path (\$CC) as argument" >& 2 ++ exit 1 ++fi ++ ++# Check endianness, by making an object file ++TMPC=$(mktemp /tmp/endian-c-XXXXXX) ++TMPO=$(mktemp /tmp/endian-o-XXXXXX) ++echo "int i = 0xbbee;" > $TMPC ++ ++$CC -x c -c $TMPC -o $TMPO ++OBJCOPY=$(echo $CC | sed 's/gcc$/objcopy/') ++if $OBJCOPY -O binary $TMPO /dev/stdout | od -t x1 -An | \ ++ grep -q 'bb ee'; then ++ echo " -DSDBFS_BIG_ENDIAN" ++else ++ echo " -DSDBFS_LITTLE_ENDIAN" ++fi ++rm -f $TMPC $TMPO +diff --git a/lib/sdb/glue.c b/lib/sdb/glue.c +new file mode 100644 +index 0000000..d8ef3cf +--- /dev/null ++++ b/lib/sdb/glue.c +@@ -0,0 +1,234 @@ ++/* ++ * Copyright (C) 2012,2014 CERN (www.cern.ch) ++ * Author: Alessandro Rubini <rubini@gnudd.com> ++ * ++ * Released according to the GNU GPL, version 2 or any later version. ++ * ++ * This work is part of the White Rabbit project, a research effort led ++ * by CERN, the European Institute for Nuclear Research. ++ */ ++ ++/* To avoid many #ifdef and associated mess, all headers are included there */ ++#include "libsdbfs.h" ++ ++static struct sdbfs *sdbfs_list; ++ ++/* All fields unused by the caller are expected to be zeroed */ ++int sdbfs_dev_create(struct sdbfs *fs, int verbose) ++{ ++ unsigned int magic; ++ ++ /* First, check we have the magic */ ++ if (fs->data) ++ magic = *(unsigned int *)(fs->data + fs->entrypoint); ++ else ++ fs->read(fs, fs->entrypoint, &magic, sizeof(magic)); ++ if (magic == SDB_MAGIC) { ++ /* Uh! If we are little-endian, we must convert */ ++ if (ntohl(1) != 1) ++ fs->flags |= SDBFS_F_CONVERT32; ++ } else if (htonl(magic) == SDB_MAGIC) { ++ /* ok, don't convert */ ++ } else { ++ return -ENOTDIR; ++ } ++ ++ if (verbose) ++ fs->flags |= SDBFS_F_VERBOSE; ++ fs->next = sdbfs_list; ++ sdbfs_list = fs; ++ ++ return 0; ++} ++ ++int sdbfs_dev_destroy(struct sdbfs *fs) ++{ ++ struct sdbfs **p; ++ ++ for (p = &sdbfs_list; *p && *p != fs; p = &(*p)->next) ++ ; ++ if (!*p) ++ return -ENOENT; ++ *p = fs->next; ++ return 0; ++} ++ ++struct sdbfs *sdbfs_dev_find(const char *name) ++{ ++ struct sdbfs *l; ++ ++ for (l = sdbfs_list; l && strcmp(l->name, name); l = l->next) ++ ; ++ if (!l) ++ return NULL; ++ return l; ++} ++ ++/* ++ * To open by name or by ID we need to scan the tree. The scan ++ * function is also exported in order for "sdb-ls" to use it ++ */ ++ ++static struct sdb_device *sdbfs_readentry(struct sdbfs *fs, ++ unsigned long offset) ++{ ++ /* ++ * This function reads an entry from a known good offset. It ++ * returns the pointer to the entry, which may be stored in ++ * the fs structure itself. Only touches fs->current_record. ++ */ ++ if (fs->data) { ++ if (!(fs->flags & SDBFS_F_CONVERT32)) ++ return (struct sdb_device *)(fs->data + offset); ++ /* copy to local storage for conversion */ ++ memcpy(&fs->current_record, fs->data + offset, ++ sizeof(fs->current_record)); ++ } else { ++ if (!fs->read) ++ return NULL; ++ fs->read(fs, offset, &fs->current_record, ++ sizeof(fs->current_record)); ++ } ++ ++ if (fs->flags & SDBFS_F_CONVERT32) { ++ uint32_t *p = (void *)&fs->current_record; ++ int i; ++ ++ for (i = 0; i < sizeof(fs->current_record) / sizeof(*p); i++) ++ p[i] = ntohl(p[i]); ++ } ++ ++ return &fs->current_record; ++} ++ ++/* Helper for scanning: we enter a new directory, and we must validate */ ++static struct sdb_device *scan_newdir(struct sdbfs *fs, int depth) ++{ ++ struct sdb_device *dev; ++ struct sdb_interconnect *intercon; ++ ++ dev = fs->currentp = sdbfs_readentry(fs, fs->this[depth]); ++ if (dev->sdb_component.product.record_type != sdb_type_interconnect) ++ return NULL; ++ ++ intercon = (typeof(intercon))dev; ++ if (ntohl(intercon->sdb_magic) != SDB_MAGIC) ++ return NULL; ++ ++ fs->nleft[depth] = ntohs(intercon->sdb_records) - 1; ++ fs->this[depth] += sizeof(*intercon); ++ fs->depth = depth; ++ return dev; ++} ++ ++struct sdb_device *sdbfs_scan(struct sdbfs *fs, int newscan) ++{ ++ /* ++ * This returns a pointer to the next sdb record, or the first one. ++ * Subdirectories (bridges) are returned before their contents. ++ * It only uses internal fields. ++ */ ++ struct sdb_device *dev; ++ struct sdb_bridge *bridge; ++ int depth, type, newdir = 0; /* check there's the magic */ ++ ++ if (newscan) { ++ fs->base[0] = 0; ++ fs->this[0] = fs->entrypoint; ++ depth = fs->depth = 0; ++ newdir = 1; ++ goto scan; ++ } ++ ++ /* If we already returned a bridge, go inside it (check type) */ ++ depth = fs->depth; ++ type = fs->currentp->sdb_component.product.record_type; ++ ++ if (type == sdb_type_bridge && depth + 1 < SDBFS_DEPTH) { ++ bridge = (typeof(bridge))fs->currentp; ++ fs->this[depth + 1] = fs->base[depth] ++ + ntohll(bridge->sdb_child); ++ fs->base[depth + 1] = fs->base[depth] ++ + ntohll(bridge->sdb_component.addr_first); ++ depth++; ++ newdir++; ++ } ++ ++scan: ++ /* If entering a new directory, verify magic and set nleft */ ++ if (newdir) { ++ dev = scan_newdir(fs, depth); ++ if (dev) ++ return dev; ++ /* Otherwise the directory is not there: no intercon */ ++ if (!depth) ++ return NULL; /* no entries at all */ ++ depth--; ++ } ++ ++ while (fs->nleft[depth] == 0) { ++ /* No more at this level, "cd .." if possible */ ++ if (!depth) ++ return NULL; ++ fs->depth = --depth; ++ } ++ ++ /* so, read the next entry */ ++ dev = fs->currentp = sdbfs_readentry(fs, fs->this[depth]); ++ fs->this[depth] += sizeof(*dev); ++ fs->nleft[depth]--; ++ return dev; ++} ++ ++static void __open(struct sdbfs *fs) ++{ ++ fs->f_offset = fs->base[fs->depth] ++ + htonll(fs->currentp->sdb_component.addr_first); ++ fs->f_len = htonll(fs->currentp->sdb_component.addr_last) ++ + 1 - htonll(fs->currentp->sdb_component.addr_first); ++ fs->read_offset = 0; ++} ++ ++int sdbfs_open_name(struct sdbfs *fs, const char *name) ++{ ++ struct sdb_device *d; ++ int len = strlen(name); ++ ++ if (len > 19) ++ return -ENOENT; ++ sdbfs_scan(fs, 1); /* new scan: get the interconnect and igore it */ ++ while ( (d = sdbfs_scan(fs, 0)) != NULL) { ++ if (strncmp(name, d->sdb_component.product.name, len)) ++ continue; ++ if (len < 19 && d->sdb_component.product.name[len] != ' ') ++ continue; ++ fs->currentp = d; ++ __open(fs); ++ return 0; ++ } ++ return -ENOENT; ++} ++ ++int sdbfs_open_id(struct sdbfs *fs, uint64_t vid, uint32_t did) ++{ ++ struct sdb_device *d; ++ ++ sdbfs_scan(fs, 1); /* new scan: get the interconnect and igore it */ ++ while ( (d = sdbfs_scan(fs, 0)) != NULL) { ++ if (vid != d->sdb_component.product.vendor_id) ++ continue; ++ if (did != d->sdb_component.product.device_id) ++ continue; ++ fs->currentp = d; ++ __open(fs); ++ return 0; ++ } ++ return -ENOENT; ++} ++ ++int sdbfs_close(struct sdbfs *fs) ++{ ++ fs->currentp = NULL; ++ return 0; ++} ++ +diff --git a/lib/sdb/libsdbfs-freestanding.h b/lib/sdb/libsdbfs-freestanding.h +new file mode 100644 +index 0000000..3f7868d +--- /dev/null ++++ b/lib/sdb/libsdbfs-freestanding.h +@@ -0,0 +1,19 @@ ++ ++/* Though freestanding, some minimal headers are expected to exist */ ++#include <stdlib.h> ++#include <stdint.h> ++#include <string.h> ++#include <errno.h> ++ ++#define SDB_KERNEL 0 ++#define SDB_USER 0 ++#define SDB_FREESTAND 1 ++ ++#ifdef SDBFS_BIG_ENDIAN ++# define ntohs(x) (x) ++# define htons(x) (x) ++# define ntohl(x) (x) ++# define htonl(x) (x) ++#else ++# error "No support, yet, for little-endian freestanding library" ++#endif +diff --git a/lib/sdb/libsdbfs-kernel.h b/lib/sdb/libsdbfs-kernel.h +new file mode 100644 +index 0000000..5f545e8 +--- /dev/null ++++ b/lib/sdb/libsdbfs-kernel.h +@@ -0,0 +1,35 @@ ++/* ++ * This supports both the Linux kernel and barebox, that is similar ++ * by design, and defines __KERNEL__ too. ++ */ ++#ifdef __BAREBOX__ ++# include <errno.h> ++#else /* really linux */ ++# include <linux/errno.h> ++#endif ++ ++#include <linux/types.h> ++#include <linux/string.h> ++#include <asm/byteorder.h> ++ ++/* ++ * The default installed /usr/include/linux stuff misses the __KERNEL__ parts. ++ * For libsdbfs it means we won't get uint32_t and similar types. ++ * ++ * So, check if we got the information we need before strange errors happen. ++ * The DECLARE_BITMAP macro is in <linux/types.h> since the epoch, but it ++ * is not installed in /usr/include/linux/types.h, so use it to check. ++ * ++ * If building for barebox, we miss the macro, but we are sure that ++ * we are picking the correct header, because the library is only built ++ * within the barebox source tree. ++ */ ++#if !defided(DECLARE_BITMAP) && !defined(__BAREBOX__) ++# error "Please point LINUX to a source tree if you define __KERNEL__" ++#endif ++ ++#define SDB_KERNEL 1 ++#define SDB_USER 0 ++#define SDB_FREESTAND 0 ++ ++#define sdb_print(format, ...) printk(format, __VA_ARGS__) +diff --git a/lib/sdb/libsdbfs-user.h b/lib/sdb/libsdbfs-user.h +new file mode 100644 +index 0000000..d54961c +--- /dev/null ++++ b/lib/sdb/libsdbfs-user.h +@@ -0,0 +1,15 @@ ++#ifndef __LIBSDBFS_USER_H__ ++#define __LIBSDBFS_USER_H__ ++ ++#include <stdio.h> ++#include <string.h> ++#include <errno.h> ++#include <arpa/inet.h> /* htonl */ ++ ++#define SDB_KERNEL 0 ++#define SDB_USER 1 ++#define SDB_FREESTAND 0 ++ ++#define sdb_print(format, ...) fprintf(stderr, format, __VA_ARGS__) ++ ++#endif /* __LIBSDBFS_USER_H__ */ +diff --git a/lib/sdb/libsdbfs.h b/lib/sdb/libsdbfs.h +new file mode 100644 +index 0000000..15325be +--- /dev/null ++++ b/lib/sdb/libsdbfs.h +@@ -0,0 +1,87 @@ ++#ifndef __LIBSDBFS_H__ ++#define __LIBSDBFS_H__ ++ ++/* The library can work in different environments, take care of them */ ++#ifdef __KERNEL__ ++# include "libsdbfs-kernel.h" ++#elif defined(__unix__) ++# include "libsdbfs-user.h" ++#else ++# include "libsdbfs-freestanding.h" ++#endif ++ ++#include <sdb.h> /* Please point your "-I" to some sensible place */ ++ ++#define SDBFS_DEPTH 4 /* Max number of subdirectory depth */ ++/* ++ * Data structures: please not that the library intself doesn't use ++ * malloc, so it's the caller who must deal withallocation/removal. ++ * For this reason we can have no opaque structures, but some fields ++ * are private ++ */ ++ ++struct sdbfs { ++ ++ /* Some fields are informative */ ++ char *name; /* may be null */ ++ void *drvdata; /* driver may need some detail.. */ ++ unsigned long blocksize; ++ unsigned long entrypoint; ++ ++ /* The "driver" must offer some methods */ ++ void *data; /* Use this if directly mapped */ ++ unsigned long datalen; /* Length of the above array */ ++ int (*read)(struct sdbfs *fs, int offset, void *buf, int count); ++ int (*write)(struct sdbfs *fs, int offset, void *buf, int count); ++ int (*erase)(struct sdbfs *fs, int offset, int count); ++ ++ /* All fields from here onwards are library-private */ ++ struct sdb_device *currentp; ++ struct sdb_device current_record; ++ unsigned long f_len; ++ unsigned long f_offset; /* start of file */ ++ unsigned long read_offset; /* current location */ ++ unsigned long flags; ++ struct sdbfs *next; ++ /* The following ones are directory-aware */ ++ unsigned long base[SDBFS_DEPTH]; /* for relative addresses */ ++ unsigned long this[SDBFS_DEPTH]; /* current sdb record */ ++ int nleft[SDBFS_DEPTH]; ++ int depth; ++}; ++ ++#define SDBFS_F_VERBOSE 0x0001 ++#define SDBFS_F_CONVERT32 0x0002 /* swap SDB words as they are read */ ++ ++ ++/* Defined in glue.c */ ++int sdbfs_dev_create(struct sdbfs *fs, int verbose); ++int sdbfs_dev_destroy(struct sdbfs *fs); ++struct sdbfs *sdbfs_dev_find(const char *name); ++int sdbfs_open_name(struct sdbfs *fs, const char *name); ++int sdbfs_open_id(struct sdbfs *fs, uint64_t vid, uint32_t did); ++int sdbfs_close(struct sdbfs *fs); ++struct sdb_device *sdbfs_scan(struct sdbfs *fs, int newscan); ++ ++/* Defined in access.c */ ++int sdbfs_fstat(struct sdbfs *fs, struct sdb_device *record_return); ++int sdbfs_fread(struct sdbfs *fs, int offset, void *buf, int count); ++int sdbfs_fwrite(struct sdbfs *fs, int offset, void *buf, int count); ++ ++/* This is needed to convert endianness. Hoping it is not defined elsewhere */ ++static inline uint64_t htonll(uint64_t ll) ++{ ++ uint64_t res; ++ ++ if (htonl(1) == 1) ++ return ll; ++ res = htonl(ll >> 32); ++ res |= (uint64_t)(htonl((uint32_t)ll)) << 32; ++ return res; ++} ++static inline uint64_t ntohll(uint64_t ll) ++{ ++ return htonll(ll); ++} ++ ++#endif /* __LIBSDBFS_H__ */ +-- +1.7.10.4 + diff --git a/patches/barebox/v2014.04/0012-lib-sdb-bb-fixes-to-be-ported-in-fpga-config-space.patch b/patches/barebox/v2014.04/0012-lib-sdb-bb-fixes-to-be-ported-in-fpga-config-space.patch new file mode 100644 index 0000000000000000000000000000000000000000..1167b7dcace0a61405b6098690fb5a59bf531848 --- /dev/null +++ b/patches/barebox/v2014.04/0012-lib-sdb-bb-fixes-to-be-ported-in-fpga-config-space.patch @@ -0,0 +1,41 @@ +From 2a346543d6cb16c4e7e638641cc947c73fb43068 Mon Sep 17 00:00:00 2001 +From: Alessandro Rubini <rubini@gnudd.com> +Date: Mon, 15 Sep 2014 11:40:01 +0200 +Subject: [PATCH 12/14] lib/sdb: bb fixes (to be ported in fpga-config-space) + +Signed-off-by: Alessandro Rubini <rubini@gnudd.com> +--- + lib/sdb/libsdbfs-kernel.h | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/lib/sdb/libsdbfs-kernel.h b/lib/sdb/libsdbfs-kernel.h +index 16e359e..a121d0e 100644 +--- a/lib/sdb/libsdbfs-kernel.h ++++ b/lib/sdb/libsdbfs-kernel.h +@@ -1,7 +1,11 @@ + + #include <linux/types.h> + #include <linux/string.h> +-#include <linux/errno.h> ++#ifdef __BAREBOX__ ++# include <errno.h> ++#else /* really linux */ ++# include <linux/errno.h> ++#endif + #include <asm/byteorder.h> + + /* +@@ -13,7 +17,9 @@ + * is not installed in /usr/include/linux/types.h, so use it to check. + */ + #ifndef DECLARE_BITMAP +-# error "Please point LINUX to a source tree if you define __KERNEL__" ++# ifndef __BAREBOX__ /* Barebox looks like the kernel and misses the define */ ++# error "Please point LINUX to a source tree if you define __KERNEL__" ++# endif + #endif + + #define SDB_KERNEL 1 +-- +1.7.10.4 + diff --git a/patches/barebox/v2014.04/0012-libsdb-integrate-in-build-system.patch b/patches/barebox/v2014.04/0012-libsdb-integrate-in-build-system.patch new file mode 100644 index 0000000000000000000000000000000000000000..9fc44d1c4e8ce7cf1516638a58261e04c3f8ffad --- /dev/null +++ b/patches/barebox/v2014.04/0012-libsdb-integrate-in-build-system.patch @@ -0,0 +1,87 @@ +From 55893c8ebab97be71eacc2f4814a2b41616ec7c1 Mon Sep 17 00:00:00 2001 +From: Alessandro Rubini <rubini@gnudd.com> +Date: Mon, 15 Sep 2014 11:40:34 +0200 +Subject: [PATCH 12/13] libsdb: integrate in build system + +Signed-off-by: Alessandro Rubini <rubini@gnudd.com> +--- + lib/Kconfig | 3 +++ + lib/Makefile | 1 + + lib/sdb/Makefile | 44 +------------------------------------------- + 3 files changed, 5 insertions(+), 43 deletions(-) + +diff --git a/lib/Kconfig b/lib/Kconfig +index d9ad4aa..7a2884e 100644 +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -47,6 +47,9 @@ config LIBUBIGEN + config LIBMTD + bool + ++config LIBSDB ++ bool ++ + config STMP_DEVICE + bool + +diff --git a/lib/Makefile b/lib/Makefile +index e8769a9..d4295fe 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -44,3 +44,4 @@ obj-y += gui/ + obj-$(CONFIG_XYMODEM) += xymodem.o + obj-y += unlink-recursive.o + obj-$(CONFIG_STMP_DEVICE) += stmp-device.o ++obj-$(CONFIG_LIBSDB) += sdb/ +diff --git a/lib/sdb/Makefile b/lib/sdb/Makefile +index 4699673..d3f06a4 100644 +--- a/lib/sdb/Makefile ++++ b/lib/sdb/Makefile +@@ -1,43 +1 @@ +- +-LINUX ?= /lib/modules/$(shell uname -r)/build +- +-# If we compile for the kernel, we need to include real kernel headers. +-# The thing is enough a mess that I moved it to a different file +-include Makefile.arch +- +- +-AS = $(CROSS_COMPILE)as +-LD = $(CROSS_COMPILE)ld +-CC = $(CROSS_COMPILE)gcc +-CPP = $(CC) -E +-AR = $(CROSS_COMPILE)ar +-NM = $(CROSS_COMPILE)nm +-STRIP = $(CROSS_COMPILE)strip +-OBJCOPY = $(CROSS_COMPILE)objcopy +-OBJDUMP = $(CROSS_COMPILE)objdump +- +-# calculate endianness at compile time +-ENDIAN := $(shell ./check-endian $(CC)) +- +-CFLAGS = -Wall -ggdb -O2 +-CFLAGS += -I../include/linux -I../include # for <sdb.h> +-CFLAGS += -ffunction-sections -fdata-sections +-CFLAGS += -Wno-pointer-sign +-CFLAGS += $(ENDIAN) $(LINUXINCLUDE) +- +- +-LIB = libsdbfs.a +-OBJS = glue.o access.o +- +-all: $(LIB) +- +-$(OBJS): $(wildcard *.h) +- +-$(LIB): $(OBJS) +- $(AR) r $@ $(OBJS) +- +-clean: +- rm -f $(OBJS) $(LIB) *~ core +- +-# add the other unused targets, so the rule in ../Makefile works +-modules install modules_install: ++obj-y += glue.o access.o +-- +1.7.10.4 + diff --git a/patches/barebox/v2014.04/0013-commands-add-sdb-commands-to-list-read-setvar.patch b/patches/barebox/v2014.04/0013-commands-add-sdb-commands-to-list-read-setvar.patch new file mode 100644 index 0000000000000000000000000000000000000000..1c063f4db8f2062d92dc9a0d0755aa22daafcdd9 --- /dev/null +++ b/patches/barebox/v2014.04/0013-commands-add-sdb-commands-to-list-read-setvar.patch @@ -0,0 +1,244 @@ +From e5312e4e8b58dfe5480b6bd3e22470527cfb85f7 Mon Sep 17 00:00:00 2001 +From: Alessandro Rubini <rubini@gnudd.com> +Date: Mon, 15 Sep 2014 11:40:59 +0200 +Subject: [PATCH 13/13] commands: add sdb commands to list, read, setvar + +Signed-off-by: Alessandro Rubini <rubini@gnudd.com> +--- + commands/Kconfig | 7 ++ + commands/Makefile | 1 + + commands/sdb.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 200 insertions(+) + create mode 100644 commands/sdb.c + +diff --git a/commands/Kconfig b/commands/Kconfig +index 352e8bf..89cadec 100644 +--- a/commands/Kconfig ++++ b/commands/Kconfig +@@ -756,6 +756,13 @@ config CMD_DETECT + actual probe of the client devices until they are needed. Use the + 'detect' command on the physical device to trigger probing. + ++config CMD_SDB ++ bool ++ select LIBSDB ++ prompt "commands for reading SDB information" ++ help ++ This enables "sdbinfo", "sdbset" and "sdbread". ++ + menuconfig CMD_WD + bool + depends on WATCHDOG +diff --git a/commands/Makefile b/commands/Makefile +index 91ec0e9..e97291e 100644 +--- a/commands/Makefile ++++ b/commands/Makefile +@@ -91,6 +91,7 @@ obj-$(CONFIG_CMD_FILETYPE) += filetype.o + obj-$(CONFIG_CMD_BAREBOX_UPDATE)+= barebox-update.o + obj-$(CONFIG_CMD_MIITOOL) += miitool.o + obj-$(CONFIG_CMD_DETECT) += detect.o ++obj-$(CONFIG_CMD_SDB) += sdb.o + obj-$(CONFIG_CMD_BOOT) += boot.o + obj-$(CONFIG_CMD_DEVINFO) += devinfo.o + obj-$(CONFIG_CMD_READF) += readf.o +diff --git a/commands/sdb.c b/commands/sdb.c +new file mode 100644 +index 0000000..e0cd5a4 +--- /dev/null ++++ b/commands/sdb.c +@@ -0,0 +1,192 @@ ++/* ++ * Copyright (c) 2014 CERN. ++ * Author: Alessandro Rubini for BE-CO-HT (White Rabbit project) ++ * ++ * Please use according to GNU GPL 2 or later ++ */ ++#include <common.h> ++#include <command.h> ++#include <init.h> ++#include <malloc.h> ++#include <errno.h> ++#include <fs.h> ++#include <fcntl.h> ++#include <xfuncs.h> ++#include <getopt.h> ++#include <environment.h> ++ ++#include <../lib/sdb/libsdbfs.h> /* hackish */ ++ ++#define BUFSIZE 1024 /* like cat.c in this directory */ ++ ++/* This is the drvdata in the SDB information */ ++struct bb_sdb_drvdata { ++ int fd; ++}; ++ ++static struct bb_sdb_drvdata drvdata; ++ ++/* and how to read the thing: use straight barebox POSIX interface */ ++static int bb_sdb_read(struct sdbfs *fs, int offset, void *buf, int count) ++{ ++ struct bb_sdb_drvdata *dd = fs->drvdata; ++ int fd = dd->fd; ++ ++ if (lseek(fd, offset, SEEK_SET) < 0) ++ return -1; ++ return read(fd, buf, count); ++} ++ ++static struct sdbfs bb_sdb_instance = { ++ .drvdata = &drvdata, ++ .entrypoint = 0, /* unfortunately: to be fixed */ ++ .read = bb_sdb_read, ++}; ++ ++/* The subcommands, assuming the device is opened and closed by the caller */ ++static int bb_sdb_ls(void) ++{ ++ struct sdb_device *d; ++ struct sdb_product *p; ++ struct sdb_component *c; ++ int new = 1; ++ ++ while ( (d = sdbfs_scan(&bb_sdb_instance, new)) != NULL) { ++ new = 0; /* for next time */ ++ ++ c = &d->sdb_component; ++ p = &c->product; ++ ++ printf("%016llx:%08x @ %08llx-%08llx ", ++ ntohll(p->vendor_id), ntohl(p->device_id), ++ ntohll(c->addr_first), ntohll(c->addr_last)); ++ printf("%.19s\n", p->name); ++ } ++ return 0; ++} ++ ++static int bb_sdb_cat(char *sdbfile) ++{ char *buf; ++ int i, j; ++ ++ /* ++ * Read a file, skipping trailing 0x00 or 0xff bytes, as a convenience. ++ * The function is based on bb::commands/cat (Sascha Hauer) ++ */ ++ i = sdbfs_open_name(&bb_sdb_instance, sdbfile); ++ if (i < 0) { ++ printf("can't open \"%s\" in SDB device\n", sdbfile); ++ return COMMAND_ERROR; ++ } ++ buf = xmalloc(BUFSIZE); ++ ++ while ( (i = sdbfs_fread(&bb_sdb_instance, -1, buf, BUFSIZE)) > 0) { ++ ++ /* trim trailing garbage as the file is assumed to be text */ ++ j = i - 1; ++ while (j > 0 && (buf[j] == 0xff || buf[j] == 0x00)) ++ j--; ++ for (i = 0; i <= j; i++) ++ putchar(buf[i]); ++ /* no ctrl-C support; this is expected to be fast */ ++ } ++ /* most files have the trailing newline already, avoid adding it */ ++ free(buf); ++ sdbfs_close(&bb_sdb_instance); ++ return 0; ++} ++ ++static int bb_sdb_set(char *varname, char *sdbfile) ++{ ++ char *buf; ++ int i; ++ ++ i = sdbfs_open_name(&bb_sdb_instance, sdbfile); ++ if (i < 0) { ++ printf("can't open \"%s\" in SDB device\n", sdbfile); ++ return COMMAND_ERROR; ++ } ++ buf = xmalloc(BUFSIZE); ++ i = sdbfs_fread(&bb_sdb_instance, -1, buf, BUFSIZE); ++ sdbfs_close(&bb_sdb_instance); ++ ++ while (i > 0 && (buf[i - 1] == 0xff || buf[i - 1] == 0x00)) { ++ /* trim trailing garbage as the file is assumed to be text */ ++ i--; ++ } ++ if (i > 0 && buf[i - 1] == '\n') ++ i--; /* remove trailing newline too */ ++ buf[i] = '\0'; ++ setenv(varname, buf); ++ free(buf); ++ sdbfs_close(&bb_sdb_instance); ++ return 0; ++} ++ ++ ++/* And finally the real command */ ++static int do_sdb(int argc, char *argv[]) ++{ ++ unsigned long entrypoint = 0; ++ int fd, ret, opt; ++ ++ while ((opt = getopt(argc, argv, "e:")) > 0) { ++ switch (opt) { ++ case 'e': ++ entrypoint = simple_strtoul(optarg, NULL, 0); ++ break; ++ default: ++ return COMMAND_ERROR_USAGE; ++ } ++ } ++ argc -= (optind - 1); ++ argv += (optind - 1); ++ if (argc < 3) ++ return COMMAND_ERROR_USAGE; ++ ++ /* for all subcommands we neet to create the device */ ++ fd = open(argv[2], O_RDONLY); ++ ++ if (fd < 0) { ++ printf("could not open %s: %s\n", argv[2], errno_str()); ++ return fd; ++ } ++ drvdata.fd = fd; ++ bb_sdb_instance.entrypoint = entrypoint; ++ ret = sdbfs_dev_create(&bb_sdb_instance, 0 /* not verbose */); ++ if (ret != 0) { ++ printf("Error accessing SDB filesystem in \"%s\"\n", ++ argv[2]); ++ return COMMAND_ERROR; ++ } ++ ++ /* now do the three subcommands */ ++ ret = COMMAND_ERROR_USAGE; ++ if (!strcmp(argv[1], "ls")) { ++ if (argc == 3) ++ ret = bb_sdb_ls(); ++ } else if (!strcmp(argv[1], "cat")) { ++ if (argc == 4) ++ ret = bb_sdb_cat(argv[3]); ++ } else if (!strcmp(argv[1], "set")) { ++ if (argc == 4 || argc == 5) ++ ret = bb_sdb_set(argv[3], argv[4] ?: argv[3]); ++ } ++ sdbfs_dev_destroy(&bb_sdb_instance); ++ return ret; ++} ++ ++ ++ ++static const __maybe_unused char cmd_sdb_help[] = ++"Usage: sdb [options] <command> <dev> [<sdbfile>]" ++"\n" ++"\"sdb [-e <entrypoint>] ls <dev>\" lists device content\n" ++"\"sdb [-e <entrypoint>] cat <dev> <sdbfile>\" prints a file\n" ++"\"sdb [-e <entrypoint>] set <dev> <varname> [<file>]\" sets var from SDB\n"; ++ ++BAREBOX_CMD_START(sdb) ++ .cmd = do_sdb, ++ .usage = "read/use SDB information in device", ++ BAREBOX_CMD_HELP(cmd_sdb_help) ++BAREBOX_CMD_END +-- +1.7.10.4 + diff --git a/patches/barebox/v2014.04/0013-libsdb-integrate-in-build-system.patch b/patches/barebox/v2014.04/0013-libsdb-integrate-in-build-system.patch new file mode 100644 index 0000000000000000000000000000000000000000..98dab817b3040b0f0e78a6d3a3838e1384287591 --- /dev/null +++ b/patches/barebox/v2014.04/0013-libsdb-integrate-in-build-system.patch @@ -0,0 +1,87 @@ +From a6e098cc24afd466441dbec4e7843dc04717e672 Mon Sep 17 00:00:00 2001 +From: Alessandro Rubini <rubini@gnudd.com> +Date: Mon, 15 Sep 2014 11:40:34 +0200 +Subject: [PATCH 13/14] libsdb: integrate in build system + +Signed-off-by: Alessandro Rubini <rubini@gnudd.com> +--- + lib/Kconfig | 3 +++ + lib/Makefile | 1 + + lib/sdb/Makefile | 44 +------------------------------------------- + 3 files changed, 5 insertions(+), 43 deletions(-) + +diff --git a/lib/Kconfig b/lib/Kconfig +index d9ad4aa..7a2884e 100644 +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -47,6 +47,9 @@ config LIBUBIGEN + config LIBMTD + bool + ++config LIBSDB ++ bool ++ + config STMP_DEVICE + bool + +diff --git a/lib/Makefile b/lib/Makefile +index e8769a9..d4295fe 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -44,3 +44,4 @@ obj-y += gui/ + obj-$(CONFIG_XYMODEM) += xymodem.o + obj-y += unlink-recursive.o + obj-$(CONFIG_STMP_DEVICE) += stmp-device.o ++obj-$(CONFIG_LIBSDB) += sdb/ +diff --git a/lib/sdb/Makefile b/lib/sdb/Makefile +index 4699673..d3f06a4 100644 +--- a/lib/sdb/Makefile ++++ b/lib/sdb/Makefile +@@ -1,43 +1 @@ +- +-LINUX ?= /lib/modules/$(shell uname -r)/build +- +-# If we compile for the kernel, we need to include real kernel headers. +-# The thing is enough a mess that I moved it to a different file +-include Makefile.arch +- +- +-AS = $(CROSS_COMPILE)as +-LD = $(CROSS_COMPILE)ld +-CC = $(CROSS_COMPILE)gcc +-CPP = $(CC) -E +-AR = $(CROSS_COMPILE)ar +-NM = $(CROSS_COMPILE)nm +-STRIP = $(CROSS_COMPILE)strip +-OBJCOPY = $(CROSS_COMPILE)objcopy +-OBJDUMP = $(CROSS_COMPILE)objdump +- +-# calculate endianness at compile time +-ENDIAN := $(shell ./check-endian $(CC)) +- +-CFLAGS = -Wall -ggdb -O2 +-CFLAGS += -I../include/linux -I../include # for <sdb.h> +-CFLAGS += -ffunction-sections -fdata-sections +-CFLAGS += -Wno-pointer-sign +-CFLAGS += $(ENDIAN) $(LINUXINCLUDE) +- +- +-LIB = libsdbfs.a +-OBJS = glue.o access.o +- +-all: $(LIB) +- +-$(OBJS): $(wildcard *.h) +- +-$(LIB): $(OBJS) +- $(AR) r $@ $(OBJS) +- +-clean: +- rm -f $(OBJS) $(LIB) *~ core +- +-# add the other unused targets, so the rule in ../Makefile works +-modules install modules_install: ++obj-y += glue.o access.o +-- +1.7.10.4 + diff --git a/patches/barebox/v2014.04/0014-commands-add-sdb-commands-to-list-read-setvar.patch b/patches/barebox/v2014.04/0014-commands-add-sdb-commands-to-list-read-setvar.patch new file mode 100644 index 0000000000000000000000000000000000000000..eb695947c530fee1264708f718b793cbbfdfbe36 --- /dev/null +++ b/patches/barebox/v2014.04/0014-commands-add-sdb-commands-to-list-read-setvar.patch @@ -0,0 +1,272 @@ +From 45c70af462edd6fb2cb6962545971a8a3ec78806 Mon Sep 17 00:00:00 2001 +From: Alessandro Rubini <rubini@gnudd.com> +Date: Mon, 15 Sep 2014 11:40:59 +0200 +Subject: [PATCH 14/14] commands: add sdb commands to list, read, setvar + +Signed-off-by: Alessandro Rubini <rubini@gnudd.com> +--- + commands/Kconfig | 7 ++ + commands/Makefile | 1 + + commands/sdb.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 228 insertions(+) + create mode 100644 commands/sdb.c + +diff --git a/commands/Kconfig b/commands/Kconfig +index 352e8bf..89cadec 100644 +--- a/commands/Kconfig ++++ b/commands/Kconfig +@@ -756,6 +756,13 @@ config CMD_DETECT + actual probe of the client devices until they are needed. Use the + 'detect' command on the physical device to trigger probing. + ++config CMD_SDB ++ bool ++ select LIBSDB ++ prompt "commands for reading SDB information" ++ help ++ This enables "sdbinfo", "sdbset" and "sdbread". ++ + menuconfig CMD_WD + bool + depends on WATCHDOG +diff --git a/commands/Makefile b/commands/Makefile +index 91ec0e9..e97291e 100644 +--- a/commands/Makefile ++++ b/commands/Makefile +@@ -91,6 +91,7 @@ obj-$(CONFIG_CMD_FILETYPE) += filetype.o + obj-$(CONFIG_CMD_BAREBOX_UPDATE)+= barebox-update.o + obj-$(CONFIG_CMD_MIITOOL) += miitool.o + obj-$(CONFIG_CMD_DETECT) += detect.o ++obj-$(CONFIG_CMD_SDB) += sdb.o + obj-$(CONFIG_CMD_BOOT) += boot.o + obj-$(CONFIG_CMD_DEVINFO) += devinfo.o + obj-$(CONFIG_CMD_READF) += readf.o +diff --git a/commands/sdb.c b/commands/sdb.c +new file mode 100644 +index 0000000..6b8e358 +--- /dev/null ++++ b/commands/sdb.c +@@ -0,0 +1,220 @@ ++/* ++ * Copyright (c) 2014 CERN. ++ * Author: Alessandro Rubini for BE-CO-HT (White Rabbit project) ++ * ++ * Please use according to GNU GPL 2 or later ++ */ ++#include <common.h> ++#include <command.h> ++#include <init.h> ++#include <malloc.h> ++#include <errno.h> ++#include <fs.h> ++#include <fcntl.h> ++#include <xfuncs.h> ++#include <environment.h> ++ ++#include <../lib/sdb/libsdbfs.h> /* hackish */ ++ ++#define BUFSIZE 1024 /* like cat.c in this directory */ ++ ++/* This is the drvdata in the SDB information */ ++struct bb_sdb_drvdata { ++ int fd; ++}; ++ ++static struct bb_sdb_drvdata drvdata; ++ ++/* and how to read the thing: use straight barebox POSIX interface */ ++static int bb_sdb_read(struct sdbfs *fs, int offset, void *buf, int count) ++{ ++ struct bb_sdb_drvdata *dd = fs->drvdata; ++ int fd = dd->fd; ++ ++ if (lseek(fd, offset, SEEK_SET) < 0) ++ return -1; ++ return read(fd, buf, count); ++} ++ ++static struct sdbfs bb_sdb_instance = { ++ .drvdata = &drvdata, ++ .entrypoint = 0, /* unfortunately: to be fixed */ ++ .read = bb_sdb_read, ++}; ++ ++/* local helpers to open and close, we do it three times on static data */ ++static int bb_sdb_create(char *name) ++{ ++ int fd, ret; ++ fd = open(name, O_RDONLY); ++ ++ if (fd < 0) { ++ printf("could not open %s: %s\n", name, errno_str()); ++ return fd; ++ } ++ drvdata.fd = fd; ++ ret = sdbfs_dev_create(&bb_sdb_instance, 1 /* verbose */); ++ if (ret != 0) { ++ printf("Error accessing SDB filesystem in \"%s\"\n", ++ name); ++ } ++ return ret; ++} ++ ++static int bb_sdb_destroy(void) ++{ ++ return sdbfs_dev_destroy(&bb_sdb_instance); ++} ++ ++/* And finally the real commands */ ++static int do_sdbinfo(int argc, char *argv[]) ++{ ++ struct sdb_device *d; ++ struct sdb_product *p; ++ struct sdb_component *c; ++ int new; ++ ++ if (argc != 2) { ++ perror("sdbinfo"); ++ return 1; ++ } ++ if (bb_sdb_create(argv[1]) != 0) ++ return 1; ++ /* now we already identified the magic number and so on */ ++ ++ new = 1; ++ while ( (d = sdbfs_scan(&bb_sdb_instance, new)) != NULL) { ++ new = 0; /* for next time */ ++ ++ c = &d->sdb_component; ++ p = &c->product; ++ ++ printf("%016llx:%08x @ %08llx-%08llx ", ++ ntohll(p->vendor_id), ntohl(p->device_id), ++ ntohll(c->addr_first), ntohll(c->addr_last)); ++ printf("%.19s\n", p->name); ++ } ++ return bb_sdb_destroy(); ++} ++ ++static int do_sdbset(int argc, char *argv[]) ++{ ++ char *buf; ++ char *filename; ++ int i, j, err = 1; ++ ++ if (argc < 3 || argc > 4) { ++ perror("sdbset"); ++ return 1; ++ } ++ if (bb_sdb_create(argv[1]) != 0) ++ return 1; ++ /* now we already identified the magic number and so on */ ++ ++ filename = argv[argc - 1]; ++ i = sdbfs_open_name(&bb_sdb_instance, filename); ++ if (i < 0) { ++ printf("can't open \"%s\" in \"%s\"\n", filename, argv[1]); ++ goto out; ++ } ++ buf = xmalloc(BUFSIZE); ++ i = sdbfs_fread(&bb_sdb_instance, -1, buf, BUFSIZE); ++ sdbfs_close(&bb_sdb_instance); ++ ++ if (i > 0) { ++ j = i - 1; ++ /* trim trailing garbage as the file is assumed to be text */ ++ while (j && (buf[j] == 0xff || buf[j] == 0x00)) ++ j--; ++ } ++ if (i > 0 && buf[i - 1] == '\n') ++ i--; /* remove trailing newline too */ ++ if (i > 0) { ++ buf[i] = '\0'; ++ setenv(argv[2], buf); ++ } ++ free(buf); ++ sdbfs_close(&bb_sdb_instance); ++ err = 0; ++out: ++ bb_sdb_destroy(); ++ return err; ++} ++ ++/* ++ * Read a file, skipping trailing 0x00 or 0xff bytes, as a convenience. ++ * The function is based on local command cat, in this director (Sascha Hauer) ++ */ ++static int do_sdbread(int argc, char *argv[]) ++{ ++ char *buf; ++ int i, j, err = 1; ++ ++ if (argc != 3) { ++ perror("sdbread"); ++ return 1; ++ } ++ ++ if (bb_sdb_create(argv[1]) != 0) ++ return 1; ++ /* now we already identified the magic number and so on */ ++ ++ i = sdbfs_open_name(&bb_sdb_instance, argv[2]); ++ if (i < 0) { ++ printf("can't open \"%s\" in \"%s\"\n", argv[2], argv[1]); ++ goto out; ++ } ++ buf = xmalloc(BUFSIZE); ++ ++ while ( (i = sdbfs_fread(&bb_sdb_instance, -1, buf, BUFSIZE)) > 0) { ++ ++ /* trim trailing garbage as the file is assumed to be text */ ++ j = i - 1; ++ while (j > 0 && (buf[j] == 0xff || buf[j] == 0x00)) ++ j--; ++ for (i = 0; i <= j; i++) ++ putchar(buf[i]); ++ /* no ctrl-C support; this is expected to be fast */ ++ } ++ /* most files have the trailing newline alrady, avoid adding it */ ++ free(buf); ++ sdbfs_close(&bb_sdb_instance); ++ err = 0; ++out: ++ bb_sdb_destroy(); ++ return err; ++} ++ ++static const __maybe_unused char cmd_sdbinfo_help[] = ++"Usage: sdbinfo <dev>" ++"\n" ++"List SDB files inside <dev>. Currently entry point must be zero"; ++ ++BAREBOX_CMD_START(sdbinfo) ++ .cmd = do_sdbinfo, ++ .usage = "sdb information in device", ++ BAREBOX_CMD_HELP(cmd_sdbinfo_help) ++BAREBOX_CMD_END ++ ++static const __maybe_unused char cmd_sdbset_help[] = ++"Usage: sdbset <dev> <varname> [<sdbfile>]" ++"\n" ++"Set a variable from the content of an SDB file in <dev>\n"; ++ ++BAREBOX_CMD_START(sdbset) ++ .cmd = do_sdbset, ++ .usage = "set a variable from an SDB file", ++ BAREBOX_CMD_HELP(cmd_sdbset_help) ++BAREBOX_CMD_END ++ ++static const __maybe_unused char cmd_sdbread_help[] = ++"Usage: sdbread <dev> <file>" ++"\n" ++"Print contents of file to stdout\n"; ++ ++BAREBOX_CMD_START(sdbread) ++ .cmd = do_sdbread, ++ .usage = "cat an SDB file", ++ BAREBOX_CMD_HELP(cmd_sdbread_help) ++BAREBOX_CMD_END ++ +-- +1.7.10.4 +