summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2017-06-14 09:29:53 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2017-06-14 09:29:53 +0200
commit253412624e0fa60a309c6691b0cd99b6c341df87 (patch)
treed261ea96f8b29388beb93ec1b05b7b972aa548c1
parent6191ef93b25edbd75caec9213db3665f486ee433 (diff)
parentc35624d1946a4756c93bdb489f4790176b6e2dcc (diff)
downloadbarebox-253412624e0fa60a309c6691b0cd99b6c341df87.tar.gz
barebox-253412624e0fa60a309c6691b0cd99b6c341df87.tar.xz
Merge branch 'for-next/misc'
-rw-r--r--Documentation/boards/mvebu.rst10
-rw-r--r--Documentation/boards/mvebu/Netgear-ReadyNAS-2120.rst13
-rw-r--r--Documentation/devicetree/bindings/firmware/altr,passive-serial.txt3
-rw-r--r--Documentation/user/booting-linux.rst56
-rw-r--r--Documentation/user/random.rst63
-rw-r--r--Documentation/user/usb.rst21
-rw-r--r--Documentation/user/user-manual.rst1
-rw-r--r--commands/edit.c2
-rw-r--r--commands/help.c2
-rw-r--r--commands/mount.c13
-rw-r--r--commands/test.c2
-rw-r--r--commands/true.c3
-rw-r--r--commands/usbgadget.c3
-rw-r--r--common/block.c2
-rw-r--r--common/command.c2
-rw-r--r--common/hush.c2
-rw-r--r--drivers/firmware/altera_serial.c159
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c2
-rw-r--r--drivers/of/base.c2
-rw-r--r--drivers/rtc/rtc-lib.c7
-rw-r--r--fs/devfs-core.c92
-rw-r--r--fs/fs.c36
-rw-r--r--fs/parseopt.c26
-rw-r--r--fs/parseopt.h1
-rw-r--r--include/command.h2
-rw-r--r--include/driver.h12
-rw-r--r--include/fs.h1
-rw-r--r--scripts/Makefile.lib6
28 files changed, 439 insertions, 105 deletions
diff --git a/Documentation/boards/mvebu.rst b/Documentation/boards/mvebu.rst
index b4f8e6043d..8e5612283e 100644
--- a/Documentation/boards/mvebu.rst
+++ b/Documentation/boards/mvebu.rst
@@ -28,14 +28,18 @@ initialisation that could be taken.
Booting second stage
--------------------
-This is currently not possible because barebox assumes the registers are mapped
-at 0xd0000000 as is the case when the boot ROM gives control to the bootloader.
+Since ``v2017.04.0`` barebox can boot a barebox image even if the register
+window is moved. This is implemented by writing the actual window position
+into the image where it is then picked up by the second stage bootloader.
Booting from UART
-----------------
The mvebu SoCs support booting from UART. For this there is a tool available in
-barebox called kwboot.
+barebox called ``kwboot``. Quite some mvebu boards are reset once more when
+they already started to read the first block of the image to boot. If you want
+to boot such a board, use the parameter ``-n 15`` for ``kwboot``. (The number
+might have to be adapted per board.)
mvebu boards
------------
diff --git a/Documentation/boards/mvebu/Netgear-ReadyNAS-2120.rst b/Documentation/boards/mvebu/Netgear-ReadyNAS-2120.rst
index 5bee03af9d..488af2d7ac 100644
--- a/Documentation/boards/mvebu/Netgear-ReadyNAS-2120.rst
+++ b/Documentation/boards/mvebu/Netgear-ReadyNAS-2120.rst
@@ -6,14 +6,5 @@ This is a rack mountable 4 bay NAS using an Armada XP dual-core processor.
UART booting
------------
-The first UART hides behind a sticker on 4 pins.
-
-The machine seems to do two resets at power on which makes UART booting hard. A
-trick to work around this is::
-
- scripts/kwboot -d /dev/ttyUSB0; kwboot -b images/barebox-netgear-rn2120.img -t /dev/ttyUSB0
-
-This way the first window in which the CPU accepts the magic string is taken by
-the first invokation which blocks until the second reset happens. The second
-window is then hit with the image to boot. This is not 100% reliable but works
-most of the time.
+The UART that can be used to boot via RS232 (using ``kwboot``) hides behind a
+sticker on the backside of the machine. It uses TTL levels.
diff --git a/Documentation/devicetree/bindings/firmware/altr,passive-serial.txt b/Documentation/devicetree/bindings/firmware/altr,passive-serial.txt
index d357dd39cf..eec12fbace 100644
--- a/Documentation/devicetree/bindings/firmware/altr,passive-serial.txt
+++ b/Documentation/devicetree/bindings/firmware/altr,passive-serial.txt
@@ -6,7 +6,8 @@ passive serial mode. This is used to upload the firmware and
to start the FPGA.
Required properties:
-- compatible: shall be "altr,fpga-passive-serial"
+- compatible: shall be "altr,fpga-passive-serial" or
+ "altr,fpga-arria10-passive-serial" for Arria 10
- reg: SPI chip select
- nstat-gpios: Specify GPIO for controlling the nstat pin
- confd-gpios: Specify GPIO for controlling the confd pin
diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst
index f26299efd9..66f64ece08 100644
--- a/Documentation/user/booting-linux.rst
+++ b/Documentation/user/booting-linux.rst
@@ -229,10 +229,10 @@ time.
Network boot
------------
-With the following steps barebox can start the Kernel and root filesystem
-over network, a standard development case.
+With the following steps, barebox can start the kernel and root filesystem
+over the network, a standard development case.
-Configure network: edit ``/env/network/eth0``. For a standard dhcp setup
+Configure network: edit ``/env/network/eth0``. For a standard DHCP setup
the following is enough:
.. code-block:: sh
@@ -242,8 +242,11 @@ the following is enough:
ip=dhcp
serverip=192.168.23.45
-serverip is only necessary if it differs from the serverip offered from the dhcp server.
-A static ip setup can look like this:
+The optional setting ``serverip`` specifies the IP address of your TFTP and NFS
+server, and is only necessary if it differs from the server IP offered by the
+DHCP server (i.e., the field ``siaddr`` in the DHCP ACK Reply).
+
+A static IP setup can look like this:
.. code-block:: sh
@@ -255,27 +258,43 @@ A static ip setup can look like this:
gateway=192.168.2.1
serverip=192.168.2.1
-Note that barebox will pass the same ip settings to the kernel, i.e. it passes
-``ip=$ipaddr:$serverip:$gateway:$netmask::eth0:`` for a static ip setup and
-``ip=dhcp`` for a dynamic dhcp setup.
+Note that barebox will pass the same IP settings to the kernel, i.e. it passes
+``ip=$ipaddr:$serverip:$gateway:$netmask::eth0:`` for a static IP setup and
+``ip=dhcp`` for a dynamic DHCP setup.
-Adjust ``global.user`` and maybe ``global.hostname`` in ``/env/config``::
+By default, barebox uses the variables ``global.user`` and ``global.hostname``
+to retrieve its kernel image over TFTP, which makes it possible to use multiple
+boards for multiple users with one single server.
+You can adjust those variables in ``/env/config``::
global.user=sha
global.hostname=efikasb
-Copy the kernel (and devicetree if needed) to the base dir of the TFTP server::
+Copy the kernel (and devicetree if needed) to the root directory of your TFTP
+server, and name them accordingly; for example::
cp zImage /tftpboot/sha-linux-efikasb
cp myboard.dtb /tftpboot/sha-oftree-efikasb
-barebox will pass ``nfsroot=/home/${global.user}/nfsroot/${global.hostname}``
-This may be a link to another location on the NFS server. Make sure that the
-link target is exported from the server.
-
-``boot net`` will then start the Kernel.
-
-If the paths or names are not suitable they can be adjusted in
+(In this example, the directory ``/tftpboot`` represents the root directory of
+the TFTP server.
+That directory depends on the configuration of your TFTP server, some servers
+may also use ``/srv/tftp`` instead.)
+
+barebox will pass ``nfsroot=/home/${global.user}/nfsroot/${global.hostname}`` to
+the kernel.
+This causes the kernel to mount its root filesystem from a NFS server, which is
+detected through the DHCP reply.
+To choose a different server, simply prepend its IP address to the mount path,
+e.g. ``nfsroot=192.168.23.5:/home/...``.
+In any case, make sure that the specified mountpoint is exported by your NFS
+server.
+
+For more information about booting with ``nfsroot``, see
+`Documentation/filesystems/nfs/nfsroot.txt <https://github.com/torvalds/linux/blob/master/Documentation/filesystems/nfs/nfsroot.txt>`__
+in the Linux kernel documentation.
+
+If the preconfigured paths or names are not suitable, they can be adjusted in
``/env/boot/net``:
.. code-block:: sh
@@ -294,3 +313,6 @@ If the paths or names are not suitable they can be adjusted in
nfsroot="/home/${global.user}/nfsroot/${global.hostname}"
bootargs-ip
global.linux.bootargs.dyn.root="root=/dev/nfs nfsroot=$nfsroot,v3,tcp"
+
+``boot net`` will then retrieve the kernel (and also the device tree and
+initramfs, if used) over TFTP and boot it.
diff --git a/Documentation/user/random.rst b/Documentation/user/random.rst
new file mode 100644
index 0000000000..95dad72e55
--- /dev/null
+++ b/Documentation/user/random.rst
@@ -0,0 +1,63 @@
+Random Number Generator support
+===============================
+
+Barebox provides two types of RNG sources - PRNG and HWRNG:
+
+- "A pseudorandom number generator (PRNG), also known as a deterministic random
+ bit generator (DRBG),[1] is an algorithm for generating a sequence of numbers
+ whose properties approximate the properties of sequences of random numbers.
+ The PRNG-generated sequence is not truly random, because it is completely
+ determined by a relatively small set of initial values, called the PRNG's seed
+ (which may include truly random values). Although sequences that are closer to
+ truly random can be generated using hardware random number generators."
+ Pseudorandom number generator. https://en.wikipedia.org/wiki/Pseudorandom_number_generator (2017.05.08).
+ The PRNG used by Barebox is LCG (linear congruential generator) non cryptographically
+ secure, so please use with caution.
+
+- The HWRNG framework is software that makes use of a special hardware feature on
+ your CPU, SoC or motherboard. It can‘t provide any guarantee about cryptographic
+ security of used HW. Please refer to vendor documentation and/or RNG certification.
+
+API
+^^^
+
+.. code-block:: c
+
+ /* seed the PRNG. */
+ void srand(unsigned int seed);
+
+ /* Fill the buffer with PRNG bits. */
+ void get_random_bytes(void *buf, int len);
+
+ /* Fill the buffer with bits provided by HWRNG.
+ * This function may fail with a message “error: no HWRNG available!”
+ * in case HWRNG is not available or HW got some runtime error.
+ * If barebox is compiled with CONFIG_ALLOW_PRNG_FALLBACK,
+ * then get_crypto_bytes() will print “warning: falling back to Pseudo RNG source!”
+ * and use PRNG instead of returning error.
+ */
+ int get_crypto_bytes(void *buf, int len);
+
+User interface
+^^^^^^^^^^^^^^
+
+- /dev/hwrng0
+ provides access to first available HWRNG. To examine this source you can use:
+
+.. code-block:: sh
+
+ md -s /dev/hwrng0
+
+- /dev/prng
+ provides access to PRNG. To examine this source you can use:
+
+.. code-block:: sh
+
+ md -s /dev/prng
+
+To seed PRNG from user space the :ref:`command_seed` is provided. For example:
+
+.. code-block:: sh
+
+ seed 12345
+ md -s /dev/prng
diff --git a/Documentation/user/usb.rst b/Documentation/user/usb.rst
index bbcb045cee..ec219cfbe4 100644
--- a/Documentation/user/usb.rst
+++ b/Documentation/user/usb.rst
@@ -216,3 +216,24 @@ mode. Once a specific mode has been selected it can't be changed later anymore.
musb-hdrc: setup fifo_mode 4
musb-hdrc: 28/31 max ep, 16384/16384 memory
barebox:/
+
+USB Gadget autostart Support
+----------------------------
+
+Barebox can be configured to start usbgadget automatically by using global variables,
+instead of creating boot script. This can be useful if autostart policy should be
+chosen at boot time from other driver or script.
+To get usbgadget autostart support barebox has to be compiled with
+CONFIG_USB_GADGET_AUTOSTART enabled.
+
+USB Gadget autostart Options
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``global.usbgadget.autostart``
+ Boolean flag. If set to 1, usbgadget will be started automatically on boot and
+ enable USB OTG mode. (Default 0).
+``global.usbgadget.acm``
+ Boolean flag. If set to 1, CDC ACM function will be created.
+ See :ref:`command_usbgadget` -a. (Default 0).
+``global.usbgadget.fastboot_function``
+ Function description for fastboot. See :ref:`command_usbgadget` -A [desc].
diff --git a/Documentation/user/user-manual.rst b/Documentation/user/user-manual.rst
index 435649f353..791c8e0979 100644
--- a/Documentation/user/user-manual.rst
+++ b/Documentation/user/user-manual.rst
@@ -33,6 +33,7 @@ Contents:
reset-reason
system-reset
state
+ random
* :ref:`search`
* :ref:`genindex`
diff --git a/commands/edit.c b/commands/edit.c
index 696a818d9d..290222ce15 100644
--- a/commands/edit.c
+++ b/commands/edit.c
@@ -559,7 +559,7 @@ out:
return ret;
}
-static const char *edit_aliases[] = { "sedit", NULL};
+static const char * const edit_aliases[] = { "sedit", NULL};
BAREBOX_CMD_HELP_START(edit)
BAREBOX_CMD_HELP_TEXT("Use cursor keys, Ctrl-C to exit and Ctrl-D to exit-with-save.")
diff --git a/commands/help.c b/commands/help.c
index 819c40653c..34ffa9a419 100644
--- a/commands/help.c
+++ b/commands/help.c
@@ -139,7 +139,7 @@ BAREBOX_CMD_HELP_OPT ("-a", "output help on all commands")
BAREBOX_CMD_HELP_OPT ("-v", "verbose")
BAREBOX_CMD_HELP_END
-static const char *help_aliases[] = { "?", NULL};
+static const char * const help_aliases[] = { "?", NULL};
BAREBOX_CMD_START(help)
.cmd = do_help,
diff --git a/commands/mount.c b/commands/mount.c
index aa769d46fe..4cf1179b7b 100644
--- a/commands/mount.c
+++ b/commands/mount.c
@@ -29,7 +29,7 @@ static int do_mount(int argc, char *argv[])
int opt, verbose = 0;
struct driver_d *drv;
const char *type = NULL;
- const char *mountpoint, *dev;
+ const char *mountpoint, *devstr;
const char *fsoptions = NULL;
while ((opt = getopt(argc, argv, "ao:t:v")) > 0) {
@@ -70,11 +70,11 @@ static int do_mount(int argc, char *argv[])
return 0;
}
+ devstr = argv[optind];
+
if (argc == optind + 1) {
struct cdev *cdev;
- const char *path, *devstr;
-
- devstr = argv[optind];
+ const char *path;
if (!strncmp(devstr, "/dev/", 5))
devstr += 5;
@@ -97,8 +97,6 @@ static int do_mount(int argc, char *argv[])
if (argc < optind + 2)
return COMMAND_ERROR_USAGE;
- dev = argv[optind];
-
if (argc == optind + 3) {
/*
* Old behaviour: mount <dev> <type> <mountpoint>
@@ -109,7 +107,7 @@ static int do_mount(int argc, char *argv[])
mountpoint = argv[optind + 1];
}
- return mount(dev, type, mountpoint, fsoptions);
+ return mount(devstr, type, mountpoint, fsoptions);
}
BAREBOX_CMD_HELP_START(mount)
@@ -119,6 +117,7 @@ BAREBOX_CMD_HELP_TEXT("With -a the mount command mounts all block devices whose
BAREBOX_CMD_HELP_TEXT("can be detected automatically to /mnt/PARTNAME")
BAREBOX_CMD_HELP_TEXT("If mountpoint is not given, a standard mountpoint of /mnt/DEVICE")
BAREBOX_CMD_HELP_TEXT("is used. This directoy is created automatically if necessary.")
+BAREBOX_CMD_HELP_TEXT("With -o loop the mount command mounts a file instead of a device.")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT("-a\t", "mount all blockdevices")
diff --git a/commands/test.c b/commands/test.c
index d0f63c1391..c4f493860f 100644
--- a/commands/test.c
+++ b/commands/test.c
@@ -224,7 +224,7 @@ out:
return expr;
}
-static const char *test_aliases[] = { "[", NULL};
+static const char * const test_aliases[] = { "[", NULL};
BAREBOX_CMD_HELP_START(test)
BAREBOX_CMD_HELP_TEXT("Options:")
diff --git a/commands/true.c b/commands/true.c
index 24dea46929..ad2be8e8eb 100644
--- a/commands/true.c
+++ b/commands/true.c
@@ -26,7 +26,10 @@ static int do_true(int argc, char *argv[])
return 0;
}
+static const char * const true_aliases[] = { ":", NULL};
+
BAREBOX_CMD_START(true)
+ .aliases = true_aliases,
.cmd = do_true,
BAREBOX_CMD_DESC("do nothing, successfully")
BAREBOX_CMD_GROUP(CMD_GRP_SCRIPT)
diff --git a/commands/usbgadget.c b/commands/usbgadget.c
index 02c2c96b02..ba09f97847 100644
--- a/commands/usbgadget.c
+++ b/commands/usbgadget.c
@@ -106,7 +106,8 @@ BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-a", "Create CDC ACM function")
BAREBOX_CMD_HELP_OPT ("-s", "Create Generic Serial function")
-BAREBOX_CMD_HELP_OPT ("-A <desc>", "Create Android Fastboot function")
+BAREBOX_CMD_HELP_OPT ("-A [desc]", "Create Android Fastboot function. If 'desc' is not provided,")
+BAREBOX_CMD_HELP_OPT ("", "trying to use 'global.usbgadget.fastboot_function' variable.")
BAREBOX_CMD_HELP_OPT ("-D <desc>", "Create DFU function")
BAREBOX_CMD_HELP_OPT ("-d", "Disable the currently running gadget")
BAREBOX_CMD_HELP_END
diff --git a/common/block.c b/common/block.c
index 0edc8619ef..e2ba9d4296 100644
--- a/common/block.c
+++ b/common/block.c
@@ -374,6 +374,8 @@ int blockdevice_register(struct block_device *blk)
list_add_tail(&blk->list, &block_device_list);
+ cdev_create_default_automount(&blk->cdev);
+
return 0;
}
diff --git a/common/command.c b/common/command.c
index 03c70834d1..d9cc4a6d48 100644
--- a/common/command.c
+++ b/common/command.c
@@ -104,7 +104,7 @@ int register_command(struct command *cmd)
list_add_sort(&cmd->list, &command_list, compare);
if (cmd->aliases) {
- char **aliases = (char**)cmd->aliases;
+ const char * const *aliases = cmd->aliases;
while(*aliases) {
struct command *c = xzalloc(sizeof(struct command));
diff --git a/common/hush.c b/common/hush.c
index d3f7bf330d..792b61ac9a 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -1974,7 +1974,7 @@ static int do_source(int argc, char *argv[])
return ret;
}
-static const char *source_aliases[] = { ".", NULL};
+static const char * const source_aliases[] = { ".", NULL};
BAREBOX_CMD_HELP_START(source)
BAREBOX_CMD_HELP_TEXT("Read and execute commands from FILE in the current shell environment.")
diff --git a/drivers/firmware/altera_serial.c b/drivers/firmware/altera_serial.c
index b119778d72..3a0175dd07 100644
--- a/drivers/firmware/altera_serial.c
+++ b/drivers/firmware/altera_serial.c
@@ -25,11 +25,12 @@
#include <fcntl.h>
#include <fs.h>
-
/*
* Physical requirements:
- * - three free GPIOs for the signals nCONFIG, CONFIGURE_DONE, nSTATUS
- * - 32 bit per word, LSB first capable SPI master (MOSI + clock)
+ * - free GPIOs for the signals nCONFIG, CONFIGURE_DONE, nSTATUS (optionally
+ * for ARRIA 10)
+ * - 32 bit / 8 bit (ARRIA 10) per word, LSB first capable SPI master
+ * (MOSI + clock)
*
* Example how to configure this driver via device tree
*
@@ -43,6 +44,13 @@
* };
*/
+struct altera_ps_data {
+ int status_wait_max_us;
+ int t_st2ck_us;
+ int spi_bits_per_word;
+ int padding;
+};
+
struct fpga_spi {
struct firmware_handler fh;
int nstat_gpio; /* input GPIO to read the status line */
@@ -50,9 +58,36 @@ struct fpga_spi {
int nconfig_gpio; /* output GPIO to start the FPGA's config */
struct device_d *dev;
struct spi_device *spi;
+ const struct altera_ps_data *data;
bool padding_done;
};
+/* | Arria 5 | Arria 10 |
+ * t_CF2ST0 | [; 600] | [; 600] | ns
+ * t_CFG | [2;] | [2;] | µs
+ * t_STATUS | [268; 1506] | [268; 3000] | µs
+ * t_CF2ST1 | [; 1506] | [; 3000] | µs
+ * t_CF2CK | [1506;] | [3010 µs;] | µs
+ * t_ST2CK | [2;] | [10;] | µs
+ * t_CD2UM | [175; 437] | [175; 830] | µs
+ */
+
+/* Arria 5 */
+static struct altera_ps_data a5_data = {
+ .status_wait_max_us = 1506, /* max(t_CF2ST1) */
+ .t_st2ck_us = 2, /* min(t_ST2CK) */
+ .spi_bits_per_word = 32,
+ .padding = true,
+};
+
+/* Arria 10 */
+static struct altera_ps_data a10_data = {
+ .status_wait_max_us = 3000, /* max(t_CF2ST1) */
+ .t_st2ck_us = 10, /* min(t_ST2CK) */
+ .spi_bits_per_word = 8,
+ .padding = false,
+};
+
static int altera_spi_open(struct firmware_handler *fh)
{
struct fpga_spi *this = container_of(fh, struct fpga_spi, fh);
@@ -77,7 +112,6 @@ static int altera_spi_open(struct firmware_handler *fh)
(gpio_get_value(this->confd_gpio) == 0));
}
-
if (ret != 0) {
dev_err(dev, "FPGA does not acknowledge the programming initiation\n");
if (gpio_is_valid(this->nstat_gpio) && gpio_get_value(this->nstat_gpio))
@@ -94,24 +128,30 @@ static int altera_spi_open(struct firmware_handler *fh)
this->padding_done = false;
/*
- * after about 1506 µs the FPGA must acknowledge this step
- * with the STATUS line at high level
+ * after max { max(t_STATUS), max(t_CF2ST1) } the FPGA must acknowledge this
+ * step with the STATUS line at high level
*/
-
if (gpio_is_valid(this->nstat_gpio)) {
- ret = wait_on_timeout(1600 * USECOND,
- gpio_get_value(this->nstat_gpio) == 1);
- if (ret != 0) {
- dev_err(dev, "FPGA does not acknowledge the programming start\n");
+ ret = wait_on_timeout(this->data->status_wait_max_us * USECOND,
+ gpio_get_value(this->nstat_gpio));
+ if (ret) {
+ dev_err(dev, "nSTATUS still low after max(t_CF2ST1)! %d\n", ret);
return ret;
}
} else {
- udelay(1600);
+ udelay(this->data->status_wait_max_us);
}
dev_dbg(dev, "Initiating passed\n");
- /* at the end, wait at least 2 µs prior beginning writing data */
- udelay(2);
+
+ /*
+ * t_CF2CK doesn't need to be honored if nSTATUS is monitored in which
+ * case only t_ST2CK applies. As we have
+ * max(t_CF2ST1) + min(t_ST2CK) >= min(t_CF2CK)
+ * and we waited for max(t_CF2ST1) in the non-monitored
+ * case already above, only waiting for min(t_ST2CK) is fine here.
+ */
+ udelay(this->data->t_st2ck_us * USECOND);
return 0;
}
@@ -129,30 +169,38 @@ static int altera_spi_write(struct firmware_handler *fh, const void *buf, size_t
spi_message_init(&m);
- if (sz < sizeof(u32)) {
- /* simple padding */
- dummy = 0;
- memcpy(&dummy, buf, sz);
- buf = &dummy;
- sz = sizeof(u32);
- this->padding_done = true;
- }
+ if (this->data->padding) {
+ if (sz < sizeof(u32)) {
+ /* simple padding */
+ dummy = 0;
+ memcpy(&dummy, buf, sz);
+ buf = &dummy;
+ sz = sizeof(u32);
+ this->padding_done = true;
+ }
- t[0].tx_buf = buf;
- t[0].rx_buf = NULL;
- t[0].len = sz;
- spi_message_add_tail(&t[0], &m);
-
- if (sz & 0x3) { /* padding required? */
- u32 *word_buf = (u32 *)buf;
- dummy = 0;
- memcpy(&dummy, &word_buf[sz >> 2], sz & 0x3);
- t[0].len &= ~0x03;
- t[1].tx_buf = &dummy;
- t[1].rx_buf = NULL;
- t[1].len = sizeof(u32);
- spi_message_add_tail(&t[1], &m);
- this->padding_done = true;
+ t[0].tx_buf = buf;
+ t[0].rx_buf = NULL;
+ t[0].len = sz;
+ spi_message_add_tail(&t[0], &m);
+
+ if (sz & 0x3) { /* padding required? */
+ u32 *word_buf = (u32 *)buf;
+ dummy = 0;
+ memcpy(&dummy, &word_buf[sz >> 2], sz & 0x3);
+ t[0].len &= ~0x03;
+ t[1].tx_buf = &dummy;
+ t[1].rx_buf = NULL;
+ t[1].len = sizeof(u32);
+ spi_message_add_tail(&t[1], &m);
+ this->padding_done = true;
+ }
+ } else {
+ memset(&t[0], 0, sizeof(t[0]));
+ t[0].tx_buf = buf;
+ t[0].rx_buf = NULL;
+ t[0].len = sz;
+ spi_message_add_tail(&t[0], &m);
}
ret = spi_sync(this->spi, &m);
@@ -173,7 +221,7 @@ static int altera_spi_close(struct firmware_handler *fh)
dev_dbg(dev, "Finalize programming\n");
- if (this->padding_done == false) {
+ if (this->data->padding && this->padding_done == false) {
spi_message_init(&m);
t.tx_buf = &dummy;
t.rx_buf = NULL;
@@ -196,12 +244,23 @@ static int altera_spi_close(struct firmware_handler *fh)
} else {
ret = wait_on_timeout(10 * USECOND,
(gpio_get_value(this->confd_gpio) == 1));
-
}
+
if (ret == 0) {
dev_dbg(dev, "Programming successful\n");
- return ret;
+
+ /*
+ * After CONF_DONE goes high, send two additional falling edges on DCLK
+ * to begin initialization and enter user mode
+ */
+ spi_message_init(&m);
+ memset(&t, 0, sizeof(t));
+ t.tx_buf = NULL;
+ t.rx_buf = NULL;
+ t.len = 2;
+ spi_message_add_tail(&t, &m);
+ return spi_sync(this->spi, &m);
}
dev_err(dev, "Programming failed due to time out\n");
@@ -267,9 +326,10 @@ out:
return ret;
}
-static void altera_spi_init_mode(struct spi_device *spi)
+static void altera_spi_init_mode(struct spi_device *spi, int spi_bits_per_word)
{
- spi->bits_per_word = 32;
+ spi->bits_per_word = spi_bits_per_word;
+
/*
* CPHA = CPOL = 0
* the FPGA expects its firmware data with LSB first
@@ -284,9 +344,14 @@ static int altera_spi_probe(struct device_d *dev)
struct firmware_handler *fh;
const char *alias = of_alias_get(dev->device_node);
const char *model = NULL;
+ const struct altera_ps_data *data;
dev_dbg(dev, "Probing FPGA firmware programmer\n");
+ rc = dev_get_drvdata(dev, (const void **)&data);
+ if (rc)
+ return rc;
+
this = xzalloc(sizeof(*this));
fh = &this->fh;
@@ -308,7 +373,9 @@ static int altera_spi_probe(struct device_d *dev)
fh->dev = dev;
this->spi = (struct spi_device *)dev->type_data;
- altera_spi_init_mode(this->spi);
+ this->data = data;
+
+ altera_spi_init_mode(this->spi, this->data->spi_bits_per_word);
this->dev = dev;
dev_dbg(dev, "Registering FPGA firmware programmer\n");
@@ -327,9 +394,9 @@ out:
}
static struct of_device_id altera_spi_id_table[] = {
- {
- .compatible = "altr,fpga-passive-serial",
- },
+ { .compatible = "altr,fpga-passive-serial", .data = &a5_data },
+ { .compatible = "altr,fpga-arria10-passive-serial", .data = &a10_data },
+ { }
};
static struct driver_d altera_spi_driver = {
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index caece3b78e..fd1665bebb 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -281,7 +281,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
if (drv_data->bytes_left == 1)
drv_data->cntl_bits &= ~REG_CONTROL_ACK;
- udelay(2);
+ udelay(2);
break;
case STATUS_MAST_RD_DATA_NO_ACK: /* 0x58 */
diff --git a/drivers/of/base.c b/drivers/of/base.c
index c9bdd91810..33f61622ae 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1910,6 +1910,8 @@ int of_probe(void)
barebox_set_model(of_model);
memory = of_find_node_by_path("/memory");
+ if (!memory)
+ memory = of_find_node_by_type(root_node, "memory");
if (memory)
of_add_memory(memory, false);
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
index 83d80455da..4a2d34fcfd 100644
--- a/drivers/rtc/rtc-lib.c
+++ b/drivers/rtc/rtc-lib.c
@@ -20,13 +20,6 @@ static const unsigned char rtc_days_in_month[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
-static const unsigned short rtc_ydays[2][13] = {
- /* Normal years */
- { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
- /* Leap years */
- { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
-};
-
#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
/*
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index 382606f1cf..3368d3ed68 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -20,11 +20,14 @@
#include <complete.h>
#include <driver.h>
#include <errno.h>
+#include <fcntl.h>
#include <malloc.h>
#include <ioctl.h>
#include <nand.h>
#include <linux/err.h>
+#include <linux/fs.h>
#include <linux/mtd/mtd.h>
+#include <unistd.h>
LIST_HEAD(cdev_list);
@@ -332,6 +335,8 @@ static struct cdev *__devfs_add_partition(struct cdev *cdev,
devfs_create(new);
+ cdev_create_default_automount(new);
+
return new;
}
@@ -407,3 +412,90 @@ int devfs_create_partitions(const char *devname,
return 0;
}
+
+struct loop_priv {
+ int fd;
+};
+
+static ssize_t loop_read(struct cdev *cdev, void *buf, size_t count,
+ loff_t offset, ulong flags)
+{
+ struct loop_priv *priv = cdev->priv;
+ loff_t ofs;
+
+ ofs = lseek(priv->fd, offset, SEEK_SET);
+ if (ofs < 0)
+ return ofs;
+
+ return read(priv->fd, buf, count);
+}
+
+static ssize_t loop_write(struct cdev *cdev, const void *buf, size_t count,
+ loff_t offset, ulong flags)
+{
+ struct loop_priv *priv = cdev->priv;
+ loff_t ofs;
+
+ ofs = lseek(priv->fd, offset, SEEK_SET);
+ if (ofs < 0)
+ return ofs;
+
+ return write(priv->fd, buf, count);
+}
+
+static const struct file_operations loop_ops = {
+ .read = loop_read,
+ .write = loop_write,
+ .memmap = generic_memmap_rw,
+ .lseek = dev_lseek_default,
+};
+
+struct cdev *cdev_create_loop(const char *path, ulong flags)
+{
+ struct cdev *new;
+ struct loop_priv *priv;
+ static int loopno;
+ loff_t ofs;
+
+ priv = xzalloc(sizeof(*priv));
+
+ priv->fd = open(path, flags);
+ if (priv->fd < 0) {
+ free(priv);
+ return NULL;
+ }
+
+ new = xzalloc(sizeof(*new));
+
+ new->ops = &loop_ops;
+ new->name = basprintf("loop%u", loopno++);
+ new->priv = priv;
+
+ ofs = lseek(priv->fd, 0, SEEK_END);
+ if (ofs < 0) {
+ free(new);
+ free(priv);
+ return NULL;
+ }
+ lseek(priv->fd, 0, SEEK_SET);
+
+ new->size = ofs;
+ new->offset = 0;
+ new->dev = NULL;
+ new->flags = 0;
+
+ devfs_create(new);
+
+ return new;
+}
+
+void cdev_remove_loop(struct cdev *cdev)
+{
+ struct loop_priv *priv = cdev->priv;
+
+ devfs_remove(cdev);
+ close(priv->fd);
+ free(priv);
+ free(cdev->name);
+ free(cdev);
+}
diff --git a/fs/fs.c b/fs/fs.c
index 1da080502c..0a5b61a2b0 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -36,6 +36,8 @@
#include <block.h>
#include <libfile.h>
+#include "parseopt.h"
+
char *mkmodestr(unsigned long mode, char *str)
{
static const char *l = "xwr";
@@ -404,6 +406,20 @@ int automount_add(const char *path, const char *cmd)
}
EXPORT_SYMBOL(automount_add);
+void cdev_create_default_automount(struct cdev *cdev)
+{
+ char *path, *cmd;
+
+ path = basprintf("/mnt/%s", cdev->name);
+ cmd = basprintf("mount %s", cdev->name);
+
+ make_directory(path);
+ automount_add(path, cmd);
+
+ free(cmd);
+ free(path);
+}
+
void automount_print(void)
{
struct automount *am;
@@ -1193,6 +1209,9 @@ static void fs_remove(struct device_d *dev)
if (fsdev->cdev)
cdev_close(fsdev->cdev);
+ if (fsdev->loop)
+ cdev_remove_loop(fsdev->cdev);
+
free(fsdev->backingstore);
free(fsdev);
}
@@ -1219,13 +1238,18 @@ int register_fs_driver(struct fs_driver_d *fsdrv)
}
EXPORT_SYMBOL(register_fs_driver);
-static const char *detect_fs(const char *filename)
+static const char *detect_fs(const char *filename, const char *fsoptions)
{
enum filetype type;
struct driver_d *drv;
struct fs_driver_d *fdrv;
+ bool loop;
- type = cdev_detect_type(filename);
+ parseopt_b(fsoptions, "loop", &loop);
+ if (loop)
+ type = file_name_detect_type(filename);
+ else
+ type = cdev_detect_type(filename);
if (type == filetype_unknown)
return NULL;
@@ -1242,7 +1266,11 @@ static const char *detect_fs(const char *filename)
int fsdev_open_cdev(struct fs_device_d *fsdev)
{
- fsdev->cdev = cdev_open(fsdev->backingstore, O_RDWR);
+ parseopt_b(fsdev->options, "loop", &fsdev->loop);
+ if (fsdev->loop)
+ fsdev->cdev = cdev_create_loop(fsdev->backingstore, O_RDWR);
+ else
+ fsdev->cdev = cdev_open(fsdev->backingstore, O_RDWR);
if (!fsdev->cdev)
return -EINVAL;
@@ -1295,7 +1323,7 @@ int mount(const char *device, const char *fsname, const char *_path,
}
if (!fsname)
- fsname = detect_fs(device);
+ fsname = detect_fs(device, fsoptions);
if (!fsname)
return -ENOENT;
diff --git a/fs/parseopt.c b/fs/parseopt.c
index 12dbe1813c..8ff83019a7 100644
--- a/fs/parseopt.c
+++ b/fs/parseopt.c
@@ -2,6 +2,32 @@
#include "parseopt.h"
+void parseopt_b(const char *options, const char *opt, bool *val)
+{
+ const char *start;
+ size_t optlen = strlen(opt);
+
+again:
+ start = strstr(options, opt);
+
+ if (!start) {
+ *val = false;
+ return;
+ }
+
+ if (start > options && start[-1] != ',') {
+ options = start;
+ goto again;
+ }
+
+ if (start[optlen] != ',' && start[optlen] != '\0') {
+ options = start;
+ goto again;
+ }
+
+ *val = true;
+}
+
void parseopt_hu(const char *options, const char *opt, unsigned short *val)
{
const char *start;
diff --git a/fs/parseopt.h b/fs/parseopt.h
index a8523b6a10..abf3be3f35 100644
--- a/fs/parseopt.h
+++ b/fs/parseopt.h
@@ -1 +1,2 @@
+void parseopt_b(const char *options, const char *opt, bool *val);
void parseopt_hu(const char *options, const char *opt, unsigned short *val);
diff --git a/include/command.h b/include/command.h
index 43ee454f22..0afc5c7550 100644
--- a/include/command.h
+++ b/include/command.h
@@ -40,7 +40,7 @@ struct string_list;
*/
struct command {
const char *name; /* Command Name */
- const char **aliases;
+ const char * const *aliases;
/* Implementation function */
int (*cmd)(int, char *[]);
int (*complete)(struct string_list *sl, char *instr);
diff --git a/include/driver.h b/include/driver.h
index 52e06f7d62..3d701f2439 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -440,7 +440,7 @@ struct file_operations {
#define MAX_PARTUUID_STR sizeof("00112233-4455-6677-8899-AABBCCDDEEFF")
struct cdev {
- struct file_operations *ops;
+ const struct file_operations *ops;
void *priv;
struct device_d *dev;
struct device_node *device_node;
@@ -473,6 +473,8 @@ struct cdev *lcdev_by_name(const char *filename);
struct cdev *cdev_readlink(struct cdev *cdev);
struct cdev *cdev_by_device_node(struct device_node *node);
struct cdev *cdev_open(const char *name, unsigned long flags);
+struct cdev *cdev_create_loop(const char *path, ulong flags);
+void cdev_remove_loop(struct cdev *cdev);
int cdev_do_open(struct cdev *, unsigned long flags);
void cdev_close(struct cdev *cdev);
int cdev_flush(struct cdev *cdev);
@@ -490,6 +492,14 @@ struct cdev *devfs_add_partition(const char *devname, loff_t offset,
loff_t size, unsigned int flags, const char *name);
int devfs_del_partition(const char *name);
+#ifdef CONFIG_FS_AUTOMOUNT
+void cdev_create_default_automount(struct cdev *cdev);
+#else
+static inline void cdev_create_default_automount(struct cdev *cdev)
+{
+}
+#endif
+
#define DEVFS_PARTITION_APPEND 0
/**
diff --git a/include/fs.h b/include/fs.h
index 71edb22f26..d7fa7714b4 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -92,6 +92,7 @@ struct fs_device_d {
struct fs_driver_d *driver;
struct cdev *cdev;
+ bool loop;
char *path;
struct device_d *parent_device;
struct list_head list;
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index e79998c1b9..b084bacabe 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -448,3 +448,9 @@ quiet_cmd_cboot_bct = BCT $@
$(obj)/%.bct: $(obj)/%.bct.cfg
$(call cmd,cboot_bct)
+
+quiet_cmd_b64dec = B64DEC $@
+ cmd_b64dec = base64 -d $< > $@
+
+%: %.base64
+ $(call cmd,b64dec)