Skip to content

Commit

Permalink
[serial] Check for UART existence in uart_select()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
mcb30 committed Jul 31, 2015
1 parent 9aa55f8 commit 2849932
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 15 deletions.
23 changes: 15 additions & 8 deletions src/arch/x86/core/x86_uart.c
Expand Up @@ -48,15 +48,22 @@ static uint16_t uart_base[] = {
* @ret rc Return status code
*/
int uart_select ( struct uart *uart, unsigned int port ) {

/* Clear UART base */
uart->base = NULL;
int rc;

/* Set new UART base */
if ( port < ( sizeof ( uart_base ) / sizeof ( uart_base[0] ) ) ) {
uart->base = ( ( void * ) ( intptr_t ) uart_base[port] );
return 0;
} else {
return -ENODEV;
if ( port >= ( sizeof ( uart_base ) / sizeof ( uart_base[0] ) ) ) {
rc = -ENODEV;
goto err;
}
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;
}
32 changes: 25 additions & 7 deletions src/core/uart.c
Expand Up @@ -80,27 +80,45 @@ void uart_flush ( struct uart *uart ) {
}

/**
* Initialise UART
* Check for existence of UART
*
* @v uart UART
* @v baud Baud rate, or zero to leave unchanged
* @v lcr Line control register value, or zero to leave unchanged
* @ret rc Return status code
*/
int uart_init ( struct uart *uart, unsigned int baud, uint8_t lcr ) {
uint8_t dlm;
uint8_t dll;
int uart_exists ( struct uart *uart ) {

/* Check for existence of 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
*
* @v uart UART
* @v baud Baud rate, or zero to leave unchanged
* @v lcr Line control register value, or zero to leave unchanged
* @ret rc Return status code
*/
int uart_init ( struct uart *uart, unsigned int baud, uint8_t lcr ) {
uint8_t dlm;
uint8_t dll;
int rc;

/* Check for existence of UART */
if ( ( rc = uart_exists ( uart ) ) != 0 )
return rc;

/* Configure divisor and line control register, if applicable */
if ( ! lcr )
lcr = uart_read ( uart, UART_LCR );
Expand Down
1 change: 1 addition & 0 deletions src/include/ipxe/uart.h
Expand Up @@ -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_flush ( struct uart *uart );
extern int uart_exists ( struct uart *uart );
extern int uart_init ( struct uart *uart, unsigned int baud, uint8_t lcr );

#endif /* _IPXE_UART_H */

0 comments on commit 2849932

Please sign in to comment.