Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / core / base16.c
1 /*
2  * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 #include <stdint.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <ipxe/base16.h>
27
28 /** @file
29  *
30  * Base16 encoding
31  *
32  */
33
34 /**
35  * Base16-encode data
36  *
37  * @v raw               Raw data
38  * @v len               Length of raw data
39  * @v encoded           Buffer for encoded string
40  *
41  * The buffer must be the correct length for the encoded string.  Use
42  * something like
43  *
44  *     char buf[ base16_encoded_len ( len ) + 1 ];
45  *
46  * (the +1 is for the terminating NUL) to provide a buffer of the
47  * correct size.
48  */
49 void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) {
50         const uint8_t *raw_bytes = raw;
51         char *encoded_bytes = encoded;
52         size_t remaining = len;
53
54         /* Encode each byte */
55         for ( ; remaining-- ; encoded_bytes += 2 ) {
56                 sprintf ( encoded_bytes, "%02x", *(raw_bytes++) );
57         }
58
59         /* Ensure terminating NUL exists even if length was zero */
60         *encoded_bytes = '\0';
61
62         DBG ( "Base16-encoded to \"%s\":\n", encoded );
63         DBG_HDA ( 0, raw, len );
64         assert ( strlen ( encoded ) == base16_encoded_len ( len ) );
65 }
66
67 /**
68  * Decode hexadecimal string
69  *
70  * @v encoded           Encoded string
71  * @v separator         Byte separator character, or 0 for no separator
72  * @v data              Buffer
73  * @v len               Length of buffer
74  * @ret len             Length of data, or negative error
75  */
76 int hex_decode ( const char *encoded, char separator, void *data, size_t len ) {
77         uint8_t *out = data;
78         unsigned int count = 0;
79         unsigned int sixteens;
80         unsigned int units;
81
82         while ( *encoded ) {
83
84                 /* Check separator, if applicable */
85                 if ( count && separator && ( ( *(encoded++) != separator ) ) )
86                         return -EINVAL;
87
88                 /* Extract digits.  Note that either digit may be NUL,
89                  * which would be interpreted as an invalid value by
90                  * strtoul_charval(); there is therefore no need for an
91                  * explicit end-of-string check.
92                  */
93                 sixteens = strtoul_charval ( *(encoded++) );
94                 if ( sixteens >= 16 )
95                         return -EINVAL;
96                 units = strtoul_charval ( *(encoded++) );
97                 if ( units >= 16 )
98                         return -EINVAL;
99
100                 /* Store result */
101                 if ( count < len )
102                         out[count] = ( ( sixteens << 4 ) | units );
103                 count++;
104
105         }
106         return count;
107 }
108
109 /**
110  * Base16-decode data
111  *
112  * @v encoded           Encoded string
113  * @v raw               Raw data
114  * @ret len             Length of raw data, or negative error
115  *
116  * The buffer must be large enough to contain the decoded data.  Use
117  * something like
118  *
119  *     char buf[ base16_decoded_max_len ( encoded ) ];
120  *
121  * to provide a buffer of the correct size.
122  */
123 int base16_decode ( const char *encoded, uint8_t *raw ) {
124         int len;
125
126         len = hex_decode ( encoded, 0, raw, -1UL );
127         if ( len < 0 )
128                 return len;
129
130         DBG ( "Base16-decoded \"%s\" to:\n", encoded );
131         DBG_HDA ( 0, raw, len );
132         assert ( len <= ( int ) base16_decoded_max_len ( encoded ) );
133
134         return len;
135 }