LIB: Add support for %d and %u format specifiers

These follow standard C printf format specifier semantics:
- %d: print signed integer value
- %u: print unsigned integer value

Change-Id: I0b7a4d519ae0f56f92936796c3541523632df4c6
Signed-off-by: Jackson Cooper-Driver <jackson.cooper-driver@arm.com>
diff --git a/lib/tfm_vprintf/src/tfm_vprintf.c b/lib/tfm_vprintf/src/tfm_vprintf.c
index d8fa4c6..4c77b28 100644
--- a/lib/tfm_vprintf/src/tfm_vprintf.c
+++ b/lib/tfm_vprintf/src/tfm_vprintf.c
@@ -53,20 +53,29 @@
 }
 
 static void output_val(tfm_log_output_str output_func, void *priv, uint32_t val,
-                        uint16_t num_padding, bool zero_padding)
+                        uint16_t num_padding, bool zero_padding, uint8_t base, bool signed_specifier)
 {
     uint8_t digit, chars_to_print;
     uint16_t i;
-    char buf[9];
+    /* uint32_t has maximum value of 4,294,967,295. Require enough space in buffer
+     * for 10 digits + null terminator */
+    char buf[11];
     char *const buf_end = &buf[sizeof(buf) - 1];
     char *buf_ptr = buf_end;
     const char pad_char = zero_padding ? '0' : ' ';
+    const char negative_char = '-';
+    bool negative = false;
+
+    if (signed_specifier && ((int32_t)val < 0)) {
+        val = -val;
+        negative = true;
+    }
 
     /* Ensure buffer ends with NULL character */
     *buf_ptr-- = '\0';
 
     do {
-        digit = val & 0xf;
+        digit = val % base;
 
         if (digit < 10) {
             *buf_ptr-- = '0' + digit;
@@ -74,25 +83,37 @@
             *buf_ptr-- = 'a' + digit - 10;
         }
 
-        val >>= 4;
+        val /= base;
     } while (val);
 
-    chars_to_print = (buf_end - 1) - buf_ptr;
+    chars_to_print = (uint8_t)negative + (buf_end - 1) - buf_ptr;
     if (num_padding > chars_to_print) {
         num_padding -= chars_to_print;
     } else {
         num_padding = 0;
     }
 
+    /* - before 0 */
+    if (negative && zero_padding) {
+        output_char(output_func, priv, negative_char);
+    }
+
     for (i = 0; i < num_padding; i++) {
         output_char(output_func, priv, pad_char);
     }
 
+    /* - after ' ' */
+    if (negative && !zero_padding) {
+        output_char(output_func, priv, negative_char);
+    }
+
     output_str(output_func, priv, buf_ptr + 1);
 }
 
 /* Basic vprintf, understands:
  * %s: output string
+ * %u: output uint32_t in decimal
+ * %d: output int32_t in decimal
  * %x: output uint32_t in hex
  */
 static void tfm_vprintf_internal(tfm_log_output_str output_func,
@@ -121,8 +142,14 @@
         switch (c) {
         case 'l':
             continue;
+        case 'u':
+            output_val(output_func, priv, va_arg(args, uint32_t), num_padding, zero_padding, 10, false);
+            break;
+        case 'd':
+            output_val(output_func, priv, va_arg(args, uint32_t), num_padding, zero_padding, 10, true);
+            break;
         case 'x':
-            output_val(output_func, priv, va_arg(args, uint32_t), num_padding, zero_padding);
+            output_val(output_func, priv, va_arg(args, uint32_t), num_padding, zero_padding, 16, false);
             break;
         case 's':
             output_str(output_func, priv, va_arg(args, char *));