decode.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,665 行 · 第 1/4 页

C
1,665
字号
  AdapterInfo->MemoryPtr    = CpbPtr->MemoryAddr;
  AdapterInfo->MemoryLength = CpbPtr->MemoryLength;

  CdbPtr->StatCode          = (PXE_STATCODE) E100bInit (AdapterInfo);

  if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {
    CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
  } else {
    AdapterInfo->State = PXE_STATFLAGS_GET_STATE_INITIALIZED;
  }

  return ;
}

VOID
UNDI_Reset (
  IN  PXE_CDB           *CdbPtr,
  IN  NIC_DATA_INSTANCE *AdapterInfo
  )
/*++

Routine Description:
  This routine resets the network adapter and initializes the UNDI using the parameters supplied in
  the CPB.  The transmit and receive queues are emptied and any pending interrupts are cleared.

  If the NIC reset fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED

Arguments:
  CdbPtr            - Pointer to the command descriptor block.
  AdapterInfo       - Pointer to the NIC data structure information which the UNDI driver is layering on..

Returns:
  None

--*/
{
  if (CdbPtr->OpFlags != PXE_OPFLAGS_NOT_USED &&
      CdbPtr->OpFlags != PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS &&
      CdbPtr->OpFlags != PXE_OPFLAGS_RESET_DISABLE_FILTERS ) {

    CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
    CdbPtr->StatCode  = PXE_STATCODE_INVALID_CDB;
    return ;
  }

  CdbPtr->StatCode = (UINT16) E100bReset (AdapterInfo, CdbPtr->OpFlags);

  if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {
    CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
  }
}

VOID
UNDI_Shutdown (
  IN  PXE_CDB           *CdbPtr,
  IN  NIC_DATA_INSTANCE *AdapterInfo
  )
/*++

Routine Description:
  This routine resets the network adapter and leaves it in a safe state for another driver to
  initialize.  Any pending transmits or receives are lost.  Receive filters and external
  interrupt enables are disabled.  Once the UNDI has been shutdown, it can then be stopped
  or initialized again.

  If the NIC reset fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED

  Otherwise, AdapterInfo->State is updated with PXE_STATFLAGS_GET_STATE_STARTED showing the state of
  the NIC as being started.

Arguments:
  CdbPtr            - Pointer to the command descriptor block.
  AdapterInfo       - Pointer to the NIC data structure information which the UNDI driver is layering on..

Returns:
  None

--*/
{
  //
  // do the shutdown stuff here
  //
  CdbPtr->StatCode = (UINT16) E100bShutdown (AdapterInfo);

  if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {
    CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
  } else {
    AdapterInfo->State = PXE_STATFLAGS_GET_STATE_STARTED;
  }

  return ;
}

VOID
UNDI_Interrupt (
  IN  PXE_CDB           *CdbPtr,
  IN  NIC_DATA_INSTANCE *AdapterInfo
  )
/*++

Routine Description:
  This routine can be used to read and/or change the current external interrupt enable
  settings.  Disabling an external interrupt enable prevents and external (hardware)
  interrupt from being signaled by the network device.  Internally the interrupt events
  can still be polled by using the UNDI_GetState command.

  The resulting information on the interrupt state will be passed back in the CdbPtr->StatFlags.

Arguments:
  CdbPtr            - Pointer to the command descriptor block.
  AdapterInfo       - Pointer to the NIC data structure information which the UNDI driver is layering on..

Returns:
  None

--*/
{
  UINT8 IntMask;

  IntMask = (UINT8)(UINTN)(CdbPtr->OpFlags & (PXE_OPFLAGS_INTERRUPT_RECEIVE |
                                              PXE_OPFLAGS_INTERRUPT_TRANSMIT |
                                              PXE_OPFLAGS_INTERRUPT_COMMAND |
                                              PXE_OPFLAGS_INTERRUPT_SOFTWARE));

  switch (CdbPtr->OpFlags & PXE_OPFLAGS_INTERRUPT_OPMASK) {
  case PXE_OPFLAGS_INTERRUPT_READ:
    break;

  case PXE_OPFLAGS_INTERRUPT_ENABLE:
    if (IntMask == 0) {
      CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
      CdbPtr->StatCode  = PXE_STATCODE_INVALID_CDB;
      return ;
    }

    AdapterInfo->int_mask = IntMask;
    E100bSetInterruptState (AdapterInfo);
    break;

  case PXE_OPFLAGS_INTERRUPT_DISABLE:
    if (IntMask != 0) {
      AdapterInfo->int_mask &= ~(IntMask);
      E100bSetInterruptState (AdapterInfo);
      break;
    }

  //
  // else fall thru.
  //
  default:
    CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
    CdbPtr->StatCode  = PXE_STATCODE_INVALID_CDB;
    return ;
  }

  if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_RECEIVE) != 0) {
    CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_RECEIVE;

  }

  if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_TRANSMIT) != 0) {
    CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_TRANSMIT;

  }

  if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_COMMAND) != 0) {
    CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_COMMAND;

  }

  return ;
}

VOID
UNDI_RecFilter (
  IN  PXE_CDB           *CdbPtr,
  IN  NIC_DATA_INSTANCE *AdapterInfo
  )
/*++

Routine Description:
  This routine is used to read and change receive filters and, if supported, read
  and change multicast MAC address filter list.

Arguments:
  CdbPtr            - Pointer to the command descriptor block.
  AdapterInfo       - Pointer to the NIC data structure information which the UNDI driver is layering on..

Returns:
  None

--*/
{
  UINT16                  NewFilter;
  UINT16                  OpFlags;
  PXE_DB_RECEIVE_FILTERS  *DbPtr;
  UINT8                   *MacAddr;
  UINTN                   MacCount;
  UINT16                  Index;
  UINT16                  copy_len;
  UINT8                   *ptr1;
  UINT8                   *ptr2;
  OpFlags   = CdbPtr->OpFlags;
  NewFilter = (UINT16) (OpFlags & 0x1F);

  switch (OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) {
  case PXE_OPFLAGS_RECEIVE_FILTER_READ:

    //
    // not expecting a cpb, not expecting any filter bits
    //
    if ((NewFilter != 0) || (CdbPtr->CPBsize != 0)) {
      goto BadCdb;

    }

    if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) == 0) {
      goto JustRead;

    }

    NewFilter |= AdapterInfo->Rx_Filter;
    //
    // all other flags are ignored except mcast_reset
    //
    break;

  case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE:
    //
    // there should be atleast one other filter bit set.
    //
    if (NewFilter == 0) {
      //
      // nothing to enable
      //
      goto BadCdb;
    }

    if (CdbPtr->CPBsize != 0) {
      //
      // this must be a multicast address list!
      // don't accept the list unless selective_mcast is set
      // don't accept confusing mcast settings with this
      //
      if (((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) == 0) ||
          ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) ||
          ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) ||
          ((CdbPtr->CPBsize % sizeof (PXE_MAC_ADDR)) != 0) ) {
        goto BadCdb;
      }

      MacAddr   = (UINT8 *) ((UINTN) (CdbPtr->CPBaddr));
      MacCount  = CdbPtr->CPBsize / sizeof (PXE_MAC_ADDR);

      for (; MacCount-- != 0; MacAddr += sizeof (PXE_MAC_ADDR)) {
        if (MacAddr[0] != 0x01 || MacAddr[1] != 0x00 || MacAddr[2] != 0x5E || (MacAddr[3] & 0x80) != 0) {
          CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
          CdbPtr->StatCode  = PXE_STATCODE_INVALID_CPB;
          return ;
        }
      }
    }

    //
    // check selective mcast case enable case
    //
    if ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) {
      if (((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) ||
          ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) ) {
        goto BadCdb;

      }
      //
      // if no cpb, make sure we have an old list
      //
      if ((CdbPtr->CPBsize == 0) && (AdapterInfo->mcast_list.list_len == 0)) {
        goto BadCdb;
      }
    }
    //
    // if you want to enable anything, you got to have unicast
    // and you have what you already enabled!
    //
    NewFilter |= (PXE_OPFLAGS_RECEIVE_FILTER_UNICAST | AdapterInfo->Rx_Filter);

    break;

  case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE:

    //
    // mcast list not expected, i.e. no cpb here!
    //
    if (CdbPtr->CPBsize != PXE_CPBSIZE_NOT_USED) {
      goto BadCdb;
    }

    NewFilter = (UINT16) ((~(CdbPtr->OpFlags & 0x1F)) & AdapterInfo->Rx_Filter);

    break;

  default:
    goto BadCdb;
  }

  if ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) {
    AdapterInfo->mcast_list.list_len = 0;
    NewFilter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST);
  }

  E100bSetfilter (AdapterInfo, NewFilter, CdbPtr->CPBaddr, CdbPtr->CPBsize);

JustRead:
  //
  // give the current mcast list
  //
  if ((CdbPtr->DBsize != 0) && (AdapterInfo->mcast_list.list_len != 0)) {
    //
    // copy the mc list to db
    //

    DbPtr = (PXE_DB_RECEIVE_FILTERS *) (UINTN) CdbPtr->DBaddr;
    ptr1  = (UINT8 *) (&DbPtr->MCastList[0]);

    //
    // DbPtr->mc_count = AdapterInfo->mcast_list.list_len;
    //
    copy_len = (UINT16) (AdapterInfo->mcast_list.list_len * PXE_MAC_LENGTH);

    if (copy_len > CdbPtr->DBsize) {
      copy_len = CdbPtr->DBsize;

    }

    ptr2 = (UINT8 *) (&AdapterInfo->mcast_list.mc_list[0]);
    for (Index = 0; Index < copy_len; Index++) {
      ptr1[Index] = ptr2[Index];
    }
  }
  //
  // give the stat flags here
  //
  if (AdapterInfo->Receive_Started) {
    CdbPtr->StatFlags |= AdapterInfo->Rx_Filter;

  }

  return ;

BadCdb:
  CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
  CdbPtr->StatCode  = PXE_STATCODE_INVALID_CDB;
}

VOID
UNDI_StnAddr (
  IN  PXE_CDB           *CdbPtr,
  IN  NIC_DATA_INSTANCE *AdapterInfo
  )
/*++

Routine Description:
  This routine is used to get the current station and broadcast MAC addresses, and to change the
  current station MAC address.

Arguments:
  CdbPtr            - Pointer to the command descriptor block.
  AdapterInfo       - Pointer to the NIC data structure information which the UNDI driver is layering on..

Returns:
  None

--*/
{
  PXE_CPB_STATION_ADDRESS *CpbPtr;
  PXE_DB_STATION_ADDRESS  *DbPtr;
  UINT16                  Index;

  if (CdbPtr->OpFlags == PXE_OPFLAGS_STATION_ADDRESS_RESET) {
    //
    // configure the permanent address.
    // change the AdapterInfo->CurrentNodeAddress field.
    //
    if (EfiCompareMem (
          &AdapterInfo->CurrentNodeAddress[0],
          &AdapterInfo->PermNodeAddress[0],
          PXE_MAC_LENGTH
          ) != 0) {
      for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {
        AdapterInfo->CurrentNodeAddress[Index] = AdapterInfo->PermNodeAddress[Index];
      }

      E100bSetupIAAddr (AdapterInfo);
    }
  }

  if (CdbPtr->CPBaddr != (UINT64) 0) {
    CpbPtr = (PXE_CPB_STATION_ADDRESS *) (UINTN) (CdbPtr->CPBaddr);
    //
    // configure the new address
    //
    for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {
      AdapterInfo->CurrentNodeAddress[Index] = CpbPtr->StationAddr[Index];
    }

    E100bSetupIAAddr (AdapterInfo);
  }

  if (CdbPtr->DBaddr != (UINT64) 0) {
    DbPtr = (PXE_DB_STATION_ADDRESS *) (UINTN) (CdbPtr->DBaddr);
    //
    // fill it with the new values
    //
    for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {
      DbPtr->StationAddr[Index]   = AdapterInfo->CurrentNodeAddress[Index];
      DbPtr->BroadcastAddr[Index] = AdapterInfo->BroadcastNodeAddress[Index];
      DbPtr->PermanentAddr[Index] = AdapterInfo->PermNodeAddress[Index];
    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?