Ejemplo n.º 1
0
/**
  Create a HTTP_IO to access the HTTP service. It will create and configure
  a HTTP child handle.

  @param[in]  Image          The handle of the driver image.
  @param[in]  Controller     The handle of the controller.
  @param[in]  IpVersion      IP_VERSION_4 or IP_VERSION_6.
  @param[in]  ConfigData     The HTTP_IO configuration data.
  @param[out] HttpIo         The HTTP_IO.

  @retval EFI_SUCCESS            The HTTP_IO is created and configured.
  @retval EFI_INVALID_PARAMETER  One or more parameters are invalid.
  @retval EFI_UNSUPPORTED        One or more of the control options are not
                                 supported in the implementation.
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
  @retval Others                 Failed to create the HTTP_IO or configure it.

**/
EFI_STATUS
HttpIoCreateIo (
    IN EFI_HANDLE             Image,
    IN EFI_HANDLE             Controller,
    IN UINT8                  IpVersion,
    IN HTTP_IO_CONFIG_DATA    *ConfigData,
    OUT HTTP_IO               *HttpIo
)
{
    EFI_STATUS                Status;
    EFI_HTTP_CONFIG_DATA      HttpConfigData;
    EFI_HTTPv4_ACCESS_POINT   Http4AccessPoint;
    EFI_HTTPv6_ACCESS_POINT   Http6AccessPoint;
    EFI_HTTP_PROTOCOL         *Http;
    EFI_EVENT                 Event;

    if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (HttpIo == NULL)) {
        return EFI_INVALID_PARAMETER;
    }

    if (IpVersion != IP_VERSION_4 && IpVersion != IP_VERSION_6) {
        return EFI_UNSUPPORTED;
    }

    ZeroMem (HttpIo, sizeof (HTTP_IO));

    //
    // Create the HTTP child instance and get the HTTP protocol.
    //
    Status = NetLibCreateServiceChild (
                 Controller,
                 Image,
                 &gEfiHttpServiceBindingProtocolGuid,
                 &HttpIo->Handle
             );
    if (EFI_ERROR (Status)) {
        return Status;
    }

    Status = gBS->OpenProtocol (
                 HttpIo->Handle,
                 &gEfiHttpProtocolGuid,
                 (VOID **) &Http,
                 Image,
                 Controller,
                 EFI_OPEN_PROTOCOL_BY_DRIVER
             );
    if (EFI_ERROR (Status) || (Http == NULL)) {
        goto ON_ERROR;
    }

    //
    // Init the configuration data and configure the HTTP child.
    //
    HttpIo->Image       = Image;
    HttpIo->Controller  = Controller;
    HttpIo->IpVersion   = IpVersion;
    HttpIo->Http        = Http;

    ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA));
    HttpConfigData.HttpVersion        = HttpVersion11;
    HttpConfigData.TimeOutMillisec    = ConfigData->Config4.RequestTimeOut;
    if (HttpIo->IpVersion == IP_VERSION_4) {
        HttpConfigData.LocalAddressIsIPv6 = FALSE;

        Http4AccessPoint.UseDefaultAddress = ConfigData->Config4.UseDefaultAddress;
        Http4AccessPoint.LocalPort         = ConfigData->Config4.LocalPort;
        IP4_COPY_ADDRESS (&Http4AccessPoint.LocalAddress, &ConfigData->Config4.LocalIp);
        IP4_COPY_ADDRESS (&Http4AccessPoint.LocalSubnet, &ConfigData->Config4.SubnetMask);
        HttpConfigData.AccessPoint.IPv4Node = &Http4AccessPoint;
    } else {
        HttpConfigData.LocalAddressIsIPv6 = TRUE;
        Http6AccessPoint.LocalPort        = ConfigData->Config6.LocalPort;
        IP6_COPY_ADDRESS (&Http6AccessPoint.LocalAddress, &ConfigData->Config6.LocalIp);
        HttpConfigData.AccessPoint.IPv6Node = &Http6AccessPoint;
    }

    Status = Http->Configure (Http, &HttpConfigData);
    if (EFI_ERROR (Status)) {
        goto ON_ERROR;
    }

    //
    // Create events for variuos asynchronous operations.
    //
    Status = gBS->CreateEvent (
                 EVT_NOTIFY_SIGNAL,
                 TPL_NOTIFY,
                 HttpBootCommonNotify,
                 &HttpIo->IsTxDone,
                 &Event
             );
    if (EFI_ERROR (Status)) {
        goto ON_ERROR;
    }
    HttpIo->ReqToken.Event = Event;
    HttpIo->ReqToken.Message = &HttpIo->ReqMessage;

    Status = gBS->CreateEvent (
                 EVT_NOTIFY_SIGNAL,
                 TPL_NOTIFY,
                 HttpBootCommonNotify,
                 &HttpIo->IsRxDone,
                 &Event
             );
    if (EFI_ERROR (Status)) {
        goto ON_ERROR;
    }
    HttpIo->RspToken.Event = Event;
    HttpIo->RspToken.Message = &HttpIo->RspMessage;

    return EFI_SUCCESS;

ON_ERROR:
    HttpIoDestroyIo (HttpIo);

    return Status;
}
Ejemplo n.º 2
0
/**
  Function to process the OACK. 
  
  It will first validate the OACK packet, then update the various negotiated parameters.

  @param  Instance              The download MTFTP session
  @param  Packet                The packet received
  @param  Len                   The packet length
  @param  Multicast             Whether this packet is received as a multicast
  @param  Completed             Returns whether the download has completed. NOT
                                used  by this function.

  @retval EFI_DEVICE_ERROR      Failed to create/start a multicast UDP child
  @retval EFI_TFTP_ERROR        Some error happened during the process
  @retval EFI_SUCCESS           The OACK is successfully processed.

**/
EFI_STATUS
Mtftp4RrqHandleOack (
  IN OUT MTFTP4_PROTOCOL       *Instance,
  IN     EFI_MTFTP4_PACKET     *Packet,
  IN     UINT32                Len,
  IN     BOOLEAN               Multicast,
     OUT BOOLEAN               *Completed
  )
{
  MTFTP4_OPTION             Reply;
  EFI_STATUS                Status;
  INTN                      Expected;
  EFI_UDP4_PROTOCOL         *Udp4;

  *Completed = FALSE;

  //
  // If already started the master download, don't change the
  // setting. Master download always succeeds.
  //
  Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
  ASSERT (Expected != -1);

  if (Instance->Master && (Expected != 1)) {
    return EFI_SUCCESS;
  }

  //
  // Parse and validate the options from server
  //
  ZeroMem (&Reply, sizeof (MTFTP4_OPTION));

  Status = Mtftp4ParseOptionOack (Packet, Len, &Reply);

  if (EFI_ERROR (Status) ||
      !Mtftp4RrqOackValid (Instance, &Reply, &Instance->RequestOption)) {
    //
    // Don't send an ERROR packet if the error is EFI_OUT_OF_RESOURCES.
    //
    if (Status != EFI_OUT_OF_RESOURCES) {
      Mtftp4SendError (
        Instance,
        EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
        (UINT8 *) "Mal-formated OACK packet"
        );
    }

    return EFI_TFTP_ERROR;
  }

  if ((Reply.Exist & MTFTP4_MCAST_EXIST) != 0) {

    //
    // Save the multicast info. Always update the Master, only update the
    // multicast IP address, block size, timeoute at the first time. If IP
    // address is updated, create a UDP child to receive the multicast.
    //
    Instance->Master = Reply.Master;

    if (Instance->McastIp == 0) {
      if ((Reply.McastIp == 0) || (Reply.McastPort == 0)) {
        Mtftp4SendError (
          Instance,
          EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
          (UINT8 *) "Illegal multicast setting"
          );

        return EFI_TFTP_ERROR;
      }

      //
      // Create a UDP child then start receive the multicast from it.
      //
      Instance->McastIp      = Reply.McastIp;
      Instance->McastPort    = Reply.McastPort;
      if (Instance->McastUdpPort == NULL) {
        Instance->McastUdpPort = UdpIoCreateIo (
                                   Instance->Service->Controller,
                                   Instance->Service->Image,
                                   Mtftp4RrqConfigMcastPort,
                                   UDP_IO_UDP4_VERSION,
                                   Instance
                                   );
        if (Instance->McastUdpPort != NULL) {
          Status = gBS->OpenProtocol (
                          Instance->McastUdpPort->UdpHandle,
                          &gEfiUdp4ProtocolGuid,
                          (VOID **) &Udp4,
                          Instance->Service->Image,
                          Instance->Handle,
                          EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
                          );
          if (EFI_ERROR (Status)) {
            UdpIoFreeIo (Instance->McastUdpPort);
            Instance->McastUdpPort = NULL;
            return EFI_DEVICE_ERROR;
          }
        }
      }


      if (Instance->McastUdpPort == NULL) {
        return EFI_DEVICE_ERROR;
      }

      Status = UdpIoRecvDatagram (Instance->McastUdpPort, Mtftp4RrqInput, Instance, 0);

      if (EFI_ERROR (Status)) {
        Mtftp4SendError (
          Instance,
          EFI_MTFTP4_ERRORCODE_ACCESS_VIOLATION,
          (UINT8 *) "Failed to create socket to receive multicast packet"
          );

        return Status;
      }
    
      //
      // Update the parameters used.
      //
      if (Reply.BlkSize != 0) {
        Instance->BlkSize = Reply.BlkSize;
      }
      
      if (Reply.Timeout != 0) {
        Instance->Timeout = Reply.Timeout;
      }  
    }    
    
  } else {
    Instance->Master = TRUE;
    
    if (Reply.BlkSize != 0) {
      Instance->BlkSize = Reply.BlkSize;
    }

    if (Reply.Timeout != 0) {
      Instance->Timeout = Reply.Timeout;
    }
  }
  
  //
  // Send an ACK to (Expected - 1) which is 0 for unicast download,
  // or tell the server we want to receive the Expected block.
  //
  return Mtftp4RrqSendAck (Instance, (UINT16) (Expected - 1));
}
Ejemplo n.º 3
0
/**
  Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports
  both blocking I/O and non-blocking I/O. The blocking I/O functionality is required, and the non-blocking
  I/O functionality is optional.


  @param[in]     This                A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance.
  @param[in]     NamespaceId         A 32 bit namespace ID as defined in the NVMe specification to which the NVM Express Command
                                     Packet will be sent.  A value of 0 denotes the NVM Express controller, a value of all 0xFF's
                                     (all bytes are 0xFF) in the namespace ID specifies that the command packet should be sent to
                                     all valid namespaces.
  @param[in,out] Packet              A pointer to the NVM Express Command Packet.
  @param[in]     Event               If non-blocking I/O is not supported then Event is ignored, and blocking I/O is performed.
                                     If Event is NULL, then blocking I/O is performed. If Event is not NULL and non-blocking I/O
                                     is supported, then non-blocking I/O is performed, and Event will be signaled when the NVM
                                     Express Command Packet completes.

  @retval EFI_SUCCESS                The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred
                                     to, or from DataBuffer.
  @retval EFI_BAD_BUFFER_SIZE        The NVM Express Command Packet was not executed. The number of bytes that could be transferred
                                     is returned in TransferLength.
  @retval EFI_NOT_READY              The NVM Express Command Packet could not be sent because the controller is not ready. The caller
                                     may retry again later.
  @retval EFI_DEVICE_ERROR           A device error occurred while attempting to send the NVM Express Command Packet.
  @retval EFI_INVALID_PARAMETER      NamespaceId or the contents of EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM
                                     Express Command Packet was not sent, so no additional status information is available.
  @retval EFI_UNSUPPORTED            The command described by the NVM Express Command Packet is not supported by the NVM Express
                                     controller. The NVM Express Command Packet was not sent so no additional status information
                                     is available.
  @retval EFI_TIMEOUT                A timeout occurred while waiting for the NVM Express Command Packet to execute.

**/
EFI_STATUS
EFIAPI
NvmExpressPassThru (
  IN     EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL          *This,
  IN     UINT32                                      NamespaceId,
  IN OUT EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET    *Packet,
  IN     EFI_EVENT                                   Event OPTIONAL
  )
{
  NVME_CONTROLLER_PRIVATE_DATA   *Private;
  EFI_STATUS                     Status;
  EFI_PCI_IO_PROTOCOL            *PciIo;
  NVME_SQ                        *Sq;
  NVME_CQ                        *Cq;
  UINT16                         QueueId;
  UINT32                         Bytes;
  UINT16                         Offset;
  EFI_EVENT                      TimerEvent;
  EFI_PCI_IO_PROTOCOL_OPERATION  Flag;
  EFI_PHYSICAL_ADDRESS           PhyAddr;
  VOID                           *MapData;
  VOID                           *MapMeta;
  VOID                           *MapPrpList;
  UINTN                          MapLength;
  UINT64                         *Prp;
  VOID                           *PrpListHost;
  UINTN                          PrpListNo;
  UINT32                         Attributes;
  UINT32                         IoAlign;
  UINT32                         MaxTransLen;
  UINT32                         Data;
  NVME_PASS_THRU_ASYNC_REQ       *AsyncRequest;
  EFI_TPL                        OldTpl;

  //
  // check the data fields in Packet parameter.
  //
  if ((This == NULL) || (Packet == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  if ((Packet->NvmeCmd == NULL) || (Packet->NvmeCompletion == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  if (Packet->QueueType != NVME_ADMIN_QUEUE && Packet->QueueType != NVME_IO_QUEUE) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // 'Attributes' with neither EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL nor
  // EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL set is an illegal
  // configuration.
  //
  Attributes  = This->Mode->Attributes;
  if ((Attributes & (EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL |
    EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL)) == 0) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Buffer alignment check for TransferBuffer & MetadataBuffer.
  //
  IoAlign     = This->Mode->IoAlign;
  if (IoAlign > 0 && (((UINTN) Packet->TransferBuffer & (IoAlign - 1)) != 0)) {
    return EFI_INVALID_PARAMETER;
  }

  if (IoAlign > 0 && (((UINTN) Packet->MetadataBuffer & (IoAlign - 1)) != 0)) {
    return EFI_INVALID_PARAMETER;
  }

  Private     = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This);

  //
  // Check NamespaceId is valid or not.
  //
  if ((NamespaceId > Private->ControllerData->Nn) &&
      (NamespaceId != (UINT32) -1)) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Check whether TransferLength exceeds the maximum data transfer size.
  //
  if (Private->ControllerData->Mdts != 0) {
    MaxTransLen = (1 << (Private->ControllerData->Mdts)) *
                  (1 << (Private->Cap.Mpsmin + 12));
    if (Packet->TransferLength > MaxTransLen) {
      Packet->TransferLength = MaxTransLen;
      return EFI_BAD_BUFFER_SIZE;
    }
  }

  PciIo       = Private->PciIo;
  MapData     = NULL;
  MapMeta     = NULL;
  MapPrpList  = NULL;
  PrpListHost = NULL;
  PrpListNo   = 0;
  Prp         = NULL;
  TimerEvent  = NULL;
  Status      = EFI_SUCCESS;

  if (Packet->QueueType == NVME_ADMIN_QUEUE) {
    QueueId = 0;
  } else {
    if (Event == NULL) {
      QueueId = 1;
    } else {
      QueueId = 2;

      //
      // Submission queue full check.
      //
      if ((Private->SqTdbl[QueueId].Sqt + 1) % (NVME_ASYNC_CSQ_SIZE + 1) ==
          Private->AsyncSqHead) {
        return EFI_NOT_READY;
      }
    }
  }
  Sq  = Private->SqBuffer[QueueId] + Private->SqTdbl[QueueId].Sqt;
  Cq  = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh;

  if (Packet->NvmeCmd->Nsid != NamespaceId) {
    return EFI_INVALID_PARAMETER;
  }

  ZeroMem (Sq, sizeof (NVME_SQ));
  Sq->Opc  = (UINT8)Packet->NvmeCmd->Cdw0.Opcode;
  Sq->Fuse = (UINT8)Packet->NvmeCmd->Cdw0.FusedOperation;
  Sq->Cid  = Private->Cid[QueueId]++;
  Sq->Nsid = Packet->NvmeCmd->Nsid;

  //
  // Currently we only support PRP for data transfer, SGL is NOT supported.
  //
  ASSERT (Sq->Psdt == 0);
  if (Sq->Psdt != 0) {
    DEBUG ((EFI_D_ERROR, "NvmExpressPassThru: doesn't support SGL mechanism\n"));
    return EFI_UNSUPPORTED;
  }

  Sq->Prp[0] = (UINT64)(UINTN)Packet->TransferBuffer;
  //
  // If the NVMe cmd has data in or out, then mapping the user buffer to the PCI controller specific addresses.
  // Note here we don't handle data buffer for CreateIOSubmitionQueue and CreateIOCompletionQueue cmds because
  // these two cmds are special which requires their data buffer must support simultaneous access by both the
  // processor and a PCI Bus Master. It's caller's responsbility to ensure this.
  //
  if (((Sq->Opc & (BIT0 | BIT1)) != 0) && (Sq->Opc != NVME_ADMIN_CRIOCQ_CMD) && (Sq->Opc != NVME_ADMIN_CRIOSQ_CMD)) {
    if ((Packet->TransferLength == 0) || (Packet->TransferBuffer == NULL)) {
      return EFI_INVALID_PARAMETER;
    }

    if ((Sq->Opc & BIT0) != 0) {
      Flag = EfiPciIoOperationBusMasterRead;
    } else {
      Flag = EfiPciIoOperationBusMasterWrite;
    }

    MapLength = Packet->TransferLength;
    Status = PciIo->Map (
                      PciIo,
                      Flag,
                      Packet->TransferBuffer,
                      &MapLength,
                      &PhyAddr,
                      &MapData
                      );
    if (EFI_ERROR (Status) || (Packet->TransferLength != MapLength)) {
      return EFI_OUT_OF_RESOURCES;
    }

    Sq->Prp[0] = PhyAddr;
    Sq->Prp[1] = 0;

    if((Packet->MetadataLength != 0) && (Packet->MetadataBuffer != NULL)) {
      MapLength = Packet->MetadataLength;
      Status = PciIo->Map (
                        PciIo,
                        Flag,
                        Packet->MetadataBuffer,
                        &MapLength,
                        &PhyAddr,
                        &MapMeta
                        );
      if (EFI_ERROR (Status) || (Packet->MetadataLength != MapLength)) {
        PciIo->Unmap (
                 PciIo,
                 MapData
                 );

        return EFI_OUT_OF_RESOURCES;
      }
      Sq->Mptr = PhyAddr;
    }
  }
  //
  // If the buffer size spans more than two memory pages (page size as defined in CC.Mps),
  // then build a PRP list in the second PRP submission queue entry.
  //
  Offset = ((UINT16)Sq->Prp[0]) & (EFI_PAGE_SIZE - 1);
  Bytes  = Packet->TransferLength;

  if ((Offset + Bytes) > (EFI_PAGE_SIZE * 2)) {
    //
    // Create PrpList for remaining data buffer.
    //
    PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
    Prp = NvmeCreatePrpList (PciIo, PhyAddr, EFI_SIZE_TO_PAGES(Offset + Bytes) - 1, &PrpListHost, &PrpListNo, &MapPrpList);
    if (Prp == NULL) {
      goto EXIT;
    }

    Sq->Prp[1] = (UINT64)(UINTN)Prp;
  } else if ((Offset + Bytes) > EFI_PAGE_SIZE) {
    Sq->Prp[1] = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1);
  }

  if(Packet->NvmeCmd->Flags & CDW2_VALID) {
    Sq->Rsvd2 = (UINT64)Packet->NvmeCmd->Cdw2;
  }
  if(Packet->NvmeCmd->Flags & CDW3_VALID) {
    Sq->Rsvd2 |= LShiftU64 ((UINT64)Packet->NvmeCmd->Cdw3, 32);
  }
  if(Packet->NvmeCmd->Flags & CDW10_VALID) {
    Sq->Payload.Raw.Cdw10 = Packet->NvmeCmd->Cdw10;
  }
  if(Packet->NvmeCmd->Flags & CDW11_VALID) {
    Sq->Payload.Raw.Cdw11 = Packet->NvmeCmd->Cdw11;
  }
  if(Packet->NvmeCmd->Flags & CDW12_VALID) {
    Sq->Payload.Raw.Cdw12 = Packet->NvmeCmd->Cdw12;
  }
  if(Packet->NvmeCmd->Flags & CDW13_VALID) {
    Sq->Payload.Raw.Cdw13 = Packet->NvmeCmd->Cdw13;
  }
  if(Packet->NvmeCmd->Flags & CDW14_VALID) {
    Sq->Payload.Raw.Cdw14 = Packet->NvmeCmd->Cdw14;
  }
  if(Packet->NvmeCmd->Flags & CDW15_VALID) {
    Sq->Payload.Raw.Cdw15 = Packet->NvmeCmd->Cdw15;
  }

  //
  // Ring the submission queue doorbell.
  //
  if ((Event != NULL) && (QueueId != 0)) {
    Private->SqTdbl[QueueId].Sqt =
      (Private->SqTdbl[QueueId].Sqt + 1) % (NVME_ASYNC_CSQ_SIZE + 1);
  } else {
    Private->SqTdbl[QueueId].Sqt ^= 1;
  }
  Data = ReadUnaligned32 ((UINT32*)&Private->SqTdbl[QueueId]);
  PciIo->Mem.Write (
               PciIo,
               EfiPciIoWidthUint32,
               NVME_BAR,
               NVME_SQTDBL_OFFSET(QueueId, Private->Cap.Dstrd),
               1,
               &Data
               );

  //
  // For non-blocking requests, return directly if the command is placed
  // in the submission queue.
  //
  if ((Event != NULL) && (QueueId != 0)) {
    AsyncRequest = AllocateZeroPool (sizeof (NVME_PASS_THRU_ASYNC_REQ));
    if (AsyncRequest == NULL) {
      Status = EFI_DEVICE_ERROR;
      goto EXIT;
    }

    AsyncRequest->Signature     = NVME_PASS_THRU_ASYNC_REQ_SIG;
    AsyncRequest->Packet        = Packet;
    AsyncRequest->CommandId     = Sq->Cid;
    AsyncRequest->CallerEvent   = Event;

    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    InsertTailList (&Private->AsyncPassThruQueue, &AsyncRequest->Link);
    gBS->RestoreTPL (OldTpl);

    return EFI_SUCCESS;
  }

  Status = gBS->CreateEvent (
                  EVT_TIMER,
                  TPL_CALLBACK,
                  NULL,
                  NULL,
                  &TimerEvent
                  );
  if (EFI_ERROR (Status)) {
    goto EXIT;
  }

  Status = gBS->SetTimer(TimerEvent, TimerRelative, Packet->CommandTimeout);

  if (EFI_ERROR(Status)) {
    goto EXIT;
  }

  //
  // Wait for completion queue to get filled in.
  //
  Status = EFI_TIMEOUT;
  while (EFI_ERROR (gBS->CheckEvent (TimerEvent))) {
    if (Cq->Pt != Private->Pt[QueueId]) {
      Status = EFI_SUCCESS;
      break;
    }
  }

  //
  // Check the NVMe cmd execution result
  //
  if (Status != EFI_TIMEOUT) {
    if ((Cq->Sct == 0) && (Cq->Sc == 0)) {
      Status = EFI_SUCCESS;
    } else {
      Status = EFI_DEVICE_ERROR;
      //
      // Copy the Respose Queue entry for this command to the callers response buffer
      //
      CopyMem(Packet->NvmeCompletion, Cq, sizeof(EFI_NVM_EXPRESS_COMPLETION));
    
      //
      // Dump every completion entry status for debugging.
      //
      DEBUG_CODE_BEGIN();
        NvmeDumpStatus(Cq);
      DEBUG_CODE_END();
    }
  }

  if ((Private->CqHdbl[QueueId].Cqh ^= 1) == 0) {
    Private->Pt[QueueId] ^= 1;
  }

  Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueId]);
  PciIo->Mem.Write (
               PciIo,
               EfiPciIoWidthUint32,
               NVME_BAR,
               NVME_CQHDBL_OFFSET(QueueId, Private->Cap.Dstrd),
               1,
               &Data
               );

  //
  // For now, the code does not support the non-blocking feature for admin queue.
  // If Event is not NULL for admin queue, signal the caller's event here.
  //
  if (Event != NULL) {
    ASSERT (QueueId == 0);
    gBS->SignalEvent (Event);
  }

EXIT:
  if (MapData != NULL) {
    PciIo->Unmap (
             PciIo,
             MapData
             );
  }

  if (MapMeta != NULL) {
    PciIo->Unmap (
             PciIo,
             MapMeta
             );
  }

  if (MapPrpList != NULL) {
    PciIo->Unmap (
             PciIo,
             MapPrpList
             );
  }

  if (Prp != NULL) {
    PciIo->FreeBuffer (PciIo, PrpListNo, PrpListHost);
  }

  if (TimerEvent != NULL) {
    gBS->CloseEvent (TimerEvent);
  }
  return Status;
}
Ejemplo n.º 4
0
Archivo: Image.c Proyecto: B-Rich/edk2
/**
  Output pixels in "1 bit per pixel" format to an image.

  This is a internal function.


  @param  Image                  Points to the image which will store the pixels.
  @param  Data                   Stores the value of output pixels, 0 or 1.
  @param  PaletteInfo            PaletteInfo which stores the color of the output
                                 pixels. First entry corresponds to color 0 and
                                 second one to color 1.


**/
VOID
Output1bitPixel (
  IN OUT EFI_IMAGE_INPUT             *Image,
  IN UINT8                           *Data,
  IN EFI_HII_IMAGE_PALETTE_INFO      *PaletteInfo
  )
{
  UINT16                             Xpos;
  UINT16                             Ypos;
  UINTN                              OffsetY;
  UINT8                              Index;
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      *BitMapPtr;
  EFI_GRAPHICS_OUTPUT_BLT_PIXEL      PaletteValue[2];
  EFI_HII_IMAGE_PALETTE_INFO         *Palette;
  UINT16                             PaletteSize;
  UINT8                              Byte;

  ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);

  BitMapPtr = Image->Bitmap;

  //
  // First entry corresponds to color 0 and second entry corresponds to color 1.
  //
  CopyMem (&PaletteSize, PaletteInfo, sizeof (UINT16));
  PaletteSize += sizeof (UINT16);
  Palette = AllocateZeroPool (PaletteSize);
  ASSERT (Palette != NULL);
  CopyMem (Palette, PaletteInfo, PaletteSize);

  ZeroMem (PaletteValue, sizeof (PaletteValue));
  CopyRgbToGopPixel (&PaletteValue[0], &Palette->PaletteValue[0], 1);
  CopyRgbToGopPixel (&PaletteValue[1], &Palette->PaletteValue[1], 1);
  FreePool (Palette);

  //
  // Convert the pixel from one bit to corresponding color.
  //
  for (Ypos = 0; Ypos < Image->Height; Ypos++) {
    OffsetY = BITMAP_LEN_1_BIT (Image->Width, Ypos);
    //
    // All bits in these bytes are meaningful
    //
    for (Xpos = 0; Xpos < Image->Width / 8; Xpos++) {
      Byte = *(Data + OffsetY + Xpos);
      for (Index = 0; Index < 8; Index++) {
        if ((Byte & (1 << Index)) != 0) {
          BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[1];
        } else {
          BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[0];
        }
      }
    }

    if (Image->Width % 8 != 0) {
      //
      // Padding bits in this byte should be ignored.
      //
      Byte = *(Data + OffsetY + Xpos);
      for (Index = 0; Index < Image->Width % 8; Index++) {
        if ((Byte & (1 << (8 - Index - 1))) != 0) {
          BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[1];
        } else {
          BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[0];
        }
      }
    }
  }
}
Ejemplo n.º 5
0
/**
  Create 4G PageTable in SMRAM.

  @param          ExtraPages       Additional page numbers besides for 4G memory
  @return         PageTable Address

**/
UINT32
Gen4GPageTable (
  IN      UINTN                     ExtraPages
  )
{
  VOID    *PageTable;
  UINTN   Index;
  UINT64  *Pte;
  UINTN   PagesNeeded;
  UINTN   Low2MBoundary;
  UINTN   High2MBoundary;
  UINTN   Pages;
  UINTN   GuardPage;
  UINT64  *Pdpte;
  UINTN   PageIndex;
  UINTN   PageAddress;

  Low2MBoundary = 0;
  High2MBoundary = 0;
  PagesNeeded = 0;
  if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
    //
    // Add one more page for known good stack, then find the lower 2MB aligned address.
    //
    Low2MBoundary = (mSmmStackArrayBase + EFI_PAGE_SIZE) & ~(SIZE_2MB-1);
    //
    // Add two more pages for known good stack and stack guard page,
    // then find the lower 2MB aligned address.
    //
    High2MBoundary = (mSmmStackArrayEnd - mSmmStackSize + EFI_PAGE_SIZE * 2) & ~(SIZE_2MB-1);
    PagesNeeded = ((High2MBoundary - Low2MBoundary) / SIZE_2MB) + 1;
  }
  //
  // Allocate the page table
  //
  PageTable = AllocatePages (ExtraPages + 5 + PagesNeeded);
  ASSERT (PageTable != NULL);

  PageTable = (VOID *)((UINTN)PageTable + EFI_PAGES_TO_SIZE (ExtraPages));
  Pte = (UINT64*)PageTable;

  //
  // Zero out all page table entries first
  //
  ZeroMem (Pte, EFI_PAGES_TO_SIZE (1));

  //
  // Set Page Directory Pointers
  //
  for (Index = 0; Index < 4; Index++) {
    Pte[Index] = (UINTN)PageTable + EFI_PAGE_SIZE * (Index + 1) + IA32_PG_P;
  }
  Pte += EFI_PAGE_SIZE / sizeof (*Pte);

  //
  // Fill in Page Directory Entries
  //
  for (Index = 0; Index < EFI_PAGE_SIZE * 4 / sizeof (*Pte); Index++) {
    Pte[Index] = (Index << 21) + IA32_PG_PS + IA32_PG_RW + IA32_PG_P;
  }

  if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
    Pages = (UINTN)PageTable + EFI_PAGES_TO_SIZE (5);
    GuardPage = mSmmStackArrayBase + EFI_PAGE_SIZE;
    Pdpte = (UINT64*)PageTable;
    for (PageIndex = Low2MBoundary; PageIndex <= High2MBoundary; PageIndex += SIZE_2MB) {
      Pte = (UINT64*)(UINTN)(Pdpte[BitFieldRead32 ((UINT32)PageIndex, 30, 31)] & ~(EFI_PAGE_SIZE - 1));
      Pte[BitFieldRead32 ((UINT32)PageIndex, 21, 29)] = (UINT64)Pages + IA32_PG_RW + IA32_PG_P;
      //
      // Fill in Page Table Entries
      //
      Pte = (UINT64*)Pages;
      PageAddress = PageIndex;
      for (Index = 0; Index < EFI_PAGE_SIZE / sizeof (*Pte); Index++) {
        if (PageAddress == GuardPage) {
          //
          // Mark the guard page as non-present
          //
          Pte[Index] = PageAddress;
          GuardPage += mSmmStackSize;
          if (GuardPage > mSmmStackArrayEnd) {
            GuardPage = 0;
          }
        } else {
          Pte[Index] = PageAddress + IA32_PG_RW + IA32_PG_P;
        }
        PageAddress+= EFI_PAGE_SIZE;
      }
      Pages += EFI_PAGE_SIZE;
    }
  }

  return (UINT32)(UINTN)PageTable;
}
Ejemplo n.º 6
0
/**
  Check and execute the pending TPM request and Lock TPM.

  The TPM request may come from OS or BIOS. This API will display request information and wait 
  for user confirmation if TPM request exists. The TPM request will be sent to TPM device after
  the TPM request is confirmed, and one or more reset may be required to make TPM request to 
  take effect. At last, it will lock TPM to prevent TPM state change by malware.
  
  This API should be invoked after console in and console out are all ready as they are required
  to display request information and get user input to confirm the request. This API should also 
  be invoked as early as possible as TPM is locked in this function.
  
**/
VOID
EFIAPI
TcgPhysicalPresenceLibProcessRequest (
  VOID
  )
{
  EFI_STATUS                        Status;
  BOOLEAN                           LifetimeLock;
  BOOLEAN                           CmdEnable;
  UINTN                             DataSize;
  EFI_PHYSICAL_PRESENCE             TcgPpData;
  EFI_TCG_PROTOCOL                  *TcgProtocol;
  EDKII_VARIABLE_LOCK_PROTOCOL      *VariableLockProtocol;
  UINT8                             PpiFlags;
  
  Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);
  if (EFI_ERROR (Status)) {
    return ;
  }

  //
  // Initialize physical presence flags.
  //
  DataSize = sizeof (UINT8);
  Status = gRT->GetVariable (
                  PHYSICAL_PRESENCE_FLAGS_VARIABLE,
                  &gEfiPhysicalPresenceGuid,
                  NULL,
                  &DataSize,
                  &PpiFlags
                  );
  if (EFI_ERROR (Status)) {
    if (Status == EFI_NOT_FOUND) {
      PpiFlags = FLAG_NO_PPI_PROVISION;
      Status   = gRT->SetVariable (
                        PHYSICAL_PRESENCE_FLAGS_VARIABLE,
                        &gEfiPhysicalPresenceGuid,
                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                        sizeof (UINT8),
                        &PpiFlags
                        );
    }
    ASSERT_EFI_ERROR (Status);
  }
      DEBUG ((EFI_D_ERROR, "[TPM] PpiFlags = %x, Status = %r\n", PpiFlags, Status));

  //
  // This flags variable controls whether physical presence is required for TPM command. 
  // It should be protected from malicious software. We set it as read-only variable here.
  //
  Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLockProtocol);
  if (!EFI_ERROR (Status)) {
    Status = VariableLockProtocol->RequestToLock (
                                     VariableLockProtocol,
                                     PHYSICAL_PRESENCE_FLAGS_VARIABLE,
                                     &gEfiPhysicalPresenceGuid
                                     );
    if (EFI_ERROR (Status)) {
      DEBUG ((EFI_D_ERROR, "[TPM] Error when lock variable %s, Status = %r\n", PHYSICAL_PRESENCE_FLAGS_VARIABLE, Status));
      ASSERT_EFI_ERROR (Status);
    }
  }
  
  //
  // Initialize physical presence variable.
  //
  DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
  Status = gRT->GetVariable (
                  PHYSICAL_PRESENCE_VARIABLE,
                  &gEfiPhysicalPresenceGuid,
                  NULL,
                  &DataSize,
                  &TcgPpData
                  );
  if (EFI_ERROR (Status)) {
    if (Status == EFI_NOT_FOUND) {
      ZeroMem ((VOID*)&TcgPpData, sizeof (TcgPpData));
      DataSize = sizeof (EFI_PHYSICAL_PRESENCE);
      Status   = gRT->SetVariable (
                        PHYSICAL_PRESENCE_VARIABLE,
                        &gEfiPhysicalPresenceGuid,
                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
                        DataSize,
                        &TcgPpData
                        );
    }
    ASSERT_EFI_ERROR (Status);
  }

  DEBUG ((EFI_D_INFO, "[TPM] Flags=%x, PPRequest=%x\n", PpiFlags, TcgPpData.PPRequest));

  if (TcgPpData.PPRequest == PHYSICAL_PRESENCE_NO_ACTION) {
    //
    // No operation request
    //
    return;
  }

  Status = GetTpmCapability (TcgProtocol, &LifetimeLock, &CmdEnable);
  if (EFI_ERROR (Status)) {
    return ;
  }
  
  if (!CmdEnable) {
    if (LifetimeLock) {
      //
      // physicalPresenceCMDEnable is locked, can't execute physical presence command.
      //
      return ;
    }
    Status = TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_CMD_ENABLE);
    if (EFI_ERROR (Status)) {
      return ;
    }
  }
  
  //
  // Set operator physical presence flags
  //
  TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_PRESENT);

  //
  // Execute pending TPM request.
  //  
  ExecutePendingTpmRequest (TcgProtocol, &TcgPpData, PpiFlags);
  DEBUG ((EFI_D_INFO, "[TPM] PPResponse = %x\n", TcgPpData.PPResponse));

  //
  // Lock physical presence.
  //
  TpmPhysicalPresence (TcgProtocol, TPM_PHYSICAL_PRESENCE_NOTPRESENT | TPM_PHYSICAL_PRESENCE_LOCK);
}
Ejemplo n.º 7
0
/**
  Function to read a single line (up to but not including the \n) from a file.

  If the position upon start is 0, then the Ascii Boolean will be set.  This should be
  maintained and not changed for all operations with the same file.
  The function will not return the \r and \n character in buffer. When an empty line is
  read a CHAR_NULL character will be returned in buffer.

  @param[in]       Handle        FileHandle to read from.
  @param[in, out]  Buffer        The pointer to buffer to read into.
  @param[in, out]  Size          The pointer to number of bytes in Buffer.
  @param[in]       Truncate      If the buffer is large enough, this has no effect.
                                 If the buffer is is too small and Truncate is TRUE,
                                 the line will be truncated.
                                 If the buffer is is too small and Truncate is FALSE,
                                 then no read will occur.

  @param[in, out]  Ascii         Boolean value for indicating whether the file is
                                 Ascii (TRUE) or UCS2 (FALSE).

  @retval EFI_SUCCESS           The operation was successful.  The line is stored in
                                Buffer.
  @retval EFI_INVALID_PARAMETER Handle was NULL.
  @retval EFI_INVALID_PARAMETER Size was NULL.
  @retval EFI_BUFFER_TOO_SMALL  Size was not large enough to store the line.
                                Size was updated to the minimum space required.
  @sa FileHandleRead
**/
EFI_STATUS
EFIAPI
FileHandleReadLine(
  IN EFI_FILE_HANDLE            Handle,
  IN OUT CHAR16                 *Buffer,
  IN OUT UINTN                  *Size,
  IN BOOLEAN                    Truncate,
  IN OUT BOOLEAN                *Ascii
  )
{
  EFI_STATUS  Status;
  CHAR16      CharBuffer;
  UINT64      FileSize;
  UINTN       CharSize;
  UINTN       CountSoFar;
  UINTN       CrCount;
  UINT64      OriginalFilePosition;

  if (Handle == NULL
    ||Size   == NULL
    ||(Buffer==NULL&&*Size!=0)
   ){
    return (EFI_INVALID_PARAMETER);
  } 
  
  if (Buffer != NULL && *Size != 0) {
    *Buffer = CHAR_NULL;
  } 
  
  Status = FileHandleGetSize (Handle, &FileSize);
  if (EFI_ERROR (Status)) {
    return Status;
  } else if (FileSize == 0) {
    *Ascii = TRUE;
    return EFI_SUCCESS;
  }  
  
  FileHandleGetPosition(Handle, &OriginalFilePosition);
  if (OriginalFilePosition == 0) {
    CharSize = sizeof(CHAR16);
    Status = FileHandleRead(Handle, &CharSize, &CharBuffer);
    ASSERT_EFI_ERROR(Status);
    if (CharBuffer == gUnicodeFileTag) {
      *Ascii = FALSE;
    } else {
      *Ascii = TRUE;
      FileHandleSetPosition(Handle, OriginalFilePosition);
    }
  }

  CrCount = 0;
  for (CountSoFar = 0;;CountSoFar++){
    CharBuffer = 0;
    if (*Ascii) {
      CharSize = sizeof(CHAR8);
    } else {
      CharSize = sizeof(CHAR16);
    }
    Status = FileHandleRead(Handle, &CharSize, &CharBuffer);
    if (  EFI_ERROR(Status)
       || CharSize == 0
       || (CharBuffer == L'\n' && !(*Ascii))
       || (CharBuffer ==  '\n' && *Ascii)
     ){
      break;
    } else if (
        (CharBuffer == L'\r' && !(*Ascii)) ||
        (CharBuffer ==  '\r' && *Ascii)
      ) {
      CrCount++;
      continue;
    }
    //
    // if we have space save it...
    //
    if ((CountSoFar+1-CrCount)*sizeof(CHAR16) < *Size){
      ASSERT(Buffer != NULL);
      ((CHAR16*)Buffer)[CountSoFar-CrCount] = CharBuffer;
      ((CHAR16*)Buffer)[CountSoFar+1-CrCount] = CHAR_NULL;
    }
  }

  //
  // if we ran out of space tell when...
  //
  if ((CountSoFar+1-CrCount)*sizeof(CHAR16) > *Size){
    *Size = (CountSoFar+1-CrCount)*sizeof(CHAR16);
    if (!Truncate) {
      if (Buffer != NULL && *Size != 0) {
        ZeroMem(Buffer, *Size);
      }
      FileHandleSetPosition(Handle, OriginalFilePosition);
      return (EFI_BUFFER_TOO_SMALL);
    } else {
      DEBUG((DEBUG_WARN, "The line was truncated in FileHandleReadLine"));
      return (EFI_SUCCESS);
    }
  }

  return (Status);
}
Ejemplo n.º 8
0
/**
  The entry point for 96BoardsDxe driver.

  @param[in] ImageHandle     The image handle of the driver.
  @param[in] SystemTable     The system table.

  @retval EFI_ALREADY_STARTED     The driver already exists in system.
  @retval EFI_OUT_OF_RESOURCES    Fail to execute entry point due to lack of
                                  resources.
  @retval EFI_SUCCES              All the related protocols are installed on
                                  the driver.

**/
EFI_STATUS
EFIAPI
EntryPoint (
  IN EFI_HANDLE                   ImageHandle,
  IN EFI_SYSTEM_TABLE             *SystemTable
  )
{
  EFI_STATUS                      Status;
  NINETY_SIX_BOARDS_CONFIG_DATA   ConfigData;
  UINTN                           BufferSize;

  //
  // Get the current config settings from the EFI variable.
  //
  BufferSize = sizeof (ConfigData);
  Status = gRT->GetVariable (NINETY_SIX_BOARDS_CONFIG_VARIABLE_NAME,
                  &g96BoardsFormsetGuid, NULL, &BufferSize, &ConfigData);
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_INFO, "%a: no config data found\n", __FUNCTION__));
    ConfigData.MezzanineType = MEZZANINE_NONE;
  }

  if (!EFI_ERROR (Status) &&
      ConfigData.MezzanineType >= MEZZANINE_MAX) {
    DEBUG ((DEBUG_WARN,
      "%a: invalid value for %s, defaulting to MEZZANINE_NONE\n",
      __FUNCTION__, NINETY_SIX_BOARDS_CONFIG_VARIABLE_NAME));
    ConfigData.MezzanineType = MEZZANINE_NONE;
    Status = EFI_INVALID_PARAMETER; // trigger setvar below
  }

  //
  // Write the newly selected value back to the variable store.
  //
  if (EFI_ERROR (Status)) {
    ZeroMem (&ConfigData.Reserved, sizeof (ConfigData.Reserved));
    Status = gRT->SetVariable (NINETY_SIX_BOARDS_CONFIG_VARIABLE_NAME,
                    &g96BoardsFormsetGuid,
                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
                    sizeof (ConfigData), &ConfigData);

    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_ERROR, "%a: gRT->SetVariable () failed - %r\n",
        __FUNCTION__, Status));
      return Status;
    }
  }

  switch (ConfigData.MezzanineType) {
  case MEZZANINE_SECURE96:
    mLsConnector.MezzanineType = MezzanineSecure96;
    break;
  default:
    mLsConnector.MezzanineType = MezzanineUnknown;
  }

  Status = gBS->InstallProtocolInterface (&ImageHandle,
                  &g96BoardsLsConnectorProtocolGuid,
                  EFI_NATIVE_INTERFACE,
                  &mLsConnector);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = gBS->CreateEventEx (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  ApplyDeviceTreeOverlay,
                  NULL,
                  &gEfiEndOfDxeEventGroupGuid,
                  &EndOfDxeEvent);
  ASSERT_EFI_ERROR (Status);

  return InstallHiiPages ();
}
Ejemplo n.º 9
0
EFI_STATUS
EFIAPI
InitializeAttrib (
  IN EFI_HANDLE           ImageHandle,
  IN EFI_SYSTEM_TABLE     *SystemTable
  )
/*++

Routine Description:

  Command entry point. Parses command line arguments and calls internal
  function to perform actual action.

Arguments:

  ImageHandle    The image handle. 
  SystemTable    The system table.

Returns:

  EFI_SUCCESS             - Command completed successfully
  EFI_INVALID_PARAMETER   - Command usage error
  Other value             - Unknown error
  
--*/
{
  UINTN                   Index;
  EFI_LIST_ENTRY          FileList;
  EFI_LIST_ENTRY          *Link;
  SHELL_FILE_ARG          *Arg;
  UINT64                  Remove;
  UINT64                  Add;
  EFI_STATUS              Status;

  SHELL_VAR_CHECK_CODE    RetCode;
  CHAR16                  *Useful;
  SHELL_ARG_LIST          *Item;
  SHELL_VAR_CHECK_PACKAGE ChkPck;

  ZeroMem (&ChkPck, sizeof (SHELL_VAR_CHECK_PACKAGE));

  //
  // We are no being installed as an internal command driver, initialize
  // as an nshell app and run
  //
  EFI_SHELL_APP_INIT (ImageHandle, SystemTable);

  //
  // Enable tab key which can pause the output
  //
  EnableOutputTabPause();
  
  Status = LibFilterNullArgs ();
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Register our string package with HII and return the handle to it.
  // If previously registered we will simply receive the handle
  //
  EFI_SHELL_STR_INIT (HiiHandle, STRING_ARRAY_NAME, EfiAttribGuid);

  if (!EFI_PROPER_VERSION (0, 99)) {
    PrintToken (
      STRING_TOKEN (STR_SHELLENV_GNC_COMMAND_NOT_SUPPORT),
      HiiHandle,
      L"attrib",
      EFI_VERSION_0_99 
      );
    Status = EFI_UNSUPPORTED;
    goto Quit;
  }

  RetCode = LibCheckVariables (SI, AttribCheckList, &ChkPck, &Useful);
  if (VarCheckOk != RetCode) {
    switch (RetCode) {
    case VarCheckConflict:

      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_FLAG_CONFLICT), HiiHandle, L"attrib", Useful);
      break;

    case VarCheckDuplicate:

      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_DUP_FLAG), HiiHandle, L"attrib", Useful);
      break;

    case VarCheckUnknown:

      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_UNKNOWN_FLAG), HiiHandle, L"attrib", Useful);
      break;

    default:
      break;
    }

    Status = EFI_INVALID_PARAMETER;
    goto Quit;
  }
  //
  // Out put help.
  //
  if (LibCheckVarGetFlag (&ChkPck, L"-b") != NULL) {
    EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);
  }

  if (LibCheckVarGetFlag (&ChkPck, L"-?") != NULL) {
    if (IS_OLD_SHELL) {
      PrintToken (STRING_TOKEN (STR_NO_HELP), HiiHandle);
      goto Quit;
    }

    if (ChkPck.ValueCount > 0 ||
        ChkPck.FlagCount > 2 ||
        (2 == ChkPck.FlagCount && !LibCheckVarGetFlag (&ChkPck, L"-b"))
        ) {
      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_TOO_MANY), HiiHandle, L"attrib");
      Status = EFI_INVALID_PARAMETER;
    } else {
      PrintToken (STRING_TOKEN (STR_ATTRIB_VERBOSE_HELP), HiiHandle);
      Status = EFI_SUCCESS;
    }

    goto Quit;
  }
  //
  // Local Variable Initializations
  //
  InitializeListHead (&FileList);
  Link    = NULL;
  Arg     = NULL;
  Remove  = 0;
  Add     = 0;

  //
  // Parse command line arguments
  //
  Item = GetFirstFlag (&ChkPck);
  for (Index = 0; Index < ChkPck.FlagCount; Index += 1) {
    if (Item->FlagStr[0] == '-') {
      //
      // Attributes to remove
      //
      Status = AttribSet (&Item->FlagStr[1], &Remove);
      if (EFI_ERROR (Status)) {
        PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_INVALID_ARG), HiiHandle, L"attrib", Item->FlagStr);
        goto Done;
      }
    } else if (Item->FlagStr[0] == '+') {
      //
      // Attributes to Add
      //
      Status = AttribSet (&Item->FlagStr[1], &Add);
      if (EFI_ERROR (Status)) {
        PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_INVALID_ARG), HiiHandle, L"attrib", Item->FlagStr);
        goto Done;
      }
    } else {
      //
      // we should never get here
      //
      ASSERT (FALSE);
    }

    Item = GetNextArg (Item);
  }

  Item = GetFirstArg (&ChkPck);
  for (Index = 0; Index < ChkPck.ValueCount; Index += 1) {
    Status = ShellFileMetaArg (Item->VarStr, &FileList);
    if (EFI_ERROR (Status)) {
      PrintToken (STRING_TOKEN (STR_ATTRIB_CANNOT_OPEN), HiiHandle, L"attrib", Item->VarStr, Status);
      goto Done;
    }

    Item = GetNextArg (Item);
  }
  //
  // if no file is specified, get the whole directory
  //
  if (IsListEmpty (&FileList)) {
    Status = ShellFileMetaArg (L"*", &FileList);
    if (EFI_ERROR (Status)) {
      PrintToken (STRING_TOKEN (STR_ATTRIB_CANNOT_OPEN_DIR), HiiHandle, L"attrib", Status);
      goto Done;
    }
  }

  ShellDelDupFileArg (&FileList);
  //
  // Attrib each file
  //
  for (Link = FileList.Flink; Link != &FileList; Link = Link->Flink) {
    //
    // Break the execution?
    //
    if (GetExecutionBreak ()) {
      goto Done;
    }

    Arg     = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
    Status  = AttribFile (Arg, Remove, Add);
  }

Done:
  ShellFreeFileList (&FileList);
Quit:
  LibCheckVarFreeVarList (&ChkPck);
  LibUnInitializeStrings ();
  return Status;
}
Ejemplo n.º 10
0
/**
  Initialize debug agent.

  This function is used to set up debug enviroment for DXE phase.

  If this function is called by DXE Core, Context must be the pointer
  to HOB list which will be used to get GUIDed HOB. It will enable
  interrupt to support break-in feature.
  If this function is called by DXE module, Context must be NULL. It
  will enable interrupt to support break-in feature.

  @param[in] InitFlag     Init flag is used to decide initialize process.
  @param[in] Context      Context needed according to InitFlag.
  @param[in] Function     Continue function called by debug agent library; it was
                          optional.

**/
VOID
EFIAPI
InitializeDebugAgent (
  IN UINT32                InitFlag,
  IN VOID                  *Context, OPTIONAL
  IN DEBUG_AGENT_CONTINUE  Function  OPTIONAL
  )
{
  DEBUG_AGENT_MAILBOX          *Mailbox;
  IA32_DESCRIPTOR              Idtr;
  UINT16                       IdtEntryCount;
  BOOLEAN                      InterruptStatus;

  if (InitFlag != DEBUG_AGENT_INIT_DXE_CORE &&
      InitFlag != DEBUG_AGENT_INIT_S3 &&
      InitFlag != DEBUG_AGENT_INIT_DXE_AP) {
    return;
  }

  //
  // Save and disable original interrupt status
  //
  InterruptStatus = SaveAndDisableInterrupts ();

  if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {
    //
    // Try to get Mailbox from GUIDed HOB.
    //
    mDxeCoreFlag = TRUE;
    Mailbox = GetMailboxFromHob (Context);
    
    //
    // Clear Break CPU index value
    //
    mDebugMpContext.BreakAtCpuIndex = (UINT32) -1;

  } else if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {

    EnableInterrupts ();

    return;

  } else {
    //
    // If it is in S3 path, needn't to install configuration table.
    //
    Mailbox = NULL;
  }

  if (Mailbox != NULL) {
    //
    // If Mailbox exists, copy it into one global variable.
    //
    CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
  } else {
    //
    // If Mailbox not exists, used the local Mailbox.
    //
    ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX));
  }

  mMailboxPointer = &mMailbox;

  //
  // Get original IDT address and size.
  //
  AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);
  IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));
  if (IdtEntryCount < 33) {
    Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);
    Idtr.Base  = (UINTN) &mIdtEntryTable;
    ZeroMem (&mIdtEntryTable, Idtr.Limit + 1);
    AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);
  }

  //
  // Initialize the IDT table entries to support source level debug.
  //
  InitializeDebugIdt ();

  //
  // Initialize debug communication port
  //
  mMailboxPointer->DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((VOID *)(UINTN)mMailbox.DebugPortHandle, NULL);

  InitializeSpinLock (&mDebugMpContext.MpContextSpinLock);
  InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock);
 
  if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {
    //
    // Initialize Debug Timer hardware and enable interrupt.
    //
    InitializeDebugTimer ();
    EnableInterrupts ();

    return;
  } else {
    //
    // Disable Debug Timer interrupt in S3 path.
    //
    SaveAndSetDebugTimerInterrupt (FALSE);

    //
    // Restore interrupt state.
    //
    SetInterruptState (InterruptStatus);
  }

}
Ejemplo n.º 11
0
/**
  Relocate this image under 4G memory for IPF.

  @param  ImageHandle  Handle of driver image.
  @param  SystemTable  Pointer to system table.

  @retval EFI_SUCCESS  Image successfully relocated.
  @retval EFI_ABORTED  Failed to relocate image.

**/
EFI_STATUS
RelocateImageUnder4GIfNeeded (
  IN EFI_HANDLE           ImageHandle,
  IN EFI_SYSTEM_TABLE     *SystemTable
  )
{
  EFI_STATUS                         Status;
  EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;
  UINTN                              NumberOfPages;
  EFI_PHYSICAL_ADDRESS               LoadedImageBase;
  PE_COFF_LOADER_IMAGE_CONTEXT       ImageContext;
  EFI_PHYSICAL_ADDRESS               MemoryAddress;
  EFI_HANDLE                         NewImageHandle;

  Status = gBS->HandleProtocol (
                    ImageHandle,
                    &gEfiLoadedImageProtocolGuid,
                    (VOID *) &LoadedImage
                    );

  if (!EFI_ERROR (Status)) {
    LoadedImageBase = (EFI_PHYSICAL_ADDRESS) (UINTN) LoadedImage->ImageBase;
    if (LoadedImageBase > 0xffffffff) {
      NumberOfPages = (UINTN) (DivU64x32(LoadedImage->ImageSize, EFI_PAGE_SIZE) + 1);

      //
      // Allocate buffer below 4GB here
      //
      Status = AllocateLegacyMemory (
                AllocateMaxAddress,
                0x7FFFFFFF,
                NumberOfPages,  // do we have to convert this to pages??
                &MemoryAddress
                );
      if (EFI_ERROR (Status)) {
        return Status;
      }

      ZeroMem (&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
      ImageContext.Handle    = (VOID *)(UINTN)LoadedImageBase;
      ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;

      //
      // Get information about the image being loaded
      //
      Status = PeCoffLoaderGetImageInfo (&ImageContext);
      if (EFI_ERROR (Status)) {
        return Status;
      }
      ImageContext.ImageAddress = (PHYSICAL_ADDRESS)MemoryAddress;
      //
      // Align buffer on section boundry
      //
      ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
     ImageContext.ImageAddress &= ~((PHYSICAL_ADDRESS)ImageContext.SectionAlignment - 1);

      //
      // Load the image to our new buffer
      //
      Status = PeCoffLoaderLoadImage (&ImageContext);
      if (EFI_ERROR (Status)) {
        gBS->FreePages (MemoryAddress, NumberOfPages);
        return Status;
      }

      //
      // Relocate the image in our new buffer
      //
      Status = PeCoffLoaderRelocateImage (&ImageContext);
      if (EFI_ERROR (Status)) {
        gBS->FreePages (MemoryAddress, NumberOfPages);
        return Status;
      }

      //
      // Create a new handle with gEfiCallerIdGuid to be used as the ImageHandle fore the reloaded image
      // 
      NewImageHandle = NULL;
      Status = gBS->InstallProtocolInterface (
                      &NewImageHandle,
                      &gEfiCallerIdGuid,
                      EFI_NATIVE_INTERFACE,
                      NULL
                      );

      //
      // Flush the instruction cache so the image data is written before we execute it
      //
      InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);

      Status = ((EFI_IMAGE_ENTRY_POINT)(UINTN)(ImageContext.EntryPoint)) (NewImageHandle, SystemTable);
      if (EFI_ERROR (Status)) {
        gBS->FreePages (MemoryAddress, NumberOfPages);
        return Status;
      }
      //
      // return error directly the BS will unload this image
      //
      return EFI_ABORTED;
    }
  }
  return EFI_SUCCESS;
}
Ejemplo n.º 12
0
/**
  This routine is invoked by main entry of PeiMain module during transition
  from SEC to PEI. After switching stack in the PEI core, it will restart
  with the old core data.

  @param SecCoreDataPtr  Points to a data structure containing information about the PEI core's operating
                         environment, such as the size and location of temporary RAM, the stack location and
                         the BFV location.
  @param PpiList         Points to a list of one or more PPI descriptors to be installed initially by the PEI core.
                         An empty PPI list consists of a single descriptor with the end-tag
                         EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST. As part of its initialization
                         phase, the PEI Foundation will add these SEC-hosted PPIs to its PPI database such
                         that both the PEI Foundation and any modules can leverage the associated service
                         calls and/or code in these early PPIs
  @param Data            Pointer to old core data that is used to initialize the
                         core's data areas.
                         If NULL, it is first PeiCore entering.

**/
VOID
EFIAPI
PeiCore (
  IN CONST EFI_SEC_PEI_HAND_OFF        *SecCoreDataPtr,
  IN CONST EFI_PEI_PPI_DESCRIPTOR      *PpiList,
  IN VOID                              *Data
  )
{
  PEI_CORE_INSTANCE           PrivateData;
  EFI_SEC_PEI_HAND_OFF        *SecCoreData;
  EFI_SEC_PEI_HAND_OFF        NewSecCoreData;
  EFI_STATUS                  Status;
  PEI_CORE_TEMP_POINTERS      TempPtr;
  PEI_CORE_INSTANCE           *OldCoreData;
  EFI_PEI_CPU_IO_PPI          *CpuIo;
  EFI_PEI_PCI_CFG2_PPI        *PciCfg;
  EFI_HOB_HANDOFF_INFO_TABLE  *HandoffInformationTable;
  EFI_PEI_TEMPORARY_RAM_DONE_PPI *TemporaryRamDonePpi;
  UINTN                       Index;
  
  //
  // Retrieve context passed into PEI Core
  //
  OldCoreData = (PEI_CORE_INSTANCE *) Data;
  SecCoreData = (EFI_SEC_PEI_HAND_OFF *) SecCoreDataPtr;

  //
  // Perform PEI Core phase specific actions.
  //
  if (OldCoreData == NULL) {
    //
    // If OldCoreData is NULL, means current is the first entry into the PEI Core before memory is available.
    //
    ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE));
    PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE;
    CopyMem (&PrivateData.ServiceTableShadow, &gPs, sizeof (gPs));
  } else {
    //
    // Memory is available to the PEI Core.  See if the PEI Core has been shadowed to memory yet.
    //
    if (OldCoreData->ShadowedPeiCore == NULL) {
      //
      // Fixup the PeiCore's private data
      //
      OldCoreData->Ps    = &OldCoreData->ServiceTableShadow;
      OldCoreData->CpuIo = &OldCoreData->ServiceTableShadow.CpuIo;
      if (OldCoreData->HeapOffsetPositive) {
        OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw + OldCoreData->HeapOffset);
        OldCoreData->UnknownFvInfo        = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *) ((UINT8 *) OldCoreData->UnknownFvInfo + OldCoreData->HeapOffset);
        OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->CurrentFvFileHandles + OldCoreData->HeapOffset);
        OldCoreData->PpiData.PpiListPtrs  = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.PpiListPtrs + OldCoreData->HeapOffset);
        OldCoreData->Fv                   = (PEI_CORE_FV_HANDLE *) ((UINT8 *) OldCoreData->Fv + OldCoreData->HeapOffset);
        for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
          OldCoreData->Fv[Index].PeimState     = (UINT8 *) OldCoreData->Fv[Index].PeimState + OldCoreData->HeapOffset;
          OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->Fv[Index].FvFileHandles + OldCoreData->HeapOffset);
        }
        OldCoreData->FileGuid             = (EFI_GUID *) ((UINT8 *) OldCoreData->FileGuid + OldCoreData->HeapOffset);
        OldCoreData->FileHandles          = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->FileHandles + OldCoreData->HeapOffset);
      } else {
        OldCoreData->HobList.Raw = (VOID *)(OldCoreData->HobList.Raw - OldCoreData->HeapOffset);
        OldCoreData->UnknownFvInfo        = (PEI_CORE_UNKNOW_FORMAT_FV_INFO *) ((UINT8 *) OldCoreData->UnknownFvInfo - OldCoreData->HeapOffset);
        OldCoreData->CurrentFvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->CurrentFvFileHandles - OldCoreData->HeapOffset);
        OldCoreData->PpiData.PpiListPtrs  = (PEI_PPI_LIST_POINTERS *) ((UINT8 *) OldCoreData->PpiData.PpiListPtrs - OldCoreData->HeapOffset);
        OldCoreData->Fv                   = (PEI_CORE_FV_HANDLE *) ((UINT8 *) OldCoreData->Fv - OldCoreData->HeapOffset);
        for (Index = 0; Index < PcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
          OldCoreData->Fv[Index].PeimState     = (UINT8 *) OldCoreData->Fv[Index].PeimState - OldCoreData->HeapOffset;
          OldCoreData->Fv[Index].FvFileHandles = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->Fv[Index].FvFileHandles - OldCoreData->HeapOffset);
        }
        OldCoreData->FileGuid             = (EFI_GUID *) ((UINT8 *) OldCoreData->FileGuid - OldCoreData->HeapOffset);
        OldCoreData->FileHandles          = (EFI_PEI_FILE_HANDLE *) ((UINT8 *) OldCoreData->FileHandles - OldCoreData->HeapOffset);
      }

      //
      // Initialize libraries that the PEI Core is linked against
      //
      ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);
      
      //
      // Fixup for PeiService's address
      //
      SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);

      //
      // Update HandOffHob for new installed permenent memory
      //
      HandoffInformationTable = OldCoreData->HobList.HandoffInformationTable;
      if (OldCoreData->HeapOffsetPositive) {
        HandoffInformationTable->EfiEndOfHobList   = HandoffInformationTable->EfiEndOfHobList + OldCoreData->HeapOffset;
      } else {
        HandoffInformationTable->EfiEndOfHobList   = HandoffInformationTable->EfiEndOfHobList - OldCoreData->HeapOffset;
      }
      HandoffInformationTable->EfiMemoryTop        = OldCoreData->PhysicalMemoryBegin + OldCoreData->PhysicalMemoryLength;
      HandoffInformationTable->EfiMemoryBottom     = OldCoreData->PhysicalMemoryBegin;
      HandoffInformationTable->EfiFreeMemoryTop    = OldCoreData->FreePhysicalMemoryTop;
      HandoffInformationTable->EfiFreeMemoryBottom = HandoffInformationTable->EfiEndOfHobList + sizeof (EFI_HOB_GENERIC_HEADER);

      //
      // We need convert the PPI descriptor's pointer
      //
      ConvertPpiPointers (SecCoreData, OldCoreData);

      //
      // After the whole temporary memory is migrated, then we can allocate page in
      // permenent memory.
      //
      OldCoreData->PeiMemoryInstalled = TRUE;

      //
      // Indicate that PeiCore reenter
      //
      OldCoreData->PeimDispatcherReenter = TRUE;
      
      if (PcdGet64(PcdLoadModuleAtFixAddressEnable) != 0 && (OldCoreData->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {
        //
        // if Loading Module at Fixed Address is enabled, allocate the PEI code memory range usage bit map array.
        // Every bit in the array indicate the status of the corresponding memory page available or not
        //
        OldCoreData->PeiCodeMemoryRangeUsageBitMap = AllocateZeroPool (((PcdGet32(PcdLoadFixAddressPeiCodePageNumber)>>6) + 1)*sizeof(UINT64));
      }

      //
      // Shadow PEI Core. When permanent memory is avaiable, shadow
      // PEI Core and PEIMs to get high performance.
      //
      OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER) (UINTN) PeiCore;
      if ((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot))
          || (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) {
        OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData);
      }
      
      //
      // PEI Core has now been shadowed to memory.  Restart PEI Core in memory.
      //
      OldCoreData->ShadowedPeiCore (SecCoreData, PpiList, OldCoreData);
      
      //
      // Should never reach here.
      //
      ASSERT (FALSE);
      CpuDeadLoop();
    }
Ejemplo n.º 13
0
/**
 * Get file information
 *
 * @v This			File handle
 * @v Type			Type of information
 * @v Len			Buffer size
 * @v Data			Buffer
 * @ret Status		EFI status code
 */
static EFI_STATUS EFIAPI
FileGetInfo(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data)
{
	EFI_STATUS Status;
	EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile);
	EFI_FILE_SYSTEM_INFO *FSInfo = (EFI_FILE_SYSTEM_INFO *) Data;
	EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
	CHAR16 GuidString[36];
	EFI_TIME Time;
	CHAR8* label;

	PrintInfo(L"GetInfo(%llx|'%s', %d) %s\n", (UINT64) This,
		FileName(File), *Len, File->IsDir?L"<DIR>":L"");

	/* Determine information to return */
	if (CompareMem(Type, &GenericFileInfo, sizeof(*Type)) == 0) {

		/* Fill file information */
		PrintExtra(L"Get regular file information\n");
		if (*Len < MINIMUM_INFO_LENGTH) {
			*Len = MINIMUM_INFO_LENGTH;
			return EFI_BUFFER_TOO_SMALL;
		}

		ZeroMem(Data, sizeof(EFI_FILE_INFO));

		Info->Attribute = EFI_FILE_READ_ONLY;
		GrubTimeToEfiTime(File->Mtime, &Time);
		CopyMem(&Info->CreateTime, &Time, sizeof(Time));
		CopyMem(&Info->LastAccessTime, &Time, sizeof(Time));
		CopyMem(&Info->ModificationTime, &Time, sizeof(Time));

		if (File->IsDir) {
			Info->Attribute |= EFI_FILE_DIRECTORY;
		} else {
			Info->FileSize = GrubGetFileSize(File);
			Info->PhysicalSize = GrubGetFileSize(File);
		}

		Status = Utf8ToUtf16NoAlloc(File->basename, Info->FileName,
				(INTN)(Info->Size - sizeof(EFI_FILE_INFO)));
		if (EFI_ERROR(Status)) {
			if (Status != EFI_BUFFER_TOO_SMALL)
				PrintStatusError(Status, L"Could not convert basename to UTF-8");
			return Status;
		}

		/* The Info struct size already accounts for the extra NUL */
		Info->Size = sizeof(EFI_FILE_INFO) +
				StrLen(Info->FileName) * sizeof(CHAR16);
		return EFI_SUCCESS;

	} else if (CompareMem(Type, &FileSystemInfo, sizeof(*Type)) == 0) {

		/* Get file system information */
		PrintExtra(L"Get file system information\n");
		if (*Len < MINIMUM_FS_INFO_LENGTH) {
			*Len = MINIMUM_FS_INFO_LENGTH;
			return EFI_BUFFER_TOO_SMALL;
		}

		ZeroMem(Data, sizeof(EFI_FILE_INFO));
		FSInfo->Size = *Len;
		FSInfo->ReadOnly = 1;
		/* NB: This should really be cluster size, but we don't have access to that */
		FSInfo->BlockSize = File->FileSystem->BlockIo->Media->BlockSize;
		if (FSInfo->BlockSize  == 0) {
			PrintWarning(L"Corrected Media BlockSize\n");
			FSInfo->BlockSize = 512;
		}
		FSInfo->VolumeSize = (File->FileSystem->BlockIo->Media->LastBlock + 1) *
			FSInfo->BlockSize;
		/* No idea if we can easily get this for GRUB, and the device is RO anyway */
		FSInfo->FreeSpace = 0;

		Status = GrubLabel(File, &label);
		if (EFI_ERROR(Status)) {
			PrintStatusError(Status, L"Could not read disk label");
		} else {
			Status = Utf8ToUtf16NoAlloc(label, FSInfo->VolumeLabel,
					(INTN)(FSInfo->Size - sizeof(EFI_FILE_SYSTEM_INFO)));
			if (EFI_ERROR(Status)) {
				if (Status != EFI_BUFFER_TOO_SMALL)
					PrintStatusError(Status, L"Could not convert label to UTF-8");
				return Status;
			}
			Info->Size = sizeof(EFI_FILE_SYSTEM_INFO) +
					StrLen(FSInfo->VolumeLabel) * sizeof(CHAR16);
		}
		return EFI_SUCCESS;

	} else {

		GuidToString(GuidString, Type);
		PrintError(L"'%s': Cannot get information of type %s\n",
				FileName(File), GuidString);
		return EFI_UNSUPPORTED;

	}
}
Ejemplo n.º 14
0
/**
 * Read directory entry
 *
 * @v file			EFI file
 * @v Len			Length to read
 * @v Data			Data buffer
 * @ret Status		EFI status code
 */
static EFI_STATUS
FileReadDir(EFI_GRUB_FILE *File, UINTN *Len, VOID *Data)
{
	EFI_FILE_INFO *Info = (EFI_FILE_INFO *) Data;
	EFI_STATUS Status;
	/* We temporarily repurpose the FileSize as a *signed* entry index */
	INT64 *Index = (INT64 *) &Info->FileSize;
	/* And PhysicalSize as a pointer to our filename */
	CHAR8 **basename = (CHAR8 **) &Info->PhysicalSize;
	CHAR8 path[MAX_PATH];
	EFI_GRUB_FILE *TmpFile = NULL;
	INTN len;

	/* Unless we can fit our maximum size, forget it */
	if (*Len < MINIMUM_INFO_LENGTH) {
		*Len = MINIMUM_INFO_LENGTH;
		return EFI_BUFFER_TOO_SMALL;
	}

	/* Populate our Info template */
	ZeroMem(Data, *Len);
	Info->Size = *Len;
	*Index = File->DirIndex;
	strcpya(path, File->path);
	len = strlena(path);
	if (path[len-1] != '/')
		path[len++] = '/';
	*basename = &path[len];

	/* Invoke GRUB's directory listing */
	Status = GrubDir(File, File->path, DirHook, Data);
	if (*Index >= 0) {
		/* No more entries */
		*Len = 0;
		return EFI_SUCCESS;
	}

	if (EFI_ERROR(Status)) {
		PrintStatusError(Status, L"Directory listing failed");
		return Status;
	}

	/* Our Index/FileSize must be reset */
	Info->FileSize = 0;
	Info->PhysicalSize = 0;

	/* For regular files, we still need to fill the size */
	if (!(Info->Attribute & EFI_FILE_DIRECTORY)) {
		/* Open the file and read its size */
		Status = GrubCreateFile(&TmpFile, File->FileSystem);
		if (EFI_ERROR(Status)) {
			PrintStatusError(Status, L"Unable to create temporary file");
			return Status;
		}
		TmpFile->path = path;

		Status = GrubOpen(TmpFile);
		if (EFI_ERROR(Status)) {
			// TODO: EFI_NO_MAPPING is returned for links...
			PrintStatusError(Status, L"Unable to obtain the size of '%s'", Info->FileName);
			/* Non fatal error */
		} else {
			Info->FileSize = GrubGetFileSize(TmpFile);
			Info->PhysicalSize = GrubGetFileSize(TmpFile);
			GrubClose(TmpFile);
		}
		GrubDestroyFile(TmpFile);
	}

	*Len = (UINTN) Info->Size;
	/* Advance to the next entry */
	File->DirIndex++;

//	PrintInfo(L"  Entry[%d]: '%s' %s\n", File->DirIndex-1, Info->FileName,
//			(Info->Attribute&EFI_FILE_DIRECTORY)?L"<DIR>":L"");

	return EFI_SUCCESS;
}
Ejemplo n.º 15
0
EFI_STATUS
CreateTimeBasedPayload (
  IN OUT UINTN            *DataSize,
  IN OUT UINT8            **Data
  )
{
  EFI_STATUS                       Status;
  UINT8                            *NewData;
  UINT8                            *Payload;
  UINTN                            PayloadSize;
  EFI_VARIABLE_AUTHENTICATION_2    *DescriptorData;
  UINTN                            DescriptorSize;
  EFI_TIME                         Time;
  EFI_GUID efi_cert_type = EFI_CERT_TYPE_PKCS7_GUID;
  
  if (Data == NULL || DataSize == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  
  //
  // In Setup mode or Custom mode, the variable does not need to be signed but the 
  // parameters to the SetVariable() call still need to be prepared as authenticated
  // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
  // data in it.
  //
  Payload     = *Data;
  PayloadSize = *DataSize;
  
  DescriptorSize    = OFFSET_OF(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData);
  NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize);
  if (NewData == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  if ((Payload != NULL) && (PayloadSize != 0)) {
    CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
  }

  DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData);

  ZeroMem (&Time, sizeof (EFI_TIME));
  Status = RT->GetTime(&Time, NULL);
  if (EFI_ERROR (Status)) {
    FreePool(NewData);
    return Status;
  }
  Time.Pad1       = 0;
  Time.Nanosecond = 0;
  Time.TimeZone   = 0;
  Time.Daylight   = 0;
  Time.Pad2       = 0;
  CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
 
  DescriptorData->AuthInfo.Hdr.dwLength         = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
  DescriptorData->AuthInfo.Hdr.wRevision        = 0x0200;
  DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
  DescriptorData->AuthInfo.CertType =  efi_cert_type;
 
  /* we're expecting an EFI signature list, so don't free the input since
   * it might not be in a pool */
#if 0
  if (Payload != NULL) {
    FreePool(Payload);
  }
#endif
  
  *DataSize = DescriptorSize + PayloadSize;
  *Data     = NewData;
  return EFI_SUCCESS;
}
Ejemplo n.º 16
0
/**
  Create 4G PageTable in SMRAM.

  @param[in]      Is32BitPageTable Whether the page table is 32-bit PAE
  @return         PageTable Address

**/
UINT32
Gen4GPageTable (
  IN      BOOLEAN                   Is32BitPageTable
  )
{
  VOID    *PageTable;
  UINTN   Index;
  UINT64  *Pte;
  UINTN   PagesNeeded;
  UINTN   Low2MBoundary;
  UINTN   High2MBoundary;
  UINTN   Pages;
  UINTN   GuardPage;
  UINT64  *Pdpte;
  UINTN   PageIndex;
  UINTN   PageAddress;

  Low2MBoundary = 0;
  High2MBoundary = 0;
  PagesNeeded = 0;
  if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
    //
    // Add one more page for known good stack, then find the lower 2MB aligned address.
    //
    Low2MBoundary = (mSmmStackArrayBase + EFI_PAGE_SIZE) & ~(SIZE_2MB-1);
    //
    // Add two more pages for known good stack and stack guard page,
    // then find the lower 2MB aligned address.
    //
    High2MBoundary = (mSmmStackArrayEnd - mSmmStackSize + EFI_PAGE_SIZE * 2) & ~(SIZE_2MB-1);
    PagesNeeded = ((High2MBoundary - Low2MBoundary) / SIZE_2MB) + 1;
  }
  //
  // Allocate the page table
  //
  PageTable = AllocatePageTableMemory (5 + PagesNeeded);
  ASSERT (PageTable != NULL);

  PageTable = (VOID *)((UINTN)PageTable);
  Pte = (UINT64*)PageTable;

  //
  // Zero out all page table entries first
  //
  ZeroMem (Pte, EFI_PAGES_TO_SIZE (1));

  //
  // Set Page Directory Pointers
  //
  for (Index = 0; Index < 4; Index++) {
    Pte[Index] = ((UINTN)PageTable + EFI_PAGE_SIZE * (Index + 1)) | mAddressEncMask |
                   (Is32BitPageTable ? IA32_PAE_PDPTE_ATTRIBUTE_BITS : PAGE_ATTRIBUTE_BITS);
  }
  Pte += EFI_PAGE_SIZE / sizeof (*Pte);

  //
  // Fill in Page Directory Entries
  //
  for (Index = 0; Index < EFI_PAGE_SIZE * 4 / sizeof (*Pte); Index++) {
    Pte[Index] = (Index << 21) | mAddressEncMask | IA32_PG_PS | PAGE_ATTRIBUTE_BITS;
  }

  Pdpte = (UINT64*)PageTable;
  if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
    Pages = (UINTN)PageTable + EFI_PAGES_TO_SIZE (5);
    GuardPage = mSmmStackArrayBase + EFI_PAGE_SIZE;
    for (PageIndex = Low2MBoundary; PageIndex <= High2MBoundary; PageIndex += SIZE_2MB) {
      Pte = (UINT64*)(UINTN)(Pdpte[BitFieldRead32 ((UINT32)PageIndex, 30, 31)] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));
      Pte[BitFieldRead32 ((UINT32)PageIndex, 21, 29)] = (UINT64)Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS;
      //
      // Fill in Page Table Entries
      //
      Pte = (UINT64*)Pages;
      PageAddress = PageIndex;
      for (Index = 0; Index < EFI_PAGE_SIZE / sizeof (*Pte); Index++) {
        if (PageAddress == GuardPage) {
          //
          // Mark the guard page as non-present
          //
          Pte[Index] = PageAddress | mAddressEncMask;
          GuardPage += mSmmStackSize;
          if (GuardPage > mSmmStackArrayEnd) {
            GuardPage = 0;
          }
        } else {
          Pte[Index] = PageAddress | mAddressEncMask | PAGE_ATTRIBUTE_BITS;
        }
        PageAddress+= EFI_PAGE_SIZE;
      }
      Pages += EFI_PAGE_SIZE;
    }
  }

  if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) {
    Pte = (UINT64*)(UINTN)(Pdpte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));
    if ((Pte[0] & IA32_PG_PS) == 0) {
      // 4K-page entries are already mapped. Just hide the first one anyway.
      Pte = (UINT64*)(UINTN)(Pte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));
      Pte[0] &= ~(UINT64)IA32_PG_P; // Hide page 0
    } else {
      // Create 4K-page entries
      Pages = (UINTN)AllocatePageTableMemory (1);
      ASSERT (Pages != 0);

      Pte[0] = (UINT64)(Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS);

      Pte = (UINT64*)Pages;
      PageAddress = 0;
      Pte[0] = PageAddress | mAddressEncMask; // Hide page 0 but present left
      for (Index = 1; Index < EFI_PAGE_SIZE / sizeof (*Pte); Index++) {
        PageAddress += EFI_PAGE_SIZE;
        Pte[Index] = PageAddress | mAddressEncMask | PAGE_ATTRIBUTE_BITS;
      }
    }
  }

  return (UINT32)(UINTN)PageTable;
}
Ejemplo n.º 17
0
EFI_STATUS fsw_efi_dnode_getinfo(IN FSW_FILE_DATA *File,
                                 IN EFI_GUID *InformationType,
                                 IN OUT UINTN *BufferSize,
                                 OUT VOID *Buffer)
{
    EFI_STATUS          Status;
    FSW_VOLUME_DATA     *Volume = (FSW_VOLUME_DATA *)File->shand.dnode->vol->host_data;
    EFI_FILE_SYSTEM_INFO *FSInfo;
    UINTN               RequiredSize;
    struct fsw_volume_stat vsb;

    if (CompareGuid(InformationType, &GUID_NAME(FileInfo))) {
#if DEBUG_LEVEL
        Print(L"fsw_efi_dnode_getinfo: FILE_INFO\n");
#endif

        Status = fsw_efi_dnode_fill_FileInfo(Volume, File->shand.dnode, BufferSize, Buffer);

    } else if (CompareGuid(InformationType, &GUID_NAME(FileSystemInfo)) == 0) {
#if DEBUG_LEVEL
        Print(L"fsw_efi_dnode_getinfo: FILE_SYSTEM_INFO\n");
#endif

        // check buffer size
        RequiredSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + fsw_efi_strsize(&Volume->vol->label);
        if (*BufferSize < RequiredSize) {
            *BufferSize = RequiredSize;
            return EFI_BUFFER_TOO_SMALL;
        }

        // fill structure
        FSInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;
        FSInfo->Size        = RequiredSize;
        FSInfo->ReadOnly    = TRUE;
        FSInfo->BlockSize   = Volume->vol->log_blocksize;
        fsw_efi_strcpy(FSInfo->VolumeLabel, &Volume->vol->label);

        // get the missing info from the fs driver
        ZeroMem(&vsb, sizeof(struct fsw_volume_stat));
        Status = fsw_efi_map_status(fsw_volume_stat(Volume->vol, &vsb), Volume);
        if (EFI_ERROR(Status))
            return Status;
        FSInfo->VolumeSize  = vsb.total_bytes;
        FSInfo->FreeSpace   = vsb.free_bytes;

        // prepare for return
        *BufferSize = RequiredSize;
        Status = EFI_SUCCESS;

    } else if (CompareGuid(InformationType, &GUID_NAME(FileSystemVolumeLabelInfoId))) {
#if DEBUG_LEVEL
        Print(L"fsw_efi_dnode_getinfo: FILE_SYSTEM_VOLUME_LABEL\n");
#endif

        // check buffer size
        RequiredSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + fsw_efi_strsize(&Volume->vol->label);
        if (*BufferSize < RequiredSize) {
            *BufferSize = RequiredSize;
            return EFI_BUFFER_TOO_SMALL;
        }

        // copy volume label
        fsw_efi_strcpy(((EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *)Buffer)->VolumeLabel, &Volume->vol->label);

        // prepare for return
        *BufferSize = RequiredSize;
        Status = EFI_SUCCESS;

    } else {
        Status = EFI_UNSUPPORTED;
    }

    return Status;
}
Ejemplo n.º 18
0
/**
  Get selection for OneOf and OrderedList (Left/Right will be ignored).

  @param  MenuOption        Pointer to the current input menu.

  @retval EFI_SUCCESS       If Option input is processed successfully
  @retval EFI_DEVICE_ERROR  If operation fails

**/
EFI_STATUS
GetSelectionInputPopUp (
  IN  UI_MENU_OPTION              *MenuOption
  )
{
  EFI_INPUT_KEY           Key;
  UINTN                   Index;
  CHAR16                  *StringPtr;
  CHAR16                  *TempStringPtr;
  UINTN                   Index2;
  UINTN                   TopOptionIndex;
  UINTN                   HighlightOptionIndex;
  UINTN                   Start;
  UINTN                   End;
  UINTN                   Top;
  UINTN                   Bottom;
  UINTN                   PopUpMenuLines;
  UINTN                   MenuLinesInView;
  UINTN                   PopUpWidth;
  CHAR16                  Character;
  INT32                   SavedAttribute;
  BOOLEAN                 ShowDownArrow;
  BOOLEAN                 ShowUpArrow;
  UINTN                   DimensionsWidth;
  LIST_ENTRY              *Link;
  BOOLEAN                 OrderedList;
  UINT8                   *ValueArray;
  UINT8                   *ReturnValue;
  UINT8                   ValueType;
  EFI_HII_VALUE           HiiValue;
  DISPLAY_QUESTION_OPTION         *OneOfOption;
  DISPLAY_QUESTION_OPTION         *CurrentOption;
  FORM_DISPLAY_ENGINE_STATEMENT  *Question;
  INTN                    Result;
  EFI_IFR_ORDERED_LIST    *OrderList;

  DimensionsWidth   = gStatementDimensions.RightColumn - gStatementDimensions.LeftColumn;

  ValueArray        = NULL;
  ValueType         = 0;
  CurrentOption     = NULL;
  ShowDownArrow     = FALSE;
  ShowUpArrow       = FALSE;

  ZeroMem (&HiiValue, sizeof (EFI_HII_VALUE));

  Question = MenuOption->ThisTag;
  if (Question->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) {
    Link = GetFirstNode (&Question->OptionListHead);
    OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
    ValueArray = Question->CurrentValue.Buffer;
    ValueType =  OneOfOption->OptionOpCode->Type;
    OrderedList = TRUE;
    OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode;
  } else {
    OrderedList = FALSE;
    OrderList = NULL;
  }

  //
  // Calculate Option count
  //
  PopUpMenuLines = 0;
  if (OrderedList) {
    AdjustOptionOrder(Question, &PopUpMenuLines);
  } else {
    Link = GetFirstNode (&Question->OptionListHead);
    while (!IsNull (&Question->OptionListHead, Link)) {
      OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
      PopUpMenuLines++;
      Link = GetNextNode (&Question->OptionListHead, Link);
    }
  }

  //
  // Get the number of one of options present and its size
  //
  PopUpWidth = 0;
  HighlightOptionIndex = 0;
  Link = GetFirstNode (&Question->OptionListHead);
  for (Index = 0; Index < PopUpMenuLines; Index++) {
    OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);

    StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
    if (StrLen (StringPtr) > PopUpWidth) {
      PopUpWidth = StrLen (StringPtr);
    }
    FreePool (StringPtr);
    HiiValue.Type = OneOfOption->OptionOpCode->Type;
    SetValuesByType (&HiiValue.Value, &OneOfOption->OptionOpCode->Value, HiiValue.Type);
    if (!OrderedList && (CompareHiiValue (&Question->CurrentValue, &HiiValue, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
      //
      // Find current selected Option for OneOf
      //
      HighlightOptionIndex = Index;
    }

    Link = GetNextNode (&Question->OptionListHead, Link);
  }

  //
  // Perform popup menu initialization.
  //
  PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT;

  SavedAttribute = gST->ConOut->Mode->Attribute;
  gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());

  if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) {
    PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH;
  }

  Start  = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gStatementDimensions.LeftColumn;
  End    = Start + PopUpWidth + POPUP_FRAME_WIDTH;
  Top    = gStatementDimensions.TopRow;
  Bottom = gStatementDimensions.BottomRow - 1;

  MenuLinesInView = Bottom - Top - 1;
  if (MenuLinesInView >= PopUpMenuLines) {
    Top     = Top + (MenuLinesInView - PopUpMenuLines) / 2;
    Bottom  = Top + PopUpMenuLines + 1;
  } else {
    ShowDownArrow = TRUE;
  }

  if (HighlightOptionIndex > (MenuLinesInView - 1)) {
    TopOptionIndex = HighlightOptionIndex - MenuLinesInView + 1;
  } else {
    TopOptionIndex = 0;
  }

  do {
    //
    // Clear that portion of the screen
    //
    ClearLines (Start, End, Top, Bottom, GetPopupColor ());

    //
    // Draw "One of" pop-up menu
    //
    Character = BOXDRAW_DOWN_RIGHT;
    PrintCharAt (Start, Top, Character);
    for (Index = Start; Index + 2 < End; Index++) {
      if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) {
        Character = GEOMETRICSHAPE_UP_TRIANGLE;
      } else {
        Character = BOXDRAW_HORIZONTAL;
      }

      PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
    }

    Character = BOXDRAW_DOWN_LEFT;
    PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
    Character = BOXDRAW_VERTICAL;
    for (Index = Top + 1; Index < Bottom; Index++) {
      PrintCharAt (Start, Index, Character);
      PrintCharAt (End - 1, Index, Character);
    }

    //
    // Move to top Option
    //
    Link = GetFirstNode (&Question->OptionListHead);
    for (Index = 0; Index < TopOptionIndex; Index++) {
      Link = GetNextNode (&Question->OptionListHead, Link);
    }

    //
    // Display the One of options
    //
    Index2 = Top + 1;
    for (Index = TopOptionIndex; (Index < PopUpMenuLines) && (Index2 < Bottom); Index++) {
      OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
      Link = GetNextNode (&Question->OptionListHead, Link);

      StringPtr = GetToken (OneOfOption->OptionOpCode->Option, gFormData->HiiHandle);
      ASSERT (StringPtr != NULL);
      //
      // If the string occupies multiple lines, truncate it to fit in one line,
      // and append a "..." for indication.
      //
      if (StrLen (StringPtr) > (PopUpWidth - 1)) {
        TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1));
        ASSERT ( TempStringPtr != NULL );
        CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5)));
        FreePool (StringPtr);
        StringPtr = TempStringPtr;
        StrCatS (StringPtr, PopUpWidth - 1, L"...");
      }

      if (Index == HighlightOptionIndex) {
          //
          // Highlight the selected one
          //
          CurrentOption = OneOfOption;

          gST->ConOut->SetAttribute (gST->ConOut, GetPickListColor ());
          PrintStringAt (Start + 2, Index2, StringPtr);
          gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
        } else {
          gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
          PrintStringAt (Start + 2, Index2, StringPtr);
        }

      Index2++;
      FreePool (StringPtr);
    }

    Character = BOXDRAW_UP_RIGHT;
    PrintCharAt (Start, Bottom, Character);
    for (Index = Start; Index + 2 < End; Index++) {
      if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) {
        Character = GEOMETRICSHAPE_DOWN_TRIANGLE;
      } else {
        Character = BOXDRAW_HORIZONTAL;
      }

      PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
    }

    Character = BOXDRAW_UP_LEFT;
    PrintCharAt ((UINTN)-1, (UINTN)-1, Character);

    //
    // Get User selection
    //
    Key.UnicodeChar = CHAR_NULL;
    if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) {
      Key.ScanCode  = gDirection;
      gDirection    = 0;
      goto TheKey;
    }

    WaitForKeyStroke (&Key);

TheKey:
    switch (Key.UnicodeChar) {
    case '+':
      if (OrderedList) {
        if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {
          //
          // Highlight reaches the top of the popup window, scroll one menu item.
          //
          TopOptionIndex--;
          ShowDownArrow = TRUE;
        }

        if (TopOptionIndex == 0) {
          ShowUpArrow = FALSE;
        }

        if (HighlightOptionIndex > 0) {
          HighlightOptionIndex--;

          ASSERT (CurrentOption != NULL);
          SwapListEntries (CurrentOption->Link.BackLink, &CurrentOption->Link);
        }
      }
      break;

    case '-':
      //
      // If an ordered list op-code, we will allow for a popup of +/- keys
      // to create an ordered list of items
      //
      if (OrderedList) {
        if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&
            (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {
          //
          // Highlight reaches the bottom of the popup window, scroll one menu item.
          //
          TopOptionIndex++;
          ShowUpArrow = TRUE;
        }

        if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {
          ShowDownArrow = FALSE;
        }

        if (HighlightOptionIndex < (PopUpMenuLines - 1)) {
          HighlightOptionIndex++;

          ASSERT (CurrentOption != NULL);
          SwapListEntries (&CurrentOption->Link, CurrentOption->Link.ForwardLink);
        }
      }
      break;

    case CHAR_NULL:
      switch (Key.ScanCode) {
      case SCAN_UP:
      case SCAN_DOWN:
        if (Key.ScanCode == SCAN_UP) {
          if ((TopOptionIndex > 0) && (TopOptionIndex == HighlightOptionIndex)) {
            //
            // Highlight reaches the top of the popup window, scroll one menu item.
            //
            TopOptionIndex--;
            ShowDownArrow = TRUE;
          }

          if (TopOptionIndex == 0) {
            ShowUpArrow = FALSE;
          }

          if (HighlightOptionIndex > 0) {
            HighlightOptionIndex--;
          }
        } else {
          if (((TopOptionIndex + MenuLinesInView) < PopUpMenuLines) &&
              (HighlightOptionIndex == (TopOptionIndex + MenuLinesInView - 1))) {
            //
            // Highlight reaches the bottom of the popup window, scroll one menu item.
            //
            TopOptionIndex++;
            ShowUpArrow = TRUE;
          }

          if ((TopOptionIndex + MenuLinesInView) == PopUpMenuLines) {
            ShowDownArrow = FALSE;
          }

          if (HighlightOptionIndex < (PopUpMenuLines - 1)) {
            HighlightOptionIndex++;
          }
        }
        break;

      case SCAN_ESC:
        gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);

        //
        // Restore link list order for orderedlist
        //
        if (OrderedList) {
          HiiValue.Type = ValueType;
          HiiValue.Value.u64 = 0;
          for (Index = 0; Index < OrderList->MaxContainers; Index++) {
            HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);
            if (HiiValue.Value.u64 == 0) {
              break;
            }

            OneOfOption = ValueToOption (Question, &HiiValue);
            if (OneOfOption == NULL) {
              return EFI_NOT_FOUND;
            }

            RemoveEntryList (&OneOfOption->Link);
            InsertTailList (&Question->OptionListHead, &OneOfOption->Link);
          }
        }

        return EFI_DEVICE_ERROR;

      default:
        break;
      }

      break;

    case CHAR_CARRIAGE_RETURN:
      //
      // return the current selection
      //
      if (OrderedList) {
        ReturnValue = AllocateZeroPool (Question->CurrentValue.BufferLen);
        ASSERT (ReturnValue != NULL);
        Index = 0;
        Link = GetFirstNode (&Question->OptionListHead);
        while (!IsNull (&Question->OptionListHead, Link)) {
          OneOfOption = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
          Link = GetNextNode (&Question->OptionListHead, Link);

          SetArrayData (ReturnValue, ValueType, Index, OneOfOption->OptionOpCode->Value.u64);

          Index++;
          if (Index > OrderList->MaxContainers) {
            break;
          }
        }
        if (CompareMem (ReturnValue, ValueArray, Question->CurrentValue.BufferLen) == 0) {
          FreePool (ReturnValue);
          return EFI_DEVICE_ERROR;
        } else {
          gUserInput->InputValue.Buffer = ReturnValue;
          gUserInput->InputValue.BufferLen = Question->CurrentValue.BufferLen;
        }
      } else {
        ASSERT (CurrentOption != NULL);
        gUserInput->InputValue.Type = CurrentOption->OptionOpCode->Type;
        if (IsValuesEqual (&Question->CurrentValue.Value, &CurrentOption->OptionOpCode->Value, gUserInput->InputValue.Type)) {
          return EFI_DEVICE_ERROR;
        } else {
          SetValuesByType (&gUserInput->InputValue.Value, &CurrentOption->OptionOpCode->Value, gUserInput->InputValue.Type);
        }
      }

      gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);

      return EFI_SUCCESS;

    default:
      break;
    }
  } while (TRUE);

}
Ejemplo n.º 19
0
EFI_STATUS
EFIAPI
SetPeiCacheMode (
  IN  CONST EFI_PEI_SERVICES    **PeiServices
  )
{
  EFI_STATUS              Status;
  PEI_CACHE_PPI           *CachePpi;

  EFI_BOOT_MODE           BootMode;
  UINT64                  MemoryLength;
  UINT64                  MemOverflow;
  UINT64                  MemoryLengthUc;
  UINT64                  MaxMemoryLength;
  UINT64                  LowMemoryLength;
  UINT64                  HighMemoryLength;
  UINT8                   Index;
  MTRR_SETTINGS           MtrrSetting;
  UINT64                  ValidMtrrAddressMask;

  //
  // Load Cache PPI
  //
  Status = (**PeiServices).LocatePpi (
             PeiServices,
             &gPeiCachePpiGuid,    // GUID
             0,                    // Instance
             NULL,                 // EFI_PEI_PPI_DESCRIPTOR
             (void **)&CachePpi             // PPI
             );
  if (!EFI_ERROR(Status)) {
    //
    // Clear the CAR Settings (Default Cache Type => UC)
    //
    DEBUG ((EFI_D_INFO, "Reset cache attribute and disable CAR. \n"));
    CachePpi->ResetCache(
                (EFI_PEI_SERVICES**)PeiServices,
                CachePpi
                );
 }


  //
  // Variable initialization
  //
  LowMemoryLength = 0;
  HighMemoryLength = 0;
  MemoryLengthUc = 0;

  Status = (*PeiServices)->GetBootMode (
                             PeiServices,
                             &BootMode
                             );

  ValidMtrrAddressMask = InitializeAddressMtrrMask ();

  //
  // Determine memory usage
  //
  GetMemorySize (
    PeiServices,
    &LowMemoryLength,
    &HighMemoryLength
    );

  LowMemoryLength  = (EFI_PHYSICAL_ADDRESS)MmPci32( 0, 0, 2, 0, 0x70);
  LowMemoryLength   &=  0xFFF00000ULL;

  MaxMemoryLength = LowMemoryLength;

  //
  // Round up to nearest 256MB with high memory and 64MB w/o high memory
  //
  if (HighMemoryLength != 0 ) {
    MemOverflow = (LowMemoryLength & 0x0fffffff);
    if (MemOverflow != 0) {
      MaxMemoryLength = LowMemoryLength + (0x10000000 - MemOverflow);
    }
  } else {
    MemOverflow = (LowMemoryLength & 0x03ffffff);
    if (MemOverflow != 0) {
      MaxMemoryLength = LowMemoryLength + (0x4000000 - MemOverflow);
    }
  }

  ZeroMem (&MtrrSetting, sizeof(MTRR_SETTINGS));
  for (Index = 0; Index < 2; Index++) {
    MtrrSetting.Fixed.Mtrr[Index]=0x0606060606060606;
   }
  for (Index = 2; Index < 11; Index++) {
    MtrrSetting.Fixed.Mtrr[Index]=0x0505050505050505;
   }

  //
  // Cache the flash area to improve the boot performance in PEI phase
  //
  Index = 0;
  ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Base)->Uint64 = FixedPcdGet32 (PcdFlashAreaBaseAddress);
  ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Base)->Bits.Type = CacheWriteProtected;
  ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Mask)->Uint64 = (~((UINT64)(FixedPcdGet32 (PcdFlashAreaSize) - 1))) & ValidMtrrAddressMask;
  ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Mask)->Bits.V = 1;

  Index ++;

  MemOverflow =0;
  while (MaxMemoryLength > MemOverflow){
    MemoryLength = MaxMemoryLength - MemOverflow;
    MemoryLength = GetPowerOfTwo64 (MemoryLength);

    ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = MemOverflow & ValidMtrrAddressMask;
    ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheWriteBack;
    ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLength - 1)) & ValidMtrrAddressMask;
    ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1;

    MemOverflow += MemoryLength;
    Index++;
  }

  MemoryLength = LowMemoryLength;

  while (MaxMemoryLength != MemoryLength) {
    MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength);

    ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = (MaxMemoryLength - MemoryLengthUc) & ValidMtrrAddressMask;
    ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheUncacheable;
    ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLengthUc   - 1)) & ValidMtrrAddressMask;
    ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1;

    MaxMemoryLength -= MemoryLengthUc;
    Index++;
  }

  MemOverflow =0x100000000;
  while (HighMemoryLength > 0) {

    MemoryLength = HighMemoryLength;
    MemoryLength = GetPowerOfTwo64 (MemoryLength);
    if (MemoryLength > MemOverflow){
      MemoryLength = MemOverflow;
    }

    ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = MemOverflow & ValidMtrrAddressMask;
    ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheWriteBack;
    ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLength - 1)) & ValidMtrrAddressMask;
    ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1;

    MemOverflow += MemoryLength;
    HighMemoryLength -= MemoryLength;
    Index++;
  }


  for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {
    if (MtrrSetting.Variables.Mtrr[Index].Base == 0){
      break;
    }
    DEBUG ((EFI_D_INFO, "Base=%lx, Mask=%lx\n",MtrrSetting.Variables.Mtrr[Index].Base ,MtrrSetting.Variables.Mtrr[Index].Mask));
  }

  //
  // set FE/E bits for IA32_MTRR_DEF_TYPE
  //
  MtrrSetting.MtrrDefType |=  3 <<10;

  MtrrSetAllMtrrs(&MtrrSetting);
  //
  // Dump MTRR Setting
  //
  MtrrDebugPrintAllMtrrs ();

  return EFI_SUCCESS;
}
Ejemplo n.º 20
0
/**
  This routine reads a numeric value from the user input.

  @param  MenuOption        Pointer to the current input menu.

  @retval EFI_SUCCESS       If numerical input is read successfully
  @retval EFI_DEVICE_ERROR  If operation fails

**/
EFI_STATUS
GetNumericInput (
  IN  UI_MENU_OPTION              *MenuOption
  )
{
  UINTN                   Column;
  UINTN                   Row;
  CHAR16                  InputText[MAX_NUMERIC_INPUT_WIDTH];
  CHAR16                  FormattedNumber[MAX_NUMERIC_INPUT_WIDTH - 1];
  UINT64                  PreviousNumber[MAX_NUMERIC_INPUT_WIDTH - 3];
  UINTN                   Count;
  UINTN                   Loop;
  BOOLEAN                 ManualInput;
  BOOLEAN                 HexInput;
  BOOLEAN                 IntInput;
  BOOLEAN                 Negative;
  BOOLEAN                 ValidateFail;
  BOOLEAN                 DateOrTime;
  UINTN                   InputWidth;
  UINT64                  EditValue;
  UINT64                  Step;
  UINT64                  Minimum;
  UINT64                  Maximum;
  UINTN                   EraseLen;
  UINT8                   Digital;
  EFI_INPUT_KEY           Key;
  EFI_HII_VALUE           *QuestionValue;
  FORM_DISPLAY_ENGINE_STATEMENT  *Question;
  EFI_IFR_NUMERIC                *NumericOp;
  UINT16                         StorageWidth;

  Column            = MenuOption->OptCol;
  Row               = MenuOption->Row;
  PreviousNumber[0] = 0;
  Count             = 0;
  InputWidth        = 0;
  Digital           = 0;
  StorageWidth      = 0;
  Minimum           = 0;
  Maximum           = 0;
  NumericOp         = NULL;
  IntInput          = FALSE;
  HexInput          = FALSE;
  Negative          = FALSE;
  ValidateFail      = FALSE;

  Question      = MenuOption->ThisTag;
  QuestionValue = &Question->CurrentValue;
  ZeroMem (InputText, MAX_NUMERIC_INPUT_WIDTH * sizeof (CHAR16));

  //
  // Only two case, user can enter to this function: Enter and +/- case.
  // In Enter case, gDirection = 0; in +/- case, gDirection = SCAN_LEFT/SCAN_WRIGHT
  //
  ManualInput        = (BOOLEAN)(gDirection == 0 ? TRUE : FALSE);

  if ((Question->OpCode->OpCode == EFI_IFR_DATE_OP) || (Question->OpCode->OpCode == EFI_IFR_TIME_OP)) {
    DateOrTime = TRUE;
  } else {
    DateOrTime = FALSE;
  }

  //
  // Prepare Value to be edit
  //
  EraseLen = 0;
  EditValue = 0;
  if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {
    Step = 1;
    Minimum = 1;

    switch (MenuOption->Sequence) {
    case 0:
      Maximum = 12;
      EraseLen = 4;
      EditValue = QuestionValue->Value.date.Month;
      break;

    case 1:
      switch (QuestionValue->Value.date.Month) {
      case 2:
        if ((QuestionValue->Value.date.Year % 4) == 0  &&
            ((QuestionValue->Value.date.Year % 100) != 0 ||
            (QuestionValue->Value.date.Year % 400) == 0)) {
          Maximum = 29;
        } else {
          Maximum = 28;
        }
        break;
      case 4:
      case 6:
      case 9:
      case 11:
        Maximum = 30;
        break;
      default:
        Maximum = 31;
        break;
      }

      EraseLen = 3;
      EditValue = QuestionValue->Value.date.Day;
      break;

    case 2:
      Maximum = 0xffff;
      EraseLen = 5;
      EditValue = QuestionValue->Value.date.Year;
      break;

    default:
      break;
    }
  } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {
    Step = 1;
    Minimum = 0;

    switch (MenuOption->Sequence) {
    case 0:
      Maximum = 23;
      EraseLen = 4;
      EditValue = QuestionValue->Value.time.Hour;
      break;

    case 1:
      Maximum = 59;
      EraseLen = 3;
      EditValue = QuestionValue->Value.time.Minute;
      break;

    case 2:
      Maximum = 59;
      EraseLen = 3;
      EditValue = QuestionValue->Value.time.Second;
      break;

    default:
      break;
    }
  } else {
    ASSERT (Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP);
    NumericOp = (EFI_IFR_NUMERIC *) Question->OpCode;
    GetValueFromNum(Question->OpCode, (NumericOp->Flags & EFI_IFR_DISPLAY) == 0, QuestionValue, &EditValue, &Minimum, &Maximum, &Step, &StorageWidth);
    EraseLen  = gOptionBlockWidth;
  }

  if ((Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) && (NumericOp != NULL)) {
    if ((NumericOp->Flags & EFI_IFR_DISPLAY) == EFI_IFR_DISPLAY_UINT_HEX){
      HexInput = TRUE;
    } else if ((NumericOp->Flags & EFI_IFR_DISPLAY) == 0){
      //
      // Display with EFI_IFR_DISPLAY_INT_DEC type. Support negative number.
      //
      IntInput = TRUE;
    }
  }

  //
  // Enter from "Enter" input, clear the old word showing.
  //
  if (ManualInput) {
    if (Question->OpCode->OpCode == EFI_IFR_NUMERIC_OP) {
      if (HexInput) {
        InputWidth = StorageWidth * 2;
      } else {
        switch (StorageWidth) {
        case 1:
          InputWidth = 3;
          break;

        case 2:
          InputWidth = 5;
          break;

        case 4:
          InputWidth = 10;
          break;

        case 8:
          InputWidth = 20;
          break;

        default:
          InputWidth = 0;
          break;
        }

        if (IntInput) {
          //
          // Support an extra '-' for negative number.
          //
          InputWidth += 1;
        }
      }

      InputText[0] = LEFT_NUMERIC_DELIMITER;
      SetUnicodeMem (InputText + 1, InputWidth, L' ');
      ASSERT (InputWidth + 2 < MAX_NUMERIC_INPUT_WIDTH);
      InputText[InputWidth + 1] = RIGHT_NUMERIC_DELIMITER;
      InputText[InputWidth + 2] = L'\0';

      PrintStringAt (Column, Row, InputText);
      Column++;
    }

    if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {
      if (MenuOption->Sequence == 2) {
        InputWidth = 4;
      } else {
        InputWidth = 2;
      }

      if (MenuOption->Sequence == 0) {
        InputText[0] = LEFT_NUMERIC_DELIMITER;
        SetUnicodeMem (InputText + 1, InputWidth, L' ');
        InputText[InputWidth + 1] = DATE_SEPARATOR;
        InputText[InputWidth + 2] = L'\0';
      } else  if (MenuOption->Sequence == 1){
        SetUnicodeMem (InputText, InputWidth, L' ');
        InputText[InputWidth] = DATE_SEPARATOR;
        InputText[InputWidth + 1] = L'\0';
      } else {
        SetUnicodeMem (InputText, InputWidth, L' ');
        InputText[InputWidth] = RIGHT_NUMERIC_DELIMITER;
        InputText[InputWidth + 1] = L'\0';
      }

      PrintStringAt (Column, Row, InputText);
      if (MenuOption->Sequence == 0) {
        Column++;
      }
    }

    if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {
      InputWidth = 2;

      if (MenuOption->Sequence == 0) {
        InputText[0] = LEFT_NUMERIC_DELIMITER;
        SetUnicodeMem (InputText + 1, InputWidth, L' ');
        InputText[InputWidth + 1] = TIME_SEPARATOR;
        InputText[InputWidth + 2] = L'\0';
      } else if (MenuOption->Sequence == 1){
        SetUnicodeMem (InputText, InputWidth, L' ');
        InputText[InputWidth] = TIME_SEPARATOR;
        InputText[InputWidth + 1] = L'\0';
      } else {
        SetUnicodeMem (InputText, InputWidth, L' ');
        InputText[InputWidth] = RIGHT_NUMERIC_DELIMITER;
        InputText[InputWidth + 1] = L'\0';
      }

      PrintStringAt (Column, Row, InputText);
      if (MenuOption->Sequence == 0) {
        Column++;
      }
    }
  }

  //
  // First time we enter this handler, we need to check to see if
  // we were passed an increment or decrement directive
  //
  do {
    Key.UnicodeChar = CHAR_NULL;
    if (gDirection != 0) {
      Key.ScanCode  = gDirection;
      gDirection    = 0;
      goto TheKey2;
    }

    WaitForKeyStroke (&Key);

TheKey2:
    switch (Key.UnicodeChar) {

    case '+':
    case '-':
      if (ManualInput && IntInput) {
        //
        // In Manual input mode, check whether input the negative flag.
        //
        if (Key.UnicodeChar == '-') {
          if (Negative) {
            break;
          }
          Negative = TRUE;
          PrintCharAt (Column++, Row, Key.UnicodeChar);
        }
      } else {
        if (Key.UnicodeChar == '+') {
          Key.ScanCode = SCAN_RIGHT;
        } else {
          Key.ScanCode = SCAN_LEFT;
        }
        Key.UnicodeChar = CHAR_NULL;
        goto TheKey2;
      }
      break;

    case CHAR_NULL:
      switch (Key.ScanCode) {
      case SCAN_LEFT:
      case SCAN_RIGHT:
        if (DateOrTime && !ManualInput) {
          //
          // By setting this value, we will return back to the caller.
          // We need to do this since an auto-refresh will destroy the adjustment
          // based on what the real-time-clock is showing.  So we always commit
          // upon changing the value.
          //
          gDirection = SCAN_DOWN;
        }

        if ((Step != 0) && !ManualInput) {
          if (Key.ScanCode == SCAN_LEFT) {
            if (IntInput) {
              if ((INT64) EditValue >= (INT64) Minimum + (INT64) Step) {
                EditValue = EditValue - Step;
              } else if ((INT64) EditValue > (INT64) Minimum){
                EditValue = Minimum;
              } else {
                EditValue = Maximum;
              }
            } else {
              if (EditValue >= Minimum + Step) {
                EditValue = EditValue - Step;
              } else if (EditValue > Minimum){
                EditValue = Minimum;
              } else {
                EditValue = Maximum;
              }
            }
          } else if (Key.ScanCode == SCAN_RIGHT) {
            if (IntInput) {
              if ((INT64) EditValue + (INT64) Step <= (INT64) Maximum) {
                EditValue = EditValue + Step;
              } else if ((INT64) EditValue < (INT64) Maximum) {
                EditValue = Maximum;
              } else {
                EditValue = Minimum;
              }
            } else {
              if (EditValue + Step <= Maximum) {
                EditValue = EditValue + Step;
              } else if (EditValue < Maximum) {
                EditValue = Maximum;
              } else {
                EditValue = Minimum;
              }
            }
          }

          ZeroMem (FormattedNumber, 21 * sizeof (CHAR16));
          if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {
            if (MenuOption->Sequence == 2) {
              //
              // Year
              //
              UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%04d", (UINT16) EditValue);
            } else {
              //
              // Month/Day
              //
              UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue);
            }

            if (MenuOption->Sequence == 0) {
              ASSERT (EraseLen >= 2);
              FormattedNumber[EraseLen - 2] = DATE_SEPARATOR;
            } else if (MenuOption->Sequence == 1) {
              ASSERT (EraseLen >= 1);
              FormattedNumber[EraseLen - 1] = DATE_SEPARATOR;
            }
          } else if (Question->OpCode->OpCode == EFI_IFR_TIME_OP) {
            UnicodeSPrint (FormattedNumber, 21 * sizeof (CHAR16), L"%02d", (UINT8) EditValue);

            if (MenuOption->Sequence == 0) {
              ASSERT (EraseLen >= 2);
              FormattedNumber[EraseLen - 2] = TIME_SEPARATOR;
            } else if (MenuOption->Sequence == 1) {
              ASSERT (EraseLen >= 1);
              FormattedNumber[EraseLen - 1] = TIME_SEPARATOR;
            }
          } else {
            QuestionValue->Value.u64 = EditValue;
            PrintFormattedNumber (Question, FormattedNumber, 21 * sizeof (CHAR16));
          }

          gST->ConOut->SetAttribute (gST->ConOut, GetFieldTextColor ());
          for (Loop = 0; Loop < EraseLen; Loop++) {
            PrintStringAt (MenuOption->OptCol + Loop, MenuOption->Row, L" ");
          }
          gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());

          if (MenuOption->Sequence == 0) {
            PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER);
            Column = MenuOption->OptCol + 1;
          }

          PrintStringAt (Column, Row, FormattedNumber);

          if (!DateOrTime || MenuOption->Sequence == 2) {
            PrintCharAt ((UINTN)-1, (UINTN)-1, RIGHT_NUMERIC_DELIMITER);
          }
        }

        goto EnterCarriageReturn;

      case SCAN_UP:
      case SCAN_DOWN:
        goto EnterCarriageReturn;

      case SCAN_ESC:
        return EFI_DEVICE_ERROR;

      default:
        break;
      }

      break;

EnterCarriageReturn:

    case CHAR_CARRIAGE_RETURN:
      //
      // Validate input value with Minimum value.
      //
      ValidateFail = FALSE;
      if (IntInput) {
        //
        // After user input Enter, need to check whether the input value.
        // If input a negative value, should compare with maximum value.
        // else compare with the minimum value.
        //
        if (Negative) {
          ValidateFail = (INT64) EditValue > (INT64) Maximum ? TRUE : FALSE;
        } else {
          ValidateFail = (INT64) EditValue < (INT64) Minimum ? TRUE : FALSE;
        }

        if (ValidateFail) {
          UpdateStatusBar (INPUT_ERROR, TRUE);
          break;
        }
      } else if (EditValue < Minimum) {
        UpdateStatusBar (INPUT_ERROR, TRUE);
        break;
      }

      UpdateStatusBar (INPUT_ERROR, FALSE);
      CopyMem (&gUserInput->InputValue, &Question->CurrentValue, sizeof (EFI_HII_VALUE));
      QuestionValue = &gUserInput->InputValue;
      //
      // Store Edit value back to Question
      //
      if (Question->OpCode->OpCode == EFI_IFR_DATE_OP) {
        switch (MenuOption->Sequence) {
        case 0:
          QuestionValue->Value.date.Month = (UINT8) EditValue;
          break;

        case 1:
          QuestionValue->Value.date.Day = (UINT8) EditValue;
          break;

        case 2:
          QuestionValue->Value.date.Year = (UINT16) EditValue;
          break;

        default:
          break;
        }
      } else if (Question->OpCode->OpCode  == EFI_IFR_TIME_OP) {
        switch (MenuOption->Sequence) {
        case 0:
          QuestionValue->Value.time.Hour = (UINT8) EditValue;
          break;

        case 1:
          QuestionValue->Value.time.Minute = (UINT8) EditValue;
          break;

        case 2:
          QuestionValue->Value.time.Second = (UINT8) EditValue;
          break;

        default:
          break;
        }
      } else {
        //
        // Numeric
        //
        QuestionValue->Value.u64 = EditValue;
      }

      //
      // Adjust the value to the correct one.
      // Sample like: 2012.02.29 -> 2013.02.29 -> 2013.02.01
      //              2013.03.29 -> 2013.02.29 -> 2013.02.28
      //
      if (Question->OpCode->OpCode  == EFI_IFR_DATE_OP &&
        (MenuOption->Sequence == 0 || MenuOption->Sequence == 2)) {
        AdjustQuestionValue (QuestionValue, (UINT8)MenuOption->Sequence);
      }

      return EFI_SUCCESS;

    case CHAR_BACKSPACE:
      if (ManualInput) {
        if (Count == 0) {
          if (Negative) {
            Negative = FALSE;
            Column--;
            PrintStringAt (Column, Row, L" ");
          }
          break;
        }
        //
        // Remove a character
        //
        EditValue = PreviousNumber[Count - 1];
        UpdateStatusBar (INPUT_ERROR,  FALSE);
        Count--;
        Column--;
        PrintStringAt (Column, Row, L" ");
      }
      break;

    default:
      if (ManualInput) {
        if (HexInput) {
          if ((Key.UnicodeChar >= L'0') && (Key.UnicodeChar <= L'9')) {
            Digital = (UINT8) (Key.UnicodeChar - L'0');
          } else if ((Key.UnicodeChar >= L'A') && (Key.UnicodeChar <= L'F')) {
            Digital = (UINT8) (Key.UnicodeChar - L'A' + 0x0A);
          } else if ((Key.UnicodeChar >= L'a') && (Key.UnicodeChar <= L'f')) {
            Digital = (UINT8) (Key.UnicodeChar - L'a' + 0x0A);
          } else {
            UpdateStatusBar (INPUT_ERROR, TRUE);
            break;
          }
        } else {
          if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') {
            UpdateStatusBar (INPUT_ERROR, TRUE);
            break;
          }
        }

        //
        // If Count exceed input width, there is no way more is valid
        //
        if (Count >= InputWidth) {
          break;
        }
        //
        // Someone typed something valid!
        //
        if (Count != 0) {
          if (HexInput) {
            EditValue = LShiftU64 (EditValue, 4) + Digital;
          } else if (IntInput && Negative) {
            //
            // Save the negative number.
            //
            EditValue = ~(MultU64x32 (~(EditValue - 1), 10) + (Key.UnicodeChar - L'0')) + 1;
          } else {
            EditValue = MultU64x32 (EditValue, 10) + (Key.UnicodeChar - L'0');
          }
        } else {
          if (HexInput) {
            EditValue = Digital;
          } else if (IntInput && Negative) {
            //
            // Save the negative number.
            //
            EditValue = ~(Key.UnicodeChar - L'0') + 1;
          } else {
            EditValue = Key.UnicodeChar - L'0';
          }
        }

        if (IntInput) {
          ValidateFail = FALSE;
          //
          // When user input a new value, should check the current value.
          // If user input a negative value, should compare it with minimum
          // value, else compare it with maximum value.
          //
          if (Negative) {
            ValidateFail = (INT64) EditValue < (INT64) Minimum ? TRUE : FALSE;
          } else {
            ValidateFail = (INT64) EditValue > (INT64) Maximum ? TRUE : FALSE;
          }

          if (ValidateFail) {
            UpdateStatusBar (INPUT_ERROR, TRUE);
            ASSERT (Count < ARRAY_SIZE (PreviousNumber));
            EditValue = PreviousNumber[Count];
            break;
          }
        } else {
          if (EditValue > Maximum) {
            UpdateStatusBar (INPUT_ERROR, TRUE);
            ASSERT (Count < ARRAY_SIZE (PreviousNumber));
            EditValue = PreviousNumber[Count];
            break;
          }
        }

        UpdateStatusBar (INPUT_ERROR, FALSE);

        Count++;
        ASSERT (Count < (ARRAY_SIZE (PreviousNumber)));
        PreviousNumber[Count] = EditValue;

        gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());
        PrintCharAt (Column, Row, Key.UnicodeChar);
        Column++;
      }
      break;
    }
  } while (TRUE);
}
Ejemplo n.º 21
0
/**
  Fetch the Ifr binary data of a FormSet.

  @param  Handle                 PackageList Handle
  @param  FormSetGuid            GUID of a formset. If not specified (NULL or zero
                                 GUID), take the first FormSet found in package
                                 list.
  @param  BinaryLength           The length of the FormSet IFR binary.
  @param  BinaryData             The buffer designed to receive the FormSet.

  @retval EFI_SUCCESS            Buffer filled with the requested FormSet.
                                 BufferLength was updated.
  @retval EFI_INVALID_PARAMETER  The handle is unknown.
  @retval EFI_NOT_FOUND          A form or FormSet on the requested handle cannot
                                 be found with the requested FormId.

**/
EFI_STATUS
GetIfrBinaryData (
    IN  EFI_HII_HANDLE   Handle,
    IN OUT EFI_GUID      *FormSetGuid,
    OUT UINTN            *BinaryLength,
    OUT UINT8            **BinaryData
)
{
    EFI_STATUS                   Status;
    EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
    UINTN                        BufferSize;
    UINT8                        *Package;
    UINT8                        *OpCodeData;
    UINT32                       Offset;
    UINT32                       Offset2;
    BOOLEAN                      ReturnDefault;
    UINT32                       PackageListLength;
    EFI_HII_PACKAGE_HEADER       PackageHeader;

    OpCodeData = NULL;
    Package = NULL;
    ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));;

    //
    // if FormSetGuid is NULL or zero GUID, return first FormSet in the package list
    //
    if (FormSetGuid == NULL || CompareGuid (FormSetGuid, &gZeroGuid)) {
        ReturnDefault = TRUE;
    } else {
        ReturnDefault = FALSE;
    }

    //
    // Get HII PackageList
    //
    BufferSize = 0;
    HiiPackageList = NULL;
    Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
    if (Status == EFI_BUFFER_TOO_SMALL) {
        HiiPackageList = AllocatePool (BufferSize);
        ASSERT (HiiPackageList != NULL);

        Status = mHiiDatabase->ExportPackageLists (mHiiDatabase, Handle, &BufferSize, HiiPackageList);
    }
    if (EFI_ERROR (Status) || HiiPackageList == NULL) {
        return EFI_NOT_FOUND;
    }

    //
    // Get Form package from this HII package List
    //
    Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
    Offset2 = 0;
    CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));

    while (Offset < PackageListLength) {
        Package = ((UINT8 *) HiiPackageList) + Offset;
        CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));

        if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
            //
            // Search FormSet in this Form Package
            //
            Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
            while (Offset2 < PackageHeader.Length) {
                OpCodeData = Package + Offset2;

                if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
                    //
                    // Check whether return default FormSet
                    //
                    if (ReturnDefault) {
                        break;
                    }

                    //
                    // FormSet GUID is specified, check it
                    //
                    if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
                        break;
                    }
                }

                Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
            }

            if (Offset2 < PackageHeader.Length) {
                //
                // Target formset found
                //
                break;
            }
        }

        Offset += PackageHeader.Length;
    }

    if (Offset >= PackageListLength) {
        //
        // Form package not found in this Package List
        //
        gBS->FreePool (HiiPackageList);
        return EFI_NOT_FOUND;
    }

    if (ReturnDefault && FormSetGuid != NULL) {
        //
        // Return the default FormSet GUID
        //
        CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID));
    }

    //
    // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
    // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
    // of the Form Package.
    //
    *BinaryLength = PackageHeader.Length - Offset2;
    *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);

    gBS->FreePool (HiiPackageList);

    if (*BinaryData == NULL) {
        return EFI_OUT_OF_RESOURCES;
    }

    return EFI_SUCCESS;
}
Ejemplo n.º 22
0
/**
  Function is used for allocating a bi-directional FW_CFG_DMA_ACCESS used
  between Host and device to exchange the information. The buffer must be free'd
  using FreeFwCfgDmaAccessBuffer ().

**/
STATIC
VOID
AllocFwCfgDmaAccessBuffer (
  OUT   VOID     **Access,
  OUT   VOID     **MapInfo
  )
{
  UINTN                 Size;
  UINTN                 NumPages;
  EFI_STATUS            Status;
  VOID                  *HostAddress;
  EFI_PHYSICAL_ADDRESS  DmaAddress;
  VOID                  *Mapping;

  Size = sizeof (FW_CFG_DMA_ACCESS);
  NumPages = EFI_SIZE_TO_PAGES (Size);

  //
  // As per UEFI spec, in order to map a host address with
  // BusMasterCommomBuffer64, the buffer must be allocated using the IOMMU
  // AllocateBuffer()
  //
  Status = mIoMmuProtocol->AllocateBuffer (
                             mIoMmuProtocol,
                             AllocateAnyPages,
                             EfiBootServicesData,
                             NumPages,
                             &HostAddress,
                             EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE
                             );
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR,
      "%a:%a failed to allocate FW_CFG_DMA_ACCESS\n", gEfiCallerBaseName,
      __FUNCTION__));
    ASSERT (FALSE);
    CpuDeadLoop ();
  }

  //
  // Avoid exposing stale data even temporarily: zero the area before mapping
  // it.
  //
  ZeroMem (HostAddress, Size);

  //
  // Map the host buffer with BusMasterCommonBuffer64
  //
  Status = mIoMmuProtocol->Map (
                             mIoMmuProtocol,
                             EdkiiIoMmuOperationBusMasterCommonBuffer64,
                             HostAddress,
                             &Size,
                             &DmaAddress,
                             &Mapping
                             );
  if (EFI_ERROR (Status)) {
    mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, HostAddress);
    DEBUG ((DEBUG_ERROR,
      "%a:%a failed to Map() FW_CFG_DMA_ACCESS\n", gEfiCallerBaseName,
      __FUNCTION__));
    ASSERT (FALSE);
    CpuDeadLoop ();
  }

  if (Size < sizeof (FW_CFG_DMA_ACCESS)) {
    mIoMmuProtocol->Unmap (mIoMmuProtocol, Mapping);
    mIoMmuProtocol->FreeBuffer (mIoMmuProtocol, NumPages, HostAddress);
    DEBUG ((DEBUG_ERROR,
      "%a:%a failed to Map() - requested 0x%Lx got 0x%Lx\n", gEfiCallerBaseName,
      __FUNCTION__, (UINT64)sizeof (FW_CFG_DMA_ACCESS), (UINT64)Size));
    ASSERT (FALSE);
    CpuDeadLoop ();
  }

  *Access = HostAddress;
  *MapInfo = Mapping;
}
Ejemplo n.º 23
0
/**
  Update the banner information for the Front Page based on DataHub information.

**/
VOID
UpdateFrontPageStrings (
  VOID
  )
{
  UINT8                             StrIndex;
  CHAR16                            *NewString;
  BOOLEAN                           Find[5];
  EFI_STATUS                        Status;
  EFI_STRING_ID                     TokenToUpdate;
  EFI_SMBIOS_HANDLE                 SmbiosHandle;
  EFI_SMBIOS_PROTOCOL               *Smbios;
  SMBIOS_TABLE_TYPE0                *Type0Record;
  SMBIOS_TABLE_TYPE1                *Type1Record;
  SMBIOS_TABLE_TYPE4                *Type4Record;
  SMBIOS_TABLE_TYPE19               *Type19Record;
  EFI_SMBIOS_TABLE_HEADER           *Record;

  ZeroMem (Find, sizeof (Find));

  //
  // Update Front Page strings
  //
  Status = gBS->LocateProtocol (
                  &gEfiSmbiosProtocolGuid,
                  NULL,
                  (VOID **) &Smbios
                  );
  ASSERT_EFI_ERROR (Status);

  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
  do {
    Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
    if (EFI_ERROR(Status)) {
      break;
    }

    if (Record->Type == EFI_SMBIOS_TYPE_BIOS_INFORMATION) {
      Type0Record = (SMBIOS_TABLE_TYPE0 *) Record;
      StrIndex = Type0Record->BiosVersion;
      GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &NewString);
      TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION);
      HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
      FreePool (NewString);
      Find[0] = TRUE;
    }  

    if (Record->Type == EFI_SMBIOS_TYPE_SYSTEM_INFORMATION) {
      Type1Record = (SMBIOS_TABLE_TYPE1 *) Record;
      StrIndex = Type1Record->ProductName;
      GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type1Record + Type1Record->Hdr.Length), StrIndex, &NewString);
      TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_COMPUTER_MODEL);
      HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
      FreePool (NewString);
      Find[1] = TRUE;
    }
      
    if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) {
      Type4Record = (SMBIOS_TABLE_TYPE4 *) Record;
      StrIndex = Type4Record->ProcessorVersion;
      GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type4Record + Type4Record->Hdr.Length), StrIndex, &NewString);
      TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_MODEL);
      HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
      FreePool (NewString);
      Find[2] = TRUE;
    }    

    if (Record->Type == EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION) {
      Type4Record = (SMBIOS_TABLE_TYPE4 *) Record;
      ConvertProcessorToString(Type4Record->CurrentSpeed, 6, &NewString);
      TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_CPU_SPEED);
      HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
      FreePool (NewString);
      Find[3] = TRUE;
    } 

    if ( Record->Type == EFI_SMBIOS_TYPE_MEMORY_ARRAY_MAPPED_ADDRESS ) {
      Type19Record = (SMBIOS_TABLE_TYPE19 *) Record;
      ConvertMemorySizeToString (
        (UINT32)(RShiftU64((Type19Record->EndingAddress - Type19Record->StartingAddress + 1), 10)),
        &NewString
        );
      TokenToUpdate = STRING_TOKEN (STR_FRONT_PAGE_MEMORY_SIZE);
      HiiSetString (gFrontPagePrivate.HiiHandle, TokenToUpdate, NewString, NULL);
      FreePool (NewString);
      Find[4] = TRUE;  
    }
  } while ( !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4]));
  return ;
}
Ejemplo n.º 24
0
/**
  Install child handles if the Handle supports Apple partition table format.

  @param[in]  This        Calling context.
  @param[in]  Handle      Parent Handle
  @param[in]  DiskIo      Parent DiskIo interface
  @param[in]  BlockIo     Parent BlockIo interface
  @param[in]  DevicePath  Parent Device Path


  @retval EFI_SUCCESS         Child handle(s) was added
  @retval EFI_MEDIA_CHANGED   Media changed Detected
  @retval other               no child handle was added

**/
EFI_STATUS
PartitionInstallAppleChildHandles (
  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN  EFI_HANDLE                   Handle,
  IN  EFI_DISK_IO_PROTOCOL         *DiskIo,
  IN  EFI_BLOCK_IO_PROTOCOL        *BlockIo,
  IN  EFI_BLOCK_IO2_PROTOCOL       *BlockIo2,
  IN  EFI_DEVICE_PATH_PROTOCOL     *DevicePath
  )
{
  EFI_STATUS                Status;
  EFI_BLOCK_IO_MEDIA       *Media;
  CDROM_DEVICE_PATH         CdDev;
  UINT32                    Partition;
  UINT32                    PartitionEntries;
  UINT32                    VolSpaceSize;
  UINT32                    SubBlockSize;
  UINT32                    BlkPerSec;
  UINT32                    MediaId;
  UINT32                    BlockSize;
  EFI_LBA                   LastBlock;
  APPLE_PT_HEADER           *AppleHeader;
  APPLE_PT_ENTRY            *AppleEntry;
  UINT32                    StartLba;
  UINT32                    SizeLbs;

  AppleEntry = NULL;

  Media         = BlockIo->Media;
  BlockSize     = BlockIo->Media->BlockSize;
  LastBlock     = BlockIo->Media->LastBlock;
  MediaId       = BlockIo->Media->MediaId;
  VolSpaceSize  = 0;

  AppleHeader = AllocatePool (BlockSize);

  if (AppleHeader == NULL) {
    return EFI_NOT_FOUND;
  }

  do {
      Status = DiskIo->ReadDisk (
                       DiskIo,
                       MediaId,
                       0,
                       BlockSize,
                       AppleHeader
                       );
      if (EFI_ERROR (Status)) {
        goto done;
      }

      if (SwapBytes16(AppleHeader->sbSig) != 0x4552) {
        Status = EFI_NOT_FOUND;
        goto done; 
      }
      SubBlockSize = SwapBytes16(AppleHeader->sbBlkSize);
      BlkPerSec    = BlockSize / SubBlockSize;
      if (BlockSize != SubBlockSize * BlkPerSec) {
        Status = EFI_NOT_FOUND;
        goto done; 
      }
      AppleEntry = AllocatePool (SubBlockSize);
      PartitionEntries = 1;
      for (Partition = 1; Partition <= PartitionEntries; Partition++)
      {
          Status = DiskIo->ReadDisk (
                       DiskIo,
                       MediaId,
                       MultU64x32 (Partition, SubBlockSize),
                       SubBlockSize,
                       AppleEntry
                       );

          if (EFI_ERROR (Status)) {
              Status = EFI_NOT_FOUND;
              goto done; /* would break, but ... */
          }
          if (SwapBytes16(AppleEntry->signature) != 0x504D) {
            continue;
          }
          if (Partition == 1) {
            PartitionEntries  = SwapBytes32(AppleEntry->map_entries);
          }
      
          StartLba = SwapBytes32(AppleEntry->pblock_start);
          SizeLbs  = SwapBytes32(AppleEntry->pblocks);
      
          ZeroMem (&CdDev, sizeof (CdDev));
          CdDev.Header.Type     = MEDIA_DEVICE_PATH;
          CdDev.Header.SubType  = MEDIA_CDROM_DP;
          SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev));
          CdDev.BootEntry = 0;
          CdDev.PartitionStart = StartLba / BlkPerSec;  /* start, LBA */
          CdDev.PartitionSize  = SizeLbs / BlkPerSec;   /* size,  LBs */

          Status = PartitionInstallChildHandle (
              This,
              Handle,
              DiskIo,
              BlockIo,
              BlockIo2,
              DevicePath,
              (EFI_DEVICE_PATH_PROTOCOL *) &CdDev,
              CdDev.PartitionStart,
              CdDev.PartitionStart + CdDev.PartitionSize - 1,
              SubBlockSize,
              FALSE );
      }

  } while (0);

 done:
  
  if (AppleHeader != NULL) {
    FreePool (AppleHeader);
  }
  if (AppleEntry != NULL) {
    FreePool (AppleEntry);
  }

  return Status;
}
Ejemplo n.º 25
0
/**
  Create a new TCP4 or TCP6 driver service binding protocol

  @param[in]  Controller         Controller handle of device to bind driver to.
  @param[in]  Image              The TCP driver's image handle.
  @param[in]  IpVersion          IP_VERSION_4 or IP_VERSION_6.

  @retval EFI_OUT_OF_RESOURCES   Failed to allocate some resources.
  @retval EFI_SUCCESS            A new IP6 service binding private was created.

**/
EFI_STATUS
TcpCreateService (
  IN EFI_HANDLE  Controller,
  IN EFI_HANDLE  Image,
  IN UINT8       IpVersion
  )
{
  EFI_STATUS         Status;
  EFI_GUID           *IpServiceBindingGuid;
  EFI_GUID           *TcpServiceBindingGuid;
  TCP_SERVICE_DATA   *TcpServiceData;
  IP_IO_OPEN_DATA    OpenData;

  if (IpVersion == IP_VERSION_4) {
    IpServiceBindingGuid  = &gEfiIp4ServiceBindingProtocolGuid;
    TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
  } else {
    IpServiceBindingGuid  = &gEfiIp6ServiceBindingProtocolGuid;
    TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
  }

  Status = gBS->OpenProtocol (
                  Controller,
                  TcpServiceBindingGuid,
                  NULL,
                  Image,
                  Controller,
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                  );
  if (!EFI_ERROR (Status)) {
    return EFI_ALREADY_STARTED;
  }

  Status = gBS->OpenProtocol (
                  Controller,
                  IpServiceBindingGuid,
                  NULL,
                  Image,
                  Controller,
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                  );
  if (EFI_ERROR (Status)) {
    return EFI_UNSUPPORTED;
  }

  //
  // Create the TCP service data.
  //
  TcpServiceData = AllocateZeroPool (sizeof (TCP_SERVICE_DATA));
  if (TcpServiceData == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  TcpServiceData->Signature            = TCP_DRIVER_SIGNATURE;
  TcpServiceData->ControllerHandle     = Controller;
  TcpServiceData->DriverBindingHandle  = Image;
  TcpServiceData->IpVersion            = IpVersion;
  CopyMem (
    &TcpServiceData->ServiceBinding,
    &gTcpServiceBinding,
    sizeof (EFI_SERVICE_BINDING_PROTOCOL)
    );

  TcpServiceData->IpIo = IpIoCreate (Image, Controller, IpVersion);
  if (TcpServiceData->IpIo == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_ERROR;
  }


  InitializeListHead (&TcpServiceData->SocketList);
  ZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));

  if (IpVersion == IP_VERSION_4) {
    CopyMem (
      &OpenData.IpConfigData.Ip4CfgData,
      &mIp4IoDefaultIpConfigData,
      sizeof (EFI_IP4_CONFIG_DATA)
      );
    OpenData.IpConfigData.Ip4CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
  } else {
    CopyMem (
      &OpenData.IpConfigData.Ip6CfgData,
      &mIp6IoDefaultIpConfigData,
      sizeof (EFI_IP6_CONFIG_DATA)
      );
    OpenData.IpConfigData.Ip6CfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
  }

  OpenData.PktRcvdNotify  = TcpRxCallback;
  Status                  = IpIoOpen (TcpServiceData->IpIo, &OpenData);
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = TcpCreateTimer ();
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->InstallMultipleProtocolInterfaces (
                  &Controller,
                  TcpServiceBindingGuid,
                  &TcpServiceData->ServiceBinding,
                  NULL
                  );
  if (EFI_ERROR (Status)) {
    TcpDestroyTimer ();

    goto ON_ERROR;
  }

  return EFI_SUCCESS;

ON_ERROR:

  if (TcpServiceData->IpIo != NULL) {
    IpIoDestroy (TcpServiceData->IpIo);
    TcpServiceData->IpIo = NULL;
  }

  FreePool (TcpServiceData);

  return Status;
}
Ejemplo n.º 26
0
/**
  Create popup window. It will replace CreateDialog(). 

  This function draws OEM/Vendor specific pop up windows.

  @param[out]  Key    User Input Key
  @param       ...    String to be shown in Popup. The variable argument list is terminated by a NULL.
  
**/
VOID
EFIAPI
CreateDialog (
  OUT EFI_INPUT_KEY  *Key,        OPTIONAL
  ...
  )
{
  VA_LIST       Marker;
  EFI_INPUT_KEY KeyValue;
  EFI_STATUS    Status;
  UINTN         LargestString;
  UINTN         LineNum;
  UINTN   Index;
  UINTN   Count;
  CHAR16  Character;
  UINTN   Start;
  UINTN   End;
  UINTN   Top;
  UINTN   Bottom;
  CHAR16  *String;
  UINTN   DimensionsWidth;
  UINTN   DimensionsHeight;
  UINTN   CurrentAttribute;
  BOOLEAN CursorVisible;

  //
  // If screen dimension info is not ready, get it from console.
  //
  if (gScreenDimensions.RightColumn == 0 || gScreenDimensions.BottomRow == 0) {
    ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
    gST->ConOut->QueryMode (
                   gST->ConOut,
                   gST->ConOut->Mode->Mode,
                   &gScreenDimensions.RightColumn,
                   &gScreenDimensions.BottomRow
                   );
  }

  DimensionsWidth   = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn;
  DimensionsHeight  = gScreenDimensions.BottomRow - gScreenDimensions.TopRow;

  LargestString = 0;
  LineNum       = 0;
  VA_START (Marker, Key);
  while  ((String = VA_ARG (Marker, CHAR16 *)) != NULL) {
    LineNum ++;
    
    if ((LibGetStringWidth (String) / 2) > LargestString) {
      LargestString = (LibGetStringWidth (String) / 2);
    }
  } 
  VA_END (Marker);

  if ((LargestString + 2) > DimensionsWidth) {
    LargestString = DimensionsWidth - 2;
  }
  
  CurrentAttribute  = gST->ConOut->Mode->Attribute;
  CursorVisible     = gST->ConOut->Mode->CursorVisible;
  gST->ConOut->EnableCursor (gST->ConOut, FALSE);
  gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());

  //
  // Subtract the PopUp width from total Columns, allow for one space extra on
  // each end plus a border.
  //
  Start     = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1;
  End       = Start + LargestString + 1;

  Top       = ((DimensionsHeight - LineNum - 2) / 2) + gScreenDimensions.TopRow - 1;
  Bottom    = Top + LineNum + 2;

  Character = BOXDRAW_DOWN_RIGHT;
  PrintCharAt (Start, Top, Character);
  Character = BOXDRAW_HORIZONTAL;
  for (Index = Start; Index + 2 < End; Index++) {
    PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
  }

  Character = BOXDRAW_DOWN_LEFT;
  PrintCharAt ((UINTN)-1, (UINTN)-1, Character);
  Character = BOXDRAW_VERTICAL;

  Count = 0;
  VA_START (Marker, Key);
  for (Index = Top; Index + 2 < Bottom; Index++, Count++) {
    String = VA_ARG (Marker, CHAR16*);

    if (String[0] == CHAR_NULL) {
      //
      // Passing in a NULL results in a blank space
      //
      ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
    } else if (String[0] == L' ') {
      //
      // Passing in a space results in the assumption that this is where typing will occur
      //
      ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND);
      PrintStringAt (
        ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
        Index + 1,
        String + 1
        );
    } else {
      //
      // This will clear the background of the line - we never know who might have been
      // here before us.  This differs from the next clear in that it used the non-reverse
      // video for normal printing.
      //
      ClearLines (Start, End, Index + 1, Index + 1, GetPopupColor ());
      PrintStringAt (
        ((DimensionsWidth - LibGetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1,
        Index + 1,
        String
        );
    }

    gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());
    PrintCharAt (Start, Index + 1, Character);
    PrintCharAt (End - 1, Index + 1, Character);
  }
  VA_END (Marker);

  Character = BOXDRAW_UP_RIGHT;
  PrintCharAt (Start, Bottom - 1, Character);
  Character = BOXDRAW_HORIZONTAL;
  for (Index = Start; Index + 2 < End; Index++) {
    PrintCharAt ((UINTN)-1, (UINTN) -1, Character);
  }

  Character = BOXDRAW_UP_LEFT;
  PrintCharAt ((UINTN)-1, (UINTN) -1, Character);

  if (Key != NULL) {
    Status = WaitForKeyStroke (&KeyValue);
    ASSERT_EFI_ERROR (Status);
    CopyMem (Key, &KeyValue, sizeof (EFI_INPUT_KEY));
  }

  gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute);
  gST->ConOut->EnableCursor (gST->ConOut, CursorVisible);
}
Ejemplo n.º 27
0
/**
  Create PRP lists for data transfer which is larger than 2 memory pages.
  Note here we calcuate the number of required PRP lists and allocate them at one time.

  @param[in]     PciIo               A pointer to the EFI_PCI_IO_PROTOCOL instance.
  @param[in]     PhysicalAddr        The physical base address of data buffer.
  @param[in]     Pages               The number of pages to be transfered.
  @param[out]    PrpListHost         The host base address of PRP lists.
  @param[in,out] PrpListNo           The number of PRP List.
  @param[out]    Mapping             The mapping value returned from PciIo.Map().

  @retval The pointer to the first PRP List of the PRP lists.

**/
VOID*
NvmeCreatePrpList (
  IN     EFI_PCI_IO_PROTOCOL          *PciIo,
  IN     EFI_PHYSICAL_ADDRESS         PhysicalAddr,
  IN     UINTN                        Pages,
     OUT VOID                         **PrpListHost,
  IN OUT UINTN                        *PrpListNo,
     OUT VOID                         **Mapping
  )
{
  UINTN                       PrpEntryNo;
  UINT64                      PrpListBase;
  UINTN                       PrpListIndex;
  UINTN                       PrpEntryIndex;
  UINT64                      Remainder;
  EFI_PHYSICAL_ADDRESS        PrpListPhyAddr;
  UINTN                       Bytes;
  EFI_STATUS                  Status;

  //
  // The number of Prp Entry in a memory page.
  //
  PrpEntryNo = EFI_PAGE_SIZE / sizeof (UINT64);

  //
  // Calculate total PrpList number.
  //
  *PrpListNo = (UINTN)DivU64x64Remainder ((UINT64)Pages, (UINT64)PrpEntryNo - 1, &Remainder);
  if (*PrpListNo == 0) {
    *PrpListNo = 1;
  } else if ((Remainder != 0) && (Remainder != 1)) {
    *PrpListNo += 1;
  } else if (Remainder == 1) {
    Remainder = PrpEntryNo;
  } else if (Remainder == 0) {
    Remainder = PrpEntryNo - 1;
  }

  Status = PciIo->AllocateBuffer (
                    PciIo,
                    AllocateAnyPages,
                    EfiBootServicesData,
                    *PrpListNo,
                    PrpListHost,
                    0
                    );

  if (EFI_ERROR (Status)) {
    return NULL;
  }

  Bytes = EFI_PAGES_TO_SIZE (*PrpListNo);
  Status = PciIo->Map (
                    PciIo,
                    EfiPciIoOperationBusMasterCommonBuffer,
                    *PrpListHost,
                    &Bytes,
                    &PrpListPhyAddr,
                    Mapping
                    );

  if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (*PrpListNo))) {
    DEBUG ((EFI_D_ERROR, "NvmeCreatePrpList: create PrpList failure!\n"));
    goto EXIT;
  }
  //
  // Fill all PRP lists except of last one.
  //
  ZeroMem (*PrpListHost, Bytes);
  for (PrpListIndex = 0; PrpListIndex < *PrpListNo - 1; ++PrpListIndex) {
    PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;

    for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) {
      if (PrpEntryIndex != PrpEntryNo - 1) {
        //
        // Fill all PRP entries except of last one.
        //
        *((UINT64*)(UINTN)PrpListBase + PrpEntryIndex) = PhysicalAddr;
        PhysicalAddr += EFI_PAGE_SIZE;
      } else {
        //
        // Fill last PRP entries with next PRP List pointer.
        //
        *((UINT64*)(UINTN)PrpListBase + PrpEntryIndex) = PrpListPhyAddr + (PrpListIndex + 1) * EFI_PAGE_SIZE;
      }
    }
  }
  //
  // Fill last PRP list.
  //
  PrpListBase = *(UINT64*)PrpListHost + PrpListIndex * EFI_PAGE_SIZE;
  for (PrpEntryIndex = 0; PrpEntryIndex < Remainder; ++PrpEntryIndex) {
    *((UINT64*)(UINTN)PrpListBase + PrpEntryIndex) = PhysicalAddr;
    PhysicalAddr += EFI_PAGE_SIZE;
  }

  return (VOID*)(UINTN)PrpListPhyAddr;

EXIT:
  PciIo->FreeBuffer (PciIo, *PrpListNo, *PrpListHost);
  return NULL;
}
Ejemplo n.º 28
0
/**
  Function to handle the MTFTP OACK packet.

  It parses the packet's options, and update the internal states of the session.

  @param  Instance              The MTFTP session
  @param  Packet                The received OACK packet
  @param  Len                   The length of the packet
  @param  Completed             Whether the transmisson has completed. NOT used by
                                this function.

  @retval EFI_SUCCESS           The OACK process is OK
  @retval EFI_TFTP_ERROR        Some error occured, and the session reset.

**/
EFI_STATUS
Mtftp4WrqHandleOack (
  IN OUT MTFTP4_PROTOCOL       *Instance,
  IN     EFI_MTFTP4_PACKET     *Packet,
  IN     UINT32                Len,
     OUT BOOLEAN               *Completed
  )
{
  MTFTP4_OPTION             Reply;
  EFI_MTFTP4_PACKET         Bogus;
  EFI_STATUS                Status;
  INTN                      Expected;

  *Completed = FALSE;

  //
  // Ignore the OACK if already started the upload
  //
  Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);

  if (Expected != 0) {
    return EFI_SUCCESS;
  }

  //
  // Parse and validate the options from server
  //
  ZeroMem (&Reply, sizeof (MTFTP4_OPTION));
  Status = Mtftp4ParseOptionOack (Packet, Len, &Reply);

  if (EFI_ERROR (Status) || !Mtftp4WrqOackValid (&Reply, &Instance->RequestOption)) {
    //
    // Don't send a MTFTP error packet when out of resource, it can
    // only make it worse.
    //
    if (Status != EFI_OUT_OF_RESOURCES) {
      Mtftp4SendError (
        Instance,
        EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
        (UINT8 *) "Mal-formated OACK packet"
        );
    }

    return EFI_TFTP_ERROR;
  }

  if (Reply.BlkSize != 0) {
    Instance->BlkSize = Reply.BlkSize;
  }

  if (Reply.Timeout != 0) {
    Instance->Timeout = Reply.Timeout;
  }

  //
  // Build a bogus ACK0 packet then pass it to the Mtftp4WrqHandleAck,
  // which will start the transmission of the first data block.
  //
  Bogus.Ack.OpCode    = HTONS (EFI_MTFTP4_OPCODE_ACK);
  Bogus.Ack.Block[0]  = 0;

  Status = Mtftp4WrqHandleAck (
             Instance,
             &Bogus,
             sizeof (EFI_MTFTP4_ACK_HEADER),
             Completed
             );

  return Status;
}
Ejemplo n.º 29
0
/**
  Create PageTable for SMM use.

  @return The address of PML4 (to set CR3).

**/
UINT32
SmmInitPageTable (
  VOID
  )
{
  EFI_PHYSICAL_ADDRESS              Pages;
  UINT64                            *PTEntry;
  LIST_ENTRY                        *FreePage;
  UINTN                             Index;
  UINTN                             PageFaultHandlerHookAddress;
  IA32_IDT_GATE_DESCRIPTOR          *IdtEntry;

  //
  // Initialize spin lock
  //
  InitializeSpinLock (&mPFLock);

  m1GPageTableSupport = Is1GPageSupport ();
  //
  // Generate PAE page table for the first 4GB memory space
  //
  Pages = Gen4GPageTable (PAGE_TABLE_PAGES + 1);

  //
  // Set IA32_PG_PMNT bit to mask this entry
  //
  PTEntry = (UINT64*)(UINTN)Pages;
  for (Index = 0; Index < 4; Index++) {
    PTEntry[Index] |= IA32_PG_PMNT;
  }

  //
  // Fill Page-Table-Level4 (PML4) entry
  //
  PTEntry = (UINT64*)(UINTN)(Pages - EFI_PAGES_TO_SIZE (PAGE_TABLE_PAGES + 1));
  *PTEntry = Pages + PAGE_ATTRIBUTE_BITS;
  ZeroMem (PTEntry + 1, EFI_PAGE_SIZE - sizeof (*PTEntry));
  //
  // Set sub-entries number
  //
  SetSubEntriesNum (PTEntry, 3);

  //
  // Add remaining pages to page pool
  //
  FreePage = (LIST_ENTRY*)(PTEntry + EFI_PAGE_SIZE / sizeof (*PTEntry));
  while ((UINTN)FreePage < Pages) {
    InsertTailList (&mPagePool, FreePage);
    FreePage += EFI_PAGE_SIZE / sizeof (*FreePage);
  }

  if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
    //
    // Set own Page Fault entry instead of the default one, because SMM Profile
    // feature depends on IRET instruction to do Single Step
    //
    PageFaultHandlerHookAddress = (UINTN)PageFaultIdtHandlerSmmProfile;
    IdtEntry  = (IA32_IDT_GATE_DESCRIPTOR *) gcSmiIdtr.Base;
    IdtEntry += EXCEPT_IA32_PAGE_FAULT;
    IdtEntry->Bits.OffsetLow      = (UINT16)PageFaultHandlerHookAddress;
    IdtEntry->Bits.Reserved_0     = 0;
    IdtEntry->Bits.GateType       = IA32_IDT_GATE_TYPE_INTERRUPT_32;
    IdtEntry->Bits.OffsetHigh     = (UINT16)(PageFaultHandlerHookAddress >> 16);
    IdtEntry->Bits.OffsetUpper    = (UINT32)(PageFaultHandlerHookAddress >> 32);
    IdtEntry->Bits.Reserved_1     = 0;
  } else {
Ejemplo n.º 30
0
/**
  Retrieve the host address using the EFI_DNS6_PROTOCOL.

  @param[in]  Private             The pointer to the driver's private data.
  @param[in]  HostName            Pointer to buffer containing hostname.
  @param[out] IpAddress           On output, pointer to buffer containing IPv6 address.

  @retval EFI_SUCCESS             Operation succeeded.
  @retval EFI_DEVICE_ERROR        An unexpected network error occurred.
  @retval Others                  Other errors as indicated.
**/
EFI_STATUS
HttpBootDns (
    IN     HTTP_BOOT_PRIVATE_DATA   *Private,
    IN     CHAR16                   *HostName,
    OUT EFI_IPv6_ADDRESS         *IpAddress
)
{
    EFI_STATUS                      Status;
    EFI_DNS6_PROTOCOL               *Dns6;
    EFI_DNS6_CONFIG_DATA            Dns6ConfigData;
    EFI_DNS6_COMPLETION_TOKEN       Token;
    EFI_HANDLE                      Dns6Handle;
    EFI_IP6_CONFIG_PROTOCOL         *Ip6Config;
    EFI_IPv6_ADDRESS                *DnsServerList;
    UINTN                           DnsServerListCount;
    UINTN                           DataSize;
    BOOLEAN                         IsDone;

    DnsServerList       = NULL;
    DnsServerListCount  = 0;
    Dns6                = NULL;
    Dns6Handle          = NULL;
    ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));

    //
    // Get DNS server list from EFI IPv6 Configuration protocol.
    //
    Status = gBS->HandleProtocol (Private->Controller, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config);
    if (!EFI_ERROR (Status)) {
        //
        // Get the required size.
        //
        DataSize = 0;
        Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);
        if (Status == EFI_BUFFER_TOO_SMALL) {
            DnsServerList = AllocatePool (DataSize);
            if (DnsServerList == NULL) {
                return EFI_OUT_OF_RESOURCES;
            }

            Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);
            if (EFI_ERROR (Status)) {
                FreePool (DnsServerList);
                DnsServerList = NULL;
            } else {
                DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
            }
        }
    }
    //
    // Create a DNSv6 child instance and get the protocol.
    //
    Status = NetLibCreateServiceChild (
                 Private->Controller,
                 Private->Image,
                 &gEfiDns6ServiceBindingProtocolGuid,
                 &Dns6Handle
             );
    if (EFI_ERROR (Status)) {
        goto Exit;
    }

    Status = gBS->OpenProtocol (
                 Dns6Handle,
                 &gEfiDns6ProtocolGuid,
                 (VOID **) &Dns6,
                 Private->Image,
                 Private->Controller,
                 EFI_OPEN_PROTOCOL_BY_DRIVER
             );
    if (EFI_ERROR (Status)) {
        goto Exit;
    }

    //
    // Configure DNS6 instance for the DNS server address and protocol.
    //
    ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));
    Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;
    Dns6ConfigData.DnsServerList  = DnsServerList;
    Dns6ConfigData.EnableDnsCache = TRUE;
    Dns6ConfigData.Protocol       = EFI_IP_PROTO_UDP;
    IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp,&Private->StationIp.v6);
    Status = Dns6->Configure (
                 Dns6,
                 &Dns6ConfigData
             );
    if (EFI_ERROR (Status)) {
        goto Exit;
    }

    Token.Status = EFI_NOT_READY;
    IsDone       = FALSE;
    //
    // Create event to set the  IsDone flag when name resolution is finished.
    //
    Status = gBS->CreateEvent (
                 EVT_NOTIFY_SIGNAL,
                 TPL_NOTIFY,
                 HttpBootCommonNotify,
                 &IsDone,
                 &Token.Event
             );
    if (EFI_ERROR (Status)) {
        goto Exit;
    }

    //
    // Start asynchronous name resolution.
    //
    Status = Dns6->HostNameToIp (Dns6, HostName, &Token);
    if (EFI_ERROR (Status)) {
        goto Exit;
    }

    while (!IsDone) {
        Dns6->Poll (Dns6);
    }

    //
    // Name resolution is done, check result.
    //
    Status = Token.Status;
    if (!EFI_ERROR (Status)) {
        if (Token.RspData.H2AData == NULL) {
            Status = EFI_DEVICE_ERROR;
            goto Exit;
        }
        if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {
            Status = EFI_DEVICE_ERROR;
            goto Exit;
        }
        //
        // We just return the first IPv6 address from DNS protocol.
        //
        IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
        Status = EFI_SUCCESS;
    }
Exit:

    if (Token.Event != NULL) {
        gBS->CloseEvent (Token.Event);
    }
    if (Token.RspData.H2AData != NULL) {
        if (Token.RspData.H2AData->IpList != NULL) {
            FreePool (Token.RspData.H2AData->IpList);
        }
        FreePool (Token.RspData.H2AData);
    }

    if (Dns6 != NULL) {
        Dns6->Configure (Dns6, NULL);

        gBS->CloseProtocol (
            Dns6Handle,
            &gEfiDns6ProtocolGuid,
            Private->Image,
            Private->Controller
        );
    }

    if (Dns6Handle != NULL) {
        NetLibDestroyServiceChild (
            Private->Controller,
            Private->Image,
            &gEfiDns6ServiceBindingProtocolGuid,
            Dns6Handle
        );
    }

    if (DnsServerList != NULL) {
        FreePool (DnsServerList);
    }

    return Status;
}