+{
+ int ret;
+
+ va_list ap;
+ va_start(ap, fmt);
+ ret = vprintf_internal(fmt, ap, __builtin_return_address(0));
+ va_end(ap);
+
+ return ret;
+}
+
+__attribute__((noinline,not_tail_called))
+int
+vprintf(const char *fmt, va_list ap)
+{
+ return vprintf_internal(fmt, ap, __builtin_return_address(0));
+}
+
+void
+consdebug_putc(char c)
+{
+ if (!disableConsoleOutput)
+ cnputc(c);
+
+ debug_putc(c);
+
+ if (!console_is_serial() && !disable_serial_output)
+ PE_kputc(c);
+}
+
+void
+consdebug_putc_unbuffered(char c)
+{
+ if (!disableConsoleOutput)
+ cnputc_unbuffered(c);
+
+ debug_putc(c);
+
+ if (!console_is_serial() && !disable_serial_output)
+ PE_kputc(c);
+}
+
+void
+consdebug_log(char c)
+{
+ debug_putc(c);
+}
+
+/*
+ * Append contents to the paniclog buffer but don't flush
+ * it. This is mainly used for writing the actual paniclog
+ * contents since flushing once for every line written
+ * would be prohibitively expensive for the paniclog
+ */
+int
+paniclog_append_noflush(const char *fmt, ...)
+{
+ va_list listp;
+
+ va_start(listp, fmt);
+ _doprnt_log(fmt, &listp, consdebug_putc, 16);
+ va_end(listp);
+
+ return 0;
+}
+
+int
+kdb_printf(const char *fmt, ...)
+{
+ va_list listp;
+
+ va_start(listp, fmt);
+ _doprnt_log(fmt, &listp, consdebug_putc, 16);
+ va_end(listp);
+
+#if CONFIG_EMBEDDED
+ paniclog_flush();
+#endif
+
+ return 0;
+}
+
+int
+kdb_log(const char *fmt, ...)
+{
+ va_list listp;
+
+ va_start(listp, fmt);
+ _doprnt(fmt, &listp, consdebug_log, 16);
+ va_end(listp);
+
+#if CONFIG_EMBEDDED
+ paniclog_flush();
+#endif
+
+ return 0;
+}
+
+int
+kdb_printf_unbuffered(const char *fmt, ...)