Update README.md
[mfgtools.git] / libuuu / sparse.cpp
blob5b36d288b29a5d6dcfbc7d39f44a5188a4b2086e
1 /*
2 * Copyright 2020 NXP.
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice, this
11 * list of conditions and the following disclaimer in the documentation and/or
12 * other materials provided with the distribution.
14 * Neither the name of the NXP Semiconductor nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
32 #include "sparse.h"
33 #include "liberror.h"
35 #include <cstddef>
36 #include <cstring>
39 int SparseFile::init_header(size_t blsz, int blcount)
41 sparse_header header;
43 memset(&header, 0, sizeof(header));
44 header.magic = SPARSE_HEADER_MAGIC;
45 header.major_version = 1;
46 header.minor_version = 0;
47 header.file_hdr_sz = sizeof(header);
48 header.chunk_hdr_sz = sizeof(chunk_header);
49 header.blk_sz = blsz;
50 m_cur_chunk_header_pos = 0;
51 if (blcount)
53 m_data.reserve(blsz*blcount + 0x1000);
54 m_max_size = blsz * blcount;
56 m_data.clear();
57 push(&header, sizeof(header));
58 m_pcrc = (uint32_t*)(m_data.data() + offsetof(sparse_header, image_checksum));
59 return 0;
62 bool SparseFile::is_append_old_chuck(int type, void *p)
64 chunk_header_t *pchunk;
65 pchunk = (chunk_header_t *)(m_data.data() + m_cur_chunk_header_pos);
67 if (m_cur_chunk_header_pos == 0)
68 return false;
70 if (pchunk->chunk_type != type)
71 return false;
73 if (type == CHUNK_TYPE_FILL)
75 uint32_t a = *(uint32_t*)(pchunk + 1);
76 uint32_t b = *(uint32_t*)p;
77 if (a != b)
78 return false;
80 return true;
83 bool SparseFile::is_same_value(void *data, size_t sz)
85 uint32_t *p = (uint32_t *)data;
86 uint32_t val = *p;
87 for (size_t i = 0; i < sz / sizeof(uint32_t); i++)
88 if (val != p[i])
89 return false;
90 return true;
93 bool SparseFile::is_validate_sparse_file(void *p, size_t)
95 sparse_header *pheader = (sparse_header*)p;
96 if (pheader->magic == SPARSE_HEADER_MAGIC)
97 return true;
98 return false;
101 int SparseFile::push(void *p, size_t sz)
103 size_t pos = m_data.size();
104 m_data.resize(pos + sz);
105 memcpy(m_data.data() + pos, p, sz);
106 return 0;
109 int SparseFile::push_one_block(void *data, bool skip)
111 chunk_header_t *pchunk;
112 pchunk = (chunk_header_t *)(m_data.data() + m_cur_chunk_header_pos);
114 sparse_header *pheader;
115 pheader = (sparse_header *)m_data.data();
117 pheader->total_blks++;
119 int type = skip ? CHUNK_TYPE_DONT_CARE : CHUNK_TYPE_RAW;
121 if (!is_append_old_chuck(type, data))
123 chunk_header_t header;
124 header.chunk_type = type;
125 header.chunk_sz = 1;
126 header.total_sz = sizeof(chunk_header_t);
127 if (type == CHUNK_TYPE_RAW)
128 header.total_sz += pheader->blk_sz;
129 header.reserved1 = 0;
131 pheader->total_chunks++;
133 m_cur_chunk_header_pos = m_data.size();
135 push(&header, sizeof(chunk_header_t));
137 if (type == CHUNK_TYPE_RAW)
138 push(data, pheader->blk_sz);
140 else
142 pchunk->chunk_sz++;
143 if (type == CHUNK_TYPE_RAW)
145 push(data, pheader->blk_sz);
146 pchunk->total_sz += pheader->blk_sz;
150 if (m_data.size() + 2 * pheader->blk_sz > m_max_size ) {
151 return -1;
154 return 0;
157 size_t SparseFile::push_one_chuck(chunk_header_t *p, void *data)
159 chunk_header_t cheader = *p;
160 sparse_header *pheader;
161 pheader = (sparse_header *)m_data.data();
163 size_t sz = p->total_sz - sizeof(chunk_header);
165 if (p->total_sz + m_data.size() > m_max_size)
167 if (p->chunk_type == CHUNK_TYPE_RAW)
169 size_t blk = (m_max_size - m_data.size()) / pheader->blk_sz;
170 if (blk < 2)
171 return 0;
173 blk -= 2;
175 cheader.chunk_sz = blk;
176 sz = blk * pheader->blk_sz;
177 cheader.total_sz = sizeof(chunk_header_t) + sz;
179 else
180 return 0;
183 push(&cheader, sizeof(chunk_header));
184 pheader->total_chunks ++;
185 pheader->total_blks += cheader.chunk_sz;
187 if (data) {
188 push(data, sz);
191 return sz;
194 size_t SparseFile::push_raw_data(void *data, size_t sz)
196 chunk_header_t cheader;
197 cheader.chunk_type = CHUNK_TYPE_RAW;
199 sparse_header *pheader;
200 pheader = (sparse_header *)m_data.data();
202 cheader.chunk_sz = sz / pheader->blk_sz;
203 cheader.total_sz = cheader.chunk_sz*pheader->blk_sz + sizeof(chunk_header_t);
204 pheader = (sparse_header *)m_data.data();
206 return push_one_chuck(&cheader, data);