Raul Rangel has uploaded this change for review. ( https://review.coreboot.org/25411
Change subject: src/include/hexutil.h: Add converters for working with hex strings ......................................................................
src/include/hexutil.h: Add converters for working with hex strings
These utilities will be used as part of fixing SMBIOS generation for soc/amd.
I have a bunch of unit tests for these functions outside of this commit. Is there somewhere I can commit them?
BUG=b:65403853 TEST=tested on grunt
Change-Id: Ifcabf09be4dc053f8b6e132b4014380cdb5c521b Signed-off-by: Raul E Rangel rrangel@chromium.org --- A src/include/hexutil.h M src/lib/Makefile.inc A src/lib/hexutil.c 3 files changed, 137 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/11/25411/1
diff --git a/src/include/hexutil.h b/src/include/hexutil.h new file mode 100644 index 0000000..847d39c --- /dev/null +++ b/src/include/hexutil.h @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 Google LLC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef HEXUTIL_H +#define HEXUTIL_H + +#include <stddef.h> +#include <stdint.h> + +/** + * Decodes a hex character [0-9A-Za-z] into a byte. + * + * Invalid characters are mapped to 0. + * */ +uint8_t decode_hex_character(char hex); + +/** + * Decodes a hex string into a byte array. + * + * Examples: + * * "01AF" => {0x01, 0xAF} + * * "1AF" => {0x01, 0xAF} + * * "1AF" => {0x00, 0x00, 0x01, 0xAF} w/ 4 byte dest buffer. + * + * @param src_size size of the src buffer + * @param dest_size must be at least (strlen(src) + 1) / 2 in size. If the + * buffer is bigger than required the most significant bytes are cleared. + */ +void decode_hex_string(const char *src, size_t src_size, uint8_t *dest, + size_t dest_size); + +/** + * Encodes a byte array into a hex string. + * + * e.g., {0x01, 0x02} => "0102" + * + * @param dest_size must be at least (src_size * 2 + 1). If it is smaller, the + * least significant bytes will be truncated. + * @return number of characters written excluding the null terminator. + */ +size_t encode_as_hex_string(const uint8_t *src, size_t src_size, char *dest, + size_t dest_size); +#endif diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 960b5cb..3ae77a6 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -133,6 +133,7 @@ ramstage-$(CONFIG_GENERIC_GPIO_LIB) += gpio.c ramstage-$(CONFIG_GENERIC_UDELAY) += timer.c ramstage-y += b64_decode.c +ramstage-y += hexutil.c ramstage-$(CONFIG_ACPI_NHLT) += nhlt.c
romstage-y += cbmem_common.c diff --git a/src/lib/hexutil.c b/src/lib/hexutil.c new file mode 100644 index 0000000..a41a94a --- /dev/null +++ b/src/lib/hexutil.c @@ -0,0 +1,81 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 Google LLC. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <hexutil.h> +#include <string.h> + +uint8_t decode_hex_character(char hex) +{ + if (isdigit(hex)) + return hex - '0'; + else if (isxdigit(hex) && isupper(hex)) + return hex - 'A' + 10; + else if (isxdigit(hex) && islower(hex)) + return hex - 'a' + 10; + else + return 0; +} + +void decode_hex_string(const char *src, size_t src_size, uint8_t *dest, + size_t dest_size) +{ + const size_t src_len = strnlen(src, src_size); + + for (size_t dest_idx = 0; dest_idx < dest_size; ++dest_idx) { + int src_idx = (src_len - 1) - dest_idx * 2; + + uint8_t byte = 0; + + if (src_idx >= 0) { + char low = src[src_idx]; + byte |= decode_hex_character(low); + } + + if (src_idx >= 1) { + char high = src[src_idx - 1]; + byte |= decode_hex_character(high) << 4; + } + + dest[(dest_size - 1) - dest_idx] = byte; + } +} + +size_t encode_as_hex_string(const uint8_t *src, size_t src_size, char *dest, + size_t dest_size) +{ + size_t cnt = 0; + + if (src_size == 0 && dest_size > 0) + dest[0] = '\0'; + + for (size_t src_idx = 0; src_idx < src_size; ++src_idx) { + size_t dest_offset = src_idx * 2; + + if (dest_offset + 3 <= dest_size) { + snprintf(dest + dest_offset, 3, "%02hhx", src[src_idx]); + cnt += 2; + } else if (dest_offset + 2 <= dest_size) { + snprintf(dest + dest_offset, 2, "%hhx", + src[src_idx] >> 4); + cnt += 1; + } else if (dest_offset < dest_size) { + dest[dest_offset] = '\0'; + + break; + } + } + + return cnt; +}