Add submodules checkout
[mfgtools.git] / libuuu / sparse.cpp
blobe2cea66e4b63b3cb38420530f3b887c9a771cd84
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)
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 = is_same_value(data, pheader->blk_sz) ? CHUNK_TYPE_FILL : CHUNK_TYPE_RAW;
120 int type = CHUNK_TYPE_RAW;
122 if (!is_append_old_chuck(type, data))
124 chunk_header_t header;
125 header.chunk_type = type;
126 header.chunk_sz = 1;
127 header.total_sz = (type == CHUNK_TYPE_FILL) ? sizeof(uint32_t) : pheader->blk_sz;
128 header.total_sz += sizeof(chunk_header_t);
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);
139 else
140 push(data, sizeof(uint32_t));
142 else
144 pchunk->chunk_sz++;
145 if (type == CHUNK_TYPE_RAW)
147 push(data, pheader->blk_sz);
148 pchunk->total_sz += pheader->blk_sz;
152 if (m_data.size() + 2 * pheader->blk_sz > m_max_size )
153 return -1;
155 return 0;
158 size_t SparseFile::push_one_chuck(chunk_header_t *p, void *data)
160 chunk_header_t cheader = *p;
161 sparse_header *pheader;
162 pheader = (sparse_header *)m_data.data();
164 size_t sz = p->total_sz - sizeof(chunk_header);
166 if (p->total_sz + m_data.size() > m_max_size)
168 if (p->chunk_type == CHUNK_TYPE_RAW)
170 size_t blk = (m_max_size - m_data.size()) / pheader->blk_sz;
171 if (blk < 2)
172 return 0;
174 blk -= 2;
176 cheader.chunk_sz = blk;
177 sz = blk * pheader->blk_sz;
178 cheader.total_sz = sizeof(chunk_header_t) + sz;
180 else
181 return 0;
184 push(&cheader, sizeof(chunk_header));
185 pheader->total_chunks ++;
186 pheader->total_blks += cheader.chunk_sz;
188 if (data) {
189 push(data, sz);
192 return sz;
195 size_t SparseFile::push_raw_data(void *data, size_t sz)
197 chunk_header_t cheader;
198 cheader.chunk_type = CHUNK_TYPE_RAW;
200 sparse_header *pheader;
201 pheader = (sparse_header *)m_data.data();
203 cheader.chunk_sz = sz / pheader->blk_sz;
204 cheader.total_sz = cheader.chunk_sz*pheader->blk_sz + sizeof(chunk_header_t);
205 pheader = (sparse_header *)m_data.data();
207 return push_one_chuck(&cheader, data);