fix linux build failure
[mfgtools.git] / libuuu / fastboot.cpp
bloba4358b893f5fd59e0763aa8c92a18265e7a0d2e8
1 /*
2 * Copyright 2018 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.
33 Android fastboot protocol define at
34 https://android.googlesource.com/platform/system/core/+/master/fastboot/
36 #include <string.h>
37 #include "fastboot.h"
38 #include "libcomm.h"
39 #include "cmd.h"
40 #include "buffer.h"
41 #include "liberror.h"
42 #include "libuuu.h"
43 #include <iostream>
44 #include <fstream>
45 #include <sys/stat.h>
46 #include "sparse.h"
47 #include "ffu_format.h"
48 #include "libcomm.h"
49 #include "trans.h"
50 #include <iterator>
51 #include "rominfo.h"
53 int FastBoot::Transport(string cmd, void *p, size_t size, vector<uint8_t> *input)
55 if (m_pTrans->write((void*)cmd.data(), cmd.size()))
56 return -1;
58 char buff[65];
59 memset(buff, 0, 65);
61 while ( strncmp(buff, "OKAY", 4) && strncmp(buff, "FAIL", 4))
63 size_t actual;
64 memset(buff, 0, 65);
65 if (m_pTrans->read(buff, 64, &actual))
66 return -1;
68 if (strncmp(buff, "DATA",4) == 0)
70 size_t sz;
71 sz = strtoul(buff+4, nullptr, 16);
73 if (input)
75 input->resize(sz);
76 size_t rz;
77 if (m_pTrans->read(input->data(), sz, &rz))
78 return -1;
79 input->resize(rz);
81 else
83 if (sz > size)
84 sz = size;
86 if (m_pTrans->write(p, sz))
87 return -1;
89 }else
91 string s;
92 s = buff + 4;
93 m_info += s;
94 uuu_notify nt;
95 nt.type = uuu_notify::NOTIFY_CMD_INFO;
96 nt.str = buff + 4;
97 call_notify(nt);
101 if (strncmp(buff, "OKAY", 4) == 0)
102 return 0;
104 set_last_err_string(m_info);
105 return -1;
108 int FBGetVar::parser(char *p)
110 if (p)
111 m_cmd = p;
113 size_t pos = 0;
114 string param = get_next_param(m_cmd, pos);
116 if (param.find(':') != string::npos)
117 param = get_next_param(m_cmd, pos);
119 if (str_to_upper(param) != "GETVAR")
121 string err = "Unknown Command:";
122 err += param;
123 set_last_err_string(err);
124 return -1;
127 m_var = get_next_param(m_cmd, pos);
128 return 0;
130 int FBGetVar::run(CmdCtx *ctx)
132 BulkTrans dev;
133 if (dev.open(ctx->m_dev))
134 return -1;
136 FastBoot fb(&dev);
137 string cmd;
138 cmd = "getvar:";
139 cmd += m_var;
141 if (fb.Transport(cmd, nullptr, 0))
142 return -1;
144 m_val = fb.m_info;
145 return 0;
148 int FBCmd::parser(char *p)
150 if (p)
151 m_cmd = p;
153 size_t pos = 0;
154 string s;
156 if (parser_protocal(p, pos))
157 return -1;
159 s = get_next_param(m_cmd, pos);
161 if (str_to_upper(s) != str_to_upper(m_fb_cmd))
163 string err = "Unknown command: ";
164 err += s;
165 set_last_err_string(s);
166 return -1;
169 if(pos!=string::npos && pos < m_cmd.size())
170 m_uboot_cmd = m_cmd.substr(pos);
171 return 0;
174 int FBCmd::run(CmdCtx *ctx)
176 BulkTrans dev{m_timeout};
177 if (dev.open(ctx->m_dev))
178 return -1;
180 FastBoot fb(&dev);
181 string cmd;
182 cmd = m_fb_cmd;
183 cmd += m_separator;
184 cmd += m_uboot_cmd;
186 if (fb.Transport(cmd, nullptr, 0))
187 return -1;
189 return 0;
192 int FBPartNumber::run(CmdCtx *ctx)
194 BulkTrans dev{m_timeout};
195 if (dev.open(ctx->m_dev))
196 return -1;
198 FastBoot fb(&dev);
200 string_ex cmd;
201 cmd.format("%s:%s:%08x", m_fb_cmd.c_str(), m_partition_name.c_str(), (uint32_t)m_Size);
203 if (fb.Transport(cmd, nullptr, 0))
204 return -1;
206 return 0;
209 int FBUpdateSuper::run(CmdCtx *ctx)
211 BulkTrans dev{m_timeout};
212 if (dev.open(ctx->m_dev))
213 return -1;
215 FastBoot fb(&dev);
217 string_ex cmd;
218 cmd.format("%s:%s:%s", m_fb_cmd.c_str(), m_partition_name.c_str(), m_opt.c_str());
220 if (fb.Transport(cmd, nullptr, 0))
221 return -1;
223 return 0;
226 int FBDownload::run(CmdCtx *ctx)
228 BulkTrans dev;
229 if (dev.open(ctx->m_dev))
230 return -1;
232 FastBoot fb(&dev);
234 shared_ptr<FileBuffer> buff = get_file_buffer(m_filename);
235 if (buff == nullptr)
236 return -1;
238 string_ex cmd;
239 cmd.format("download:%08x", buff->size());
241 if (fb.Transport(cmd, buff->data(), buff->size()))
242 return -1;
244 return 0;
247 int FBUpload::run(CmdCtx* ctx)
249 BulkTrans dev;
250 if (dev.open(ctx->m_dev))
251 return -1;
253 FastBoot fb(&dev);
255 string_ex cmd;
256 cmd.format("upload");
258 std::vector<uint8_t> buff;
259 if (fb.Transport(cmd, nullptr, buff.size(), &buff))
260 return -1;
262 std::ofstream fout(m_filename, ios::out | ios::trunc);
263 std::copy(buff.begin(), buff.end(), std::ostream_iterator<uint8_t>(fout));
264 fout.flush();
265 fout.close();
267 return 0;
270 int FBCopy::parser(char *p)
272 if (p)
273 m_cmd = p;
275 size_t pos = 0;
276 string s;
277 s = get_next_param(m_cmd, pos);
278 if (s.find(":") != s.npos)
279 s = get_next_param(m_cmd, pos);
281 if ((str_to_upper(s) != "UCP"))
283 string err = "Unknown command: ";
284 err += s;
285 set_last_err_string(s);
286 return -1;
289 string source;
290 string dest;
292 source = get_next_param(m_cmd, pos);
293 dest = get_next_param(m_cmd, pos);
295 if (source.empty())
297 set_last_err_string("ucp: source missed");
298 return -1;
301 if (dest.empty())
303 set_last_err_string("ucp: destination missed");
304 return -1;
307 if (source.find("T:") == 0 || source.find("t:") == 0)
309 if (dest.find("T:") == 0 || dest.find("t:") == 0)
311 set_last_err_string("ucp just support one is remote file start with t:");
312 return -1;
314 m_target_file = source.substr(2);
315 m_bDownload = false; //upload a file
316 m_local_file = dest;
318 else if (dest.find("T:") == 0 || dest.find("t:") == 0)
320 m_target_file = dest.substr(2);
321 m_bDownload = true;
322 m_local_file = source;
323 get_file_buffer(source, true);
325 else
327 set_last_err_string("ucp must a remote file name, start with t:<file name>");
328 return -1;
330 return 0;
333 int FBCopy::run(CmdCtx *ctx)
335 BulkTrans dev;
336 if (dev.open(ctx->m_dev))
337 return -1;
339 FastBoot fb(&dev);
340 string_ex cmd;
342 if(m_bDownload)
344 size_t i;
345 shared_ptr<FileBuffer> buff = get_file_buffer(m_local_file);
346 if (buff == nullptr)
348 return -1;
351 cmd.format("WOpen:%s", m_target_file.c_str());
352 if (fb.Transport(cmd, nullptr, 0))
354 if (fb.m_info == "DIR")
356 Path p;
357 p.append(m_local_file);
358 string target = m_target_file;
359 target += "/";
360 target += p.get_file_name();
362 cmd.format("WOpen:%s", target.c_str());
363 if (fb.Transport(cmd, nullptr, 0))
364 return -1;
366 else {
367 return -1;
371 uuu_notify nt;
372 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
373 nt.total = buff->size();
374 call_notify(nt);
376 for (i = 0; i < buff->size(); i += this->m_Maxsize_pre_cmd)
378 size_t sz = buff->size() - i;
379 if (sz > m_Maxsize_pre_cmd)
380 sz = m_Maxsize_pre_cmd;
382 cmd.format("donwload:%08X", sz);
383 if (fb.Transport(cmd, buff->data() + i, sz))
385 if (fb.m_info == "EPIPE")
386 set_last_err_string("pipe closed by target");
387 else
388 set_last_err_string("target return unknown error");
390 cmd.format("Close");
391 if (fb.Transport(cmd, nullptr, 0))
392 return -1;
394 return -1;
397 nt.type = uuu_notify::NOTIFY_TRANS_POS;
398 nt.index = i;
399 call_notify(nt);
402 nt.type = uuu_notify::NOTIFY_TRANS_POS;
403 nt.index = buff->size();
404 call_notify(nt);
406 else
408 cmd.format("ROpen:%s", m_target_file.c_str());
409 if (fb.Transport(cmd, nullptr, 0))
410 return -1;
412 uuu_notify nt;
413 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
414 size_t total = nt.total = strtoul(fb.m_info.c_str(), nullptr, 16);
415 call_notify(nt);
417 nt.index = 0;
418 ofstream of;
420 struct stat st;
422 Path localfile;
423 localfile.append(m_local_file);
425 if (stat(localfile.c_str(), &st) == 0)
427 if (st.st_mode & S_IFDIR)
429 localfile += "/";
430 Path t;
431 t.append(m_target_file);
432 localfile += t.get_file_name();
436 of.open(localfile, ofstream::binary);
438 if (!of)
440 string err;
441 err = "Fail to open file";
442 err += localfile;
443 set_last_err_string(err);
447 vector<uint8_t> data;
448 if (fb.Transport("upload", nullptr, 0, &data))
449 return -1;
451 of.write((const char*)data.data(), data.size());
453 nt.type = uuu_notify::NOTIFY_TRANS_POS;
454 nt.index += data.size();
455 call_notify(nt);
457 if (data.size() == 0)
458 break;
460 } while (nt.index < total || total == 0 ); // If total is 0, it is stream
462 nt.type = uuu_notify::NOTIFY_TRANS_POS;
463 call_notify(nt);
466 cmd.format("Close");
467 if (fb.Transport(cmd, nullptr, 0))
468 return -1;
470 return 0;
473 int FBFlashCmd::parser(char *p)
475 if (FBCmd::parser(p))
476 return -1;
478 string subcmd = m_uboot_cmd;
479 size_t pos = 0;
480 m_partition = get_next_param(subcmd, pos);
482 if (m_partition == "-raw2sparse")
484 m_raw2sparse = true;
485 m_partition = get_next_param(subcmd, pos);
488 if (m_partition == "-scanterm")
490 m_scanterm = true;
491 m_partition = get_next_param(subcmd, pos);
494 if (m_partition == "-S")
496 m_partition = get_next_param(subcmd, pos);
497 bool conversion_success = false;
498 m_sparse_limit = str_to_uint64(m_partition, &conversion_success);
499 if (!conversion_success)
501 set_last_err_string("FB: flash failed to parse size argument given to -S: "s + m_partition);
502 return -1;
504 m_partition = get_next_param(subcmd, pos);
507 if (pos == string::npos || m_partition.empty())
509 set_last_err_string("Missed partition name");
510 return -1;
512 m_filename = get_next_param(subcmd, pos);
513 if (m_filename.empty())
515 set_last_err_string("Missed file name");
516 return -1;
519 if (!check_file_exist(m_filename))
520 return -1;
522 return 0;
525 int FBFlashCmd::flash(FastBoot *fb, void * pdata, size_t sz)
527 string_ex cmd;
528 cmd.format("download:%08x", sz);
530 if (fb->Transport(cmd, pdata, sz))
531 return -1;
533 cmd.format("flash:%s", m_partition.c_str());
534 if (fb->Transport(cmd, nullptr, 0))
535 return -1;
537 return 0;
540 int FBFlashCmd::flash_raw2sparse(FastBoot *fb, shared_ptr<FileBuffer> pdata, size_t block_size, size_t max)
542 SparseFile sf;
544 vector<uint8_t> data;
546 if (max > m_sparse_limit)
547 max = m_sparse_limit;
549 sf.init_header(block_size, (max + block_size -1) / block_size);
551 data.resize(block_size);
553 uuu_notify nt;
554 bool bload = pdata->IsKnownSize();
556 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
557 if (bload)
558 nt.total = pdata->size();
559 else
560 nt.total = 0;
562 call_notify(nt);
565 size_t i = 0;
566 int r;
567 while (!(r=pdata->request_data(data, i*block_size, block_size)))
569 int ret = sf.push_one_block(data.data());
570 if (ret)
572 if (flash(fb, sf.m_data.data(), sf.m_data.size()))
573 return -1;
575 sf.init_header(block_size, (max + block_size - 1) / block_size);
577 chunk_header_t ct;
578 ct.chunk_type = CHUNK_TYPE_DONT_CARE;
579 ct.chunk_sz = i + 1;
580 ct.reserved1 = 0;
581 ct.total_sz = sizeof(ct);
583 sf.push_one_chuck(&ct, nullptr);
585 nt.type = uuu_notify::NOTIFY_TRANS_POS;
586 nt.total = i * block_size;
587 call_notify(nt);
590 i++;
592 if (bload != pdata->IsKnownSize())
594 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
595 nt.total = pdata->size();
596 call_notify(nt);
598 bload = pdata->IsKnownSize();
602 if (r == ERR_OUT_MEMORY)
603 return r;
605 if (flash(fb, sf.m_data.data(), sf.m_data.size()))
606 return -1;
608 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
609 nt.total = pdata->size();
610 call_notify(nt);
612 nt.type = uuu_notify::NOTIFY_TRANS_POS;
613 nt.total = pdata->size();
614 call_notify(nt);
616 return 0;
619 int FBFlashCmd::run(CmdCtx *ctx)
621 FBGetVar getvar((char*)"FB: getvar max-download-size");
622 if (getvar.parser(nullptr))
623 return -1;
624 if (getvar.run(ctx))
625 return -1;
627 size_t max = getvar.m_val.empty() ? m_sparse_limit : str_to_uint32(getvar.m_val);
629 BulkTrans dev{m_timeout};
630 if (dev.open(ctx->m_dev))
631 return -1;
633 FastBoot fb(&dev);
635 if (m_raw2sparse)
637 size_t block_size = 4096;
639 if (getvar.parser((char*)"FB: getvar logical-block-size"))
640 return -1;
641 if (!getvar.run(ctx))
642 block_size = str_to_uint32(getvar.m_val);
644 if (block_size == 0)
646 set_last_err_string("Device report block_size is 0");
647 return -1;
650 shared_ptr<FileBuffer> pdata = get_file_buffer(m_filename, true);
652 if (isffu(pdata))
654 string str;
655 str = "FB: getvar partition-size:";
656 str += m_partition;
658 if (getvar.parser((char*)str.c_str()))
659 return -1;
661 if (getvar.run(ctx))
662 return -1;
664 m_totalsize = str_to_uint64(getvar.m_val);
666 return flash_ffu(&fb, pdata);
669 return flash_raw2sparse(&fb, pdata, block_size, max);
672 shared_ptr<FileBuffer> pdata = get_file_buffer(m_filename, true);
673 if (pdata == nullptr)
674 return -1;
676 pdata->request_data(sizeof(sparse_header));
677 if (SparseFile::is_validate_sparse_file(pdata->data(), sizeof(sparse_header)))
678 { /* Limited max size to 16M for sparse file to avoid long timeout at read status*/
679 if (max > m_sparse_limit)
680 max = m_sparse_limit;
683 if (m_scanterm)
685 pdata->request_data(WIC_BOOTPART_SIZE);
686 size_t length,pos=0;
687 if (IsMBR(pdata))
689 length = ScanTerm(pdata, pos);
690 if (length == 0)
692 set_last_err_string("This wic have NOT terminate tag after bootloader, please use new yocto");
693 return -1;
695 size_t offset = pos - length;
696 if (offset < 0)
698 set_last_err_string("This wic boot length is wrong");
699 return -1;
701 return flash(&fb, pdata->data() + offset, length);
705 if (pdata->size() <= max)
707 pdata->request_data(pdata->size());
709 if (flash(&fb, pdata->data(), pdata->size()))
710 return -1;
712 else
714 size_t pos = 0;
715 pdata->request_data(sizeof(sparse_header));
716 sparse_header * pfile = (sparse_header *)pdata->data();
718 if (!SparseFile::is_validate_sparse_file(pdata->data(), sizeof(sparse_header)))
720 set_last_err_string("Sparse file magic miss matched");
721 return -1;
724 SparseFile sf;
725 size_t startblock;
726 chunk_header_t * pheader;
728 uuu_notify nt;
729 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
730 nt.total = pfile->total_blks;
731 call_notify(nt);
733 sf.init_header(pfile->blk_sz, max / pfile->blk_sz);
734 startblock = 0;
736 for(size_t nblk=0; nblk < pfile->total_chunks && pos <= pdata->size(); nblk++)
738 pdata->request_data(pos+sizeof(chunk_header_t)+sizeof(sparse_header));
739 size_t oldpos = pos;
740 pheader = SparseFile::get_next_chunk(pdata->data(), pos);
741 pdata->request_data(pos);
743 size_t sz = sf.push_one_chuck(pheader, pheader + 1);
744 if (sz == pheader->total_sz - sizeof(chunk_header_t))
746 startblock += pheader->chunk_sz;
748 else if (sz == 0)
750 //whole chuck have not push into data.
751 if (flash(&fb, sf.m_data.data(), sf.m_data.size()))
752 return -1;
754 sf.init_header(pfile->blk_sz, max / pfile->blk_sz);
756 chunk_header_t ct;
757 ct.chunk_type = CHUNK_TYPE_DONT_CARE;
758 ct.chunk_sz = startblock;
759 ct.reserved1 = 0;
760 ct.total_sz = sizeof(ct);
762 sz = sf.push_one_chuck(&ct, nullptr);
765 roll back pos to previous failure chunck and let it push again into new sparse file.
766 can't push it here because next chuck may big size chuck and need split as below else logic.
768 pos = oldpos;
769 nblk--;
771 uuu_notify nt;
772 nt.type = uuu_notify::NOTIFY_TRANS_POS;
773 nt.total = startblock;
774 call_notify(nt);
776 else
778 size_t off = ((uint8_t*)pheader) - pdata->data() + sz + sizeof(chunk_header_t);
779 startblock += sz / pfile->blk_sz;
783 if (flash(&fb, sf.m_data.data(), sf.m_data.size()))
784 return -1;
786 sf.init_header(pfile->blk_sz, max / pfile->blk_sz);
788 chunk_header_t ct;
789 ct.chunk_type = CHUNK_TYPE_DONT_CARE;
790 ct.chunk_sz = startblock;
791 ct.reserved1 = 0;
792 ct.total_sz = sizeof(ct);
794 sz = sf.push_one_chuck(&ct, nullptr);
796 sz = sf.push_raw_data(pdata->data() + off, pos - off);
797 off += sz;
798 startblock += sz / pfile->blk_sz;
800 uuu_notify nt;
801 nt.type = uuu_notify::NOTIFY_TRANS_POS;
802 nt.total = startblock;
803 call_notify(nt);
805 } while (off < pos);
809 //send last data
810 if (flash(&fb, sf.m_data.data(), sf.m_data.size()))
811 return -1;
813 sparse_header * pf = (sparse_header *)sf.m_data.data();
814 nt.type = uuu_notify::NOTIFY_TRANS_POS;
815 nt.total = startblock + pf->total_blks;
816 call_notify(nt);
818 return 0;
821 bool FBFlashCmd::isffu(shared_ptr<FileBuffer> p)
823 vector<uint8_t> data;
824 data.resize(sizeof(FFU_SECURITY_HEADER));
825 p->request_data(data, 0, sizeof(FFU_SECURITY_HEADER));
827 FFU_SECURITY_HEADER *h = (FFU_SECURITY_HEADER*)data.data();
828 if (strncmp((const char*)h->signature, FFU_SECURITY_SIGNATURE, sizeof(h->signature)) == 0)
829 return true;
830 else
831 return false;
834 int FBFlashCmd::flash_ffu_oneblk(FastBoot *fb, shared_ptr<FileBuffer> p, size_t off, size_t blksz, size_t blkindex)
836 SparseFile sf;
838 sf.init_header(blksz, 10);
840 p->request_data(off + blksz);
842 chunk_header_t ct;
843 ct.chunk_type = CHUNK_TYPE_DONT_CARE;
844 ct.chunk_sz = blkindex;
845 ct.reserved1 = 0;
846 ct.total_sz = sizeof(ct);
848 sf.push_one_chuck(&ct, nullptr);
850 if (sf.push_one_block(p->data() + off))
851 return -1;
853 return flash(fb, sf.m_data.data(), sf.m_data.size());
856 int FBFlashCmd::flash_ffu(FastBoot *fb, shared_ptr<FileBuffer> p)
858 p->request_data(sizeof(FFU_SECURITY_HEADER));
859 FFU_SECURITY_HEADER *h = (FFU_SECURITY_HEADER*)p->data();
860 if (strncmp((const char*)h->signature, FFU_SECURITY_SIGNATURE, sizeof(h->signature)) != 0)
862 set_last_err_string("Invalidate FFU Security header signature");
863 return -1;
866 size_t off;
867 off = h->dwCatalogSize + h->dwHashTableSize;
868 off = round_up(off, (size_t)h->dwChunkSizeInKb * 1024);
870 p->request_data(off + sizeof(FFU_IMAGE_HEADER));
871 FFU_IMAGE_HEADER *pIh = (FFU_IMAGE_HEADER *)(p->data() + off);
873 if (strncmp((const char*)pIh->Signature, FFU_SIGNATURE, sizeof(pIh->Signature)) != 0)
875 set_last_err_string("Invalidate FFU Security header signature");
876 return -1;
879 off += pIh->ManifestLength + pIh->cbSize;
880 off = round_up(off, (size_t)h->dwChunkSizeInKb * 1024);
882 p->request_data(off + sizeof(FFU_STORE_HEADER));
883 FFU_STORE_HEADER *pIs = (FFU_STORE_HEADER*) (p->data() + off);
885 if(pIs->MajorVersion == 1)
886 off += pIs->dwValidateDescriptorLength + offsetof(FFU_STORE_HEADER, NumOfStores);
887 else
888 off += pIs->dwValidateDescriptorLength + sizeof(FFU_STORE_HEADER);
890 p->request_data(off + pIs->dwWriteDescriptorLength);
892 size_t block_off = off + pIs->dwWriteDescriptorLength;
893 block_off = round_up(block_off, (size_t)h->dwChunkSizeInKb * 1024);
895 uuu_notify nt;
896 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
897 nt.total = pIs->dwWriteDescriptorCount;
898 call_notify(nt);
900 size_t currrent_block = 0;
901 size_t i;
902 for (i = 0; i < pIs->dwWriteDescriptorCount; i++)
904 FFU_BLOCK_DATA_ENTRY *entry = (FFU_BLOCK_DATA_ENTRY*)(p->data() + off);
906 off += sizeof(FFU_BLOCK_DATA_ENTRY) + (entry->dwLocationCount -1) * sizeof(_DISK_LOCATION);
908 if (currrent_block >= pIs->dwInitialTableIndex && currrent_block < pIs->dwInitialTableIndex + pIs->dwInitialTableCount)
910 //Skip Init Block
912 else
914 for (uint32_t loc = 0; loc < entry->dwLocationCount; loc++)
916 //printf("block 0x%x write to 0x%x seek %d\n", currrent_block, entry->rgDiskLocations[loc].dwBlockIndex, entry->rgDiskLocations[loc].dwDiskAccessMethod);
917 uint32_t access = entry->rgDiskLocations[loc].dwDiskAccessMethod;
918 uint32_t blockindex;
919 if (entry->rgDiskLocations[loc].dwDiskAccessMethod == DISK_BEGIN)
920 blockindex = entry->rgDiskLocations[loc].dwBlockIndex;
921 else
922 blockindex = m_totalsize / pIs->dwBlockSizeInBytes - 1 - entry->rgDiskLocations[loc].dwBlockIndex;
924 for (uint32_t blk = 0; blk < entry->dwBlockCount; blk++)
926 if (flash_ffu_oneblk(fb,
928 block_off + (currrent_block + blk) * pIs->dwBlockSizeInBytes,
929 pIs->dwBlockSizeInBytes,
930 blockindex + blk))
931 return -1;
936 nt.type = uuu_notify::NOTIFY_TRANS_POS;
937 nt.total = i;
938 call_notify(nt);
940 currrent_block += entry->dwBlockCount;
943 nt.type = uuu_notify::NOTIFY_TRANS_POS;
944 nt.total = i;
945 call_notify(nt);
947 return 0;