+static int32_t
+ulp_blob_msb_block_merge(struct ulp_blob *dst, struct ulp_blob *src,
+ uint32_t block_size, uint32_t pad)
+{
+ uint32_t i, k, write_bytes, remaining;
+ uint16_t num;
+ uint8_t *src_buf = ulp_blob_data_get(src, &num);
+ uint8_t bluff;
+
+ for (i = 0; i < num;) {
+ if (((dst->write_idx % block_size) + (num - i)) > block_size)
+ write_bytes = block_size -
+ (dst->write_idx % block_size);
+ else
+ write_bytes = num - i;
+ for (k = 0; k < ULP_BITS_2_BYTE_NR(write_bytes); k++) {
+ ulp_bs_put_msb(dst->data, dst->write_idx, ULP_BLOB_BYTE,
+ *src_buf);
+ dst->write_idx += ULP_BLOB_BYTE;
+ src_buf++;
+ }
+ remaining = write_bytes % ULP_BLOB_BYTE;
+ if (remaining) {
+ bluff = (*src_buf) & ((uint8_t)-1 <<
+ (ULP_BLOB_BYTE - remaining));
+ ulp_bs_put_msb(dst->data, dst->write_idx,
+ ULP_BLOB_BYTE, bluff);
+ dst->write_idx += remaining;
+ }
+ if (write_bytes != (num - i)) {
+ /* add the padding */
+ ulp_blob_pad_push(dst, pad);
+ if (remaining) {
+ ulp_bs_put_msb(dst->data, dst->write_idx,
+ ULP_BLOB_BYTE - remaining,
+ *src_buf);
+ dst->write_idx += ULP_BLOB_BYTE - remaining;
+ src_buf++;
+ }
+ }
+ i += write_bytes;
+ }
+ return 0;
+}
+
+/*
+ * Perform the blob buffer merge.
+ * This api makes the src blob merged to the dst blob.
+ * The block size and pad size help in padding the dst blob
+ *
+ * dst [in] The destination blob, the blob to be merged.
+ * src [in] The src blob.
+ * block_size [in] The size of the block after which padding gets applied.
+ * pad [in] The size of the pad to be applied.
+ *
+ * returns 0 on success.
+ */
+int32_t
+ulp_blob_block_merge(struct ulp_blob *dst, struct ulp_blob *src,
+ uint32_t block_size, uint32_t pad)
+{
+ if (dst->byte_order == BNXT_ULP_BYTE_ORDER_BE &&
+ src->byte_order == BNXT_ULP_BYTE_ORDER_BE)
+ return ulp_blob_msb_block_merge(dst, src, block_size, pad);
+
+ BNXT_TF_DBG(ERR, "block merge not implemented yet\n");
+ return -EINVAL;
+}
+
+int32_t
+ulp_blob_append(struct ulp_blob *dst, struct ulp_blob *src,
+ uint16_t src_offset, uint16_t src_len)
+{
+ uint32_t k, remaining;
+ uint16_t num;
+ uint8_t bluff;
+ uint8_t *src_buf = ulp_blob_data_get(src, &num);
+
+ if ((src_offset + src_len) > num)
+ return -EINVAL;
+
+ /* Only supporting BE for now */
+ if (src->byte_order != BNXT_ULP_BYTE_ORDER_BE ||
+ dst->byte_order != BNXT_ULP_BYTE_ORDER_BE)
+ return -EINVAL;
+
+ /* Handle if the source offset is not on a byte boundary */
+ remaining = src_offset % ULP_BLOB_BYTE;
+ if (remaining) {
+ bluff = src_buf[src_offset / ULP_BLOB_BYTE] & ((uint8_t)-1 >>
+ (ULP_BLOB_BYTE - remaining));
+ ulp_bs_put_msb(dst->data, dst->write_idx,
+ ULP_BLOB_BYTE, bluff);
+ dst->write_idx += remaining;
+ src_offset += remaining;
+ }
+
+ src_buf += ULP_BITS_2_BYTE_NR(src_offset);
+
+ /* Push the byte aligned pieces */
+ for (k = 0; k < ULP_BITS_2_BYTE_NR(src_len); k++) {
+ ulp_bs_put_msb(dst->data, dst->write_idx, ULP_BLOB_BYTE,
+ *src_buf);
+ dst->write_idx += ULP_BLOB_BYTE;
+ src_buf++;
+ }
+
+ /* Handle the remaining if length is not a byte boundary */
+ remaining = src_len % ULP_BLOB_BYTE;
+ if (remaining) {
+ bluff = (*src_buf) & ((uint8_t)-1 <<
+ (ULP_BLOB_BYTE - remaining));
+ ulp_bs_put_msb(dst->data, dst->write_idx,
+ ULP_BLOB_BYTE, bluff);
+ dst->write_idx += remaining;
+ }
+
+ return 0;
+}
+
+/*
+ * Perform the blob buffer copy.
+ * This api makes the src blob merged to the dst blob.
+ *
+ * dst [in] The destination blob, the blob to be merged.
+ * src [in] The src blob.
+ *
+ * returns 0 on success.
+ */
+int32_t
+ulp_blob_buffer_copy(struct ulp_blob *dst, struct ulp_blob *src)
+{
+ if ((dst->write_idx + src->write_idx) > dst->bitlen) {
+ BNXT_TF_DBG(ERR, "source buffer too large\n");
+ return -EINVAL;
+ }
+ if (ULP_BITS_IS_BYTE_NOT_ALIGNED(dst->write_idx) ||
+ ULP_BITS_IS_BYTE_NOT_ALIGNED(src->write_idx)) {
+ BNXT_TF_DBG(ERR, "source buffer is not aligned\n");
+ return -EINVAL;
+ }
+ memcpy(&dst->data[ULP_BITS_2_BYTE_NR(dst->write_idx)],
+ src->data, ULP_BITS_2_BYTE_NR(src->write_idx));
+ dst->write_idx += src->write_idx;
+ return 0;
+}
+