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.
35 #include "hidreport.h"
46 int SDPCmdBase::check_ack(HIDReport
*report
, uint32_t ack
)
48 if (get_hab_type(report
) == HabUnknown
)
52 if (get_status(report
, status
, 4))
57 set_last_err_string("Status Miss matched");
63 SDPCmdBase::HAB_t
SDPCmdBase::get_hab_type(HIDReport
*report
)
66 if (get_status(report
, status
, 3))
69 if (status
== HabEnabled
)
72 if (status
== HabDisabled
)
75 set_last_err_string("unknown hab type");
79 int SDPCmdBase::get_status(HIDReport
*p
, uint32_t &status
, uint8_t report_id
)
82 m_input
[0] = report_id
;
83 int ret
= p
->read(m_input
);
87 if (m_input
.size() < (1 + sizeof(uint32_t)))
89 set_last_err_string("HID report size is too small");
93 status
= *(uint32_t*)(m_input
.data() + 1);
97 int SDPCmdBase::init_cmd()
99 memset(&m_spdcmd
, 0, sizeof(m_spdcmd
));
100 insert_param_info("-scanlimited", &m_scan_limited
, Param::Type::e_uint64
);
104 IvtHeader
*SDPCmdBase::search_ivt_header(shared_ptr
<DataBuffer
> data
, size_t &off
, size_t limit
)
106 if (limit
>= data
->size())
107 limit
= data
->size();
109 for (; off
< limit
; off
+= 0x4)
111 IvtHeader
*p
= (IvtHeader
*)(data
->data() + off
);
112 if (p
->IvtBarker
== IVT_BARKER_HEADER
)
114 if (p
->IvtBarker
== IVT_BARKER2_HEADER
)
116 BootData
*pDB
= (BootData
*) &(data
->at(off
+ p
->BootData
- p
->SelfAddr
));
118 /*Skip HDMI firmware for i.MX8MQ*/
119 if (pDB
->PluginFlag
& 0xFFFFFFFE)
128 int SDPCmdBase::send_cmd(HIDReport
*p
)
130 return p
->write(&m_spdcmd
, sizeof(m_spdcmd
), 1);
133 SDPDcdCmd::SDPDcdCmd(char *p
) : SDPCmdBase(p
)
135 insert_param_info("dcd", nullptr, Param::Type::e_null
);
136 insert_param_info("-f", &m_filename
, Param::Type::e_string_filename
);
137 insert_param_info("-dcdaddr", &m_dcd_addr
, Param::Type::e_uint32
);
141 int SDPDcdCmd::run(CmdCtx
*ctx
)
143 const ROM_INFO
* rom
= search_rom_info(ctx
->m_config_item
);
147 err
.format("%s:%d can't get rom info", __FUNCTION__
, __LINE__
);
148 set_last_err_string(err
);
153 shared_ptr
<FileBuffer
> p
= get_file_buffer(m_filename
, true);
158 shared_ptr
<DataBuffer
> buff
;
159 buff
= p
->request_data(0, m_scan_limited
);
160 if (!buff
) return -1;
163 IvtHeader
*pIVT
= search_ivt_header(buff
, off
);
169 if (pIVT
->DCDAddress
== 0)
172 uint8_t * pdcd
= &(buff
->at(off
+ pIVT
->DCDAddress
- pIVT
->SelfAddr
));
174 if (pdcd
[0] != HAB_TAG_DCD
)
177 err
.format("%s:%d DCD TAG miss matched", __FUNCTION__
, __LINE__
);
178 set_last_err_string(err
);
182 uint32_t size
= (pdcd
[1] << 8) | pdcd
[2];
184 if (size
>= m_scan_limited
)
186 set_last_err_string("dcd bigger than 8M");
190 // point maybe change after new requisition buffer.
191 pdcd
= &(buff
->at(off
+ pIVT
->DCDAddress
- pIVT
->SelfAddr
));
193 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_DCD_WRITE
;
194 m_spdcmd
.m_addr
= EndianSwap(m_dcd_addr
? m_dcd_addr
: rom
->free_addr
);
195 m_spdcmd
.m_count
= EndianSwap(size
);
197 HIDTrans
dev(m_timeout
);
198 if (dev
.open(ctx
->m_dev
))
201 HIDReport
report(&dev
);
202 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
205 if (report
.write(pdcd
, size
, 2))
208 if (check_ack(&report
, ROM_WRITE_ACK
))
214 SDPSkipDCDCmd::SDPSkipDCDCmd(char *p
) : SDPCmdBase(p
)
216 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_SKIP_DCD_HEADER
;
219 int SDPSkipDCDCmd::run(CmdCtx
*ctx
)
221 HIDTrans
dev(m_timeout
);
222 if (dev
.open(ctx
->m_dev
))
225 HIDReport
report(&dev
);
226 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
229 if (check_ack(&report
, ROM_OK_ACK
))
235 SDPBootCmd::SDPBootCmd(char *p
) : SDPCmdBase(p
)
237 insert_param_info("boot", nullptr, Param::Type::e_null
);
238 insert_param_info("-f", &m_filename
, Param::Type::e_string_filename
);
239 insert_param_info("-nojump", &m_nojump
, Param::Type::e_bool
);
240 insert_param_info("-cleardcd", &m_clear_dcd
, Param::Type::e_bool
);
241 insert_param_info("-dcdaddr", &m_dcd_addr
, Param::Type::e_uint32
);
242 insert_param_info("-scanlimited", &m_scan_limited
, Param::Type::e_uint64
);
243 insert_param_info("-barebox", &m_barebox
, Param::Type::e_bool
);
246 # define BAREBOX_MAGIC_OFFSET 0x20
248 bool SDPBootCmd::is_barebox_img(void)
250 shared_ptr
<FileBuffer
> fbuf
= get_file_buffer(m_filename
, true);
254 string
barebox_magic ("barebox");
256 shared_ptr
<DataBuffer
> dbuf
= fbuf
->request_data(0, BAREBOX_MAGIC_OFFSET
+ barebox_magic
.length());
260 string
img ((const char *)&dbuf
->at(BAREBOX_MAGIC_OFFSET
), barebox_magic
.length());
262 return img
.compare(barebox_magic
) == 0 ? true : false;
265 int SDPBootCmd::load_barebox(CmdCtx
*ctx
)
267 const ROM_INFO
*rom
= search_rom_info(ctx
->m_config_item
);
272 // The barebox USB loading mechanism differs between SoCs due to SRAM
275 // E.g. all i.MX8M SoCs require a two stage loading, first the
276 // pre-bootloader (PBL) is loaded to the internal SRAM and started. The
277 // PBL intialize the DDR and uses the BootROM initialized USB
278 // controller to load the remaining "full barebox image" to the DDR.
280 // On i.MX6 devices this is not the case since the DDR setup is done
281 // via the DCD and we can load the image directly to the DDR.
283 // The ROM_INFO_NEED_BAREBOX_FULL_IMAGE flag indicates if the two-stage
284 // load mechanism is required for a specific SoC. So the user can
285 // always specify '-barebox' no matter if it's required or not:
287 // SDP: boot -barebox -f <barebox.img>
288 if (!(rom
->flags
& ROM_INFO_NEED_BAREBOX_FULL_IMAGE
))
292 str
= "SDP: write -f ";
295 str
+= " -barebox-bl33";
297 SDPWriteCmd
wr((char *)str
.c_str());
298 if (wr
.parser()) return -1;
303 int SDPBootCmd::run(CmdCtx
*ctx
)
306 str
= "SDP: dcd -f ";
310 str
+= std::to_string(m_dcd_addr
);
313 if (m_scan_limited
!= UINT64_MAX
)
315 str
+= " -scanlimited ";
316 str
+= std::to_string(m_scan_limited
);
319 SDPDcdCmd
dcd((char *)str
.c_str());
321 if (m_scan_limited
!= UINT64_MAX
)
323 str
+= " -scanlimited ";
324 str
+= std::to_string(m_scan_limited
);
327 if (dcd
.parser()) return -1;
328 if (dcd
.run(ctx
)) return -1;
330 str
= "SDP: write -f ";
334 if (m_scan_limited
!= UINT64_MAX
)
336 str
+= " -scanlimited ";
337 str
+= std::to_string(m_scan_limited
);
340 SDPWriteCmd
wr((char *)str
.c_str());
341 if (wr
.parser()) return -1;
342 if (wr
.run(ctx
)) return -1;
344 str
= "SDP: jump -f ";
350 if (m_scan_limited
!= UINT64_MAX
)
352 str
+= " -scanlimited ";
353 str
+= std::to_string(m_scan_limited
);
356 SDPJumpCmd
jmp((char *)str
.c_str());
359 if (jmp
.parser()) return -1;
360 if (jmp
.run(ctx
)) return -1;
363 if (m_barebox
|| is_barebox_img())
365 if (load_barebox(ctx
)) return -1;
368 SDPBootlogCmd
log(nullptr);
374 SDPStatusCmd::SDPStatusCmd(char *p
) : SDPCmdBase(p
)
376 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_ERROR_STATUS
;
377 insert_param_info("status", nullptr, Param::Type::e_null
);
380 int SDPStatusCmd::run(CmdCtx
*ctx
)
382 HIDTrans
dev(m_timeout
);
383 if (dev
.open(ctx
->m_dev
))
386 HIDReport
report(&dev
);
387 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
390 if (get_hab_type(&report
) == HabUnknown
)
394 if (get_status(&report
, status
, 4))
400 SDPWriteCmd::SDPWriteCmd(char *p
) : SDPCmdBase(p
)
402 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_WR_FILE
;
405 m_max_download_pre_cmd
= 0x200000;
407 m_bIvtReserve
= false;
411 m_barebox_bl33
= false;
413 insert_param_info("write", nullptr, Param::Type::e_null
);
414 insert_param_info("-f", &m_filename
, Param::Type::e_string_filename
);
415 insert_param_info("-ivt", &m_Ivt
, Param::Type::e_uint32
);
416 insert_param_info("-addr", &m_download_addr
, Param::Type::e_uint32
);
417 insert_param_info("-barebox-bl33", &m_barebox_bl33
, Param::Type::e_bool
);
418 insert_param_info("-offset", &m_offset
, Param::Type::e_uint32
);
419 insert_param_info("-skipspl", &m_bskipspl
, Param::Type::e_bool
);
420 insert_param_info("-skipfhdr", &m_bskipfhdr
, Param::Type::e_bool
);
421 insert_param_info("-scanterm", &m_bscanterm
, Param::Type::e_bool
);
424 int SDPWriteCmd::run(CmdCtx
*ctx
)
429 bool validate_run
= true;
431 shared_ptr
<FileBuffer
> p1
= get_file_buffer(m_filename
, true);
436 shared_ptr
<DataBuffer
> fbuff
;
438 fbuff
= p1
->request_data(0, m_scan_limited
);
439 if (!fbuff
) return -1;
443 pbuff
= fbuff
->data();
444 size
= fbuff
->size();
449 offset
+= GetFlashHeaderSize(fbuff
, offset
);
451 size_t pos
= 0, length
;
456 length
= ScanTerm(fbuff
, pos
);
459 set_last_err_string("This wic have NOT terminate tag after bootloader, please use new yocto");
463 offset
= pos
- length
;
466 set_last_err_string("This wic boot length is wrong");
474 const ROM_INFO
* rom
= search_rom_info(ctx
->m_config_item
);
475 if(! (rom
->flags
& ROM_INFO_AUTO_SCAN_UBOOT_POS
))
477 set_last_err_string("SPL doesn't support auto scan uboot position");
482 IvtHeader
*pIvt
= search_ivt_header(fbuff
, off
, 0x100000);
487 BootData
*pDB
= (BootData
*) &(fbuff
->at(off
+ pIvt
->BootData
- pIvt
->SelfAddr
));
488 offset
= off
+ pDB
->ImageSize
- (pIvt
->SelfAddr
- pDB
->ImageStartAddr
);
493 offset
+= GetContainerActualSize(fbuff
, offset
, rom
->flags
& ROM_INFO_HID_ROMAPI
, m_bskipspl
);
496 if (size_t(offset
) >= fbuff
->size())
498 set_last_err_string("Unknown Image type, can't use skipspl format");
508 IvtHeader
*pIvt
= search_ivt_header(fbuff
, off
);
509 for (int i
= 0; i
< m_Ivt
; i
++)
511 off
+= sizeof(IvtHeader
);
512 pIvt
= search_ivt_header(fbuff
, off
, m_scan_limited
);
516 set_last_err_string("Cannot find valid IVT header");
520 BootData
*pDB
= (BootData
*) &(fbuff
->at(off
+ pIvt
->BootData
- pIvt
->SelfAddr
));
522 m_download_addr
= pIvt
->SelfAddr
;
523 //size = fbuff->size() - off;
524 size
= pDB
->ImageSize
- (pIvt
->SelfAddr
- pDB
->ImageStartAddr
);
526 if (size
>= m_scan_limited
)
528 set_last_err_string("TODO: image is too big");
532 //ImageSize may be bigger than Imagesize because ImageSize include IVT offset
533 //Difference boot storage have difference IVT offset.
534 if (size
> fbuff
->size() - off
)
535 size
= fbuff
->size() - off
;
537 if (m_barebox_bl33
) {
538 if (pIvt
->IvtBarker
!= IVT_BARKER_HEADER
) {
539 set_last_err_string("Barebox BL33 loading is only support for IVT Header V2");
542 offset
= pIvt
->ImageStartAddr
- pIvt
->SelfAddr
;
543 size
= fbuff
->size() - off
- offset
;
546 // Barebox does start as soon as the bl33 was loaded
547 // and the check_ack() fails
548 validate_run
= false;
551 pbuff
= (uint8_t*)pIvt
;
553 return run(ctx
, pbuff
+ offset
, size
, m_download_addr
, validate_run
);
556 int SDPWriteCmd::run(CmdCtx
*ctx
, void *pbuff
, size_t size
, uint32_t addr
, bool validate
)
558 HIDTrans
dev(m_timeout
);
559 if (dev
.open(ctx
->m_dev
))
562 HIDReport
report(&dev
);
564 report
.set_notify_total(size
);
566 const ROM_INFO
* rom
= search_rom_info(ctx
->m_config_item
);
568 size_t max
= m_max_download_pre_cmd
;
570 /* SPL needn't split transfer */
571 if (rom
&& (rom
->flags
& ROM_INFO_HID_SDP_NO_MAX_PER_TRANS
))
574 for (size_t i
=0; i
< size
; i
+= max
)
581 m_spdcmd
.m_addr
= EndianSwap((uint32_t)(addr
+ i
)); // force use 32bit endian swap function;
582 m_spdcmd
.m_count
= EndianSwap((uint32_t)sz
); //force use 32bit endian swap function;
584 report
.set_position_base(i
);
585 report
.set_skip_notify(true);
587 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
590 report
.set_skip_notify(false);
592 if (report
.write(((uint8_t*)pbuff
)+i
, sz
, 2))
595 if (validate
&& check_ack(&report
, ROM_STATUS_ACK
))
602 SDPReadMemCmd::SDPReadMemCmd(char *p
) : SDPCmdBase(p
)
604 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_RD_MEM
;
606 insert_param_info("rdmem", nullptr, Param::Type::e_null
);
607 insert_param_info("-addr", &m_mem_addr
, Param::Type::e_uint32
);
608 insert_param_info("-format", &m_mem_format
, Param::Type::e_uint32
);
611 int SDPReadMemCmd::run(CmdCtx
*ctx
)
613 HIDTrans
dev(m_timeout
);
614 if (dev
.open(ctx
->m_dev
))
617 HIDReport
report(&dev
);
619 printf("\nReading address 0x%08X ...\n", m_mem_addr
);
620 m_spdcmd
.m_addr
= EndianSwap(m_mem_addr
);
621 m_spdcmd
.m_format
= m_mem_format
;
622 switch (m_mem_format
) {
624 m_spdcmd
.m_count
= EndianSwap((uint32_t)0x1);
627 m_spdcmd
.m_count
= EndianSwap((uint32_t)0x2);
630 m_spdcmd
.m_count
= EndianSwap((uint32_t)0x4);
633 set_last_err_string("Invalid format, use <8|16|32>");
638 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
641 if (get_hab_type(&report
) == HabUnknown
)
645 if (get_status(&report
, mem_value
, 4) == 0)
647 printf("\nValue of address 0x%08X: ", m_mem_addr
);
648 switch (m_mem_format
) {
650 printf("0x%02X\n", mem_value
& 0xff);
653 printf("0x%04X\n", mem_value
& 0xffff);
656 printf("0x%08X\n", mem_value
);
659 set_last_err_string("Invalid format, use <8|16|32>");
667 SDPWriteMemCmd::SDPWriteMemCmd(char *p
) : SDPCmdBase(p
)
669 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_WR_MEM
;
671 insert_param_info("wrmem", nullptr, Param::Type::e_null
);
672 insert_param_info("-addr", &m_mem_addr
, Param::Type::e_uint32
);
673 insert_param_info("-format", &m_mem_format
, Param::Type::e_uint32
);
674 insert_param_info("-value", &m_mem_value
, Param::Type::e_uint32
);
677 int SDPWriteMemCmd::run(CmdCtx
*ctx
)
679 HIDTrans
dev(m_timeout
);
680 if (dev
.open(ctx
->m_dev
))
683 HIDReport
report(&dev
);
685 printf("\nWriting 0x%08X to address 0x%08X ...\n", m_mem_value
, m_mem_addr
);
686 m_spdcmd
.m_addr
= EndianSwap(m_mem_addr
);
687 m_spdcmd
.m_format
= m_mem_format
;
688 switch (m_mem_format
) {
690 m_spdcmd
.m_count
= EndianSwap((uint32_t)0x1);
693 m_spdcmd
.m_count
= EndianSwap((uint32_t)0x2);
696 m_spdcmd
.m_count
= EndianSwap((uint32_t)0x4);
699 set_last_err_string("Invalid format, use <8|16|32>");
703 m_spdcmd
.m_data
= EndianSwap(m_mem_value
);
705 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
708 if (get_hab_type(&report
) == HabUnknown
)
713 if (get_status(&report
, status
, 4) < 0 || status
!= ROM_WRITE_ACK
) {
716 err
.format("%s:%d Failed to write to address 0x%X",
717 __FUNCTION__
, __LINE__
, m_mem_addr
);
718 set_last_err_string(err
);
724 SDPJumpCmd::SDPJumpCmd(char *p
) : SDPCmdBase(p
)
726 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_JUMP_ADDR
;
727 insert_param_info("jump", nullptr, Param::Type::e_null
);
728 insert_param_info("-f", &m_filename
, Param::Type::e_string_filename
);
729 insert_param_info("-ivt", &m_Ivt
, Param::Type::e_uint32
);
730 insert_param_info("-plugin", &m_PlugIn
, Param::Type::e_bool
);
731 insert_param_info("-addr", &m_jump_addr
, Param::Type::e_uint32
);
732 insert_param_info("-cleardcd", &m_clear_dcd
, Param::Type::e_bool
);
735 int SDPJumpCmd::run(CmdCtx
*ctx
)
737 const ROM_INFO
* rom
= search_rom_info(ctx
->m_config_item
);
739 HIDTrans
dev(m_timeout
);
740 if (dev
.open(ctx
->m_dev
))
743 HIDReport
report(&dev
);
748 err
.format("%s:%d can't get rom info", __FUNCTION__
, __LINE__
);
749 set_last_err_string(err
);
753 if (rom
->flags
& ROM_INFO_SPL_JUMP
)
755 m_spdcmd
.m_addr
= EndianSwap(m_jump_addr
);
756 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
759 //Omit last return value.
760 check_ack(&report
, ROM_OK_ACK
);
764 shared_ptr
<FileBuffer
> p1
= get_file_buffer(m_filename
, true);
768 shared_ptr
<DataBuffer
> buff
;
769 buff
= p1
->request_data(0, m_scan_limited
);
770 if (!buff
) return -1;
773 IvtHeader
*pIVT
= search_ivt_header(buff
, off
, m_scan_limited
);
775 for (int i
= 0; i
< m_Ivt
; i
++)
777 off
+= sizeof(IvtHeader
);
778 pIVT
= search_ivt_header(buff
, off
);
783 set_last_err_string("Cannot find valid IVT header");
787 m_spdcmd
.m_addr
= EndianSwap(pIVT
->SelfAddr
);
790 if (rom
->flags
& ROM_INFO_HID_SKIP_DCD
&& !m_clear_dcd
)
792 SDPSkipDCDCmd
skipcmd(nullptr);
793 if (skipcmd
.run(ctx
))
799 /* Need send out whole report size buffer avoid overwrite other data
800 * Some platform require receive whole package for report id = 2
802 ivt
.resize(report
.get_out_package_size());
804 size_t sz
= buff
->size();
805 sz
-= (uint8_t*)pIVT
- (uint8_t*)buff
->data();
810 memcpy(ivt
.data(), pIVT
, sz
);
812 IvtHeader
*header
= (IvtHeader
*)ivt
.data();
813 header
->DCDAddress
= 0;
815 SDPWriteCmd
writecmd(nullptr);
816 if(writecmd
.run(ctx
, header
, ivt
.size(), pIVT
->SelfAddr
))
820 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
823 //Omit last return value.
824 check_ack(&report
, ROM_OK_ACK
);
829 SDPBootlogCmd::SDPBootlogCmd(char *p
) : SDPCmdBase(p
)
831 insert_param_info("blog", nullptr, Param::Type::e_null
);
834 int SDPBootlogCmd::run(CmdCtx
*ctx
)
838 if (dev
.open(ctx
->m_dev
))
841 HIDReport
report(&dev
);
843 vector
<uint8_t> v(65);
847 nt
.type
= uuu_notify::NOTIFY_CMD_INFO
;
852 ret
= report
.read(v
);
857 nt
.str
= (char*)(v
.data() + 4);