hv: vuart: fix 'Shifting value too far'

MISRA-C requires that shift operation cannot exceed the word length.

What this patch does:
- Fix the bug in 'vuart_init'
  The register 'dll' and 'dlh' should be uint8_t rather than char.
  'dll' is the lower 8-bit of divisor.
  'dlh' is the higher 8-bit of divisor.
  So, the shift value should be 8U rather than 16U.
- Fix other data type issues regarding to the registers in 'struct
  vuart'
  The registers should be unsigned variables.

v1 -> v2:
 * Use a local variable 'uint8_t value_u8 = (uint8_t)value' to avoid
   mutiple times type conversion
 * Use '(uint8_t)divisor' rather than '(uint8_t)(divisor & 0xFFU)' to
   get the lower 8 bit of 'divisor'
   Direct type conversion is safe and simple per Xiangyang's suggestion.

Tracked-On: #861
Signed-off-by: Shiqing Gao <shiqing.gao@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
Shiqing Gao 2018-08-14 15:14:54 +08:00 committed by lijinxia
parent de487fff2b
commit 3df3c9f6a1
2 changed files with 31 additions and 31 deletions

View File

@ -133,12 +133,13 @@ static void vuart_toggle_intr(struct vuart *vu)
} }
} }
static void vuart_write(__unused struct vm_io_handler *hdlr, static void vuart_write(__unused struct vm_io_handler *hdlr, struct vm *vm,
struct vm *vm, uint16_t offset_arg, uint16_t offset_arg, __unused size_t width, uint32_t value)
__unused size_t width, uint32_t value)
{ {
uint16_t offset = offset_arg; uint16_t offset = offset_arg;
struct vuart *vu = vm_vuart(vm); struct vuart *vu = vm_vuart(vm);
uint8_t value_u8 = (uint8_t)value;
offset -= vu->base; offset -= vu->base;
vuart_lock(vu); vuart_lock(vu);
/* /*
@ -146,19 +147,19 @@ static void vuart_write(__unused struct vm_io_handler *hdlr,
*/ */
if ((vu->lcr & LCR_DLAB) != 0) { if ((vu->lcr & LCR_DLAB) != 0) {
if (offset == UART16550_DLL) { if (offset == UART16550_DLL) {
vu->dll = value; vu->dll = value_u8;
goto done; goto done;
} }
if (offset == UART16550_DLM) { if (offset == UART16550_DLM) {
vu->dlh = value; vu->dlh = value_u8;
goto done; goto done;
} }
} }
switch (offset) { switch (offset) {
case UART16550_THR: case UART16550_THR:
fifo_putchar(&vu->txfifo, value); fifo_putchar(&vu->txfifo, value_u8);
vu->thre_int_pending = true; vu->thre_int_pending = true;
break; break;
case UART16550_IER: case UART16550_IER:
@ -166,26 +167,26 @@ static void vuart_write(__unused struct vm_io_handler *hdlr,
* Apply mask so that bits 4-7 are 0 * Apply mask so that bits 4-7 are 0
* Also enables bits 0-3 only if they're 1 * Also enables bits 0-3 only if they're 1
*/ */
vu->ier = value & 0x0FU; vu->ier = value_u8 & 0x0FU;
break; break;
case UART16550_FCR: case UART16550_FCR:
/* /*
* The FCR_ENABLE bit must be '1' for the programming * The FCR_ENABLE bit must be '1' for the programming
* of other FCR bits to be effective. * of other FCR bits to be effective.
*/ */
if ((value & FCR_FIFOE) == 0U) { if ((value_u8 & FCR_FIFOE) == 0U) {
vu->fcr = 0; vu->fcr = 0U;
} else { } else {
if ((value & FCR_RFR) != 0U) { if ((value_u8 & FCR_RFR) != 0U) {
fifo_reset(&vu->rxfifo); fifo_reset(&vu->rxfifo);
} }
vu->fcr = value & vu->fcr = value_u8 &
(FCR_FIFOE | FCR_DMA | FCR_RX_MASK); (FCR_FIFOE | FCR_DMA | FCR_RX_MASK);
} }
break; break;
case UART16550_LCR: case UART16550_LCR:
vu->lcr = value; vu->lcr = value_u8;
break; break;
case UART16550_MCR: case UART16550_MCR:
/* ignore modem */ /* ignore modem */
@ -202,7 +203,7 @@ static void vuart_write(__unused struct vm_io_handler *hdlr,
*/ */
break; break;
case UART16550_SCR: case UART16550_SCR:
vu->scr = value; vu->scr = value_u8;
break; break;
default: default:
/* /*
@ -218,14 +219,13 @@ done:
vuart_unlock(vu); vuart_unlock(vu);
} }
static uint32_t vuart_read(__unused struct vm_io_handler *hdlr, static uint32_t vuart_read(__unused struct vm_io_handler *hdlr, struct vm *vm,
struct vm *vm, uint16_t offset_arg, uint16_t offset_arg, __unused size_t width)
__unused size_t width)
{ {
uint16_t offset = offset_arg; uint16_t offset = offset_arg;
char iir, reg; uint8_t iir, reg, intr_reason;
uint8_t intr_reason;
struct vuart *vu = vm_vuart(vm); struct vuart *vu = vm_vuart(vm);
offset -= vu->base; offset -= vu->base;
vuart_lock(vu); vuart_lock(vu);
/* /*
@ -295,7 +295,7 @@ static uint32_t vuart_read(__unused struct vm_io_handler *hdlr,
done: done:
vuart_toggle_intr(vu); vuart_toggle_intr(vu);
vuart_unlock(vu); vuart_unlock(vu);
return reg; return (uint32_t)reg;
} }
static void vuart_register_io_handler(struct vm *vm) static void vuart_register_io_handler(struct vm *vm)
@ -370,8 +370,8 @@ void *vuart_init(struct vm *vm)
/* Set baud rate*/ /* Set baud rate*/
divisor = UART_CLOCK_RATE / BAUD_9600 / 16U; divisor = UART_CLOCK_RATE / BAUD_9600 / 16U;
vu->dll = divisor; vu->dll = (uint8_t)divisor;
vu->dlh = divisor >> 16U; vu->dlh = (uint8_t)(divisor >> 8U);
vu->active = false; vu->active = false;
vu->base = COM1_BASE; vu->base = COM1_BASE;

View File

@ -39,16 +39,16 @@ struct fifo {
}; };
struct vuart { struct vuart {
char data; /* Data register (R/W) */ uint8_t data; /* Data register (R/W) */
char ier; /* Interrupt enable register (R/W) */ uint8_t ier; /* Interrupt enable register (R/W) */
char lcr; /* Line control register (R/W) */ uint8_t lcr; /* Line control register (R/W) */
char mcr; /* Modem control register (R/W) */ uint8_t mcr; /* Modem control register (R/W) */
char lsr; /* Line status register (R/W) */ uint8_t lsr; /* Line status register (R/W) */
char msr; /* Modem status register (R/W) */ uint8_t msr; /* Modem status register (R/W) */
char fcr; /* FIFO control register (W) */ uint8_t fcr; /* FIFO control register (W) */
char scr; /* Scratch register (R/W) */ uint8_t scr; /* Scratch register (R/W) */
char dll; /* Baudrate divisor latch LSB */ uint8_t dll; /* Baudrate divisor latch LSB */
char dlh; /* Baudrate divisor latch MSB */ uint8_t dlh; /* Baudrate divisor latch MSB */
struct fifo rxfifo; struct fifo rxfifo;
struct fifo txfifo; struct fifo txfifo;