+/*
+ * Perform the blob buffer reversal byte wise.
+ * This api makes the first byte the last and
+ * vice-versa.
+ *
+ * blob [in] The blob's data to be used for swap.
+ * chunk_size[in] the swap is done within the chunk in bytes
+ *
+ * returns void.
+ */
+void
+ulp_blob_perform_byte_reverse(struct ulp_blob *blob,
+ uint32_t chunk_size)
+{
+ uint32_t idx = 0, jdx = 0, num = 0;
+ uint8_t xchar;
+ uint8_t *buff;
+
+ /* validate the arguments */
+ if (!blob) {
+ BNXT_TF_DBG(ERR, "invalid argument\n");
+ return; /* failure */
+ }
+
+ buff = blob->data;
+ num = ULP_BITS_2_BYTE(blob->write_idx) / chunk_size;
+ for (idx = 0; idx < num; idx++) {
+ for (jdx = 0; jdx < chunk_size / 2; jdx++) {
+ xchar = buff[jdx];
+ buff[jdx] = buff[(chunk_size - 1) - jdx];
+ buff[(chunk_size - 1) - jdx] = xchar;
+ }
+ buff += chunk_size;
+ }
+}
+
+/*
+ * Perform the blob buffer 64 bit word swap.
+ * This api makes the first 4 bytes the last in
+ * a given 64 bit value and vice-versa.
+ *
+ * blob [in] The blob's data to be used for swap.
+ *
+ * returns void.
+ */
+void
+ulp_blob_perform_64B_word_swap(struct ulp_blob *blob)
+{
+ uint32_t i, j, num;
+ uint8_t xchar;
+ uint32_t word_size = ULP_64B_IN_BYTES / 2;
+
+ /* validate the arguments */
+ if (!blob) {
+ BNXT_TF_DBG(ERR, "invalid argument\n");
+ return; /* failure */
+ }
+ num = ULP_BITS_2_BYTE(blob->write_idx);
+ for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
+ for (j = 0; j < word_size; j++) {
+ xchar = blob->data[i + j];
+ blob->data[i + j] = blob->data[i + j + word_size];
+ blob->data[i + j + word_size] = xchar;
+ }
+ }
+}
+
+/*
+ * Perform the blob buffer 64 bit byte swap.
+ * This api makes the first byte the last in
+ * a given 64 bit value and vice-versa.
+ *
+ * blob [in] The blob's data to be used for swap.
+ *
+ * returns void.
+ */
+void
+ulp_blob_perform_64B_byte_swap(struct ulp_blob *blob)
+{
+ uint32_t i, j, num;
+ uint8_t xchar;
+ uint32_t offset = ULP_64B_IN_BYTES - 1;
+
+ /* validate the arguments */
+ if (!blob) {
+ BNXT_TF_DBG(ERR, "invalid argument\n");
+ return; /* failure */
+ }
+ num = ULP_BITS_2_BYTE(blob->write_idx);
+ for (i = 0; i < num; i = i + ULP_64B_IN_BYTES) {
+ for (j = 0; j < (ULP_64B_IN_BYTES / 2); j++) {
+ xchar = blob->data[i + j];
+ blob->data[i + j] = blob->data[i + offset - j];
+ blob->data[i + offset - j] = xchar;
+ }
+ }
+}
+
+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;
+}
+