/*************************************************************************** * Copyright (c) 2003-2008, Broadcom Corporation * All Rights Reserved * Confidential Property of Broadcom Corporation * * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. * * $brcm_Workfile: $ * $brcm_Revision: $ * $brcm_Date: $ * * Module Description: * * Revision History: * * $brcm_Log: $ * * ***************************************************************************/ #include "bsettop_smessage.h" #include "dsmcc.h" #include "bstd.h" #include "bdbg.h" #include "image_recv.h" #include "bapp_util.h" BDBG_MODULE(image_recv); #define MSG_VERBOSE 1 #if MSG_VERBOSE & 1 #define BDBG_MSG_0(x) BDBG_MSG(x) #else #define BDBG_MSG_0(x) BDBG_NOP() #endif #if MSG_VERBOSE & 2 #define BDBG_MSG_2(x) BDBG_MSG(x) #else #define BDBG_MSG_2(x) BDBG_NOP() #endif #define MSG_BUFFER_SIZE 0x1000 #define MAX_MSG_EVENTS 1 #define MSG_TIMEOUT (60000) #define DDB_TIMEOUT (5*60000) static uint8_t msg_buffer[MSG_BUFFER_SIZE]; #define MAX_BITS (0x200*8) struct bitmap_t { uint32_t bits[0x200]; /* support 4096 DDB */ }; struct image_state_t { b_queue_t msg_evt; b_event_t msg_evt_data[MAX_MSG_EVENTS]; struct bitmap_t bitmap; uint32_t blocks_count; uint32_t blocks_received; struct dii_info_t dii_data; struct dii_module_t dii_module; struct image_t * im; }; struct abs_path_t { uint8_t abs_path_length; uint8_t abs_path_byte[0x100]; }; static struct image_state_t image_state; static void * msg_callback(void * c, size_t msg_size); static void * msg_callback_ddb(void * c, size_t msg_size); static void * overflow_callback(void * c, size_t msg_size); static void bitmap_clear(struct bitmap_t * bm); static void bitmap_set_bit(struct bitmap_t * bm, uint32_t bit); static uint32_t bitmap_get_bit(struct bitmap_t * bm, uint32_t bit); bresult image_init(void) { bresult bres; memset(&image_state, 0, sizeof(struct image_state_t)); bres = bos_create_queue(&image_state.msg_evt, image_state.msg_evt_data, MAX_MSG_EVENTS); BDBG_SetModuleLevel("image_recv", BDBG_eMsg); return bres; } /*************************************************************************** Summary: receive image from dsm-cc pid Description: Input: Output: Returns: SeeAlso: None ***************************************************************************/ /* - Setup filter to capture dii - discover module number and all releated attributes - initialize storage and bitmap - setup filter to capture module data - capture module blocks and store them in to image_t structure */ bresult image_receive(bband_t band, uint16_t pid, struct image_t ** image, uint8_t name_length, uint8_t * name) { smessage_stream_t dii, ddb; smessage_stream_params_t params; bresult bres; size_t msg_size; size_t idx; size_t i; #if 0 struct abs_path_t * ap; #endif *image = NULL; dii = smessage_open(smessage_format_psi); BDBG_ASSERT(NULL != dii); smessage_stream_params_init(¶ms, dii); params.band = band; params.pid = pid; params.buffer_size = MSG_BUFFER_SIZE; params.buffer = msg_buffer; params.data_ready_callback = msg_callback; params.overflow = overflow_callback; params.callback_context = &image_state; params.filter.coef[0] = 0x3b; params.filter.mask[0] = 0x00; params.filter.coef[8] = 0x11; params.filter.mask[8] = 0x00; params.filter.coef[9] = 0x03; params.filter.mask[9] = 0x00; params.filter.coef[10] = 0x10; params.filter.mask[10] = 0x00; params.filter.coef[11] = 0x02; params.filter.mask[11] = 0x00; BDBG_MSG_0(("dii on pid 0x%x.", pid)); while(1){ bres = smessage_start(¶ms, dii); BDBG_ASSERT(b_ok == bres); msg_size = (size_t)bos_pend_event(image_state.msg_evt, MSG_TIMEOUT); bres = smessage_stop(dii); BDBG_ASSERT(b_ok == bres); if(0 == msg_size){ smessage_close(dii); bres = berr_timeout; goto ExitFunc; } bres = dsmcc_dii_parse(msg_buffer, msg_size, &image_state.dii_data); if(0 == bres){ BDBG_MSG_0(("got dii %u nom:%u", msg_size, image_state.dii_data.number_of_modules)); for(i = 0; i < image_state.dii_data.number_of_modules; i++){ bres = dsmcc_dii_next_module(&image_state.dii_data, &image_state.dii_module); if(0 == bres){ #if 0 ap = (struct abs_path_t *)(&image_state.dii_module.module_info_byte[0]); if(name_length != ap->abs_path_length){ BDBG_MSG_0(("abs_path_length mismatch %d %d.", name_length, ap->abs_path_length)); continue; } for(idx = 0; idx < name_length; idx++){ if(ap->abs_path_byte[idx] != name[idx]){ BDBG_MSG_0(("abs_path_byte mismatch.")); break; } } #else if(name_length != image_state.dii_module.module_info_length){ BDBG_MSG_0(("module_info_length mismatch %d %d.", name_length, image_state.dii_module.module_info_length)); continue; } for(idx = 0; idx < name_length; idx++){ if(image_state.dii_module.module_info_byte[idx] != name[idx]){ BDBG_MSG_0(("module_info_byte mismatch.")); break; } } #endif if(idx == name_length){ break; } } } if(i < image_state.dii_data.number_of_modules){ break; /* found one we are looking for */ } }else{ BDBG_ERR(("got dii parser failed %u", bres)); } } smessage_close(dii); bitmap_clear(&image_state.bitmap); image_state.blocks_count = image_state.dii_module.module_size/image_state.dii_data.block_size + (((image_state.dii_module.module_size%image_state.dii_data.block_size == 0))?0:1); image_state.blocks_received = 0; image_state.im = malloc(sizeof(struct image_t) + image_state.dii_module.module_size + (image_state.dii_data.block_size*2)); BDBG_ASSERT(NULL != image_state.im); memset((image_state.im->data + image_state.dii_module.module_size), 0x55, (image_state.dii_data.block_size*2)); image_state.im->size = image_state.dii_module.module_size; ddb = smessage_open(smessage_format_psi); BDBG_ASSERT(NULL != ddb); smessage_stream_params_init(¶ms, dii); params.band = band; params.pid = pid; params.buffer_size = MSG_BUFFER_SIZE; params.buffer = msg_buffer; params.data_ready_callback = msg_callback_ddb; params.overflow = overflow_callback; params.callback_context = &image_state; params.filter.coef[0] = 0x3c; params.filter.mask[0] = 0x00; params.filter.coef[3] = (image_state.dii_module.module_id >> 8) & 0xff; params.filter.mask[3] = 0; params.filter.coef[4] = image_state.dii_module.module_id & 0xff; params.filter.mask[4] = 0; params.filter.coef[8] = 0x11; params.filter.mask[8] = 0x00; params.filter.coef[9] = 0x03; params.filter.mask[9] = 0x00; params.filter.coef[10] = 0x10; params.filter.mask[10] = 0x00; params.filter.coef[11] = 0x03; params.filter.mask[11] = 0x00; bres = smessage_start(¶ms, ddb); BDBG_ASSERT(b_ok == bres); msg_size = (size_t)bos_pend_event(image_state.msg_evt, DDB_TIMEOUT); bres = smessage_stop(ddb); BDBG_ASSERT(b_ok == bres); if(0 == msg_size){ BDBG_ERR(("ddb timeout")); free(image_state.im); bres = berr_timeout; }else{ *image = image_state.im; bres = b_ok; } smessage_close(ddb); ExitFunc: return bres; } void * msg_callback(void * c, size_t msg_size) { struct image_state_t * is; is = (struct image_state_t *)c; bos_post_event(is->msg_evt, (b_event_t*)msg_size); return NULL; } void * msg_callback_ddb(void * c, size_t msg_size) { bresult bres; struct image_state_t * is; struct ddb_info_t ddb_data; is = (struct image_state_t *)c; bres = dsmcc_ddb_parse(msg_buffer, msg_size, &ddb_data); if(0 == bres){ uint32_t have_block; BDBG_MSG_0(("got ddb %u %hu %hu", msg_size, ddb_data.module_id, ddb_data.block_number)); have_block = bitmap_get_bit(&is->bitmap, ddb_data.block_number); if(0 == have_block){ uint8_t * p_block; size_t copy_size; size_t block_offset; BDBG_MSG_2(("%hx %hx %hx %hx", ddb_data.data_bytes[0], ddb_data.data_bytes[1], ddb_data.data_bytes[2], ddb_data.data_bytes[3])); block_offset = ddb_data.block_number * is->dii_data.block_size; p_block = is->im->data + block_offset; copy_size = (is->dii_module.module_size - block_offset) > is->dii_data.block_size ? is->dii_data.block_size : (is->dii_module.module_size - block_offset); memcpy(p_block, ddb_data.data_bytes, copy_size); is->blocks_received++; BDBG_MSG_0(("Copied %u (%d, %d)", copy_size, is->blocks_received, is->blocks_count)); bitmap_set_bit(&is->bitmap, ddb_data.block_number); if(is->blocks_count == is->blocks_received){ BDBG_MSG_0(("Received all blocks")); bos_post_event(is->msg_evt, (b_event_t*)msg_size); } }else{ BDBG_MSG_0(("Have block %u", ddb_data.block_number)); } } return msg_buffer; } void * overflow_callback(void * c, size_t msg_size) { return NULL; } void bitmap_clear(struct bitmap_t * bm) { memset(bm, 0, sizeof(struct bitmap_t)); } void bitmap_set_bit(struct bitmap_t * bm, uint32_t bit) { uint32_t word; uint32_t word_bit; BDBG_ASSERT(MAX_BITS > bit); word = bit >> 5; word_bit = bit & 0x1f; bm->bits[word] |= (0x1 << word_bit); } uint32_t bitmap_get_bit(struct bitmap_t * bm, uint32_t bit) { uint32_t word; uint32_t word_bit; BDBG_ASSERT(MAX_BITS > bit); word = bit >> 5; word_bit = bit & 0x1f; return ((bm->bits[word] >> word_bit) & 1); } void image_get_status(struct image_status_t * status) { status->blocks_count = image_state.blocks_count; status->blocks_received = image_state.blocks_received; status->module_version = image_state.dii_module.module_version; status->module_info_length = image_state.dii_module.module_info_length; status->module_info_bytes = &image_state.dii_module.module_info_byte[0]; }