david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[serial] Check for UART existence in uart_select()

Check for existence of the UART in uart_select(), not just in
uart_init().  This allows uart_select() to refuse to set a non-working
address in uart->base, which in turns means that the serial console
code will not attempt to use a non-existent UART.

Reported-by: Torgeir Wulfsberg <Torgeir.Wulfsberg@kongsberg.com>
Reported-by: Ján ONDREJ (SAL) <ondrejj@salstar.sk>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2015-07-31 11:19:19 +01:00
parent 9aa55f811a
commit 2849932c48
3 changed files with 42 additions and 16 deletions

View File

@ -48,15 +48,22 @@ static uint16_t uart_base[] = {
* @ret rc Return status code * @ret rc Return status code
*/ */
int uart_select ( struct uart *uart, unsigned int port ) { int uart_select ( struct uart *uart, unsigned int port ) {
int rc;
/* Clear UART base */
uart->base = NULL;
/* Set new UART base */ /* Set new UART base */
if ( port < ( sizeof ( uart_base ) / sizeof ( uart_base[0] ) ) ) { if ( port >= ( sizeof ( uart_base ) / sizeof ( uart_base[0] ) ) ) {
uart->base = ( ( void * ) ( intptr_t ) uart_base[port] ); rc = -ENODEV;
return 0; goto err;
} else {
return -ENODEV;
} }
uart->base = ( ( void * ) ( intptr_t ) uart_base[port] );
/* Check that UART exists */
if ( ( rc = uart_exists ( uart ) ) != 0 )
goto err;
return 0;
err:
uart->base = NULL;
return rc;
} }

View File

@ -79,6 +79,29 @@ void uart_flush ( struct uart *uart ) {
} }
} }
/**
* Check for existence of UART
*
* @v uart UART
* @ret rc Return status code
*/
int uart_exists ( struct uart *uart ) {
/* Fail if no UART port is defined */
if ( ! uart->base )
return -ENODEV;
/* Fail if UART scratch register seems not to be present */
uart_write ( uart, UART_SCR, 0x18 );
if ( uart_read ( uart, UART_SCR ) != 0x18 )
return -ENODEV;
uart_write ( uart, UART_SCR, 0xae );
if ( uart_read ( uart, UART_SCR ) != 0xae )
return -ENODEV;
return 0;
}
/** /**
* Initialise UART * Initialise UART
* *
@ -90,16 +113,11 @@ void uart_flush ( struct uart *uart ) {
int uart_init ( struct uart *uart, unsigned int baud, uint8_t lcr ) { int uart_init ( struct uart *uart, unsigned int baud, uint8_t lcr ) {
uint8_t dlm; uint8_t dlm;
uint8_t dll; uint8_t dll;
int rc;
/* Check for existence of UART */ /* Check for existence of UART */
if ( ! uart->base ) if ( ( rc = uart_exists ( uart ) ) != 0 )
return -ENODEV; return rc;
uart_write ( uart, UART_SCR, 0x18 );
if ( uart_read ( uart, UART_SCR ) != 0x18 )
return -ENODEV;
uart_write ( uart, UART_SCR, 0xae );
if ( uart_read ( uart, UART_SCR ) != 0xae )
return -ENODEV;
/* Configure divisor and line control register, if applicable */ /* Configure divisor and line control register, if applicable */
if ( ! lcr ) if ( ! lcr )

View File

@ -126,6 +126,7 @@ static inline uint8_t uart_receive ( struct uart *uart ) {
extern void uart_transmit ( struct uart *uart, uint8_t data ); extern void uart_transmit ( struct uart *uart, uint8_t data );
extern void uart_flush ( struct uart *uart ); extern void uart_flush ( struct uart *uart );
extern int uart_exists ( struct uart *uart );
extern int uart_init ( struct uart *uart, unsigned int baud, uint8_t lcr ); extern int uart_init ( struct uart *uart, unsigned int baud, uint8_t lcr );
#endif /* _IPXE_UART_H */ #endif /* _IPXE_UART_H */