| 1 | /*************************************************************************** |
|---|
| 2 | * Copyright (c) 2003-2008, Broadcom Corporation |
|---|
| 3 | * All Rights Reserved |
|---|
| 4 | * Confidential Property of Broadcom Corporation |
|---|
| 5 | * |
|---|
| 6 | * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE |
|---|
| 7 | * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR |
|---|
| 8 | * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. |
|---|
| 9 | * |
|---|
| 10 | * $brcm_Workfile: $ |
|---|
| 11 | * $brcm_Revision: $ |
|---|
| 12 | * $brcm_Date: $ |
|---|
| 13 | * |
|---|
| 14 | * Module Description: |
|---|
| 15 | * |
|---|
| 16 | * Revision History: |
|---|
| 17 | * |
|---|
| 18 | * $brcm_Log: $ |
|---|
| 19 | * |
|---|
| 20 | * |
|---|
| 21 | ***************************************************************************/ |
|---|
| 22 | |
|---|
| 23 | #include "bsettop_smessage.h" |
|---|
| 24 | #include "dsmcc.h" |
|---|
| 25 | |
|---|
| 26 | #include "bstd.h" |
|---|
| 27 | #include "bdbg.h" |
|---|
| 28 | |
|---|
| 29 | #include "image_recv.h" |
|---|
| 30 | |
|---|
| 31 | #include "bapp_util.h" |
|---|
| 32 | |
|---|
| 33 | BDBG_MODULE(image_recv); |
|---|
| 34 | |
|---|
| 35 | #define MSG_VERBOSE 1 |
|---|
| 36 | #if MSG_VERBOSE & 1 |
|---|
| 37 | #define BDBG_MSG_0(x) BDBG_MSG(x) |
|---|
| 38 | #else |
|---|
| 39 | #define BDBG_MSG_0(x) BDBG_NOP() |
|---|
| 40 | #endif |
|---|
| 41 | |
|---|
| 42 | #if MSG_VERBOSE & 2 |
|---|
| 43 | #define BDBG_MSG_2(x) BDBG_MSG(x) |
|---|
| 44 | #else |
|---|
| 45 | #define BDBG_MSG_2(x) BDBG_NOP() |
|---|
| 46 | #endif |
|---|
| 47 | |
|---|
| 48 | #define MSG_BUFFER_SIZE 0x1000 |
|---|
| 49 | #define MAX_MSG_EVENTS 1 |
|---|
| 50 | #define MSG_TIMEOUT (60000) |
|---|
| 51 | #define DDB_TIMEOUT (5*60000) |
|---|
| 52 | |
|---|
| 53 | static uint8_t msg_buffer[MSG_BUFFER_SIZE]; |
|---|
| 54 | |
|---|
| 55 | #define MAX_BITS (0x200*8) |
|---|
| 56 | struct bitmap_t { |
|---|
| 57 | uint32_t bits[0x200]; /* support 4096 DDB */ |
|---|
| 58 | }; |
|---|
| 59 | |
|---|
| 60 | struct image_state_t { |
|---|
| 61 | b_queue_t msg_evt; |
|---|
| 62 | b_event_t msg_evt_data[MAX_MSG_EVENTS]; |
|---|
| 63 | struct bitmap_t bitmap; |
|---|
| 64 | uint32_t blocks_count; |
|---|
| 65 | uint32_t blocks_received; |
|---|
| 66 | struct dii_info_t dii_data; |
|---|
| 67 | struct dii_module_t dii_module; |
|---|
| 68 | struct image_t * im; |
|---|
| 69 | }; |
|---|
| 70 | |
|---|
| 71 | struct abs_path_t { |
|---|
| 72 | uint8_t abs_path_length; |
|---|
| 73 | uint8_t abs_path_byte[0x100]; |
|---|
| 74 | }; |
|---|
| 75 | |
|---|
| 76 | static struct image_state_t image_state; |
|---|
| 77 | |
|---|
| 78 | static void * msg_callback(void * c, size_t msg_size); |
|---|
| 79 | static void * msg_callback_ddb(void * c, size_t msg_size); |
|---|
| 80 | static void * overflow_callback(void * c, size_t msg_size); |
|---|
| 81 | |
|---|
| 82 | static void bitmap_clear(struct bitmap_t * bm); |
|---|
| 83 | static void bitmap_set_bit(struct bitmap_t * bm, uint32_t bit); |
|---|
| 84 | static uint32_t bitmap_get_bit(struct bitmap_t * bm, uint32_t bit); |
|---|
| 85 | |
|---|
| 86 | |
|---|
| 87 | bresult image_init(void) |
|---|
| 88 | { |
|---|
| 89 | bresult bres; |
|---|
| 90 | memset(&image_state, 0, sizeof(struct image_state_t)); |
|---|
| 91 | bres = bos_create_queue(&image_state.msg_evt, image_state.msg_evt_data, MAX_MSG_EVENTS); |
|---|
| 92 | BDBG_SetModuleLevel("image_recv", BDBG_eMsg); |
|---|
| 93 | return bres; |
|---|
| 94 | } |
|---|
| 95 | /*************************************************************************** |
|---|
| 96 | Summary: receive image from dsm-cc pid |
|---|
| 97 | Description: |
|---|
| 98 | Input: |
|---|
| 99 | Output: |
|---|
| 100 | Returns: |
|---|
| 101 | SeeAlso: |
|---|
| 102 | None |
|---|
| 103 | ***************************************************************************/ |
|---|
| 104 | /* |
|---|
| 105 | - Setup filter to capture dii |
|---|
| 106 | - discover module number and all releated attributes |
|---|
| 107 | - initialize storage and bitmap |
|---|
| 108 | - setup filter to capture module data |
|---|
| 109 | - capture module blocks and store them in to image_t structure |
|---|
| 110 | */ |
|---|
| 111 | |
|---|
| 112 | bresult image_receive(bband_t band, uint16_t pid, struct image_t ** image, uint8_t name_length, uint8_t * name) |
|---|
| 113 | { |
|---|
| 114 | smessage_stream_t dii, ddb; |
|---|
| 115 | smessage_stream_params_t params; |
|---|
| 116 | bresult bres; |
|---|
| 117 | size_t msg_size; |
|---|
| 118 | size_t idx; |
|---|
| 119 | size_t i; |
|---|
| 120 | #if 0 |
|---|
| 121 | struct abs_path_t * ap; |
|---|
| 122 | #endif |
|---|
| 123 | *image = NULL; |
|---|
| 124 | |
|---|
| 125 | dii = smessage_open(smessage_format_psi); |
|---|
| 126 | BDBG_ASSERT(NULL != dii); |
|---|
| 127 | |
|---|
| 128 | smessage_stream_params_init(¶ms, dii); |
|---|
| 129 | params.band = band; |
|---|
| 130 | params.pid = pid; |
|---|
| 131 | params.buffer_size = MSG_BUFFER_SIZE; |
|---|
| 132 | params.buffer = msg_buffer; |
|---|
| 133 | params.data_ready_callback = msg_callback; |
|---|
| 134 | params.overflow = overflow_callback; |
|---|
| 135 | params.callback_context = &image_state; |
|---|
| 136 | params.filter.coef[0] = 0x3b; |
|---|
| 137 | params.filter.mask[0] = 0x00; |
|---|
| 138 | params.filter.coef[8] = 0x11; |
|---|
| 139 | params.filter.mask[8] = 0x00; |
|---|
| 140 | params.filter.coef[9] = 0x03; |
|---|
| 141 | params.filter.mask[9] = 0x00; |
|---|
| 142 | params.filter.coef[10] = 0x10; |
|---|
| 143 | params.filter.mask[10] = 0x00; |
|---|
| 144 | params.filter.coef[11] = 0x02; |
|---|
| 145 | params.filter.mask[11] = 0x00; |
|---|
| 146 | BDBG_MSG_0(("dii on pid 0x%x.", pid)); |
|---|
| 147 | while(1){ |
|---|
| 148 | bres = smessage_start(¶ms, dii); |
|---|
| 149 | BDBG_ASSERT(b_ok == bres); |
|---|
| 150 | |
|---|
| 151 | msg_size = (size_t)bos_pend_event(image_state.msg_evt, MSG_TIMEOUT); |
|---|
| 152 | bres = smessage_stop(dii); |
|---|
| 153 | BDBG_ASSERT(b_ok == bres); |
|---|
| 154 | |
|---|
| 155 | if(0 == msg_size){ |
|---|
| 156 | smessage_close(dii); |
|---|
| 157 | bres = berr_timeout; |
|---|
| 158 | goto ExitFunc; |
|---|
| 159 | } |
|---|
| 160 | bres = dsmcc_dii_parse(msg_buffer, msg_size, &image_state.dii_data); |
|---|
| 161 | if(0 == bres){ |
|---|
| 162 | BDBG_MSG_0(("got dii %u nom:%u", msg_size, image_state.dii_data.number_of_modules)); |
|---|
| 163 | for(i = 0; i < image_state.dii_data.number_of_modules; i++){ |
|---|
| 164 | bres = dsmcc_dii_next_module(&image_state.dii_data, &image_state.dii_module); |
|---|
| 165 | if(0 == bres){ |
|---|
| 166 | #if 0 |
|---|
| 167 | ap = (struct abs_path_t *)(&image_state.dii_module.module_info_byte[0]); |
|---|
| 168 | if(name_length != ap->abs_path_length){ |
|---|
| 169 | BDBG_MSG_0(("abs_path_length mismatch %d %d.", name_length, ap->abs_path_length)); |
|---|
| 170 | continue; |
|---|
| 171 | } |
|---|
| 172 | for(idx = 0; idx < name_length; idx++){ |
|---|
| 173 | if(ap->abs_path_byte[idx] != name[idx]){ |
|---|
| 174 | BDBG_MSG_0(("abs_path_byte mismatch.")); |
|---|
| 175 | break; |
|---|
| 176 | } |
|---|
| 177 | } |
|---|
| 178 | #else |
|---|
| 179 | if(name_length != image_state.dii_module.module_info_length){ |
|---|
| 180 | BDBG_MSG_0(("module_info_length mismatch %d %d.", name_length, image_state.dii_module.module_info_length)); |
|---|
| 181 | continue; |
|---|
| 182 | } |
|---|
| 183 | for(idx = 0; idx < name_length; idx++){ |
|---|
| 184 | if(image_state.dii_module.module_info_byte[idx] != name[idx]){ |
|---|
| 185 | BDBG_MSG_0(("module_info_byte mismatch.")); |
|---|
| 186 | break; |
|---|
| 187 | } |
|---|
| 188 | } |
|---|
| 189 | #endif |
|---|
| 190 | if(idx == name_length){ |
|---|
| 191 | break; |
|---|
| 192 | } |
|---|
| 193 | } |
|---|
| 194 | } |
|---|
| 195 | if(i < image_state.dii_data.number_of_modules){ |
|---|
| 196 | break; /* found one we are looking for */ |
|---|
| 197 | } |
|---|
| 198 | }else{ |
|---|
| 199 | BDBG_ERR(("got dii parser failed %u", bres)); |
|---|
| 200 | } |
|---|
| 201 | } |
|---|
| 202 | smessage_close(dii); |
|---|
| 203 | |
|---|
| 204 | bitmap_clear(&image_state.bitmap); |
|---|
| 205 | image_state.blocks_count = image_state.dii_module.module_size/image_state.dii_data.block_size + |
|---|
| 206 | (((image_state.dii_module.module_size%image_state.dii_data.block_size == 0))?0:1); |
|---|
| 207 | image_state.blocks_received = 0; |
|---|
| 208 | image_state.im = malloc(sizeof(struct image_t) + image_state.dii_module.module_size + (image_state.dii_data.block_size*2)); |
|---|
| 209 | BDBG_ASSERT(NULL != image_state.im); |
|---|
| 210 | memset((image_state.im->data + image_state.dii_module.module_size), 0x55, (image_state.dii_data.block_size*2)); |
|---|
| 211 | image_state.im->size = image_state.dii_module.module_size; |
|---|
| 212 | |
|---|
| 213 | ddb = smessage_open(smessage_format_psi); |
|---|
| 214 | BDBG_ASSERT(NULL != ddb); |
|---|
| 215 | |
|---|
| 216 | smessage_stream_params_init(¶ms, dii); |
|---|
| 217 | params.band = band; |
|---|
| 218 | params.pid = pid; |
|---|
| 219 | params.buffer_size = MSG_BUFFER_SIZE; |
|---|
| 220 | params.buffer = msg_buffer; |
|---|
| 221 | params.data_ready_callback = msg_callback_ddb; |
|---|
| 222 | params.overflow = overflow_callback; |
|---|
| 223 | params.callback_context = &image_state; |
|---|
| 224 | params.filter.coef[0] = 0x3c; |
|---|
| 225 | params.filter.mask[0] = 0x00; |
|---|
| 226 | params.filter.coef[3] = (image_state.dii_module.module_id >> 8) & 0xff; |
|---|
| 227 | params.filter.mask[3] = 0; |
|---|
| 228 | params.filter.coef[4] = image_state.dii_module.module_id & 0xff; |
|---|
| 229 | params.filter.mask[4] = 0; |
|---|
| 230 | params.filter.coef[8] = 0x11; |
|---|
| 231 | params.filter.mask[8] = 0x00; |
|---|
| 232 | params.filter.coef[9] = 0x03; |
|---|
| 233 | params.filter.mask[9] = 0x00; |
|---|
| 234 | params.filter.coef[10] = 0x10; |
|---|
| 235 | params.filter.mask[10] = 0x00; |
|---|
| 236 | params.filter.coef[11] = 0x03; |
|---|
| 237 | params.filter.mask[11] = 0x00; |
|---|
| 238 | |
|---|
| 239 | bres = smessage_start(¶ms, ddb); |
|---|
| 240 | BDBG_ASSERT(b_ok == bres); |
|---|
| 241 | |
|---|
| 242 | msg_size = (size_t)bos_pend_event(image_state.msg_evt, DDB_TIMEOUT); |
|---|
| 243 | |
|---|
| 244 | bres = smessage_stop(ddb); |
|---|
| 245 | BDBG_ASSERT(b_ok == bres); |
|---|
| 246 | |
|---|
| 247 | if(0 == msg_size){ |
|---|
| 248 | BDBG_ERR(("ddb timeout")); |
|---|
| 249 | free(image_state.im); |
|---|
| 250 | bres = berr_timeout; |
|---|
| 251 | }else{ |
|---|
| 252 | *image = image_state.im; |
|---|
| 253 | bres = b_ok; |
|---|
| 254 | } |
|---|
| 255 | smessage_close(ddb); |
|---|
| 256 | |
|---|
| 257 | ExitFunc: |
|---|
| 258 | return bres; |
|---|
| 259 | } |
|---|
| 260 | |
|---|
| 261 | void * msg_callback(void * c, size_t msg_size) |
|---|
| 262 | { |
|---|
| 263 | struct image_state_t * is; |
|---|
| 264 | is = (struct image_state_t *)c; |
|---|
| 265 | bos_post_event(is->msg_evt, (b_event_t*)msg_size); |
|---|
| 266 | return NULL; |
|---|
| 267 | } |
|---|
| 268 | |
|---|
| 269 | void * msg_callback_ddb(void * c, size_t msg_size) |
|---|
| 270 | { |
|---|
| 271 | bresult bres; |
|---|
| 272 | struct image_state_t * is; |
|---|
| 273 | struct ddb_info_t ddb_data; |
|---|
| 274 | is = (struct image_state_t *)c; |
|---|
| 275 | |
|---|
| 276 | bres = dsmcc_ddb_parse(msg_buffer, msg_size, &ddb_data); |
|---|
| 277 | if(0 == bres){ |
|---|
| 278 | uint32_t have_block; |
|---|
| 279 | BDBG_MSG_0(("got ddb %u %hu %hu", msg_size, ddb_data.module_id, ddb_data.block_number)); |
|---|
| 280 | have_block = bitmap_get_bit(&is->bitmap, ddb_data.block_number); |
|---|
| 281 | if(0 == have_block){ |
|---|
| 282 | uint8_t * p_block; |
|---|
| 283 | size_t copy_size; |
|---|
| 284 | size_t block_offset; |
|---|
| 285 | |
|---|
| 286 | 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])); |
|---|
| 287 | block_offset = ddb_data.block_number * is->dii_data.block_size; |
|---|
| 288 | p_block = is->im->data + block_offset; |
|---|
| 289 | 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); |
|---|
| 290 | memcpy(p_block, ddb_data.data_bytes, copy_size); |
|---|
| 291 | |
|---|
| 292 | is->blocks_received++; |
|---|
| 293 | BDBG_MSG_0(("Copied %u (%d, %d)", copy_size, is->blocks_received, is->blocks_count)); |
|---|
| 294 | bitmap_set_bit(&is->bitmap, ddb_data.block_number); |
|---|
| 295 | if(is->blocks_count == is->blocks_received){ |
|---|
| 296 | BDBG_MSG_0(("Received all blocks")); |
|---|
| 297 | bos_post_event(is->msg_evt, (b_event_t*)msg_size); |
|---|
| 298 | } |
|---|
| 299 | }else{ |
|---|
| 300 | BDBG_MSG_0(("Have block %u", ddb_data.block_number)); |
|---|
| 301 | } |
|---|
| 302 | } |
|---|
| 303 | return msg_buffer; |
|---|
| 304 | } |
|---|
| 305 | |
|---|
| 306 | void * overflow_callback(void * c, size_t msg_size) |
|---|
| 307 | { |
|---|
| 308 | return NULL; |
|---|
| 309 | } |
|---|
| 310 | |
|---|
| 311 | void bitmap_clear(struct bitmap_t * bm) |
|---|
| 312 | { |
|---|
| 313 | memset(bm, 0, sizeof(struct bitmap_t)); |
|---|
| 314 | } |
|---|
| 315 | |
|---|
| 316 | void bitmap_set_bit(struct bitmap_t * bm, uint32_t bit) |
|---|
| 317 | { |
|---|
| 318 | uint32_t word; |
|---|
| 319 | uint32_t word_bit; |
|---|
| 320 | |
|---|
| 321 | BDBG_ASSERT(MAX_BITS > bit); |
|---|
| 322 | word = bit >> 5; |
|---|
| 323 | word_bit = bit & 0x1f; |
|---|
| 324 | bm->bits[word] |= (0x1 << word_bit); |
|---|
| 325 | } |
|---|
| 326 | |
|---|
| 327 | uint32_t bitmap_get_bit(struct bitmap_t * bm, uint32_t bit) |
|---|
| 328 | { |
|---|
| 329 | uint32_t word; |
|---|
| 330 | uint32_t word_bit; |
|---|
| 331 | |
|---|
| 332 | BDBG_ASSERT(MAX_BITS > bit); |
|---|
| 333 | word = bit >> 5; |
|---|
| 334 | word_bit = bit & 0x1f; |
|---|
| 335 | return ((bm->bits[word] >> word_bit) & 1); |
|---|
| 336 | } |
|---|
| 337 | |
|---|
| 338 | void image_get_status(struct image_status_t * status) |
|---|
| 339 | { |
|---|
| 340 | status->blocks_count = image_state.blocks_count; |
|---|
| 341 | status->blocks_received = image_state.blocks_received; |
|---|
| 342 | status->module_version = image_state.dii_module.module_version; |
|---|
| 343 | status->module_info_length = image_state.dii_module.module_info_length; |
|---|
| 344 | status->module_info_bytes = &image_state.dii_module.module_info_byte[0]; |
|---|
| 345 | } |
|---|
| 346 | |
|---|