pxe_bc_mtftp.c

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

C
2,396
字号
    } while (Status == EFI_TIMEOUT && --Retries);

    if (Status != EFI_SUCCESS) {
      return Status;
    }

    BufferPtr = (VOID *) ((UINT8 *) (BufferPtr) + TransferLen);
    TransferSize -= TransferLen;
    ++BlockNum;
    Header.BlockNum = HTONS ((UINT16) BlockNum);
  } while (TransferLen == *PacketSizePtr);

  return EFI_SUCCESS;
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
PxeBcMtftp (
  PXE_BASECODE_DEVICE               *Private,
  IN EFI_PXE_BASE_CODE_TFTP_OPCODE  Operation,
  UINT64                            *BufferSizePtr,
  VOID                              *BufferPtr,
  EFI_IP_ADDRESS                    *ServerIpPtr,
  UINT8                             *FilenamePtr,
  UINTN                             *PacketSizePtr,
  IN EFI_PXE_BASE_CODE_MTFTP_INFO   *MtftpInfoPtr, OPTIONAL
  IN BOOLEAN                        Overwrite,
  IN BOOLEAN                        DontUseBuffer
  )
/*++
Routine description:
  MTFTP API entry point

Parameters:
  Private := 
  Operation := 
  BufferSizePtr := 
  BufferPtr := 
  ServerIpPtr := 
  FilenamePtr := 
  PacketSizePtr := 
  MtftpInfoPtr := 
  Overwrite := 
  DontUseBuffer := 

Returns:
 *  EFI_INVALID_PARAMETER
 *  EFI_OUT_OF_RESOURCES
 *  EFI_BAD_BUFFER_SIZE
 *  Status is also returned from IpFilter(), TftpInfo(), MtftpDownload(),
 *  TftpDownload() and TftpUpload().
--*/
{
  EFI_PXE_BASE_CODE_IP_FILTER Filter;
  EFI_STATUS                  StatCode;
  EFI_STATUS                  Status;
  UINT64                      BufferSizeLocal;
  UINTN                       PacketSize;
  UINT8                       *BufferPtrLocal;

  Filter.Filters  = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;
  Filter.IpCnt    = 0;
  Filter.reserved = 0;

  /* No error has occurred, yet. */
  Private->EfiBc.Mode->TftpErrorReceived = FALSE;

  /* We must at least have an MTFTP server IP address and
   * a pointer to the buffer size.
   */
  if (!ServerIpPtr || !BufferSizePtr) {
    DEBUG ((EFI_D_WARN, "\nPxeBcMtftp()  Exit #1"));

    return EFI_INVALID_PARAMETER;
  }

  Private->Function = EFI_PXE_BASE_CODE_FUNCTION_MTFTP;

  //
  // make sure filter set to unicast at start
  //
  if ((StatCode = IpFilter (Private, &Filter)) != EFI_SUCCESS) {
    DEBUG (
      (EFI_D_NET,
      "\nPxeBcMtftp()  Exit  IpFilter() == %Xh",
      StatCode)
      );

    return StatCode;
  }
  //
  // set unset parms to default values
  //
  if (!PacketSizePtr) {
    *(PacketSizePtr = &PacketSize) = MAX_TFTP_PKT_SIZE;
  }

  if (*PacketSizePtr > *BufferSizePtr) {
    *PacketSizePtr = (UINTN) *BufferSizePtr;
  }

  if (*PacketSizePtr < MIN_TFTP_PKT_SIZE) {
    *PacketSizePtr = MIN_TFTP_PKT_SIZE;
  }

  if (*PacketSizePtr > BUFFER_ALLOCATE_SIZE) {
    *PacketSizePtr = BUFFER_ALLOCATE_SIZE;
  }

  if (*PacketSizePtr > MAX_TFTP_PKT_SIZE) {
    *PacketSizePtr = MAX_TFTP_PKT_SIZE;
  }

  if (Operation == EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE) {
    StatCode = TftpInfo (
                Private,
                BufferSizePtr,
                ServerIpPtr,
                TftpRequestPort,
                FilenamePtr,
                PacketSizePtr
                );

    if (StatCode != EFI_SUCCESS) {
      DEBUG (
        (EFI_D_WARN,
        "\nPxeBcMtftp()  Exit  TftpInfo() == %Xh",
        StatCode)
        );
    }

    return StatCode;
  }

  if (Operation == EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE) {
    if (!MtftpInfoPtr || !MtftpInfoPtr->SPort) {
      DEBUG ((EFI_D_WARN, "\nPxeBcMtftp()  Exit #2"));
      return EFI_INVALID_PARAMETER;
    } else {
      StatCode = TftpInfo (
                  Private,
                  BufferSizePtr,
                  ServerIpPtr,
                  MtftpInfoPtr->SPort,
                  FilenamePtr,
                  PacketSizePtr
                  );

      gBS->Stall (10000);

      if (StatCode != EFI_SUCCESS) {
        DEBUG (
          (EFI_D_WARN,
          "\nPxeBcMtftp()  Exit  TftpInfo() == %Xh",
          StatCode)
          );
      }

      return StatCode;
    }
  }

  if (!BufferPtr && !DontUseBuffer) {
    //
    // if dontusebuffer is false and no buffer???
    //
    DEBUG ((EFI_D_WARN, "\nPxeBcMtftp()  Exit #3"));
    //
    // DontUseBuffer can be true only for read_file operation
    //
    return EFI_INVALID_PARAMETER;
  }

  if (DontUseBuffer) {
    Status = gBS->AllocatePool (
                    EfiBootServicesData,
                    BUFFER_ALLOCATE_SIZE,
                    &BufferPtrLocal
                    );

    if (EFI_ERROR (Status) || BufferPtrLocal == NULL) {
      DEBUG ((EFI_D_NET, "\nPxeBcMtftp()  Exit #4"));
      return EFI_OUT_OF_RESOURCES;
    }

    BufferSizeLocal = BUFFER_ALLOCATE_SIZE;
  } else {
    if (!*BufferSizePtr && Operation != EFI_PXE_BASE_CODE_TFTP_WRITE_FILE) {
      DEBUG ((EFI_D_WARN, "\nPxeBcMtftp()  Exit #5"));
      return EFI_BAD_BUFFER_SIZE;
    }

    BufferPtrLocal  = BufferPtr;
    BufferSizeLocal = *BufferSizePtr;
  }

  switch (Operation) {
  case EFI_PXE_BASE_CODE_MTFTP_READ_FILE:
    if (FilenamePtr == NULL ||
        MtftpInfoPtr == NULL ||
        MtftpInfoPtr->MCastIp.Addr[0] == 0 ||
        MtftpInfoPtr->SPort == 0 ||
        MtftpInfoPtr->CPort == 0 ||
        MtftpInfoPtr->ListenTimeout == 0 ||
        MtftpInfoPtr->TransmitTimeout == 0
        ) {
      StatCode = EFI_INVALID_PARAMETER;
      break;
    }
    //
    // try MTFTP - if fails, drop into TFTP read
    //
    if ((StatCode = MtftpDownload (
                      Private,
                      &BufferSizeLocal,
                      BufferPtrLocal,
                      ServerIpPtr,
                      FilenamePtr,
                      MtftpInfoPtr,
                      DontUseBuffer
                      )) == EFI_SUCCESS || StatCode == EFI_BUFFER_TOO_SMALL) {
      if (BufferSizePtr /* %% !DontUseBuffer */ ) {
        *BufferSizePtr = BufferSizeLocal;
      }

      break;
    }
    //
    // go back to unicast
    //
    if ((StatCode = IpFilter (Private, &Filter)) != EFI_SUCCESS) {
      break;
    }

  /* fall thru */
  case EFI_PXE_BASE_CODE_TFTP_READ_FILE:
    if (FilenamePtr == NULL) {
      StatCode = EFI_INVALID_PARAMETER;
      break;
    }

    StatCode = TftpDownload (
                Private,
                &BufferSizeLocal,
                BufferPtrLocal,
                ServerIpPtr,
                FilenamePtr,
                PacketSizePtr,
                TftpRequestPort,
                TFTP_RRQ,
                DontUseBuffer
                );

    if (StatCode == EFI_SUCCESS || StatCode == EFI_BUFFER_TOO_SMALL) {
      if (BufferSizePtr /* !DontUseBuffer */ ) {
        *BufferSizePtr = BufferSizeLocal;
      }
    }

    break;

  case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE:
    if (FilenamePtr == NULL || DontUseBuffer) {
      //
      // not a valid option
      //
      StatCode = EFI_INVALID_PARAMETER;
      break;
    }

    StatCode = TftpUpload (
                Private,
                BufferSizePtr,
                BufferPtr,
                ServerIpPtr,
                FilenamePtr,
                PacketSizePtr,
                Overwrite
                );

    if (StatCode != EFI_SUCCESS) {
      DEBUG (
        (EFI_D_WARN,
        "\nPxeBcMtftp()  Exit #6  %xh (%r)",
        StatCode,
        StatCode)
        );
    }

    return StatCode;

  case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY:
    if (FilenamePtr == NULL || DontUseBuffer) {
      //
      // not a valid option
      //
      StatCode = EFI_INVALID_PARAMETER;
      break;
    }

    StatCode = TftpDownload (
                Private,
                BufferSizePtr,
                BufferPtr,
                ServerIpPtr,
                FilenamePtr,
                PacketSizePtr,
                TftpRequestPort,
                TFTP_DIR,
                DontUseBuffer
                );

    if (StatCode != EFI_SUCCESS) {
      DEBUG (
        (EFI_D_WARN,
        "\nPxeBcMtftp()  Exit #7  %xh (%r)",
        StatCode,
        StatCode)
        );
    }

    return StatCode;

  case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY:
    if (DontUseBuffer) {
      StatCode = EFI_INVALID_PARAMETER;
      break;
    }

    if (MtftpInfoPtr == NULL || !MtftpInfoPtr->SPort) {
      DEBUG (
        (EFI_D_WARN,
        "\nPxeBcMtftp()  Exit #9  %xh (%r)",
        EFI_INVALID_PARAMETER,
        EFI_INVALID_PARAMETER)
        );

      return EFI_INVALID_PARAMETER;
    }

    StatCode = TftpDownload (
                Private,
                BufferSizePtr,
                BufferPtr,
                ServerIpPtr,
                (UINT8 *) "/",
                PacketSizePtr,
                MtftpInfoPtr->SPort,
                TFTP_DIR,
                DontUseBuffer
                );

    break;

  default:
    StatCode = EFI_INVALID_PARAMETER;
  }

  if (DontUseBuffer) {
    gBS->FreePool (BufferPtrLocal);
  }

  if (StatCode != EFI_SUCCESS) {
    DEBUG (
      (EFI_D_WARN,
      "\nPxeBcMtftp()  Exit #8  %xh (%r)",
      StatCode,
      StatCode)
      );
  }

  gBS->Stall (10000);

  return StatCode;
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
EFIAPI
BcMtftp (
  IN EFI_PXE_BASE_CODE_PROTOCOL       * This,
  IN EFI_PXE_BASE_CODE_TFTP_OPCODE    Operation,
  IN OUT VOID                         *BufferPtr,
  IN BOOLEAN                          Overwrite,
  IN OUT UINT64                       *BufferSizePtr,
  IN UINTN                            *BlockSizePtr OPTIONAL,
  IN EFI_IP_ADDRESS                   * ServerIpPtr,
  IN UINT8                            *FilenamePtr,
  IN EFI_PXE_BASE_CODE_MTFTP_INFO     * MtftpInfoPtr OPTIONAL,
  IN BOOLEAN                          DontUseBuffer
  )
/*++
Routine description:
  MTFTP API entry point.

Parameters:
  This := 
  Operation := 
  BufferPtr := 
  Overwrite := 
  BufferSizePtr := 
  BlockSizePtr := 
  ServerIpPtr := 
  FilenamePtr := 
  MtftpInfoPtr := 
  DontUseBuffer := 

Returns:
 *  EFI_INVALID_PARAMETER
 *  Status is also returned from PxeBcMtftp();
--*/
{
  EFI_PXE_BASE_CODE_IP_FILTER Filter;
  EFI_STATUS                  StatCode;
  PXE_BASECODE_DEVICE         *Private;

  //
  // Lock the instance data and make sure started
  //
  StatCode = EFI_SUCCESS;

  if (This == NULL) {
    DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));
    return EFI_INVALID_PARAMETER;
  }

  Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);

  if (Private == NULL) {
    DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
    return EFI_INVALID_PARAMETER;
  }

  EfiAcquireLock (&Private->Lock);

  if (This->Mode == NULL || !This->Mode->Started) {
    DEBUG ((EFI_D_ERROR, "BC was not started."));
    EfiReleaseLock (&Private->Lock);
    return EFI_NOT_STARTED;
  }
  //
  // Issue BC command
  //
  Filter.Filters  = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;
  Filter.IpCnt    = 0;
  Filter.reserved = 0;

  DEBUG ((EFI_D_WARN, "\nBcMtftp()  Op=%d  Buf=%Xh", Operation, BufferPtr));

  StatCode = PxeBcMtftp (
              Private,
              Operation,
              BufferSizePtr,
              BufferPtr,
              ServerIpPtr,
              FilenamePtr,
              BlockSizePtr,
              MtftpInfoPtr,
              Overwrite,
              DontUseBuffer
              );

  //
  // restore to unicast
  //
  IpFilter (Private, &Filter);

  //
  // Unlock the instance data
  //
  EfiReleaseLock (&Private->Lock);
  return StatCode;
}

/* eof - PxeBcMtftp.c */

⌨️ 快捷键说明

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