Add a readnum() variant for hex

Yet another read.* helper for read() on various devices.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/include/ns.h b/kern/include/ns.h
index 126f335..d36fdc7 100644
--- a/kern/include/ns.h
+++ b/kern/include/ns.h
@@ -854,6 +854,8 @@
 			void *mem, size_t mem_len);
 int readnum(unsigned long off, char *buf, unsigned long n, unsigned long val,
 			size_t size);
+int readnum_hex(unsigned long off, char *buf, unsigned long n,
+                unsigned long val, size_t size);
 int readstr(unsigned long offset, char *buf, unsigned long n, char *str);
 int readnum_int64_t(uint32_t, char *unused_char_p_t, uint32_t, int64_t, int);
 unsigned long strtoul_from_ubuf(void *ubuf, size_t count, int base);
diff --git a/kern/src/ns/util.c b/kern/src/ns/util.c
index 633d752..333e95e 100644
--- a/kern/src/ns/util.c
+++ b/kern/src/ns/util.c
@@ -20,18 +20,30 @@
 /* Read a num/string to user mode, accounting for offset.  Not a huge fan of the
  * 'size' parameter (the old plan9 users just picked NUMSIZE (12), though they
  * seem to want to limit it).  */
-int readnum(unsigned long off, char *buf, unsigned long n, unsigned long val,
-			size_t size)
+static int __readnum(unsigned long off, char *buf, unsigned long n,
+                     unsigned long val, size_t size, const char *fmt)
 {
 	char tmp[64];
 	size = MIN(sizeof(tmp), size);
 	/* we really need the %* format. */
-	size = snprintf(tmp, size, "%lu", val);
+	size = snprintf(tmp, size, fmt, val);
 	/* size is now strlen, so the rest of this is just like readstr. */
 	/* always include the \0 */
 	return readmem(off, buf, n, tmp, size + 1);
 }
 
+int readnum(unsigned long off, char *buf, unsigned long n, unsigned long val,
+            size_t size)
+{
+	return __readnum(off, buf, n, val, size, "%lu");
+}
+
+int readnum_hex(unsigned long off, char *buf, unsigned long n,
+                unsigned long val, size_t size)
+{
+	return __readnum(off, buf, n, val, size, "0x%lx");
+}
+
 int readstr(unsigned long offset, char *buf, unsigned long n, char *str)
 {
 	/* always include the \0 */
@@ -48,7 +60,8 @@
 	if (count > sizeof(num64)) {
 		set_errno(EINVAL);
 		error(EFAIL, "attempted to write %d chars, max %d", count,
-			  sizeof(num64)); }
+			  sizeof(num64));
+	}
 	memcpy(num64, ubuf, count);
 	num64[count] = 0;	/* enforce trailing 0 */
 	return strtoul(num64, 0, base);