/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* implement a file store for embedded firmware images */ #include "AP_ROMFS.h" #include "tinf.h" #include #include #include #include #ifdef HAL_HAVE_AP_ROMFS_EMBEDDED_H #include #else const AP_ROMFS::embedded_file AP_ROMFS::files[] = {}; #endif /* find an embedded file */ const AP_ROMFS::embedded_file *AP_ROMFS::find_file(const char *name) { for (uint16_t i=0; idecompressed_size; return f->contents; #else uint8_t *decompressed_data = (uint8_t *)malloc(f->decompressed_size+1); if (!decompressed_data) { return nullptr; } if (f->decompressed_size == 0) { // empty file size = 0; return decompressed_data; } // explicitly null-terminate the data decompressed_data[f->decompressed_size] = 0; TINF_DATA *d = (TINF_DATA *)malloc(sizeof(TINF_DATA)); if (!d) { ::free(decompressed_data); return nullptr; } uzlib_uncompress_init(d, NULL, 0); d->source = f->contents; d->source_limit = f->contents + f->compressed_size; d->dest = decompressed_data; d->destSize = f->decompressed_size; int res = uzlib_uncompress(d); ::free(d); if (res != TINF_OK) { ::free(decompressed_data); return nullptr; } if (crc32_small(0, decompressed_data, f->decompressed_size) != f->crc) { ::free(decompressed_data); return nullptr; } size = f->decompressed_size; return decompressed_data; #endif } // free returned data void AP_ROMFS::free(const uint8_t *data) { #ifndef HAL_ROMFS_UNCOMPRESSED ::free(const_cast(data)); #endif } /* directory listing interface. Start with ofs=0. Returns pathnames that match dirname prefix. Ends with nullptr return when no more files found */ const char *AP_ROMFS::dir_list(const char *dirname, uint16_t &ofs) { const size_t dlen = strlen(dirname); for ( ; ofs < ARRAY_SIZE(files); ofs++) { if (strncmp(dirname, files[ofs].filename, dlen) == 0) { const char last_char = files[ofs].filename[dlen]; if (dlen != 0 && last_char != '/' && last_char != 0) { // only a partial match, skip continue; } /* prevent duplicate directories */ const char *start_name = files[ofs].filename + dlen + 1; const char *slash = strchr(start_name, '/'); if (ofs > 0 && slash != nullptr) { auto len = slash - start_name; if (memcmp(files[ofs].filename, files[ofs-1].filename, len+dlen+1) == 0) { continue; } } // found one return files[ofs++].filename; } } return nullptr; } /* find a compressed file and return its size */ bool AP_ROMFS::find_size(const char *name, uint32_t &size) { const struct embedded_file *f = find_file(name); if (f == nullptr) { return false; } size = f->decompressed_size; return true; }