summaryrefslogtreecommitdiff
path: root/util/nvmutil/lib/num.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/nvmutil/lib/num.c')
-rw-r--r--util/nvmutil/lib/num.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/util/nvmutil/lib/num.c b/util/nvmutil/lib/num.c
new file mode 100644
index 00000000..dd6e9901
--- /dev/null
+++ b/util/nvmutil/lib/num.c
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (c) 2026 Leah Rowe <leah@libreboot.org>
+ *
+ * Numerical functions.
+ */
+
+#ifdef __OpenBSD__
+#include <sys/param.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "../include/common.h"
+
+unsigned short
+hextonum(char ch_s)
+{
+ unsigned char ch;
+
+ ch = (unsigned char)ch_s;
+
+ if ((unsigned int)(ch - '0') <= 9)
+ return ch - '0';
+
+ ch |= 0x20;
+
+ if ((unsigned int)(ch - 'a') <= 5)
+ return ch - 'a' + 10;
+
+ if (ch == '?' || ch == 'x')
+ return (unsigned short)rlong() & 0xf;
+
+ return 16; /* invalid character */
+}
+
+/*
+ * Portable random
+ * number generator
+ */
+unsigned long
+rlong(void)
+{
+#if (defined(__OpenBSD__) && (OpenBSD) >= 201) || \
+ defined(__FreeBSD__) || \
+ defined(__NetBSD__) || defined(__APPLE__)
+
+ unsigned long rval;
+ arc4random_buf(&rval, sizeof(unsigned long));
+
+ return rval;
+#else
+ int fd;
+
+ long nr;
+
+ unsigned long rval;
+
+ fd = open("/dev/urandom", O_RDONLY | O_BINARY);
+
+#ifdef __OpenBSD__
+ if (fd < 0) /* old openbsd */
+ fd = open("/dev/arandom", O_RDONLY | O_BINARY);
+#endif
+
+ if (fd < 0)
+ fd = open("/dev/random", O_RDONLY | O_BINARY);
+
+ if (fd < 0)
+ err(errno, "can't open random device");
+
+ nr = rw_file_exact(fd, (unsigned char *)&rval,
+ sizeof(unsigned long), 0, IO_READ, LOOP_EAGAIN,
+ LOOP_EINTR, MAX_ZERO_RW_RETRY, OFF_ERR);
+
+ if (x_i_close(fd) < 0)
+ err(errno, "Can't close randomness fd");
+
+ if (nr != sizeof(unsigned long))
+ err(errno, "Incomplete read from random device");
+
+ return rval;
+#endif
+}
+
+void
+check_bin(unsigned long a, const char *a_name)
+{
+ if (a > 1)
+ err(EINVAL, "%s must be 0 or 1, but is %lu",
+ a_name, (unsigned long)a);
+}