/** * @brief Decode an extension list type 3 * * @param decomp The list decompressor * @param packet The ROHC packet to decompress * @param packet_len The length (in bytes) of the packet to decompress * @param gen_id The id of the current list * maybe ROHC_LIST_GEN_ID_ANON if not defined * @param ps The ps field * @param xi_1 The XI 1 field if PS = 1 (4-bit XI) * @return \li In case of success, the number of bytes read in the given * packet, ie. the length of the compressed list * \li -1 in case of failure */ static int rohc_list_decode_type_3(struct list_decomp *const decomp, const uint8_t *packet, size_t packet_len, const unsigned int gen_id, const int ps, const int xi_1) { size_t packet_read_len = 0; struct rohc_list removal_list; /* list after removal scheme but before insertion scheme */ unsigned int ref_id; int ret; assert(decomp != NULL); assert(packet != NULL); assert(gen_id != ROHC_LIST_GEN_ID_NONE); assert(ps == 0 || ps == 1); /* in case of 8-bit XI, the XI 1 field should be set to 0 */ if(ps && xi_1 != 0) { rd_list_warn(decomp, "sender does not conform to ROHC standards: when " "8-bit XIs are used, the 4-bit XI 1 field should be set " "to 0, not 0x%x", xi_1); #ifdef ROHC_RFC_STRICT_DECOMPRESSOR goto error; #endif } /* is there enough data in packet for the ref_id? */ if(packet_len < 1) { rd_list_warn(decomp, "packet too small for ref_id and minimal removal " "bit mask fields (only %zu bytes while at least 1 byte " "is required)", packet_len); goto error; } /* parse ref_id */ ref_id = GET_BIT_0_7(packet); packet++; packet_len--; packet_read_len++; rd_list_debug(decomp, "ref_id = 0x%02x", ref_id); /* reference list must be known */ if(!rohc_list_is_gen_id_known(decomp, ref_id)) { rd_list_warn(decomp, "unknown ID 0x%02x given for reference list", ref_id); goto error; } /* reference list must not be empty (RFC 4815, §5.7) */ if(decomp->lists[ref_id].items_nr == 0) { rd_list_warn(decomp, "list encoding type 3 must not be used with an " "empty reference list, discard packet"); goto error; } /* removal scheme */ rohc_list_reset(&removal_list); ret = rohc_list_parse_removal_scheme(decomp, packet, packet_len, &(decomp->lists[ref_id]), &removal_list); if(ret < 0) { if(gen_id == ROHC_LIST_GEN_ID_ANON) { rd_list_warn(decomp, "failed to anonymous decompress list based on " "reference list %u: removal scheme failed", ref_id); } else { rd_list_warn(decomp, "failed to decompress list with ID %u based on " "reference list %u: removal scheme failed", gen_id, ref_id); } goto error; } packet += ret; packet_len -= ret; packet_read_len += ret; /* insertion scheme */ ret = rohc_list_parse_insertion_scheme(decomp, packet, packet_len, ps, xi_1, removal_list.items_nr, &removal_list, &decomp->pkt_list); if(ret < 0) { if(gen_id == ROHC_LIST_GEN_ID_ANON) { rd_list_warn(decomp, "failed to anonymous decompress list based on " "reference list %u: removal scheme failed", ref_id); } else { rd_list_warn(decomp, "failed to decompress list with ID %u based on " "reference list %u: insertion scheme failed", gen_id, ref_id); } goto error; } #ifndef __clang_analyzer__ /* silent warning about dead in/decrement */ packet += ret; packet_len -= ret; #endif packet_read_len += ret; return packet_read_len; error: return -1; }
/** * @brief Decompress the compressed list in given packet * * @param decomp The list decompressor * @param packet The ROHC packet to decompress * @param packet_len The remaining length of the packet to decode (in bytes) * @return The size of the compressed list in packet in case of * success, -1 in case of failure */ static int rohc_list_decode(struct list_decomp *decomp, const uint8_t *packet, size_t packet_len) { size_t read_length = 0; uint8_t et; /* the type of list encoding */ bool gp; /* whether the gen_id field is present or not */ uint8_t ps; /* the type of XI field */ uint8_t m; /* the CC or Count field (share bits with XI 1) */ uint8_t xi_1; /* the XI 1 field (share bits with m) */ unsigned int gen_id; /* the gen_id if present, ROHC_LIST_GEN_ID_ANON otherwise */ int ret; /* reset the list of the current packet */ rohc_list_reset(&decomp->pkt_list); /* is there enough data in packet for the ET, PS, m/XI1 and gen_id * fields? */ if(packet_len < 2) { rd_list_warn(decomp, "packet too small for compressed list (only %zu " "bytes while at least 2 bytes are required)", packet_len); goto error; } /* parse ET, GP, PS, and m/XI1 fields */ et = GET_BIT_6_7(packet); gp = !!GET_BIT_5(packet); ps = GET_REAL(GET_BIT_4(packet)); m = GET_BIT_0_3(packet); xi_1 = m; /* m and XI 1 are the same field */ packet++; read_length++; packet_len--; rd_list_debug(decomp, "ET = %d, GP = %d, PS = %d, m = XI 1 = %d", et, gp, ps, m); assert(m <= ROHC_LIST_ITEMS_MAX); /* parse gen_id if present */ if(gp == 1) { gen_id = GET_BIT_0_7(packet); packet++; read_length++; packet_len--; rd_list_debug(decomp, "gen_id = 0x%02x", gen_id); } else { gen_id = ROHC_LIST_GEN_ID_ANON; rd_list_debug(decomp, "decode anonymous list"); } decomp->pkt_list.id = gen_id; /* decode the compressed list according to its type */ switch(et) { case 0: ret = rohc_list_decode_type_0(decomp, packet, packet_len, gen_id, ps, m); break; case 1: ret = rohc_list_decode_type_1(decomp, packet, packet_len, gen_id, ps, xi_1); break; case 2: ret = rohc_list_decode_type_2(decomp, packet, packet_len, gen_id); break; case 3: ret = rohc_list_decode_type_3(decomp, packet, packet_len, gen_id, ps, xi_1); break; default: /* should not happen */ rohc_error(decomp, ROHC_TRACE_DECOMP, decomp->profile_id, "unknown type of compressed list (ET = %u)", et); assert(0); goto error; } if(ret < 0) { rd_list_warn(decomp, "failed to decode compressed list type %d", et); goto error; } assert(((size_t) ret) <= packet_len); #ifndef __clang_analyzer__ /* silent warning about dead in/decrement */ packet += ret; packet_len -= ret; #endif read_length += ret; /* RFC3095, section 5.8.2.1 reads: * When the decompressor receives a compressed list, it retrieves the * proper ref_list from the sliding window based on the ref_id, and * decompresses the compressed list obtaining curr_list. * In U/O-mode, curr_list is inserted into the sliding window * together with its generation identifier if the compressed list had * a generation identifier and the sliding window does not contain a * list with that generation identifier. All lists with generations * older than ref_id are removed from the sliding window. */ if(gen_id == ROHC_LIST_GEN_ID_ANON) { /* list is not identified by a gen_id, so do not update the sliding * window of lists */ rd_list_debug(decomp, "anonymous list was received"); } else if(decomp->lists[gen_id].counter > 0) { /* list is identified by a gen_id, but the sliding window of lists * already contain a list with that generation identifier, so do * not update the sliding window of lists */ decomp->lists[gen_id].counter++; rd_list_debug(decomp, "list with gen_id %u is already present in " "reference lists (received for the #%zu times)", gen_id, decomp->lists[gen_id].counter); } else { /* list is identified by a gen_id and the sliding window of lists does * not contain a list with that generation identifier yet, so update * the sliding window of lists */ rd_list_debug(decomp, "list with gen_id %u is not present yet in " "reference lists, add it", gen_id); memcpy(decomp->lists[gen_id].items, decomp->pkt_list.items, ROHC_LIST_ITEMS_MAX * sizeof(struct decomp_list *)); decomp->lists[gen_id].items_nr = decomp->pkt_list.items_nr; decomp->lists[gen_id].counter = 1; /* TODO: remove all lists with gen_id < ref_id */ } return read_length; error: return -1; }
/** * @brief Decode an extension list type 2 * * @param decomp The list decompressor * @param packet The ROHC packet to decompress * @param packet_len The length (in bytes) of the packet to decompress * @param gen_id The id of the current list, * maybe ROHC_LIST_GEN_ID_ANON if not defined * @return \li In case of success, the number of bytes read in the given * packet, ie. the length of the compressed list * \li -1 in case of failure */ static int rohc_list_decode_type_2(struct list_decomp *const decomp, const uint8_t *packet, size_t packet_len, const unsigned int gen_id) { size_t packet_read_len = 0; unsigned int ref_id; int ret; assert(decomp != NULL); assert(packet != NULL); assert(gen_id != ROHC_LIST_GEN_ID_NONE); /* is there enough data in packet for the ref_id and minimal removal bit mask fields ? */ if(packet_len < 2) { rd_list_warn(decomp, "packet too small for ref_id and minimal removal " "bit mask fields (only %zu bytes while at least 2 bytes " "are required)", packet_len); goto error; } /* parse ref_id */ ref_id = GET_BIT_0_7(packet); packet++; packet_len--; packet_read_len++; rd_list_debug(decomp, "ref_id = 0x%02x", ref_id); /* reference list must be known */ if(!rohc_list_is_gen_id_known(decomp, ref_id)) { rd_list_warn(decomp, "unknown ID 0x%02x given for reference list", ref_id); goto error; } /* reference list must not be empty (RFC 4815, §5.7) */ if(decomp->lists[ref_id].items_nr == 0) { rd_list_warn(decomp, "list encoding type 2 must not be used with an " "empty reference list, discard packet"); goto error; } /* removal scheme */ ret = rohc_list_parse_removal_scheme(decomp, packet, packet_len, &(decomp->lists[ref_id]), &(decomp->pkt_list)); if(ret < 0) { if(gen_id == ROHC_LIST_GEN_ID_ANON) { rd_list_warn(decomp, "failed to anonymous decompress list based on " "reference list %u: removal scheme failed", ref_id); } else { rd_list_warn(decomp, "failed to decompress list with ID %u based on " "reference list %u: removal scheme failed", gen_id, ref_id); } goto error; } #ifndef __clang_analyzer__ /* silent warning about dead in/decrement */ packet += ret; packet_len -= ret; #endif packet_read_len += ret; return packet_read_len; error: return -1; }
// Decide if the field is a padding field // Return: 1 = padding // 0 = else int d_is_paddning(const unsigned char *data) { if (GET_BIT_0_7(data) == D_PADDING) return 1; return 0; }
/**************************************************************************** * * Function Name : FlashEraseSector * Description : Perform erase operation on Flash * Arguments : PFLASH_SSD_CONFIG, UINT32, UINT32, pFLASHCOMMANDSEQUENCE * Return Value : UINT32 * *****************************************************************************/ UINT32 FlashEraseSector(PFLASH_SSD_CONFIG pSSDConfig, \ UINT32 dest, \ UINT32 size, \ pFLASHCOMMANDSEQUENCE pFlashCommandSequence) { UINT32 ret; /* return code variable */ UINT32 sectorSize ,temp; /* size of one sector */ ret = FTFx_OK; /* convert to byte address */ dest = WORD2BYTE(dest); #if (DEBLOCK_SIZE) temp = WORD2BYTE(pSSDConfig->DFlashBlockBase); if((dest >= temp) && (dest < (temp + pSSDConfig->DFlashBlockSize))) { dest = dest - temp + 0x800000; sectorSize = FTFx_DSECTOR_SIZE; } else #endif { temp = WORD2BYTE(pSSDConfig->PFlashBlockBase); if((dest >= temp) && (dest < (temp + pSSDConfig->PFlashBlockSize))) { dest -= temp; sectorSize = FTFx_PSECTOR_SIZE; }else{ ret = FTFx_ERR_ACCERR; goto EXIT; } } /* check if the size is sector alignment or not */ if(size & (sectorSize-1)) { /* return an error code FTFx_ERR_SIZE */ ret = FTFx_ERR_SIZE; goto EXIT; } while(size > 0) { /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register. Write 1 to clear*/ REG_WRITE(pSSDConfig->ftfxRegBase + FTFx_SSD_FSTAT_OFFSET,FTFx_SSD_FSTAT_ERROR_BITS); /* passing parameter to the command */ REG_WRITE(pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB0_OFFSET, FTFx_ERASE_SECTOR); REG_WRITE(pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB1_OFFSET, GET_BIT_16_23(dest)); REG_WRITE(pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB2_OFFSET, GET_BIT_8_15(dest)); REG_WRITE(pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB3_OFFSET, GET_BIT_0_7(dest)); /* calling flash command sequence function to execute the command */ ret = pFlashCommandSequence(pSSDConfig); /* checking the success of command execution */ if(FTFx_OK != ret) { break; } else { /* update size and destination address */ size -= sectorSize; dest += sectorSize; } } EXIT: /* Enter Debug state if enabled */ if (TRUE == (pSSDConfig->DebugEnable)) { ENTER_DEBUG_MODE; } return(ret); }
uint32_t SIZE_OPTIMIZATION FlashReadResource(PFLASH_SSD_CONFIG pSSDConfig, \ uint32_t dest, \ uint8_t* pDataArray, \ uint8_t resourceSelectCode, \ pFLASHCOMMANDSEQUENCE pFlashCommandSequence) { uint8_t i; uint32_t ret = FTFx_OK; /* return code variable */ uint32_t temp; /* convert to byte address */ dest = WORD2BYTE(dest); /* check if the destination is aligned or not */ #if (DEBLOCK_SIZE) temp = WORD2BYTE(pSSDConfig->DFlashBase); if((dest >= temp) && (dest < (temp + pSSDConfig->DFlashSize))) { dest = dest - temp + 0x800000U; } else #endif { temp = WORD2BYTE(pSSDConfig->PFlashBase); if((dest >= temp) && (dest < (temp + pSSDConfig->PFlashSize))) { dest -= temp; } else { ret = FTFx_ERR_ACCERR; } } if(ret == FTFx_OK) { /* clear RDCOLERR & ACCERR & FPVIOL flag in flash status register. Write 1 to clear */ temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FSTAT_OFFSET; REG_WRITE(temp, FTFx_SSD_FSTAT_ERROR_BITS); /* passing parameter to the command */ temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB0_OFFSET; REG_WRITE(temp, FTFx_READ_RESOURCE); temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB1_OFFSET; REG_WRITE(temp, GET_BIT_16_23(dest)); temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB2_OFFSET; REG_WRITE(temp, GET_BIT_8_15(dest)); temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB3_OFFSET; REG_WRITE(temp, GET_BIT_0_7(dest)); temp = pSSDConfig->ftfxRegBase + RSRC_CODE_OFSSET; REG_WRITE(temp, resourceSelectCode); /* calling flash command sequence function to execute the command */ ret = pFlashCommandSequence(pSSDConfig); if (FTFx_OK == ret) { /* Read the data from the FCCOB registers into the pDataArray */ for (i = 0x0U; i < PGM_SIZE_BYTE; i ++) { temp = pSSDConfig->ftfxRegBase + i + 0x08U; pDataArray[i] = REG_READ(temp); } } } #if C90TFS_ENABLE_DEBUG /* Enter Debug state if enabled */ if (TRUE == (pSSDConfig->DebugEnable)) { ENTER_DEBUG_MODE; } #endif return(ret); }
uint32_t SIZE_OPTIMIZATION FlashProgramSection(PFLASH_SSD_CONFIG pSSDConfig, \ uint32_t dest, \ uint16_t number, \ pFLASHCOMMANDSEQUENCE pFlashCommandSequence) { uint32_t ret = FTFx_OK; /* return code variable */ uint32_t temp; /* check RAMRDY bit of the flash configuration register */ temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCNFG_OFFSET; if(0x0U == (REG_BIT_GET(temp, FTFx_SSD_FCNFG_RAMRDY))) { /* return an error code FTFx_ERR_RAMRDY */ ret = FTFx_ERR_RAMRDY; } else { /* convert to byte address */ dest = WORD2BYTE(dest); #if (DEBLOCK_SIZE) temp = WORD2BYTE(pSSDConfig->DFlashBase); if((dest >= temp) && (dest < (temp + pSSDConfig->DFlashSize))) { dest = dest - temp + 0x800000U; } else #endif { temp = WORD2BYTE(pSSDConfig->PFlashBase); if((dest >= temp) && (dest < (temp + pSSDConfig->PFlashSize))) { dest -= temp; } else { ret = FTFx_ERR_ACCERR; } } if(ret == FTFx_OK) { temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FSTAT_OFFSET; REG_WRITE(temp, FTFx_SSD_FSTAT_ERROR_BITS); /* passing parameter to command */ temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB0_OFFSET; REG_WRITE(temp, FTFx_PROGRAM_SECTION); temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB1_OFFSET; REG_WRITE(temp, GET_BIT_16_23(dest)); temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB2_OFFSET; REG_WRITE(temp, GET_BIT_8_15(dest)); temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB3_OFFSET; REG_WRITE(temp, GET_BIT_0_7(dest)); temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB4_OFFSET; REG_WRITE(temp, GET_BIT_8_15(number)); temp = pSSDConfig->ftfxRegBase + FTFx_SSD_FCCOB5_OFFSET; REG_WRITE(temp, GET_BIT_0_7(number)); /* calling flash command sequence function to execute the command */ ret = pFlashCommandSequence(pSSDConfig); } } #if C90TFS_ENABLE_DEBUG /* Enter Debug state if enabled */ if (TRUE == (pSSDConfig->DebugEnable)) { ENTER_DEBUG_MODE; } #endif return(ret); }