Skip to content

Commit

Permalink
Silicon/Synopsys/DesignWare: DwEmacSnpDxe: Fix bug in EmacGetDmaStatus
Browse files Browse the repository at this point in the history
The EFI spec (see UEFI 2.10, 24.1.12) requires EFI_SIMPLE_NETWORK's
GetStatus() method to handle NULL InterruptStatus pointers by not
reading nor clearing the interrupt status from the device.

However, EmacGetDmaStatus (part of the DwEmacSnpDxe GetStatus()
implementation) did not correctly handle NULL IrqStat, despite already
being tagged as an OPTIONAL argument. This made calling GetStatus() with
a NULL pointer (for example, the call in MnpRecycleTxBuf) either corrupt
memory or straight-up crash.

Make it EFI spec compliant, by adding proper NULL pointer checks around
RI_SET_MSK and TI_SET_MSK retrieval/clearing.

Signed-off-by: Yang Wang <wangyzhaoz@163.com>
[ardb: update commit log according to Pedro's suggestion]
Acked-by: Pedro Falcato <pedro.falcato@gmail.com>
Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
  • Loading branch information
wangy566 authored and ardbiesheuvel committed Jul 29, 2023
1 parent 4f31689 commit cbab3c4
Showing 1 changed file with 14 additions and 8 deletions.
22 changes: 14 additions & 8 deletions Silicon/Synopsys/DesignWare/Drivers/DwEmacSnpDxe/EmacDxeUtil.c
Original file line number Diff line number Diff line change
Expand Up @@ -500,24 +500,30 @@ EmacGetDmaStatus (
UINT32 ErrorBit;
UINT32 Mask = 0;

if (IrqStat != NULL) {
*IrqStat = 0;
}

DmaStatus = MmioRead32 (MacBaseAddress +
DW_EMAC_DMAGRP_STATUS_OFST);
if (DmaStatus & DW_EMAC_DMAGRP_STATUS_NIS_SET_MSK) {
Mask |= DW_EMAC_DMAGRP_STATUS_NIS_SET_MSK;
// Rx interrupt
if (DmaStatus & DW_EMAC_DMAGRP_STATUS_RI_SET_MSK) {
*IrqStat |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
Mask |= DW_EMAC_DMAGRP_STATUS_RI_SET_MSK;
} else {
*IrqStat &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
if (IrqStat != NULL) {
*IrqStat |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
Mask |= DW_EMAC_DMAGRP_STATUS_RI_SET_MSK;
}
}

// Tx interrupt
if (DmaStatus & DW_EMAC_DMAGRP_STATUS_TI_SET_MSK) {
*IrqStat |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
Mask |= DW_EMAC_DMAGRP_STATUS_TI_SET_MSK;
} else {
*IrqStat &= ~EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
if (IrqStat != NULL) {
*IrqStat |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
Mask |= DW_EMAC_DMAGRP_STATUS_TI_SET_MSK;
}
}

// Tx Buffer
if (DmaStatus & DW_EMAC_DMAGRP_STATUS_TU_SET_MSK){
Mask |= DW_EMAC_DMAGRP_STATUS_TU_SET_MSK;
Expand Down

0 comments on commit cbab3c4

Please sign in to comment.