bc.c

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

C
2,547
字号
        break;
      }
      //
      // Packet was received.  Make received callback then return.
      //
      if (CallbackPtr != NULL) {
        StatCode = CallbackPtr (
                    Private->CallbackProtocolPtr,
                    Function,
                    TRUE,
                    (UINT32) *BufferSizePtr,
                    (EFI_PXE_BASE_CODE_PACKET *) Private->ReceiveBufferPtr
                    );

        if (StatCode != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {
          StatCode = EFI_ABORTED;
        } else {
          StatCode = EFI_SUCCESS;
        }
      }

      break;
    }

#else
    //
    // Poll for received packet.
    //
    *BufferSizePtr = BUFFER_ALLOCATE_SIZE;

    StatCode = SnpPtr->Receive (
                        SnpPtr,
                        HeaderSizePtr,
                        BufferSizePtr,
                        Private->ReceiveBufferPtr,
                        0,
                        0,
                        ProtocolPtr
                        );

    if (!EFI_ERROR (StatCode)) {
      //
      // Packet was received.  Make received callback then return.
      //
      if (CallbackPtr != NULL) {
        StatCode = CallbackPtr (
                    Private->CallbackProtocolPtr,
                    Function,
                    TRUE,
                    (UINT32) *BufferSizePtr,
                    (EFI_PXE_BASE_CODE_PACKET *) Private->ReceiveBufferPtr
                    );

        if (StatCode != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {
          StatCode = EFI_ABORTED;
        } else {
          StatCode = EFI_SUCCESS;
        }
      }

      break;
    }

    if (StatCode != EFI_NOT_READY) {
      break;
    }
#endif
    //
    // Check for callback event.
    //
    if (!EFI_ERROR (gBS->CheckEvent (CallbackEvent))) {
      //
      // Make periodic callback if callback pointer is initialized.
      //
      if (CallbackPtr != NULL) {
        StatCode = CallbackPtr (
                    Private->CallbackProtocolPtr,
                    Function,
                    FALSE,
                    0,
                    NULL
                    );

        //
        // Abort if directed to by callback routine.
        //
        if (StatCode != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {
          StatCode = EFI_ABORTED;
          break;
        }
      }
    }
    //
    // Check for timeout event.
    //
    if (TimeoutEvent == 0) {
      StatCode = EFI_TIMEOUT;
      break;
    }

    if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
      StatCode = EFI_TIMEOUT;
      break;
    }
    //
    // Check IGMP timer events.
    //
    IgmpCheckTimers (Private);
  }

  gBS->CloseEvent (CallbackEvent);

  return StatCode;
}

EFI_STATUS
SendPacket (
  PXE_BASECODE_DEVICE           *Private,
  VOID                          *HeaderPtr,
  VOID                          *PacketPtr,
  INTN                          PacketLen,
  VOID                          *HardwareAddr,
  UINT16                        MediaProtocol,
  IN EFI_PXE_BASE_CODE_FUNCTION Function
  )
/*++

  Routine Description:
    Routine which does an SNP->Transmit of a buffer

  Arguments:
    Private       - Pointer to Pxe BaseCode Protocol
    HeaderPtr          - Pointer to the buffer 
    PacketPtr          - Pointer to the packet to send
    PacketLen        - The length of the entire packet to send
    HardwareAddr        - Pointer to the MAC address of the destination
    MediaProtocol - What type of frame to create (RFC 1700) - IE. Ethernet
    Function      - What PXE function to callback

  Returns:
    0             - Something was sent
    !0            - An error was encountered during sending of a packet

--*/
{
  EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;
  EFI_SIMPLE_NETWORK_MODE     *SnpModePtr;
  EFI_PXE_CALLBACK            CallbackPtr;
  EFI_STATUS                  StatCode;
  EFI_EVENT                   TimeoutEvent;
  UINT32                      IntStatus;
  VOID                        *TxBuf;

  //
  //
  //
  CallbackPtr = Private->EfiBc.Mode->MakeCallbacks ? Private->CallbackProtocolPtr->Callback : 0;

  SnpPtr      = Private->SimpleNetwork;
  SnpModePtr  = SnpPtr->Mode;

  //
  // clear prior interrupt status
  //
  StatCode = SnpPtr->GetStatus (SnpPtr, &IntStatus, 0);

  if (EFI_ERROR (StatCode)) {
    DEBUG (
      (EFI_D_WARN,
      "\nSendPacket()  Exit #1  %xh (%r)",
      StatCode,
      StatCode)
      );
    return StatCode;
  }

  Private->DidTransmit = FALSE;

  if (CallbackPtr != NULL) {
    if (CallbackPtr (
          Private->CallbackProtocolPtr,
          Function,
          FALSE,
          (UINT32) PacketLen,
          PacketPtr
          ) != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {
      DEBUG (
        (EFI_D_WARN,
        "\nSendPacket()  Exit #2  %xh (%r)",
        EFI_ABORTED,
        EFI_ABORTED)
        );
      return EFI_ABORTED;
    }
  }
  //
  // put packet in transmit queue
  // headersize should be zero if not filled in
  //
  StatCode = gBS->CreateEvent (
                    EFI_EVENT_TIMER,
                    EFI_TPL_CALLBACK,
                    NULL,
                    NULL,
                    &TimeoutEvent
                    );

  if (EFI_ERROR (StatCode)) {
    DEBUG (
      (EFI_D_ERROR,
      "Could not create transmit timeout event.  %r\n",
      StatCode)
      );
    return EFI_DEVICE_ERROR;
  }

  //
  // 5 milliseconds
  //
  StatCode = gBS->SetTimer (
                    TimeoutEvent,
                    TimerRelative,
                    50000
                    );

  if (EFI_ERROR (StatCode)) {
    DEBUG (
      (EFI_D_ERROR,
      "Could not set transmit timeout event timer.  %r\n",
      StatCode)
      );
    gBS->CloseEvent (TimeoutEvent);
    return EFI_DEVICE_ERROR;
  }

  for (;;) {
    StatCode = SnpPtr->Transmit (
                        SnpPtr,
                        (UINTN) SnpPtr->Mode->MediaHeaderSize,
                        (UINTN) (PacketLen + SnpPtr->Mode->MediaHeaderSize),
                        HeaderPtr,
                        &SnpModePtr->CurrentAddress,
                        (EFI_MAC_ADDRESS *) HardwareAddr,
                        &MediaProtocol
                        );

    if (StatCode != EFI_NOT_READY) {
      break;
    }

    if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
      StatCode = EFI_TIMEOUT;
      break;
    }
  }

  gBS->CloseEvent (TimeoutEvent);

  if (EFI_ERROR (StatCode)) {
    DEBUG (
      (EFI_D_WARN,
      "\nSendPacket()  Exit #3  %xh (%r)",
      StatCode,
      StatCode)
      );
    return StatCode;
  }
  //
  // remove transmit buffer from snp's unused queue
  // done this way in case someday things are buffered and we don't get it back
  // immediately
  //
  StatCode = gBS->CreateEvent (
                    EFI_EVENT_TIMER,
                    EFI_TPL_CALLBACK,
                    NULL,
                    NULL,
                    &TimeoutEvent
                    );

  if (EFI_ERROR (StatCode)) {
    DEBUG (
      (EFI_D_ERROR,
      "Could not create transmit status timeout event.  %r\n",
      StatCode)
      );
    return EFI_DEVICE_ERROR;
  }

  //
  // 5 milliseconds
  //
  StatCode = gBS->SetTimer (
                    TimeoutEvent,
                    TimerRelative,
                    50000
                    );

  if (EFI_ERROR (StatCode)) {
    DEBUG (
      (EFI_D_ERROR,
      "Could not set transmit status timeout event timer.  %r\n",
      StatCode)
      );
    gBS->CloseEvent (TimeoutEvent);
    return EFI_DEVICE_ERROR;
  }

  for (;;) {
    StatCode = SnpPtr->GetStatus (SnpPtr, &IntStatus, &TxBuf);

    if (EFI_ERROR (StatCode)) {
      DEBUG (
        (EFI_D_WARN,
        "\nSendPacket()  Exit #4  %xh (%r)",
        StatCode,
        StatCode)
        );
      break;
    }

    if (IntStatus & EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT) {
      Private->DidTransmit = TRUE;
    }

    if (TxBuf != NULL) {
      break;
    }

    if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
      StatCode = EFI_TIMEOUT;
      break;
    }
  }

  gBS->CloseEvent (TimeoutEvent);

  return StatCode;
}
//
//
//
EFI_BIS_PROTOCOL *
PxebcBisStart (
  IN PXE_BASECODE_DEVICE      *Private,
  OUT BIS_APPLICATION_HANDLE  *BisAppHandle,
  OUT OPTIONAL EFI_BIS_DATA            **BisDataSigInfo
  )
/*++
Routine description:
  Locate BIS interface and if found, try to start it.

Parameters:
  Private := Pointer to PxeBc protocol
  BisAppHandle := Pointer to BIS application handle storage
  BisDataSigInfo := Pointer to BIS signature information storage
Returns:
--*/
{
  EFI_STATUS        EfiStatus;
  EFI_HANDLE        BisHandleBuffer;
  UINTN             BisHandleCount;
  EFI_BIS_PROTOCOL  *BisPtr;
  EFI_BIS_VERSION   BisInterfaceVersion;
  BOOLEAN           BisCheckFlag;

  BisHandleCount  = sizeof (EFI_HANDLE);
  BisCheckFlag    = FALSE;

  //
  // Locate BIS protocol handle (if present).
  // If BIS protocol handle is not found, return NULL.
  //
  DEBUG ((EFI_D_INFO, "\ngBS->LocateHandle()  "));

  EfiStatus = gBS->LocateHandle (
                    ByProtocol,
                    &gEfiBisProtocolGuid,
                    NULL,
                    &BisHandleCount,
                    &BisHandleBuffer
                    );

  if (EFI_ERROR (EfiStatus)) {
    //
    // Any error means that there is no BIS.
    // Note - It could mean that there are more than
    // one BIS protocols installed, but that scenario
    // is not yet supported.
    //
    DEBUG (
      (EFI_D_WARN,
      "\nPxebcBisStart()""\n  gBS->LocateHandle()  %r (%xh)\n",
      EfiStatus,
      EfiStatus)
      );

    return NULL;
  }

  if (BisHandleCount != sizeof BisHandleBuffer) {
    //
    // This really should never happen, but I am paranoid.
    //
    DEBUG (
      (EFI_D_NET,
      "\nPxebcBisStart()  BisHandleCount != %d\n",
      sizeof BisHandleBuffer)
      );

    return NULL;
  }

  DEBUG ((EFI_D_INFO, "BIS handle found."));

  //
  // Locate BIS protocol interface.
  // If the BIS protocol interface cannot be found, return NULL.
  //
  DEBUG ((EFI_D_INFO, "\ngBS->HandleProtocol()  "));

  EfiStatus = gBS->HandleProtocol (
                    BisHandleBuffer,
                    &gEfiBisProtocolGuid,
                    &BisPtr
                    );

  if (EFI_ERROR (EfiStatus)) {
    DEBUG (
      (EFI_D_WARN,
      "\nPxebcBisStart()""\n  gBS->HandleProtocol()  %r (%xh)\n",
      EfiStatus,
      EfiStatus)
      );

    return NULL;
  }

  if (BisPtr == NULL) {
    //
    // This really should never happen.
    //
    DEBUG (
      (EFI_D_NET,
      "\nPxebcBisStart()""\n  gBS->HandleProtocoL()  ""BIS protocol interface pointer is NULL!\n")
      );

    return NULL;
  }

  DEBUG ((EFI_D_INFO, "BIS protocol interface found."));

  //
  // Check BIS protocol revision.
  // If the protocol revision is not recognized and supported by
  // this PXE BaseCode revision, return FALSE.
  //
  switch (BisPtr->Revision) {
  case 0: /* special case */
  //
  // Early revisions of the BIS protocol returned zero.
  // Fall through to 0x10000.
  //
  case 0x10000:
    DEBUG (
      (EFI_D_INFO,
      "\nPxebcBisStart()""\n  BisPtr->Revision: %xh",
      BisPtr->Revision)
      );

    break;

  default:
    DEBUG (
      (EFI_D_NET,
      "\nPxebcBisStart()""\nUnsupported BIS revision: %xh\n",
      BisPtr->Revision)
      );

    return NULL;
  }
  //
  // Check that all of the BIS API function pointers are not NULL.
  //
  if (BisPtr->Initialize == NULL ||
      BisPtr->Shutdown == NULL ||
      BisPtr->Free == NULL ||
      BisPtr->GetBootObjectAuthorizationCertificate == NULL ||
      BisPtr->GetBootObjectAuthorizationCheckFlag == NULL ||
      BisPtr->GetBootObjectAuthorizationUpdateToken == NULL ||
      BisPtr->GetSignatureInfo == NULL ||
      BisPtr->UpdateBootObjectAuthorization == NULL ||
      BisPtr->VerifyBootObject == NULL ||
      BisPtr->VerifyObjectWithCredential == NULL
      ) {
    DEBUG (
      (
      EFI_D_NET,
      "\nPxebcBisStart()""\n  BIS protocol interface is invalid."
      "\n  At least one BIS protocol function pointer is NULL.\n"
      )
      );

    return NULL;
  }
  //
  // Initialize BIS.
  // If BIS does not initialize, return NULL.
  //
  DEBUG ((EFI_D_INFO, "\nBisPtr->Initialize()  "));

⌨️ 快捷键说明

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