You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
341 lines
5.8 KiB
C
341 lines
5.8 KiB
C
/*
|
|
* Utilites for XDR encode and decode of data
|
|
*
|
|
* Copyright (C) 2013, Broadcom Corporation
|
|
* All Rights Reserved.
|
|
*
|
|
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
|
|
* the contents of this file may not be disclosed to third parties, copied
|
|
* or duplicated in any form, in whole or in part, without the prior
|
|
* written permission of Broadcom Corporation.
|
|
*
|
|
* $Id: bcm_xdr.c 419467 2013-08-21 09:19:48Z $
|
|
*/
|
|
|
|
#include <osl.h>
|
|
#include <typedefs.h>
|
|
#include <bcmendian.h>
|
|
#include <bcm_xdr.h>
|
|
|
|
void
|
|
bcm_xdr_buf_init(bcm_xdr_buf_t *b, void *buf, size_t len)
|
|
{
|
|
b->buf = b->origbuf = buf;
|
|
b->size = b->origsize = (uint)len;
|
|
}
|
|
|
|
int
|
|
bcm_xdr_pack_uint8_vec(bcm_xdr_buf_t *b, uint8 *vec, uint32 elems)
|
|
{
|
|
int err = 0;
|
|
err = bcm_xdr_pack_opaque(b, elems, vec);
|
|
|
|
return err;
|
|
}
|
|
|
|
int
|
|
bcm_xdr_unpack_uint8_vec(bcm_xdr_buf_t *b, uint8 *vec, uint32 elems)
|
|
{
|
|
int err = 0;
|
|
err = bcm_xdr_unpack_opaque_cpy(b, elems, vec);
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Pack 16-bit vectors */
|
|
int
|
|
bcm_xdr_pack_uint16_vec(bcm_xdr_buf_t *b, uint len, void *vec)
|
|
{
|
|
size_t tot_len, r;
|
|
int i;
|
|
uint16 *vec16 = (uint16*)vec, *buf16 = (uint16*)b->buf;
|
|
ASSERT((len % sizeof(uint16)) == 0);
|
|
|
|
/* calc residual padding to 4 bytes */
|
|
r = (4 - len) & 3;
|
|
|
|
tot_len = len + r;
|
|
|
|
if (b->size < tot_len)
|
|
return -1;
|
|
|
|
/* Do the 16 bit swap and copy */
|
|
for (i = 0; i < (int)(len/sizeof(uint16)); i++)
|
|
buf16[i] = htol16(vec16[i]);
|
|
|
|
/* Padding */
|
|
memset(b->buf + len, 0, r);
|
|
|
|
b->size -= tot_len;
|
|
b->buf += tot_len;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Unpack 16-bit vectors */
|
|
int
|
|
bcm_xdr_unpack_uint16_vec(bcm_xdr_buf_t *b, uint len, void *vec)
|
|
{
|
|
int err = 0, i;
|
|
uint16 *vec16 = (uint16*)vec;
|
|
ASSERT((len % sizeof(uint16)) == 0);
|
|
|
|
err = bcm_xdr_unpack_opaque_cpy(b, len, vec);
|
|
|
|
/* Do the 16 bit swapping in the copied buffer */
|
|
for (i = 0; i < (int)(len/sizeof(uint16)); i++)
|
|
vec16[i] = ltoh16(vec16[i]);
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Pack 32-bit vectors */
|
|
int
|
|
bcm_xdr_pack_uint32_vec(bcm_xdr_buf_t *b, uint len, void *vec)
|
|
{
|
|
int i;
|
|
uint32 *vec32 = (uint32*)vec, *buf32 = (uint32*)b->buf;
|
|
ASSERT((len % sizeof(uint32)) == 0);
|
|
|
|
if (b->size < len)
|
|
return -1;
|
|
|
|
/* Do the 32 bit swap and copy */
|
|
for (i = 0; i < (int)(len/sizeof(uint32)); i++)
|
|
buf32[i] = htol32(vec32[i]);
|
|
|
|
b->size -= len;
|
|
b->buf += len;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Unpack 32-bit vectors */
|
|
int
|
|
bcm_xdr_unpack_uint32_vec(bcm_xdr_buf_t *b, uint len, void *vec)
|
|
{
|
|
int err = 0, i;
|
|
uint32 *vec32 = (uint32*)vec;
|
|
ASSERT((len % sizeof(uint32)) == 0);
|
|
|
|
err = bcm_xdr_unpack_opaque_cpy(b, len, vec);
|
|
|
|
/* Do the 32 bit swapping in the copied buffer */
|
|
for (i = 0; i < (int)(len/sizeof(uint32)); i++)
|
|
vec32[i] = ltoh32(vec32[i]);
|
|
|
|
return err;
|
|
}
|
|
|
|
int
|
|
bcm_xdr_pack_uint32(bcm_xdr_buf_t *b, uint32 val)
|
|
{
|
|
if (b->size < 4)
|
|
return -1;
|
|
|
|
*(uint32*)(b->buf) = htol32((uint32)val);
|
|
b->size -= 4;
|
|
b->buf += 4;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
bcm_xdr_unpack_uint32(bcm_xdr_buf_t *b, uint32 *pval)
|
|
{
|
|
if (b->size < 4)
|
|
return -1;
|
|
|
|
*pval = ltoh32(*(uint32*)(b->buf));
|
|
|
|
b->size -= 4;
|
|
b->buf += 4;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
bcm_xdr_pack_int32(bcm_xdr_buf_t *b, int32 val)
|
|
{
|
|
return bcm_xdr_pack_uint32(b, (uint32)val);
|
|
}
|
|
|
|
int
|
|
bcm_xdr_unpack_int32(bcm_xdr_buf_t *b, int32 *pval)
|
|
{
|
|
return bcm_xdr_unpack_uint32(b, (uint32*)pval);
|
|
}
|
|
|
|
int
|
|
bcm_xdr_pack_int8(bcm_xdr_buf_t *b, int8 val)
|
|
{
|
|
return bcm_xdr_pack_uint32(b, (uint32)val);
|
|
}
|
|
|
|
int
|
|
bcm_xdr_unpack_int8(bcm_xdr_buf_t *b, int8 *pval)
|
|
{
|
|
uint32 val = 0;
|
|
int err;
|
|
|
|
err = bcm_xdr_unpack_uint32(b, &val);
|
|
*pval = (int8)val;
|
|
|
|
return err;
|
|
}
|
|
|
|
int
|
|
bcm_xdr_pack_opaque_raw(bcm_xdr_buf_t *b, uint len, void *data)
|
|
{
|
|
if (b->size < len)
|
|
return -1;
|
|
memcpy(b->buf, data, len);
|
|
|
|
b->size -= len;
|
|
b->buf += len;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Pad 0 at the remaining part of a rpc buffer */
|
|
int
|
|
bcm_xdr_pack_opaque_pad(bcm_xdr_buf_t *b)
|
|
{
|
|
size_t len;
|
|
size_t r;
|
|
|
|
/* calc residual padding to 4 bytes */
|
|
len = (size_t)(b->buf - b->origbuf);
|
|
r = (4 - len) & 0x3;
|
|
|
|
if (r == 0)
|
|
return 0;
|
|
|
|
if (b->size < r)
|
|
return -1;
|
|
|
|
memset(b->buf, 0, r);
|
|
|
|
b->size -= r;
|
|
b->buf += r;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* pack a word-aligned buffer without dealing with the endianess, pad 0 at the end and make
|
|
* it word-aligned if len is not multiple of 4
|
|
*/
|
|
int
|
|
bcm_xdr_pack_opaque(bcm_xdr_buf_t *b, uint len, const void *data)
|
|
{
|
|
size_t tot_len;
|
|
size_t r;
|
|
|
|
/* calc residual padding to 4 bytes */
|
|
r = (4 - len) & 3;
|
|
|
|
tot_len = len + r;
|
|
|
|
if (b->size < tot_len)
|
|
return -1;
|
|
|
|
memcpy(b->buf, data, len);
|
|
memset(b->buf + len, 0, r);
|
|
|
|
b->size -= tot_len;
|
|
b->buf += tot_len;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
bcm_xdr_unpack_opaque(bcm_xdr_buf_t *b, uint len, void **pdata)
|
|
{
|
|
size_t tot_len;
|
|
size_t r;
|
|
|
|
/* calc residual padding to 4 bytes */
|
|
r = (4 - len) & 3;
|
|
tot_len = len + r;
|
|
|
|
if (b->size < tot_len)
|
|
return -1;
|
|
|
|
*pdata = b->buf;
|
|
|
|
b->size -= tot_len;
|
|
b->buf += tot_len;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
bcm_xdr_unpack_opaque_cpy(bcm_xdr_buf_t *b, uint len, void *data)
|
|
{
|
|
void *xdr_data;
|
|
int err;
|
|
|
|
err = bcm_xdr_unpack_opaque(b, len, &xdr_data);
|
|
if (err)
|
|
return err;
|
|
|
|
memcpy(data, xdr_data, len);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
bcm_xdr_pack_opaque_varlen(bcm_xdr_buf_t *b, uint len, const void *data)
|
|
{
|
|
int err;
|
|
|
|
err = bcm_xdr_pack_uint32(b, len);
|
|
if (err)
|
|
return err;
|
|
|
|
return bcm_xdr_pack_opaque(b, len, data);
|
|
}
|
|
|
|
int
|
|
bcm_xdr_unpack_opaque_varlen(bcm_xdr_buf_t *b, uint *plen, void **pdata)
|
|
{
|
|
int err;
|
|
|
|
err = bcm_xdr_unpack_uint32(b, plen);
|
|
if (err)
|
|
return err;
|
|
|
|
return bcm_xdr_unpack_opaque(b, *plen, pdata);
|
|
}
|
|
|
|
int
|
|
bcm_xdr_pack_string(bcm_xdr_buf_t *b, char *str)
|
|
{
|
|
return bcm_xdr_pack_opaque_varlen(b, strlen(str), str);
|
|
}
|
|
|
|
int
|
|
bcm_xdr_unpack_string(bcm_xdr_buf_t *b, uint *plen, char **pstr)
|
|
{
|
|
return bcm_xdr_unpack_opaque_varlen(b, plen, (void**)pstr);
|
|
}
|
|
|
|
|
|
int
|
|
bcm_xdr_opaque_resrv(bcm_xdr_buf_t *b, uint len, void **pdata)
|
|
{
|
|
return bcm_xdr_unpack_opaque(b, len, pdata);
|
|
}
|
|
|
|
int
|
|
bcm_xdr_opaque_resrv_varlen(bcm_xdr_buf_t *b, uint len, void **pdata)
|
|
{
|
|
int err;
|
|
err = bcm_xdr_pack_uint32(b, len);
|
|
|
|
if (err)
|
|
return err;
|
|
|
|
return bcm_xdr_opaque_resrv(b, len, pdata);
|
|
}
|