bc.c

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

C
2,547
字号
/*++

Copyright (c) 2004 - 2005, Intel Corporation                                                         
All rights reserved. This program and the accompanying materials                          
are licensed and made available under the terms and conditions of the BSD License         
which accompanies this distribution.  The full text of the license may be found at        
http://opensource.org/licenses/bsd-license.php                                            
                                                                                          
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             

Module Name:
  
  bc.c

Abstract:

--*/

#include "bc.h"

//
//
//
EFI_STATUS
EFIAPI
PxeBcDriverSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  );

EFI_STATUS
EFIAPI
PxeBcDriverStart (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  );

EFI_STATUS
EFIAPI
PxeBcDriverStop (
  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN  EFI_HANDLE                     Controller,
  IN  UINTN                          NumberOfChildren,
  IN  EFI_HANDLE                     *ChildHandleBuffer
  );

extern
VOID
InitArpHeader (
  VOID
  );
extern
VOID
OptionsStrucInit (
  VOID
  );

//
// helper routines
//
VOID
CvtNum (
  IN UINTN  Number,
  IN UINT8  *Buffer,
  IN INTN   Length
  )
/*++

  Routine Description:
    Convert number to ASCII value

  Arguments:
    Number              - Numeric value to convert to decimal ASCII value.
    Buffer              - Buffer to place ASCII version of the Number
    Length              - Length of Buffer.

  Returns:
    none                - none

--*/
{
  UINTN Remainder;

  while (Length--) {
    Remainder = Number % 10;
    Number /= 10;
    Buffer[Length] = (UINT8) ('0' + Remainder);
  }
}

VOID
UtoA10 (
  IN UINTN Number,
  IN UINT8 *Buffer
  )
/*++

  Routine Description:
    Convert number to decimal ASCII value at Buffer location

  Arguments:
    Number              - Numeric value to convert to decimal ASCII value.
    Buffer              - Buffer to place ASCII version of the Number

  Returns:
    none                - none

--*/
{
  INTN  Index;
  UINT8 BuffArray[31];

  BuffArray[30] = 0;
  CvtNum (Number, BuffArray, 30);

  for (Index = 0; Index < 30; ++Index) {
    if (BuffArray[Index] != '0') {
      break;
    }
  }

  EfiCopyMem (Buffer, BuffArray + Index, 31 - Index);
}

UINTN
AtoU (
  IN UINT8 *Buffer
  )
/*++

  Routine Description:
    Convert ASCII numeric string to a UINTN value

  Arguments:
    Number              - Numeric value to convert to decimal ASCII value.
    Buffer              - Buffer to place ASCII version of the Number

  Returns:
    Value                - UINTN value of the ASCII string.

--*/
{
  UINTN Value;
  INT8  Character;

  Value     = 0;
  Character = *Buffer++;
  do {
    Value     = Value * 10 + Character - '0';
    Character = *Buffer++;
  } while (Character);

  return Value;
}

UINT64
AtoU64 (
  IN UINT8 *Buffer
  )
/*++

  Routine Description:
    Convert ASCII numeric string to a UINTN value

  Arguments:
    Number              - Numeric value to convert to decimal ASCII value.
    Buffer              - Buffer to place ASCII version of the Number

  Returns:
    Value                - UINTN value of the ASCII string.

--*/
{
  UINT64  Value;
  UINT8   Character;

  Value = 0;
  while ((Character = *Buffer++) != '\0') {
    Value = MultU64x32 (Value, 10) + (Character - '0');
  }

  return Value;
}
//
// random number generator
//
#define RANDOM_MULTIPLIER   2053
#define RANDOM_ADD_IN_VALUE 19

VOID
SeedRandom (
  IN PXE_BASECODE_DEVICE  *Private,
  IN UINT16               InitialSeed
  )
/*++

  Routine Description:
    Initialize the Seed for the random number generator

  Arguments:

  Returns:
    none                - 

--*/
{
  if (Private != NULL) {
    Private->RandomSeed = InitialSeed;
  }
}

UINT16
Random (
  IN PXE_BASECODE_DEVICE  *Private
  )
/*++

  Routine Description:
    Generate and return a pseudo-random number

  Arguments:

  Returns:
    Number           - UINT16 random number

--*/
{
  UINTN Number;

  if (Private != NULL) {
    Number = -(INTN) Private->RandomSeed * RANDOM_MULTIPLIER + RANDOM_ADD_IN_VALUE;

    return Private->RandomSeed = (UINT16) Number;
  } else {
    return 0;
  }
}
//
// calculate the internet checksum (RFC 1071)
// return 16 bit ones complement of ones complement sum of 16 bit words
//
UINT16
IpChecksum (
  IN UINT16 *Packet,
  IN UINTN  Length
  )
/*++

  Routine Description:
    Calculate the internet checksum (see RFC 1071)

  Arguments:
    Packet             - Buffer which contains the data to be checksummed
    Length             - Length to be checksummed

  Returns:
    Checksum           - Returns the 16 bit ones complement of 
                         ones complement sum of 16 bit words

--*/
{
  UINT32  Sum;
  UINT8   Odd;

  Sum = 0;
  Odd = (UINT8) (Length & 1);
  Length >>= 1;
  while (Length--) {
    Sum += *Packet++;
  }

  if (Odd) {
    Sum += *(UINT8 *) Packet;
  }

  Sum = (Sum & 0xffff) + (Sum >> 16);
  //
  // in case above carried
  //
  Sum += Sum >> 16;

  return (UINT16) (~ (UINT16) Sum);
}

UINT16
IpChecksum2 (
  IN UINT16 *Header,
  IN UINTN  HeaderLen,
  IN UINT16 *Message,
  IN UINTN  MessageLen
  )
/*++

  Routine Description:
    Calculate the internet checksum (see RFC 1071)
    on a non contiguous header and data

  Arguments:
    Header        - Buffer which contains the data to be checksummed
    HeaderLen     - Length to be checksummed
    Message       - Buffer which contains the data to be checksummed
    MessageLen    - Length to be checksummed

  Returns:
    Checksum      - Returns the 16 bit ones complement of 
                    ones complement sum of 16 bit words

--*/
{
  UINT32  Sum;

  Sum = (UINT16)~IpChecksum (Header, HeaderLen) + (UINT16)~IpChecksum (Message, MessageLen);

  //
  // in case above carried
  //
  Sum += Sum >> 16;

  return (UINT16) (~ (UINT16) Sum);
}

UINT16
UpdateChecksum (
  IN UINT16 OldChksum,
  IN UINT16 OldWord,
  IN UINT16 NewWord
  )
/*++

  Routine Description:
    Adjust the internet checksum (see RFC 1071) on a single word update.

  Arguments:
    OldChkSum          - Checksum previously calculated
    OldWord            - Value
    NewWord            - New Value

  Returns:
    Checksum           - Returns the 16 bit ones complement of 
                         ones complement sum of 16 bit words

--*/
{
  UINT32  sum;

  sum = ~OldChksum + NewWord - OldWord;
  //
  // in case above carried
  //
  sum += sum >> 16;
  return (UINT16) (~ (UINT16) sum);
}

STATIC
BOOLEAN
SetMakeCallback (
  IN PXE_BASECODE_DEVICE *Private
  )
/*++

  Routine Description:
    See if a callback is in play

  Arguments:
    Private                - Pointer to Pxe BaseCode Protocol

  Returns:
    0                  - Callbacks are active on the handle
    1                  - Callbacks are not active on the handle                         

--*/
{
  Private->EfiBc.Mode->MakeCallbacks = (BOOLEAN) (gBS->HandleProtocol (
                                                        Private->Handle,
                                                        &gEfiPxeBaseCodeCallbackProtocolGuid,
                                                        (VOID *) &Private->CallbackProtocolPtr
                                                        ) == EFI_SUCCESS);

  DEBUG (
    (EFI_D_INFO,
    "\nMode->MakeCallbacks == %d  ",
    Private->EfiBc.Mode->MakeCallbacks)
    );

  DEBUG (
    (EFI_D_INFO,
    "\nPrivate->CallbackProtocolPtr == %xh  ",
    Private->CallbackProtocolPtr)
    );

  if (Private->CallbackProtocolPtr != NULL) {
    DEBUG (
      (EFI_D_INFO,
      "\nCallbackProtocolPtr->Revision = %xh  ",
      Private->CallbackProtocolPtr->Revision)
      );

    DEBUG (
      (EFI_D_INFO,
      "\nCallbackProtocolPtr->Callback = %xh  ",
      Private->CallbackProtocolPtr->Callback)
      );
  }

  return Private->EfiBc.Mode->MakeCallbacks;
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
WaitForReceive (
  IN PXE_BASECODE_DEVICE        *Private,
  IN EFI_PXE_BASE_CODE_FUNCTION Function,
  IN EFI_EVENT                  TimeoutEvent,
  IN OUT UINTN                  *HeaderSizePtr,
  IN OUT UINTN                  *BufferSizePtr,
  IN OUT UINT16                 *ProtocolPtr
  )
/*++

  Routine Description:
    Routine which does an SNP->Receive over a timeout period and doing callbacks

  Arguments:
    Private       - Pointer to Pxe BaseCode Protocol
    Function      - What PXE function to callback
    TimeoutEvent  - Timer event that will trigger when we have waited too 
                    long for an incoming packet
    HeaderSizePtr - Pointer to the size of the Header size
    BufferSizePtr - Pointer to the size of the Buffer size
    ProtocolPtr   - The protocol to sniff for (namely, UDP/TCP/etc)

  Returns:
    0             - Something was returned
    !0            - Like there was nothing to receive (EFI_TIMEOUT/NOT_READY)

--*/
{
  EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;
  EFI_PXE_CALLBACK            CallbackPtr;
  EFI_STATUS                  StatCode;
  EFI_EVENT                   CallbackEvent;

  //
  // Initialize pointer to SNP interface
  //
  SnpPtr = Private->SimpleNetwork;

  //
  // Initialize pointer to PxeBc callback routine - if any
  //
  CallbackPtr = (Private->EfiBc.Mode->MakeCallbacks) ? Private->CallbackProtocolPtr->Callback : NULL;

  //
  // Create callback event and set timer
  //
  StatCode = gBS->CreateEvent (
                    EFI_EVENT_TIMER,
                    EFI_TPL_CALLBACK,
                    NULL,
                    NULL,
                    &CallbackEvent
                    );

  if (EFI_ERROR (StatCode)) {
    return EFI_DEVICE_ERROR;
  }

  //
  // every 100 milliseconds
  //
  StatCode = gBS->SetTimer (
                    CallbackEvent,
                    TimerPeriodic,
                    1000000
                    );

  if (EFI_ERROR (StatCode)) {
    gBS->CloseEvent (CallbackEvent);
    return EFI_DEVICE_ERROR;
  }
  //
  // Loop until a packet is received or a receive error is detected or
  // a callback abort is detected or a timeout event occurs.
  //
  for (;;)
  {
#if 0
    //
    // Check for received packet event.
    //
    if (!EFI_ERROR (gBS->CheckEvent (SnpPtr->WaitForPacket))) {
      //
      // Packet should be available.  Attempt to read it.
      //
      *BufferSizePtr = BUFFER_ALLOCATE_SIZE;

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

      if (EFI_ERROR (StatCode)) {

⌨️ 快捷键说明

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