├── .gitattributes ├── .gitignore ├── .gitmodules ├── .travis.yml ├── README.md ├── extmod ├── filesystems └── minipython-demo-fatfs.img.gz ├── lib ├── minios ├── Makefile ├── alloc.c ├── blkdev.c ├── blkdev.h ├── builtin_open.c ├── debug.c ├── debug.h ├── diskio.c ├── diskio.h ├── examples │ ├── helloworld.py │ ├── http_client.py │ ├── http_server.py │ ├── pinger.py │ ├── readfile.py │ ├── test_time.py │ ├── test_tryexcept.py │ ├── testcar.py │ └── vehicles │ │ ├── __init__.py │ │ └── car.py ├── fatfs_port.c ├── frozentest.mpy ├── frozentest.py ├── gccollect.c ├── hexdump.c ├── hexdump.h ├── input.h ├── likely.h ├── main.c ├── mempool.c ├── mempool.h ├── minipython.c ├── minipython.h ├── minipython.xen ├── mkenv_minios.mk ├── mods │ ├── modlwip.c │ ├── modlwip.h │ ├── modos.c │ ├── modtime.c │ └── modusocket.c ├── mpconfigport.h ├── mphalport.h ├── qstrdefsport.h ├── ring.c ├── ring.h ├── shfs │ ├── dlist.h │ ├── hash.h │ ├── htable.c │ ├── htable.h │ ├── scripts │ │ └── mkwebfs │ ├── shfs-tools │ │ ├── Makefile │ │ ├── README.md │ │ ├── hash.h │ │ ├── htable.c │ │ ├── htable.h │ │ ├── http_parser.c │ │ ├── http_parser.h │ │ ├── likely.h │ │ ├── shfs_admin.c │ │ ├── shfs_admin.h │ │ ├── shfs_alloc.c │ │ ├── shfs_alloc.h │ │ ├── shfs_btable.h │ │ ├── shfs_check.c │ │ ├── shfs_check.h │ │ ├── shfs_defs.h │ │ ├── shfs_mkfs.c │ │ ├── shfs_mkfs.h │ │ ├── tools_common.c │ │ └── tools_common.h │ ├── shfs.c │ ├── shfs.h │ ├── shfs_btable.h │ ├── shfs_cache.c │ ├── shfs_cache.h │ ├── shfs_check.c │ ├── shfs_check.h │ ├── shfs_defs.h │ ├── shfs_fio.c │ ├── shfs_fio.h │ ├── shfs_stats.c │ ├── shfs_stats.h │ ├── shfs_stats_data.h │ ├── shfs_tools.c │ ├── shfs_tools.h │ └── sys.h ├── tools │ └── libimport.py └── unix_mphal.c ├── py ├── stmhal └── tools /.gitattributes: -------------------------------------------------------------------------------- 1 | # Per default everything gets normalized and gets LF line endings on checkout. 2 | * text eol=lf 3 | 4 | # These will always have CRLF line endings on checkout. 5 | *.vcxproj text eol=crlf 6 | *.props text eol=crlf 7 | *.bat text eol=crlf 8 | 9 | # These are binary so should never be modified by git. 10 | *.png binary 11 | *.jpg binary 12 | *.dxf binary 13 | 14 | # These should also not be modified by git. 15 | tests/basics/string_cr_conversion.py -text 16 | tests/basics/string_crlf_conversion.py -text 17 | stmhal/startup_stm32f40xx.s -text 18 | stmhal/pybcdc.inf_template -text 19 | stmhal/usbd_* -text 20 | stmhal/boards/*/stm32f4xx_hal_conf.h -text 21 | stmhal/cmsis/** -text 22 | stmhal/hal/** -text 23 | stmhal/usbdev/** -text 24 | stmhal/usbhost/** -text 25 | cc3200/hal/aes.c -text 26 | cc3200/hal/aes.h -text 27 | cc3200/hal/des.c -text 28 | cc3200/hal/i2s.c -text 29 | cc3200/hal/i2s.h -text 30 | cc3200/version.h -text 31 | lib/fatfs/** -text 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Sources 2 | ################### 3 | *.o 4 | *.a 5 | *.elf 6 | *.bin 7 | *.map 8 | *.hex 9 | *.dis 10 | *.exe 11 | 12 | # Packages 13 | ############ 14 | 15 | # Logs and Databases 16 | ###################### 17 | *.log 18 | 19 | # VIM Swap Files 20 | ###################### 21 | *.swp 22 | 23 | # Build directory 24 | ###################### 25 | build/ 26 | 27 | # Test failure outputs 28 | ###################### 29 | tests/*.exp 30 | tests/*.out 31 | 32 | # Python cache files 33 | ###################### 34 | __pycache__/ 35 | 36 | # Customized Makefile/project overrides 37 | ###################### 38 | GNUmakefile 39 | user.props 40 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "micropython"] 2 | path = micropython 3 | url = https://github.com/micropython/micropython.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | language: c 4 | compiler: 5 | - gcc 6 | 7 | before_script: 8 | # Extra CPython versions 9 | # - sudo add-apt-repository -y ppa:fkrull/deadsnakes 10 | # Extra gcc versions 11 | # - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test 12 | - sudo add-apt-repository -y ppa:terry.guo/gcc-arm-embedded 13 | - sudo dpkg --add-architecture i386 14 | - sudo apt-get update -qq || true 15 | - sudo apt-get install -y python3 gcc-multilib gcc-arm-none-eabi pkg-config libffi-dev libffi-dev:i386 qemu-system mingw32 16 | # For teensy build 17 | - sudo apt-get install realpath 18 | # For coverage testing 19 | - sudo pip install cpp-coveralls 20 | - gcc --version 21 | - arm-none-eabi-gcc --version 22 | - python3 --version 23 | 24 | script: 25 | - make -C minimal test 26 | - make -C unix deplibs 27 | - make -C unix 28 | - make -C unix nanbox 29 | - make -C bare-arm 30 | - make -C qemu-arm test 31 | - make -C stmhal 32 | - make -C stmhal -B MICROPY_PY_WIZNET5K=1 MICROPY_PY_CC3K=1 33 | - make -C stmhal BOARD=STM32F4DISC 34 | - make -C teensy 35 | - make -C cc3200 BTARGET=application BTYPE=release 36 | - make -C cc3200 BTARGET=bootloader BTYPE=release 37 | - make -C windows CROSS_COMPILE=i586-mingw32msvc- 38 | 39 | # run tests without coverage info 40 | #- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests) 41 | #- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests --emit native) 42 | 43 | # run tests with coverage info 44 | - make -C unix coverage 45 | - (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests) 46 | - (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests --emit native) 47 | 48 | after_success: 49 | - (cd unix && coveralls --root .. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod) 50 | 51 | after_failure: 52 | - (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done) 53 | - (grep "FAIL" qemu-arm/build/console.out) 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Minipython 2 | 3 | Minipython is a Xen-based unikernel to run Python scripts. It consists of MicroPython (https://github.com/micropython/micropython) running on top of the Xen paravirtualized Mini-OS operating system (https://wiki.xenproject.org/wiki/Mini-OS). 4 | 5 | ## Building 6 | 7 | Clone the Xen sources, the toolstack, Mini-OS and Minipython: 8 | 9 | $ git clone git://xenbits.xen.org/xen.git 10 | $ git clone https://github.com/sysml/mini-os.git 11 | $ git clone https://github.com/sysml/toolchain.git 12 | $ git clone https://github.com/sysml/minipython.git 13 | 14 | Check out a stable version of the Xen sources: 15 | 16 | $ cd xen 17 | $ git checkout stable-4.9 18 | $ cd .. 19 | 20 | Set up environment variables: 21 | 22 | $ export XEN_ROOT=$(pwd)/xen 23 | $ export TOOLCHAIN_ROOT=$(pwd)/toolchain 24 | $ export MINIOS_ROOT=$(pwd)/mini-os 25 | 26 | Prepare to build Minipython: 27 | 28 | $ cd minipython/micropython 29 | $ git submodule init 30 | $ git submodule update 31 | $ cd .. 32 | 33 | Next, edit minipython's Makefile (found in minios/Makefile) and set the paths to the Xen sources, the Xen toolchain sources and the Mini-OS sources: 34 | 35 | XEN_ROOT ?= $(realpath ../../xen) 36 | TOOLCHAIN_ROOT ?= $(realpath ../../toolchain) 37 | MINIOS_ROOT ?= $(realpath ../../mini-os) 38 | 39 | There are a number of options at the top of that Makefile that you can also set. For instance, by default, networking via lwip is enabled. 40 | 41 | To build minipython: 42 | 43 | $ cd minios 44 | $ make 45 | 46 | ## Specifying a Python Script 47 | 48 | To specify a Python script edit the run_script() function in minios/main.c . You have two main options: do\_str(), which allows you to specify a string for your script directly in main.c, and do_file() which retrieves and executes a file from your filesystem. 49 | 50 | ## Running 51 | 52 | The minipython VM can be simply run with 53 | 54 | $ cd minios 55 | $ xl create -c minipython.xen 56 | 57 | Before this will work though we need to set up a filesystem and networking (the latter is only needed if the Makefile has networking enabled; by default it is). Please see instructions below. 58 | 59 | ### Filesystem 60 | 61 | Minipython uses FAT as its default filesystem type. To get you started, you can use the demo filesystem in these sources (filesystems/minipython-demo-fatfs.img) which contains a few basic scripts. First uncompress it with: 62 | 63 | $ gzip -d minipython-demo-fatfs.img.gz 64 | 65 | Then mount it: 66 | 67 | $ losetup /dev/loop0 filesystems/minipython-demo-fatfs.img 68 | $ kpartx -a /dev/loop0 69 | $ mkdir -p /mnt/fat 70 | $ mount /dev/mapper/loop0p1 /mnt/fat/ 71 | 72 | Finally specify a disk in minios/minipython.xen (the version of this file in these sources already has this line): 73 | 74 | 75 | disk = ['phy:/dev/loop0,xvda,w'] 76 | 77 | 78 | #### SHFS 79 | 80 | [Use this only if you know what you're doing!] 81 | 82 | First, set CONFIG_SHFS=y in minios/Makefile (make distclean; make if you had previously built the image). Then add a disk to minios/minipython.xen: 83 | 84 | disk = [ 'file:/path/to/your/volume/minipython-vol.shfs,xvda,w'] 85 | 86 | To create minipython-vol.shfs, in the minios/shfs/shfs-tools/ subdirectory run make, then: 87 | 88 | ./mkwebfs /path/to/your/python/files minipython-vol.shfs 89 | 90 | Get the signature of the file you want to run with: 91 | 92 | ./shfs_admin -l minipython-vol.shfs 93 | 94 | Set the default file flag with 95 | 96 | /shfs_admin -d [signature] minipython-vol.shfs 97 | 98 | 99 | 100 | ### Networking 101 | 102 | First, create a bridge with brctl and bring it up: 103 | 104 | $ brctl addbr minipythonbr 105 | $ ifconfig minipythonbr 192.168.0.1 netmask 255.255.255.0 up 106 | 107 | Then, add a vif to minios/minipython.xen: 108 | 109 | vif = [ 'mac=00:11:22:33:44:55,bridge=minipythonbr,ip=192.168.0.100' ] 110 | 111 | To test it out you can run the HTTP server script provided with the minipython sources: 112 | 113 | $ cp minios/examples/http_server.py /mnt/fat 114 | 115 | Add the line to main.c's run_script() function: 116 | 117 | do_file("http_server.py"); 118 | 119 | Run make and xl create -c minipython.xen. You can test that it is working by running the following command on the host (i.e., dom0): 120 | 121 | $ wget 192.168.0.100:8080 --no-proxy 122 | 123 | ## MicroPython Libs 124 | 125 | To add https://github.com/micropython/micropython-lib to minipython, edit 126 | minos/tools/libimport.py and set the MICROPY\_LIB\_DIR and MINIPYTHON\_TARGET\_DIR 127 | variables, then 128 | 129 | $ python minios/tools/libimport.py 130 | 131 | The program will print which modules it actually copied (it ignores 132 | placeholder libraries, i.e., those with empty .py files). 133 | 134 | The output under "Added libs" (a Python array) can be copied into minios/examples/test_tryexcept.py to see which modules will actually run under minipython. -------------------------------------------------------------------------------- /extmod: -------------------------------------------------------------------------------- 1 | micropython/extmod -------------------------------------------------------------------------------- /filesystems/minipython-demo-fatfs.img.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysml/minipython/6dbf93c4e4c81cc02032e693636212b7ce2eb1ed/filesystems/minipython-demo-fatfs.img.gz -------------------------------------------------------------------------------- /lib: -------------------------------------------------------------------------------- 1 | micropython/lib -------------------------------------------------------------------------------- /minios/alloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Micro Python project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2014 Fabian Vogt 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "py/mpstate.h" 34 | #include "py/gc.h" 35 | 36 | #if MICROPY_EMIT_NATIVE 37 | 38 | //#if defined(__OpenBSD__) || defined(__MACH__) 39 | #define MAP_ANONYMOUS MAP_ANON 40 | //#endif 41 | 42 | // The memory allocated here is not on the GC heap (and it may contain pointers 43 | // that need to be GC'd) so we must somehow trace this memory. We do it by 44 | // keeping a linked list of all mmap'd regions, and tracing them explicitly. 45 | 46 | typedef struct _mmap_region_t { 47 | void *ptr; 48 | size_t len; 49 | struct _mmap_region_t *next; 50 | } mmap_region_t; 51 | 52 | void mp_unix_alloc_exec(mp_uint_t min_size, void **ptr, mp_uint_t *size) { 53 | // size needs to be a multiple of the page size 54 | *size = (min_size + 0xfff) & (~0xfff); 55 | *ptr = mmap(NULL, *size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 56 | if (*ptr == MAP_FAILED) { 57 | *ptr = NULL; 58 | } 59 | 60 | // add new link to the list of mmap'd regions 61 | mmap_region_t *rg = m_new_obj(mmap_region_t); 62 | rg->ptr = *ptr; 63 | rg->len = min_size; 64 | rg->next = MP_STATE_VM(mmap_region_head); 65 | MP_STATE_VM(mmap_region_head) = rg; 66 | } 67 | 68 | void mp_unix_free_exec(void *ptr, mp_uint_t size) { 69 | munmap(ptr, size); 70 | 71 | // unlink the mmap'd region from the list 72 | for (mmap_region_t **rg = (mmap_region_t**)&MP_STATE_VM(mmap_region_head); *rg != NULL; *rg = (*rg)->next) { 73 | if ((*rg)->ptr == ptr) { 74 | mmap_region_t *next = (*rg)->next; 75 | m_del_obj(mmap_region_t, *rg); 76 | *rg = next; 77 | return; 78 | } 79 | } 80 | } 81 | 82 | void mp_unix_mark_exec(void) { 83 | for (mmap_region_t *rg = MP_STATE_VM(mmap_region_head); rg != NULL; rg = rg->next) { 84 | gc_collect_root(rg->ptr, rg->len / sizeof(mp_uint_t)); 85 | } 86 | } 87 | 88 | #endif // MICROPY_EMIT_NATIVE 89 | -------------------------------------------------------------------------------- /minios/blkdev.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Block device wrapper for MiniOS 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "blkdev.h" 43 | 44 | #ifndef container_of 45 | /* NOTE: This is copied from linux kernel. 46 | * It probably makes sense to move this to mini-os's kernel.h */ 47 | /** 48 | * container_of - cast a member of a structure out to the containing structure 49 | * @ptr:the pointer to the member. 50 | * @type:the type of the container struct this is embedded in. 51 | * @member:the name of the member within the struct. 52 | */ 53 | #define container_of(ptr, type, member) ({\ 54 | const typeof( ((type *)0)->member ) *__mptr = (ptr);\ 55 | (type *)( (char *)__mptr - offsetof(type,member) );}) 56 | #endif /* container_of */ 57 | 58 | struct blkdev *_open_bd_list = NULL; 59 | 60 | int blkdev_id_parse(const char *id, blkdev_id_t *out) 61 | { 62 | int ival, ret; 63 | 64 | ret = sscanf(id, "%d", &ival); 65 | if (ret != 1 || ival < 0) 66 | return -1; 67 | *out = (blkdev_id_t) ival; 68 | return 0; 69 | } 70 | 71 | unsigned int detect_blkdevs(blkdev_id_t ids_out[], unsigned int max_nb) 72 | { 73 | register unsigned int i = 0; 74 | register unsigned int found = 0; 75 | char path[128]; 76 | char *xb_errmsg; 77 | char **vbd_entries; 78 | 79 | snprintf(path, sizeof(path), "/local/domain/%u/device/vbd", xenbus_get_self_id()); 80 | xb_errmsg = xenbus_ls(XBT_NIL, path, &vbd_entries); 81 | if (xb_errmsg || (!vbd_entries)) { 82 | if (xb_errmsg) 83 | free(xb_errmsg); 84 | return 0; 85 | } 86 | 87 | /* interate through list */ 88 | while (vbd_entries[i] != NULL) { 89 | if (found < max_nb) { 90 | if (blkdev_id_parse(vbd_entries[i], &ids_out[found]) >= 0) { 91 | found++; 92 | } 93 | } 94 | free(vbd_entries[i++]); 95 | } 96 | 97 | free(vbd_entries); 98 | return found; 99 | } 100 | 101 | struct blkdev *open_blkdev(blkdev_id_t id, int mode) 102 | { 103 | struct blkdev *bd; 104 | 105 | /* search in blkdev list if device is already open */ 106 | for (bd = _open_bd_list; bd != NULL; bd = bd->_next) { 107 | if (blkdev_id_cmp(blkdev_id(bd), id) == 0) { 108 | /* found: device is already open, 109 | * now we check if it was/shall be opened 110 | * exclusively and requested permissions 111 | * are available */ 112 | if (mode & O_EXCL || 113 | bd->exclusive) { 114 | errno = EBUSY; 115 | goto err; 116 | } 117 | if (((mode & O_WRONLY) && !(bd->info.mode & (O_WRONLY | O_RDWR))) || 118 | ((mode & O_RDWR) && !(bd->info.mode & O_RDWR))) { 119 | errno = EACCES; 120 | goto err; 121 | } 122 | 123 | ++bd->refcount; 124 | return bd; 125 | } 126 | } 127 | 128 | bd = xmalloc(struct blkdev); 129 | if (!bd) { 130 | errno = ENOMEM; 131 | goto err; 132 | } 133 | 134 | bd->reqpool = alloc_simple_mempool(MAX_REQUESTS, sizeof(struct _blkdev_req)); 135 | if (!bd->reqpool) { 136 | errno = ENOMEM; 137 | goto err_free_bd; 138 | } 139 | 140 | bd->id = id; 141 | bd->refcount = 1; 142 | bd->exclusive = !!(mode & O_EXCL); 143 | snprintf(bd->nname, sizeof(bd->nname), "device/vbd/%u", id); 144 | 145 | bd->dev = init_blkfront(bd->nname, &(bd->info)); 146 | if (!bd->dev) { 147 | errno = ENODEV; 148 | goto err_free_reqpool; 149 | } 150 | 151 | if (((mode & O_WRONLY) && !(bd->info.mode & (O_WRONLY | O_RDWR))) || 152 | ((mode & O_RDWR) && !(bd->info.mode & O_RDWR))) { 153 | errno = EACCES; 154 | goto err_shutdown_blkfront; 155 | } 156 | 157 | #ifdef CONFIG_SELECT_POLL 158 | bd->fd = blkfront_open(bd->dev); 159 | if (bd->fd < 0) 160 | goto err_close_blkfront; 161 | #endif 162 | 163 | /* link new element to the head of _open_bd_list */ 164 | bd->_prev = NULL; 165 | bd->_next = _open_bd_list; 166 | _open_bd_list = bd; 167 | if (bd->_next) 168 | bd->_next->_prev = bd; 169 | 170 | blkdev_async_io_wait_slot(bd); 171 | return bd; 172 | 173 | #ifdef CONFIG_SELECT_POLL 174 | err_close_blkfront: 175 | /* blkfront_close(bd->fd); // DOES NOT EXIST */ 176 | #endif 177 | err_shutdown_blkfront: 178 | shutdown_blkfront(bd->dev); 179 | err_free_reqpool: 180 | free_mempool(bd->reqpool); 181 | err_free_bd: 182 | xfree(bd); 183 | err: 184 | return NULL; 185 | } 186 | 187 | void close_blkdev(struct blkdev *bd) 188 | { 189 | --bd->refcount; 190 | if (bd->refcount == 0) { 191 | /* unlink element from _open_bd_list */ 192 | if (bd->_next) 193 | bd->_next->_prev = bd->_prev; 194 | if (bd->_prev) 195 | bd->_prev->_next = bd->_next; 196 | else 197 | _open_bd_list = bd->_next; 198 | 199 | shutdown_blkfront(bd->dev); 200 | free_mempool(bd->reqpool); 201 | xfree(bd); 202 | } 203 | } 204 | 205 | void _blkdev_async_io_cb(struct blkfront_aiocb *aiocb, int ret) 206 | { 207 | struct mempool_obj *robj; 208 | struct _blkdev_req *req; 209 | 210 | req = container_of(aiocb, struct _blkdev_req, aiocb); 211 | robj = req->p_obj; 212 | 213 | if (req->cb) 214 | req->cb(ret, req->cb_argp); /* user callback */ 215 | 216 | mempool_put(robj); 217 | } 218 | 219 | void _blkdev_sync_io_cb(int ret, void *argp) 220 | { 221 | struct _blkdev_sync_io_sync *iosync = argp; 222 | 223 | iosync->ret = ret; 224 | up(&iosync->sem); 225 | } 226 | -------------------------------------------------------------------------------- /minios/blkdev.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Block device wrapper for MiniOS 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _BLKDEV_H_ 37 | #define _BLKDEV_H_ 38 | 39 | #include 40 | #include 41 | #include 42 | 43 | #include "mempool.h" 44 | 45 | #define MAX_REQUESTS ((__RING_SIZE((struct blkif_sring *)0, PAGE_SIZE)) - 1) 46 | #define MAX_DISKSIZE (1ll << 40) /* 1 TB */ 47 | 48 | typedef unsigned int blkdev_id_t; /* device id is a uint */ 49 | typedef uint64_t sector_t; 50 | #define PRIsctr PRIu64 51 | 52 | typedef void (blkdev_aiocb_t)(int ret, void *argp); 53 | 54 | struct blkdev { 55 | struct blkfront_dev *dev; 56 | struct blkfront_info info; 57 | struct mempool *reqpool; 58 | char nname[64]; 59 | blkdev_id_t id; 60 | #ifdef CONFIG_SELECT_POLL 61 | int fd; 62 | #endif 63 | 64 | int exclusive; 65 | unsigned int refcount; 66 | struct blkdev *_next; 67 | struct blkdev *_prev; 68 | }; 69 | 70 | struct _blkdev_req { 71 | struct mempool_obj *p_obj; /* reference to dependent memory pool object */ 72 | struct blkdev *bd; 73 | struct blkfront_aiocb aiocb; 74 | sector_t sector; 75 | sector_t nb_sectors; 76 | int write; 77 | blkdev_aiocb_t *cb; 78 | void *cb_argp; 79 | }; 80 | 81 | #define CAN_DETECT_BLKDEVS 82 | unsigned int detect_blkdevs(blkdev_id_t ids_out[], unsigned int max_nb); 83 | struct blkdev *open_blkdev(blkdev_id_t id, int mode); 84 | void close_blkdev(struct blkdev *bd); 85 | #define blkdev_refcount(bd) ((bd)->refcount) 86 | 87 | int blkdev_id_parse(const char *id, blkdev_id_t *out); 88 | #define blkdev_id_unparse(id, out, maxlen) \ 89 | (snprintf((out), (maxlen), "%u", (id))) 90 | #define blkdev_id_cmp(id0, id1) \ 91 | ((id0) != (id1)) 92 | #define blkdev_id_cpy(dst, src) \ 93 | ((dst) = (src)) 94 | #define blkdev_id(bd) ((bd)->id) 95 | #define blkdev_ioalign(bd) blkdev_ssize((bd)) 96 | 97 | /** 98 | * Retrieve device information 99 | */ 100 | static inline sector_t blkdev_sectors(struct blkdev *bd) 101 | { 102 | /* WORKAROUND: blkfront cannot handle > 1TB -> limit the disk size */ 103 | if (((sector_t) bd->info.sectors * (sector_t) bd->info.sector_size) > MAX_DISKSIZE) 104 | return (MAX_DISKSIZE / (sector_t) bd->info.sector_size); 105 | return (sector_t) bd->info.sectors; 106 | } 107 | #define blkdev_ssize(bd) ((uint32_t) (bd)->info.sector_size) 108 | #define blkdev_size(bd) (blkdev_sectors((bd)) * (sector_t) blkdev_ssize((bd))) 109 | #define blkdev_avail_req(bd) mempool_free_count((bd)->reqpool) 110 | 111 | 112 | /** 113 | * Async I/O 114 | * 115 | * Note: target buffer has to be aligned to device sector size 116 | */ 117 | void _blkdev_async_io_cb(struct blkfront_aiocb *aiocb, int ret); 118 | 119 | #define blkdev_async_io_submit(bd) blkfront_aio_submit((bd)->dev) 120 | #define blkdev_async_io_wait_slot(bd) blkfront_wait_slot((bd)->dev) 121 | 122 | static inline int blkdev_async_io_nocheck(struct blkdev *bd, sector_t start, sector_t len, 123 | int write, void *buffer, blkdev_aiocb_t *cb, void *cb_argp) 124 | { 125 | struct mempool_obj *robj; 126 | struct _blkdev_req *req; 127 | int ret; 128 | 129 | robj = mempool_pick(bd->reqpool); 130 | if (unlikely(!robj)) 131 | return -EAGAIN; /* too many requests on queue */ 132 | 133 | req = robj->data; 134 | req->p_obj = robj; 135 | 136 | req->aiocb.data = NULL; 137 | req->aiocb.aio_dev = bd->dev; 138 | req->aiocb.aio_buf = buffer; 139 | req->aiocb.aio_offset = (off_t) (start * blkdev_ssize(bd)); 140 | req->aiocb.aio_nbytes = len * blkdev_ssize(bd); 141 | req->aiocb.aio_cb = _blkdev_async_io_cb; 142 | req->bd = bd; 143 | req->sector = start; 144 | req->nb_sectors = len; 145 | req->write = write; 146 | req->cb = cb; 147 | req->cb_argp = cb_argp; 148 | 149 | retry: 150 | ret = blkfront_aio_enqueue(&(req->aiocb), write); 151 | if (unlikely(ret == -EBUSY)) { 152 | blkdev_async_io_submit(bd); 153 | blkdev_async_io_wait_slot(bd); /* yields CPU */ 154 | goto retry; 155 | } 156 | return ret; 157 | } 158 | #define blkdev_async_write_nocheck(bd, start, len, buffer, cb, cb_argp) \ 159 | blkdev_async_io_nocheck((bd), (start), (len), 1, (buffer), (cb), (cb_argp)) 160 | #define blkdev_async_read_nocheck(bd, start, len, buffer, cb, cb_argp) \ 161 | blkdev_async_io_nocheck((bd), (start), (len), 0, (buffer), (cb), (cb_argp)) 162 | 163 | static inline int blkdev_async_io(struct blkdev *bd, sector_t start, sector_t len, 164 | int write, void *buffer, blkdev_aiocb_t *cb, void *cb_argp) 165 | { 166 | if (unlikely(write && !(bd->info.mode & (O_WRONLY | O_RDWR)))) { 167 | /* write access on non-writable device or read access on non-readable device */ 168 | return -EACCES; 169 | } 170 | 171 | if (unlikely((len * blkdev_ssize(bd)) / PAGE_SIZE > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { 172 | /* request too big -> cannot be handled with a single request */ 173 | return -ENXIO; 174 | } 175 | 176 | if (unlikely(((uintptr_t) buffer) & ((uintptr_t) blkdev_ssize(bd) - 1))) { 177 | /* buffer is not aligned to device sector size */ 178 | return -EINVAL; 179 | } 180 | 181 | return blkdev_async_io_nocheck(bd, start, len, write, buffer, cb, cb_argp); 182 | } 183 | #define blkdev_async_write(bd, start, len, buffer, cb, cb_argp) \ 184 | blkdev_async_io((bd), (start), (len), 1, (buffer), (cb), (cb_argp)) 185 | #define blkdev_async_read(bd, start, len, buffer, cb, cb_argp) \ 186 | blkdev_async_io((bd), (start), (len), 0, (buffer), (cb), (cb_argp)) 187 | 188 | #define blkdev_poll_req(bd) \ 189 | blkfront_aio_poll((bd)->dev) 190 | 191 | #ifdef CONFIG_SELECT_POLL 192 | #define CAN_POLL_BLKDEV 193 | #define blkdev_get_fd(bd) ((bd)->fd) 194 | #endif /* CONFIG_SELECT_POLL */ 195 | 196 | /** 197 | * Sync I/O 198 | */ 199 | void _blkdev_sync_io_cb(int ret, void *argp); 200 | 201 | struct _blkdev_sync_io_sync { 202 | struct semaphore sem; 203 | int ret; 204 | }; 205 | 206 | static inline int blkdev_sync_io_nocheck(struct blkdev *bd, sector_t start, sector_t len, 207 | int write, void *target) 208 | { 209 | struct _blkdev_sync_io_sync iosync; 210 | int ret; 211 | 212 | init_SEMAPHORE(&iosync.sem, 0); 213 | retry: 214 | ret = blkdev_async_io_nocheck(bd, start, len, write, target, 215 | _blkdev_sync_io_cb, &iosync); 216 | blkdev_async_io_submit(bd); 217 | if (unlikely(ret == -EAGAIN)) { 218 | /* try again, queue was full */ 219 | blkdev_poll_req(bd); 220 | schedule(); 221 | goto retry; 222 | } 223 | if (unlikely(ret == -EBUSY)) { 224 | blkdev_async_io_wait_slot(bd); /* yields CPU */ 225 | goto retry; 226 | } 227 | if (unlikely(ret < 0)) 228 | return ret; 229 | 230 | /* wait for I/O completion */ 231 | while (trydown(&iosync.sem) == 0) { 232 | blkdev_poll_req(bd); 233 | schedule(); /* yield CPU */ 234 | } 235 | 236 | return iosync.ret; 237 | } 238 | #define blkdev_sync_write_nocheck(bd, start, len, buffer) \ 239 | blkdev_sync_io_nocheck((bd), (start), (len), 1, (buffer)) 240 | #define blkdev_sync_read_nocheck(bd, start, len, buffer) \ 241 | blkdev_sync_io_nocheck((bd), (start), (len), 0, (buffer)) 242 | 243 | static inline int blkdev_sync_io(struct blkdev *bd, sector_t start, sector_t len, 244 | int write, void *target) 245 | { 246 | if (unlikely(write && !(bd->info.mode & (O_WRONLY | O_RDWR)))) { 247 | /* write access on non-writable device or read access on non-readable device */ 248 | return -EACCES; 249 | } 250 | 251 | if (unlikely((len * blkdev_ssize(bd)) / PAGE_SIZE > BLKIF_MAX_SEGMENTS_PER_REQUEST)) { 252 | /* request too big -> cannot be handled with a single request */ 253 | return -ENXIO; 254 | } 255 | 256 | if (unlikely(((uintptr_t) target) & ((uintptr_t) blkdev_ssize(bd) - 1))) { 257 | /* buffer is not aligned to device sector size */ 258 | return -EINVAL; 259 | } 260 | 261 | return blkdev_sync_io_nocheck(bd, start, len, write, target); 262 | } 263 | #define blkdev_sync_write(bd, start, len, buffer) \ 264 | blkdev_sync_io((bd), (start), (len), 1, (buffer)) 265 | #define blkdev_sync_read(bd, start, len, buffer) \ 266 | blkdev_sync_io((bd), (start), (len), 0, (buffer)) 267 | 268 | #endif /* _BLKDEV_H_ */ 269 | -------------------------------------------------------------------------------- /minios/builtin_open.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the MicroPython project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2013, 2014 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include "py/runtime.h" 28 | #include "extmod/vfs_fat_file.h" 29 | 30 | MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, fatfs_builtin_open); 31 | -------------------------------------------------------------------------------- /minios/debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MiniCache Debugging 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #include "debug.h" 37 | 38 | struct timeval __debug_tsref; 39 | -------------------------------------------------------------------------------- /minios/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MiniCache Debugging 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _DEBUG_H_ 37 | #define _DEBUG_H_ 38 | 39 | //#include 40 | #include 41 | #include 42 | 43 | extern struct timeval __debug_tsref; 44 | 45 | #define init_debug() (gettimeofday(&__debug_tsref, NULL)) 46 | 47 | #ifndef STRINGIFY 48 | #define STRINGIFY(s) #s 49 | #endif 50 | #ifndef XSTRINGIFY 51 | #define XSTRINGIFY(s) STRINGIFY(s) 52 | #endif 53 | 54 | #ifdef ENABLE_DEBUG 55 | #ifdef __MINIOS__ 56 | #if (defined __x86_64__ || defined __x86_32__) 57 | #define CONFIG_DEBUG_CALLDEPTH 58 | #endif 59 | #define __debug_printf(fmt, ...) printk((fmt), ##__VA_ARGS__) 60 | #else 61 | #define __debug_printf(fmt, ...) fprintf(stderr, (fmt), ##__VA_ARGS__) 62 | #endif /* __MINIOS__ */ 63 | 64 | #if defined __MINIOS__ && defined __x86_64__ 65 | #define __get_bp() \ 66 | ({ \ 67 | unsigned long bp; \ 68 | asm("movq %%rbp, %0":"=r"(bp)); \ 69 | bp; \ 70 | }) 71 | #elif defined __MINIOS__ && defined __x86_32__ 72 | #define __get_bp() \ 73 | ({ \ 74 | unsigned long bp; \ 75 | asm("movq %%ebp, %0":"=r"(bp)); \ 76 | bp; \ 77 | }) 78 | #endif 79 | 80 | #if defined __MINIOS__ && (defined __x86_64__ || defined __x86_32__) 81 | /** 82 | * get_caller(): returns calling address for the current function 83 | * 84 | * Note: On non-x86 platforms, 0xBADC0DED is returned 85 | */ 86 | #define get_caller() \ 87 | ({ \ 88 | unsigned long *frame = (void *) __get_bp(); \ 89 | frame[1]; \ 90 | }) 91 | 92 | /** 93 | * get_calldepth(): returns the current number of invoked function calls 94 | * 95 | * Note: On non-x86 platforms, 0x0 is returned always 96 | */ 97 | #define get_calldepth() \ 98 | ({ \ 99 | unsigned long depth = 0; \ 100 | unsigned long *frame = (void *) __get_bp(); \ 101 | while (frame[0]) { \ 102 | ++depth; \ 103 | frame = (void *) frame[0]; \ 104 | } \ 105 | depth; \ 106 | }) 107 | #else 108 | #define get_caller() (0xBADC0DED) 109 | #define get_calldepth() (0x0) 110 | #endif 111 | 112 | /** 113 | * printd(): prints a debug message to stdout 114 | */ 115 | #ifdef CONFIG_DEBUG_CALLDEPTH 116 | #define printd(fmt, ...) \ 117 | do { \ 118 | struct timeval now; \ 119 | uint64_t mins, secs, usecs; \ 120 | unsigned long cd = get_calldepth(); \ 121 | \ 122 | gettimeofday(&now, NULL); \ 123 | if (now.tv_usec < __debug_tsref.tv_usec) { \ 124 | now.tv_usec += 1000000l; \ 125 | now.tv_sec--; \ 126 | } \ 127 | usecs = (now.tv_usec - __debug_tsref.tv_usec); \ 128 | \ 129 | secs = (now.tv_sec - __debug_tsref.tv_sec); \ 130 | secs += usecs / 1000000l; \ 131 | usecs %= 1000000l; \ 132 | mins = secs / 60; \ 133 | secs %= 60; \ 134 | \ 135 | __debug_printf("[%"PRIu64"m%02"PRIu64".%06"PRIu64"s] ", \ 136 | mins, secs, usecs); \ 137 | while (cd--) \ 138 | __debug_printf("-"); \ 139 | __debug_printf(" %s():%d: " \ 140 | fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ 141 | } while(0) 142 | #else 143 | #define printd(fmt, ...) \ 144 | do { \ 145 | struct timeval now; \ 146 | uint64_t mins, secs, usecs; \ 147 | \ 148 | gettimeofday(&now, NULL); \ 149 | if (now.tv_usec < __debug_tsref.tv_usec) { \ 150 | now.tv_usec += 1000000l; \ 151 | now.tv_sec--; \ 152 | } \ 153 | usecs = (now.tv_usec - __debug_tsref.tv_usec); \ 154 | \ 155 | secs = (now.tv_sec - __debug_tsref.tv_sec); \ 156 | secs += usecs / 1000000l; \ 157 | usecs %= 1000000l; \ 158 | mins = secs / 60; \ 159 | secs %= 60; \ 160 | \ 161 | __debug_printf("[%"PRIu64"m%02"PRIu64".%06"PRIu64"s] %s:%4d: %s(): " \ 162 | fmt, mins, secs, usecs, \ 163 | __FILE__, __LINE__, __FUNCTION__, \ 164 | ##__VA_ARGS__); \ 165 | } while(0) 166 | #endif 167 | 168 | #else /* ENABLE_DEBUG */ 169 | 170 | #define printd(fmt, ...) do {} while(0) 171 | #define get_caller() (0xDEADC0DE) 172 | #define get_calldepth() (0x0) 173 | 174 | #endif /* ENABLE_DEBUG */ 175 | 176 | #define tprobe_start(x) \ 177 | uint64_t x; \ 178 | x = target_now_ns(); 179 | #define tprobe_end(x) \ 180 | x = target_now_ns() - x; \ 181 | printk(STRINGIFY(x)": %01"PRIu64".%09"PRIu64"s\n", x / 1000000000ull, x % 1000000000ull); 182 | 183 | #endif /* _DEBUG_H_ */ 184 | -------------------------------------------------------------------------------- /minios/diskio.c: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /* Low level disk I/O module for FatFs on MiniOS */ 3 | /*-----------------------------------------------------------------------*/ 4 | #include "diskio.h" /* FatFs lower layer API */ 5 | #include "blkdev.h" /* MiniOS block device driver */ 6 | 7 | #define XEN_XVDA_DEVID 51712 8 | 9 | /* The block device */ 10 | static struct blkdev *bd = NULL; 11 | 12 | /*-----------------------------------------------------------------------*/ 13 | /* Get Drive Status */ 14 | /*-----------------------------------------------------------------------*/ 15 | DSTATUS disk_status ( 16 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 17 | ) 18 | { 19 | if (bd == NULL) { 20 | return STA_NOINIT; 21 | } 22 | return RES_OK; 23 | } 24 | 25 | /*-----------------------------------------------------------------------*/ 26 | /* Inidialize a Drive */ 27 | /*-----------------------------------------------------------------------*/ 28 | DSTATUS disk_initialize ( 29 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 30 | ) 31 | { 32 | bd = open_blkdev((blkdev_id_t)pdrv * 16 + XEN_XVDA_DEVID, O_RDWR); 33 | if (!bd) return STA_NOINIT; 34 | return RES_OK; 35 | } 36 | 37 | /*-----------------------------------------------------------------------*/ 38 | /* Read Sector(s) */ 39 | /*-----------------------------------------------------------------------*/ 40 | DRESULT disk_read ( 41 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 42 | BYTE *buff, /* Data buffer to store read data */ 43 | DWORD sector, /* Sector address in LBA */ 44 | UINT count /* Number of sectors to read */ 45 | ) 46 | { 47 | void *iobuf; 48 | sector_t slen; 49 | 50 | if (bd == NULL) { 51 | return RES_PARERR; 52 | } 53 | 54 | slen = count * blkdev_ssize(bd); 55 | iobuf = _xmalloc(slen, blkdev_ioalign(bd)); 56 | 57 | if (blkdev_sync_io(bd, (sector_t)sector, count, 0, iobuf) < 0) { 58 | xfree(iobuf); 59 | return RES_ERROR; 60 | } 61 | memcpy(buff, iobuf, slen); 62 | xfree(iobuf); 63 | 64 | return RES_OK; 65 | } 66 | 67 | 68 | 69 | /*-----------------------------------------------------------------------*/ 70 | /* Write Sector(s) */ 71 | /*-----------------------------------------------------------------------*/ 72 | DRESULT disk_write ( 73 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 74 | const BYTE *buff, /* Data to be written */ 75 | DWORD sector, /* Sector address in LBA */ 76 | UINT count /* Number of sectors to write */ 77 | ) 78 | { 79 | void *iobuf; 80 | sector_t slen; 81 | 82 | if (bd == NULL) { 83 | return RES_PARERR; 84 | } 85 | 86 | slen = count * blkdev_ssize(bd); 87 | iobuf = _xmalloc(slen, blkdev_ioalign(bd)); 88 | memcpy(iobuf, buff, slen); 89 | 90 | if (blkdev_sync_io(bd, (sector_t)sector, count, 1, iobuf) < 0) { 91 | xfree(iobuf); 92 | return RES_ERROR; 93 | } 94 | 95 | xfree(iobuf); 96 | return RES_OK; 97 | } 98 | 99 | 100 | 101 | /*-----------------------------------------------------------------------*/ 102 | /* Miscellaneous Functions */ 103 | /*-----------------------------------------------------------------------*/ 104 | DRESULT disk_ioctl ( 105 | BYTE pdrv, /* Physical drive nmuber (0..) */ 106 | BYTE cmd, /* Control code */ 107 | void *buff /* Buffer to send/receive control data */ 108 | ) 109 | { 110 | if (bd == NULL) { 111 | return RES_PARERR; 112 | } 113 | 114 | switch (cmd) { 115 | case CTRL_SYNC: { 116 | /* not yet supported by the block device driver */ 117 | return RES_OK; 118 | } 119 | case GET_SECTOR_COUNT: { 120 | *((DWORD*)buff) = blkdev_sectors(bd); 121 | return RES_OK; 122 | } 123 | case GET_SECTOR_SIZE: { 124 | *((DWORD*)buff) = blkdev_ssize(bd); 125 | return RES_OK; 126 | } 127 | case GET_BLOCK_SIZE: { 128 | *((DWORD*)buff) = 1; // erase block size in units of sector size 129 | return RES_OK; 130 | } 131 | default: { 132 | return RES_PARERR; 133 | } 134 | } 135 | 136 | return RES_PARERR; 137 | } 138 | -------------------------------------------------------------------------------- /minios/diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------/ 2 | / Low level disk interface modlue include file / 3 | /-----------------------------------------------------------------------*/ 4 | #include "../lib/fatfs/integer.h" 5 | 6 | /* Status of Disk Functions */ 7 | typedef BYTE DSTATUS; 8 | 9 | /* Results of Disk Functions */ 10 | typedef enum { 11 | RES_OK = 0, /* 0: Successful */ 12 | RES_ERROR, /* 1: R/W Error */ 13 | RES_WRPRT, /* 2: Write Protected */ 14 | RES_NOTRDY, /* 3: Not Ready */ 15 | RES_PARERR /* 4: Invalid Parameter */ 16 | } DRESULT; 17 | 18 | /* Prototypes for disk control functions */ 19 | DSTATUS disk_initialize (BYTE pdrv); 20 | DSTATUS disk_status (BYTE pdrv); 21 | DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); 22 | DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); 23 | DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); 24 | 25 | /* Disk Status Bits (DSTATUS) */ 26 | #define STA_NOINIT 0x01 /* Drive not initialized */ 27 | #define STA_NODISK 0x02 /* No medium in the drive */ 28 | #define STA_PROTECT 0x04 /* Write protected */ 29 | 30 | /* Generic command (Used by FatFs) */ 31 | #define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */ 32 | #define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */ 33 | #define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */ 34 | #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */ 35 | #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ 36 | 37 | /* Generic command (Not used by FatFs) */ 38 | #define CTRL_POWER 5 /* Get/Set power status */ 39 | #define CTRL_LOCK 6 /* Lock/Unlock media removal */ 40 | #define CTRL_EJECT 7 /* Eject media */ 41 | #define CTRL_FORMAT 8 /* Create physical format on the media */ 42 | 43 | /* MMC/SDC specific ioctl command */ 44 | #define MMC_GET_TYPE 10 /* Get card type */ 45 | #define MMC_GET_CSD 11 /* Get CSD */ 46 | #define MMC_GET_CID 12 /* Get CID */ 47 | #define MMC_GET_OCR 13 /* Get OCR */ 48 | #define MMC_GET_SDSTAT 14 /* Get SD status */ 49 | 50 | /* ATA/CF specific ioctl command */ 51 | #define ATA_GET_REV 20 /* Get F/W revision */ 52 | #define ATA_GET_MODEL 21 /* Get model name */ 53 | #define ATA_GET_SN 22 /* Get serial number */ 54 | -------------------------------------------------------------------------------- /minios/examples/helloworld.py: -------------------------------------------------------------------------------- 1 | print("Hello world!") 2 | -------------------------------------------------------------------------------- /minios/examples/http_client.py: -------------------------------------------------------------------------------- 1 | try: 2 | import usocket as socket 3 | except: 4 | import socket 5 | 6 | 7 | def main(use_stream=False): 8 | s = socket.socket() 9 | 10 | ai = socket.getaddrinfo("google.com", 80) 11 | print("Address infos:", ai) 12 | addr = ai[0][-1] 13 | 14 | print("Connect address:", addr) 15 | s.connect(addr) 16 | 17 | if use_stream: 18 | # MicroPython socket objects support stream (aka file) interface 19 | # directly, but the line below is needed for CPython. 20 | s = s.makefile("rwb", 0) 21 | s.write(b"GET / HTTP/1.0\n\n") 22 | print(s.readall()) 23 | else: 24 | s.send(b"GET / HTTP/1.0\n\n") 25 | print(s.recv(4096)) 26 | 27 | 28 | main() 29 | -------------------------------------------------------------------------------- /minios/examples/http_server.py: -------------------------------------------------------------------------------- 1 | try: 2 | import usocket as socket 3 | except: 4 | import socket 5 | 6 | def readfile(filename): 7 | f = open(filename, 'r') 8 | s = f.read() 9 | f.close() 10 | return s 11 | 12 | def main(): 13 | s = socket.socket() 14 | 15 | ai = socket.getaddrinfo("0.0.0.0", 8080) 16 | addr = ai[0][-1] 17 | 18 | s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 19 | s.bind(addr) 20 | s.listen(5) 21 | print("Listening, connect your browser to http://172.64.0.100:8080/") 22 | 23 | while True: 24 | f = readfile("index.html") 25 | res = s.accept() 26 | client_s = res[0] 27 | client_addr = res[1] 28 | client_s.recv(4096) 29 | client_s.send(f) 30 | client_s.close() 31 | 32 | main() 33 | -------------------------------------------------------------------------------- /minios/examples/pinger.py: -------------------------------------------------------------------------------- 1 | import lwip 2 | lwip.reset() 3 | eth = lwip.ether('172.64.0.100', '255.255.255.0', '0.0.0.0') 4 | 5 | while 1: eth.poll() 6 | -------------------------------------------------------------------------------- /minios/examples/readfile.py: -------------------------------------------------------------------------------- 1 | f = open('index.html', 'r') 2 | s = f.read() 3 | print(s) 4 | f.close() 5 | -------------------------------------------------------------------------------- /minios/examples/test_time.py: -------------------------------------------------------------------------------- 1 | #import utime as time 2 | import time 3 | 4 | start = time.clock() 5 | for x in range(0, 10000000): 6 | pass 7 | end = time.clock() 8 | elapsed = end - start 9 | print("Time: " + str(elapsed)) 10 | -------------------------------------------------------------------------------- /minios/examples/test_tryexcept.py: -------------------------------------------------------------------------------- 1 | mods = ['_libc', '_markupbase', 'abc', 'argparse', 'asyncio_slow', 'base64', 'binascii', 'bisect', 'cgi', 'cmd', 'collections.defaultdict', 'collections.deque', 'collections', 'concurrent.futures', 'contextlib', 'copy', 'curses.ascii', 'email.charset', 'email.encoders', 'email.errors', 'email.feedparser', 'email.header', 'email.internal', 'email.message', 'email.parser', 'email.utils', 'errno', 'fcntl', 'ffilib', 'fnmatch', 'functools', 'getopt', 'glob', 'gzip', 'hashlib', 'heapq', 'hmac', 'html.entities', 'html.parser', 'html', 'http.client', 'inspect', 'io', 'itertools', 'json', 'keyword', 'locale', 'logging', 'machine', 'multiprocessing', 'operator', 'os.path', 'os', 'pickle', 'pkg_resources', 'pkgutil', 'pprint', 'pyb', 'pystone', 'pystone_lowmem', 'quopri', 'select', 'shutil', 'signal', 'socket', 'sqlite3', 'stat', 'string', 'struct', 'test.pystone', 'test.support', 'textwrap', 'time', 'timeit', 'traceback', 'tty', 'types', 'uasyncio.core', 'uasyncio.queues', 'uasyncio', 'ucontextlib', 'ucurses', 'unicodedata', 'unittest', 'upip', 'upysh', 'urequests', 'urllib.parse', 'urllib.urequest', 'utarfile', 'uu', 'warnings', 'weakref', 'xmltok'] 2 | 3 | WORKING = [] 4 | BROKEN = [] 5 | for m in mods: 6 | try: 7 | __import__(m) 8 | WORKING.append(m) 9 | except: 10 | BROKEN.append(m) 11 | 12 | print("\nWorking modules:\n===========================\n" + str(WORKING)) 13 | print("\nBroken modules:\n===========================\n" + str(BROKEN)) 14 | -------------------------------------------------------------------------------- /minios/examples/testcar.py: -------------------------------------------------------------------------------- 1 | from vehicles.car import Car 2 | c = Car() 3 | print(c.type()) 4 | -------------------------------------------------------------------------------- /minios/examples/vehicles/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysml/minipython/6dbf93c4e4c81cc02032e693636212b7ce2eb1ed/minios/examples/vehicles/__init__.py -------------------------------------------------------------------------------- /minios/examples/vehicles/car.py: -------------------------------------------------------------------------------- 1 | class Car: 2 | def __init__(self): 3 | pass 4 | 5 | def type(self): 6 | return "Fiat" 7 | -------------------------------------------------------------------------------- /minios/fatfs_port.c: -------------------------------------------------------------------------------- 1 | #include "lib/fatfs/ff.h" 2 | #include "lib/fatfs/diskio.h" 3 | 4 | DWORD get_fattime(void) { 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /minios/frozentest.mpy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sysml/minipython/6dbf93c4e4c81cc02032e693636212b7ce2eb1ed/minios/frozentest.mpy -------------------------------------------------------------------------------- /minios/frozentest.py: -------------------------------------------------------------------------------- 1 | print('uPy') 2 | print('a long string that is not interned') 3 | print('a string that has unicode αβγ chars') 4 | print(b'bytes 1234\x01') 5 | print(123456789) 6 | for i in range(4): 7 | print(i) 8 | -------------------------------------------------------------------------------- /minios/gccollect.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Micro Python project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2013, 2014 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | 29 | #include "py/mpstate.h" 30 | #include "py/gc.h" 31 | 32 | #if MICROPY_ENABLE_GC 33 | 34 | extern void mp_unix_mark_exec(void); 35 | 36 | // Even if we have specific support for an architecture, it is 37 | // possible to force use of setjmp-based implementation. 38 | #if !MICROPY_GCREGS_SETJMP 39 | 40 | // We capture here callee-save registers, i.e. ones which may contain 41 | // interesting values held there by our callers. It doesn't make sense 42 | // to capture caller-saved registers, because they, well, put on the 43 | // stack already by the caller. 44 | #if defined(__x86_64__) 45 | typedef mp_uint_t regs_t[6]; 46 | 47 | STATIC void gc_helper_get_regs(regs_t arr) { 48 | register long rbx asm ("rbx"); 49 | register long rbp asm ("rbp"); 50 | register long r12 asm ("r12"); 51 | register long r13 asm ("r13"); 52 | register long r14 asm ("r14"); 53 | register long r15 asm ("r15"); 54 | #ifdef __clang__ 55 | // TODO: 56 | // This is dirty workaround for Clang. It tries to get around 57 | // uncompliant (wrt to GCC) behavior of handling register variables. 58 | // Application of this patch here is random, and done only to unbreak 59 | // MacOS build. Better, cross-arch ways to deal with Clang issues should 60 | // be found. 61 | asm("" : "=r"(rbx)); 62 | asm("" : "=r"(rbp)); 63 | asm("" : "=r"(r12)); 64 | asm("" : "=r"(r13)); 65 | asm("" : "=r"(r14)); 66 | asm("" : "=r"(r15)); 67 | #endif 68 | arr[0] = rbx; 69 | arr[1] = rbp; 70 | arr[2] = r12; 71 | arr[3] = r13; 72 | arr[4] = r14; 73 | arr[5] = r15; 74 | } 75 | 76 | #elif defined(__i386__) 77 | 78 | typedef mp_uint_t regs_t[4]; 79 | 80 | STATIC void gc_helper_get_regs(regs_t arr) { 81 | register long ebx asm ("ebx"); 82 | register long esi asm ("esi"); 83 | register long edi asm ("edi"); 84 | register long ebp asm ("ebp"); 85 | arr[0] = ebx; 86 | arr[1] = esi; 87 | arr[2] = edi; 88 | arr[3] = ebp; 89 | } 90 | 91 | #elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__) 92 | 93 | typedef mp_uint_t regs_t[10]; 94 | 95 | STATIC void gc_helper_get_regs(regs_t arr) { 96 | register long r4 asm ("r4"); 97 | register long r5 asm ("r5"); 98 | register long r6 asm ("r6"); 99 | register long r7 asm ("r7"); 100 | register long r8 asm ("r8"); 101 | register long r9 asm ("r9"); 102 | register long r10 asm ("r10"); 103 | register long r11 asm ("r11"); 104 | register long r12 asm ("r12"); 105 | register long r13 asm ("r13"); 106 | arr[0] = r4; 107 | arr[1] = r5; 108 | arr[2] = r6; 109 | arr[3] = r7; 110 | arr[4] = r8; 111 | arr[5] = r9; 112 | arr[6] = r10; 113 | arr[7] = r11; 114 | arr[8] = r12; 115 | arr[9] = r13; 116 | } 117 | 118 | #else 119 | 120 | // If we don't have architecture-specific optimized support, 121 | // just fall back to setjmp-based implementation. 122 | #undef MICROPY_GCREGS_SETJMP 123 | #define MICROPY_GCREGS_SETJMP (1) 124 | 125 | #endif // Arch-specific selection 126 | #endif // !MICROPY_GCREGS_SETJMP 127 | 128 | // If MICROPY_GCREGS_SETJMP was requested explicitly, or if 129 | // we enabled it as a fallback above. 130 | #if MICROPY_GCREGS_SETJMP 131 | #include 132 | 133 | typedef jmp_buf regs_t; 134 | 135 | STATIC void gc_helper_get_regs(regs_t arr) { 136 | setjmp(arr); 137 | } 138 | 139 | #endif // MICROPY_GCREGS_SETJMP 140 | 141 | void gc_collect(void) { 142 | //gc_dump_info(); 143 | 144 | gc_collect_start(); 145 | regs_t regs; 146 | gc_helper_get_regs(regs); 147 | // GC stack (and regs because we captured them) 148 | void **regs_ptr = (void**)(void*)®s; 149 | gc_collect_root(regs_ptr, ((uintptr_t)MP_STATE_VM(stack_top) - (uintptr_t)®s) / sizeof(uintptr_t)); 150 | #if MICROPY_EMIT_NATIVE 151 | mp_unix_mark_exec(); 152 | #endif 153 | gc_collect_end(); 154 | 155 | //printf("-----\n"); 156 | //gc_dump_info(); 157 | } 158 | 159 | #endif //MICROPY_ENABLE_GC 160 | -------------------------------------------------------------------------------- /minios/hexdump.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Hexdump-like routines 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #include 48 | 49 | #ifndef min 50 | #define min(a, b) \ 51 | ({ __typeof__ (a) __a = (a); \ 52 | __typeof__ (b) __b = (b); \ 53 | __a < __b ? __a : __b; }) 54 | #endif 55 | 56 | /** 57 | * @buf: data blob to dump 58 | * @len: number of bytes in the @buf 59 | * @rowsize: number of buffer bytes to print per line; must be 16, 32, 60 | * 64, or 128 61 | * @groupsize: number of bytes to print as group together (1, 2, 4, 8) 62 | * @linebuf: where to put the hexdump string 63 | * @linebuflen: total size of @linebuf, including terminating \0 character 64 | * @show_ascii_comlumn: include ASCII after the hex output 65 | * 66 | * _hdline2buf() prints a single "line" of output at a time, i.e., 67 | * 16 or 32 bytes of input data converted to hex + ASCII output. 68 | * 69 | * Given a buffer of uint8_t data, _hdline2buf() converts the input data 70 | * to a hex + ASCII dump at the supplied memory location. 71 | * The converted output (string) is always NUL-terminated (\0). 72 | */ 73 | static inline size_t _hdline2buf(const void *buf, size_t len, 74 | size_t rowlen, size_t groupsize, 75 | int show_ascii_column, 76 | char *trglinebuf, size_t trglinebuflen) 77 | { 78 | const uint8_t *ptr = buf; 79 | uint8_t ch; 80 | size_t nb_groups, group, byte; 81 | size_t trglinebufpos = 0; 82 | 83 | if (!len) 84 | goto eol; 85 | if (len > rowlen) /* limit input to rowlen */ 86 | len = rowlen; 87 | nb_groups = rowlen / groupsize; 88 | 89 | if (show_ascii_column) 90 | ASSERT(trglinebuflen >= (((3 * groupsize) * nb_groups) - 1) + (nb_groups) + 1); 91 | else 92 | ASSERT(trglinebuflen >= (((3 * groupsize) * nb_groups) - 1) + (2 * nb_groups) + 1 + ((groupsize * nb_groups) - 1) + 1); 93 | 94 | for (group = 0; group < nb_groups; group++) { 95 | if (group) /* leading space for group */ 96 | trglinebufpos += snprintf(trglinebuf + trglinebufpos, trglinebuflen - trglinebufpos, " "); 97 | 98 | for (byte = ( group * groupsize); 99 | byte < ((group + 1)* groupsize); 100 | byte++) { 101 | if (byte < len) { /* print hex number */ 102 | ptr = ((uint8_t *) buf) + byte; 103 | trglinebufpos += snprintf(trglinebuf + trglinebufpos, trglinebuflen - trglinebufpos, 104 | "%s%02x", (group || byte) ? " " : "", *(ptr)); 105 | } else { /* print white space */ 106 | if (!show_ascii_column) 107 | goto eol; 108 | trglinebufpos += snprintf(trglinebuf + trglinebufpos, trglinebuflen - trglinebufpos, 109 | "%s ", (group || byte) ? " " : ""); 110 | } 111 | } 112 | } 113 | 114 | if (show_ascii_column) { 115 | trglinebufpos += snprintf(trglinebuf + trglinebufpos, trglinebuflen - trglinebufpos, " "); 116 | 117 | for (group = 0; group < nb_groups; group++) { 118 | if (group) /* leading space for group */ 119 | trglinebufpos += snprintf(trglinebuf + trglinebufpos, trglinebuflen - trglinebufpos, " "); 120 | 121 | for (byte = ( group * groupsize); 122 | byte < ((group + 1)* groupsize); 123 | byte++) { 124 | if (byte < len) { /* print ascii character */ 125 | ptr = ((uint8_t *) buf) + byte; 126 | ch = (char) *(ptr); 127 | trglinebufpos += snprintf(trglinebuf + trglinebufpos, trglinebuflen - trglinebufpos, 128 | "%c", (ch >= 32 && ch <= 126) ? ch : '.'); 129 | } else { 130 | break; 131 | } 132 | } 133 | } 134 | } 135 | eol: 136 | trglinebuf[trglinebufpos++] = '\0'; 137 | return trglinebufpos; 138 | } 139 | 140 | void hexdump(FILE *cout, const void *buf, size_t len, 141 | const char *prefix_str, enum hd_addr_type addr_type, 142 | off_t addr_offset, size_t rowlen, size_t groupsize, 143 | int show_ascii_column) 144 | { 145 | const uint8_t *ptr; 146 | size_t i, linelen, remaining; 147 | char linebuf[512]; 148 | 149 | ASSERT(rowlen == 16 || rowlen == 32 || rowlen == 64 || rowlen == 128); 150 | ASSERT(groupsize == 1 || groupsize == 2 || groupsize == 4 || groupsize == 8); 151 | 152 | ptr = buf; 153 | remaining = len; 154 | 155 | for (i = 0; i < len; i += rowlen) { 156 | linelen = min(remaining, rowlen); 157 | remaining -= linelen; 158 | 159 | _hdline2buf(ptr + i, linelen, rowlen, groupsize, 160 | show_ascii_column, linebuf, sizeof(linebuf)); 161 | 162 | switch (addr_type) { 163 | case HDAT_ABSOLUTE: 164 | fprintf(cout, "%s%p: %s\n", 165 | prefix_str, ptr + i, linebuf); 166 | break; 167 | case HDAT_RELATIVE: 168 | fprintf(cout, "%s%.8x: %s\n", prefix_str, i + addr_offset, linebuf); 169 | break; 170 | default: /* HDAT_NONE */ 171 | fprintf(cout, "%s%s\n", prefix_str, linebuf); 172 | break; 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /minios/hexdump.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Hexdump-like routines 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _HEXDUMP_H_ 37 | #define _HEXDUMP_H_ 38 | 39 | enum hd_addr_type { 40 | HDAT_NONE = 0, 41 | HDAT_RELATIVE, 42 | HDAT_ABSOLUTE 43 | }; 44 | 45 | /** 46 | * hexdump - print a text hexdump for a binary blob of data 47 | * @buf: data blob to dump 48 | * @len: number of bytes in the @buf 49 | * @prefix_str: null-terminated string that is prefixed to each line 50 | * @addr_type: controls whether the offset address, full address, or none 51 | * is printed in front of each line (%HDAT_RELATIVE, %HDAT_ABSOLUTE, 52 | * %HDAT_NONE) 53 | * @addr_offset: An offset that is added to each printed address if %addr_tpe is 54 | * set to %HDAT_RELATIVE 55 | * @rowlen: number of buffer bytes to print per line 56 | * @groupsize: number of bytes to print as group together 57 | * @show_ascii_comlumn: include ASCII after the hex output 58 | * 59 | * Example output using %HDAT_RELATIVE and 4-byte mode: 60 | * 0009ab42: 40 41 42 43 44 45 46 47 @ABCD EFGH 61 | * Example output using %HDAT_ABSOLUTE and 2-byte mode: 62 | * ffffffff88089af0: 73 72 71 70 77 76 75 74 pq rs tu vw 63 | */ 64 | void hexdump(FILE *cout, const void *buf, size_t len, 65 | const char *prefix_str, enum hd_addr_type addr_type, 66 | off_t addr_offset ,size_t rowsize, size_t groupsize, 67 | int show_ascii_column); 68 | 69 | /** 70 | * printh - shorthand form of print_hex_dump() with default params 71 | * @buf: data blob to dump 72 | * @len: number of bytes in the @buf 73 | * 74 | * Calls hexdump(), with rowsize of 16, groupsize of 4, 75 | * and enabled ASCII column output. 76 | */ 77 | #define printh(buf, len) \ 78 | hexdump((stdout), (buf), (len), "", HDAT_RELATIVE, 0, 16, 4, 1) 79 | 80 | #endif /* _HEXDUMP_H_ */ 81 | -------------------------------------------------------------------------------- /minios/input.h: -------------------------------------------------------------------------------- 1 | char *prompt(char *p); 2 | void prompt_read_history(void); 3 | void prompt_write_history(void); 4 | -------------------------------------------------------------------------------- /minios/likely.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Branching hints 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _LIKELY_H_ 37 | #define _LIKELY_H_ 38 | 39 | #ifndef likely 40 | #define likely(_x) (__builtin_expect((!!(_x)), 1)) 41 | #endif 42 | 43 | #ifndef unlikely 44 | #define unlikely(_x) (__builtin_expect((!!(_x)), 0)) 45 | #endif 46 | 47 | #endif /* _LIKELY_H_ */ 48 | -------------------------------------------------------------------------------- /minios/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Minipython, a Xen-based Unikernel. 3 | * 4 | * Authors: Felipe Huici 5 | * Simon Kuenzer 6 | * 7 | * 8 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * 1. Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 3. Neither the name of the copyright holder nor the names of its 20 | * contributors may be used to endorse or promote products derived from 21 | * this software without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 | * POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | */ 36 | 37 | #include "minipython.h" 38 | 39 | void run_script() { 40 | do_file("helloworld-infinite.py"); 41 | // do_str("print('hello world')"); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /minios/minipython.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Minipython, a Xen-based Unikernel. 3 | * 4 | * Authors: Felipe Huici 5 | * Simon Kuenzer 6 | * 7 | * 8 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 9 | * 10 | * Redistribution and use in source and binary forms, with or without 11 | * modification, are permitted provided that the following conditions 12 | * are met: 13 | * 14 | * 1. Redistributions of source code must retain the above copyright 15 | * notice, this list of conditions and the following disclaimer. 16 | * 2. Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 3. Neither the name of the copyright holder nor the names of its 20 | * contributors may be used to endorse or promote products derived from 21 | * this software without specific prior written permission. 22 | * 23 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 | * POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | */ 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | #include "console.h" 50 | #include "py/mpstate.h" 51 | #include "py/nlr.h" 52 | #include "py/compile.h" 53 | #include "py/runtime.h" 54 | #include "py/builtin.h" 55 | #include "py/repl.h" 56 | #include "py/gc.h" 57 | #include "py/stackctrl.h" 58 | #include "py/mphal.h" 59 | #include "extmod/misc.h" 60 | #include "genhdr/mpversion.h" 61 | #include "input.h" 62 | #if SHFS_ENABLE 63 | #include "shfs/shfs.h" 64 | #include "shfs/shfs_fio.h" 65 | #endif 66 | #if MICROPY_VFS_FAT 67 | #include "lib/fatfs/ff.h" 68 | #include "extmod/fsusermount.h" 69 | extern mp_lexer_t *fat_vfs_lexer_new_from_file(const char *filename); 70 | extern mp_import_stat_t fat_vfs_import_stat(const char *path); 71 | #endif 72 | 73 | int handle_uncaught_exception(mp_obj_base_t *exc); 74 | int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl); 75 | 76 | #if SHFS_ENABLE 77 | STATIC mp_uint_t shfs_file_buf_next_byte(mp_lexer_file_buf_t *fb); 78 | STATIC void shfs_file_buf_close(mp_lexer_file_buf_t *fb); 79 | mp_lexer_t *mp_lexer_new_from_file(const char *filename); 80 | #endif 81 | 82 | #if MICROPY_VFS_FAT 83 | mp_lexer_t *mp_lexer_new_from_file(const char *filename); 84 | mp_obj_t vfs_proxy_call(qstr method_name, mp_uint_t n_args, const mp_obj_t *args); 85 | #endif 86 | 87 | int do_str(const char *str); 88 | int do_file(const char *file); 89 | void print_banner(); 90 | uint mp_import_stat(const char *path); 91 | void nlr_jump_fail(void *val); 92 | void pythonpath_append(char *path); 93 | int main(int argc, char **argv); 94 | -------------------------------------------------------------------------------- /minios/minipython.xen: -------------------------------------------------------------------------------- 1 | kernel = "build/minipython_x86_64.gz" 2 | memory = "16" 3 | cpus = ["0"] 4 | vcpus = "1" 5 | name = "minipython" 6 | 7 | vif = [ 'mac=00:11:22:33:44:55,bridge=minipythonbr,ip=10.0.1.1' ] 8 | disk = ['phy:/dev/loop0,xvda,w'] 9 | 10 | on_poweroff = "preserve" 11 | on_crash = "preserve" 12 | on_reboot = "preserve" 13 | -------------------------------------------------------------------------------- /minios/mkenv_minios.mk: -------------------------------------------------------------------------------- 1 | ifneq ($(lastword a b),b) 2 | $(error These Makefiles require make 3.81 or newer) 3 | endif 4 | 5 | # Set TOP to be the path to get from the current directory (where make was 6 | # invoked) to the top of the tree. $(lastword $(MAKEFILE_LIST)) returns 7 | # the name of this makefile relative to where make was invoked. 8 | # 9 | # We assume that this file is in the py directory so we use $(dir ) twice 10 | # to get to the top of the tree. 11 | 12 | THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST)) 13 | TOP := .. 14 | 15 | #BUILD ?= build 16 | PY_BUILD = $(BUILD)/py 17 | 18 | # where autogenerated header files go 19 | HEADER_BUILD = $(BUILD)/genhdr 20 | 21 | # file containing qstr defs for the core Python bit 22 | PY_QSTR_DEFS = $(PY_SRC)/qstrdefs.h 23 | 24 | QSTR_DEFS_COLLECTED = $(HEADER_BUILD)/qstrdefs.collected.h 25 | 26 | # py object files 27 | PY_O_BASENAME = \ 28 | mpstate.o \ 29 | nlrx86.o \ 30 | nlrx64.o \ 31 | nlrthumb.o \ 32 | nlrxtensa.o \ 33 | nlrsetjmp.o \ 34 | malloc.o \ 35 | gc.o \ 36 | qstr.o \ 37 | vstr.o \ 38 | mpprint.o \ 39 | unicode.o \ 40 | mpz.o \ 41 | lexer.o \ 42 | lexerstr.o \ 43 | parse.o \ 44 | scope.o \ 45 | compile.o \ 46 | emitcommon.o \ 47 | emitbc.o \ 48 | asmx64.o \ 49 | emitnx64.o \ 50 | asmx86.o \ 51 | emitnx86.o \ 52 | asmthumb.o \ 53 | emitnthumb.o \ 54 | emitinlinethumb.o \ 55 | asmarm.o \ 56 | emitnarm.o \ 57 | formatfloat.o \ 58 | parsenumbase.o \ 59 | parsenum.o \ 60 | emitglue.o \ 61 | runtime.o \ 62 | runtime_utils.o \ 63 | nativeglue.o \ 64 | stackctrl.o \ 65 | argcheck.o \ 66 | warning.o \ 67 | map.o \ 68 | obj.o \ 69 | objarray.o \ 70 | objattrtuple.o \ 71 | objbool.o \ 72 | objboundmeth.o \ 73 | objcell.o \ 74 | objclosure.o \ 75 | objcomplex.o \ 76 | objdict.o \ 77 | objenumerate.o \ 78 | objexcept.o \ 79 | objfilter.o \ 80 | objfloat.o \ 81 | objfun.o \ 82 | objgenerator.o \ 83 | objgetitemiter.o \ 84 | objint.o \ 85 | objint_longlong.o \ 86 | objint_mpz.o \ 87 | objlist.o \ 88 | objmap.o \ 89 | objmodule.o \ 90 | objobject.o \ 91 | objpolyiter.o \ 92 | objproperty.o \ 93 | objnone.o \ 94 | objnamedtuple.o \ 95 | objrange.o \ 96 | objreversed.o \ 97 | objset.o \ 98 | objsingleton.o \ 99 | objslice.o \ 100 | objstr.o \ 101 | objstrunicode.o \ 102 | objstringio.o \ 103 | objtuple.o \ 104 | objtype.o \ 105 | objzip.o \ 106 | opmethods.o \ 107 | sequence.o \ 108 | stream.o \ 109 | binary.o \ 110 | builtinimport.o \ 111 | builtinevex.o \ 112 | modarray.o \ 113 | modbuiltins.o \ 114 | modcollections.o \ 115 | modgc.o \ 116 | modio.o \ 117 | modmath.o \ 118 | modcmath.o \ 119 | modmicropython.o \ 120 | modstruct.o \ 121 | modsys.o \ 122 | vm.o \ 123 | bc.o \ 124 | showbc.o \ 125 | repl.o \ 126 | smallint.o \ 127 | frozenmod.o \ 128 | ../extmod/moductypes.o \ 129 | ../extmod/modure.o \ 130 | ../extmod/moduzlib.o \ 131 | ../extmod/moduheapq.o \ 132 | ../extmod/moduhashlib.o \ 133 | ../extmod/modubinascii.o \ 134 | ../extmod/machine_mem.o \ 135 | ../extmod/machine_i2c.o \ 136 | ../extmod/modussl.o \ 137 | ../extmod/modurandom.o \ 138 | ../extmod/modwebsocket.o \ 139 | ../extmod/modwebrepl.o \ 140 | ../extmod/modframebuf.o \ 141 | ../extmod/fsusermount.o \ 142 | ../extmod/modujson.o \ 143 | ../extmod/moduos_dupterm.o 144 | 145 | ifeq ($(CONFIG_SHFS),n) 146 | PY_O_BASENAME += ../extmod/vfs_fat.o \ 147 | ../extmod/vfs_fat_ffconf.o \ 148 | ../extmod/vfs_fat_file.o \ 149 | ../extmod/vfs_fat_lexer.o \ 150 | ../extmod/vfs_fat_misc.o \ 151 | ../lib/fatfs/ff.o \ 152 | ../lib/fatfs/option/cc932.o 153 | endif 154 | 155 | ifeq ($(CONFIG_LWIP),y) 156 | LWIP_ROOT ?= $(realpath ../../toolchain)/x86_64-root/x86_64-xen-elf 157 | SRC_MOD += ../lib/netutils/netutils.c 158 | SRC_MOD += $(addprefix $(LWIP_ROOT)/src/lwip/,\ 159 | core/def.c \ 160 | core/dns.c \ 161 | core/init.c \ 162 | core/mem.c \ 163 | core/memp.c \ 164 | core/netif.c \ 165 | core/pbuf.c \ 166 | core/raw.c \ 167 | core/stats.c \ 168 | core/sys.c \ 169 | core/tcp.c \ 170 | core/tcp_in.c \ 171 | core/tcp_out.c \ 172 | core/timers.c \ 173 | core/udp.c \ 174 | core/ipv4/autoip.c \ 175 | core/ipv4/icmp.c \ 176 | core/ipv4/igmp.c \ 177 | core/ipv4/ip4_addr.c \ 178 | core/ipv4/ip4.c \ 179 | core/ipv4/ip_frag.c \ 180 | ) 181 | endif 182 | 183 | SRC_MOD += builtin_open.c \ 184 | 185 | APP_MODS_SRC_C = $(addprefix mods/,\ 186 | modusocket.c \ 187 | modtime.c \ 188 | modos.c \ 189 | modlwip.c \ 190 | ) 191 | 192 | # prepend the build destination prefix to the py object files 193 | PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME)) 194 | 195 | # Sources that may contain qstrings 196 | SRC_QSTR_IGNORE = nlr% emitnx% emitnthumb% emitnarm% 197 | SRC_QSTR = $(SRC_MOD) $(APP_MODS_SRC_C) $(addprefix ../py/,$(filter-out $(SRC_QSTR_IGNORE),$(PY_O_BASENAME:.o=.c)) emitnative.c) 198 | 199 | PY_SRC ?= $(TOP)/py 200 | -------------------------------------------------------------------------------- /minios/mods/modlwip.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Micro Python project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2013, 2014 Damien P. George 7 | * Copyright (c) 2015 Galen Hazelwood 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "py/nlr.h" 33 | #include "py/objlist.h" 34 | #include "py/runtime.h" 35 | #include "py/stream.h" 36 | #include "py/mphal.h" 37 | 38 | #include "netutils.h" 39 | 40 | #include "lwip/init.h" 41 | #include "lwip/timers.h" 42 | #include "lwip/tcp.h" 43 | #include "lwip/udp.h" 44 | #include "lwip/dns.h" 45 | #include "lwip/tcp_impl.h" 46 | #include "lwip/netif.h" 47 | #include "lwip/inet.h" 48 | #include 49 | 50 | typedef struct _lwip_socket_obj_t { 51 | mp_obj_base_t base; 52 | 53 | volatile union { 54 | struct tcp_pcb *tcp; 55 | struct udp_pcb *udp; 56 | } pcb; 57 | volatile union { 58 | struct pbuf *pbuf; 59 | struct tcp_pcb *connection; 60 | } incoming; 61 | mp_obj_t callback; 62 | byte peer[4]; 63 | mp_uint_t peer_port; 64 | mp_uint_t timeout; 65 | uint16_t leftover_count; 66 | 67 | uint8_t domain; 68 | uint8_t type; 69 | 70 | #define STATE_NEW 0 71 | #define STATE_CONNECTING 1 72 | #define STATE_CONNECTED 2 73 | #define STATE_PEER_CLOSED 3 74 | // Negative value is lwIP error 75 | int8_t state; 76 | } lwip_socket_obj_t; 77 | 78 | struct mcargs { 79 | struct eth_addr mac; 80 | struct netif netif; 81 | ip4_addr_t ip; 82 | ip4_addr_t mask; 83 | ip4_addr_t gw; 84 | #if LWIP_DNS 85 | ip4_addr_t dns0; 86 | ip4_addr_t dns1; 87 | #endif 88 | } args; 89 | 90 | 91 | void lwip_socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); 92 | mp_obj_t lwip_socket_close(mp_obj_t self_in); 93 | mp_obj_t lwip_socket_bind(mp_obj_t self_in, mp_obj_t addr_in); 94 | mp_obj_t lwip_socket_listen(mp_obj_t self_in, mp_obj_t backlog_in); 95 | mp_obj_t lwip_socket_accept(mp_obj_t self_in); 96 | mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in); 97 | void lwip_socket_check_connected(lwip_socket_obj_t *socket); 98 | mp_obj_t lwip_socket_send(mp_obj_t self_in, mp_obj_t buf_in); 99 | mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in); 100 | mp_obj_t lwip_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in); 101 | mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in); 102 | mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in); 103 | mp_obj_t lwip_socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in); 104 | mp_obj_t lwip_socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in); 105 | mp_obj_t lwip_socket_setsockopt(mp_uint_t n_args, const mp_obj_t *args); 106 | mp_obj_t lwip_socket_makefile(mp_uint_t n_args, const mp_obj_t *args); 107 | mp_uint_t lwip_socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode); 108 | mp_uint_t lwip_socket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode); 109 | mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args); 110 | mp_obj_t lwip_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in); 111 | -------------------------------------------------------------------------------- /minios/mods/modos.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Micro Python project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2013, 2014 Damien P. George 7 | * Copyright (c) 2014 Paul Sokolovsky 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "py/mpconfig.h" 34 | 35 | #include "py/nlr.h" 36 | #include "py/runtime.h" 37 | #include "py/objtuple.h" 38 | #include "extmod/misc.h" 39 | #include "lib/fatfs/ff.h" 40 | 41 | extern const mp_obj_type_t mp_fat_vfs_type; 42 | 43 | #define RAISE_ERRNO(err_flag, error_val) \ 44 | { if (err_flag != FR_OK) \ 45 | { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error_val))); } } 46 | 47 | STATIC mp_obj_t mod_os_unlink(mp_obj_t path_in) { 48 | mp_uint_t len; 49 | const char *path = mp_obj_str_get_data(path_in, &len); 50 | FRESULT r = f_unlink(path); 51 | RAISE_ERRNO(r, errno); 52 | return mp_const_none; 53 | } 54 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_unlink_obj, mod_os_unlink); 55 | 56 | STATIC mp_obj_t mod_os_mkdir(mp_obj_t path_in) { 57 | const char *path = mp_obj_str_get_str(path_in); 58 | FRESULT res = f_mkdir(path); 59 | RAISE_ERRNO(res, errno); 60 | 61 | return mp_const_none; 62 | } 63 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_mkdir_obj, mod_os_mkdir); 64 | 65 | STATIC mp_obj_t mod_os_errno(size_t n_args, const mp_obj_t *args) { 66 | if (n_args == 0) { 67 | return MP_OBJ_NEW_SMALL_INT(errno); 68 | } 69 | 70 | errno = mp_obj_get_int(args[0]); 71 | return mp_const_none; 72 | } 73 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_errno_obj, 0, 1, mod_os_errno); 74 | 75 | STATIC const mp_rom_map_elem_t mp_module_os_globals_table[] = { 76 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, 77 | { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mod_os_errno_obj) }, 78 | { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mod_os_unlink_obj) }, 79 | { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mod_os_mkdir_obj) }, 80 | #if MICROPY_VFS_FAT 81 | { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, 82 | #endif 83 | }; 84 | 85 | STATIC MP_DEFINE_CONST_DICT(mp_module_os_globals, mp_module_os_globals_table); 86 | 87 | const mp_obj_module_t mp_module_os = { 88 | .base = { &mp_type_module }, 89 | .name = MP_QSTR_uos, 90 | .globals = (mp_obj_dict_t*)&mp_module_os_globals, 91 | }; 92 | -------------------------------------------------------------------------------- /minios/mods/modtime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Micro Python project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2013, 2014 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "py/runtime.h" 33 | #include "py/smallint.h" 34 | #include "py/mphal.h" 35 | 36 | #define sleep_select select 37 | 38 | #define FLOAT_NSEC_TO_SEC(_nsec) ((float)(_nsec) / (float)1000000000ULL) 39 | 40 | // mingw32 defines CLOCKS_PER_SEC as ((clock_t)) but preprocessor does not handle casts 41 | #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) 42 | #define MP_REMOVE_BRACKETSA(x) 43 | #define MP_REMOVE_BRACKETSB(x) MP_REMOVE_BRACKETSA x 44 | #define MP_REMOVE_BRACKETSC(x) MP_REMOVE_BRACKETSB x 45 | #define MP_CLOCKS_PER_SEC MP_REMOVE_BRACKETSC(CLOCKS_PER_SEC) 46 | #else 47 | #define MP_CLOCKS_PER_SEC CLOCKS_PER_SEC 48 | #endif 49 | 50 | #if defined(MP_CLOCKS_PER_SEC) 51 | #define CLOCK_DIV (MP_CLOCKS_PER_SEC / 1000.0F) 52 | #else 53 | #error Unsupported clock() implementation 54 | #endif 55 | 56 | STATIC mp_obj_t mod_time_time(void) { 57 | #if MICROPY_PY_BUILTINS_FLOAT 58 | struct timeval tv; 59 | gettimeofday(&tv, NULL); 60 | mp_float_t val = tv.tv_sec + (mp_float_t)tv.tv_usec / 1000000; 61 | return mp_obj_new_float(val); 62 | #else 63 | return mp_obj_new_int((mp_int_t)time(NULL)); 64 | #endif 65 | } 66 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_time_obj, mod_time_time); 67 | 68 | STATIC mp_obj_t mod_time_ticks_us(void) { 69 | struct timeval tv; 70 | gettimeofday(&tv, NULL); 71 | mp_uint_t us = tv.tv_sec * 1000000 + tv.tv_usec; 72 | return MP_OBJ_NEW_SMALL_INT(us & MP_SMALL_INT_POSITIVE_MASK); 73 | } 74 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_ticks_us_obj, mod_time_ticks_us); 75 | 76 | STATIC mp_obj_t mod_time_ticks_ms(void) { 77 | struct timeval tv; 78 | gettimeofday(&tv, NULL); 79 | mp_uint_t ms = tv.tv_sec * 1000 + tv.tv_usec / 1000; 80 | return MP_OBJ_NEW_SMALL_INT(ms & MP_SMALL_INT_POSITIVE_MASK); 81 | } 82 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_ticks_ms_obj, mod_time_ticks_ms); 83 | 84 | STATIC mp_obj_t mod_time_ticks_diff(mp_obj_t oldval, mp_obj_t newval) { 85 | mp_uint_t old = MP_OBJ_SMALL_INT_VALUE(oldval); 86 | mp_uint_t new = MP_OBJ_SMALL_INT_VALUE(newval); 87 | return MP_OBJ_NEW_SMALL_INT((new - old) & MP_SMALL_INT_POSITIVE_MASK); 88 | } 89 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_time_ticks_diff_obj, mod_time_ticks_diff); 90 | 91 | // Note: this is deprecated since CPy3.3, but pystone still uses it. 92 | STATIC mp_obj_t mod_time_clock(void) { 93 | return mp_obj_new_float(FLOAT_NSEC_TO_SEC(monotonic_clock())); 94 | } 95 | STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_clock_obj, mod_time_clock); 96 | 97 | STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) { 98 | #if MICROPY_PY_BUILTINS_FLOAT 99 | struct timeval tv; 100 | mp_float_t val = mp_obj_get_float(arg); 101 | double ipart; 102 | tv.tv_usec = round(modf(val, &ipart) * 1000000); 103 | tv.tv_sec = ipart; 104 | int res; 105 | while (1) { 106 | res = sleep_select(0, NULL, NULL, NULL, &tv); 107 | #if MICROPY_SELECT_REMAINING_TIME 108 | // TODO: This assumes Linux behavior of modifying tv to the remaining 109 | // time. 110 | if (res != -1 || errno != EINTR) { 111 | break; 112 | } 113 | if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { 114 | return mp_const_none; 115 | } 116 | //printf("select: EINTR: %ld:%ld\n", tv.tv_sec, tv.tv_usec); 117 | #else 118 | break; 119 | #endif 120 | } 121 | RAISE_ERRNO(res, errno); 122 | #else 123 | // TODO: Handle EINTR 124 | sleep(mp_obj_get_int(arg)); 125 | #endif 126 | return mp_const_none; 127 | } 128 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_time_sleep_obj, mod_time_sleep); 129 | 130 | STATIC mp_obj_t mod_time_sleep_ms(mp_obj_t arg) { 131 | usleep(mp_obj_get_int(arg) * 1000); 132 | return mp_const_none; 133 | } 134 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_time_sleep_ms_obj, mod_time_sleep_ms); 135 | 136 | STATIC mp_obj_t mod_time_sleep_us(mp_obj_t arg) { 137 | usleep(mp_obj_get_int(arg)); 138 | return mp_const_none; 139 | } 140 | STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_time_sleep_us_obj, mod_time_sleep_us); 141 | 142 | STATIC mp_obj_t mod_time_strftime(size_t n_args, const mp_obj_t *args) { 143 | time_t t; 144 | if (n_args == 1) { 145 | t = time(NULL); 146 | } else { 147 | // CPython requires passing struct tm, but we allow to pass time_t 148 | // (and don't support struct tm so far). 149 | t = mp_obj_get_int(args[1]); 150 | } 151 | struct tm *tm = localtime(&t); 152 | char buf[32]; 153 | size_t sz = strftime(buf, sizeof(buf), mp_obj_str_get_str(args[0]), tm); 154 | return mp_obj_new_str(buf, sz, false); 155 | } 156 | STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_time_strftime_obj, 1, 2, mod_time_strftime); 157 | 158 | STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = { 159 | { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) }, 160 | { MP_ROM_QSTR(MP_QSTR_clock), MP_ROM_PTR(&mod_time_clock_obj) }, 161 | { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mod_time_sleep_obj) }, 162 | { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mod_time_sleep_ms_obj) }, 163 | { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mod_time_sleep_us_obj) }, 164 | { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mod_time_time_obj) }, 165 | { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mod_time_ticks_ms_obj) }, 166 | { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mod_time_ticks_us_obj) }, 167 | { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mod_time_ticks_diff_obj) }, 168 | { MP_ROM_QSTR(MP_QSTR_strftime), MP_ROM_PTR(&mod_time_strftime_obj) }, 169 | }; 170 | 171 | STATIC MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table); 172 | 173 | const mp_obj_module_t mp_module_time = { 174 | .base = { &mp_type_module }, 175 | .name = MP_QSTR_utime, 176 | .globals = (mp_obj_dict_t*)&mp_module_time_globals, 177 | }; 178 | 179 | -------------------------------------------------------------------------------- /minios/mods/modusocket.c: -------------------------------------------------------------------------------- 1 | #include "modlwip.h" 2 | #include "py/obj.h" 3 | #include "lwip/sockets.h" 4 | 5 | #define SEC_SOCKET 100 /* Secured Socket Layer (SSL,TLS) */ 6 | 7 | STATIC const mp_map_elem_t socket_locals_dict_table[] = { 8 | { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&lwip_socket_close }, 9 | { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&lwip_socket_close }, 10 | { MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&lwip_socket_bind }, 11 | { MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&lwip_socket_listen }, 12 | { MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&lwip_socket_accept }, 13 | { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&lwip_socket_connect }, 14 | { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&lwip_socket_send }, 15 | { MP_OBJ_NEW_QSTR(MP_QSTR_sendall), (mp_obj_t)&lwip_socket_sendall }, 16 | { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&lwip_socket_recv }, 17 | { MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&lwip_socket_sendto }, 18 | { MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&lwip_socket_recvfrom }, 19 | { MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&lwip_socket_setsockopt }, 20 | { MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&lwip_socket_settimeout }, 21 | { MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&lwip_socket_setblocking }, 22 | { MP_OBJ_NEW_QSTR(MP_QSTR_makefile), (mp_obj_t)&lwip_socket_makefile }, 23 | 24 | // stream methods 25 | { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&lwip_socket_read }, 26 | { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&lwip_socket_write }, 27 | }; 28 | 29 | MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); 30 | 31 | STATIC const mp_obj_type_t socket_type = { 32 | { &mp_type_type }, 33 | .name = MP_QSTR_usocket, 34 | .make_new = lwip_socket_make_new, 35 | .stream_p = NULL, 36 | .locals_dict = (mp_obj_t)&socket_locals_dict, 37 | }; 38 | 39 | STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_getaddrinfo_obj, lwip_getaddrinfo); 40 | 41 | STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = { 42 | { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usocket) }, 43 | 44 | { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&socket_type }, 45 | { MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&lwip_getaddrinfo_obj }, 46 | 47 | // class exceptions 48 | { MP_OBJ_NEW_QSTR(MP_QSTR_error), (mp_obj_t)&mp_type_OSError }, 49 | // { MP_OBJ_NEW_QSTR(MP_QSTR_timeout), (mp_obj_t)&mp_type_TimeoutError }, 50 | 51 | // class constants 52 | { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(AF_INET) }, 53 | 54 | { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SOCK_STREAM) }, 55 | { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SOCK_DGRAM) }, 56 | { MP_OBJ_NEW_QSTR(MP_QSTR_SO_REUSEADDR), MP_OBJ_NEW_SMALL_INT(SO_REUSEADDR) }, 57 | 58 | { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_SEC), MP_OBJ_NEW_SMALL_INT(SEC_SOCKET) }, 59 | { MP_OBJ_NEW_QSTR(MP_QSTR_SOL_SOCKET), MP_OBJ_NEW_SMALL_INT(SOL_SOCKET) }, 60 | { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP) }, 61 | { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(IPPROTO_UDP) }, 62 | }; 63 | 64 | STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table); 65 | 66 | 67 | const mp_obj_module_t mp_module_usocket = { 68 | .base = { &mp_type_module }, 69 | .name = MP_QSTR_usocket, 70 | .globals = (mp_obj_dict_t*)&mp_module_usocket_globals, 71 | }; 72 | -------------------------------------------------------------------------------- /minios/mphalport.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Micro Python project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2015 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | #include 27 | 28 | #ifndef CHAR_CTRL_C 29 | #define CHAR_CTRL_C (3) 30 | #endif 31 | 32 | void mp_hal_set_interrupt_char(char c); 33 | 34 | void mp_hal_stdio_mode_raw(void); 35 | void mp_hal_stdio_mode_orig(void); 36 | 37 | static inline void mp_hal_delay_ms(mp_uint_t ms) { usleep((ms) * 1000); } 38 | 39 | #define RAISE_ERRNO(err_flag, error_val) \ 40 | { if (err_flag == -1) \ 41 | { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error_val))); } } 42 | -------------------------------------------------------------------------------- /minios/qstrdefsport.h: -------------------------------------------------------------------------------- 1 | // qstrs specific to this port 2 | -------------------------------------------------------------------------------- /minios/ring.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple ring implementation to handle object references. 3 | * 4 | * file: ring.c 5 | * 6 | * NEC Europe Ltd. PROPRIETARY INFORMATION 7 | * 8 | * This software is supplied under the terms of a license agreement 9 | * or nondisclosure agreement with NEC Europe Ltd. and may not be 10 | * copied or disclosed except in accordance with the terms of that 11 | * agreement. The software and its source code contain valuable trade 12 | * secrets and confidential information which have to be maintained in 13 | * confidence. 14 | * Any unauthorized publication, transfer to third parties or duplication 15 | * of the object or source code - either totally or in part – is 16 | * prohibited. 17 | * 18 | * Copyright (c) 2014 NEC Europe Ltd. All Rights Reserved. 19 | * 20 | * Authors: Simon Kuenzer 21 | * 22 | * NEC Europe Ltd. DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, 23 | * INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY 24 | * AND FITNESS FOR A PARTICULAR PURPOSE AND THE WARRANTY AGAINST LATENT 25 | * DEFECTS, WITH RESPECT TO THE PROGRAM AND THE ACCOMPANYING 26 | * DOCUMENTATION. 27 | * 28 | * No Liability For Consequential Damages IN NO EVENT SHALL NEC Europe 29 | * Ltd., NEC Corporation OR ANY OF ITS SUBSIDIARIES BE LIABLE FOR ANY 30 | * DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS 31 | * OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF INFORMATION, OR 32 | * OTHER PECUNIARY LOSS AND INDIRECT, CONSEQUENTIAL, INCIDENTAL, 33 | * ECONOMIC OR PUNITIVE DAMAGES) ARISING OUT OF THE USE OF OR INABILITY 34 | * TO USE THIS PROGRAM, EVEN IF NEC Europe Ltd. HAS BEEN ADVISED OF THE 35 | * POSSIBILITY OF SUCH DAMAGES. 36 | * 37 | */ 38 | /* 39 | * Parts of this code is derived/copied from FreeBSD's buf_ring.h: 40 | * 41 | * Copyright (c) 2007,2008 Kip Macy kmacy@freebsd.org 42 | * All rights reserved. 43 | * 44 | * Redistribution and use in source and binary forms, with or without 45 | * modification, are permitted provided that the following conditions are met: 46 | * 47 | * 1. Redistributions of source code must retain the above copyright notice, 48 | * this list of conditions and the following disclaimer. 49 | * 50 | * 2. The name of Kip Macy nor the names of other 51 | * contributors may be used to endorse or promote products derived from 52 | * this software without specific prior written permission. 53 | * 54 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 55 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 58 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 59 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 60 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 61 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 62 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 63 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 64 | * POSSIBILITY OF SUCH DAMAGE. 65 | * 66 | */ 67 | /* Note: This implementation is thread-safe but not SMP-safe. */ 68 | 69 | //#include 70 | #include 71 | #include "ring.h" 72 | 73 | #define MIN_ALIGN 8 74 | #define CACHELINE_SIZE 64 75 | 76 | #ifndef POWER_OF_2 77 | #define POWER_OF_2(x) (((x)) && (!((x) & ((x) - 1)))) 78 | #endif 79 | 80 | #ifndef ALIGN_UP 81 | #define ALIGN_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) 82 | #endif 83 | 84 | struct ring *alloc_ring(uint32_t size) 85 | { 86 | struct ring *r; 87 | size_t h_size = ALIGN_UP(sizeof(struct ring), MIN_ALIGN); 88 | 89 | ASSERT(size > 0 && POWER_OF_2(size)); 90 | 91 | r = _xmalloc(h_size + (sizeof(void *) * size), CACHELINE_SIZE); 92 | if (!r) { 93 | errno = ENOMEM; 94 | return NULL; 95 | } 96 | r->size = size; 97 | r->mask = size - 1; 98 | r->enq_idx = 0; 99 | r->deq_idx = 0; 100 | r->ring = (void **) ((uintptr_t) r + h_size); 101 | return r; 102 | } 103 | 104 | void free_ring(struct ring *r) 105 | { 106 | xfree(r); 107 | } 108 | -------------------------------------------------------------------------------- /minios/ring.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple ring implementation to handle object references. 3 | * 4 | * file: ring.c 5 | * 6 | * NEC Europe Ltd. PROPRIETARY INFORMATION 7 | * 8 | * This software is supplied under the terms of a license agreement 9 | * or nondisclosure agreement with NEC Europe Ltd. and may not be 10 | * copied or disclosed except in accordance with the terms of that 11 | * agreement. The software and its source code contain valuable trade 12 | * secrets and confidential information which have to be maintained in 13 | * confidence. 14 | * Any unauthorized publication, transfer to third parties or duplication 15 | * of the object or source code - either totally or in part – is 16 | * prohibited. 17 | * 18 | * Copyright (c) 2014 NEC Europe Ltd. All Rights Reserved. 19 | * 20 | * Authors: Simon Kuenzer 21 | * 22 | * NEC Europe Ltd. DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, 23 | * INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY 24 | * AND FITNESS FOR A PARTICULAR PURPOSE AND THE WARRANTY AGAINST LATENT 25 | * DEFECTS, WITH RESPECT TO THE PROGRAM AND THE ACCOMPANYING 26 | * DOCUMENTATION. 27 | * 28 | * No Liability For Consequential Damages IN NO EVENT SHALL NEC Europe 29 | * Ltd., NEC Corporation OR ANY OF ITS SUBSIDIARIES BE LIABLE FOR ANY 30 | * DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS 31 | * OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF INFORMATION, OR 32 | * OTHER PECUNIARY LOSS AND INDIRECT, CONSEQUENTIAL, INCIDENTAL, 33 | * ECONOMIC OR PUNITIVE DAMAGES) ARISING OUT OF THE USE OF OR INABILITY 34 | * TO USE THIS PROGRAM, EVEN IF NEC Europe Ltd. HAS BEEN ADVISED OF THE 35 | * POSSIBILITY OF SUCH DAMAGES. 36 | * 37 | */ 38 | /* 39 | * Parts of this code is derived/copied from FreeBSD's buf_ring.h: 40 | * 41 | * Copyright (c) 2007,2008 Kip Macy kmacy@freebsd.org 42 | * All rights reserved. 43 | * 44 | * Redistribution and use in source and binary forms, with or without 45 | * modification, are permitted provided that the following conditions are met: 46 | * 47 | * 1. Redistributions of source code must retain the above copyright notice, 48 | * this list of conditions and the following disclaimer. 49 | * 50 | * 2. The name of Kip Macy nor the names of other 51 | * contributors may be used to endorse or promote products derived from 52 | * this software without specific prior written permission. 53 | * 54 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 55 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 56 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 57 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 58 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 59 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 60 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 61 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 62 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 63 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 64 | * POSSIBILITY OF SUCH DAMAGE. 65 | * 66 | */ 67 | /* Note: This implementation is thread-safe but not SMP-safe. */ 68 | 69 | #ifndef _RING_H_ 70 | #define _RING_H_ 71 | 72 | //#include 73 | 74 | #include 75 | #include 76 | #include 77 | #include 78 | #include 79 | #include 80 | #include 81 | 82 | 83 | 84 | struct ring { 85 | volatile uint32_t enq_idx; 86 | volatile uint32_t deq_idx; 87 | uint32_t size; 88 | uint32_t mask; 89 | void **ring; 90 | }; 91 | 92 | /* Note: size has to be a power of to. (size - 1) slots are available in the ring */ 93 | struct ring *alloc_ring(uint32_t size); 94 | void free_ring(struct ring *r); 95 | 96 | #define ring_full(r) ((((r)->enq_idx + 1) & (r)->mask) == (r)->deq_idx) 97 | #define ring_empty(r) ((r)->enq_idx == (r)->deq_idx) 98 | /* number of used slots */ 99 | #define ring_count(r) (((r)->size + (r)->enq_idx - (r)->deq_idx) & (r)->mask) 100 | /* number of available slots */ 101 | #define ring_avail(r) (((r)->mask + (r)->deq_idx - (r)->enq_idx) & (r)->mask) 102 | 103 | /* 104 | * Multi-producer-safe enqueue 105 | * Returns 0 on success, -1 on errors (inspect errno for reason) 106 | */ 107 | static inline int ring_enqueue(struct ring *r, void *element) 108 | { 109 | uint32_t enq_idx; 110 | unsigned long flags; 111 | 112 | local_irq_save(flags); 113 | enq_idx = r->enq_idx; 114 | 115 | if (((enq_idx + 1) & r->mask) == r->deq_idx) { 116 | local_irq_restore(flags); 117 | errno = ENOBUFS; 118 | return -1; 119 | } 120 | r->ring[enq_idx] = element; 121 | r->enq_idx = (enq_idx + 1) & r->mask; 122 | local_irq_restore(flags); 123 | return 0; 124 | } 125 | 126 | /* 127 | * Returns 0 on success, -1 on errors (inspect errno for reason) 128 | */ 129 | static inline int ring_enqueue_multiple(struct ring *r, void *elements[], uint32_t count) 130 | { 131 | uint32_t i; 132 | uint32_t enq_idx; 133 | unsigned long flags; 134 | 135 | local_irq_save(flags); 136 | enq_idx = r->enq_idx; 137 | 138 | if (((r->size - 1) - ring_count(r)) < count) { 139 | local_irq_restore(flags); 140 | errno = ENOBUFS; 141 | return -1; 142 | } 143 | 144 | for (i=0; iring[enq_idx] = elements[i]; 146 | enq_idx = (enq_idx + 1) & r->mask; 147 | } 148 | r->enq_idx = enq_idx; 149 | local_irq_restore(flags); 150 | return 0; 151 | } 152 | 153 | /* 154 | * Returns the number of successfully dequeued elements 155 | */ 156 | static inline uint32_t ring_try_enqueue_multiple(struct ring *r, void *elements[], uint32_t count) 157 | { 158 | uint32_t i = 0; 159 | int ret = 0; 160 | 161 | while (!ret || i < count) 162 | ret = ring_enqueue(r, elements[i++]); 163 | 164 | if (!ret) 165 | return i; 166 | return (i - 1); 167 | } 168 | 169 | /* 170 | * Multi-consumer-safe dequeue 171 | * Returns NULL on errors (inspect errno for reason) 172 | */ 173 | static inline void *ring_dequeue(struct ring *r) 174 | { 175 | uint32_t deq_idx; 176 | unsigned long flags; 177 | void *e; 178 | 179 | local_irq_save(flags); 180 | deq_idx = r->deq_idx; 181 | 182 | if (deq_idx == r->enq_idx) { 183 | local_irq_restore(flags); 184 | errno = ENOBUFS; 185 | return NULL; 186 | } 187 | e = r->ring[deq_idx]; 188 | r->deq_idx = (deq_idx + 1) & r->mask; 189 | local_irq_restore(flags); 190 | return e; 191 | } 192 | 193 | /* 194 | * Returns 0 on success, -1 on errors (inspect errno for reason) 195 | */ 196 | static inline int ring_dequeue_multiple(struct ring *r, void *elements[], uint32_t count) 197 | { 198 | uint32_t i; 199 | uint32_t deq_idx; 200 | unsigned long flags; 201 | 202 | local_irq_save(flags); 203 | deq_idx = r->deq_idx; 204 | 205 | if ((ring_count(r)) < count) { 206 | local_irq_restore(flags); 207 | errno = ENOBUFS; 208 | return -1; 209 | } 210 | 211 | for (i=0; iring[deq_idx]; 213 | deq_idx = (deq_idx + 1) & r->mask; 214 | } 215 | r->deq_idx = deq_idx; 216 | local_irq_restore(flags); 217 | return 0; 218 | } 219 | 220 | /* 221 | * Returns the number of successfully dequeued elements 222 | */ 223 | static inline uint32_t ring_try_dequeue_multiple(struct ring *r, void *elements[], uint32_t count) 224 | { 225 | uint32_t i = 0; 226 | int ret = 0; 227 | void *e; 228 | 229 | while (!ret || i < count) { 230 | e = ring_dequeue(r); 231 | if (!e) 232 | return i; 233 | elements[i++] = e; 234 | } 235 | 236 | return i; 237 | } 238 | 239 | #endif /* _RING_H_ */ 240 | -------------------------------------------------------------------------------- /minios/shfs/dlist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Double linked list implementation 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _DLIST_H_ 37 | #define _DLIST_H_ 38 | 39 | #include 40 | #include 41 | #include "likely.h" 42 | 43 | struct dlist_el { 44 | void *next; 45 | void *prev; 46 | }; 47 | #define dlist_el(dlname) \ 48 | struct dlist_el (dlname) 49 | 50 | struct dlist_head { 51 | void *first; 52 | void *last; 53 | }; 54 | #define dlist_head(dlname) \ 55 | struct dlist_head (dlname) 56 | 57 | #define dlist_init_head(head)\ 58 | do { \ 59 | (head).first = NULL; \ 60 | (head).last = NULL; \ 61 | } while (0) 62 | #define dlist_init_el(el, dlname) /* optional as long as */ \ 63 | /* dlist_is_linked() is not used */ \ 64 | do { \ 65 | (el)->dlname.next = NULL; \ 66 | (el)->dlname.prev = NULL; \ 67 | } while (0) 68 | 69 | #define dlist_is_empty(head) \ 70 | ((head).first == NULL) 71 | 72 | #define dlist_next_el(el, dlname) \ 73 | ((typeof((el))) (el)->dlname.next) 74 | #define dlist_prev_el(el, dlname) \ 75 | ((typeof((el))) (el)->dlname.prev) 76 | #define dlist_first_el(head, eltype) \ 77 | ((eltype *) ((head).first)) 78 | #define dlist_last_el(head, eltype) \ 79 | ((eltype *) ((head).last)) 80 | 81 | /* Note: This function only supports checking if an element is linked into 82 | * a specific list. It will fail as soon as the element is linked to a 83 | * different list (with same dlname) than checked against */ 84 | #define dlist_is_linked(el, head, dlname) /* requires dlist_init_el() */ \ 85 | (((el)->dlname.prev != NULL || (el)->dlname.next != NULL) || \ 86 | ((head).first == (el) || (head).last == (el))) 87 | 88 | #define dlist_unlink(el, head, dlname) \ 89 | do { \ 90 | if ((el)->dlname.prev) { \ 91 | ((typeof((el))) (el)->dlname.prev)->dlname.next = (el)->dlname.next; \ 92 | } else { \ 93 | (head).first = (el)->dlname.next; \ 94 | } \ 95 | if ((el)->dlname.next) { \ 96 | ((typeof((el))) (el)->dlname.next)->dlname.prev = (el)->dlname.prev; \ 97 | } else { \ 98 | (head).last = (el)->dlname.prev; \ 99 | } \ 100 | dlist_init_el((el), dlname); \ 101 | } while(0) 102 | 103 | #define dlist_foreach(el, head, dlname) \ 104 | for((el) = ((typeof((el))) (head).first); \ 105 | (el) != NULL; \ 106 | (el) = dlist_next_el((el), dlname)) 107 | 108 | #define dlist_foreach_reverse(el, head, dlname) \ 109 | for((el) = ((typeof((el))) (head).last); \ 110 | (el) != NULL; \ 111 | (el) = dlist_prev_el((el), dlname)) 112 | 113 | #define dlist_append(el, head, dlname) \ 114 | do { \ 115 | if (dlist_is_empty((head))) { \ 116 | (head).first = (el); \ 117 | (el)->dlname.prev = NULL; \ 118 | } else { \ 119 | ((typeof((el))) (head).last)->dlname.next = (el); \ 120 | (el)->dlname.prev = (head).last; \ 121 | } \ 122 | (el)->dlname.next = NULL; \ 123 | (head).last = (el); \ 124 | } while(0) 125 | #define dlist_relink_tail(el, head, dlname) \ 126 | do { \ 127 | dlist_unlink((el), (head), dlname); \ 128 | dlist_append((el), (head), dlname); \ 129 | } while(0) 130 | 131 | #define dlist_prepend(el, head, dlname) \ 132 | do { \ 133 | if (dlist_is_empty((head))) { \ 134 | (head).last = (el); \ 135 | (el)->dlname.next = NULL; \ 136 | } else { \ 137 | ((typeof((el))) (head).first)->dlname.prev = (el); \ 138 | (el)->dlname.next = (head).first; \ 139 | } \ 140 | (el)->dlname.prev = NULL; \ 141 | (head).first = (el); \ 142 | } while(0) 143 | #define dlist_relink_head(el, head, dlname) \ 144 | do { \ 145 | dlist_unlink((el), (head), dlname); \ 146 | dlist_prepend((el), (head), dlname); \ 147 | } while(0) 148 | 149 | #endif /* _DLIST_H_ */ 150 | -------------------------------------------------------------------------------- /minios/shfs/hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple hash value implementation for MiniOS and POSIX 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _HASH_H_ 37 | #define _HASH_H_ 38 | 39 | #include 40 | 41 | typedef uint8_t hash512_t[64] __attribute__((aligned(8))); 42 | 43 | 44 | static inline void hash_copy(hash512_t dst, const hash512_t src, uint8_t hlen) 45 | { 46 | #ifdef __x86_64 47 | register uint8_t nbleft = hlen & 0x07; /* = mod by 8 */ 48 | register uint64_t mask64; 49 | register uint64_t *p64_dst; 50 | register uint64_t *p64_src; 51 | register uint8_t i; 52 | 53 | hlen -= nbleft; 54 | i = 0; 55 | for (; i < hlen; i += 8) { 56 | p64_dst = (uint64_t *) &dst[i]; 57 | p64_src = (uint64_t *) &src[i]; 58 | *p64_dst = *p64_src; 59 | } 60 | if (nbleft) { 61 | mask64 = ((uint64_t) 1 << (nbleft << 3)) - 1; 62 | p64_dst = (uint64_t *) &dst[i]; 63 | p64_src = (uint64_t *) &src[i]; 64 | *p64_dst = *p64_src & mask64; 65 | } 66 | #else 67 | memcpy(dst, src, hlen); 68 | #endif 69 | } 70 | 71 | static inline int hash_compare(const hash512_t h0, const hash512_t h1, uint8_t hlen) 72 | { 73 | #ifdef __x86_64 74 | register uint8_t nbleft = hlen & 0x07; /* = mod by 8 */ 75 | register uint64_t mask64; 76 | register uint64_t *p64_0; 77 | register uint64_t *p64_1; 78 | register uint8_t i; 79 | 80 | hlen -= nbleft; 81 | i = 0; 82 | for (; i < hlen; i += 8) { 83 | p64_0 = (uint64_t *) &h0[i]; 84 | p64_1 = (uint64_t *) &h1[i]; 85 | if (*p64_0 != *p64_1) 86 | return 1; 87 | } 88 | if (nbleft) { 89 | mask64 = ((uint64_t) 1 << (nbleft << 3)) - 1; 90 | p64_0 = (uint64_t *) &h0[i]; 91 | p64_1 = (uint64_t *) &h1[i]; 92 | if ((*p64_0 & mask64) != (*p64_1 & mask64)) 93 | return 1; 94 | } 95 | 96 | return 0; 97 | #else 98 | return (memcmp(h0, h1, hlen) != 0); 99 | #endif 100 | } 101 | 102 | static inline int hash_is_zero(const hash512_t h, uint8_t hlen) 103 | { 104 | #ifdef __x86_64 105 | register uint8_t nbleft = hlen & 0x07; /* = mod by 8 */ 106 | register uint64_t mask64; 107 | register uint64_t *p64; 108 | register uint8_t i; 109 | 110 | hlen -= nbleft; 111 | i = 0; 112 | for (; i < hlen; i += 8) { 113 | p64 = (uint64_t *) &h[i]; 114 | if (*p64 != 0) 115 | return 0; 116 | } 117 | if (nbleft) { 118 | mask64 = ((uint64_t) 1 << (nbleft << 3)) - 1; 119 | p64 = (uint64_t *) &h[i]; 120 | if ((*p64 & mask64) != 0) 121 | return 0; 122 | } 123 | 124 | return 1; 125 | #else 126 | uint8_t i; 127 | 128 | for (i = 0; i < hlen; ++i) 129 | if (h[i] != 0) 130 | return 0; 131 | return 1; 132 | #endif 133 | } 134 | 135 | static inline int hash_is_max(const hash512_t h, uint8_t hlen) 136 | { 137 | #ifdef __x86_64 138 | register uint8_t nbleft = hlen & 0x07; /* = mod by 8 */ 139 | register uint64_t mask64; 140 | register uint64_t *p64; 141 | register uint8_t i; 142 | 143 | hlen -= nbleft; 144 | i = 0; 145 | for (; i < hlen; i += 8) { 146 | p64 = (uint64_t *) &h[i]; 147 | if (*p64 != UINT64_MAX) 148 | return 0; 149 | } 150 | if (nbleft) { 151 | mask64 = ((uint64_t) 1 << (nbleft << 3)) - 1; 152 | p64 = (uint64_t *) &h[i]; 153 | if ((*p64 & mask64) != mask64) 154 | return 0; 155 | } 156 | 157 | return 1; 158 | #else 159 | uint8_t i; 160 | 161 | for (i = 0; i < hlen; ++i) 162 | if (h[i] != 0xFF) 163 | return 0; 164 | return 1; 165 | #endif 166 | } 167 | 168 | static inline void hash_clear(hash512_t h, uint8_t hlen) 169 | { 170 | #ifdef __x86_64 171 | register uint64_t *p64; 172 | register uint8_t i; 173 | 174 | for (i = 0; i < hlen; i += 8) { 175 | p64 = (uint64_t *) &h[i]; 176 | *p64 = 0; 177 | } 178 | #else 179 | memset(h, 0x00, hlen); 180 | #endif 181 | } 182 | 183 | static inline int hash_parse(const char *in, hash512_t h, uint8_t hlen) 184 | { 185 | uint8_t strlen = hlen * 2; 186 | uint8_t i, nu, nl; 187 | 188 | for (i = 0; i < strlen; ++i) { 189 | /* get upper nibble (4 bits) */ 190 | switch (in[i]) { 191 | case '0' ... '9': 192 | nu = in[i] - '0'; 193 | break; 194 | case 'a' ... 'f': 195 | nu = in[i] - 'a' + 10; 196 | break; 197 | case 'A' ... 'F': 198 | nu = in[i] - 'A' + 10; 199 | break; 200 | case '\0': 201 | default: 202 | return -1; /* unknown character or string ended unexpectedly */ 203 | } 204 | 205 | /* get lower nibble (4 bits) */ 206 | ++i; 207 | switch (in[i]) { 208 | case '0' ... '9': 209 | nl = in[i] - '0'; 210 | break; 211 | case 'a' ... 'f': 212 | nl = in[i] - 'a' + 10; 213 | break; 214 | case 'A' ... 'F': 215 | nl = in[i] - 'A' + 10; 216 | break; 217 | case '\0': 218 | default: 219 | return -1; 220 | } 221 | 222 | h[i >> 1] = (nu << 4) | nl; 223 | } 224 | 225 | if (in[i] != '\0') 226 | return -1; 227 | 228 | return 0; 229 | } 230 | 231 | #endif /* _HASH_H_ */ 232 | -------------------------------------------------------------------------------- /minios/shfs/htable.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple hash table implementation for MiniOS and POSIX 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifdef __MINIOS__ 37 | #include 38 | #include 39 | #include 40 | #else 41 | #include 42 | #include 43 | #endif 44 | 45 | #ifndef MIN_ALIGN 46 | #define MIN_ALIGN 8 47 | #endif 48 | 49 | #include "htable.h" 50 | 51 | #ifndef max 52 | #define max(a, b) \ 53 | ({ __typeof__ (a) __a = (a); \ 54 | __typeof__ (b) __b = (b); \ 55 | __a > __b ? __a : __b; }) 56 | #endif 57 | 58 | static inline size_t align_up(size_t size, size_t align) 59 | { 60 | return (size + align - 1) & ~(align - 1); 61 | } 62 | 63 | struct htable *alloc_htable(uint32_t nb_bkts, uint32_t el_per_bkt, uint8_t hlen, size_t el_private_len, size_t align) 64 | { 65 | size_t ht_size; 66 | size_t bkt_hdr_size; 67 | size_t bkt_size; 68 | size_t el_hdr_size; 69 | size_t el_size; 70 | struct htable *ht; 71 | struct htable_bkt *bkt; 72 | struct htable_el *el; 73 | uint32_t i, j; 74 | 75 | align = max(MIN_ALIGN, align); 76 | 77 | el_hdr_size = align_up(sizeof(struct htable_el), align); 78 | el_size = el_hdr_size + align_up(el_private_len, align); 79 | bkt_hdr_size = align_up(sizeof(struct htable_bkt) 80 | + (sizeof(hash512_t) * el_per_bkt), align); /* hash list */ 81 | bkt_size = bkt_hdr_size 82 | + (el_size * el_per_bkt) /* element list */; 83 | ht_size = sizeof(struct htable) 84 | + sizeof(struct htable_bkt *) * nb_bkts; 85 | 86 | #ifdef HTABLE_DEBUG 87 | printf("el_size = %lu B\n", el_size); 88 | printf("bkt_size = %lu B\n", bkt_size); 89 | printf("ht_size = %lu B\n", ht_size); 90 | #endif 91 | /* allocate main htable struct */ 92 | #ifdef __MINIOS__ 93 | ht = _xmalloc(ht_size, align); 94 | #else 95 | ht = malloc(ht_size); 96 | #endif 97 | if (!ht) { 98 | errno = ENOMEM; 99 | goto err_out; 100 | } 101 | memset(ht, 0, ht_size); 102 | 103 | #ifdef HTABLE_DEBUG 104 | printf("htable (%lu B) @ %p\n", ht_size); 105 | #endif 106 | ht->nb_bkts = nb_bkts; 107 | ht->el_per_bkt = el_per_bkt; 108 | ht->hlen = hlen; 109 | ht->head = NULL; 110 | ht->tail = NULL; 111 | 112 | /* allocate buckets */ 113 | for (i = 0; i < nb_bkts; ++i) { 114 | #ifdef __MINIOS__ 115 | bkt = _xmalloc(bkt_size, align); 116 | #else 117 | bkt = malloc(bkt_size); 118 | #endif 119 | if (!bkt) { 120 | errno = ENOMEM; 121 | goto err_free_bkts; 122 | } 123 | memset(bkt, 0, bkt_size); 124 | 125 | #ifdef HTABLE_DEBUG 126 | printf(" bucket %lu (%lu B) @ %p\n", i, bkt_size, bkt); 127 | #endif 128 | ht->b[i] = bkt; 129 | bkt->el = (void *) (((uint8_t *) ht->b[i]) + bkt_hdr_size); 130 | bkt->el_size = el_size; 131 | bkt->el_private_len = el_private_len; 132 | 133 | for (j = 0; j < el_per_bkt; ++j) { 134 | el = _htable_bkt_el(bkt, j); 135 | el->h = &bkt->h[j]; 136 | el->private = (void *) (((uint8_t *) el) + el_hdr_size); 137 | 138 | #ifdef HTABLE_DEBUG 139 | //printf(" entry %3lu:%02lu (%p): h = @%p; private = @%p\n", 140 | // i, j, el, el->h, el->private); 141 | #endif 142 | } 143 | } 144 | 145 | return ht; 146 | 147 | err_free_bkts: 148 | for (i = 0; i < nb_bkts; ++i) { 149 | if (ht->b[i]) { 150 | #ifdef __MINIOS__ 151 | xfree(ht->b[i]); 152 | #else 153 | free(ht->b[i]); 154 | #endif 155 | } 156 | } 157 | #ifdef __MINIOS__ 158 | xfree(ht); 159 | #else 160 | free(ht); 161 | #endif 162 | err_out: 163 | return NULL; 164 | } 165 | 166 | void free_htable(struct htable *ht) 167 | { 168 | uint32_t i; 169 | 170 | for (i = 0; i < ht->nb_bkts; ++i) { 171 | if (ht->b[i]) { 172 | #ifdef __MINIOS__ 173 | xfree(ht->b[i]); 174 | #else 175 | free(ht->b[i]); 176 | #endif 177 | } 178 | } 179 | #ifdef __MINIOS__ 180 | xfree(ht); 181 | #else 182 | free(ht); 183 | #endif 184 | } 185 | -------------------------------------------------------------------------------- /minios/shfs/scripts/mkwebfs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | WWWDIR="$1" 3 | SHFSIMG="$2" 4 | IFSORIG=$IFS 5 | NL=$'\n' 6 | CSIZE=4096 7 | NB_BKTS=1024 8 | E_PER_BKT=16 9 | ESIZE=256 10 | 11 | SHFS_MKFS=${SHFS_MKFS:-"../shfs-tools/shfs_mkfs"} 12 | SHFS_ADMIN=${SHFS_ADMIN:-"../shfs-tools/shfs_admin"} 13 | 14 | function usage() { 15 | echo "Usage: $0 [WWWDIR] [SHFSOUT]" 16 | } 17 | 18 | function get_hash() { 19 | # 128 bits hash of passed string 20 | printf "%s" "$1" | sha1sum | awk '{ print $1 }' 21 | } 22 | 23 | function str_tolower() 24 | { 25 | local STR=$1 26 | printf "%s" "${STR,,}" 27 | } 28 | 29 | function str_fileext() 30 | { 31 | # contains string an file extension part? 32 | local STR=$1 33 | local LEN=${#STR} 34 | local I= 35 | 36 | for (( I=LEN-1; I>0; I-- )); do 37 | if [ "${STR:$I:1}" = "." ]; then 38 | # yes -> cut / give me the last extension 39 | local P=$(( I + 1 )) 40 | local L=$(( LEN - P )) 41 | printf "%s" "${STR:$P:$L}" 42 | return 43 | fi 44 | done 45 | printf "%s" "" 46 | } 47 | 48 | function get_mime() { 49 | local FEXT="$( str_tolower "$( str_fileext "$1" )" )" 50 | local MIME= 51 | 52 | case "$FEXT" in 53 | "shtml"|"html"|"htm") 54 | MIME="text/html" 55 | ;; 56 | "js") 57 | MIME="text/javascript" 58 | ;; 59 | "css") 60 | MIME="text/css" 61 | ;; 62 | "xml") 63 | MIME="application/xml" 64 | ;; 65 | "text"|"txt"|"md"|"asc") 66 | MIME="text/plain" 67 | ;; 68 | "rtf") 69 | MIME="text/rtf" 70 | ;; 71 | "odg") 72 | MIME="application/vnd.oasis.opendocument.graphics" 73 | ;; 74 | "pdf") 75 | MIME="application/pdf" 76 | ;; 77 | "ps"|"eps"|"ai") 78 | MIME="application/postscript" 79 | ;; 80 | 81 | "jpeg"|"jpg"|"jpe") 82 | MIME="image/jpeg" 83 | ;; 84 | "gif") 85 | MIME="image/gif" 86 | ;; 87 | "png") 88 | MIME="image/png" 89 | ;; 90 | "tiff"|"tif") 91 | MIME="image/tiff" 92 | ;; 93 | "ico") 94 | MIME="image/x-icon" 95 | ;; 96 | "bmp"|"bm") 97 | MIME="image/x-bmp" 98 | ;; 99 | "svg") 100 | MIME="image/svg+xml" 101 | ;; 102 | 103 | "ttf") 104 | MIME="application/font-ttf" 105 | ;; 106 | "otf") 107 | MIME="application/vnd.ms-opentype" 108 | ;; 109 | "eot") 110 | MIME="application/vnd.ms-fontobject" 111 | ;; 112 | "woff") 113 | MIME="application/font-woff" 114 | ;; 115 | 116 | "mka") 117 | MIME="audio/x-matroska" 118 | ;; 119 | "mpga"|"mpa"|"mp3"|"mp2") 120 | MIME="audio/mpeg" 121 | ;; 122 | "oga"|"ogg"|"spx") 123 | MIME="audio/ogg" 124 | ;; 125 | "flac") 126 | MIME="audio/flac" 127 | ;; 128 | "wav") 129 | MIME="audio/wav" 130 | ;; 131 | 132 | "mpeg"|"mpg"|"mpe") 133 | MIME="video/mpeg" 134 | ;; 135 | "ogv") 136 | MIME="video/ogg" 137 | ;; 138 | "flv"|"f4v") 139 | MIME="video/x-flv" 140 | ;; 141 | "mp4") 142 | MIME="video/mpeg" 143 | ;; 144 | "mk3d"|"mkv"|"mks") 145 | MIME="video/x-matroska" 146 | ;; 147 | "mov"|"qt") 148 | MIME="video/quicktime" 149 | ;; 150 | "avi") 151 | MIME="video/avi" 152 | ;; 153 | 154 | "tar") 155 | MIME="application/x-tar" 156 | ;; 157 | "tgz"|"gz") 158 | MIME="application/x-gzip" 159 | ;; 160 | "zip") 161 | MIME="application/zip" 162 | ;; 163 | 164 | # default type 165 | *) 166 | MIME="application/octet-stream" 167 | ;; 168 | esac 169 | printf "%s" "$MIME" 170 | } 171 | 172 | function get_size() { 173 | stat --printf='%s' "$1" 174 | } 175 | 176 | function mksparse() { 177 | local FNAME="$1" 178 | local SIZE="$2" 179 | 180 | dd if=/dev/zero of="${FNAME}" count=0 bs=1 seek="${SIZE}" 181 | } 182 | 183 | function isindex() { 184 | local BNAME="$( basename "$1" )" 185 | if [ "$BNAME" = "index.htm" -o "$BNAME" = "index.html" ]; then 186 | return 0 187 | fi 188 | return 1 189 | } 190 | 191 | 192 | 193 | if [ -z "$WWWDIR" -o -z "$SHFSIMG" ]; then 194 | usage 195 | exit 1 196 | fi 197 | if [ ! -d "$WWWDIR" ]; then 198 | echo "${WWWDIR} is not a directory" 1>&2 199 | usage 200 | exit 1 201 | fi 202 | if [ -e "$SHFSIMG" -a ! -b "$SHFSIMG" ]; then 203 | echo "${SHFSIMG} exists already and is not a block device" 1>&2 204 | usage 205 | exit 1 206 | fi 207 | 208 | BASE=$( pwd ) 209 | cd "$WWWDIR" 210 | FILES="$( find ./ -not \( -path ./.git -prune \) -not \( -path ./.gitignore -prune \) -not \( -path ./.DS_Store \) )" 211 | I=0 212 | DEF_I=-1 213 | FILE=() 214 | NAME=() 215 | MIME=() 216 | HASH=() 217 | SIZE=() 218 | TSIZE=0 219 | CHUNKS=() 220 | TCHUNKS=0 221 | 222 | echo "* Collecting file information..." 223 | IFS=$NL 224 | for F in $FILES; do 225 | IFS=$IFSORIG 226 | F="${F:2}" # cuts leading './' 227 | if [ -z "$F" -o ! -f "$F" ]; then 228 | continue 229 | fi 230 | 231 | # build up array 232 | echo " ${F}" 233 | FILE[$I]="$( pwd )/${F}" 234 | NAME[$I]="${F}" 235 | HASH[$I]="$( get_hash "${NAME[$I]}" )" # hash of target filename 236 | MIME[$I]="$( get_mime "${F}" )" 237 | SIZE[$I]="$( get_size "${F}" )" 238 | CHUNKS[$I]=$(( (SIZE[$I] + CSIZE - 1) / CSIZE )) 239 | 240 | (( TSIZE += SIZE[$I] )) 241 | (( TCHUNKS += CHUNKS[$I] )) 242 | 243 | isindex "${FILE[$I]}" 244 | if [ $? -eq 0 ]; then 245 | # file is an index file 246 | if [ "$( dirname "${NAME[$I]}" )" != "." ]; then 247 | # WORKARAOUND add a copy of the file with just having the dirname 248 | FILE[$(( I + 1 ))]="${FILE[$I]}" 249 | NAME[$(( I + 1 ))]="$( dirname "${NAME[$I]}" )" 250 | HASH[$(( I + 1 ))]="$( get_hash "${NAME[$(( I + 1 ))]}" )" 251 | MIME[$(( I + 1 ))]="${MIME[$I]}" 252 | SIZE[$(( I + 1 ))]="${SIZE[$I]}" 253 | CHUNKS[$(( I + 1 ))]="${CHUNKS[$I]}" 254 | 255 | FILE[$(( I + 2 ))]="${FILE[$I]}" 256 | NAME[$(( I + 2 ))]="$( dirname "${NAME[$I]}" )/" 257 | HASH[$(( I + 2 ))]="$( get_hash "${NAME[$(( I + 2 ))]}" )" 258 | MIME[$(( I + 2 ))]="${MIME[$I]}" 259 | SIZE[$(( I + 2 ))]="${SIZE[$I]}" 260 | CHUNKS[$(( I + 1 ))]="${CHUNKS[$I]}" 261 | 262 | (( TSIZE += 2 * SIZE[$I] )) 263 | (( TCHUNKS += 2 * CHUNKS[$I] )) 264 | (( I += 2 )) 265 | else 266 | # index file in base dir -> set default flag 267 | DEF_I=$I 268 | fi 269 | fi 270 | 271 | (( I++ )) 272 | IFS=$NL 273 | done 274 | IFS=$IFSORIG 275 | cd "${BASE}" 276 | NB_FILES=$I 277 | 278 | echo "* Summary:" 279 | echo " ${NB_FILES} files" 280 | echo " ${TCHUNKS} chunks ($(( TSIZE / 1024 )) KiB)" 281 | 282 | if [ ! -b "${SHFSIMG}" ]; then 283 | SHFSIMG_SIZE=$(( (TCHUNKS + 3 + ((NB_BKTS * E_PER_BKT * ESIZE) / CSIZE)) * CSIZE )) 284 | echo "* Creating sparse image file with size of $(( SHFSIMG_SIZE / 1024 )) KiB" 285 | mksparse "${SHFSIMG}" "${SHFSIMG_SIZE}" 286 | fi 287 | 288 | echo "* Formatting" 289 | $SHFS_MKFS -f -n "mkwebfs" -F manual -l 20 -b "${NB_BKTS}" -e "${E_PER_BKT}" -s "${CSIZE}" "${SHFSIMG}" 290 | 291 | echo "* Adding files" 292 | for (( I=0; I<${NB_FILES}; I++ )); do 293 | echo " ${NAME[$I]}" 294 | $SHFS_ADMIN -a "${FILE[$I]}" -D "${HASH[$I]}" -n "${NAME[$I]}" -m "${MIME[$I]}" "${SHFSIMG}" 295 | done 296 | 297 | if [ "$DEF_I" != "-1" ]; then 298 | echo "* Marking index file (${NAME[$DEF_I]}, ${HASH[$DEF_I]})" 299 | $SHFS_ADMIN -d "${HASH[$DEF_I]}" "${SHFSIMG}" 300 | fi 301 | 302 | echo "* Done" 303 | $SHFS_ADMIN -l "${SHFSIMG}" 304 | -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/Makefile: -------------------------------------------------------------------------------- 1 | RM = rm -f 2 | CC = gcc 3 | LD = gcc 4 | CFLAGS += -O3 -g -Wunused -Wtype-limits -D__SHFS_TOOLS__ 5 | LDFLAGS += 6 | LDLIBS += -luuid -lmhash 7 | 8 | default: all 9 | 10 | %.o: %.c 11 | $(CC) $(CFLAGS) -c $< -o $@ 12 | 13 | %: %.o 14 | $(LD) $(LDFLAGS) $^ $(LDLIBS) -o $@ 15 | 16 | shfs_mkfs: shfs_mkfs.o tools_common.o 17 | 18 | shfs_admin: shfs_admin.o htable.o tools_common.o shfs_alloc.o shfs_check.o http_parser.o 19 | 20 | all: shfs_mkfs shfs_admin 21 | 22 | clean: 23 | $(RM) *.o core shfs_mkfs shfs_admin 24 | -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/README.md: -------------------------------------------------------------------------------- 1 | SHFS Tools 2 | ========== 3 | 4 | The SHFS tools can be used to create and manage SHFS object stores. 5 | 6 | 7 | Requirements 8 | ------------ 9 | 10 | In order to build the SHFS tools, you will need to have the following 11 | shared libraries installed: 12 | * [libuuid](http://e2fsprogs.sourceforge.net) 13 | * [libmhash](http://mhash.sourceforge.net) 14 | 15 | On Debian/Ubuntu you install them via: 16 | 17 | apt-get install libmhash2 libmhash-dev libuuid1 uuid-dev 18 | 19 | 20 | Build Instructions 21 | ------------------ 22 | 23 | You build the SHFS tools with the following make command: 24 | 25 | make 26 | 27 | Alternatively, you can also build a single tool by passing its executable 28 | name (e.g., shfs_mkfs) to make: 29 | 30 | make shfs_mkfs 31 | 32 | 33 | Examples: Using SHFS Tools 34 | -------------------------- 35 | 36 | ### Format a Physical Block Device with SHFS 37 | 38 | shfs_mkfs -n "NewVol#00" /dev/sdb2 39 | 40 | ### Create an 2GB SHFS Image File 41 | 42 | dd if=/dev/zero of=shfs-demo.img count=0 bs=1 seek=2G 43 | shfs_mkfs -n "SHFS-Demo" shfs-demo.img 44 | 45 | ### Adding Files to an SHFS Volume 46 | 47 | shfs_admin --add-obj /path/to/my_music.mp3 -m audio/mpeg3 shfs-demo.img 48 | 49 | ### Note 50 | 51 | Please remember that you have to run remount on a MiniCache Domain after you 52 | did changes to the object store while it is mounted. 53 | -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/hash.h: -------------------------------------------------------------------------------- 1 | ../hash.h -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/htable.c: -------------------------------------------------------------------------------- 1 | ../htable.c -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/htable.h: -------------------------------------------------------------------------------- 1 | ../htable.h -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/http_parser.c: -------------------------------------------------------------------------------- 1 | ../http_parser.c -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/http_parser.h: -------------------------------------------------------------------------------- 1 | ../http_parser.h -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/likely.h: -------------------------------------------------------------------------------- 1 | ../likely.h -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/shfs_admin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple hash filesystem (SHFS) tools 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _SHFS_ADMIN_ 37 | #define _SHFS_ADMIN_ 38 | 39 | #include "tools_common.h" 40 | #include "shfs_defs.h" 41 | 42 | #define STR_VERSION "Simple Hash FS (SHFS) Tools: Admin" 43 | 44 | #define MAX_NB_TRY_BLKDEVS SHFS_MAX_NB_MEMBERS 45 | 46 | enum action { 47 | NONE = 0, 48 | ADDOBJ, 49 | ADDLNK, 50 | RMOBJ, 51 | CATOBJ, 52 | SETDEFOBJ, 53 | CLEARDEFOBJ, 54 | LSOBJS, 55 | SHOWINFO 56 | }; 57 | 58 | enum ltype { 59 | LREDIRECT = 0, 60 | LRAW, 61 | LAUTO 62 | }; 63 | 64 | struct token { 65 | struct token *next; 66 | 67 | enum action action; 68 | char *path; 69 | char *optstr0; 70 | char *optstr1; 71 | char *optstr2; 72 | enum ltype optltype; 73 | }; 74 | 75 | struct args { 76 | char **devpath; 77 | unsigned int nb_devs; 78 | 79 | struct token *tokens; /* list of tokens */ 80 | }; 81 | 82 | struct vol_info { 83 | uuid_t uuid; 84 | char volname[17]; 85 | uint32_t chunksize; 86 | chk_t volsize; 87 | 88 | struct storage s; 89 | 90 | /* hash table */ 91 | struct htable *bt; 92 | void **htable_chunk_cache; 93 | int *htable_chunk_cache_state; 94 | chk_t htable_ref; 95 | chk_t htable_bak_ref; 96 | chk_t htable_len; 97 | uint32_t htable_nb_buckets; 98 | uint32_t htable_nb_entries; 99 | uint32_t htable_nb_entries_per_bucket; 100 | uint32_t htable_nb_entries_per_chunk; 101 | uint8_t hfunc; 102 | uint8_t hlen; 103 | 104 | struct shfs_bentry *def_bentry; 105 | 106 | /* allocator */ 107 | uint8_t allocator; 108 | struct shfs_alist *al; 109 | }; 110 | 111 | /* chunk_cache_states */ 112 | #define CCS_MODIFIED 0x02 113 | 114 | #endif /* _SHFS_ADMIN_ */ 115 | -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/shfs_alloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple hash filesystem (SHFS) tools 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #include 37 | #include 38 | 39 | #include "shfs_alloc.h" 40 | 41 | struct shfs_alist *shfs_alloc_alist(chk_t area_size, uint8_t allocator) 42 | { 43 | struct shfs_alist *alist; 44 | 45 | if (allocator != SALLOC_FIRSTFIT && 46 | allocator != SALLOC_BESTFIT) { 47 | errno = ENOTSUP; 48 | return NULL; 49 | } 50 | 51 | alist = malloc(sizeof(*alist)); 52 | if (!alist) 53 | return NULL; 54 | 55 | alist->head = NULL; 56 | alist->tail = NULL; 57 | alist->count = 0; 58 | alist->end = area_size; 59 | alist->allocator = allocator; 60 | return alist; 61 | } 62 | 63 | void shfs_free_alist(struct shfs_alist *al) 64 | { 65 | struct shfs_aentry *cur; 66 | struct shfs_aentry *next; 67 | 68 | if (al) { 69 | cur = al->head; 70 | while (cur) { 71 | next = cur->next; 72 | free(cur); 73 | cur = next; 74 | } 75 | 76 | free(al); 77 | } 78 | } 79 | 80 | int shfs_alist_register(struct shfs_alist *al, chk_t start, chk_t len) 81 | { 82 | struct shfs_aentry *e; 83 | struct shfs_aentry *prev; 84 | struct shfs_aentry *next; 85 | struct shfs_aentry *new; 86 | 87 | new = malloc(sizeof(*new)); 88 | if (!new) 89 | return -ENOMEM; 90 | new->start = start; 91 | new->end = (start + len); 92 | 93 | if (!al->head) { 94 | /* list is empty */ 95 | al->head = new; 96 | al->tail = new; 97 | new->prev = NULL; 98 | new->next = NULL; 99 | } else { 100 | /* search for predecessor which has start <= new->start */ 101 | prev = NULL; 102 | next = NULL; 103 | for (e = al->head; e != NULL; e = e->next) { 104 | if (e->start <= start) { 105 | prev = e; 106 | continue; 107 | } else { 108 | next = e; 109 | break; 110 | } 111 | } 112 | 113 | new->prev = prev; 114 | new->next = next; 115 | if (prev) 116 | prev->next = new; 117 | else 118 | al->head = new; 119 | if (next) 120 | next->prev = new; 121 | else 122 | al->tail = new; 123 | } 124 | 125 | al->count++; 126 | return 0; 127 | } 128 | 129 | int shfs_alist_unregister(struct shfs_alist *al, chk_t start, chk_t len) 130 | { 131 | struct shfs_aentry *e; 132 | chk_t end = (start + len); 133 | 134 | /* search for element in the list and remove it if found */ 135 | for (e = al->head; e != NULL; e = e->next) { 136 | if (e->start == start && 137 | e->end == end) { 138 | if (e->prev) 139 | e->prev->next = e->next; 140 | else 141 | al->head = e->next; 142 | if (e->next) 143 | e->next->prev = e->prev; 144 | else 145 | al->tail = e->prev; 146 | free(e); 147 | al->count--; 148 | return 0; 149 | } 150 | } 151 | 152 | return -ENOENT; 153 | } 154 | 155 | static chk_t _shfs_alist_find_ff(struct shfs_alist *al, chk_t len) 156 | { 157 | struct shfs_aentry *e; 158 | chk_t free_start, free_end; 159 | 160 | /* list all segments */ 161 | for (e = al->head; e != NULL; e = e->next) { 162 | /* find actual start and end of a free space segment */ 163 | free_start = e->end; 164 | while (e->next && 165 | e->next->start <= e->end) { 166 | if (e->next->end > free_start) 167 | free_start = e->next->end; 168 | e = e->next; 169 | } 170 | 171 | if (e->next) 172 | free_end = e->next->start; 173 | else { 174 | free_end = al->end; 175 | if (free_end == free_start) 176 | break; /* nothing else found -> cancel */ 177 | } 178 | 179 | /* free_start and free_end points now to a free space segment */ 180 | if (free_end - free_start >= len) 181 | return free_start; 182 | } 183 | 184 | return 0; 185 | } 186 | 187 | static chk_t _shfs_alist_find_bf(struct shfs_alist *al, chk_t len) 188 | { 189 | struct shfs_aentry *e; 190 | chk_t free_start, free_end; 191 | 192 | /* list all segments */ 193 | for (e = al->head; e != NULL; e = e->next) { 194 | /* find actual start and end of a free space segment */ 195 | free_start = e->end; 196 | while (e->next && 197 | e->next->start <= e->end) { 198 | if (e->next->end > free_start) 199 | free_start = e->next->end; 200 | e = e->next; 201 | } 202 | 203 | if (e->next) 204 | free_end = e->next->start; 205 | else { 206 | free_end = al->end; 207 | if (free_end == free_start) 208 | break; /* nothing else found -> cancel */ 209 | } 210 | 211 | /* free_start and free_end points now to a free space segment */ 212 | printf("[FREE] %15"PRIchk" - %15"PRIchk"\n", free_start, free_end); 213 | } 214 | 215 | return 0; 216 | } 217 | 218 | chk_t shfs_alist_find_free(struct shfs_alist *al, chk_t len) 219 | { 220 | switch (al->allocator) { 221 | case SALLOC_FIRSTFIT: 222 | return _shfs_alist_find_ff(al, len); 223 | case SALLOC_BESTFIT: 224 | return _shfs_alist_find_bf(al, len); 225 | default: 226 | break; 227 | } 228 | return 0; 229 | } 230 | -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/shfs_alloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple hash filesystem (SHFS) tools 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _SHFS_ALLOC_ 37 | #define _SHFS_ALLOC_ 38 | 39 | #include "shfs_defs.h" 40 | 41 | struct shfs_aentry { 42 | chk_t start; 43 | chk_t end; 44 | 45 | struct shfs_aentry *next; 46 | struct shfs_aentry *prev; 47 | }; 48 | 49 | struct shfs_alist { 50 | chk_t end; 51 | unsigned int count; 52 | uint8_t allocator; 53 | 54 | struct shfs_aentry *head; 55 | struct shfs_aentry *tail; 56 | }; 57 | 58 | struct shfs_alist *shfs_alloc_alist(chk_t area_size, uint8_t allocator); 59 | void shfs_free_alist(struct shfs_alist *al); 60 | 61 | int shfs_alist_register(struct shfs_alist *al, chk_t start, chk_t len); 62 | int shfs_alist_unregister(struct shfs_alist *al, chk_t start, chk_t len); 63 | chk_t shfs_alist_find_free(struct shfs_alist *al, chk_t len); 64 | 65 | 66 | /******* DEBUG ********/ 67 | #include 68 | 69 | static inline print_alist(struct shfs_alist *al) 70 | { 71 | struct shfs_aentry *e; 72 | unsigned int i = 0; 73 | 74 | for (e = al->head; e != NULL; e = e->next) 75 | printf("[entry%5u] %15"PRIchk" - %15"PRIchk" (len: %15"PRIchk")\n", i++, e->start, e->end, e->end - e->start); 76 | } 77 | 78 | 79 | #endif /* _SHFS_ALLOC_ */ 80 | -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/shfs_btable.h: -------------------------------------------------------------------------------- 1 | ../shfs_btable.h -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/shfs_check.c: -------------------------------------------------------------------------------- 1 | ../shfs_check.c -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/shfs_check.h: -------------------------------------------------------------------------------- 1 | ../shfs_check.h -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/shfs_defs.h: -------------------------------------------------------------------------------- 1 | ../shfs_defs.h -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/shfs_mkfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple hash filesystem (SHFS) tools 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _SHFS_MKFS_ 37 | #define _SHFS_MKFS_ 38 | 39 | #include "tools_common.h" 40 | 41 | #define STR_VERSION "Simple Hash FS (SHFS) Tools: MakeFS" 42 | 43 | struct args { 44 | char **devpath; 45 | uint8_t nb_devs; 46 | 47 | uint8_t encoding; 48 | char volname[17]; /* null-terminated */ 49 | uint32_t stripesize; 50 | 51 | int fullerase; 52 | int combined_striping; 53 | 54 | uint8_t allocator; 55 | uint8_t hashfunc; 56 | uint8_t hashlen; 57 | uint32_t bucket_count; 58 | uint32_t entries_per_bucket; 59 | }; 60 | 61 | #endif /* _SHFS_MKFS_ */ 62 | -------------------------------------------------------------------------------- /minios/shfs/shfs-tools/tools_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple hash filesystem (SHFS) tools 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _TOOLS_COMMON_ 37 | #define _TOOLS_COMMON_ 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include "shfs_defs.h" 47 | 48 | /* 49 | * Print helpers 50 | */ 51 | extern unsigned int verbosity; 52 | extern int force; 53 | 54 | #define eprintf(...) fprintf(stderr, __VA_ARGS__) 55 | #define fatal() eprintf("%s\n", strerror(errno)) 56 | #define dief(...) do { eprintf(__VA_ARGS__); exit(EXIT_FAILURE); } while(0) 57 | #define die() do { fatal(); exit(EXIT_FAILURE); } while(0) 58 | #define dprintf(LEVEL, ...) do { if (verbosity >= (LEVEL)) fprintf(stderr, __VA_ARGS__); } while(0) 59 | #define printvar(VAR, FMT) do { if (verbosity >= (D_MAX)) fprintf(stderr, #VAR ": "FMT"\n", (VAR)); } while(0) 60 | 61 | #define D_L0 1 62 | #define D_L1 2 63 | #define D_MAX D_L1 64 | 65 | 66 | /* 67 | * Argument parsing helper 68 | */ 69 | static inline int parse_args_setval_str(char** out, const char* buf) 70 | { 71 | if (*out) 72 | free(*out); 73 | *out = strdup(buf); 74 | if (!*out) { 75 | *out = NULL; 76 | return -ENOMEM; 77 | } 78 | 79 | return 0; 80 | } 81 | 82 | static inline int parse_args_setval_int(int* out, const char* buf) 83 | { 84 | if (sscanf(optarg, "%d", out) != 1) 85 | return -EINVAL; 86 | return 0; 87 | } 88 | 89 | /* 90 | * Disk I/O 91 | */ 92 | struct disk { 93 | int fd; 94 | char *path; 95 | uint64_t size; 96 | uint32_t blksize; 97 | int discard; 98 | }; 99 | 100 | struct disk *open_disk(const char *path, int mode); 101 | void close_disk(struct disk *d); 102 | 103 | struct vol_member { 104 | struct disk *d; 105 | uuid_t uuid; 106 | }; 107 | 108 | struct storage { 109 | struct vol_member member[SHFS_MAX_NB_MEMBERS]; 110 | uint8_t nb_members; 111 | uint32_t stripesize; 112 | uint8_t stripemode; 113 | }; 114 | 115 | int sync_io_chunk(struct storage *s, chk_t start, chk_t len, int owrite, void *buffer); 116 | #define sync_read_chunk(s, start, len, buffer) \ 117 | sync_io_chunk((s), (start), (len), 0, (buffer)) 118 | #define sync_write_chunk(s, start, len, buffer) \ 119 | sync_io_chunk((s), (start), (len), 1, (buffer)) 120 | int sync_erase_chunk(struct storage *s, chk_t start, chk_t len); 121 | 122 | 123 | /* 124 | * Misc 125 | */ 126 | void print_shfs_hdr_summary(struct shfs_hdr_common *hdr_common, 127 | struct shfs_hdr_config *hdr_config); 128 | chk_t metadata_size(struct shfs_hdr_common *hdr_common, 129 | struct shfs_hdr_config *hdr_config); 130 | chk_t avail_space(struct shfs_hdr_common *hdr_common, 131 | struct shfs_hdr_config *hdr_config); 132 | static inline void hash_unparse(hash512_t h, uint8_t hlen, char *out) 133 | { 134 | uint8_t i; 135 | 136 | for (i = 0; i < hlen; i++) 137 | snprintf(out + (2*i), 3, "%02x", h[i]); 138 | } 139 | 140 | static inline size_t strftimestamp_s(char *s, size_t slen, const char *fmt, uint64_t ts_sec) 141 | { 142 | struct tm *tm; 143 | time_t *tsec = (time_t *) &ts_sec; 144 | tm = localtime(tsec); 145 | return strftime(s, slen, fmt, tm); 146 | } 147 | 148 | size_t strshfshost(char *s, size_t slen, struct shfs_host *h); 149 | 150 | #endif /* _TOOLS_COMMON_ */ 151 | -------------------------------------------------------------------------------- /minios/shfs/shfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HashFS (SHFS) for Mini-OS 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _SHFS_H_ 37 | #define _SHFS_H_ 38 | 39 | //#include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | typedef struct semaphore sem_t; 47 | #include "blkdev.h" 48 | #include 49 | 50 | #include "mempool.h" 51 | #include "likely.h" 52 | 53 | #include "shfs_defs.h" 54 | #ifdef SHFS_STATS 55 | #include "shfs_stats_data.h" 56 | #endif 57 | 58 | #if defined __MINIOS__ && !defined CONFIG_ARM && !defined DEBUG_BUILD 59 | #include 60 | #define shfs_memcpy(dst, src, len) \ 61 | rte_memcpy((dst), (src), (len)) 62 | #warning "rte_memcpy is used for SHFS" 63 | #else 64 | #define shfs_memcpy(dst, src, len) \ 65 | memcpy((dst), (src), (len)) 66 | #endif 67 | 68 | #define MAX_NB_TRY_BLKDEVS 64 69 | #define NB_AIOTOKEN 750 /* should be at least MAX_REQUESTS */ 70 | 71 | struct shfs_cache; 72 | 73 | struct vol_member { 74 | struct blkdev *bd; 75 | uuid_t uuid; 76 | sector_t sfactor; 77 | }; 78 | 79 | struct vol_info { 80 | uuid_t uuid; 81 | char volname[17]; 82 | uint64_t ts_creation; 83 | uint32_t chunksize; 84 | chk_t volsize; 85 | 86 | uint8_t nb_members; 87 | struct vol_member member[SHFS_MAX_NB_MEMBERS]; 88 | uint32_t stripesize; 89 | uint8_t stripemode; 90 | uint32_t ioalign; 91 | #if defined CONFIG_SELECT_POLL && defined CAN_POLL_BLKDEV 92 | int members_maxfd; /* biggest fd number of mounted members (required for select()) */ 93 | #endif 94 | 95 | struct htable *bt; /* SHFS bucket entry table */ 96 | void **htable_chunk_cache; 97 | void *remount_chunk_buffer; 98 | chk_t htable_ref; 99 | chk_t htable_bak_ref; 100 | chk_t htable_len; 101 | uint32_t htable_nb_buckets; 102 | uint32_t htable_nb_entries; 103 | uint32_t htable_nb_entries_per_bucket; 104 | uint32_t htable_nb_entries_per_chunk; 105 | uint8_t hlen; 106 | 107 | struct shfs_bentry *def_bentry; 108 | 109 | struct mempool *aiotoken_pool; /* token for async I/O */ 110 | struct shfs_cache *chunkcache; /* chunkcache */ 111 | 112 | #ifdef SHFS_STATS 113 | struct shfs_mstats mstats; 114 | #endif 115 | }; 116 | 117 | extern struct vol_info shfs_vol; 118 | extern sem_t shfs_mount_lock; 119 | extern int shfs_mounted; 120 | extern unsigned int shfs_nb_open; 121 | 122 | int init_shfs(void); 123 | int mount_shfs(blkdev_id_t bd_id[], unsigned int count); 124 | int remount_shfs(void); 125 | int umount_shfs(int force); 126 | void exit_shfs(void); 127 | 128 | #define shfs_blkdevs_count() \ 129 | ((shfs_mounted) ? shfs_vol.nb_members : 0) 130 | 131 | static inline void shfs_poll_blkdevs(void) { 132 | register unsigned int i; 133 | register uint8_t m = shfs_blkdevs_count(); 134 | 135 | for(i = 0; i < m; ++i) 136 | blkdev_poll_req(shfs_vol.member[i].bd); 137 | } 138 | 139 | #ifdef CAN_POLL_BLKDEV 140 | #include 141 | 142 | static inline void shfs_blkdevs_fds(int *fds) { 143 | register unsigned int i; 144 | register uint8_t m = shfs_blkdevs_count(); 145 | 146 | for(i = 0; i < m; ++i) 147 | fds[i] = blkdev_get_fd(shfs_vol.member[i].bd); 148 | } 149 | 150 | static inline void shfs_blkdevs_fdset(fd_set *fdset) { 151 | register unsigned int i; 152 | register uint8_t m = shfs_blkdevs_count(); 153 | 154 | for(i = 0; i < m; ++i) 155 | FD_SET(blkdev_get_fd(shfs_vol.member[i].bd), fdset); 156 | } 157 | #endif /* CAN_POLL_BLKDEV */ 158 | 159 | /** 160 | * Fast I/O: asynchronous I/O for volume chunks 161 | * A request is done via shfs_aio_chunk(). This function returns immediately 162 | * after the I/O request was set up. 163 | * Afterwards, the caller has to wait for the I/O completion via 164 | * tests on shfs_aio_is_done() or by calling shfs_aio_wait() or using a 165 | * function callback registration on shfs_aio_chunk(). 166 | * The result (return code) of the I/O operation is retrieved via 167 | * shfs_aio_finalize() (can be called within the user's callback). 168 | */ 169 | struct _shfs_aio_token; 170 | typedef struct _shfs_aio_token SHFS_AIO_TOKEN; 171 | typedef void (shfs_aiocb_t)(SHFS_AIO_TOKEN *t, void *cookie, void *argp); 172 | struct _shfs_aio_token { 173 | /** this struct has only private data **/ 174 | struct mempool_obj *p_obj; 175 | uint64_t infly; 176 | int ret; 177 | 178 | shfs_aiocb_t *cb; 179 | void *cb_cookie; 180 | void *cb_argp; 181 | 182 | struct _shfs_aio_token *_prev; /* token chains (used by shfs_cache) */ 183 | struct _shfs_aio_token *_next; 184 | }; 185 | 186 | /* 187 | * Setups a asynchronous I/O operation and returns a token 188 | * NULL is returned if the async I/O operation could not be set up 189 | * The callback registration is optional and can be seen as an alternative way 190 | * to wait for the I/O completation compared to using shfs_aio_is_done() 191 | * or shfs_aio_wait() 192 | * cb_cookie and cb_argp are user definable values that get passed 193 | * to the user defined callback. 194 | */ 195 | SHFS_AIO_TOKEN *shfs_aio_chunk(chk_t start, chk_t len, int write, void *buffer, 196 | shfs_aiocb_t *cb, void *cb_cookie, void *cb_argp); 197 | #define shfs_aread_chunk(start, len, buffer, cb, cb_cookie, cb_argp) \ 198 | shfs_aio_chunk((start), (len), 0, (buffer), (cb), (cb_cookie), (cb_argp)) 199 | #define shfs_awrite_chunk(start, len, buffer, cb, cb_cookie, cb_argp) \ 200 | shfs_aio_chunk((start), (len), 1, (buffer), (cb), (cb_cookie), (cb_argp)) 201 | 202 | static inline void shfs_aio_submit(void) { 203 | register unsigned int i; 204 | register uint8_t m = shfs_blkdevs_count(); 205 | 206 | for(i = 0; i < m; ++i) 207 | blkdev_async_io_submit(shfs_vol.member[i].bd); 208 | } 209 | 210 | static inline void shfs_aio_wait_slot(void) { 211 | register unsigned int i; 212 | register uint8_t m = shfs_blkdevs_count(); 213 | 214 | for(i = 0; i < m; ++i) 215 | blkdev_async_io_wait_slot(shfs_vol.member[i].bd); 216 | } 217 | 218 | /* 219 | * Internal AIO token management (do not use this functions directly!) 220 | */ 221 | static inline SHFS_AIO_TOKEN *shfs_aio_pick_token(void) 222 | { 223 | struct mempool_obj *t_obj; 224 | t_obj = mempool_pick(shfs_vol.aiotoken_pool); 225 | if (!t_obj) 226 | return NULL; 227 | return (SHFS_AIO_TOKEN *) t_obj->data; 228 | } 229 | #define shfs_aio_put_token(t) \ 230 | mempool_put(t->p_obj) 231 | 232 | /* 233 | * Returns 1 if the I/O operation has finished, 0 otherwise 234 | */ 235 | #define shfs_aio_is_done(t) \ 236 | (!(t) || (t)->infly == 0) 237 | 238 | /* 239 | * Busy-waiting until the async I/O operation is completed 240 | * 241 | * Note: This function will end up in a deadlock when there is no 242 | * SHFS volume mounted 243 | */ 244 | #define shfs_aio_wait(t) \ 245 | while (!shfs_aio_is_done((t))) { \ 246 | shfs_poll_blkdevs(); \ 247 | if (!shfs_aio_is_done((t))) \ 248 | schedule(); \ 249 | } 250 | 251 | #define shfs_aio_wait_nosched(t) \ 252 | while (!shfs_aio_is_done((t))) { \ 253 | shfs_poll_blkdevs(); \ 254 | } 255 | 256 | /* 257 | * Destroys an asynchronous I/O token after the I/O completed 258 | * This function returns the return code of the IO operation 259 | * 260 | * Note: This function has and can only be called after an I/O is done! 261 | */ 262 | static inline int shfs_aio_finalize(SHFS_AIO_TOKEN *t) 263 | { 264 | int ret; 265 | 266 | BUG_ON(t->infly != 0); 267 | ret = t->ret; 268 | shfs_aio_put_token(t); 269 | 270 | return ret; 271 | } 272 | 273 | /** 274 | * Slow I/O: sequential sync I/O for volume chunks 275 | * These functions are intended to be used during mount/umount time 276 | */ 277 | static inline int shfs_io_chunk(chk_t start, chk_t len, int write, void *buffer) { 278 | SHFS_AIO_TOKEN *t; 279 | 280 | retry: 281 | t = shfs_aio_chunk(start, len, write, buffer, NULL, NULL, NULL); 282 | shfs_aio_submit(); 283 | if (unlikely(!t && errno == EBUSY)) { 284 | shfs_aio_wait_slot(); /* yield CPU */ 285 | goto retry; 286 | } 287 | if (unlikely(!t)) 288 | return -errno; 289 | 290 | shfs_aio_wait(t); 291 | return shfs_aio_finalize(t); 292 | } 293 | #define shfs_read_chunk(start, len, buffer) \ 294 | shfs_io_chunk((start), (len), 0, (buffer)) 295 | #define shfs_write_chunk(start, len, buffer) \ 296 | shfs_io_chunk((start), (len), 1, (buffer)) 297 | 298 | static inline int shfs_io_chunk_nosched(chk_t start, chk_t len, int write, void *buffer) { 299 | SHFS_AIO_TOKEN *t; 300 | 301 | retry: 302 | t = shfs_aio_chunk(start, len, write, buffer, NULL, NULL, NULL); 303 | shfs_aio_submit(); 304 | if (unlikely(!t && errno == EBUSY)) 305 | goto retry; 306 | if (unlikely(!t)) 307 | return -errno; 308 | 309 | shfs_aio_wait_nosched(t); 310 | return shfs_aio_finalize(t); 311 | } 312 | #define shfs_read_chunk_nosched(start, len, buffer) \ 313 | shfs_io_chunk_nosched((start), (len), 0, (buffer)) 314 | #define shfs_write_chunk_nosched(start, len, buffer) \ 315 | shfs_io_chunk_nosched((start), (len), 1, (buffer)) 316 | 317 | #endif /* _SHFS_H_ */ 318 | -------------------------------------------------------------------------------- /minios/shfs/shfs_btable.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple HashFS (SHFS) for Mini-OS 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _SHFS_BTABLE_H_ 37 | #define _SHFS_BTABLE_H_ 38 | 39 | #ifdef __SHFS_TOOLS__ 40 | #include 41 | #include 42 | #define ASSERT assert 43 | #else 44 | //#include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | typedef struct semaphore sem_t; 52 | #endif 53 | 54 | #include "shfs_defs.h" 55 | #include "htable.h" 56 | 57 | #ifdef SHFS_STATS 58 | #include "shfs_stats_data.h" 59 | #endif 60 | 61 | #ifndef CACHELINE_SIZE 62 | #define CACHELINE_SIZE 64 63 | #endif 64 | 65 | /* 66 | * Bucket entry that points to 67 | * the depending hentry (SHFS Hash Table Entry) 68 | */ 69 | struct shfs_bentry { 70 | chk_t hentry_htchunk; /* relative chunk:offfset addres to entry in SHFS htable */ 71 | off_t hentry_htoffset; 72 | 73 | #ifndef __SHFS_TOOLS__ 74 | struct shfs_hentry *hentry; /* reference to buffered entry in cache */ 75 | uint32_t refcount; 76 | sem_t updatelock; /* lock is helt as long the file is opened */ 77 | int update; /* is set when a entry update is ongoing */ 78 | 79 | #ifdef SHFS_STATS 80 | struct shfs_el_stats hstats; 81 | #endif /* SHFS_STATS */ 82 | 83 | void *cookie; /* shfs_fio: upper layer software can attach cookies to open files */ 84 | #endif 85 | }; 86 | 87 | #define shfs_alloc_btable(nb_bkts, ent_per_bkt, hlen) \ 88 | alloc_htable((nb_bkts), (ent_per_bkt), (hlen), sizeof(struct shfs_bentry), CACHELINE_SIZE); 89 | #define shfs_free_btable(bt) \ 90 | free_htable((bt)) 91 | 92 | /** 93 | * Does a lookup for a bucket entry by its hash value 94 | */ 95 | static inline struct shfs_bentry *shfs_btable_lookup(struct htable *bt, hash512_t h) { 96 | struct htable_el *el; 97 | 98 | el = htable_lookup(bt, h); 99 | if (el) 100 | return (struct shfs_bentry *) el->private; 101 | return NULL; 102 | } 103 | 104 | /** 105 | * Searches and allocates an according bucket entry for a given hash value 106 | */ 107 | static inline struct shfs_bentry *shfs_btable_addentry(struct htable *bt, hash512_t h) { 108 | struct htable_el *el; 109 | 110 | el = htable_add(bt, h); 111 | if (el) 112 | return (struct shfs_bentry *) el->private; 113 | return NULL; 114 | } 115 | 116 | #ifndef __MINIOS__ 117 | /** 118 | * Deletes an entry from table 119 | */ 120 | static void shfs_btable_rmentry(struct htable *bt, hash512_t h) { 121 | struct htable_el *el; 122 | 123 | el = htable_lookup(bt, h); 124 | if (el) 125 | htable_rm(bt, el); 126 | } 127 | #endif 128 | 129 | /** 130 | * This function is intended to be used during (re-)mount time. 131 | * It is intended to load a hash table from a device: 132 | * It picks a bucket entry by its total index of the hash table, 133 | * replaces its hash value and (re-)links the element to the end of the table list. 134 | * The functions returns the according shfs_bentry so that this data structure 135 | * can be filled-in/updated with further meta data 136 | */ 137 | static inline struct shfs_bentry *shfs_btable_feed(struct htable *bt, uint64_t ent_idx, hash512_t h) { 138 | uint32_t bkt_idx; 139 | uint32_t el_idx_bkt; 140 | struct htable_bkt *b; 141 | struct htable_el *el; 142 | 143 | /* TODO: Check for overflows */ 144 | bkt_idx = (uint32_t) (ent_idx / (uint64_t) bt->el_per_bkt); 145 | el_idx_bkt = (uint32_t) (ent_idx % (uint64_t) bt->el_per_bkt); 146 | ASSERT(bkt_idx < bt->nb_bkts); 147 | 148 | /* entry found */ 149 | b = bt->b[bkt_idx]; 150 | el = _htable_bkt_el(b, el_idx_bkt); 151 | 152 | /* check if a previous entry was there -> if yes, unlink it */ 153 | if (!hash_is_zero(b->h[el_idx_bkt], bt->hlen)) { 154 | if (el->prev) 155 | el->prev->next = el->next; 156 | else 157 | bt->head = el->next; 158 | 159 | if (el->next) 160 | el->next->prev = el->prev; 161 | else 162 | bt->tail = el->prev; 163 | } 164 | 165 | /* replace hash value */ 166 | hash_copy(b->h[el_idx_bkt], h, bt->hlen); 167 | 168 | /* link the new element to the list, (if it is not empty) */ 169 | if (!hash_is_zero(h, bt->hlen)) { 170 | if (!bt->head) { 171 | bt->head = el; 172 | bt->tail = el; 173 | el->prev = NULL; 174 | el->next = NULL; 175 | } else { 176 | bt->tail->next = el; 177 | el->prev = bt->tail; 178 | el->next = NULL; 179 | bt->tail = el; 180 | } 181 | } 182 | 183 | return (struct shfs_bentry *) el->private; 184 | } 185 | 186 | #endif /* _SHFS_BTABLE_H_ */ 187 | -------------------------------------------------------------------------------- /minios/shfs/shfs_check.c: -------------------------------------------------------------------------------- 1 | /* 2 | * HashFS (SHFS) for Mini-OS 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #include "shfs_check.h" 37 | #include "shfs_defs.h" 38 | 39 | int shfs_detect_hdr0(void *chk0) { 40 | struct shfs_hdr_common *hdr_common; 41 | 42 | hdr_common = (void *)((uint8_t *) chk0 + BOOT_AREA_LENGTH); 43 | 44 | /* Check for SHFS magic */ 45 | if (hdr_common->magic[0] != SHFS_MAGIC0) 46 | return -1; 47 | if (hdr_common->magic[1] != SHFS_MAGIC1) 48 | return -1; 49 | if (hdr_common->magic[2] != SHFS_MAGIC2) 50 | return -1; 51 | if (hdr_common->magic[3] != SHFS_MAGIC3) 52 | return -1; 53 | 54 | /* Check for compatible version */ 55 | if (hdr_common->version[0] != SHFS_MAJOR) 56 | return -2; 57 | if (hdr_common->version[1] != SHFS_MINOR) 58 | return -2; 59 | 60 | /* Check Endianess */ 61 | #if __BYTE_ORDER == __LITTLE_ENDIAN 62 | if (hdr_common->vol_byteorder != SBO_LITTLEENDIAN) 63 | #elif __BYTE_ORDER == __BIG_ENDIAN 64 | if (hdr_common->vol_byteorder != SBO_BIGENDIAN) 65 | #else 66 | #warning "Could not detect byte-order" 67 | #endif 68 | return -3; 69 | 70 | /* Briefly check member count */ 71 | if (hdr_common->member_count == 0 || hdr_common->member_count > SHFS_MAX_NB_MEMBERS) 72 | return -4; 73 | 74 | return 1; /* SHFSv1 detected */ 75 | } 76 | -------------------------------------------------------------------------------- /minios/shfs/shfs_check.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HashFS (SHFS) for Mini-OS 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _SHFS_CHECK_H_ 37 | #define _SHFS_CHECK_H_ 38 | 39 | /** 40 | * Can be used to detect an compatible SHFS filesystem 41 | * header. It returns a value >= 0 if SHFS was detected. 42 | * Note: chk0 buffer has to be at least 4096 bytes long 43 | */ 44 | int shfs_detect_hdr0(void *chk0); 45 | 46 | #endif /* _SHFS_CHECK_H_ */ 47 | -------------------------------------------------------------------------------- /minios/shfs/shfs_defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HashFS (SHFS) for Mini-OS 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _SHFS_DEFS_H_ 37 | #define _SHFS_DEFS_H_ 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include "hash.h" 46 | 47 | #ifdef __SHFS_TOOLS__ 48 | #include 49 | #include 50 | #else 51 | typedef uint8_t uuid_t[16]; 52 | #endif /* __SHFS_TOOLS__ */ 53 | 54 | typedef uint64_t chk_t; 55 | typedef uint64_t strp_t; 56 | 57 | #define PRIchk PRIu64 58 | #define PRIstrp PRIu64 59 | 60 | #define SHFS_MAX_NB_MEMBERS 16 61 | 62 | /* vol_byteorder */ 63 | #define SBO_LITTLEENDIAN 0 64 | #define SBO_BIGENDIAN 1 65 | 66 | /* vol_encoding */ 67 | #define SENC_UNSPECIFIED 0 68 | 69 | /* allocator */ 70 | #define SALLOC_FIRSTFIT 0 71 | #define SALLOC_BESTFIT 1 72 | 73 | /* hash function */ 74 | #define SHFUNC_MANUAL 1 75 | #define SHFUNC_SHA 2 76 | #define SHFUNC_CRC 3 77 | #define SHFUNC_MD5 4 78 | #define SHFUNC_HAVAL 5 79 | 80 | /* 81 | * Helper 82 | */ 83 | #ifndef ALIGN_UP 84 | /* Note: align has to be a power of 2 */ 85 | #define ALIGN_UP(size, align) (((size) + (align) - 1) & ~((align) - 1)) 86 | #endif 87 | #ifndef DIV_ROUND_UP 88 | #define DIV_ROUND_UP(num, div) (((num) + (div) - 1) / (div)) 89 | #endif 90 | #ifndef POWER_OF_2 91 | #define POWER_OF_2(x) ((0 != x) && (0 == (x & (x-1)))) 92 | #endif 93 | #ifndef min 94 | #define min(a, b) \ 95 | ({ __typeof__ (a) __a = (a); \ 96 | __typeof__ (b) __b = (b); \ 97 | __a < __b ? __a : __b; }) 98 | #endif 99 | #ifndef max 100 | #define max(a, b) \ 101 | ({ __typeof__ (a) __a = (a); \ 102 | __typeof__ (b) __b = (b); \ 103 | __a > __b ? __a : __b; }) 104 | #endif 105 | 106 | struct shfs_host { 107 | uint8_t type; /* name or address */ 108 | union { 109 | char name[32]; /* hostname */ 110 | uint8_t addr[32]; /* address (e.g., IPv4, IPv6) */ 111 | }; 112 | } __attribute__((packed)); 113 | 114 | #define SHFS_HOST_TYPE_NAME 0x00 115 | #define SHFS_HOST_TYPE_IPV4 0x01 116 | #define SHFS_HOST_TYPE_IPV6 0x02 /* not supported yet */ 117 | 118 | /** 119 | * Common SHFS header 120 | * (on chunk no. 0) 121 | * Note: character strings fields are not necessarily null-terminated 122 | */ 123 | #define BOOT_AREA_LENGTH 1024 124 | #define SHFS_MAGIC0 'S' 125 | #define SHFS_MAGIC1 'H' 126 | #define SHFS_MAGIC2 'F' 127 | #define SHFS_MAGIC3 'S' 128 | #define SHFS_MAJOR 0x02 129 | #define SHFS_MINOR 0x01 130 | 131 | /* member_stripemode */ 132 | #define SHFS_SM_INDEPENDENT 0x0 133 | #define SHFS_SM_COMBINED 0x1 134 | 135 | struct shfs_hdr_common { 136 | uint8_t magic[4]; 137 | uint8_t version[2]; /* little endian */ 138 | uuid_t vol_uuid; 139 | char vol_name[16]; 140 | uint8_t vol_byteorder; 141 | uint8_t vol_encoding; 142 | chk_t vol_size; 143 | uint64_t vol_ts_creation; 144 | uint8_t member_stripemode; 145 | uint32_t member_stripesize; /* at least 4 KiB (because of first chunk), blkfront can handle at most 32 KiB */ 146 | uuid_t member_uuid; /* this disk */ 147 | uint8_t member_count; 148 | struct { /* uuid's of all members */ 149 | uuid_t uuid; 150 | } member[SHFS_MAX_NB_MEMBERS]; 151 | } __attribute__((packed)); 152 | 153 | 154 | /** 155 | * SHFS configuration header 156 | * (on chunk no. 1) 157 | */ 158 | struct shfs_hdr_config { 159 | chk_t htable_ref; 160 | chk_t htable_bak_ref; /* if 0 => no backup */ 161 | uint8_t hfunc; 162 | uint8_t hlen; /* num bytes of hash digest, max is 64 (= 512 bits) */ 163 | uint32_t htable_bucket_count; 164 | uint32_t htable_entries_per_bucket; 165 | uint8_t allocator; 166 | } __attribute__((packed)); 167 | 168 | /** 169 | * SHFS entry (container description) 170 | * Note: character strings fields are not necessarily null-terminated 171 | */ 172 | /* hentry flags */ 173 | #define SHFS_EFLAG_HIDDEN 0x1 174 | #define SHFS_EFLAG_DEFAULT 0x8 175 | #define SHFS_EFLAG_LINK 0x4 176 | 177 | /* l_attr.type */ 178 | #define SHFS_LTYPE_REDIRECT 0x0 179 | #define SHFS_LTYPE_RAW 0x1 180 | #define SHFS_LTYPE_AUTO 0x2 181 | 182 | struct shfs_hentry { 183 | hash512_t hash; /* hash digest */ 184 | 185 | union { 186 | /* SHFS_EFLAG_LINK not set */ 187 | struct { 188 | chk_t chunk; 189 | uint64_t offset; /* byte offset, usually 0 */ 190 | uint64_t len; /* length (bytes) */ 191 | 192 | char mime[32]; /* internet media type */ 193 | char encoding[16]; /* set on pre-encoded content */ 194 | } f_attr __attribute__((packed)); 195 | 196 | /* SHFS_EFLAG_LINK set */ 197 | struct { 198 | struct shfs_host rhost; /* remote host */ 199 | uint16_t rport; 200 | char rpath[64 + 7]; 201 | uint8_t type; 202 | } l_attr __attribute__((packed)); 203 | }; 204 | 205 | uint64_t ts_creation; 206 | uint8_t flags; 207 | char name[64]; 208 | } __attribute__((packed)); 209 | 210 | #define SHFS_MIN_CHUNKSIZE 4096 211 | 212 | #define CHUNKS_TO_BYTES(chunks, chunksize) ((uint64_t) (chunks) * (uint64_t) (chunksize)) 213 | 214 | #define SHFS_CHUNKSIZE(hdr_common) (hdr_common->member_stripemode == SHFS_SM_COMBINED ? \ 215 | ((hdr_common)->member_stripesize * (uint32_t) ((hdr_common)->member_count)) : \ 216 | (hdr_common)->member_stripesize) 217 | #define SHFS_HENTRY_ALIGN 64 /* has to be a power of 2 */ 218 | #define SHFS_HENTRY_SIZE ALIGN_UP(sizeof(struct shfs_hentry), SHFS_HENTRY_ALIGN) 219 | #define SHFS_HENTRIES_PER_CHUNK(chunksize) ((chunksize) / SHFS_HENTRY_SIZE) 220 | 221 | #define SHFS_HTABLE_NB_ENTRIES(hdr_config) \ 222 | ((hdr_config)->htable_entries_per_bucket * (hdr_config)->htable_bucket_count) 223 | #define SHFS_HTABLE_SIZE_CHUNKS(hdr_config, chunksize) \ 224 | DIV_ROUND_UP(SHFS_HTABLE_NB_ENTRIES((hdr_config)), SHFS_HENTRIES_PER_CHUNK((chunksize))) 225 | 226 | #define SHFS_HTABLE_CHUNK_NO(hentry_no, hentries_per_chunk) \ 227 | ((hentry_no) / (hentries_per_chunk)) 228 | #define SHFS_HTABLE_ENTRY_OFFSET(hentry_no, hentries_per_chunk) \ 229 | (((hentry_no) % (hentries_per_chunk)) * SHFS_HENTRY_SIZE) 230 | 231 | #define SHFS_HENTRY_ISHIDDEN(hentry) \ 232 | ((hentry)->flags & (SHFS_EFLAG_HIDDEN)) 233 | #define SHFS_HENTRY_ISDEFAULT(hentry) \ 234 | ((hentry)->flags & (SHFS_EFLAG_DEFAULT)) 235 | #define SHFS_HENTRY_ISLINK(hentry) \ 236 | ((hentry)->flags & (SHFS_EFLAG_LINK)) 237 | 238 | #define SHFS_HENTRY_LINKATTR(hentry) \ 239 | ((hentry)->l_attr) 240 | #define SHFS_HENTRY_FILEATTR(hentry) \ 241 | ((hentry)->f_attr) 242 | 243 | #define SHFS_HENTRY_LINK_TYPE(hentry) \ 244 | ((SHFS_HENTRY_LINKATTR((hentry))).type) 245 | 246 | #ifndef __SHFS_TOOLS__ 247 | static inline int uuid_compare(const uuid_t uu1, const uuid_t uu2) 248 | { 249 | return memcmp(uu1, uu2, sizeof(uuid_t)); 250 | } 251 | 252 | static inline int uuid_is_zero(const uuid_t uu) 253 | { 254 | unsigned i; 255 | for (i = 0; i < sizeof(uuid_t); ++i) 256 | if (uu[i] != 0) 257 | return 0; 258 | return 1; 259 | } 260 | 261 | static inline int uuid_is_null(const uuid_t uu) 262 | { 263 | return (uu == NULL); 264 | } 265 | 266 | static inline void uuid_copy(uuid_t dst, const uuid_t src) 267 | { 268 | memcpy(dst, src, sizeof(uuid_t)); 269 | } 270 | #endif /* __SHFS_TOOLS__ */ 271 | 272 | static inline int shfshost_compare(const struct shfs_host *h0, const struct shfs_host *h1) 273 | { 274 | size_t l0, l1; 275 | 276 | if (h0->type != h1->type) 277 | return 1; 278 | 279 | switch(h0->type) { 280 | case SHFS_HOST_TYPE_NAME: 281 | l0 = strnlen(h0->name, sizeof(h0->name)); 282 | l1 = strnlen(h1->name, sizeof(h1->name)); 283 | 284 | if (l0 != l1) 285 | return 1; 286 | return (memcmp(h0->name, h1->name, l0) != 0); 287 | 288 | case SHFS_HOST_TYPE_IPV4: 289 | if ((h0->addr[0] != h1->addr[0]) || 290 | (h0->addr[1] != h1->addr[1]) || 291 | (h0->addr[2] != h1->addr[2]) || 292 | (h0->addr[3] != h1->addr[3])) 293 | return 1; 294 | break; 295 | default: 296 | return 2; /* unsupported type */ 297 | } 298 | 299 | return 0; 300 | } 301 | 302 | static inline void shfshost_copy(struct shfs_host *dst, const struct shfs_host *src) 303 | { 304 | dst->type = src->type; 305 | 306 | switch(src->type) { 307 | case SHFS_HOST_TYPE_NAME: 308 | strncpy(dst->name, src->name, sizeof(src->name)); 309 | break; 310 | 311 | case SHFS_HOST_TYPE_IPV4: 312 | dst->addr[0] = src->addr[0]; 313 | dst->addr[1] = src->addr[1]; 314 | dst->addr[2] = src->addr[2]; 315 | dst->addr[3] = src->addr[3]; 316 | break; 317 | default: 318 | /* unsupported type; just copy */ 319 | memcpy(dst, src, sizeof(*dst)); 320 | break; 321 | } 322 | } 323 | 324 | static inline uint64_t gettimestamp_s(void) 325 | { 326 | struct timeval now; 327 | gettimeofday(&now, NULL); 328 | return (uint64_t) now.tv_sec; 329 | } 330 | 331 | #endif /* _SHFS_DEFS_H_ */ 332 | -------------------------------------------------------------------------------- /minios/shfs/shfs_fio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HashFS (SHFS) for Mini-OS 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _SHFS_FIO_ 37 | #define _SHFS_FIO_ 38 | 39 | #include "shfs_defs.h" 40 | #include "shfs.h" 41 | #include "shfs_btable.h" 42 | #include "shfs_cache.h" 43 | #include "likely.h" 44 | 45 | #define SHFS_HASH_INDICATOR_PREFIX '?' /* has to be the same as HTTPURL_ARGS_INDICATOR_PREFIX in http.c */ 46 | 47 | typedef struct shfs_bentry *SHFS_FD; 48 | 49 | /** 50 | * Opens a file/object via hash string or name depending on 51 | * the first character of path: 52 | * 53 | * Hash: "?024a5bec" 54 | * Name: "index.html" 55 | */ 56 | SHFS_FD shfs_fio_open(const char *path); 57 | /** 58 | * Opens a file/object via a hash digest 59 | */ 60 | SHFS_FD shfs_fio_openh(hash512_t h); 61 | /** 62 | * Creates a file descriptor clone 63 | */ 64 | SHFS_FD shfs_fio_openf(SHFS_FD f); 65 | /** 66 | * Closes a file descriptor 67 | */ 68 | void shfs_fio_close(SHFS_FD f); 69 | 70 | void shfs_fio_name(SHFS_FD f, char *out, size_t outlen); /* null-termination is ensured */ 71 | void shfs_fio_hash(SHFS_FD f, hash512_t out); 72 | #define shfs_fio_islink(f) \ 73 | (SHFS_HENTRY_ISLINK((f)->hentry)) 74 | void shfs_fio_size(SHFS_FD f, uint64_t *out); /* returns 0 on links */ 75 | 76 | /** 77 | * Link object attributes 78 | * The following interfaces can only be used on link objects 79 | */ 80 | #define shfs_fio_link_type(f) \ 81 | (SHFS_HENTRY_LINK_TYPE((f)->hentry)) 82 | #define shfs_fio_link_rport(f) \ 83 | (SHFS_HENTRY_LINKATTR((f)->hentry).rport) 84 | #define shfs_fio_link_rhost(f) \ 85 | (&(SHFS_HENTRY_LINKATTR((f)->hentry).rhost)) 86 | void shfs_fio_link_rpath(SHFS_FD f, char *out, size_t outlen); /* null-termination is ensured */ 87 | 88 | /** 89 | * File object attributes 90 | * The following interfaces can only be used to non-link objects 91 | */ 92 | void shfs_fio_mime(SHFS_FD f, char *out, size_t outlen); /* null-termination is ensured */ 93 | 94 | /* file container size in chunks */ 95 | #define shfs_fio_size_chks(f) \ 96 | (DIV_ROUND_UP(((f)->hentry->f_attr.offset + (f)->hentry->f_attr.len), shfs_vol.chunksize)) 97 | 98 | /* volume chunk address of file chunk address */ 99 | #define shfs_volchk_fchk(f, fchk) \ 100 | ((f)->hentry->f_attr.chunk + (fchk)) 101 | 102 | /* volume chunk address of file byte offset */ 103 | #define shfs_volchk_foff(f, foff) \ 104 | (((f)->hentry->f_attr.offset + (foff)) / shfs_vol.chunksize + (f)->hentry->f_attr.chunk) 105 | /* byte offset in volume chunk of file byte offset */ 106 | #define shfs_volchkoff_foff(f, foff) \ 107 | (((f)->hentry->f_attr.offset + (foff)) % shfs_vol.chunksize) 108 | 109 | /* Check macros to test if a address is within file bounds */ 110 | #define shfs_is_fchk_in_bound(f, fchk) \ 111 | (shfs_fio_size_chks((f)) > (fchk)) 112 | #define shfs_is_foff_in_bound(f, foff) \ 113 | ((f)->hentry->f_attr.len > (foff)) 114 | 115 | /** 116 | * File cookies 117 | */ 118 | #define shfs_fio_get_cookie(f) \ 119 | ((f)->cookie) 120 | static inline int shfs_fio_set_cookie(SHFS_FD f, void *cookie) { 121 | if (f->cookie) 122 | return -EBUSY; 123 | f->cookie = cookie; 124 | return 0; 125 | } 126 | #define shfs_fio_clear_cookie(f) \ 127 | do { (f)->cookie = NULL; } while (0) 128 | 129 | /* 130 | * Simple but synchronous file read 131 | * Note: Busy-waiting is used 132 | */ 133 | /* direct read */ 134 | int shfs_fio_read(SHFS_FD f, uint64_t offset, void *buf, uint64_t len); 135 | int shfs_fio_read_nosched(SHFS_FD f, uint64_t offset, void *buf, uint64_t len); 136 | /* read is using cache */ 137 | int shfs_fio_cache_read(SHFS_FD f, uint64_t offset, void *buf, uint64_t len); 138 | int shfs_fio_cache_read_nosched(SHFS_FD f, uint64_t offset, void *buf, uint64_t len); 139 | 140 | /* 141 | * Async file read 142 | */ 143 | static inline int shfs_fio_cache_aread(SHFS_FD f, chk_t offset, shfs_aiocb_t *cb, void *cb_cookie, void *cb_argp, struct shfs_cache_entry **cce_out, SHFS_AIO_TOKEN **t_out) 144 | { 145 | register chk_t addr; 146 | 147 | if (unlikely(!(shfs_is_fchk_in_bound(f, offset)))) 148 | return -EINVAL; 149 | addr = shfs_volchk_fchk(f, offset); 150 | return shfs_cache_aread(addr, cb, cb_cookie, cb_argp, cce_out, t_out); 151 | } 152 | 153 | #endif /* _SHFS_FIO_ */ 154 | -------------------------------------------------------------------------------- /minios/shfs/shfs_stats.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Statistics extensions for SHFS 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _SHFS_STATS_H_ 37 | #define _SHFS_STATS_H_ 38 | 39 | #include "shfs_stats_data.h" 40 | #include "shfs_btable.h" 41 | #include "shfs_fio.h" 42 | #include "shfs.h" 43 | #include "likely.h" 44 | #ifdef HAVE_CTLDIR 45 | #include 46 | #endif 47 | 48 | /* 49 | * Retrieve stats structure from SHFS btable entry 50 | */ 51 | #define shfs_stats_from_bentry(bentry) \ 52 | (&((bentry)->hstats)) 53 | 54 | /* 55 | * Retrieves stats structure from an SHFS_FD 56 | * NOTE: No NULL check is made since it is assumed that 57 | * f is provided by the currently mounted shfs hash table 58 | * -> bentry does exist 59 | */ 60 | static inline struct shfs_el_stats *shfs_stats_from_fd(SHFS_FD f) { 61 | struct shfs_bentry *bentry = (struct shfs_bentry *) f; 62 | 63 | return shfs_stats_from_bentry(bentry); 64 | } 65 | 66 | /* 67 | * Retrieves stats element from miss stats table 68 | * NOTE: A new entry is created automatically, if it does not 69 | * exist yet 70 | */ 71 | static inline struct shfs_el_stats *shfs_stats_from_mstats(hash512_t h) { 72 | int is_new; 73 | struct htable_el *el; 74 | struct shfs_el_stats *el_stats; 75 | 76 | el = htable_lookup_add(shfs_vol.mstats.el_ht, h, &is_new); 77 | if (unlikely(!el)) 78 | return NULL; 79 | 80 | el_stats = (struct shfs_el_stats *) el->private; 81 | if (is_new) 82 | memset(el_stats, 0, sizeof(*el_stats)); 83 | return el_stats; 84 | } 85 | 86 | /* 87 | * Deletes an entry from mstat table 88 | */ 89 | static inline void shfs_stats_mstats_drop(hash512_t h) { 90 | struct htable_el *el; 91 | 92 | el = htable_lookup(shfs_vol.mstats.el_ht, h); 93 | if (!el) 94 | return; 95 | htable_rm(shfs_vol.mstats.el_ht, el); 96 | } 97 | 98 | /* 99 | * Resetting statistics 100 | */ 101 | static inline void shfs_reset_mstats(void) { 102 | htable_clear(shfs_vol.mstats.el_ht); 103 | shfs_vol.mstats.i = 0; 104 | shfs_vol.mstats.e = 0; 105 | } 106 | 107 | static inline void shfs_reset_hstats(void) { 108 | struct htable_el *el; 109 | struct shfs_el_stats *el_stats; 110 | 111 | foreach_htable_el(shfs_vol.bt, el) { 112 | el_stats = shfs_stats_from_bentry((struct shfs_bentry *) el->private); 113 | memset(el_stats, 0, sizeof(*el_stats)); 114 | } 115 | } 116 | 117 | #define shfs_reset_stats() \ 118 | do { \ 119 | shfs_reset_hstats(); \ 120 | shfs_reset_mstats(); \ 121 | } while (0) 122 | 123 | /* 124 | * Dumps statistics of element entries 125 | */ 126 | typedef int (*shfs_dump_el_stats_t)(void *argp, hash512_t h, int loaded, struct shfs_el_stats *stats); 127 | 128 | int shfs_dump_mstats(shfs_dump_el_stats_t dump_el, void *dump_el_argp); 129 | int shfs_dump_hstats(shfs_dump_el_stats_t dump_el, void *dump_el_argp); 130 | 131 | static inline int shfs_dump_stats(shfs_dump_el_stats_t dump_el, void *dump_el_argp) 132 | { 133 | int ret; 134 | ret = shfs_dump_hstats(dump_el, dump_el_argp); 135 | if (unlikely(ret < 0)) 136 | return ret; 137 | ret = shfs_dump_mstats(dump_el, dump_el_argp); 138 | if (unlikely(ret < 0)) 139 | return ret; 140 | return 0; 141 | } 142 | 143 | /* 144 | * Tools to display/export stats via uSh/ctldir 145 | */ 146 | int init_shfs_stats_export(blkdev_id_t bd_id); 147 | #ifdef HAVE_CTLDIR 148 | int register_shfs_stats_tools(struct ctldir *cd); 149 | #else 150 | int register_shfs_stats_tools(void); 151 | #endif 152 | void exit_shfs_stats_export(void); 153 | 154 | #endif /* _SHFS_STATS_H_ */ 155 | -------------------------------------------------------------------------------- /minios/shfs/shfs_stats_data.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Statistics extensions for SHFS 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _SHFS_STATS_DATA_H_ 37 | #define _SHFS_STATS_DATA_H_ 38 | 39 | #include "htable.h" 40 | 41 | #ifdef SHFS_STATS_HTTP 42 | #ifdef SHFS_STATS_HTTP_DPC 43 | #ifndef SHFS_STATS_HTTP_DPCR 44 | #define SHFS_STATS_HTTP_DPCR 3 /* enabler download progress counters 45 | per default with 0%, 50%, 100% */ 46 | #else 47 | #if SHFS_STATS_HTTP_DPCR < 2 48 | #warn "DPCR value has to be >= 2, disabling download progress counters" 49 | #undef SHFS_STATS_HTTP_DPC /* disable download progress counters */ 50 | #endif 51 | #endif 52 | #endif 53 | 54 | #ifdef SHFS_STATS_HTTP_DPC 55 | /* threshold calculation */ 56 | #define SHFS_STATS_HTTP_DPC_THRESHOLD(r, x) \ 57 | (((x) * (r)) / ((SHFS_STATS_HTTP_DPCR) - 1)) 58 | #define SHFS_STATS_HTTP_DPC_THRESHOLD_PERCENTAGE(x) \ 59 | SHFS_STATS_HTTP_DPC_THRESHOLD(100, (x)) 60 | #endif 61 | #endif 62 | 63 | struct shfs_mstats { 64 | uint32_t i; /* invalid requests */ 65 | uint32_t e; /* errors */ 66 | struct htable *el_ht; /* hash table of elements that are not in cache */ 67 | }; 68 | 69 | struct shfs_el_stats { 70 | uint32_t laccess; /* last access timestamp */ 71 | uint32_t h; /* element hit */ 72 | uint32_t m; /* element miss */ 73 | #ifdef SHFS_STATS_HTTP 74 | uint32_t c; /* successfully completed file transfers (even partial) */ 75 | 76 | /* download progress counters */ 77 | #ifdef SHFS_STATS_HTTP_DPC 78 | uint32_t p[SHFS_STATS_HTTP_DPCR]; 79 | #endif 80 | #endif 81 | }; 82 | 83 | int shfs_init_mstats(uint32_t nb_bkts, uint32_t ent_per_bkt, uint8_t hlen); 84 | void shfs_free_mstats(void); 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /minios/shfs/shfs_tools.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HashFS (SHFS) for Mini-OS 3 | * 4 | * Authors: Simon Kuenzer 5 | * 6 | * 7 | * Copyright (c) 2013-2017, NEC Europe Ltd., NEC Corporation All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. Neither the name of the copyright holder nor the names of its 19 | * contributors may be used to endorse or promote products derived from 20 | * this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | * POSSIBILITY OF SUCH DAMAGE. 33 | * 34 | */ 35 | 36 | #ifndef _SHFS_TOOLS_H_ 37 | #define _SHFS_TOOLS_H_ 38 | 39 | #include "shfs_defs.h" 40 | #ifdef HAVE_CTLDIR 41 | #include 42 | #endif 43 | 44 | /** 45 | * Registers shfs tools to micro shell + ctldir (if *cd is not NULL) 46 | */ 47 | #ifdef HAVE_CTLDIR 48 | int register_shfs_tools(struct ctldir *cd); 49 | #else 50 | int register_shfs_tools(void); 51 | #endif 52 | 53 | /** 54 | * Prints an uuid/hash number to a buffer 55 | * Note: The target buffer for the UUID has to be at least 37 bytes long 56 | * Note: The target buffer for the hash has to be at least ((2 * hlen) + 1) bytes long 57 | */ 58 | #ifdef __MINIOS__ 59 | void uuid_unparse(const uuid_t uu, char *out); 60 | #endif 61 | void hash_unparse(const hash512_t h, uint8_t hlen, char *out); 62 | 63 | size_t strftimestamp_s(char *s, size_t slen, const char *fmt, uint64_t ts_sec); 64 | 65 | size_t strshfshost(char *s, size_t slen, struct shfs_host *h); 66 | 67 | #ifdef HAVE_LWIP 68 | #include 69 | #include 70 | #include 71 | 72 | #if LWIP_DNS 73 | static inline int shfshost2ipaddr(const struct shfs_host *h, ip_addr_t *out, dns_found_callback dns_cb, void *dns_cb_argp) 74 | #else 75 | static inline int shfshost2ipaddr(const struct shfs_host *h, ip_addr_t *out) 76 | #endif 77 | { 78 | err_t err; 79 | char hname[sizeof(h->name) + 1]; 80 | 81 | switch(h->type) { 82 | #if !(defined LWIP_IPV4) || LWIP_IPV4 83 | case SHFS_HOST_TYPE_IPV4: 84 | IP4_ADDR(out, h->addr[0], h->addr[1], h->addr[2], h->addr[3]); 85 | return 0; 86 | #endif 87 | #if LWIP_IPV6 88 | case SHFS_HOST_TYPE_IPV6: 89 | IP6_ADDR(out, h->addr[0], h->addr[1], h->addr[2], h->addr[3], 90 | h->addr[4], h->addr[5], h->addr[6], h->addr[7]); 91 | return 0; 92 | #endif 93 | #if LWIP_DNS 94 | case SHFS_HOST_TYPE_NAME: 95 | /* FIXME: remove this workaround for null-terminating hostname in SHFS field */ 96 | strncpy(hname, h->name, sizeof(h->name)); 97 | hname[sizeof(hname) - 1] = '\0'; 98 | err = dns_gethostbyname(h->name, out, dns_cb, dns_cb_argp); 99 | if (err == ERR_OK) 100 | return 0; /* hostname found in local table */ 101 | if (err == ERR_INPROGRESS) 102 | return 1; /* query sent, callback will be called on answer */ 103 | return -EINVAL; /* general error */ 104 | #endif 105 | default: 106 | return -ENOTSUP; 107 | } 108 | } 109 | #endif /* HAVE_LWIP */ 110 | 111 | #endif /* _SHFS_TOOLS_H_ */ 112 | -------------------------------------------------------------------------------- /minios/shfs/sys.h: -------------------------------------------------------------------------------- 1 | #ifndef _SYS_H_ 2 | #define _SYS_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define target_malloc(align, size) \ 11 | ((void *) _xmalloc((size), (align))) 12 | #define target_free(ptr) \ 13 | xfree(ptr) 14 | 15 | /* semaphores */ 16 | #include 17 | typedef struct semaphore sem_t; 18 | 19 | /* shutdown */ 20 | #include 21 | 22 | #define TARGET_SHTDN_POWEROFF \ 23 | SHUTDOWN_poweroff 24 | #define TARGET_SHTDN_REBOOT \ 25 | SHUTDOWN_reboot 26 | #define TARGET_SHTDN_SUSPEND \ 27 | SHUTDOWN_suspend 28 | 29 | #define target_suspend() \ 30 | kernel_suspend() 31 | 32 | #define target_halt() \ 33 | kernel_shutdown(SHUTDOWN_poweroff) 34 | 35 | #define target_reboot() \ 36 | kernel_shutdown(SHUTDOWN_reboot) 37 | 38 | #define target_crash() \ 39 | kernel_shutdown(SHUTDOWN_crash) 40 | 41 | #define target_init() \ 42 | do {} while(0) 43 | #define target_exit() \ 44 | do {} while(0) 45 | 46 | /* 47 | #ifdef CONFIG_ARM 48 | #define target_now_ns() ({ \ 49 | uint64_t r; \ 50 | struct timeval now; \ 51 | gettimeofday(&now, NULL); \ 52 | r = now.tv_usec * 1000 + now.tv_sec * 1000000000l; \ 53 | r; }) 54 | #else 55 | */ 56 | #define target_now_ns() (NOW()) 57 | /* 58 | #endif 59 | */ 60 | 61 | #endif /* _SYS_H_ */ 62 | -------------------------------------------------------------------------------- /minios/tools/libimport.py: -------------------------------------------------------------------------------- 1 | ################################################################## 2 | # 3 | # Copies the contents of the MicroPython lib repo 4 | # (https://github.com/micropython/micropython-lib) 5 | # to MINIPYTHON_TARGET_DIR so that the libs are ready 6 | # to use by minipython. 7 | # 8 | ################################################################## 9 | import os 10 | import subprocess 11 | 12 | MICROPY_LIB_DIR = "/root/workspace/micropython-lib/" 13 | MINIPYTHON_TARGET_DIR = "/mnt/fat/lib/" 14 | IGNORE_DIRS = [".git", "__future__"] 15 | 16 | # For reporting at the end 17 | ADDED_LIBS = [] 18 | IGNORED_LIBS = [] 19 | 20 | def process_lib(libname, path): 21 | t_dir = MINIPYTHON_TARGET_DIR + libname 22 | 23 | print "\nprocessing library: " + libname 24 | print "====================================" 25 | 26 | # Only skip if python file of same name as lib exists and it's empty 27 | # (some libs don't have such a base file, we don't skip those.). 28 | basefile = path + "/" + libname + ".py" 29 | if os.path.isfile(basefile) and os.stat(basefile).st_size == 0: 30 | IGNORED_LIBS.append(libname) 31 | print "main library file is empty, skipping..." 32 | return 33 | 34 | # Process library directory 35 | for f in os.listdir(path): 36 | print "processing file: " + f 37 | 38 | # File has same name as library name, i.e., socket.py 39 | # for socket library. Make a new subdirectory in 40 | # MINIPYTHON_TARGET_DIR and copy the file over 41 | if f == libname + ".py": 42 | full_f = path + "/" + f 43 | cmd = "cp " + full_f + " " + MINIPYTHON_TARGET_DIR 44 | run_cmd(cmd) 45 | add_lib(libname) 46 | # We've found a subdirectory in the library, simply copy it 47 | # over (recursively) 48 | elif os.path.isdir(path + "/" + f): 49 | t_subdir = t_dir + "/" + f 50 | cmd = "mkdir -p " + t_dir 51 | run_cmd(cmd) 52 | cmd = "cp -R " + path + "/ " + MINIPYTHON_TARGET_DIR 53 | run_cmd(cmd) 54 | add_lib(libname) 55 | 56 | def add_lib(lib): 57 | if lib not in ADDED_LIBS: 58 | ADDED_LIBS.append(lib) 59 | 60 | def run_cmd(cmd): 61 | print cmd 62 | subprocess.call(cmd, shell=True) 63 | 64 | def is_ignore_dir(path): 65 | for d in IGNORE_DIRS: 66 | if path.find(d) != -1: 67 | return True 68 | return False 69 | 70 | def main(): 71 | run_cmd("mkdir -p " + MINIPYTHON_TARGET_DIR) 72 | for libname in os.listdir(MICROPY_LIB_DIR): 73 | path = MICROPY_LIB_DIR + libname 74 | if os.path.isdir(path) and not is_ignore_dir(path): 75 | process_lib(libname, path) 76 | 77 | print "\n\nAdded libs:\n=====================\n" + str(ADDED_LIBS) 78 | print "\n\nIgnored libs:\n=====================\n" + str(IGNORED_LIBS) 79 | 80 | main() 81 | -------------------------------------------------------------------------------- /minios/unix_mphal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Micro Python project, http://micropython.org/ 3 | * 4 | * The MIT License (MIT) 5 | * 6 | * Copyright (c) 2015 Damien P. George 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "py/mpstate.h" 33 | #include "py/mphal.h" 34 | #include "py/runtime.h" 35 | #include "extmod/misc.h" 36 | 37 | #ifndef _WIN32 38 | #include 39 | 40 | STATIC void sighandler(int signum) { 41 | if (signum == SIGINT) { 42 | #if MICROPY_ASYNC_KBD_INTR 43 | mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj)); 44 | sigset_t mask; 45 | sigemptyset(&mask); 46 | // On entry to handler, its signal is blocked, and unblocked on 47 | // normal exit. As we instead perform longjmp, unblock it manually. 48 | sigprocmask(SIG_SETMASK, &mask, NULL); 49 | nlr_raise(MP_STATE_VM(keyboard_interrupt_obj)); 50 | #else 51 | if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) { 52 | // this is the second time we are called, so die straight away 53 | exit(1); 54 | } 55 | mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj)); 56 | MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj); 57 | #endif 58 | } 59 | } 60 | #endif 61 | 62 | void mp_hal_set_interrupt_char(char c) { 63 | // configure terminal settings to (not) let ctrl-C through 64 | if (c == CHAR_CTRL_C) { 65 | #ifndef _WIN32 66 | // enable signal handler 67 | struct sigaction sa; 68 | sa.sa_flags = 0; 69 | sa.sa_handler = sighandler; 70 | sigemptyset(&sa.sa_mask); 71 | sigaction(SIGINT, &sa, NULL); 72 | #endif 73 | } else { 74 | #ifndef _WIN32 75 | // disable signal handler 76 | struct sigaction sa; 77 | sa.sa_flags = 0; 78 | sa.sa_handler = SIG_DFL; 79 | sigemptyset(&sa.sa_mask); 80 | sigaction(SIGINT, &sa, NULL); 81 | #endif 82 | } 83 | } 84 | 85 | #if MICROPY_USE_READLINE == 1 86 | 87 | #include 88 | 89 | static struct termios orig_termios; 90 | 91 | void mp_hal_stdio_mode_raw(void) { 92 | // save and set terminal settings 93 | tcgetattr(0, &orig_termios); 94 | static struct termios termios; 95 | termios = orig_termios; 96 | termios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); 97 | termios.c_cflag = (termios.c_cflag & ~(CSIZE | PARENB)) | CS8; 98 | termios.c_lflag = 0; 99 | termios.c_cc[VMIN] = 1; 100 | termios.c_cc[VTIME] = 0; 101 | tcsetattr(0, TCSAFLUSH, &termios); 102 | } 103 | 104 | void mp_hal_stdio_mode_orig(void) { 105 | // restore terminal settings 106 | tcsetattr(0, TCSAFLUSH, &orig_termios); 107 | } 108 | 109 | #endif 110 | 111 | #if MICROPY_PY_OS_DUPTERM 112 | static int call_dupterm_read(void) { 113 | nlr_buf_t nlr; 114 | if (nlr_push(&nlr) == 0) { 115 | mp_obj_t read_m[3]; 116 | mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m); 117 | read_m[2] = MP_OBJ_NEW_SMALL_INT(1); 118 | mp_obj_t res = mp_call_method_n_kw(1, 0, read_m); 119 | if (res == mp_const_none) { 120 | return -2; 121 | } 122 | mp_buffer_info_t bufinfo; 123 | mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ); 124 | if (bufinfo.len == 0) { 125 | mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n"); 126 | MP_STATE_PORT(term_obj) = NULL; 127 | return -1; 128 | } 129 | nlr_pop(); 130 | return *(byte*)bufinfo.buf; 131 | } else { 132 | // Temporarily disable dupterm to avoid infinite recursion 133 | mp_obj_t save_term = MP_STATE_PORT(term_obj); 134 | MP_STATE_PORT(term_obj) = NULL; 135 | mp_printf(&mp_plat_print, "dupterm: "); 136 | mp_obj_print_exception(&mp_plat_print, nlr.ret_val); 137 | MP_STATE_PORT(term_obj) = save_term; 138 | } 139 | 140 | return -1; 141 | } 142 | #endif 143 | 144 | int mp_hal_stdin_rx_chr(void) { 145 | unsigned char c; 146 | #if MICROPY_PY_OS_DUPTERM 147 | if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) { 148 | int c; 149 | do { 150 | c = call_dupterm_read(); 151 | } while (c == -2); 152 | if (c == -1) { 153 | goto main_term; 154 | } 155 | if (c == '\n') { 156 | c = '\r'; 157 | } 158 | return c; 159 | } else { 160 | main_term:; 161 | #endif 162 | int ret = read(0, &c, 1); 163 | if (ret == 0) { 164 | c = 4; // EOF, ctrl-D 165 | } else if (c == '\n') { 166 | c = '\r'; 167 | } 168 | return c; 169 | #if MICROPY_PY_OS_DUPTERM 170 | } 171 | #endif 172 | } 173 | 174 | void mp_hal_stdout_tx_strn(const char *str, size_t len) { 175 | int ret = write(1, str, len); 176 | mp_uos_dupterm_tx_strn(str, len); 177 | (void)ret; // to suppress compiler warning 178 | } 179 | 180 | // cooked is same as uncooked because the terminal does some postprocessing 181 | void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { 182 | mp_hal_stdout_tx_strn(str, len); 183 | } 184 | 185 | void mp_hal_stdout_tx_str(const char *str) { 186 | mp_hal_stdout_tx_strn(str, strlen(str)); 187 | } 188 | 189 | mp_uint_t mp_hal_ticks_ms(void) { 190 | struct timeval tv; 191 | gettimeofday(&tv, NULL); 192 | return tv.tv_sec * 1000 + tv.tv_usec / 1000; 193 | } 194 | -------------------------------------------------------------------------------- /py: -------------------------------------------------------------------------------- 1 | micropython/py -------------------------------------------------------------------------------- /stmhal: -------------------------------------------------------------------------------- 1 | micropython/stmhal -------------------------------------------------------------------------------- /tools: -------------------------------------------------------------------------------- 1 | micropython/tools --------------------------------------------------------------------------------