Fix some spelling errors
[mfgtools.git] / libuuu / fastboot.cpp
blob9028e72ce9d34aa53c9ed4f44dd245bbdf6383bf
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"
51 int FastBoot::Transport(string cmd, void *p, size_t size, vector<uint8_t> *input)
53 if (m_pTrans->write((void*)cmd.data(), cmd.size()))
54 return -1;
56 char buff[65];
57 memset(buff, 0, 65);
59 while ( strncmp(buff, "OKAY", 4) && strncmp(buff, "FAIL", 4))
61 size_t actual;
62 memset(buff, 0, 65);
63 if (m_pTrans->read(buff, 64, &actual))
64 return -1;
66 if (strncmp(buff, "DATA",4) == 0)
68 size_t sz;
69 sz = strtoul(buff+4, nullptr, 16);
71 if (input)
73 input->resize(sz);
74 size_t rz;
75 if (m_pTrans->read(input->data(), sz, &rz))
76 return -1;
77 input->resize(rz);
79 else
81 if (sz > size)
82 sz = size;
84 if (m_pTrans->write(p, sz))
85 return -1;
87 }else
89 string s;
90 s = buff + 4;
91 m_info += s;
92 uuu_notify nt;
93 nt.type = uuu_notify::NOTIFY_CMD_INFO;
94 nt.str = buff + 4;
95 call_notify(nt);
99 if (strncmp(buff, "OKAY", 4) == 0)
100 return 0;
102 set_last_err_string(m_info);
103 return -1;
106 int FBGetVar::parser(char *p)
108 if (p)
109 m_cmd = p;
111 size_t pos = 0;
112 string param = get_next_param(m_cmd, pos);
114 if (param.find(':') != string::npos)
115 param = get_next_param(m_cmd, pos);
117 if (str_to_upper(param) != "GETVAR")
119 string err = "Unknown Command:";
120 err += param;
121 set_last_err_string(err);
122 return -1;
125 m_var = get_next_param(m_cmd, pos);
126 return 0;
128 int FBGetVar::run(CmdCtx *ctx)
130 BulkTrans dev;
131 if (dev.open(ctx->m_dev))
132 return -1;
134 FastBoot fb(&dev);
135 string cmd;
136 cmd = "getvar:";
137 cmd += m_var;
139 if (fb.Transport(cmd, nullptr, 0))
140 return -1;
142 m_val = fb.m_info;
143 return 0;
146 int FBCmd::parser(char *p)
148 if (p)
149 m_cmd = p;
151 size_t pos = 0;
152 string s;
154 if (parser_protocal(p, pos))
155 return -1;
157 s = get_next_param(m_cmd, pos);
159 if (str_to_upper(s) != str_to_upper(m_fb_cmd))
161 string err = "Unknown command: ";
162 err += s;
163 set_last_err_string(s);
164 return -1;
167 if(pos!=string::npos && pos < m_cmd.size())
168 m_uboot_cmd = m_cmd.substr(pos);
169 return 0;
172 int FBCmd::run(CmdCtx *ctx)
174 BulkTrans dev{m_timeout};
175 if (dev.open(ctx->m_dev))
176 return -1;
178 FastBoot fb(&dev);
179 string cmd;
180 cmd = m_fb_cmd;
181 cmd += m_separator;
182 cmd += m_uboot_cmd;
184 if (fb.Transport(cmd, nullptr, 0))
185 return -1;
187 return 0;
190 int FBPartNumber::run(CmdCtx *ctx)
192 BulkTrans dev{m_timeout};
193 if (dev.open(ctx->m_dev))
194 return -1;
196 FastBoot fb(&dev);
198 string_ex cmd;
199 cmd.format("%s:%s:%08x", m_fb_cmd.c_str(), m_partition_name.c_str(), (uint32_t)m_Size);
201 if (fb.Transport(cmd, nullptr, 0))
202 return -1;
204 return 0;
207 int FBUpdateSuper::run(CmdCtx *ctx)
209 BulkTrans dev{m_timeout};
210 if (dev.open(ctx->m_dev))
211 return -1;
213 FastBoot fb(&dev);
215 string_ex cmd;
216 cmd.format("%s:%s:%s", m_fb_cmd.c_str(), m_partition_name.c_str(), m_opt.c_str());
218 if (fb.Transport(cmd, nullptr, 0))
219 return -1;
221 return 0;
224 int FBDownload::run(CmdCtx *ctx)
226 BulkTrans dev;
227 if (dev.open(ctx->m_dev))
228 return -1;
230 FastBoot fb(&dev);
232 shared_ptr<FileBuffer> buff = get_file_buffer(m_filename);
233 if (buff == nullptr)
234 return -1;
236 string_ex cmd;
237 cmd.format("download:%08x", buff->size());
239 if (fb.Transport(cmd, buff->data(), buff->size()))
240 return -1;
242 return 0;
245 int FBCopy::parser(char *p)
247 if (p)
248 m_cmd = p;
250 size_t pos = 0;
251 string s;
252 s = get_next_param(m_cmd, pos);
253 if (s.find(":") != s.npos)
254 s = get_next_param(m_cmd, pos);
256 if ((str_to_upper(s) != "UCP"))
258 string err = "Unknown command: ";
259 err += s;
260 set_last_err_string(s);
261 return -1;
264 string source;
265 string dest;
267 source = get_next_param(m_cmd, pos);
268 dest = get_next_param(m_cmd, pos);
270 if (source.empty())
272 set_last_err_string("ucp: source missed");
273 return -1;
276 if (dest.empty())
278 set_last_err_string("ucp: destination missed");
279 return -1;
282 if (source.find("T:") == 0 || source.find("t:") == 0)
284 if (dest.find("T:") == 0 || dest.find("t:") == 0)
286 set_last_err_string("ucp just support one is remote file start with t:");
287 return -1;
289 m_target_file = source.substr(2);
290 m_bDownload = false; //upload a file
291 m_local_file = dest;
293 else if (dest.find("T:") == 0 || dest.find("t:") == 0)
295 m_target_file = dest.substr(2);
296 m_bDownload = true;
297 m_local_file = source;
298 get_file_buffer(source, true);
300 else
302 set_last_err_string("ucp must a remote file name, start with t:<file name>");
303 return -1;
305 return 0;
308 int FBCopy::run(CmdCtx *ctx)
310 BulkTrans dev;
311 if (dev.open(ctx->m_dev))
312 return -1;
314 FastBoot fb(&dev);
315 string_ex cmd;
317 if(m_bDownload)
319 size_t i;
320 shared_ptr<FileBuffer> buff = get_file_buffer(m_local_file);
321 if (buff == nullptr)
323 return -1;
326 cmd.format("WOpen:%s", m_target_file.c_str());
327 if (fb.Transport(cmd, nullptr, 0))
329 if (fb.m_info == "DIR")
331 Path p;
332 p.append(m_local_file);
333 string target = m_target_file;
334 target += "/";
335 target += p.get_file_name();
337 cmd.format("WOpen:%s", target.c_str());
338 if (fb.Transport(cmd, nullptr, 0))
339 return -1;
341 else {
342 return -1;
346 uuu_notify nt;
347 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
348 nt.total = buff->size();
349 call_notify(nt);
351 for (i = 0; i < buff->size(); i += this->m_Maxsize_pre_cmd)
353 size_t sz = buff->size() - i;
354 if (sz > m_Maxsize_pre_cmd)
355 sz = m_Maxsize_pre_cmd;
357 cmd.format("donwload:%08X", sz);
358 if (fb.Transport(cmd, buff->data() + i, sz))
360 if (fb.m_info == "EPIPE")
361 set_last_err_string("pipe closed by target");
362 else
363 set_last_err_string("target return unknown error");
365 cmd.format("Close");
366 if (fb.Transport(cmd, nullptr, 0))
367 return -1;
369 return -1;
372 nt.type = uuu_notify::NOTIFY_TRANS_POS;
373 nt.index = i;
374 call_notify(nt);
377 nt.type = uuu_notify::NOTIFY_TRANS_POS;
378 nt.index = buff->size();
379 call_notify(nt);
381 else
383 cmd.format("ROpen:%s", m_target_file.c_str());
384 if (fb.Transport(cmd, nullptr, 0))
385 return -1;
387 uuu_notify nt;
388 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
389 size_t total = nt.total = strtoul(fb.m_info.c_str(), nullptr, 16);
390 call_notify(nt);
392 nt.index = 0;
393 ofstream of;
395 struct stat st;
397 Path localfile;
398 localfile.append(m_local_file);
400 if (stat(localfile.c_str(), &st) == 0)
402 if (st.st_mode & S_IFDIR)
404 localfile += "/";
405 Path t;
406 t.append(m_target_file);
407 localfile += t.get_file_name();
411 of.open(localfile, ofstream::binary);
413 if (!of)
415 string err;
416 err = "Fail to open file";
417 err += localfile;
418 set_last_err_string(err);
422 vector<uint8_t> data;
423 if (fb.Transport("upload", nullptr, 0, &data))
424 return -1;
426 of.write((const char*)data.data(), data.size());
428 nt.type = uuu_notify::NOTIFY_TRANS_POS;
429 nt.index += data.size();
430 call_notify(nt);
432 if (data.size() == 0)
433 break;
435 } while (nt.index < total || total == 0 ); // If total is 0, it is stream
437 nt.type = uuu_notify::NOTIFY_TRANS_POS;
438 call_notify(nt);
441 cmd.format("Close");
442 if (fb.Transport(cmd, nullptr, 0))
443 return -1;
445 return 0;
448 int FBFlashCmd::parser(char *p)
450 if (FBCmd::parser(p))
451 return -1;
453 string subcmd = m_uboot_cmd;
454 size_t pos = 0;
455 m_partition = get_next_param(subcmd, pos);
456 if (m_partition == "-raw2sparse")
458 m_raw2sparse = true;
459 m_partition = get_next_param(subcmd, pos);
461 else if (m_partition == "-S")
463 m_partition = get_next_param(subcmd, pos);
464 bool conversion_success = false;
465 m_sparse_limit = str_to_uint64(m_partition, &conversion_success);
466 if (!conversion_success)
468 set_last_err_string("FB: flash failed to parse size argument given to -S: "s + m_partition);
469 return -1;
471 m_partition = get_next_param(subcmd, pos);
474 if (pos == string::npos || m_partition.empty())
476 set_last_err_string("Missed partition name");
477 return -1;
479 m_filename = get_next_param(subcmd, pos);
480 if (m_filename.empty())
482 set_last_err_string("Missed file name");
483 return -1;
486 if (!check_file_exist(m_filename))
487 return -1;
489 return 0;
492 int FBFlashCmd::flash(FastBoot *fb, void * pdata, size_t sz)
494 string_ex cmd;
495 cmd.format("download:%08x", sz);
497 if (fb->Transport(cmd, pdata, sz))
498 return -1;
500 cmd.format("flash:%s", m_partition.c_str());
501 if (fb->Transport(cmd, nullptr, 0))
502 return -1;
504 return 0;
507 int FBFlashCmd::flash_raw2sparse(FastBoot *fb, shared_ptr<FileBuffer> pdata, size_t block_size, size_t max)
509 SparseFile sf;
511 vector<uint8_t> data;
513 if (max > m_sparse_limit)
514 max = m_sparse_limit;
516 sf.init_header(block_size, (max + block_size -1) / block_size);
518 data.resize(block_size);
520 uuu_notify nt;
521 bool bload = pdata->IsKnownSize();
523 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
524 if (bload)
525 nt.total = pdata->size();
526 else
527 nt.total = 0;
529 call_notify(nt);
532 size_t i = 0;
533 int r;
534 while (!(r=pdata->request_data(data, i*block_size, block_size)))
536 int ret = sf.push_one_block(data.data());
537 if (ret)
539 if (flash(fb, sf.m_data.data(), sf.m_data.size()))
540 return -1;
542 sf.init_header(block_size, (max + block_size - 1) / block_size);
544 chunk_header_t ct;
545 ct.chunk_type = CHUNK_TYPE_DONT_CARE;
546 ct.chunk_sz = i + 1;
547 ct.reserved1 = 0;
548 ct.total_sz = sizeof(ct);
550 sf.push_one_chuck(&ct, nullptr);
552 nt.type = uuu_notify::NOTIFY_TRANS_POS;
553 nt.total = i * block_size;
554 call_notify(nt);
557 i++;
559 if (bload != pdata->IsKnownSize())
561 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
562 nt.total = pdata->size();
563 call_notify(nt);
565 bload = pdata->IsKnownSize();
569 if (r == ERR_OUT_MEMORY)
570 return r;
572 if (flash(fb, sf.m_data.data(), sf.m_data.size()))
573 return -1;
575 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
576 nt.total = pdata->size();
577 call_notify(nt);
579 nt.type = uuu_notify::NOTIFY_TRANS_POS;
580 nt.total = pdata->size();
581 call_notify(nt);
583 return 0;
586 int FBFlashCmd::run(CmdCtx *ctx)
588 FBGetVar getvar((char*)"FB: getvar max-download-size");
589 if (getvar.parser(nullptr))
590 return -1;
591 if (getvar.run(ctx))
592 return -1;
594 size_t max = getvar.m_val.empty() ? m_sparse_limit : str_to_uint32(getvar.m_val);
596 BulkTrans dev{m_timeout};
597 if (dev.open(ctx->m_dev))
598 return -1;
600 FastBoot fb(&dev);
602 if (m_raw2sparse)
604 size_t block_size = 4096;
606 if (getvar.parser((char*)"FB: getvar logical-block-size"))
607 return -1;
608 if (!getvar.run(ctx))
609 block_size = str_to_uint32(getvar.m_val);
611 if (block_size == 0)
613 set_last_err_string("Device report block_size is 0");
614 return -1;
617 shared_ptr<FileBuffer> pdata = get_file_buffer(m_filename, true);
619 if (isffu(pdata))
621 string str;
622 str = "FB: getvar partition-size:";
623 str += m_partition;
625 if (getvar.parser((char*)str.c_str()))
626 return -1;
628 if (getvar.run(ctx))
629 return -1;
631 m_totalsize = str_to_uint64(getvar.m_val);
633 return flash_ffu(&fb, pdata);
636 return flash_raw2sparse(&fb, pdata, block_size, max);
639 shared_ptr<FileBuffer> pdata = get_file_buffer(m_filename, true);
640 if (pdata == nullptr)
641 return -1;
643 pdata->request_data(sizeof(sparse_header));
644 if (SparseFile::is_validate_sparse_file(pdata->data(), sizeof(sparse_header)))
645 { /* Limited max size to 16M for sparse file to avoid long timeout at read status*/
646 if (max > m_sparse_limit)
647 max = m_sparse_limit;
650 if (pdata->size() <= max)
652 pdata->request_data(pdata->size());
654 if (flash(&fb, pdata->data(), pdata->size()))
655 return -1;
657 else
659 size_t pos = 0;
660 pdata->request_data(sizeof(sparse_header));
661 sparse_header * pfile = (sparse_header *)pdata->data();
663 if (!SparseFile::is_validate_sparse_file(pdata->data(), sizeof(sparse_header)))
665 set_last_err_string("Sparse file magic miss matched");
666 return -1;
669 SparseFile sf;
670 size_t startblock;
671 chunk_header_t * pheader;
673 uuu_notify nt;
674 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
675 nt.total = pfile->total_blks;
676 call_notify(nt);
678 sf.init_header(pfile->blk_sz, max / pfile->blk_sz);
679 startblock = 0;
681 for(size_t nblk=0; nblk < pfile->total_chunks && pos <= pdata->size(); nblk++)
683 pdata->request_data(pos+sizeof(chunk_header_t)+sizeof(sparse_header));
684 size_t oldpos = pos;
685 pheader = SparseFile::get_next_chunk(pdata->data(), pos);
686 pdata->request_data(pos);
688 size_t sz = sf.push_one_chuck(pheader, pheader + 1);
689 if (sz == pheader->total_sz - sizeof(chunk_header_t))
691 startblock += pheader->chunk_sz;
693 else if (sz == 0)
695 //whole chuck have not push into data.
696 if (flash(&fb, sf.m_data.data(), sf.m_data.size()))
697 return -1;
699 sf.init_header(pfile->blk_sz, max / pfile->blk_sz);
701 chunk_header_t ct;
702 ct.chunk_type = CHUNK_TYPE_DONT_CARE;
703 ct.chunk_sz = startblock;
704 ct.reserved1 = 0;
705 ct.total_sz = sizeof(ct);
707 sz = sf.push_one_chuck(&ct, nullptr);
710 roll back pos to previous failure chunck and let it push again into new sparse file.
711 can't push it here because next chuck may big size chuck and need split as below else logic.
713 pos = oldpos;
714 nblk--;
716 uuu_notify nt;
717 nt.type = uuu_notify::NOTIFY_TRANS_POS;
718 nt.total = startblock;
719 call_notify(nt);
721 else
723 size_t off = ((uint8_t*)pheader) - pdata->data() + sz + sizeof(chunk_header_t);
724 startblock += sz / pfile->blk_sz;
728 if (flash(&fb, sf.m_data.data(), sf.m_data.size()))
729 return -1;
731 sf.init_header(pfile->blk_sz, max / pfile->blk_sz);
733 chunk_header_t ct;
734 ct.chunk_type = CHUNK_TYPE_DONT_CARE;
735 ct.chunk_sz = startblock;
736 ct.reserved1 = 0;
737 ct.total_sz = sizeof(ct);
739 sz = sf.push_one_chuck(&ct, nullptr);
741 sz = sf.push_raw_data(pdata->data() + off, pos - off);
742 off += sz;
743 startblock += sz / pfile->blk_sz;
745 uuu_notify nt;
746 nt.type = uuu_notify::NOTIFY_TRANS_POS;
747 nt.total = startblock;
748 call_notify(nt);
750 } while (off < pos);
754 //send last data
755 if (flash(&fb, sf.m_data.data(), sf.m_data.size()))
756 return -1;
758 sparse_header * pf = (sparse_header *)sf.m_data.data();
759 nt.type = uuu_notify::NOTIFY_TRANS_POS;
760 nt.total = startblock + pf->total_blks;
761 call_notify(nt);
763 return 0;
766 bool FBFlashCmd::isffu(shared_ptr<FileBuffer> p)
768 vector<uint8_t> data;
769 data.resize(sizeof(FFU_SECURITY_HEADER));
770 p->request_data(data, 0, sizeof(FFU_SECURITY_HEADER));
772 FFU_SECURITY_HEADER *h = (FFU_SECURITY_HEADER*)data.data();
773 if (strncmp((const char*)h->signature, FFU_SECURITY_SIGNATURE, sizeof(h->signature)) == 0)
774 return true;
775 else
776 return false;
779 int FBFlashCmd::flash_ffu_oneblk(FastBoot *fb, shared_ptr<FileBuffer> p, size_t off, size_t blksz, size_t blkindex)
781 SparseFile sf;
783 sf.init_header(blksz, 10);
785 p->request_data(off + blksz);
787 chunk_header_t ct;
788 ct.chunk_type = CHUNK_TYPE_DONT_CARE;
789 ct.chunk_sz = blkindex;
790 ct.reserved1 = 0;
791 ct.total_sz = sizeof(ct);
793 sf.push_one_chuck(&ct, nullptr);
795 if (sf.push_one_block(p->data() + off))
796 return -1;
798 return flash(fb, sf.m_data.data(), sf.m_data.size());
801 int FBFlashCmd::flash_ffu(FastBoot *fb, shared_ptr<FileBuffer> p)
803 p->request_data(sizeof(FFU_SECURITY_HEADER));
804 FFU_SECURITY_HEADER *h = (FFU_SECURITY_HEADER*)p->data();
805 if (strncmp((const char*)h->signature, FFU_SECURITY_SIGNATURE, sizeof(h->signature)) != 0)
807 set_last_err_string("Invalidate FFU Security header signature");
808 return -1;
811 size_t off;
812 off = h->dwCatalogSize + h->dwHashTableSize;
813 off = round_up(off, (size_t)h->dwChunkSizeInKb * 1024);
815 p->request_data(off + sizeof(FFU_IMAGE_HEADER));
816 FFU_IMAGE_HEADER *pIh = (FFU_IMAGE_HEADER *)(p->data() + off);
818 if (strncmp((const char*)pIh->Signature, FFU_SIGNATURE, sizeof(pIh->Signature)) != 0)
820 set_last_err_string("Invalidate FFU Security header signature");
821 return -1;
824 off += pIh->ManifestLength + pIh->cbSize;
825 off = round_up(off, (size_t)h->dwChunkSizeInKb * 1024);
827 p->request_data(off + sizeof(FFU_STORE_HEADER));
828 FFU_STORE_HEADER *pIs = (FFU_STORE_HEADER*) (p->data() + off);
830 if(pIs->MajorVersion == 1)
831 off += pIs->dwValidateDescriptorLength + offsetof(FFU_STORE_HEADER, NumOfStores);
832 else
833 off += pIs->dwValidateDescriptorLength + sizeof(FFU_STORE_HEADER);
835 p->request_data(off + pIs->dwWriteDescriptorLength);
837 size_t block_off = off + pIs->dwWriteDescriptorLength;
838 block_off = round_up(block_off, (size_t)h->dwChunkSizeInKb * 1024);
840 uuu_notify nt;
841 nt.type = uuu_notify::NOTIFY_TRANS_SIZE;
842 nt.total = pIs->dwWriteDescriptorCount;
843 call_notify(nt);
845 size_t currrent_block = 0;
846 size_t i;
847 for (i = 0; i < pIs->dwWriteDescriptorCount; i++)
849 FFU_BLOCK_DATA_ENTRY *entry = (FFU_BLOCK_DATA_ENTRY*)(p->data() + off);
851 off += sizeof(FFU_BLOCK_DATA_ENTRY) + (entry->dwLocationCount -1) * sizeof(_DISK_LOCATION);
853 if (currrent_block >= pIs->dwInitialTableIndex && currrent_block < pIs->dwInitialTableIndex + pIs->dwInitialTableCount)
855 //Skip Init Block
857 else
859 for (uint32_t loc = 0; loc < entry->dwLocationCount; loc++)
861 //printf("block 0x%x write to 0x%x seek %d\n", currrent_block, entry->rgDiskLocations[loc].dwBlockIndex, entry->rgDiskLocations[loc].dwDiskAccessMethod);
862 uint32_t access = entry->rgDiskLocations[loc].dwDiskAccessMethod;
863 uint32_t blockindex;
864 if (entry->rgDiskLocations[loc].dwDiskAccessMethod == DISK_BEGIN)
865 blockindex = entry->rgDiskLocations[loc].dwBlockIndex;
866 else
867 blockindex = m_totalsize / pIs->dwBlockSizeInBytes - 1 - entry->rgDiskLocations[loc].dwBlockIndex;
869 for (uint32_t blk = 0; blk < entry->dwBlockCount; blk++)
871 if (flash_ffu_oneblk(fb,
873 block_off + (currrent_block + blk) * pIs->dwBlockSizeInBytes,
874 pIs->dwBlockSizeInBytes,
875 blockindex + blk))
876 return -1;
881 nt.type = uuu_notify::NOTIFY_TRANS_POS;
882 nt.total = i;
883 call_notify(nt);
885 currrent_block += entry->dwBlockCount;
888 nt.type = uuu_notify::NOTIFY_TRANS_POS;
889 nt.total = i;
890 call_notify(nt);
892 return 0;