void early_putch(char c);
void early_flush(void);
-void early_puts(const char *s)
+void early_puts(const char *s, size_t nr)
{
- while (*s != '\0') {
+ while ( nr-- > 0 )
+ {
if (*s == '\n')
early_putch('\r');
early_putch(*s);
static char __initdata opt_gdb[30];
string_param("gdb", opt_gdb);
-static void gdbstub_console_puts(const char *str);
+static void gdbstub_console_puts(const char *str, size_t nr);
/* value <-> char (de)serialzers */
static char
static struct gdb_context *gdb_ctx = &__gdb_ctx;
static void
-gdbstub_console_puts(const char *str)
+gdbstub_console_puts(const char *str, size_t nr)
{
const char *p;
gdb_start_packet(gdb_ctx);
gdb_write_to_packet_char('O', gdb_ctx);
- for ( p = str; *p != '\0'; p++ )
+ for ( p = str; nr > 0; p++, nr-- )
{
gdb_write_to_packet_char(hex2char((*p>>4) & 0x0f), gdb_ctx );
gdb_write_to_packet_char(hex2char((*p) & 0x0f), gdb_ctx );
static char serial_rx_ring[SERIAL_RX_SIZE];
static unsigned int serial_rx_cons, serial_rx_prod;
-static void (*serial_steal_fn)(const char *) = early_puts;
+static void (*serial_steal_fn)(const char *, size_t nr) = early_puts;
-int console_steal(int handle, void (*fn)(const char *))
+int console_steal(int handle, void (*fn)(const char *, size_t nr))
{
if ( (handle == -1) || (handle != sercon_handle) )
return 0;
serial_steal_fn = NULL;
}
-static void sercon_puts(const char *s)
+static void sercon_puts(const char *s, size_t nr)
{
if ( serial_steal_fn != NULL )
- (*serial_steal_fn)(s);
+ serial_steal_fn(s, nr);
else
- serial_puts(sercon_handle, s);
+ serial_puts(sercon_handle, s, nr);
/* Copy all serial output into PV console */
- pv_console_puts(s);
+ pv_console_puts(s, nr);
}
static void dump_console_ring_key(unsigned char key)
sofar += len;
c += len;
}
- buf[sofar] = '\0';
- sercon_puts(buf);
- video_puts(buf);
+ sercon_puts(buf, sofar);
+ video_puts(buf, sofar);
free_xenheap_pages(buf, order);
}
static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer, int count)
{
char kbuf[128];
- int kcount = 0;
+ unsigned int kcount = 0;
struct domain *cd = current->domain;
while ( count > 0 )
kcount = min_t(int, count, sizeof(kbuf)-1);
if ( copy_from_guest(kbuf, buffer, kcount) )
return -EFAULT;
- kbuf[kcount] = '\0';
if ( is_hardware_domain(cd) )
{
/* Use direct console output as it could be interactive */
spin_lock_irq(&console_lock);
- sercon_puts(kbuf);
- video_puts(kbuf);
+ sercon_puts(kbuf, kcount);
+ video_puts(kbuf, kcount);
#ifdef CONFIG_X86
if ( opt_console_xen )
{
- size_t len = strlen(kbuf);
-
if ( xen_guest )
- xen_hypercall_console_write(kbuf, len);
+ xen_hypercall_console_write(kbuf, kcount);
else
- xen_console_write_debug_port(kbuf, len);
+ xen_console_write_debug_port(kbuf, kcount);
}
#endif
char *kin = kbuf, *kout = kbuf, c;
/* Strip non-printable characters */
- for ( ; ; )
+ do
{
c = *kin++;
- if ( c == '\0' || c == '\n' )
+ if ( c == '\n' )
break;
if ( isprint(c) || c == '\t' )
*kout++ = c;
- }
+ } while ( --kcount > 0 );
+
*kout = '\0';
spin_lock(&cd->pbuf_lock);
+ kcount = kin - kbuf;
if ( c == '\n' )
{
- kcount = kin - kbuf;
cd->pbuf[cd->pbuf_idx] = '\0';
guest_printk(cd, XENLOG_G_DEBUG "%s%s\n", cd->pbuf, kbuf);
cd->pbuf_idx = 0;
static void __putstr(const char *str)
{
+ size_t len = strlen(str);
+
ASSERT(spin_is_locked(&console_lock));
- sercon_puts(str);
- video_puts(str);
+ sercon_puts(str, len);
+ video_puts(str, len);
#ifdef CONFIG_X86
if ( opt_console_xen )
{
- size_t len = strlen(str);
-
if ( xen_guest )
xen_hypercall_console_write(str, len);
else
char cntbuf[24];
va_list args;
unsigned long flags;
+ unsigned int nr;
if ( debugtrace_bytes == 0 )
return;
ASSERT(debugtrace_buf[debugtrace_bytes - 1] == 0);
va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
+ nr = vscnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if ( debugtrace_send_to_console )
{
- snprintf(cntbuf, sizeof(cntbuf), "%u ", ++count);
- serial_puts(sercon_handle, cntbuf);
- serial_puts(sercon_handle, buf);
+ unsigned int n = scnprintf(cntbuf, sizeof(cntbuf), "%u ", ++count);
+
+ serial_puts(sercon_handle, cntbuf, n);
+ serial_puts(sercon_handle, buf, nr);
}
else
{
* **************************************************************
*/
-static void suspend_steal_fn(const char *str) { }
+static void suspend_steal_fn(const char *str, size_t nr) { }
static int suspend_steal_id;
int console_suspend(void)
if ( idx >= BUF_SZ )
{
- pv_console_puts(buf);
+ pv_console_puts(buf, BUF_SZ);
idx = 0;
}
}
if ( idx )
- {
- buf[idx] = '\0';
- pv_console_puts(buf);
- }
+ pv_console_puts(buf, idx);
/* No need for a mem barrier because every character was already consumed */
barrier();
spin_unlock_irqrestore(&port->tx_lock, flags);
}
-void serial_puts(int handle, const char *s)
+void serial_puts(int handle, const char *s, size_t nr)
{
struct serial_port *port;
unsigned long flags;
- char c;
if ( handle == -1 )
return;
spin_lock_irqsave(&port->tx_lock, flags);
- while ( (c = *s++) != '\0' )
+ for ( ; nr > 0; nr--, s++ )
{
+ char c = *s;
+
if ( (c == '\n') && (handle & SERHND_COOKED) )
__serial_putc(port, '\r' | ((handle & SERHND_HI) ? 0x80 : 0x00));
return recv;
}
-static size_t pv_ring_puts(const char *buf)
+static size_t pv_ring_puts(const char *buf, size_t nr)
{
XENCONS_RING_IDX cons, prod;
size_t sent = 0, avail;
bool put_r = false;
- while ( buf[sent] != '\0' || put_r )
+ while ( sent < nr || put_r )
{
cons = ACCESS_ONCE(cons_ring->out_cons);
prod = cons_ring->out_prod;
continue;
}
- while ( avail && (buf[sent] != '\0' || put_r) )
+ while ( avail && (sent < nr || put_r) )
{
if ( put_r )
{
return sent;
}
-void pv_console_puts(const char *buf)
+void pv_console_puts(const char *buf, size_t nr)
{
unsigned long flags;
return;
spin_lock_irqsave(&tx_lock, flags);
- pv_ring_puts(buf);
+ pv_ring_puts(buf, nr);
spin_unlock_irqrestore(&tx_lock, flags);
}
}
/* Fast mode which redraws all modified parts of a 2D text buffer. */
-void lfb_redraw_puts(const char *s)
+void lfb_redraw_puts(const char *s, size_t nr)
{
unsigned int i, min_redraw_y = lfb.ypos;
- char c;
/* Paste characters into text buffer. */
- while ( (c = *s++) != '\0' )
+ for ( ; nr > 0; nr--, s++ )
{
+ char c = *s;
+
if ( (c == '\n') || (lfb.xpos >= lfb.lfbp.text_columns) )
{
if ( ++lfb.ypos >= lfb.lfbp.text_rows )
}
/* Slower line-based scroll mode which interacts better with dom0. */
-void lfb_scroll_puts(const char *s)
+void lfb_scroll_puts(const char *s, size_t nr)
{
unsigned int i;
- char c;
- while ( (c = *s++) != '\0' )
+ for ( ; nr > 0; nr--, s++ )
{
+ char c = *s;
+
if ( (c == '\n') || (lfb.xpos >= lfb.lfbp.text_columns) )
{
unsigned int bytes = (lfb.lfbp.width *
unsigned int text_rows;
};
-void lfb_redraw_puts(const char *s);
-void lfb_scroll_puts(const char *s);
+void lfb_redraw_puts(const char *s, size_t nr);
+void lfb_scroll_puts(const char *s, size_t nr);
void lfb_carriage_return(void);
void lfb_free(void);
static unsigned int xpos, ypos;
static unsigned char *video;
-static void vga_text_puts(const char *s);
-static void vga_noop_puts(const char *s) {}
-void (*video_puts)(const char *) = vga_noop_puts;
+static void vga_text_puts(const char *s, size_t nr);
+static void vga_noop_puts(const char *s, size_t nr) {}
+void (*video_puts)(const char *, size_t nr) = vga_noop_puts;
/*
* 'vga=<mode-specifier>[,keep]' where <mode-specifier> is one of:
}
}
-static void vga_text_puts(const char *s)
+static void vga_text_puts(const char *s, size_t nr)
{
- char c;
-
- while ( (c = *s++) != '\0' )
+ for ( ; nr > 0; nr--, s++ )
{
+ char c = *s;
+
if ( (c == '\n') || (xpos >= columns) )
{
if ( ++ypos >= lines )
* Steal output from the console. Returns +ve identifier, else -ve error.
* Takes the handle of the serial line to steal, and steal callback function.
*/
-int console_steal(int handle, void (*fn)(const char *));
+int console_steal(int handle, void (*fn)(const char *, size_t nr));
/* Give back stolen console. Takes the identifier returned by console_steal. */
void console_giveback(int id);
#define __XEN_EARLY_PRINTK_H__
#ifdef CONFIG_EARLY_PRINTK
-void early_puts(const char *s);
+void early_puts(const char *s, size_t nr);
#else
#define early_puts NULL
#endif
void pv_console_init(void);
void pv_console_set_rx_handler(serial_rx_fn fn);
void pv_console_init_postirq(void);
-void pv_console_puts(const char *buf);
+void pv_console_puts(const char *buf, size_t nr);
size_t pv_console_rx(struct cpu_user_regs *regs);
evtchn_port_t pv_console_evtchn(void);
static inline void pv_console_init(void) {}
static inline void pv_console_set_rx_handler(serial_rx_fn fn) { }
static inline void pv_console_init_postirq(void) { }
-static inline void pv_console_puts(const char *buf) { }
+static inline void pv_console_puts(const char *buf, size_t nr) { }
static inline size_t pv_console_rx(struct cpu_user_regs *regs) { return 0; }
evtchn_port_t pv_console_evtchn(void)
{
/* Transmit a single character via the specified COM port. */
void serial_putc(int handle, char c);
-/* Transmit a NULL-terminated string via the specified COM port. */
-void serial_puts(int handle, const char *s);
+/* Transmit a string via the specified COM port. */
+void serial_puts(int handle, const char *s, size_t nr);
/*
* An alternative to registering a character-receive hook. This function
#ifdef CONFIG_VIDEO
void video_init(void);
-extern void (*video_puts)(const char *);
+extern void (*video_puts)(const char *, size_t nr);
void video_endboot(void);
#else
#define video_init() ((void)0)
-#define video_puts(s) ((void)0)
+static inline void video_puts(const char *str, size_t nr) {}
#define video_endboot() ((void)0)
#endif