1/* 2 * Utilites for XDR encode and decode of data 3 * 4 * Copyright (C) 2015, Broadcom Corporation 5 * All Rights Reserved. 6 * 7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; 8 * the contents of this file may not be disclosed to third parties, copied 9 * or duplicated in any form, in whole or in part, without the prior 10 * written permission of Broadcom Corporation. 11 * 12 * $Id: bcm_xdr.c 419467 2013-08-21 09:19:48Z $ 13 */ 14 15#include <osl.h> 16#include <typedefs.h> 17#include <bcmendian.h> 18#include <bcm_xdr.h> 19 20void 21bcm_xdr_buf_init(bcm_xdr_buf_t *b, void *buf, size_t len) 22{ 23 b->buf = b->origbuf = buf; 24 b->size = b->origsize = (uint)len; 25} 26 27int 28bcm_xdr_pack_uint8_vec(bcm_xdr_buf_t *b, uint8 *vec, uint32 elems) 29{ 30 int err = 0; 31 err = bcm_xdr_pack_opaque(b, elems, vec); 32 33 return err; 34} 35 36int 37bcm_xdr_unpack_uint8_vec(bcm_xdr_buf_t *b, uint8 *vec, uint32 elems) 38{ 39 int err = 0; 40 err = bcm_xdr_unpack_opaque_cpy(b, elems, vec); 41 42 return err; 43} 44 45/* Pack 16-bit vectors */ 46int 47bcm_xdr_pack_uint16_vec(bcm_xdr_buf_t *b, uint len, void *vec) 48{ 49 size_t tot_len, r; 50 int i; 51 uint16 *vec16 = (uint16*)vec, *buf16 = (uint16*)b->buf; 52 ASSERT((len % sizeof(uint16)) == 0); 53 54 /* calc residual padding to 4 bytes */ 55 r = (4 - len) & 3; 56 57 tot_len = len + r; 58 59 if (b->size < tot_len) 60 return -1; 61 62 /* Do the 16 bit swap and copy */ 63 for (i = 0; i < (int)(len/sizeof(uint16)); i++) 64 buf16[i] = htol16(vec16[i]); 65 66 /* Padding */ 67 memset(b->buf + len, 0, r); 68 69 b->size -= tot_len; 70 b->buf += tot_len; 71 72 return 0; 73} 74 75/* Unpack 16-bit vectors */ 76int 77bcm_xdr_unpack_uint16_vec(bcm_xdr_buf_t *b, uint len, void *vec) 78{ 79 int err = 0, i; 80 uint16 *vec16 = (uint16*)vec; 81 ASSERT((len % sizeof(uint16)) == 0); 82 83 err = bcm_xdr_unpack_opaque_cpy(b, len, vec); 84 85 /* Do the 16 bit swapping in the copied buffer */ 86 for (i = 0; i < (int)(len/sizeof(uint16)); i++) 87 vec16[i] = ltoh16(vec16[i]); 88 89 return err; 90} 91 92/* Pack 32-bit vectors */ 93int 94bcm_xdr_pack_uint32_vec(bcm_xdr_buf_t *b, uint len, void *vec) 95{ 96 int i; 97 uint32 *vec32 = (uint32*)vec, *buf32 = (uint32*)b->buf; 98 ASSERT((len % sizeof(uint32)) == 0); 99 100 if (b->size < len) 101 return -1; 102 103 /* Do the 32 bit swap and copy */ 104 for (i = 0; i < (int)(len/sizeof(uint32)); i++) 105 buf32[i] = htol32(vec32[i]); 106 107 b->size -= len; 108 b->buf += len; 109 110 return 0; 111} 112 113/* Unpack 32-bit vectors */ 114int 115bcm_xdr_unpack_uint32_vec(bcm_xdr_buf_t *b, uint len, void *vec) 116{ 117 int err = 0, i; 118 uint32 *vec32 = (uint32*)vec; 119 ASSERT((len % sizeof(uint32)) == 0); 120 121 err = bcm_xdr_unpack_opaque_cpy(b, len, vec); 122 123 /* Do the 32 bit swapping in the copied buffer */ 124 for (i = 0; i < (int)(len/sizeof(uint32)); i++) 125 vec32[i] = ltoh32(vec32[i]); 126 127 return err; 128} 129 130int 131bcm_xdr_pack_uint32(bcm_xdr_buf_t *b, uint32 val) 132{ 133 if (b->size < 4) 134 return -1; 135 136 *(uint32*)(b->buf) = htol32((uint32)val); 137 b->size -= 4; 138 b->buf += 4; 139 140 return 0; 141} 142 143int 144bcm_xdr_unpack_uint32(bcm_xdr_buf_t *b, uint32 *pval) 145{ 146 if (b->size < 4) 147 return -1; 148 149 *pval = ltoh32(*(uint32*)(b->buf)); 150 151 b->size -= 4; 152 b->buf += 4; 153 154 return 0; 155} 156 157int 158bcm_xdr_pack_int32(bcm_xdr_buf_t *b, int32 val) 159{ 160 return bcm_xdr_pack_uint32(b, (uint32)val); 161} 162 163int 164bcm_xdr_unpack_int32(bcm_xdr_buf_t *b, int32 *pval) 165{ 166 return bcm_xdr_unpack_uint32(b, (uint32*)pval); 167} 168 169int 170bcm_xdr_pack_int8(bcm_xdr_buf_t *b, int8 val) 171{ 172 return bcm_xdr_pack_uint32(b, (uint32)val); 173} 174 175int 176bcm_xdr_unpack_int8(bcm_xdr_buf_t *b, int8 *pval) 177{ 178 uint32 val = 0; 179 int err; 180 181 err = bcm_xdr_unpack_uint32(b, &val); 182 *pval = (int8)val; 183 184 return err; 185} 186 187int 188bcm_xdr_pack_opaque_raw(bcm_xdr_buf_t *b, uint len, void *data) 189{ 190 if (b->size < len) 191 return -1; 192 memcpy(b->buf, data, len); 193 194 b->size -= len; 195 b->buf += len; 196 197 return 0; 198} 199 200/* Pad 0 at the remaining part of a rpc buffer */ 201int 202bcm_xdr_pack_opaque_pad(bcm_xdr_buf_t *b) 203{ 204 size_t len; 205 size_t r; 206 207 /* calc residual padding to 4 bytes */ 208 len = (size_t)(b->buf - b->origbuf); 209 r = (4 - len) & 0x3; 210 211 if (r == 0) 212 return 0; 213 214 if (b->size < r) 215 return -1; 216 217 memset(b->buf, 0, r); 218 219 b->size -= r; 220 b->buf += r; 221 222 return 0; 223} 224 225/* pack a word-aligned buffer without dealing with the endianess, pad 0 at the end and make 226 * it word-aligned if len is not multiple of 4 227 */ 228int 229bcm_xdr_pack_opaque(bcm_xdr_buf_t *b, uint len, const void *data) 230{ 231 size_t tot_len; 232 size_t r; 233 234 /* calc residual padding to 4 bytes */ 235 r = (4 - len) & 3; 236 237 tot_len = len + r; 238 239 if (b->size < tot_len) 240 return -1; 241 242 memcpy(b->buf, data, len); 243 memset(b->buf + len, 0, r); 244 245 b->size -= tot_len; 246 b->buf += tot_len; 247 248 return 0; 249} 250 251int 252bcm_xdr_unpack_opaque(bcm_xdr_buf_t *b, uint len, void **pdata) 253{ 254 size_t tot_len; 255 size_t r; 256 257 /* calc residual padding to 4 bytes */ 258 r = (4 - len) & 3; 259 tot_len = len + r; 260 261 if (b->size < tot_len) 262 return -1; 263 264 *pdata = b->buf; 265 266 b->size -= tot_len; 267 b->buf += tot_len; 268 269 return 0; 270} 271 272int 273bcm_xdr_unpack_opaque_cpy(bcm_xdr_buf_t *b, uint len, void *data) 274{ 275 void *xdr_data; 276 int err; 277 278 err = bcm_xdr_unpack_opaque(b, len, &xdr_data); 279 if (err) 280 return err; 281 282 memcpy(data, xdr_data, len); 283 284 return 0; 285} 286 287int 288bcm_xdr_pack_opaque_varlen(bcm_xdr_buf_t *b, uint len, const void *data) 289{ 290 int err; 291 292 err = bcm_xdr_pack_uint32(b, len); 293 if (err) 294 return err; 295 296 return bcm_xdr_pack_opaque(b, len, data); 297} 298 299int 300bcm_xdr_unpack_opaque_varlen(bcm_xdr_buf_t *b, uint *plen, void **pdata) 301{ 302 int err; 303 304 err = bcm_xdr_unpack_uint32(b, plen); 305 if (err) 306 return err; 307 308 return bcm_xdr_unpack_opaque(b, *plen, pdata); 309} 310 311int 312bcm_xdr_pack_string(bcm_xdr_buf_t *b, char *str) 313{ 314 return bcm_xdr_pack_opaque_varlen(b, strlen(str), str); 315} 316 317int 318bcm_xdr_unpack_string(bcm_xdr_buf_t *b, uint *plen, char **pstr) 319{ 320 return bcm_xdr_unpack_opaque_varlen(b, plen, (void**)pstr); 321} 322 323 324int 325bcm_xdr_opaque_resrv(bcm_xdr_buf_t *b, uint len, void **pdata) 326{ 327 return bcm_xdr_unpack_opaque(b, len, pdata); 328} 329 330int 331bcm_xdr_opaque_resrv_varlen(bcm_xdr_buf_t *b, uint len, void **pdata) 332{ 333 int err; 334 err = bcm_xdr_pack_uint32(b, len); 335 336 if (err) 337 return err; 338 339 return bcm_xdr_opaque_resrv(b, len, pdata); 340} 341