diff options
Diffstat (limited to 'extmod')
-rw-r--r-- | extmod/fsusermount.c | 2 | ||||
-rw-r--r-- | extmod/fsusermount.h | 1 | ||||
-rw-r--r-- | extmod/machine_spi.c | 85 | ||||
-rw-r--r-- | extmod/machine_spi.h | 42 | ||||
-rw-r--r-- | extmod/modbtree.c | 1 | ||||
-rw-r--r-- | extmod/modframebuf.c | 33 | ||||
-rw-r--r-- | extmod/modubinascii.c | 15 | ||||
-rw-r--r-- | extmod/modubinascii.h | 2 | ||||
-rw-r--r-- | extmod/moduzlib.c | 153 | ||||
-rw-r--r-- | extmod/modwebrepl.c | 7 | ||||
-rw-r--r-- | extmod/uzlib/adler32.c | 6 | ||||
-rw-r--r-- | extmod/uzlib/crc32.c | 63 | ||||
-rw-r--r-- | extmod/uzlib/tinf.h | 78 | ||||
-rw-r--r-- | extmod/uzlib/tinflate.c | 378 | ||||
-rw-r--r-- | extmod/uzlib/tinfzlib.c | 53 | ||||
-rw-r--r-- | extmod/vfs_fat.c | 8 |
16 files changed, 642 insertions, 285 deletions
diff --git a/extmod/fsusermount.c b/extmod/fsusermount.c index 9ddc98f3dd..cbc1e36220 100644 --- a/extmod/fsusermount.c +++ b/extmod/fsusermount.c @@ -162,7 +162,7 @@ STATIC mp_obj_t fatfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k } MP_DEFINE_CONST_FUN_OBJ_KW(fsuser_mount_obj, 2, fatfs_mount); -STATIC mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in) { +mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in) { size_t i = 0; if (MP_OBJ_IS_STR(bdev_or_path_in)) { mp_uint_t mnt_len; diff --git a/extmod/fsusermount.h b/extmod/fsusermount.h index a25434b781..e1f26f2ce8 100644 --- a/extmod/fsusermount.h +++ b/extmod/fsusermount.h @@ -55,6 +55,7 @@ typedef struct _fs_user_mount_t { } fs_user_mount_t; fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, bool mkfs); +mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in); MP_DECLARE_CONST_FUN_OBJ(fsuser_mount_obj); MP_DECLARE_CONST_FUN_OBJ(fsuser_umount_obj); diff --git a/extmod/machine_spi.c b/extmod/machine_spi.c new file mode 100644 index 0000000000..6b6202a221 --- /dev/null +++ b/extmod/machine_spi.c @@ -0,0 +1,85 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdio.h> + +#include "py/runtime.h" +#include "extmod/machine_spi.h" + +#if MICROPY_PY_MACHINE_SPI + +STATIC void mp_machine_spi_transfer(mp_obj_t self, size_t slen, const uint8_t *src, size_t dlen, uint8_t *dest) { + mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self); + mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol; + spi_p->transfer(s, slen, src, dlen, dest); +} + +STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) { + uint8_t write_byte = 0; + if (n_args == 3) { + write_byte = mp_obj_get_int(args[2]); + } + vstr_t vstr; + vstr_init_len(&vstr, mp_obj_get_int(args[1])); + mp_machine_spi_transfer(args[0], 1, &write_byte, vstr.len, (uint8_t*)vstr.buf); + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read); + +STATIC mp_obj_t mp_machine_spi_readinto(size_t n_args, const mp_obj_t *args) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); + uint8_t write_byte = 0; + if (n_args == 3) { + write_byte = mp_obj_get_int(args[2]); + } + mp_machine_spi_transfer(args[0], 1, &write_byte, bufinfo.len, (uint8_t*)bufinfo.buf); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj, 2, 3, mp_machine_spi_readinto); + +STATIC mp_obj_t mp_machine_spi_write(mp_obj_t self, mp_obj_t wr_buf) { + mp_buffer_info_t src; + mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); + mp_machine_spi_transfer(self, src.len, (const uint8_t*)src.buf, 0, NULL); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj, mp_machine_spi_write); + +STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self, mp_obj_t wr_buf, mp_obj_t rd_buf) { + mp_buffer_info_t src; + mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); + mp_buffer_info_t dest; + mp_get_buffer_raise(rd_buf, &dest, MP_BUFFER_WRITE); + if (src.len != dest.len) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "buffers must be the same length")); + } + mp_machine_spi_transfer(self, src.len, (const uint8_t*)src.buf, dest.len, (uint8_t*)dest.buf); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj, mp_machine_spi_write_readinto); + +#endif // MICROPY_PY_MACHINE_SPI diff --git a/extmod/machine_spi.h b/extmod/machine_spi.h new file mode 100644 index 0000000000..26d716fc11 --- /dev/null +++ b/extmod/machine_spi.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H +#define MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H + +#include "py/obj.h" + +// SPI protocol +typedef struct _mp_machine_spi_p_t { + void (*transfer)(mp_obj_base_t *obj, size_t slen, const uint8_t *src, size_t dlen, uint8_t *dest); +} mp_machine_spi_p_t; + +MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_read_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_readinto_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_write_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_write_readinto_obj); + +#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H diff --git a/extmod/modbtree.c b/extmod/modbtree.c index f21e7e4421..ea2ea582c8 100644 --- a/extmod/modbtree.c +++ b/extmod/modbtree.c @@ -133,6 +133,7 @@ STATIC mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) { } int res = __bt_seq(self->db, &key, &val, flags); + CHECK_ERROR(res); if (res == RET_SPECIAL) { return mp_const_none; } diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index d0ef238075..3c884c6898 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -33,7 +33,7 @@ #if MICROPY_PY_FRAMEBUF -#include "font_petme128_8x8.h" +#include "stmhal/font_petme128_8x8.h" // 1-bit frame buffer, each byte is a column of 8 pixels typedef struct _mp_obj_framebuf1_t { @@ -68,7 +68,8 @@ STATIC mp_obj_t framebuf1_fill(mp_obj_t self_in, mp_obj_t col_in) { if (col) { col = 0xff; } - for (int y = 0; y < self->height / 8; ++y) { + int end = (self->height + 7) >> 3; + for (int y = 0; y < end; ++y) { memset(self->buf + y * self->stride, col, self->width); } return mp_const_none; @@ -83,7 +84,7 @@ STATIC mp_obj_t framebuf1_pixel(size_t n_args, const mp_obj_t *args) { int index = (y / 8) * self->stride + x; if (n_args == 3) { // get - return MP_OBJ_NEW_SMALL_INT(self->buf[index] >> (y & 7)); + return MP_OBJ_NEW_SMALL_INT((self->buf[index] >> (y & 7)) & 1); } else { // set if (mp_obj_get_int(args[3])) { @@ -101,8 +102,9 @@ STATIC mp_obj_t framebuf1_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t y mp_obj_framebuf1_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t xstep = mp_obj_get_int(xstep_in); mp_int_t ystep = mp_obj_get_int(ystep_in); - if (xstep == 0 && ystep > 0) { - for (int y = self->height / 8; y > 0;) { + int end = (self->height + 7) >> 3; + if (ystep > 0) { + for (int y = end; y > 0;) { --y; for (int x = 0; x < self->width; ++x) { int prev = 0; @@ -112,18 +114,31 @@ STATIC mp_obj_t framebuf1_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t y self->buf[y * self->stride + x] = (self->buf[y * self->stride + x] << ystep) | prev; } } - } else if (xstep == 0 && ystep < 0) { - for (int y = 0; y < self->height / 8; ++y) { + } else if (ystep < 0) { + for (int y = 0; y < end; ++y) { for (int x = 0; x < self->width; ++x) { int prev = 0; - if (y + 1 < self->height / 8) { + if (y + 1 < end) { prev = self->buf[(y + 1) * self->stride + x] << (8 + ystep); } self->buf[y * self->stride + x] = (self->buf[y * self->stride + x] >> -ystep) | prev; } } } - // TODO xstep!=0 + if (xstep < 0) { + for (int y = 0; y < end; ++y) { + for (int x = 0; x < self->width + xstep; ++x) { + self->buf[y * self->stride + x] = self->buf[y * self->stride + x - xstep]; + } + } + } else if (xstep > 0) { + for (int y = 0; y < end; ++y) { + for (int x = self->width - 1; x >= xstep; --x) { + self->buf[y * self->stride + x] = self->buf[y * self->stride + x - xstep]; + } + } + } + // TODO: Should we clear the margin created by scrolling? return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf1_scroll_obj, framebuf1_scroll); diff --git a/extmod/modubinascii.c b/extmod/modubinascii.c index 3cceb991f1..562c754b52 100644 --- a/extmod/modubinascii.c +++ b/extmod/modubinascii.c @@ -33,6 +33,7 @@ #include "py/binary.h" #include "extmod/modubinascii.h" +#include "uzlib/tinf.h" mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) { // Second argument is for an extension to allow a separator to be used @@ -203,6 +204,17 @@ mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) { } MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj, mod_binascii_b2a_base64); +#if MICROPY_PY_UBINASCII_CRC32 +mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); + uint32_t crc = (n_args > 1) ? mp_obj_get_int(args[1]) : 0; + crc = uzlib_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff); + return MP_OBJ_NEW_SMALL_INT(crc ^ 0xffffffff); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_crc32); +#endif + #if MICROPY_PY_UBINASCII STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = { @@ -211,6 +223,9 @@ STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&mod_binascii_unhexlify_obj) }, { MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) }, { MP_ROM_QSTR(MP_QSTR_b2a_base64), MP_ROM_PTR(&mod_binascii_b2a_base64_obj) }, + #if MICROPY_PY_UBINASCII_CRC32 + { MP_ROM_QSTR(MP_QSTR_crc32), MP_ROM_PTR(&mod_binascii_crc32_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table); diff --git a/extmod/modubinascii.h b/extmod/modubinascii.h index 0f9b82c1cb..71dd8a6936 100644 --- a/extmod/modubinascii.h +++ b/extmod/modubinascii.h @@ -31,10 +31,12 @@ extern mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args); extern mp_obj_t mod_binascii_unhexlify(mp_obj_t data); extern mp_obj_t mod_binascii_a2b_base64(mp_obj_t data); extern mp_obj_t mod_binascii_b2a_base64(mp_obj_t data); +extern mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args); MP_DECLARE_CONST_FUN_OBJ(mod_binascii_hexlify_obj); MP_DECLARE_CONST_FUN_OBJ(mod_binascii_unhexlify_obj); MP_DECLARE_CONST_FUN_OBJ(mod_binascii_a2b_base64_obj); MP_DECLARE_CONST_FUN_OBJ(mod_binascii_b2a_base64_obj); +MP_DECLARE_CONST_FUN_OBJ(mod_binascii_crc32_obj); #endif /* MICROPY_EXTMOD_MODUBINASCII */ diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c index 3d945abba5..65cbc5eb01 100644 --- a/extmod/moduzlib.c +++ b/extmod/moduzlib.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2014 Paul Sokolovsky + * Copyright (c) 2014-2016 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,9 +25,12 @@ */ #include <stdio.h> +#include <string.h> #include "py/nlr.h" #include "py/runtime.h" +#include "py/stream.h" +#include "py/mperrno.h" #if MICROPY_PY_UZLIB @@ -39,16 +42,99 @@ #define DEBUG_printf(...) (void)0 #endif -STATIC int mod_uzlib_grow_buf(TINF_DATA *d, unsigned alloc_req) { - if (alloc_req < 256) { - alloc_req = 256; +typedef struct _mp_obj_decompio_t { + mp_obj_base_t base; + mp_obj_t src_stream; + TINF_DATA decomp; + bool eof; +} mp_obj_decompio_t; + +STATIC unsigned char read_src_stream(TINF_DATA *data) { + byte *p = (void*)data; + p -= offsetof(mp_obj_decompio_t, decomp); + mp_obj_decompio_t *self = (mp_obj_decompio_t*)p; + + const mp_stream_p_t *stream = mp_get_stream_raise(self->src_stream, MP_STREAM_OP_READ); + int err; + byte c; + mp_uint_t out_sz = stream->read(self->src_stream, &c, 1, &err); + if (out_sz == MP_STREAM_ERROR) { + nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(err))); } - DEBUG_printf("uzlib: Resizing buffer to " UINT_FMT " bytes\n", d->destSize + alloc_req); - d->destStart = m_renew(byte, d->destStart, d->destSize, d->destSize + alloc_req); - d->destSize += alloc_req; - return 0; + if (out_sz == 0) { + nlr_raise(mp_obj_new_exception(&mp_type_EOFError)); + } + return c; +} + +STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, 2, false); + mp_obj_decompio_t *o = m_new_obj(mp_obj_decompio_t); + o->base.type = type; + memset(&o->decomp, 0, sizeof(o->decomp)); + o->decomp.readSource = read_src_stream; + o->src_stream = args[0]; + o->eof = false; + + mp_int_t dict_opt = 0; + int dict_sz; + if (n_args > 1) { + dict_opt = mp_obj_get_int(args[1]); + } + if (dict_opt >= 0) { + dict_opt = uzlib_zlib_parse_header(&o->decomp); + if (dict_opt < 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "zlib header")); + } + dict_sz = 1 << dict_opt; + } else { + dict_sz = 1 << -dict_opt; + } + + uzlib_uncompress_init(&o->decomp, m_new(byte, dict_sz), dict_sz); + return MP_OBJ_FROM_PTR(o); } +STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { + mp_obj_decompio_t *o = MP_OBJ_TO_PTR(o_in); + if (o->eof) { + return 0; + } + + o->decomp.dest = buf; + o->decomp.destSize = size; + int st = uzlib_uncompress_chksum(&o->decomp); + if (st == TINF_DONE) { + o->eof = true; + } + if (st < 0) { + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; + } + return o->decomp.dest - (byte*)buf; +} + +STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table); + +STATIC const mp_stream_p_t decompio_stream_p = { + .read = decompio_read, +}; + +STATIC const mp_obj_type_t decompio_type = { + { &mp_type_type }, + .name = MP_QSTR_DecompIO, + .make_new = decompio_make_new, + .protocol = &decompio_stream_p, + .locals_dict = (void*)&decompio_locals_dict, +}; + STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) { (void)n_args; mp_obj_t data = args[0]; @@ -56,36 +142,62 @@ STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) { mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); TINF_DATA *decomp = m_new_obj(TINF_DATA); + memset(decomp, 0, sizeof(*decomp)); DEBUG_printf("sizeof(TINF_DATA)=" UINT_FMT "\n", sizeof(*decomp)); + uzlib_uncompress_init(decomp, NULL, 0); + mp_uint_t dest_buf_size = (bufinfo.len + 15) & ~15; + byte *dest_buf = m_new(byte, dest_buf_size); - decomp->destSize = (bufinfo.len + 15) & ~15; - decomp->destStart = m_new(byte, decomp->destSize); + decomp->dest = dest_buf; + decomp->destSize = dest_buf_size; DEBUG_printf("uzlib: Initial out buffer: " UINT_FMT " bytes\n", decomp->destSize); - decomp->destGrow = mod_uzlib_grow_buf; decomp->source = bufinfo.buf; int st; + bool is_zlib = true; + if (n_args > 1 && MP_OBJ_SMALL_INT_VALUE(args[1]) < 0) { - st = tinf_uncompress_dyn(decomp); - } else { - st = tinf_zlib_uncompress_dyn(decomp, bufinfo.len); + is_zlib = false; } - if (st != 0) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st))); + + if (is_zlib) { + st = uzlib_zlib_parse_header(decomp); + if (st < 0) { + goto error; + } } - mp_uint_t final_sz = decomp->dest - decomp->destStart; - DEBUG_printf("uzlib: Resizing from " UINT_FMT " to final size: " UINT_FMT " bytes\n", decomp->destSize, final_sz); - decomp->destStart = (byte*)m_renew(byte, decomp->destStart, decomp->destSize, final_sz); - mp_obj_t res = mp_obj_new_bytearray_by_ref(final_sz, decomp->destStart); + while (1) { + st = uzlib_uncompress_chksum(decomp); + if (st < 0) { + goto error; + } + if (st == TINF_DONE) { + break; + } + size_t offset = decomp->dest - dest_buf; + dest_buf = m_renew(byte, dest_buf, dest_buf_size, dest_buf_size + 256); + dest_buf_size += 256; + decomp->dest = dest_buf + offset; + decomp->destSize = 256; + } + + mp_uint_t final_sz = decomp->dest - dest_buf; + DEBUG_printf("uzlib: Resizing from " UINT_FMT " to final size: " UINT_FMT " bytes\n", dest_buf_size, final_sz); + dest_buf = (byte*)m_renew(byte, dest_buf, dest_buf_size, final_sz); + mp_obj_t res = mp_obj_new_bytearray_by_ref(final_sz, dest_buf); m_del_obj(TINF_DATA, decomp); return res; + +error: + nlr_raise(mp_obj_new_exception_arg1(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st))); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_uzlib_decompress_obj, 1, 3, mod_uzlib_decompress); STATIC const mp_rom_map_elem_t mp_module_uzlib_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uzlib) }, { MP_ROM_QSTR(MP_QSTR_decompress), MP_ROM_PTR(&mod_uzlib_decompress_obj) }, + { MP_ROM_QSTR(MP_QSTR_DecompIO), MP_ROM_PTR(&decompio_type) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_uzlib_globals, mp_module_uzlib_globals_table); @@ -102,5 +214,6 @@ const mp_obj_module_t mp_module_uzlib = { #include "uzlib/tinflate.c" #include "uzlib/tinfzlib.c" #include "uzlib/adler32.c" +#include "uzlib/crc32.c" #endif // MICROPY_PY_UZLIB diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index 4e3780fa4d..858d2c1c0b 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -310,9 +310,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_close_obj, webrepl_close); STATIC mp_obj_t webrepl_set_password(mp_obj_t passwd_in) { mp_uint_t len; const char *passwd = mp_obj_str_get_data(passwd_in, &len); - len = MIN(len, sizeof(webrepl_passwd) - 1); - memcpy(webrepl_passwd, passwd, len); - webrepl_passwd[len] = 0; + if (len > sizeof(webrepl_passwd) - 1) { + mp_raise_ValueError(""); + } + strcpy(webrepl_passwd, passwd); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_set_password_obj, webrepl_set_password); diff --git a/extmod/uzlib/adler32.c b/extmod/uzlib/adler32.c index f99b2d7f40..1f1759493b 100644 --- a/extmod/uzlib/adler32.c +++ b/extmod/uzlib/adler32.c @@ -41,12 +41,12 @@ #define A32_BASE 65521 #define A32_NMAX 5552 -unsigned int tinf_adler32(const void *data, unsigned int length) +uint32_t uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum /* 1 */) { const unsigned char *buf = (const unsigned char *)data; - unsigned int s1 = 1; - unsigned int s2 = 0; + unsigned int s1 = prev_sum & 0xffff; + unsigned int s2 = prev_sum >> 16; while (length > 0) { diff --git a/extmod/uzlib/crc32.c b/extmod/uzlib/crc32.c new file mode 100644 index 0000000000..e24c643b6a --- /dev/null +++ b/extmod/uzlib/crc32.c @@ -0,0 +1,63 @@ +/* + * CRC32 checksum + * + * Copyright (c) 1998-2003 by Joergen Ibsen / Jibz + * All Rights Reserved + * + * http://www.ibsensoftware.com/ + * + * This software is provided 'as-is', without any express + * or implied warranty. In no event will the authors be + * held liable for any damages arising from the use of + * this software. + * + * Permission is granted to anyone to use this software + * for any purpose, including commercial applications, + * and to alter it and redistribute it freely, subject to + * the following restrictions: + * + * 1. The origin of this software must not be + * misrepresented; you must not claim that you + * wrote the original software. If you use this + * software in a product, an acknowledgment in + * the product documentation would be appreciated + * but is not required. + * + * 2. Altered source versions must be plainly marked + * as such, and must not be misrepresented as + * being the original software. + * + * 3. This notice may not be removed or altered from + * any source distribution. + */ + +/* + * CRC32 algorithm taken from the zlib source, which is + * Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler + */ + +#include "tinf.h" + +static const unsigned int tinf_crc32tab[16] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, + 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, + 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, + 0xbdbdf21c +}; + +/* crc is previous value for incremental computation, 0xffffffff initially */ +uint32_t uzlib_crc32(const void *data, unsigned int length, uint32_t crc) +{ + const unsigned char *buf = (const unsigned char *)data; + unsigned int i; + + for (i = 0; i < length; ++i) + { + crc ^= buf[i]; + crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4); + crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4); + } + + // return value suitable for passing in next time, for final value invert it + return crc/* ^ 0xffffffff*/; +} diff --git a/extmod/uzlib/tinf.h b/extmod/uzlib/tinf.h index e9401f2de5..3545bbd883 100644 --- a/extmod/uzlib/tinf.h +++ b/extmod/uzlib/tinf.h @@ -5,7 +5,7 @@ * All Rights Reserved * http://www.ibsensoftware.com/ * - * Copyright (c) 2014 by Paul Sokolovsky + * Copyright (c) 2014-2016 by Paul Sokolovsky */ #ifndef TINF_H_INCLUDED @@ -26,9 +26,17 @@ extern "C" { #endif +/* ok status, more data produced */ #define TINF_OK 0 +/* end of compressed stream reached */ +#define TINF_DONE 1 #define TINF_DATA_ERROR (-3) -#define TINF_DEST_OVERFLOW (-4) +#define TINF_CHKSUM_ERROR (-4) + +/* checksum types */ +#define TINF_CHKSUM_NONE 0 +#define TINF_CHKSUM_ADLER 1 +#define TINF_CHKSUM_CRC 2 /* data structures */ @@ -40,6 +48,10 @@ typedef struct { struct TINF_DATA; typedef struct TINF_DATA { const unsigned char *source; + /* If source above is NULL, this function will be used to read + next byte from source stream */ + unsigned char (*readSource)(struct TINF_DATA *data); + unsigned int tag; unsigned int bitcount; @@ -51,49 +63,51 @@ typedef struct TINF_DATA { unsigned char *dest; /* Remaining bytes in buffer */ unsigned int destRemaining; - /* Argument is the allocation size which didn't fit into buffer. Note that - exact mimumum size to grow buffer by is lastAlloc - destRemaining. But - growing by this exact size is ineficient, as the next allocation will - fail again. */ - int (*destGrow)(struct TINF_DATA *data, unsigned int lastAlloc); + + /* Accumulating checksum */ + unsigned int checksum; + char checksum_type; + + int btype; + int bfinal; + unsigned int curlen; + int lzOff; + unsigned char *dict_ring; + unsigned int dict_size; + unsigned int dict_idx; TINF_TREE ltree; /* dynamic length/symbol tree */ TINF_TREE dtree; /* dynamic distance tree */ } TINF_DATA; +#define TINF_PUT(d, c) \ + { \ + *d->dest++ = c; \ + if (d->dict_ring) { d->dict_ring[d->dict_idx++] = c; if (d->dict_idx == d->dict_size) d->dict_idx = 0; } \ + } -/* low-level API */ - -/* Step 1: Allocate TINF_DATA structure */ -/* Step 2: Set destStart, destSize, and destGrow fields */ -/* Step 3: Set source field */ -/* Step 4: Call tinf_uncompress_dyn() */ -/* Step 5: In response to destGrow callback, update destStart and destSize fields */ -/* Step 6: When tinf_uncompress_dyn() returns, buf.dest points to a byte past last uncompressed byte */ - -int TINFCC tinf_uncompress_dyn(TINF_DATA *d); -int TINFCC tinf_zlib_uncompress_dyn(TINF_DATA *d, unsigned int sourceLen); - -/* high-level API */ - -void TINFCC tinf_init(void); +unsigned char TINFCC uzlib_get_byte(TINF_DATA *d); -int TINFCC tinf_uncompress(void *dest, unsigned int *destLen, - const void *source, unsigned int sourceLen); +/* Decompression API */ -int TINFCC tinf_gzip_uncompress(void *dest, unsigned int *destLen, - const void *source, unsigned int sourceLen); +void TINFCC uzlib_init(void); +void TINFCC uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen); +int TINFCC uzlib_uncompress(TINF_DATA *d); +int TINFCC uzlib_uncompress_chksum(TINF_DATA *d); -int TINFCC tinf_zlib_uncompress(void *dest, unsigned int *destLen, - const void *source, unsigned int sourceLen); +int TINFCC uzlib_zlib_parse_header(TINF_DATA *d); +int TINFCC uzlib_gzip_parse_header(TINF_DATA *d); -unsigned int TINFCC tinf_adler32(const void *data, unsigned int length); +/* Compression API */ -unsigned int TINFCC tinf_crc32(const void *data, unsigned int length); +void TINFCC uzlib_compress(void *data, const uint8_t *src, unsigned slen); -/* compression API */ +/* Checksum API */ -void TINFCC tinf_compress(void *data, const uint8_t *src, unsigned slen); +/* prev_sum is previous value for incremental computation, 1 initially */ +uint32_t TINFCC uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum); +/* crc is previous value for incremental computation, 0xffffffff initially */ +uint32_t TINFCC uzlib_crc32(const void *data, unsigned int length, uint32_t crc); #ifdef __cplusplus } /* extern "C" */ diff --git a/extmod/uzlib/tinflate.c b/extmod/uzlib/tinflate.c index faf27e5739..0e53f7f072 100644 --- a/extmod/uzlib/tinflate.c +++ b/extmod/uzlib/tinflate.c @@ -5,7 +5,7 @@ * All Rights Reserved * http://www.ibsensoftware.com/ * - * Copyright (c) 2014 by Paul Sokolovsky + * Copyright (c) 2014-2016 by Paul Sokolovsky * * This software is provided 'as-is', without any express * or implied warranty. In no event will the authors be @@ -32,8 +32,12 @@ * any source distribution. */ +#include <assert.h> #include "tinf.h" +uint32_t tinf_get_le_uint32(TINF_DATA *d); +uint32_t tinf_get_be_uint32(TINF_DATA *d); + /* --------------------------------------------------- * * -- uninitialized global data (static structures) -- * * --------------------------------------------------- */ @@ -89,21 +93,6 @@ const unsigned char clcidx[] = { * -- utility functions -- * * ----------------------- */ -/* Execute callback to grow destination buffer */ -static int tinf_grow_dest_buf(TINF_DATA *d, unsigned int lastAlloc) -{ - unsigned int oldsize = d->dest - d->destStart; - /* This will update only destStart and destSize */ - if (!d->destGrow) - { - return TINF_DEST_OVERFLOW; - } - d->destGrow(d, lastAlloc); - d->dest = d->destStart + oldsize; - d->destRemaining = d->destSize - oldsize; - return 0; -} - #ifdef RUNTIME_BITS_TABLES /* build extra bits and base tables */ static void tinf_build_bits_base(unsigned char *bits, unsigned short *base, int delta, int first) @@ -180,6 +169,34 @@ static void tinf_build_tree(TINF_TREE *t, const unsigned char *lengths, unsigned * -- decode functions -- * * ---------------------- */ +unsigned char uzlib_get_byte(TINF_DATA *d) +{ + if (d->source) { + return *d->source++; + } + return d->readSource(d); +} + +uint32_t tinf_get_le_uint32(TINF_DATA *d) +{ + uint32_t val = 0; + int i; + for (i = 4; i--;) { + val = val >> 8 | uzlib_get_byte(d) << 24; + } + return val; +} + +uint32_t tinf_get_be_uint32(TINF_DATA *d) +{ + uint32_t val = 0; + int i; + for (i = 4; i--;) { + val = val << 8 | uzlib_get_byte(d); + } + return val; +} + /* get one bit from source stream */ static int tinf_getbit(TINF_DATA *d) { @@ -189,7 +206,7 @@ static int tinf_getbit(TINF_DATA *d) if (!d->bitcount--) { /* load next tag */ - d->tag = *d->source++; + d->tag = uzlib_get_byte(d); d->bitcount = 7; } @@ -318,113 +335,83 @@ static void tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) /* given a stream and two trees, inflate a block of data */ static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) { - while (1) - { - int sym = tinf_decode_symbol(d, lt); - - /* check for end of block */ - if (sym == 256) - { - return TINF_OK; - } - - if (sym < 256) - { - if (d->destRemaining == 0) - { - int res = tinf_grow_dest_buf(d, 1); - if (res) return res; - } - - *d->dest++ = sym; - d->destRemaining--; - - } else { - - unsigned int length, offs, i; - int dist; - - sym -= 257; - - /* possibly get more bits from length code */ - length = tinf_read_bits(d, length_bits[sym], length_base[sym]); - - dist = tinf_decode_symbol(d, dt); - - /* possibly get more bits from distance code */ - offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]); - - if (d->destRemaining < length) - { - int res = tinf_grow_dest_buf(d, length); - if (res) return res; - } - - /* copy match */ - for (i = 0; i < length; ++i) - { - d->dest[i] = d->dest[(int)(i - offs)]; - } - - d->dest += length; - d->destRemaining -= length; - } - } + if (d->curlen == 0) { + unsigned int offs; + int dist; + int sym = tinf_decode_symbol(d, lt); + //printf("huff sym: %02x\n", sym); + + /* literal byte */ + if (sym < 256) { + TINF_PUT(d, sym); + return TINF_OK; + } + + /* end of block */ + if (sym == 256) { + return TINF_DONE; + } + + /* substring from sliding dictionary */ + sym -= 257; + /* possibly get more bits from length code */ + d->curlen = tinf_read_bits(d, length_bits[sym], length_base[sym]); + + dist = tinf_decode_symbol(d, dt); + /* possibly get more bits from distance code */ + offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]); + if (d->dict_ring) { + d->lzOff = d->dict_idx - offs; + if (d->lzOff < 0) { + d->lzOff += d->dict_size; + } + } else { + d->lzOff = -offs; + } + } + + /* copy next byte from dict substring */ + if (d->dict_ring) { + TINF_PUT(d, d->dict_ring[d->lzOff]); + if ((unsigned)++d->lzOff == d->dict_size) { + d->lzOff = 0; + } + } else { + d->dest[0] = d->dest[d->lzOff]; + d->dest++; + } + d->curlen--; + return TINF_OK; } /* inflate an uncompressed block of data */ static int tinf_inflate_uncompressed_block(TINF_DATA *d) { - unsigned int length, invlength; - unsigned int i; - - /* get length */ - length = d->source[1]; - length = 256*length + d->source[0]; - - /* get one's complement of length */ - invlength = d->source[3]; - invlength = 256*invlength + d->source[2]; - - /* check length */ - if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR; - - if (d->destRemaining < length) - { - int res = tinf_grow_dest_buf(d, length); - if (res) return res; - } - - d->source += 4; - - /* copy block */ - for (i = length; i; --i) *d->dest++ = *d->source++; - d->destRemaining -= length; - - /* make sure we start next block on a byte boundary */ - d->bitcount = 0; - - return TINF_OK; -} - -/* inflate a block of data compressed with fixed huffman trees */ -static int tinf_inflate_fixed_block(TINF_DATA *d) -{ - /* build fixed huffman trees */ - tinf_build_fixed_trees(&d->ltree, &d->dtree); - - /* decode block using fixed trees */ - return tinf_inflate_block_data(d, &d->ltree, &d->dtree); -} - -/* inflate a block of data compressed with dynamic huffman trees */ -static int tinf_inflate_dynamic_block(TINF_DATA *d) -{ - /* decode trees from stream */ - tinf_decode_trees(d, &d->ltree, &d->dtree); - - /* decode block using decoded trees */ - return tinf_inflate_block_data(d, &d->ltree, &d->dtree); + if (d->curlen == 0) { + unsigned int length, invlength; + + /* get length */ + length = uzlib_get_byte(d) + 256 * uzlib_get_byte(d); + /* get one's complement of length */ + invlength = uzlib_get_byte(d) + 256 * uzlib_get_byte(d); + /* check length */ + if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR; + + /* increment length to properly return TINF_DONE below, without + producing data at the same time */ + d->curlen = length + 1; + + /* make sure we start next block on a byte boundary */ + d->bitcount = 0; + } + + if (--d->curlen == 0) { + return TINF_DONE; + } + + unsigned char c = uzlib_get_byte(d); + TINF_PUT(d, c); + return TINF_OK; } /* ---------------------- * @@ -432,7 +419,7 @@ static int tinf_inflate_dynamic_block(TINF_DATA *d) * ---------------------- */ /* initialize global (static) data */ -void tinf_init(void) +void uzlib_init(void) { #ifdef RUNTIME_BITS_TABLES /* build extra bits and base tables */ @@ -445,72 +432,117 @@ void tinf_init(void) #endif } -/* inflate stream from source to dest */ -int tinf_uncompress(void *dest, unsigned int *destLen, - const void *source, unsigned int sourceLen) +/* initialize decompression structure */ +void uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen) { - (void)sourceLen; - TINF_DATA d; - int res; - - /* initialise data */ - d.source = (const unsigned char *)source; - - d.destStart = (unsigned char *)dest; - d.destRemaining = *destLen; - d.destSize = *destLen; - - res = tinf_uncompress_dyn(&d); - - *destLen = d.dest - d.destStart; + d->bitcount = 0; + d->bfinal = 0; + d->btype = -1; + d->dict_size = dictLen; + d->dict_ring = dict; + d->dict_idx = 0; + d->curlen = 0; +} - return res; +/* inflate next byte of compressed stream */ +int uzlib_uncompress(TINF_DATA *d) +{ + do { + int res; + + /* start a new block */ + if (d->btype == -1) { +next_blk: + /* read final block flag */ + d->bfinal = tinf_getbit(d); + /* read block type (2 bits) */ + d->btype = tinf_read_bits(d, 2, 0); + + //printf("Started new block: type=%d final=%d\n", d->btype, d->bfinal); + + if (d->btype == 1) { + /* build fixed huffman trees */ + tinf_build_fixed_trees(&d->ltree, &d->dtree); + } else if (d->btype == 2) { + /* decode trees from stream */ + tinf_decode_trees(d, &d->ltree, &d->dtree); + } + } + + /* process current block */ + switch (d->btype) + { + case 0: + /* decompress uncompressed block */ + res = tinf_inflate_uncompressed_block(d); + break; + case 1: + case 2: + /* decompress block with fixed/dyanamic huffman trees */ + /* trees were decoded previously, so it's the same routine for both */ + res = tinf_inflate_block_data(d, &d->ltree, &d->dtree); + break; + default: + return TINF_DATA_ERROR; + } + + if (res == TINF_DONE && !d->bfinal) { + /* the block has ended (without producing more data), but we + can't return without data, so start procesing next block */ + goto next_blk; + } + + if (res != TINF_OK) { + return res; + } + + } while (--d->destSize); + + return TINF_OK; } -/* inflate stream from source to dest */ -int tinf_uncompress_dyn(TINF_DATA *d) +int uzlib_uncompress_chksum(TINF_DATA *d) { - int bfinal; + int res; + unsigned char *data = d->dest; - /* initialise data */ - d->bitcount = 0; + res = uzlib_uncompress(d); - d->dest = d->destStart; - d->destRemaining = d->destSize; + if (res < 0) return res; - do { + switch (d->checksum_type) { - unsigned int btype; - int res; + case TINF_CHKSUM_ADLER: + d->checksum = uzlib_adler32(data, d->dest - data, d->checksum); + break; - /* read final block flag */ - bfinal = tinf_getbit(d); + case TINF_CHKSUM_CRC: + d->checksum = uzlib_crc32(data, d->dest - data, d->checksum); + break; + } - /* read block type (2 bits) */ - btype = tinf_read_bits(d, 2, 0); + if (res == TINF_DONE) { + unsigned int val; - /* decompress block */ - switch (btype) - { - case 0: - /* decompress uncompressed block */ - res = tinf_inflate_uncompressed_block(d); - break; - case 1: - /* decompress block with fixed huffman trees */ - res = tinf_inflate_fixed_block(d); - break; - case 2: - /* decompress block with dynamic huffman trees */ - res = tinf_inflate_dynamic_block(d); - break; - default: - return TINF_DATA_ERROR; - } + switch (d->checksum_type) { - if (res != TINF_OK) return TINF_DATA_ERROR; + case TINF_CHKSUM_ADLER: + val = tinf_get_be_uint32(d); + if (d->checksum != val) { + return TINF_CHKSUM_ERROR; + } + break; - } while (!bfinal); + case TINF_CHKSUM_CRC: + val = tinf_get_le_uint32(d); + if (~d->checksum != val) { + return TINF_CHKSUM_ERROR; + } + // Uncompressed size. TODO: Check + val = tinf_get_le_uint32(d); + break; + } + } - return TINF_OK; + return res; } diff --git a/extmod/uzlib/tinfzlib.c b/extmod/uzlib/tinfzlib.c index dbacc1d9db..74fade3b9d 100644 --- a/extmod/uzlib/tinfzlib.c +++ b/extmod/uzlib/tinfzlib.c @@ -6,6 +6,8 @@ * * http://www.ibsensoftware.com/ * + * Copyright (c) 2014-2016 by Paul Sokolovsky + * * This software is provided 'as-is', without any express * or implied warranty. In no event will the authors be * held liable for any damages arising from the use of @@ -33,35 +35,14 @@ #include "tinf.h" -int tinf_zlib_uncompress(void *dest, unsigned int *destLen, - const void *source, unsigned int sourceLen) -{ - TINF_DATA d; - int res; - - /* initialise data */ - d.source = (const unsigned char *)source; - - d.destStart = (unsigned char *)dest; - d.destRemaining = *destLen; - - res = tinf_zlib_uncompress_dyn(&d, sourceLen); - - *destLen = d.dest - d.destStart; - - return res; -} - -int tinf_zlib_uncompress_dyn(TINF_DATA *d, unsigned int sourceLen) +int uzlib_zlib_parse_header(TINF_DATA *d) { - unsigned int a32; - int res; unsigned char cmf, flg; /* -- get header bytes -- */ - cmf = d->source[0]; - flg = d->source[1]; + cmf = uzlib_get_byte(d); + flg = uzlib_get_byte(d); /* -- check format -- */ @@ -77,25 +58,9 @@ int tinf_zlib_uncompress_dyn(TINF_DATA *d, unsigned int sourceLen) /* check there is no preset dictionary */ if (flg & 0x20) return TINF_DATA_ERROR; - /* -- get adler32 checksum -- */ + /* initialize for adler32 checksum */ + d->checksum_type = TINF_CHKSUM_ADLER; + d->checksum = 1; - a32 = d->source[sourceLen - 4]; - a32 = 256*a32 + d->source[sourceLen - 3]; - a32 = 256*a32 + d->source[sourceLen - 2]; - a32 = 256*a32 + d->source[sourceLen - 1]; - - d->source += 2; - - /* -- inflate -- */ - - res = tinf_uncompress_dyn(d); - - if (res != TINF_OK) return res; - - /* -- check adler32 checksum -- */ - - if (a32 != tinf_adler32(d->destStart, d->dest - d->destStart)) return TINF_DATA_ERROR; - - return TINF_OK; + return cmf >> 4; } - diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index a691ee062c..eea075f6b0 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -250,6 +250,13 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat); +// Unmount the filesystem +STATIC mp_obj_t fat_vfs_umount(mp_obj_t vfs_in) { + fatfs_umount(((fs_user_mount_t *)vfs_in)->readblocks[1]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, fat_vfs_umount); + STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) }, @@ -261,6 +268,7 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&fat_vfs_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&fat_vfs_rename_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&fat_vfs_stat_obj) }, + { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) }, }; STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table); |