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.
34 #include "hidreport.h"
45 int SDPCmdBase::check_ack(HIDReport
*report
, uint32_t ack
)
47 if (get_hab_type(report
) == HabUnknown
)
51 if (get_status(report
, status
, 4))
56 set_last_err_string("Status Miss matched");
62 SDPCmdBase::HAB_t
SDPCmdBase::get_hab_type(HIDReport
*report
)
65 if (get_status(report
, status
, 3))
68 if (status
== HabEnabled
)
71 if (status
== HabDisabled
)
74 set_last_err_string("unknown hab type");
78 int SDPCmdBase::get_status(HIDReport
*p
, uint32_t &status
, uint8_t report_id
)
81 m_input
[0] = report_id
;
82 int ret
= p
->read(m_input
);
86 if (m_input
.size() < (1 + sizeof(uint32_t)))
88 set_last_err_string("HID report size is too small");
92 status
= *(uint32_t*)(m_input
.data() + 1);
96 int SDPCmdBase::init_cmd()
98 memset(&m_spdcmd
, 0, sizeof(m_spdcmd
)); return 0;
101 IvtHeader
*SDPCmdBase::search_ivt_header(shared_ptr
<FileBuffer
> data
, size_t &off
, size_t limit
)
103 if (limit
>= data
->m_avaible_size
)
104 limit
= data
->m_avaible_size
;
106 for (; off
< limit
; off
+= 0x4)
108 IvtHeader
*p
= (IvtHeader
*)(data
->data() + off
);
109 if (p
->IvtBarker
== IVT_BARKER_HEADER
)
111 if (p
->IvtBarker
== IVT_BARKER2_HEADER
)
113 BootData
*pDB
= (BootData
*) &(data
->at(off
+ p
->BootData
- p
->SelfAddr
));
115 /*Skip HDMI firmware for i.MX8MQ*/
116 if (pDB
->PluginFlag
& 0xFFFFFFFE)
125 int SDPCmdBase::send_cmd(HIDReport
*p
)
127 return p
->write(&m_spdcmd
, sizeof(m_spdcmd
), 1);
130 SDPDcdCmd::SDPDcdCmd(char *p
) : SDPCmdBase(p
)
132 insert_param_info("dcd", nullptr, Param::Type::e_null
);
133 insert_param_info("-f", &m_filename
, Param::Type::e_string_filename
);
134 insert_param_info("-dcdaddr", &m_dcd_addr
, Param::Type::e_uint32
);
138 int SDPDcdCmd::run(CmdCtx
*ctx
)
140 const ROM_INFO
* rom
= search_rom_info(ctx
->m_config_item
);
144 err
.format("%s:%d can't get rom info", __FUNCTION__
, __LINE__
);
145 set_last_err_string(err
);
150 shared_ptr
<FileBuffer
> buff
= get_file_buffer(m_filename
, false);
152 buff
->request_data(WIC_BOOTPART_SIZE
);
155 IvtHeader
*pIVT
= search_ivt_header(buff
, off
);
161 if (pIVT
->DCDAddress
== 0)
164 uint8_t * pdcd
= &(buff
->at(off
+ pIVT
->DCDAddress
- pIVT
->SelfAddr
));
166 if (pdcd
[0] != HAB_TAG_DCD
)
169 err
.format("%s:%d DCD TAG miss matched", __FUNCTION__
, __LINE__
);
170 set_last_err_string(err
);
174 uint32_t size
= (pdcd
[1] << 8) | pdcd
[2];
176 buff
->request_data(off
+ size
);
178 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_DCD_WRITE
;
179 m_spdcmd
.m_addr
= EndianSwap(m_dcd_addr
? m_dcd_addr
: rom
->free_addr
);
180 m_spdcmd
.m_count
= EndianSwap(size
);
183 if (dev
.open(ctx
->m_dev
))
186 HIDReport
report(&dev
);
187 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
190 if (report
.write(pdcd
, size
, 2))
193 if (check_ack(&report
, ROM_WRITE_ACK
))
199 SDPSkipDCDCmd::SDPSkipDCDCmd(char *p
) : SDPCmdBase(p
)
201 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_SKIP_DCD_HEADER
;
204 int SDPSkipDCDCmd::run(CmdCtx
*ctx
)
207 if (dev
.open(ctx
->m_dev
))
210 HIDReport
report(&dev
);
211 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
214 if (check_ack(&report
, ROM_OK_ACK
))
220 SDPBootCmd::SDPBootCmd(char *p
) : SDPCmdBase(p
)
222 insert_param_info("boot", nullptr, Param::Type::e_null
);
223 insert_param_info("-f", &m_filename
, Param::Type::e_string_filename
);
224 insert_param_info("-nojump", &m_nojump
, Param::Type::e_bool
);
225 insert_param_info("-cleardcd", &m_clear_dcd
, Param::Type::e_bool
);
226 insert_param_info("-dcdaddr", &m_dcd_addr
, Param::Type::e_uint32
);
229 int SDPBootCmd::run(CmdCtx
*ctx
)
232 str
= "SDP: dcd -f ";
236 str
+= std::to_string(m_dcd_addr
);
238 SDPDcdCmd
dcd((char *)str
.c_str());
239 if (dcd
.parser()) return -1;
240 if (dcd
.run(ctx
)) return -1;
242 str
= "SDP: write -f ";
245 SDPWriteCmd
wr((char *)str
.c_str());
246 if (wr
.parser()) return -1;
247 if (wr
.run(ctx
)) return -1;
249 str
= "SDP: jump -f ";
255 SDPJumpCmd
jmp((char *)str
.c_str());
258 if (jmp
.parser()) return -1;
259 if (jmp
.run(ctx
)) return -1;
262 SDPBootlogCmd
log(nullptr);
268 SDPStatusCmd::SDPStatusCmd(char *p
) : SDPCmdBase(p
)
270 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_ERROR_STATUS
;
271 insert_param_info("status", nullptr, Param::Type::e_null
);
274 int SDPStatusCmd::run(CmdCtx
*ctx
)
277 if (dev
.open(ctx
->m_dev
))
280 HIDReport
report(&dev
);
281 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
284 if (get_hab_type(&report
) == HabUnknown
)
288 if (get_status(&report
, status
, 4))
294 SDPWriteCmd::SDPWriteCmd(char *p
) : SDPCmdBase(p
)
296 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_WR_FILE
;
299 m_max_download_pre_cmd
= 0x200000;
301 m_bIvtReserve
= false;
306 insert_param_info("write", nullptr, Param::Type::e_null
);
307 insert_param_info("-f", &m_filename
, Param::Type::e_string_filename
);
308 insert_param_info("-ivt", &m_Ivt
, Param::Type::e_uint32
);
309 insert_param_info("-addr", &m_download_addr
, Param::Type::e_uint32
);
310 insert_param_info("-offset", &m_offset
, Param::Type::e_uint32
);
311 insert_param_info("-skipspl", &m_bskipspl
, Param::Type::e_bool
);
312 insert_param_info("-skipfhdr", &m_bskipfhdr
, Param::Type::e_bool
);
313 insert_param_info("-scanterm", &m_bscanterm
, Param::Type::e_bool
);
316 int SDPWriteCmd::run(CmdCtx
*ctx
)
322 shared_ptr
<FileBuffer
> fbuff
= get_file_buffer(m_filename
, false);
324 if (fbuff
== nullptr)
327 fbuff
->request_data(WIC_BOOTPART_SIZE
);
331 pbuff
= fbuff
->data();
332 size
= fbuff
->size();
337 offset
+= GetFlashHeaderSize(fbuff
, offset
);
339 size_t pos
= 0, length
;
344 length
= ScanTerm(fbuff
, pos
);
347 set_last_err_string("This wic have NOT terminate tag after bootloader, please use new yocto");
351 offset
= pos
- length
;
354 set_last_err_string("This wic boot length is wrong");
362 const ROM_INFO
* rom
= search_rom_info(ctx
->m_config_item
);
363 if(! (rom
->flags
& ROM_INFO_AUTO_SCAN_UBOOT_POS
))
365 set_last_err_string("SPL doesn't support auto scan uboot position");
370 IvtHeader
*pIvt
= search_ivt_header(fbuff
, off
, 0x100000);
373 BootData
*pDB
= (BootData
*) &(fbuff
->at(off
+ pIvt
->BootData
- pIvt
->SelfAddr
));
374 offset
= off
+ pDB
->ImageSize
- (pIvt
->SelfAddr
- pDB
->ImageStartAddr
);
378 offset
+= GetContainerActualSize(fbuff
, offset
);
381 fbuff
->request_data(offset
);
383 if (offset
>= fbuff
->m_avaible_size
)
385 set_last_err_string("Unknown Image type, can't use skipspl format");
395 IvtHeader
*pIvt
= search_ivt_header(fbuff
, off
);
396 for (int i
= 0; i
< m_Ivt
; i
++)
398 off
+= sizeof(IvtHeader
);
399 pIvt
= search_ivt_header(fbuff
, off
);
403 set_last_err_string("Cannot find valid IVT header");
407 BootData
*pDB
= (BootData
*) &(fbuff
->at(off
+ pIvt
->BootData
- pIvt
->SelfAddr
));
409 m_download_addr
= pIvt
->SelfAddr
;
410 //size = fbuff->size() - off;
411 size
= pDB
->ImageSize
- (pIvt
->SelfAddr
- pDB
->ImageStartAddr
);
413 fbuff
->request_data(size
);
415 //ImageSize may be bigger than Imagesize because ImageSize include IVT offset
416 //Difference boot storage have difference IVT offset.
417 if (size
> fbuff
->size() - off
)
418 size
= fbuff
->size() - off
;
420 pbuff
= (uint8_t*)pIvt
;
422 return run(ctx
, pbuff
+ offset
, size
, m_download_addr
);
425 int SDPWriteCmd::run(CmdCtx
*ctx
, void *pbuff
, size_t size
, uint32_t addr
)
428 if (dev
.open(ctx
->m_dev
))
431 HIDReport
report(&dev
);
433 report
.set_notify_total(size
);
435 const ROM_INFO
* rom
= search_rom_info(ctx
->m_config_item
);
437 size_t max
= m_max_download_pre_cmd
;
439 /* SPL needn't split transfer */
440 if (rom
&& (rom
->flags
& ROM_INFO_HID_SDP_NO_MAX_PER_TRANS
))
443 for (size_t i
=0; i
< size
; i
+= max
)
450 m_spdcmd
.m_addr
= EndianSwap((uint32_t)(addr
+ i
)); // force use 32bit endian swap function;
451 m_spdcmd
.m_count
= EndianSwap((uint32_t)sz
); //force use 32bit endian swap function;
453 report
.set_position_base(i
);
454 report
.set_skip_notify(true);
456 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
459 report
.set_skip_notify(false);
461 if (report
.write(((uint8_t*)pbuff
)+i
, sz
, 2))
464 if (check_ack(&report
, ROM_STATUS_ACK
))
471 SDPReadMemCmd::SDPReadMemCmd(char *p
) : SDPCmdBase(p
)
473 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_RD_MEM
;
475 insert_param_info("rdmem", nullptr, Param::Type::e_null
);
476 insert_param_info("-addr", &m_mem_addr
, Param::Type::e_uint32
);
477 insert_param_info("-format", &m_mem_format
, Param::Type::e_uint32
);
480 int SDPReadMemCmd::run(CmdCtx
*ctx
)
483 if (dev
.open(ctx
->m_dev
))
486 HIDReport
report(&dev
);
488 printf("\nReading address 0x%08X ...\n", m_mem_addr
);
489 m_spdcmd
.m_addr
= EndianSwap(m_mem_addr
);
490 m_spdcmd
.m_format
= m_mem_format
;
491 switch (m_mem_format
) {
493 m_spdcmd
.m_count
= EndianSwap((uint32_t)0x1);
496 m_spdcmd
.m_count
= EndianSwap((uint32_t)0x2);
499 m_spdcmd
.m_count
= EndianSwap((uint32_t)0x4);
502 set_last_err_string("Invalid format, use <8|16|32>");
507 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
510 if (get_hab_type(&report
) == HabUnknown
)
514 if (get_status(&report
, mem_value
, 4) == 0)
516 printf("\nValue of address 0x%08X: ", m_mem_addr
);
517 switch (m_mem_format
) {
519 printf("0x%02X\n", mem_value
& 0xff);
522 printf("0x%04X\n", mem_value
& 0xffff);
525 printf("0x%08X\n", mem_value
);
528 set_last_err_string("Invalid format, use <8|16|32>");
536 SDPWriteMemCmd::SDPWriteMemCmd(char *p
) : SDPCmdBase(p
)
538 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_WR_MEM
;
540 insert_param_info("wrmem", nullptr, Param::Type::e_null
);
541 insert_param_info("-addr", &m_mem_addr
, Param::Type::e_uint32
);
542 insert_param_info("-format", &m_mem_format
, Param::Type::e_uint32
);
543 insert_param_info("-value", &m_mem_value
, Param::Type::e_uint32
);
546 int SDPWriteMemCmd::run(CmdCtx
*ctx
)
549 if (dev
.open(ctx
->m_dev
))
552 HIDReport
report(&dev
);
554 printf("\nWriting 0x%08X to address 0x%08X ...\n", m_mem_value
, m_mem_addr
);
555 m_spdcmd
.m_addr
= EndianSwap(m_mem_addr
);
556 m_spdcmd
.m_format
= m_mem_format
;
557 switch (m_mem_format
) {
559 m_spdcmd
.m_count
= EndianSwap((uint32_t)0x1);
562 m_spdcmd
.m_count
= EndianSwap((uint32_t)0x2);
565 m_spdcmd
.m_count
= EndianSwap((uint32_t)0x4);
568 set_last_err_string("Invalid format, use <8|16|32>");
572 m_spdcmd
.m_data
= EndianSwap(m_mem_value
);
574 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
577 if (get_hab_type(&report
) == HabUnknown
)
582 if (get_status(&report
, status
, 4) < 0 || status
!= ROM_WRITE_ACK
) {
585 err
.format("%s:%d Failed to write to address 0x%X",
586 __FUNCTION__
, __LINE__
, m_mem_addr
);
587 set_last_err_string(err
);
593 SDPJumpCmd::SDPJumpCmd(char *p
) : SDPCmdBase(p
)
595 m_spdcmd
.m_cmd
= ROM_KERNEL_CMD_JUMP_ADDR
;
596 insert_param_info("jump", nullptr, Param::Type::e_null
);
597 insert_param_info("-f", &m_filename
, Param::Type::e_string_filename
);
598 insert_param_info("-ivt", &m_Ivt
, Param::Type::e_uint32
);
599 insert_param_info("-plugin", &m_PlugIn
, Param::Type::e_bool
);
600 insert_param_info("-addr", &m_jump_addr
, Param::Type::e_uint32
);
601 insert_param_info("-cleardcd", &m_clear_dcd
, Param::Type::e_bool
);
604 int SDPJumpCmd::run(CmdCtx
*ctx
)
606 const ROM_INFO
* rom
= search_rom_info(ctx
->m_config_item
);
609 if (dev
.open(ctx
->m_dev
))
612 HIDReport
report(&dev
);
617 err
.format("%s:%d can't get rom info", __FUNCTION__
, __LINE__
);
618 set_last_err_string(err
);
622 if (rom
->flags
& ROM_INFO_SPL_JUMP
)
624 m_spdcmd
.m_addr
= EndianSwap(m_jump_addr
);
625 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
628 //Omit last return value.
629 check_ack(&report
, ROM_OK_ACK
);
633 shared_ptr
<FileBuffer
> buff
= get_file_buffer(m_filename
, false);
635 buff
->request_data(WIC_BOOTPART_SIZE
);
638 IvtHeader
*pIVT
= search_ivt_header(buff
, off
, WIC_BOOTPART_SIZE
);
640 for (int i
= 0; i
< m_Ivt
; i
++)
642 off
+= sizeof(IvtHeader
);
643 pIVT
= search_ivt_header(buff
, off
);
648 set_last_err_string("Cannot find valid IVT header");
652 m_spdcmd
.m_addr
= EndianSwap(pIVT
->SelfAddr
);
655 if (rom
->flags
& ROM_INFO_HID_SKIP_DCD
&& !m_clear_dcd
)
657 SDPSkipDCDCmd
skipcmd(nullptr);
658 if (skipcmd
.run(ctx
))
664 /* Need send out whole report size buffer avoid overwrite other data
665 * Some platform require receive whole package for report id = 2
667 ivt
.resize(report
.get_out_package_size());
669 size_t sz
= buff
->size();
670 sz
-= (uint8_t*)pIVT
- (uint8_t*)buff
->data();
675 memcpy(ivt
.data(), pIVT
, sz
);
677 IvtHeader
*header
= (IvtHeader
*)ivt
.data();
678 header
->DCDAddress
= 0;
680 SDPWriteCmd
writecmd(nullptr);
681 if(writecmd
.run(ctx
, header
, ivt
.size(), pIVT
->SelfAddr
))
685 if (report
.write(&m_spdcmd
, sizeof(m_spdcmd
), 1))
688 //Omit last return value.
689 check_ack(&report
, ROM_OK_ACK
);
694 SDPBootlogCmd::SDPBootlogCmd(char *p
) : SDPCmdBase(p
)
696 insert_param_info("blog", nullptr, Param::Type::e_null
);
699 int SDPBootlogCmd::run(CmdCtx
*ctx
)
703 if (dev
.open(ctx
->m_dev
))
706 HIDReport
report(&dev
);
708 vector
<uint8_t> v(65);
712 nt
.type
= uuu_notify::NOTIFY_CMD_INFO
;
717 ret
= report
.read(v
);
722 nt
.str
= (char*)(v
.data() + 4);