Line data Source code
1 : /* 2 : This program is free software: you can redistribute it and/or modify 3 : it under the terms of the GNU General Public License as published by 4 : the Free Software Foundation, either version 3 of the License, or 5 : (at your option) any later version. 6 : 7 : This program is distributed in the hope that it will be useful, 8 : but WITHOUT ANY WARRANTY; without even the implied warranty of 9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 : GNU General Public License for more details. 11 : 12 : You should have received a copy of the GNU General Public License 13 : along with this program. If not, see <http://www.gnu.org/licenses/>. 14 : */ 15 : /* 16 : implement a file store for embedded firmware images 17 : */ 18 : 19 : #include "AP_ROMFS.h" 20 : #include "tinf.h" 21 : #include <AP_Math/crc.h> 22 : 23 : #include <AP_Common/AP_Common.h> 24 : #include <AP_HAL/AP_HAL_Boards.h> 25 : 26 : #include <string.h> 27 : 28 : #ifdef HAL_HAVE_AP_ROMFS_EMBEDDED_H 29 : #include <ap_romfs_embedded.h> 30 : #else 31 : const AP_ROMFS::embedded_file AP_ROMFS::files[] = {}; 32 : #endif 33 : 34 : /* 35 : find an embedded file 36 : */ 37 25092 : const AP_ROMFS::embedded_file *AP_ROMFS::find_file(const char *name) 38 : { 39 2278025 : for (uint16_t i=0; i<ARRAY_SIZE(files); i++) { 40 2269370 : if (strcmp(name, files[i].filename) == 0) { 41 16437 : return &files[i]; 42 : } 43 : } 44 8655 : return nullptr; 45 : } 46 : 47 : /* 48 : Find the named file and return its decompressed data and size. Caller must 49 : call AP_ROMFS::free() on the return value after use to free it. The data is 50 : guaranteed to be null-terminated such that it can be treated as a string. 51 : */ 52 16600 : const uint8_t *AP_ROMFS::find_decompress(const char *name, uint32_t &size) 53 : { 54 16600 : const struct embedded_file *f = find_file(name); 55 16600 : if (f == nullptr) { 56 2315 : return nullptr; 57 : } 58 : 59 : #ifdef HAL_ROMFS_UNCOMPRESSED 60 : size = f->decompressed_size; 61 : return f->contents; 62 : #else 63 : // add one byte for null termination; ArduPilot's malloc will zero it. 64 14285 : uint8_t *decompressed_data = (uint8_t *)malloc(f->decompressed_size+1); 65 14285 : if (!decompressed_data) { 66 0 : return nullptr; 67 : } 68 : 69 14285 : if (f->decompressed_size == 0) { 70 : // empty file, avoid decompression problems 71 0 : size = 0; 72 0 : return decompressed_data; 73 : } 74 : 75 14285 : TINF_DATA *d = (TINF_DATA *)malloc(sizeof(TINF_DATA)); 76 14285 : if (!d) { 77 0 : ::free(decompressed_data); 78 0 : return nullptr; 79 : } 80 14285 : uzlib_uncompress_init(d, NULL, 0); 81 : 82 14285 : d->source = f->contents; 83 14285 : d->source_limit = f->contents + f->compressed_size; 84 14285 : d->dest = decompressed_data; 85 14285 : d->destSize = f->decompressed_size; 86 : 87 14285 : int res = uzlib_uncompress(d); 88 : 89 14285 : ::free(d); 90 : 91 14285 : if (res != TINF_OK) { 92 0 : ::free(decompressed_data); 93 0 : return nullptr; 94 : } 95 : 96 14285 : if (crc32_small(0, decompressed_data, f->decompressed_size) != f->crc) { 97 0 : ::free(decompressed_data); 98 0 : return nullptr; 99 : } 100 : 101 14285 : size = f->decompressed_size; 102 14285 : return decompressed_data; 103 : #endif 104 : } 105 : 106 : // free decompressed file data 107 14285 : void AP_ROMFS::free(const uint8_t *data) 108 : { 109 : #ifndef HAL_ROMFS_UNCOMPRESSED 110 14285 : ::free(const_cast<uint8_t *>(data)); 111 : #endif 112 14285 : } 113 : 114 : /* 115 : directory listing interface. Start with ofs=0. Returns pathnames 116 : that match dirname prefix. Ends with nullptr return when no more 117 : files found 118 : */ 119 1 : const char *AP_ROMFS::dir_list(const char *dirname, uint16_t &ofs) 120 : { 121 1 : const size_t dlen = strlen(dirname); 122 1 : for ( ; ofs < ARRAY_SIZE(files); ofs++) { 123 1 : if (strncmp(dirname, files[ofs].filename, dlen) == 0) { 124 1 : const char last_char = files[ofs].filename[dlen]; 125 1 : if (dlen != 0 && last_char != '/' && last_char != 0) { 126 : // only a partial match, skip 127 0 : continue; 128 : } 129 : /* 130 : prevent duplicate directories 131 : */ 132 1 : const char *start_name = files[ofs].filename + dlen + 1; 133 1 : const char *slash = strchr(start_name, '/'); 134 1 : if (ofs > 0 && slash != nullptr) { 135 0 : auto len = slash - start_name; 136 0 : if (memcmp(files[ofs].filename, files[ofs-1].filename, len+dlen+1) == 0) { 137 0 : continue; 138 : } 139 : } 140 : // found one 141 1 : return files[ofs++].filename; 142 : } 143 : } 144 0 : return nullptr; 145 : } 146 : 147 : /* 148 : find a compressed file and return its size 149 : */ 150 8492 : bool AP_ROMFS::find_size(const char *name, uint32_t &size) 151 : { 152 8492 : const struct embedded_file *f = find_file(name); 153 8492 : if (f == nullptr) { 154 6340 : return false; 155 : } 156 2152 : size = f->decompressed_size; 157 2152 : return true; 158 : } 159 :