From 9200a15a6f98c76d9a75a036af7e5a9396b4fd39 Mon Sep 17 00:00:00 2001 From: Heesub Shin Date: Thu, 4 May 2017 21:58:27 +0900 Subject: [PATCH] drivers: add BCH device driver BCH device driver allows us to access the block device as if it is a character device. It is very helpful when we implement OTA downloader. All credits should go to many other contributors who wrote the original commits for NuttX. Change-Id: I368d963e6e58d810f5fdc0cdc48279521453ac18 [Shin: backported from NuttX] Signed-off-by: Heesub Shin --- os/drivers/Kconfig | 12 ++ os/drivers/Makefile | 1 + os/drivers/bch/Make.defs | 69 +++++++ os/drivers/bch/bch.h | 118 +++++++++++ os/drivers/bch/bchdev_driver.c | 398 +++++++++++++++++++++++++++++++++++++ os/drivers/bch/bchdev_register.c | 99 +++++++++ os/drivers/bch/bchdev_unregister.c | 149 ++++++++++++++ os/drivers/bch/bchlib_cache.c | 200 +++++++++++++++++++ os/drivers/bch/bchlib_read.c | 190 ++++++++++++++++++ os/drivers/bch/bchlib_sem.c | 97 +++++++++ os/drivers/bch/bchlib_setup.c | 148 ++++++++++++++ os/drivers/bch/bchlib_teardown.c | 105 ++++++++++ os/drivers/bch/bchlib_write.c | 187 +++++++++++++++++ 13 files changed, 1773 insertions(+) create mode 100644 os/drivers/bch/Make.defs create mode 100644 os/drivers/bch/bch.h create mode 100644 os/drivers/bch/bchdev_driver.c create mode 100644 os/drivers/bch/bchdev_register.c create mode 100644 os/drivers/bch/bchdev_unregister.c create mode 100644 os/drivers/bch/bchlib_cache.c create mode 100644 os/drivers/bch/bchlib_read.c create mode 100644 os/drivers/bch/bchlib_sem.c create mode 100644 os/drivers/bch/bchlib_setup.c create mode 100644 os/drivers/bch/bchlib_teardown.c create mode 100644 os/drivers/bch/bchlib_write.c diff --git a/os/drivers/Kconfig b/os/drivers/Kconfig index 458d4c7..8ec31a1 100644 --- a/os/drivers/Kconfig +++ b/os/drivers/Kconfig @@ -194,6 +194,18 @@ menuconfig I2S if I2S endif # I2S +menuconfig BCH + bool "Block-to-Character (BCH) Support" + default n + ---help--- + Contains logic that may be used to convert a block driver into + a character driver. This is the complementary conversion as + that performed by loop.c. See include/tinyara/fs/fs.h for + registration information. + +if BCH +endif # BCH + menuconfig RTC bool "RTC Driver Support" default n diff --git a/os/drivers/Makefile b/os/drivers/Makefile index 5a406e4..810c65e 100644 --- a/os/drivers/Makefile +++ b/os/drivers/Makefile @@ -67,6 +67,7 @@ VPATH = . # the appropriate paths to the VPATH variable include analog$(DELIM)Make.defs +include bch$(DELIM)Make.defs include i2c$(DELIM)Make.defs include lcd$(DELIM)Make.defs include net$(DELIM)Make.defs diff --git a/os/drivers/bch/Make.defs b/os/drivers/bch/Make.defs new file mode 100644 index 0000000..35c2470 --- /dev/null +++ b/os/drivers/bch/Make.defs @@ -0,0 +1,69 @@ +############################################################################ +## +## Copyright 2017 Samsung Electronics All Rights Reserved. +## +## Licensed under the Apache License, Version 2.0 (the "License"); +## you may not use this file except in compliance with the License. +## You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +## either express or implied. See the License for the specific +## language governing permissions and limitations under the License. +## +############################################################################ +############################################################################ +# drivers/bch/Make.defs +# +# Copyright (C) 2008, 2011-2012 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +############################################################################ + +ifneq ($(CONFIG_NFILE_DESCRIPTORS),0) +ifneq ($(CONFIG_DISABLE_MOUNTPOINT),y) + +# Include BCH driver + +CSRCS += bchlib_setup.c bchlib_teardown.c bchlib_read.c bchlib_write.c \ + bchlib_cache.c bchlib_sem.c bchdev_register.c bchdev_unregister.c \ + bchdev_driver.c + +# Include BCH driver build support + +DEPPATH += --dep-path bch +VPATH += :bch +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)bch} + +endif +endif diff --git a/os/drivers/bch/bch.h b/os/drivers/bch/bch.h new file mode 100644 index 0000000..78af6f7 --- /dev/null +++ b/os/drivers/bch/bch.h @@ -0,0 +1,118 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/bch/bch.h + * + * Copyright (C) 2008-2009, 2014-2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ +#ifndef __DRIVERS_BCH_BCH_H +#define __DRIVERS_BCH_BCH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include + +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +#define bchlib_semgive(d) sem_post(&(d)->sem) /* To match bchlib_semtake */ +#define MAX_OPENCNT (255) /* Limit of uint8_t */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ +struct bchlib_s +{ + FAR struct inode *inode; /* I-node of the block driver */ + uint32_t sectsize; /* The size of one sector on the device */ + size_t nsectors; /* Number of sectors supported by the device */ + size_t sector; /* The current sector in the buffer */ + sem_t sem; /* For atomic accesses to this structure */ + uint8_t refs; /* Number of references */ + bool dirty; /* true: Data has been written to the buffer */ + bool readonly; /* true: Only read operations are supported */ + bool unlinked; /* true: The driver has been unlinked */ + FAR uint8_t *buffer; /* One sector buffer */ + +#if defined(CONFIG_BCH_ENCRYPTION) + uint8_t key[CONFIG_BCH_ENCRYPTION_KEY_SIZE]; /* Encryption key */ +#endif +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + +EXTERN const struct file_operations bch_fops; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ +EXTERN void bchlib_semtake(FAR struct bchlib_s *bch); +EXTERN int bchlib_flushsector(FAR struct bchlib_s *bch); +EXTERN int bchlib_readsector(FAR struct bchlib_s *bch, size_t sector); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __DRIVERS_BCH_BCH_H */ diff --git a/os/drivers/bch/bchdev_driver.c b/os/drivers/bch/bchdev_driver.c new file mode 100644 index 0000000..da7845b --- /dev/null +++ b/os/drivers/bch/bchdev_driver.c @@ -0,0 +1,398 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/bch/bchdev_driver.c + * + * Copyright (C) 2008-2009, 2014-2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +static int bch_open(FAR struct file *filep); +static int bch_close(FAR struct file *filep); +static off_t bch_seek(FAR struct file *filep, off_t offset, int whence); +static ssize_t bch_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t bch_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +static int bch_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int bch_unlink(FAR struct inode *inode); +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ +const struct file_operations bch_fops = +{ + bch_open, /* open */ + bch_close, /* close */ + bch_read, /* read */ + bch_write, /* write */ + bch_seek, /* seek */ + bch_ioctl, /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + 0, /* poll */ +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + bch_unlink, /* unlink */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: bch_open + * + * Description: Open the block device + * + ****************************************************************************/ +static int bch_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct bchlib_s *bch; + + DEBUGASSERT(inode && inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + /* Increment the reference count */ + + bchlib_semtake(bch); + if (bch->refs == MAX_OPENCNT) { + return -EMFILE; + } else { + bch->refs++; + } + + bchlib_semgive(bch); + return OK; +} + +/**************************************************************************** + * Name: bch_close + * + * Description: close the block device + * + ****************************************************************************/ +static int bch_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct bchlib_s *bch; + int ret = OK; + + DEBUGASSERT(inode && inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + /* Flush any dirty pages remaining in the cache */ + bchlib_semtake(bch); + (void)bchlib_flushsector(bch); + + /* + * Decrement the reference count (I don't use bchlib_decref() because I + * want the entire close operation to be atomic wrt other driver + * operations. + */ + if (bch->refs == 0) { + ret = -EIO; + } else { + bch->refs--; + + /* + * If the reference count decremented to zero AND if the character + * driver has been unlinked, then teardown the BCH device now. + */ + if (bch->refs == 0 && bch->unlinked) { + /* Tear the driver down now. */ + ret = bchlib_teardown((FAR void *)bch); + + /* + * bchlib_teardown() would only fail if there are outstanding + * references on the device. Since we know that is not true, it + * should not fail at all. + */ + DEBUGASSERT(ret >= 0); + if (ret >= 0) { + /* Return without releasing the stale semaphore */ + return OK; + } + } + } + + bchlib_semgive(bch); + return ret; +} + +/**************************************************************************** + * Name: bch_seek + ****************************************************************************/ +static off_t bch_seek(FAR struct file *filep, off_t offset, int whence) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct bchlib_s *bch; + off_t newpos; + int ret; + + DEBUGASSERT(inode && inode->i_private); + + bch = (FAR struct bchlib_s *)inode->i_private; + bchlib_semtake(bch); + + /* Determine the new, requested file position */ + switch (whence) { + case SEEK_CUR: + newpos = filep->f_pos + offset; + break; + + case SEEK_SET: + newpos = offset; + break; + + case SEEK_END: + newpos = bch->sectsize * bch->nsectors + offset; + break; + + default: + /* Return EINVAL if the whence argument is invalid */ + bchlib_semgive(bch); + return -EINVAL; + } + + /* + * Opengroup.org: + * + * "The lseek() function shall allow the file offset to be set beyond the + * end of the existing data in the file. If data is later written at this + * point, subsequent reads of data in the gap shall return bytes with the + * value 0 until data is actually written into the gap." + * + * We can conform to the first part, but not the second. But return EINVAL + * if + * + * "...the resulting file offset would be negative for a regular file, + * block special file, or directory." + */ + if (newpos >= 0) { + filep->f_pos = newpos; + ret = newpos; + } else { + ret = -EINVAL; + } + + bchlib_semgive(bch); + return ret; +} + +/**************************************************************************** + * Name: bch_read + ****************************************************************************/ +static ssize_t bch_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct bchlib_s *bch; + int ret; + + DEBUGASSERT(inode && inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + bchlib_semtake(bch); + ret = bchlib_read(bch, buffer, filep->f_pos, len); + if (ret > 0) { + filep->f_pos += len; + } + + bchlib_semgive(bch); + return ret; +} + +/**************************************************************************** + * Name:bch_write + ****************************************************************************/ +static ssize_t bch_write(FAR struct file *filep, FAR const char *buffer, size_t len) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct bchlib_s *bch; + int ret = -EACCES; + + DEBUGASSERT(inode && inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + if (!bch->readonly) { + bchlib_semtake(bch); + ret = bchlib_write(bch, buffer, filep->f_pos, len); + if (ret > 0) { + filep->f_pos += len; + } + + bchlib_semgive(bch); + } + + return ret; +} + +/**************************************************************************** + * Name: bch_ioctl + * + * Description: Return device geometry + * + ****************************************************************************/ +static int bch_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct bchlib_s *bch; + int ret = -ENOTTY; + + DEBUGASSERT(inode && inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + /* Is this a request to get the private data structure */ + if (cmd == DIOC_GETPRIV) { + FAR struct bchlib_s **bchr = (FAR struct bchlib_s **)((uintptr_t)arg); + + bchlib_semtake(bch); + if (!bchr || bch->refs == MAX_OPENCNT) { + ret = -EINVAL; + } else { + bch->refs++; + *bchr = bch; + } + + bchlib_semgive(bch); + } +#ifdef CONFIG_BCH_ENCRYPTION + /* Is this a request to set the encryption key? */ + else if (cmd == DIOC_SETKEY) { + memcpy(bch->key, (FAR void *)arg, CONFIG_BCH_ENCRYPTION_KEY_SIZE); + ret = OK; + } +#endif + /* Otherwise, pass the IOCTL command on to the contained block driver */ + else { + FAR struct inode *bchinode = bch->inode; + + /* Does the block driver support the ioctl method? */ + if (bchinode->u.i_bops->ioctl != NULL) { + ret = bchinode->u.i_bops->ioctl(bchinode, cmd, arg); + } + } + + return ret; +} + +/**************************************************************************** + * Name: bch_unlink + * + * Handle unlinking of the BCH device + * + ****************************************************************************/ +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int bch_unlink(FAR struct inode *inode) +{ + FAR struct bchlib_s *bch; + int ret = OK; + + DEBUGASSERT(inode && inode->i_private); + bch = (FAR struct bchlib_s *)inode->i_private; + + /* Get exclusive access to the BCH device */ + bchlib_semtake(bch); + + /* Indicate that the driver has been unlinked */ + bch->unlinked = true; + + /* + * If there are no open references to the drvier then teardown the BCH + * device now. + */ + if (bch->refs == 0) { + /* Tear the driver down now. */ + ret = bchlib_teardown((FAR void *)bch); + + /* + * bchlib_teardown() would only fail if there are outstanding + * references on the device. Since we know that is not true, it + * should not fail at all. + */ + DEBUGASSERT(ret >= 0); + if (ret >= 0) { + /* Return without releasing the stale semaphore */ + return OK; + } + } + + bchlib_semgive(bch); + return ret; +} +#endif diff --git a/os/drivers/bch/bchdev_register.c b/os/drivers/bch/bchdev_register.c new file mode 100644 index 0000000..f235b59 --- /dev/null +++ b/os/drivers/bch/bchdev_register.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/bch/bchdev_register.c + * + * Copyright (C) 2008-2009, 2012, 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include + +#include +#include +#include +#include + +#include + +#include "bch.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: bchdev_register + * + * Description: + * Setup so that it exports the block driver referenced by 'blkdev' as a + * character device 'chardev' + * + ****************************************************************************/ +int bchdev_register(FAR const char *blkdev, FAR const char *chardev, bool readonly) +{ + FAR void *handle; + int ret; + + /* Setup the BCH lib functions */ + ret = bchlib_setup(blkdev, readonly, &handle); + if (ret < 0) { + fdbg("ERROR: bchlib_setup failed: %d\n", -ret); + return ret; + } + + /* Then setup the character device */ + ret = register_driver(chardev, &bch_fops, 0666, handle); + if (ret < 0) { + fdbg("ERROR: register_driver failed: %d\n", -ret); + bchlib_teardown(handle); + handle = NULL; + } + + return ret; +} diff --git a/os/drivers/bch/bchdev_unregister.c b/os/drivers/bch/bchdev_unregister.c new file mode 100644 index 0000000..420c560 --- /dev/null +++ b/os/drivers/bch/bchdev_unregister.c @@ -0,0 +1,149 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/bch/bchdev_unregister.c + * + * Copyright (C) 2008-2009, 2012, 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bch.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: bchdev_unregister + * + * Description: + * Unregister character driver access to a block device that was created + * by a previous call to bchdev_register(). + * + ****************************************************************************/ +int bchdev_unregister(FAR const char *chardev) +{ + FAR struct bchlib_s *bch; + int fd; + int ret; + + /* Sanity check */ +#ifdef CONFIG_DEBUG_FEATURES + if (!chardev) { + return -EINVAL; + } +#endif + + /* Open the character driver associated with chardev */ + fd = open(chardev, O_RDONLY); + if (fd < 0) { + _err("ERROR: Failed to open %s: %d\n", chardev, errno); + return -errno; + } + + /* + * Get a reference to the internal data structure. On success, we + * will hold a reference count on the state structure. + */ + ret = ioctl(fd, DIOC_GETPRIV, (unsigned long)((uintptr_t)&bch)); + (void)close(fd); + + if (ret < 0) { + _err("ERROR: ioctl failed: %d\n", errno); + return -errno; + } + + /* + * Lock out context switches. If there are no other references + * and no context switches, then we can assume that we can safely + * teardown the driver. + */ + sched_lock(); + + /* Check if the internal structure is non-busy (we hold one reference). */ + if (bch->refs > 1) { + ret = -EBUSY; + goto errout_with_lock; + } + + /* + * Unregister the driver (this cannot suspend or we lose our non-preemptive + * state!). Once the driver is successfully unregistered, we can assume + * we have exclusive access to the state instance. + */ + ret = unregister_driver(chardev); + if (ret < 0) { + goto errout_with_lock; + } + + sched_unlock(); + + /* Release the internal structure */ + bch->refs = 0; + return bchlib_teardown(bch); + +errout_with_lock: + bch->refs--; + sched_unlock(); + return ret; +} diff --git a/os/drivers/bch/bchlib_cache.c b/os/drivers/bch/bchlib_cache.c new file mode 100644 index 0000000..6dfdf61 --- /dev/null +++ b/os/drivers/bch/bchlib_cache.c @@ -0,0 +1,200 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/bch/bchlib_cache.c + * + * Copyright (C) 2008-2009, 2014, 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include + +#include +#include +#include +#include +#include + +#include "bch.h" + +#if defined(CONFIG_BCH_ENCRYPTION) +# include +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bch_xor + ****************************************************************************/ +#if defined(CONFIG_BCH_ENCRYPTION) +static void bch_xor(uint32_t *R, uint32_t *A, uint32_t *B) +{ + R[0] = A[0] ^ B[0]; + R[1] = A[1] ^ B[1]; + R[2] = A[2] ^ B[2]; + R[3] = A[3] ^ B[3]; +} +#endif + +/**************************************************************************** + * Name: bch_cypher + ****************************************************************************/ +#if defined(CONFIG_BCH_ENCRYPTION) +static int bch_cypher(FAR struct bchlib_s *bch, int encrypt) +{ + int blocks = bch->sectsize / 16; + FAR uint32_t *buffer = (FAR uint32_t *)bch->buffer; + int i; + + for (i = 0; i < blocks; i++, buffer += 16 / sizeof(uint32_t)) { + uint32_t T[4]; + uint32_t X[4] = { + bch->sector, 0, 0, i + }; + + aes_cypher(X, X, 16, NULL, bch->key, CONFIG_BCH_ENCRYPTION_KEY_SIZE, + AES_MODE_ECB, CYPHER_ENCRYPT); + + /* Xor-Encrypt-Xor */ + bch_xor(T, X, buffer); + aes_cypher(T, T, 16, NULL, bch->key, CONFIG_BCH_ENCRYPTION_KEY_SIZE, + AES_MODE_ECB, encrypt); + bch_xor(buffer, X, T); + } + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: bchlib_flushsector + * + * Description: + * Flush the current contents of the sector buffer (if dirty) + * + * Assumptions: + * Caller must assume mutual exclusion + * + ****************************************************************************/ +int bchlib_flushsector(FAR struct bchlib_s *bch) +{ + FAR struct inode *inode; + ssize_t ret = OK; + + /* + * Check if the sector has been modified and is out of synch with the + * media. + */ + if (bch->dirty) { + inode = bch->inode; + +#if defined(CONFIG_BCH_ENCRYPTION) + /* Encrypt data as necessary */ + bch_cypher(bch, CYPHER_ENCRYPT); +#endif + + /* Write the sector to the media */ + ret = inode->u.i_bops->write(inode, bch->buffer, bch->sector, 1); + if (ret < 0) { + fdbg("Write failed: %d\n"); + } + +#if defined(CONFIG_BCH_ENCRYPTION) + /* + * Computation overhead to save memory for extra sector buffer + * TODO: Add configuration switch for extra sector buffer + */ + bch_cypher(bch, CYPHER_DECRYPT); +#endif + + /* The sector is now in sync with the media */ + bch->dirty = false; + } + + return (int)ret; +} + +/**************************************************************************** + * Name: bchlib_readsector + * + * Description: + * Flush the current contents of the sector buffer (if dirty) + * + * Assumptions: + * Caller must assume mutual exclusion + * + ****************************************************************************/ +int bchlib_readsector(FAR struct bchlib_s *bch, size_t sector) +{ + FAR struct inode *inode; + ssize_t ret = OK; + + if (bch->sector != sector) { + inode = bch->inode; + + (void)bchlib_flushsector(bch); + bch->sector = (size_t)-1; + + ret = inode->u.i_bops->read(inode, bch->buffer, sector, 1); + if (ret < 0) { + fdbg("Read failed: %d\n"); + } + bch->sector = sector; +#if defined(CONFIG_BCH_ENCRYPTION) + bch_cypher(bch, CYPHER_DECRYPT); +#endif + } + return (int)ret; +} + diff --git a/os/drivers/bch/bchlib_read.c b/os/drivers/bch/bchlib_read.c new file mode 100644 index 0000000..96f5365 --- /dev/null +++ b/os/drivers/bch/bchlib_read.c @@ -0,0 +1,190 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/bch/bchlib_read.c + * + * Copyright (C) 2008-2009, 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include + +#include +#include +#include +#include +#include +#include + +#include "bch.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bchlib_read + * + * Description: + * Read from the block device set-up by bchlib_setup as if it were a + * character device. + * + ****************************************************************************/ +ssize_t bchlib_read(FAR void *handle, FAR char *buffer, size_t offset, size_t len) +{ + FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle; + size_t nsectors; + size_t sector; + uint16_t sectoffset; + size_t nbytes; + size_t bytesread; + int ret; + + /* Get rid of this special case right away */ + if (len < 1) { + return 0; + } + + /* Convert the file position into a sector number an offset. */ + sector = offset / bch->sectsize; + sectoffset = offset - sector * bch->sectsize; + + if (sector >= bch->nsectors) { + /* Return end-of-file */ + return 0; + } + + /* Read the initial partial sector */ + + bytesread = 0; + if (sectoffset > 0) { + /* Read the sector into the sector buffer */ + bchlib_readsector(bch, sector); + + /* Copy the tail end of the sector to the user buffer */ + if (sectoffset + len > bch->sectsize) { + nbytes = bch->sectsize - sectoffset; + } else { + nbytes = len; + } + + memcpy(buffer, &bch->buffer[sectoffset], nbytes); + + /* Adjust pointers and counts */ + sector++; + + if (sector >= bch->nsectors) { + return nbytes; + } + + bytesread = nbytes; + buffer += nbytes; + len -= nbytes; + } + + /* + * Then read all of the full sectors following the partial sector directly + * into the user buffer. + */ + if (len >= bch->sectsize) { + nsectors = len / bch->sectsize; + if (sector + nsectors > bch->nsectors) { + nsectors = bch->nsectors - sector; + } + + ret = bch->inode->u.i_bops->read(bch->inode, (FAR uint8_t *)buffer, + sector, nsectors); + if (ret < 0) { + fdbg("ERROR: Read failed: %d\n"); + return ret; + } + + /* Adjust pointers and counts */ + sector += nsectors; + nbytes = nsectors * bch->sectsize; + bytesread += nbytes; + + if (sector >= bch->nsectors) { + return bytesread; + } + + buffer += nbytes; + len -= nbytes; + } + + /* Then read any partial final sector */ + if (len > 0) { + /* Read the sector into the sector buffer */ + bchlib_readsector(bch, sector); + + /* Copy the head end of the sector to the user buffer */ + memcpy(buffer, bch->buffer, len); + + /* Adjust counts */ + bytesread += len; + } + + return bytesread; +} diff --git a/os/drivers/bch/bchlib_sem.c b/os/drivers/bch/bchlib_sem.c new file mode 100644 index 0000000..e3943fe --- /dev/null +++ b/os/drivers/bch/bchlib_sem.c @@ -0,0 +1,97 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/bch/bchlib_sem.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include + +#include +#include +#include + +#include "bch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bch_semtake + ****************************************************************************/ +void bchlib_semtake(FAR struct bchlib_s *bch) +{ + /* Take the semaphore (perhaps waiting) */ + while (sem_wait(&bch->sem) != 0) { + /* + * The only case that an error should occur here is if + * the wait was awakened by a signal. + */ + ASSERT(errno == EINTR); + } +} diff --git a/os/drivers/bch/bchlib_setup.c b/os/drivers/bch/bchlib_setup.c new file mode 100644 index 0000000..fb5a62c --- /dev/null +++ b/os/drivers/bch/bchlib_setup.c @@ -0,0 +1,148 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/bch/bchlib_setup.c + * + * Copyright (C) 2008-2009, 2011, 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "bch.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bchlib_setup + * + * Description: + * Setup so that the block driver referenced by 'blkdev' can be accessed + * similar to a character device. + * + ****************************************************************************/ +int bchlib_setup(const char *blkdev, bool readonly, FAR void **handle) +{ + FAR struct bchlib_s *bch; + struct geometry geo; + int ret; + + DEBUGASSERT(blkdev); + + /* Allocate the BCH state structure */ + bch = (FAR struct bchlib_s *)kmm_zalloc(sizeof(struct bchlib_s)); + if (!bch) { + fdbg("ERROR: Failed to allocate BCH structure\n"); + return -ENOMEM; + } + + /* Open the block driver */ + ret = open_blockdriver(blkdev, readonly ? MS_RDONLY : 0, &bch->inode); + if (ret < 0) { + fdbg("ERROR: Failed to open driver %s: %d\n", blkdev, -ret); + goto errout_with_bch; + } + + DEBUGASSERT(bch->inode && bch->inode->u.i_bops && bch->inode->u.i_bops->geometry); + + ret = bch->inode->u.i_bops->geometry(bch->inode, &geo); + if (ret < 0) { + fdbg("ERROR: geometry failed: %d\n", -ret); + goto errout_with_bch; + } + + if (!geo.geo_available) { + fdbg("ERROR: geometry failed: %d\n", -ret); + ret = -ENODEV; + goto errout_with_bch; + } + + if (!readonly && (!bch->inode->u.i_bops->write || !geo.geo_writeenabled)) { + fdbg("ERROR: write access not supported\n"); + ret = -EACCES; + goto errout_with_bch; + } + + /* Save the geometry info and complete initialization of the structure */ + sem_init(&bch->sem, 0, 1); + bch->nsectors = geo.geo_nsectors; + bch->sectsize = geo.geo_sectorsize; + bch->sector = (size_t)-1; + bch->readonly = readonly; + + /* Allocate the sector I/O buffer */ + bch->buffer = (FAR uint8_t *)kmm_malloc(bch->sectsize); + if (!bch->buffer) { + fdbg("ERROR: Failed to allocate sector buffer\n"); + ret = -ENOMEM; + goto errout_with_bch; + } + + *handle = bch; + return OK; + +errout_with_bch: + kmm_free(bch); + return ret; +} diff --git a/os/drivers/bch/bchlib_teardown.c b/os/drivers/bch/bchlib_teardown.c new file mode 100644 index 0000000..32ef6b2 --- /dev/null +++ b/os/drivers/bch/bchlib_teardown.c @@ -0,0 +1,105 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/bch/bchlib_teardown.c + * + * Copyright (C) 2008-2009, 2011, 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include + +#include +#include +#include +#include + +#include +#include + +#include "bch.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: bchlib_teardown + * + * Description: + * Setup so that the block driver referenced by 'blkdev' can be accessed + * similar to a character device. + * + ****************************************************************************/ +int bchlib_teardown(FAR void *handle) +{ + FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle; + + DEBUGASSERT(handle); + + /* Check that there are not outstanding reference counts on the object */ + if (bch->refs > 0) { + return -EBUSY; + } + + /* Flush any pending data to the block driver */ + bchlib_flushsector(bch); + + /* Close the block driver */ + (void)close_blockdriver(bch->inode); + + /* Free the BCH state structure */ + if (bch->buffer) { + kmm_free(bch->buffer); + } + + sem_destroy(&bch->sem); + kmm_free(bch); + return OK; +} + diff --git a/os/drivers/bch/bchlib_write.c b/os/drivers/bch/bchlib_write.c new file mode 100644 index 0000000..fecdc40 --- /dev/null +++ b/os/drivers/bch/bchlib_write.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * + * Copyright 2017 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +/**************************************************************************** + * drivers/bch/bchlib_write.c + * + * Copyright (C) 2008-2009, 2011, 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "bch.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bchlib_write + * + * Description: + * Write to the block device set-up by bchlib_setup as if it were a + * character device. + * + ****************************************************************************/ +ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, size_t offset, size_t len) +{ + FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle; + size_t nsectors; + size_t sector; + uint16_t sectoffset; + size_t nbytes; + size_t byteswritten; + int ret; + + /* Get rid of this special case right away */ + if (len < 1) { + return 0; + } + + /* Convert the file position into a sector number and offset. */ + sector = offset / bch->sectsize; + sectoffset = offset - sector * bch->sectsize; + + if (sector >= bch->nsectors) { + return -EFBIG; + } + + /* Write the initial partial sector */ + + byteswritten = 0; + if (sectoffset > 0) { + /* Read the full sector into the sector buffer */ + bchlib_readsector(bch, sector); + + /* Copy the tail end of the sector from the user buffer */ + if (sectoffset + len > bch->sectsize) { + nbytes = bch->sectsize - sectoffset; + } else { + nbytes = len; + } + + memcpy(&bch->buffer[sectoffset], buffer, nbytes); + bch->dirty = true; + + /* Adjust pointers and counts */ + sector++; + + if (sector >= bch->nsectors) { + return nbytes; + } + + byteswritten = nbytes; + buffer += nbytes; + len -= nbytes; + } + + /* + * Then write all of the full sectors following the partial sector + * directly from the user buffer. + */ + if (len >= bch->sectsize) { + nsectors = len / bch->sectsize; + if (sector + nsectors > bch->nsectors) { + nsectors = bch->nsectors - sector; + } + + /* Write the contiguous sectors */ + ret = bch->inode->u.i_bops->write(bch->inode, (FAR uint8_t *)buffer, + sector, nsectors); + if (ret < 0) { + fdbg("ERROR: Write failed: %d\n", ret); + return ret; + } + + /* Adjust pointers and counts */ + sector += nsectors; + nbytes = nsectors * bch->sectsize; + byteswritten += nbytes; + + if (sector >= bch->nsectors) { + return byteswritten; + } + + buffer += nbytes; + len -= nbytes; + } + + /* Then write any partial final sector */ + if (len > 0) { + /* Read the sector into the sector buffer */ + bchlib_readsector(bch, sector); + + /* Copy the head end of the sector from the user buffer */ + memcpy(bch->buffer, buffer, len); + bch->dirty = true; + + /* Adjust counts */ + byteswritten += len; + } + + /* Finally, flush any cached writes to the device as well */ + ret = bchlib_flushsector(bch); + if (ret < 0) { + fdbg("ERROR: Flush failed: %d\n", ret); + return ret; + } + + return byteswritten; +} + -- 2.7.4