//====================================================================== // check partition table info command //====================================================================== void check_pt_cmd (void) { DM_ERRCODE_PACKET errp = { DM_ERROR_PKT_PATN, 0 }; DM_PKT_TYPE pkt_type; char buffer[DM_CMD_MAX_SIZE]; int i; #ifdef DEBUG print ("DM_PARTITION_INFO_PACKET\n"); print (": pattern %x\n", g_img_dl_pt_info.pattern); print (": part_num = %d\n", g_img_dl_pt_info.part_num); for (i = 0; i < PART_MAX_COUNT; i++) { print (": part_info[%d].part_name = %s\n", i, g_img_dl_pt_info.part_info[i].part_name); print (": part_info[%d].start_addr = %x\n", i, g_img_dl_pt_info.part_info[i].start_addr); print (": part_info[%d].part_len = %x\n", i, g_img_dl_pt_info.part_info[i].part_len); print (": part_info[%d].part_visibility = %x\n", i, g_img_dl_pt_info.part_info[i].part_visibility); print (": part_info[%d].dl_selected = %x\n", i, g_img_dl_pt_info.part_info[i].dl_selected); print ("\n"); } #endif //================================================== // check if specified partitions can be downloaded //================================================== #if CFG_PMT_SUPPORT errp.err_code = new_part_tab ((u8 *) &g_img_dl_pt_info); #else print("%s : PMT is not supported\n", MOD); errp.err_code = DM_ERR_OK; #endif mt_usbtty_putcn (DM_SZ_ERR_CODE_PKT, (u8 *) & errp, TRUE); if (errp.err_code != DM_ERR_OK) { print ("\n%s : the specified partitions can not be downloaded, err_code = %d\n", MOD, errp.err_code); //================================ // receive REBOOT packet //================================ reset_dm_descriptor (); mt_usbtty_getcn (DM_SZ_REBOOT_STR, buffer); pkt_type = judge_pkt_type ((const void *) buffer); if (pkt_type == DM_PKT_REBT) { //print ("%s : received REBOOT packet\n", MOD); dm_ctx.dm_status = DM_STATUS_REBOOT; } else { //print ("%s : do not received REBOOT packet\n", MOD); dm_ctx.dm_status = DM_STATUS_START; } } else { dm_ctx.dm_status = DM_STATUS_START; } }
/************************************************************************** * Handle Image **************************************************************************/ u32 handle_imgp (u32 * pktsz) { DM_EXT_IMAGE_INFO_PACKET ext_imgp; DM_IMAGE_INFO_PACKET imgp; memset(&ext_imgp, 0, sizeof(DM_EXT_IMAGE_INFO_PACKET)); memset(&imgp, 0, sizeof(DM_IMAGE_INFO_PACKET)); DM_ENTRY_LOG (); mt_usbtty_getcn (DM_SZ_EXT_IMG_INFO_PKT, (u8 *) & ext_imgp); fill_internal_imgp(&imgp , &ext_imgp); check_imgp (&imgp, pktsz); mt_usbtty_puts (DM_STR_START_REQ); return *pktsz; }
static bool usb_listen(struct bldr_comport *comport, uint8 *data, uint32 size, uint32 tmo_ms) { ulong start_time = get_timer(0); uint32 dsz; uint32 tmo_en = (tmo_ms) ? 1 : 0; uint8 *ptr = data; if (!size) return FALSE; while (1) { if (tool_is_present()) mt_usbtty_puts(HSHK_COM_READY); /* "READY" */ if (tmo_en && (get_timer(start_time) > tmo_ms)) return FALSE; if (!tmo_en) { /* kick watchdog to avoid cpu reset */ platform_wdt_all_kick(); } dsz = mt_usbtty_query_data_size(); if (dsz) { dsz = dsz < size ? dsz : size; mt_usbtty_getcn(dsz, (char*)ptr); #if CFG_USB_DOWNLOAD && !CFG_LEGACY_USB_DOWNLOAD if (*ptr == 0xa0) { print("%s sync time %dms\n", MOD, get_timer(start_time)); usbdl_handler(comport, 300); print("%s : ignore %d bytes garbage data\n", MOD, dsz); continue; /* ingore received data */ } #endif ptr += dsz; size -= dsz; } if (size == 0) break; udelay(20000); /* 20ms */ } print("%s sync time %dms\n", MOD, get_timer(start_time)); return TRUE; }
static int usb_recv(u8 *buf, u32 size, u32 tmo_ms) { ulong start_time = get_timer(0); u32 dsz; u32 tmo_en = (tmo_ms) ? 1 : 0; u8 *ptr = buf; if (!size) return 0; while (1) { if (tmo_en && (get_timer(start_time) > tmo_ms)) return -1; if (!tmo_en) { /* kick watchdog to avoid cpu reset but don't kick pmic wdt since * it could use i2c operations during a communication command protocl * that could break the atomic operation of 2 pmic i2c communication * commands. i2c operations should be not used during usb send or recv. * for example: * * i2c_write(pmic_addr) -> usb_recv() -> i2c_read(&pmic_data). */ platform_wdt_kick(); } dsz = mt_usbtty_query_data_size(); if (dsz) { dsz = dsz < size ? dsz : size; mt_usbtty_getcn(dsz, (char*)ptr); ptr += dsz; size -= dsz; } if (size == 0) break; } return 0; }
/************************************************************************** * Middle State **************************************************************************/ void handle_midle_state (u8 * buf) { DM_PKT_TYPE pkt_type; DM_EXT_IMAGE_INFO_PACKET *ext_imgp; DM_PATCH_CMD_PACKET *patch_cmd; DM_IMAGE_INFO_PACKET imgp; u32 pktsz = 0; part_t *part; u8 *name = NULL; DM_ENTRY_LOG (); memset(&imgp, 0, sizeof(DM_IMAGE_INFO_PACKET)); reset_dm_descriptor (); /* receive a little bit data, check if it is REBOOT */ mt_usbtty_getcn (DM_SZ_REBOOT_STR, buf); pkt_type = judge_pkt_type ((const void *) buf); if (pkt_type == DM_PKT_REBT) { dm_ctx.dm_status = DM_STATUS_REBOOT; return; } if (pkt_type == DM_PKT_AUTO) { print ("autoboot mode !!!\n"); dm_ctx.dm_status = DM_STATUS_ATBOOT; return; } if (pkt_type == DM_PKT_UPDT) { print ("update partition table\n"); dm_ctx.dm_status = DM_STATUS_UPDATE; return; } /* pcaket type is IMGP */ if (pkt_type == DM_PKT_IMGP) { //print ("\nCASE 2 : pcaket type is DM_PKT_IMGP\n"); mt_usbtty_getcn (DM_SZ_EXT_IMG_INFO_PKT - DM_SZ_REBOOT_STR, (u8 *) (buf + DM_SZ_REBOOT_STR)); ext_imgp = (DM_EXT_IMAGE_INFO_PACKET *) buf; fill_internal_imgp (&imgp , &(*ext_imgp)); check_imgp (&imgp, &pktsz); mt_usbtty_puts (DM_STR_START_REQ); } else { print ("\nCASE 3 : others\n"); if (pkt_type != DM_PKT_IMGP) { print ("pkt_type = 0x%x\n", pkt_type); } ASSERT (0); } return; }
//====================================================================== // handle partition table info command //====================================================================== void handle_pt_cmd (void) { DM_ENTRY_LOG (); mt_usbtty_getcn (DM_SZ_PT_INFO_CMD_PKT, (u8 *) & g_img_dl_pt_info); check_pt_cmd (); }
/************************************************************************** * Handle Data **************************************************************************/ void handle_data (u32 pktsz, u8 * buf) { bool res = TRUE; unsigned int i = 0; u32 starting_block = 0; u32 spare_start, spare_offset, spare_len; bool first_page = TRUE; bool need_erase_nand = TRUE; bool invalid_addr = FALSE; blkdev_t *blkdev; blkdev = blkdev_get(CFG_BOOT_DEV); DM_ENTRY_LOG (); if (dm_ctx.dm_status == DM_STATUS_ERR_ONGOING) { while (dm_ctx.curr_cnt <= dm_ctx.pkt_cnt) { mt_usbtty_getcn (pktsz, buf); dm_ctx.curr_cnt++; }; dm_ctx.dm_status = DM_STATUS_ERR_FINISHED; return; } /* make sure the starting block is good */ starting_block = g_boot_dev.dev_find_safe_block (dm_ctx.page_off); if (dm_ctx.page_off != starting_block) { dm_ctx.page_off = starting_block; } do { /* fill USB buffer */ DM_TIME_BEGIN; mt_usbtty_getcn (pktsz, buf); DM_TIME_END_USB_READ; /* calculate check sum of received buffer */ #if (DM_CAL_CKSM_FROM_USB_BUFFER || DM_DBG_LOG) #if DM_CAL_CKSM_FROM_USB_BUFFER DM_TIME_BEGIN; cal_chksum_per_pkt (buf, pktsz); DM_TIME_END_CHECKSM; #endif #endif /* check image boundary always check image boundary at begining to ensure that "won't write any data to next partition" */ if (dm_ctx.page_off >= dm_ctx.img_info.addr_boundary) { //print ("current page_off (0%x) >= addr_boundary (0x%x)\n", dm_ctx.page_off, dm_ctx.img_info.addr_boundary); invalid_addr = TRUE; } /* if addr is invalid, skip the nand writing process */ if (invalid_addr == TRUE) { goto _next; } if (TRUE == need_erase_nand) { /* erase nand flash */ handle_erase (&dm_ctx.img_info, pktsz); need_erase_nand = FALSE; } /* when the address is block alignment, check if this block is good */ DM_TIME_BEGIN; if (dm_ctx.page_off % blkdev->erasesz == 0) { dm_ctx.page_off = g_boot_dev.dev_find_safe_block (dm_ctx.page_off); } DM_TIME_END_NAND_BAD_BLOCK; /* write nand flash */ DM_TIME_BEGIN; g_boot_dev.dev_write_data (buf, dm_ctx.page_off) ; DM_TIME_END_NAND_WRITE; _next: /* update the latest safe nand addr */ g_dl_safe_start_addr = dm_ctx.page_off; /* increase must after flash data */ dm_ctx.curr_cnt++; dm_ctx.curr_off += pktsz; dm_ctx.page_off += dm_ctx.page_size; //delay (1000); } while ((dm_ctx.curr_cnt <= dm_ctx.pkt_cnt) && (dm_ctx.dm_status == DM_STATUS_SECT_ONGING)); dm_ctx.dm_status = DM_STATUS_SECT_FINISHED; return; }