debuggers.hg

view xen/drivers/char/serial.c @ 22855:1d1eec7e1fb4

xl: Perform minimal validation of virtual disk file while parsing config file

This patch performs some very basic validation on the virtual disk
file passed through the config file. This validation ensures that we
don't go too far with the initialization like spawn qemu and more
while there could be some potentially fundamental issues.

[ Patch fixed up to work with PHYSTYPE_EMPTY 22808:6ec61438713a -iwj ]

Signed-off-by: Kamala Narasimhan <kamala.narasimhan@citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Kamala Narasimhan <kamala.narasimhan@gmail.com>
date Tue Jan 25 18:09:49 2011 +0000 (2011-01-25)
parents 5a224e101cb3
children
line source
1 /******************************************************************************
2 * serial.c
3 *
4 * Framework for serial device drivers.
5 *
6 * Copyright (c) 2003-2008, K A Fraser
7 */
9 #include <xen/config.h>
10 #include <xen/delay.h>
11 #include <xen/init.h>
12 #include <xen/irq.h>
13 #include <xen/keyhandler.h>
14 #include <xen/sched.h>
15 #include <xen/mm.h>
16 #include <xen/serial.h>
18 /* Never drop characters, even if the async transmit buffer fills. */
19 /* #define SERIAL_NEVER_DROP_CHARS 1 */
21 unsigned int __read_mostly serial_txbufsz = 16384;
22 size_param("serial_tx_buffer", serial_txbufsz);
24 #define mask_serial_rxbuf_idx(_i) ((_i)&(serial_rxbufsz-1))
25 #define mask_serial_txbuf_idx(_i) ((_i)&(serial_txbufsz-1))
27 static struct serial_port com[2] = {
28 { .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED },
29 { .rx_lock = SPIN_LOCK_UNLOCKED, .tx_lock = SPIN_LOCK_UNLOCKED }
30 };
32 void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
33 {
34 char c;
35 serial_rx_fn fn = NULL;
36 unsigned long flags;
38 spin_lock_irqsave(&port->rx_lock, flags);
40 if ( port->driver->getc(port, &c) )
41 {
42 if ( port->rx != NULL )
43 fn = port->rx;
44 else if ( (c & 0x80) && (port->rx_hi != NULL) )
45 fn = port->rx_hi;
46 else if ( !(c & 0x80) && (port->rx_lo != NULL) )
47 fn = port->rx_lo;
48 else if ( (port->rxbufp - port->rxbufc) != serial_rxbufsz )
49 port->rxbuf[mask_serial_rxbuf_idx(port->rxbufp++)] = c;
50 }
52 spin_unlock_irqrestore(&port->rx_lock, flags);
54 if ( fn != NULL )
55 (*fn)(c & 0x7f, regs);
56 }
58 void serial_tx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
59 {
60 int i;
61 unsigned long flags;
63 local_irq_save(flags);
65 /*
66 * Avoid spinning for a long time: if there is a long-term lock holder
67 * then we know that they'll be stuffing bytes into the transmitter which
68 * will therefore not be empty for long.
69 */
70 while ( !spin_trylock(&port->tx_lock) )
71 {
72 if ( !port->driver->tx_empty(port) )
73 goto out;
74 cpu_relax();
75 }
77 if ( port->driver->tx_empty(port) )
78 {
79 for ( i = 0; i < port->tx_fifo_size; i++ )
80 {
81 if ( port->txbufc == port->txbufp )
82 break;
83 port->driver->putc(
84 port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]);
85 }
86 }
88 spin_unlock(&port->tx_lock);
90 out:
91 local_irq_restore(flags);
92 }
94 static void __serial_putc(struct serial_port *port, char c)
95 {
96 if ( (port->txbuf != NULL) && !port->sync )
97 {
98 /* Interrupt-driven (asynchronous) transmitter. */
100 if ( port->tx_quench )
101 {
102 /* Buffer filled and we are dropping characters. */
103 if ( (port->txbufp - port->txbufc) > (serial_txbufsz / 2) )
104 return;
105 port->tx_quench = 0;
106 }
108 if ( (port->txbufp - port->txbufc) == serial_txbufsz )
109 {
110 if ( port->tx_log_everything )
111 {
112 /* Buffer is full: we spin waiting for space to appear. */
113 int i;
114 while ( !port->driver->tx_empty(port) )
115 cpu_relax();
116 for ( i = 0; i < port->tx_fifo_size; i++ )
117 port->driver->putc(
118 port,
119 port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]);
120 port->txbuf[mask_serial_txbuf_idx(port->txbufp++)] = c;
121 }
122 else
123 {
124 /* Buffer is full: drop chars until buffer is half empty. */
125 port->tx_quench = 1;
126 }
127 return;
128 }
130 if ( ((port->txbufp - port->txbufc) == 0) &&
131 port->driver->tx_empty(port) )
132 {
133 /* Buffer and UART FIFO are both empty. */
134 port->driver->putc(port, c);
135 }
136 else
137 {
138 /* Normal case: buffer the character. */
139 port->txbuf[mask_serial_txbuf_idx(port->txbufp++)] = c;
140 }
141 }
142 else if ( port->driver->tx_empty )
143 {
144 /* Synchronous finite-capacity transmitter. */
145 while ( !port->driver->tx_empty(port) )
146 cpu_relax();
147 port->driver->putc(port, c);
148 }
149 else
150 {
151 /* Simple synchronous transmitter. */
152 port->driver->putc(port, c);
153 }
154 }
156 void serial_putc(int handle, char c)
157 {
158 struct serial_port *port;
159 unsigned long flags;
161 if ( handle == -1 )
162 return;
164 port = &com[handle & SERHND_IDX];
165 if ( !port->driver || !port->driver->putc )
166 return;
168 spin_lock_irqsave(&port->tx_lock, flags);
170 if ( (c == '\n') && (handle & SERHND_COOKED) )
171 __serial_putc(port, '\r' | ((handle & SERHND_HI) ? 0x80 : 0x00));
173 if ( handle & SERHND_HI )
174 c |= 0x80;
175 else if ( handle & SERHND_LO )
176 c &= 0x7f;
178 __serial_putc(port, c);
180 spin_unlock_irqrestore(&port->tx_lock, flags);
181 }
183 void serial_puts(int handle, const char *s)
184 {
185 struct serial_port *port;
186 unsigned long flags;
187 char c;
189 if ( handle == -1 )
190 return;
192 port = &com[handle & SERHND_IDX];
193 if ( !port->driver || !port->driver->putc )
194 return;
196 spin_lock_irqsave(&port->tx_lock, flags);
198 while ( (c = *s++) != '\0' )
199 {
200 if ( (c == '\n') && (handle & SERHND_COOKED) )
201 __serial_putc(port, '\r' | ((handle & SERHND_HI) ? 0x80 : 0x00));
203 if ( handle & SERHND_HI )
204 c |= 0x80;
205 else if ( handle & SERHND_LO )
206 c &= 0x7f;
208 __serial_putc(port, c);
209 }
211 spin_unlock_irqrestore(&port->tx_lock, flags);
212 }
214 char serial_getc(int handle)
215 {
216 struct serial_port *port;
217 char c;
218 unsigned long flags;
220 if ( handle == -1 )
221 return '\0';
223 port = &com[handle & SERHND_IDX];
224 if ( !port->driver || !port->driver->getc )
225 return '\0';
227 do {
228 for ( ; ; )
229 {
230 spin_lock_irqsave(&port->rx_lock, flags);
232 if ( port->rxbufp != port->rxbufc )
233 {
234 c = port->rxbuf[mask_serial_rxbuf_idx(port->rxbufc++)];
235 spin_unlock_irqrestore(&port->rx_lock, flags);
236 break;
237 }
239 if ( port->driver->getc(port, &c) )
240 {
241 spin_unlock_irqrestore(&port->rx_lock, flags);
242 break;
243 }
245 spin_unlock_irqrestore(&port->rx_lock, flags);
247 cpu_relax();
248 udelay(100);
249 }
250 } while ( ((handle & SERHND_LO) && (c & 0x80)) ||
251 ((handle & SERHND_HI) && !(c & 0x80)) );
253 return c & 0x7f;
254 }
256 int serial_parse_handle(char *conf)
257 {
258 int handle;
260 if ( strncmp(conf, "com", 3) )
261 goto fail;
263 switch ( conf[3] )
264 {
265 case '1':
266 handle = 0;
267 break;
268 case '2':
269 handle = 1;
270 break;
271 default:
272 goto fail;
273 }
275 if ( !com[handle].driver )
276 goto fail;
278 if ( conf[4] == 'H' )
279 handle |= SERHND_HI;
280 else if ( conf[4] == 'L' )
281 handle |= SERHND_LO;
283 handle |= SERHND_COOKED;
285 return handle;
287 fail:
288 return -1;
289 }
291 void serial_set_rx_handler(int handle, serial_rx_fn fn)
292 {
293 struct serial_port *port;
294 unsigned long flags;
296 if ( handle == -1 )
297 return;
299 port = &com[handle & SERHND_IDX];
301 spin_lock_irqsave(&port->rx_lock, flags);
303 if ( port->rx != NULL )
304 goto fail;
306 if ( handle & SERHND_LO )
307 {
308 if ( port->rx_lo != NULL )
309 goto fail;
310 port->rx_lo = fn;
311 }
312 else if ( handle & SERHND_HI )
313 {
314 if ( port->rx_hi != NULL )
315 goto fail;
316 port->rx_hi = fn;
317 }
318 else
319 {
320 if ( (port->rx_hi != NULL) || (port->rx_lo != NULL) )
321 goto fail;
322 port->rx = fn;
323 }
325 spin_unlock_irqrestore(&port->rx_lock, flags);
326 return;
328 fail:
329 spin_unlock_irqrestore(&port->rx_lock, flags);
330 printk("ERROR: Conflicting receive handlers for COM%d\n",
331 handle & SERHND_IDX);
332 }
334 void serial_force_unlock(int handle)
335 {
336 struct serial_port *port;
338 if ( handle == -1 )
339 return;
341 port = &com[handle & SERHND_IDX];
343 spin_lock_init(&port->rx_lock);
344 spin_lock_init(&port->tx_lock);
346 serial_start_sync(handle);
347 }
349 void serial_start_sync(int handle)
350 {
351 struct serial_port *port;
352 unsigned long flags;
354 if ( handle == -1 )
355 return;
357 port = &com[handle & SERHND_IDX];
359 spin_lock_irqsave(&port->tx_lock, flags);
361 if ( port->sync++ == 0 )
362 {
363 while ( (port->txbufp - port->txbufc) != 0 )
364 {
365 while ( !port->driver->tx_empty(port) )
366 cpu_relax();
367 port->driver->putc(
368 port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]);
369 }
370 }
372 spin_unlock_irqrestore(&port->tx_lock, flags);
373 }
375 void serial_end_sync(int handle)
376 {
377 struct serial_port *port;
378 unsigned long flags;
380 if ( handle == -1 )
381 return;
383 port = &com[handle & SERHND_IDX];
385 spin_lock_irqsave(&port->tx_lock, flags);
387 port->sync--;
389 spin_unlock_irqrestore(&port->tx_lock, flags);
390 }
392 void serial_start_log_everything(int handle)
393 {
394 struct serial_port *port;
395 unsigned long flags;
397 if ( handle == -1 )
398 return;
400 port = &com[handle & SERHND_IDX];
402 spin_lock_irqsave(&port->tx_lock, flags);
403 port->tx_log_everything++;
404 port->tx_quench = 0;
405 spin_unlock_irqrestore(&port->tx_lock, flags);
406 }
408 void serial_end_log_everything(int handle)
409 {
410 struct serial_port *port;
411 unsigned long flags;
413 if ( handle == -1 )
414 return;
416 port = &com[handle & SERHND_IDX];
418 spin_lock_irqsave(&port->tx_lock, flags);
419 port->tx_log_everything--;
420 spin_unlock_irqrestore(&port->tx_lock, flags);
421 }
423 int serial_tx_space(int handle)
424 {
425 struct serial_port *port;
426 if ( handle == -1 )
427 return serial_txbufsz;
428 port = &com[handle & SERHND_IDX];
429 return serial_txbufsz - (port->txbufp - port->txbufc);
430 }
432 void __devinit serial_init_preirq(void)
433 {
434 int i;
435 for ( i = 0; i < ARRAY_SIZE(com); i++ )
436 if ( com[i].driver && com[i].driver->init_preirq )
437 com[i].driver->init_preirq(&com[i]);
438 }
440 void __devinit serial_init_postirq(void)
441 {
442 int i;
443 for ( i = 0; i < ARRAY_SIZE(com); i++ )
444 if ( com[i].driver && com[i].driver->init_postirq )
445 com[i].driver->init_postirq(&com[i]);
446 }
448 void __init serial_endboot(void)
449 {
450 int i;
451 for ( i = 0; i < ARRAY_SIZE(com); i++ )
452 if ( com[i].driver && com[i].driver->endboot )
453 com[i].driver->endboot(&com[i]);
454 }
456 int serial_irq(int idx)
457 {
458 if ( (idx >= 0) && (idx < ARRAY_SIZE(com)) &&
459 com[idx].driver && com[idx].driver->irq )
460 return com[idx].driver->irq(&com[idx]);
462 return -1;
463 }
465 void serial_suspend(void)
466 {
467 int i, irq;
468 for ( i = 0; i < ARRAY_SIZE(com); i++ )
469 if ( (irq = serial_irq(i)) >= 0 )
470 release_irq(irq);
471 }
473 void serial_resume(void)
474 {
475 serial_init_preirq();
476 serial_init_postirq();
477 }
479 void serial_register_uart(int idx, struct uart_driver *driver, void *uart)
480 {
481 /* Store UART-specific info. */
482 com[idx].driver = driver;
483 com[idx].uart = uart;
485 /* Default is no transmit FIFO. */
486 com[idx].tx_fifo_size = 1;
487 }
489 void serial_async_transmit(struct serial_port *port)
490 {
491 BUG_ON(!port->driver->tx_empty);
492 if ( port->txbuf != NULL )
493 return;
494 if ( serial_txbufsz < 512 )
495 serial_txbufsz = 512;
496 while ( serial_txbufsz & (serial_txbufsz - 1) )
497 serial_txbufsz &= serial_txbufsz - 1;
498 port->txbuf = alloc_xenheap_pages(
499 get_order_from_bytes(serial_txbufsz), 0);
500 }
502 /*
503 * Local variables:
504 * mode: C
505 * c-set-style: "BSD"
506 * c-basic-offset: 4
507 * tab-width: 4
508 * indent-tabs-mode: nil
509 * End:
510 */