Beispiel #1
0
/**
  Stalls the CPU for at least the given number of ticks.

  Stalls the CPU for at least the given number of ticks. It's invoked by
  MicroSecondDelay() and NanoSecondDelay().

  @param  Delay     A period of time to delay in ticks.

**/
VOID
InternalAcpiDelay (
  IN UINT32  Delay
  )
{
  UINT16   Port;
  UINT32   Ticks;
  UINT32   Times;

  Port   = InternalAcpiGetAcpiTimerIoPort ();
  Times  = Delay >> 22;
  Delay &= BIT22 - 1;
  do {
    //
    // The target timer count is calculated here
    //
    Ticks = IoRead32 (Port) + Delay;
    Delay = BIT22;
    //
    // Wait until time out
    // Delay >= 2^23 could not be handled by this function
    // Timer wrap-arounds are handled correctly by this function
    //
    while (((Ticks - IoRead32 (Port)) & BIT23) == 0) {
      CpuPause ();
    }
  } while (Times-- > 0);
}
Beispiel #2
0
EFI_STATUS
EFIAPI
Stall (
  IN CONST EFI_PEI_SERVICES   **PeiServices,
  IN CONST EFI_PEI_STALL_PPI      *This,
  IN UINTN              Microseconds
  )
{
  UINTN   Ticks;
  UINTN   Counts;
  UINT32  CurrentTick;
  UINT32  OriginalTick;
  UINT32  RemainingTick;

  if (Microseconds == 0) {
    return EFI_SUCCESS;
  }

  OriginalTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR);
  OriginalTick &= (V_PCH_ACPI_PM1_TMR_MAX_VAL - 1);
  CurrentTick = OriginalTick;

  //
  // The timer frequency is 3.579545MHz, so 1 ms corresponds to 3.58 clocks
  //
  Ticks = Microseconds * 358 / 100 + OriginalTick + 1;

  //
  // The loops needed for timer overflow
  //
  Counts = (UINTN)RShiftU64((UINT64)Ticks, 24);

  //
  // Remaining clocks within one loop
  //
  RemainingTick = Ticks & 0xFFFFFF;

  //
  // Do not intend to use TMROF_STS bit of register PM1_STS, because this add extra
  // one I/O operation, and may generate SMI
  //
  while (Counts != 0) {
    CurrentTick = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR) & B_PCH_ACPI_PM1_TMR_VAL;
    if (CurrentTick <= OriginalTick) {
      Counts--;
    }
    OriginalTick = CurrentTick;
  }

  while ((RemainingTick > CurrentTick) && (OriginalTick <= CurrentTick)) {
    OriginalTick  = CurrentTick;
    CurrentTick   = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_TMR) & B_PCH_ACPI_PM1_TMR_VAL;
  }

  return EFI_SUCCESS;
}
Beispiel #3
0
/**
  Reads I/O registers.

  @param[in]  PeiServices  An indirect pointer to the PEI Services Table
                           published by the PEI Foundation.
  @param[in]  This         Pointer to local data for the interface.
  @param[in]  Width        The width of the access. Enumerated in bytes.
  @param[in]  Address      The physical address of the access.
  @param[in]  Count        The number of accesses to perform.
  @param[out] Buffer       A pointer to the buffer of data.

  @retval EFI_SUCCESS            The function completed successfully.
  @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
  @retval EFI_UNSUPPORTED        The address range specified by Address, Width, 
                                 and Count is not valid for this EFI system.

**/
EFI_STATUS
EFIAPI
CpuIoServiceRead (
  IN  CONST EFI_PEI_SERVICES    **PeiServices,
  IN  CONST EFI_PEI_CPU_IO_PPI  *This,
  IN  EFI_PEI_CPU_IO_PPI_WIDTH  Width,
  IN  UINT64                    Address,
  IN  UINTN                     Count,
  OUT VOID                      *Buffer
  )
{
  EFI_STATUS                Status;
  UINT8                     InStride;
  UINT8                     OutStride;
  EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
  BOOLEAN                   Aligned;
  UINT8                     *Uint8Buffer;

  Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Select loop based on the width of the transfer
  //
  InStride = mInStride[Width];
  OutStride = mOutStride[Width];
  OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
  Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
    if (OperationWidth == EfiPeiCpuIoWidthUint8) {
      *Uint8Buffer = IoRead8 ((UINTN)Address);
    } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
      if (Aligned) {
        *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
      } else {
        WriteUnaligned16 ((UINT16 *)Uint8Buffer, IoRead16 ((UINTN)Address));
      }
    } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
      if (Aligned) {
        *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
      } else {
        WriteUnaligned32 ((UINT32 *)Uint8Buffer, IoRead32 ((UINTN)Address));
      }
    }
  }

  return EFI_SUCCESS;
}
/**
  Internal function to read the current tick counter of ACPI.

  Dynamically compute the address of the ACPI tick counter based on the
  properties of the underlying platform, to avoid relying on global variables.

  @return The tick counter read.

**/
UINT32
InternalAcpiGetTimerTick (
  VOID
  )
{
  UINT16 HostBridgeDevId;
  UINTN Pmba;

  //
  // Query Host Bridge DID to determine platform type
  //
  HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
  switch (HostBridgeDevId) {
    case INTEL_82441_DEVICE_ID:
      Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
      break;
    case INTEL_Q35_MCH_DEVICE_ID:
      Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
      break;
    default:
      DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
        __FUNCTION__, HostBridgeDevId));
      ASSERT (FALSE);
      return 0;
  }

  //
  //   Read PMBA to read and return the current ACPI timer value.
  //
  return IoRead32 ((PciRead32 (Pmba) & ~PMBA_RTE) + ACPI_TIMER_OFFSET);
}
EFI_STATUS
EFIAPI
GetWakeupEventAndSaveToHob (
  IN CONST EFI_PEI_SERVICES   **PeiServices
  )
{
  UINT16  Pm1Sts;
  UINTN   Gpe0Sts;
  UINTN   WakeEventData;

  //
  // Read the ACPI registers
  //
  Pm1Sts  = IoRead16 (ACPI_BASE_ADDRESS + R_PCH_ACPI_PM1_STS);
  Gpe0Sts = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_ACPI_GPE0a_STS);

  //
  // Figure out the wake-up event
  //
  if ((Pm1Sts & B_PCH_ACPI_PM1_STS_PWRBTN) != 0) {
    WakeEventData = SMBIOS_WAKEUP_TYPE_POWER_SWITCH;
  } else if (((Pm1Sts & B_PCH_ACPI_PM1_STS_WAK) != 0)) {
    WakeEventData = SMBIOS_WAKEUP_TYPE_PCI_PME;
  } else if (Gpe0Sts != 0) {
    WakeEventData = SMBIOS_WAKEUP_TYPE_OTHERS;
  } else {
    WakeEventData = SMBIOS_WAKEUP_TYPE_UNKNOWN;
  }

  DEBUG ((EFI_D_ERROR, "ACPI Wake Status Register: %04x\n", Pm1Sts));
  DEBUG ((EFI_D_ERROR, "ACPI Wake Event Data: %02x\n", WakeEventData));

  return EFI_SUCCESS;
}
Beispiel #6
0
/**
  Read from IO space

  Argv[0] - "ioread"[.#] # is optional width 1, 2, or 4. Default 1
  Argv[1] - Hex IO address

  ior.4 0x3f8  ;Do a 32-bit IO Read from 0x3f8
  ior   0x3f8  ;Do a  8-bit IO Read from 0x3f8

  @param  Argc   Number of command arguments in Argv
  @param  Argv   Array of strings that represent the parsed command line.
                 Argv[0] is the command name

  @return EFI_SUCCESS

**/
EFI_STATUS
EblIoReadCmd (
  IN UINTN  Argc,
  IN CHAR8  **Argv
  )
{
  UINTN   Width;
  UINTN   Port;
  UINTN   Data;

  if (Argc < 2) {
    return EFI_INVALID_PARAMETER;
  }

  Port = AsciiStrHexToUintn (Argv[1]);
  Width = WidthFromCommandName (Argv[0], 1);

  if (Width == 1) {
    Data = IoRead8 (Port);
  } else if (Width == 2) {
    Data = IoRead16 (Port);
  } else if (Width == 4) {
    Data = IoRead32 (Port);
  } else {
    return EFI_INVALID_PARAMETER;
  }

  AsciiPrint ("0x%04x = 0x%x", Port, Data);

  return EFI_SUCCESS;
}
Beispiel #7
0
/**
  Reads I/O registers.

  The I/O operations are carried out exactly as requested.  The caller is 
  responsible for any alignment and I/O width issues that the bus, device, 
  platform, or type of I/O might require.

  @param[in]  This     The EFI_SMM_CPU_IO2_PROTOCOL instance.
  @param[in]  Width    Signifies the width of the I/O operations.
  @param[in]  Address  The base address of the I/O operations.  The caller is 
                       responsible for aligning the Address if required. 
  @param[in]  Count    The number of I/O operations to perform.
  @param[out] Buffer   For read operations, the destination buffer to store 
                       the results.  For write operations, the source buffer 
                       from which to write data.

  @retval EFI_SUCCESS            The data was read from or written to the device.
  @retval EFI_UNSUPPORTED        The Address is not valid for this system.
  @retval EFI_INVALID_PARAMETER  Width or Count, or both, were invalid.
  @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a 
                                 lack of resources

**/
EFI_STATUS
EFIAPI
CpuIoServiceRead (
  IN  CONST EFI_SMM_CPU_IO2_PROTOCOL  *This,
  IN  EFI_SMM_IO_WIDTH                Width,
  IN  UINT64                          Address,
  IN  UINTN                           Count,
  OUT VOID                            *Buffer
  )
{
  EFI_STATUS  Status;
  UINT8       Stride;
  UINT8       *Uint8Buffer;

  Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Select loop based on the width of the transfer
  //
  Stride = mStride[Width];
  for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
    if (Width == SMM_IO_UINT8) {
      *Uint8Buffer = IoRead8 ((UINTN)Address);
    } else if (Width == SMM_IO_UINT16) {
      *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
    } else if (Width == SMM_IO_UINT32) {
      *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
    }
  }

  return EFI_SUCCESS;
}
Beispiel #8
0
/**
  Internal function to read the current tick counter of ACPI.

  @return The tick counter read.

**/
STATIC
UINT32
InternalAcpiGetTimerTick (
  VOID
  )
{
  return IoRead32 ((UINTN)gAcpiDesc->PM_TMR_BLK.Address);
}
/**
  Internal function to read the current tick counter of ACPI.

  Internal function to read the current tick counter of ACPI.

  @return The tick counter read.

**/
STATIC
UINT32
InternalAcpiGetTimerTick (
  VOID
  )
{
  return IoRead32 (mPmba + ACPI_TIMER_OFFSET);
}
/**
  Internal function to read the current tick counter of ACPI.

  Internal function to read the current tick counter of ACPI.

  @return The tick counter read.

**/
STATIC
   UINT32
   InternalAcpiGetTimerTick (
   VOID
   )
{
   return IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_PM1BLK_PM1T);
}
Beispiel #11
0
/**
  Internal function to read the current tick counter of ACPI.

  Internal function to read the current tick counter of ACPI.

  @return The tick counter read.

**/
UINT32
InternalAcpiGetTimerTick (
  VOID
  )
{
  //
  //   Read PMBA to read and return the current ACPI timer value.
  //
  return IoRead32 ((PciRead32 (PMBA) & ~PMBA_RTE) + ACPI_TIMER_OFFSET);
}
Beispiel #12
0
/**
  Internal function to read the current tick counter of ACPI.

  Read the current ACPI tick counter using the counter address cached
  by this instance's constructor.

  @return The tick counter read.

**/
UINT32
InternalAcpiGetTimerTick (
  VOID
  )
{
  //
  //   Return the current ACPI timer value.
  //
  return IoRead32 (mAcpiTimerIoAddr);
}
Beispiel #13
0
/**
  32-bit I/O read operations.

  @param[in] PeiServices  An indirect pointer to the PEI Services Table published
                          by the PEI Foundation.
  @param[in] This         Pointer to local data for the interface.
  @param[in] Address      The physical address of the access.

  @return  A 32-bit value returned from the I/O space.

**/
UINT32
EFIAPI
CpuIoRead32 (
  IN CONST EFI_PEI_SERVICES     **PeiServices,
  IN CONST EFI_PEI_CPU_IO_PPI   *This,
  IN UINT64                     Address
  )
{
  return IoRead32 ((UINTN)Address);
}
Beispiel #14
0
VOID
EFIAPI
S4S5CallBack (
  IN  EFI_HANDLE                    DispatchHandle,
  IN  EFI_SMM_SX_DISPATCH_CONTEXT   *DispatchContext
  )
{

  UINT32        Data32;

  //
  // Enable/Disable USB Charging
  //
  if (mSystemConfiguration.UsbCharging == 0x01) {
    Data32 = IoRead32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL);
    Data32 |= BIT8;
    IoWrite32(GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_LVL, Data32);
  }

}
Beispiel #15
0
EFI_STATUS
SaveState (
  VOID
  )
/*++

Routine Description:

  Save Index registers to avoid corrupting the foreground environment

Arguments:
  None

Returns:
  Status - EFI_SUCCESS

--*/
{
  mPciAddress = IoRead32 (EFI_PCI_ADDRESS_PORT);
  return EFI_SUCCESS;
}
Beispiel #16
0
/**
  Reads I/O registers.

  The I/O operations are carried out exactly as requested. The caller is responsible 
  for satisfying any alignment and I/O width restrictions that a PI System on a 
  platform might require. For example on some platforms, width requests of 
  EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will 
  be handled by the driver.
  
  If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, 
  or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for 
  each of the Count operations that is performed.
  
  If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, 
  EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is 
  incremented for each of the Count operations that is performed. The read or 
  write operation is performed Count times on the same Address.
  
  If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, 
  EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is 
  incremented for each of the Count operations that is performed. The read or 
  write operation is performed Count times from the first element of Buffer.
  
  @param[in]  This     A pointer to the EFI_CPU_IO2_PROTOCOL instance.
  @param[in]  Width    Signifies the width of the I/O or Memory operation.
  @param[in]  Address  The base address of the I/O operation. 
  @param[in]  Count    The number of I/O operations to perform. The number of 
                       bytes moved is Width size * Count, starting at Address.
  @param[out] Buffer   For read operations, the destination buffer to store the results.
                       For write operations, the source buffer from which to write data.

  @retval EFI_SUCCESS            The data was read from or written to the PI system.
  @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
  @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
  @retval EFI_UNSUPPORTED        The address range specified by Address, Width, 
                                 and Count is not valid for this PI system.

**/
EFI_STATUS
EFIAPI
CpuIoServiceRead (
  IN  EFI_CPU_IO2_PROTOCOL       *This,
  IN  EFI_CPU_IO_PROTOCOL_WIDTH  Width,
  IN  UINT64                     Address,
  IN  UINTN                      Count,
  OUT VOID                       *Buffer
  )
{
  EFI_STATUS                 Status;
  UINT8                      InStride;
  UINT8                      OutStride;
  EFI_CPU_IO_PROTOCOL_WIDTH  OperationWidth;
  UINT8                      *Uint8Buffer;

  Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Select loop based on the width of the transfer
  //
  InStride = mInStride[Width];
  OutStride = mOutStride[Width];
  OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03);
  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
    if (OperationWidth == EfiCpuIoWidthUint8) {
      *Uint8Buffer = IoRead8 ((UINTN)Address);
    } else if (OperationWidth == EfiCpuIoWidthUint16) {
      *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
    } else if (OperationWidth == EfiCpuIoWidthUint32) {
      *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
    }
  }

  return EFI_SUCCESS;
}
//
// Routines local to this source module.
//
STATIC
VOID
LegacyGpioSetLevel (
  IN CONST UINT32                         LevelRegOffset,
  IN CONST UINT32                         GpioNum,
  IN CONST BOOLEAN                        HighLevel
  )
{
  UINT32                            RegValue;
  UINT32                            GpioBaseAddress;
  UINT32                            GpioNumMask;

  GpioBaseAddress =  LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;
  ASSERT (GpioBaseAddress > 0);

  RegValue = IoRead32 (GpioBaseAddress + LevelRegOffset);
  GpioNumMask = (1 << GpioNum);
  if (HighLevel) {
    RegValue |= (GpioNumMask);
  } else {
    RegValue &= ~(GpioNumMask);
  }
  IoWrite32 (GpioBaseAddress + R_QNC_GPIO_RGLVL_RESUME_WELL, RegValue);
}
Beispiel #18
0
static bool ReadPNG(PngT *png, RwOpsT *stream) {
  uint32_t id[2];
  bool error = false;
  PngChunkT chunk;

  memset(png, 0, sizeof(PngT));

  if (!IoRead32(stream, &id[0]) || !IoRead32(stream, &id[1])) {
    LOG("Could not read PNG header!");
    return false;
  }

  if (id[0] != PNG_ID0 || id[1] != PNG_ID1) {
    LOG("Not a PNG file!");
    return false;
  }

  memset(&chunk, 0, sizeof(chunk));

  while (chunk.id != PNG_IEND && !error) {
    uint32_t their_crc;
    uint8_t *ptr;

    if (IoRead(stream, &chunk, 8) != 8)
      return false;

    LOG("%.4s: length: %d", (char *)&chunk.id, chunk.length);

    ptr = MemNew(chunk.length);

    if (IoRead(stream, ptr, chunk.length) != chunk.length)
      return false;

    if (chunk.id == PNG_IHDR) {
      MemCopy(&png->ihdr, ptr, sizeof(IhdrT));
    } else if (chunk.id == PNG_IDAT) {
      if (!png->idat.data) {
        png->idat.length = chunk.length;
        png->idat.data = ptr;
      } else {
        IdatT *idat = &png->idat;

        while (idat->next)
          idat = idat->next;

        idat->next = NewRecord(IdatT);
        idat->next->length = chunk.length;
        idat->next->data = ptr;
      }
      ptr = NULL;
    } else if (chunk.id == PNG_PLTE) {
      png->plte.no_colors = chunk.length / 3;
      png->plte.colors = (RGB *)ptr;
      ptr = NULL;
    } else if (chunk.id == PNG_tRNS) {
      if (png->ihdr.colour_type == PNG_INDEXED) {
        png->trns = MemNew(sizeof(uint32_t) + chunk.length);
        png->trns->type3.length = chunk.length;
        MemCopy(png->trns->type3.alpha, ptr, chunk.length);
      } else {
        png->trns = (TrnsT *)ptr;
        ptr = NULL;
      }
    }

    if (ptr)
      MemUnref(ptr);

    if (!IoRead32(stream, &their_crc))
      return false;
  }

  return !error;
}
Beispiel #19
0
/**

  This function is IO instruction handler.

  @param Index CPU index

**/
VOID
IoHandler (
  IN UINT32 Index
  )
{
  VM_EXIT_QUALIFICATION   Qualification;
  UINT16                  Port;
  UINTN                   *DataPtr;
  IO_WRITE_HANDLER_ITEM   *IoWriteHandler;
  IO_READ_HANDLER_ITEM    *IoReadHandler;
  UINT32                  Action;
  UINT32                  Value;
  UINTN                   LinearAddr;

  Qualification.UintN = VmReadN (VMCS_N_RO_EXIT_QUALIFICATION_INDEX);

  Port = (UINT16)Qualification.IoInstruction.PortNum;
  DataPtr = (UINTN *)&mGuestContextCommon.GuestContextPerCpu[Index].Register.Rax;

  if (Qualification.IoInstruction.Rep) {
    UINT64 RcxMask;

    RcxMask = 0xFFFFFFFFFFFFFFFFull;
    if ((mGuestContextCommon.GuestContextPerCpu[Index].EFER & IA32_EFER_MSR_MLA) == 0) {
      RcxMask = 0xFFFFFFFFull;
    }
    if ((mGuestContextCommon.GuestContextPerCpu[Index].Register.Rcx & RcxMask) == 0) {
      // Skip
      VmWriteN (VMCS_N_GUEST_RIP_INDEX, VmReadN(VMCS_N_GUEST_RIP_INDEX) + VmRead32(VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
      return ;
    }
  }

  if (Port == 0xB2) {
    DEBUG ((EFI_D_INFO, "(FRM) !!! SmiCmd(0xb2) - 0x%02x !!!\n", (UINT8)*DataPtr));
  }

  if ((mHostContextCommon.ResetIoPortBaseAddress != 0) && (Port == mHostContextCommon.ResetIoPortBaseAddress) && (Qualification.IoInstruction.Direction == 0)) {
    IoResetHandler (Index, Port, (UINT8)*DataPtr);
  } else if ((Port == mHostContextCommon.AcpiPmControlIoPortBaseAddress) && (Qualification.IoInstruction.Direction == 0)) {
    IoAcpiHandler (Index, Port, (UINT32)*DataPtr);
  }

  if (Qualification.IoInstruction.String) {
    LinearAddr = VmReadN (VMCS_N_RO_GUEST_LINEAR_ADDR_INDEX);
    if (VmReadN (VMCS_N_GUEST_CR0_INDEX) & CR0_PG) {
      DataPtr = (UINTN *)(UINTN)GuestVirtualToGuestPhysical (Index, LinearAddr);
    } else {
      DataPtr = (UINTN *)LinearAddr;
    }

    if (VmReadN (VMCS_N_GUEST_RFLAGS_INDEX) & RFLAGS_DF) {
      if (Qualification.IoInstruction.Direction) {
        mGuestContextCommon.GuestContextPerCpu[Index].Register.Rdi -= Qualification.IoInstruction.Size + 1;
      } else {
        mGuestContextCommon.GuestContextPerCpu[Index].Register.Rsi -= Qualification.IoInstruction.Size + 1;
      }
    } else {
      if (Qualification.IoInstruction.Direction) {
        mGuestContextCommon.GuestContextPerCpu[Index].Register.Rdi += Qualification.IoInstruction.Size + 1;
      } else {
        mGuestContextCommon.GuestContextPerCpu[Index].Register.Rsi += Qualification.IoInstruction.Size + 1;
      }
    }
  }

  if (Qualification.IoInstruction.Direction) { // IN
    IoReadHandler = FindIoReadHandler (Port, Qualification.IoInstruction.Size + 1);
    if (IoReadHandler != NULL) {
      Action = IO_ACTION_NO_ACTION;
      Value = 0;
      IoReadHandler->Handler (IoReadHandler->Context, Port, &Value, &Action);
      if (Action == IO_ACTION_NO_ACTION) {
        switch (Qualification.IoInstruction.Size) {
        case 0:
          *(UINT8 *)DataPtr = (UINT8)Value;
          goto Ret;
          break;
        case 1:
          *(UINT16 *)DataPtr = (UINT16)Value;
          goto Ret;
          break;
        case 3:
          *(UINT32 *)DataPtr = Value;
          goto Ret;
          break;
        default:
          break;
        }
        goto Ret;
      } else {
        // Passthrough
      }
    }
    switch (Qualification.IoInstruction.Size) {
    case 0:
      *(UINT8 *)DataPtr = IoRead8 (Port);
      goto Ret;
      break;
    case 1:
      *(UINT16 *)DataPtr = IoRead16 (Port);
      goto Ret;
      break;
    case 3:
      *(UINT32 *)DataPtr = IoRead32 (Port);
      goto Ret;
      break;
    default:
      break;
    }
  } else { // OUT
    IoWriteHandler = FindIoWriteHandler (Port, Qualification.IoInstruction.Size + 1);
    if (IoWriteHandler != NULL) {
      Action = IO_ACTION_NO_ACTION;
      Value = (UINT32)*DataPtr;
      IoWriteHandler->Handler (IoWriteHandler->Context, Port, Value, &Action);
      if (Action == IO_ACTION_NO_ACTION) {
        goto Ret;
      } else {
        // Passthrough
      }
    }
    switch (Qualification.IoInstruction.Size) {
    case 0:
      IoWrite8 (Port, (UINT8)*DataPtr);
      goto Ret;
      break;
    case 1:
      IoWrite16 (Port, (UINT16)*DataPtr);
      goto Ret;
      break;
    case 3:
      IoWrite32 (Port, (UINT32)*DataPtr);
      goto Ret;
      break;
    default:
      break;
    }
  }

  DEBUG ((EFI_D_ERROR, "(FRM) !!!IoHandler!!!\n"));
  DumpVmcsAllField ();

  CpuDeadLoop ();

Ret:
  if (Qualification.IoInstruction.Rep) {
    // replay
    mGuestContextCommon.GuestContextPerCpu[Index].Register.Rcx --;
    return ;
  }

  VmWriteN (VMCS_N_GUEST_RIP_INDEX, VmReadN(VMCS_N_GUEST_RIP_INDEX) + VmRead32(VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
  return ;
}
Beispiel #20
0
/**
  Calling this function causes the system to enter a power state for capsule
  update.

  Reset update should not return, if it returns, it means the system does
  not support capsule update.

**/
VOID
EFIAPI
EnterS3WithImmediateWake (
VOID
)
{
  UINT8     Data8;
  UINT16    Data16;
  UINT32    Data32;
  UINTN     Eflags;
  UINTN     RegCr0;
  EFI_TIME  EfiTime;
  UINT32    SmiEnSave;

  Eflags  = AsmReadEflags ();
  if ( (Eflags & 0x200) ) {
     DisableInterrupts ();
  }

  //
  //  Write all cache data to memory because processor will lost power
  //
  AsmWbinvd();
  RegCr0 = AsmReadCr0();
  AsmWriteCr0 (RegCr0 | 0x060000000);

  SmiEnSave = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, (SmiEnSave & ~SMI_EN));

  //
  // Pogram RTC alarm for immediate WAKE
  //

  //
  // Disable SMI sources
  //
  IoWrite16 (PcdGet16 (PcdGpe0blkIoBaseAddress) + R_QNC_GPE0BLK_SMIE, 0);

  //
  // Disable RTC alarm interrupt
  //
  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B);
  Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
  IoWrite8 (PCAT_RTC_DATA_REGISTER, (Data8 & ~BIT5));

  //
  // Clear RTC alarm if already set
  //
  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_C);
  Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);              // Read clears alarm status

  //
  // Disable all WAKE events
  //
  IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, B_QNC_PM1BLK_PM1E_PWAKED);

  //
  // Clear all WAKE status bits
  //
  IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S, B_QNC_PM1BLK_PM1S_ALL);

  //
  // Avoid RTC rollover
  //
  do {
    WaitForRTCUpdate();
    IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS);
    EfiTime.Second = IoRead8 (PCAT_RTC_DATA_REGISTER);
  } while (EfiTime.Second > PLATFORM_RTC_ROLLOVER_LIMIT);

  //
  // Read RTC time
  //
  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOURS);
  EfiTime.Hour = IoRead8 (PCAT_RTC_DATA_REGISTER);
  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTES);
  EfiTime.Minute = IoRead8 (PCAT_RTC_DATA_REGISTER);
  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS);
  EfiTime.Second = IoRead8 (PCAT_RTC_DATA_REGISTER);

  //
  // Set RTC alarm
  //

  //
  // Add PLATFORM_WAKE_SECONDS_BUFFER to current EfiTime.Second
  // The maths is to allow for the fact we are adding to a BCD number and require the answer to be BCD (EfiTime.Second)
  //
  if ((BCD_BASE - (EfiTime.Second & 0x0F)) <= PLATFORM_WAKE_SECONDS_BUFFER) {
    Data8 = (((EfiTime.Second & 0xF0) + 0x10) + (PLATFORM_WAKE_SECONDS_BUFFER - (BCD_BASE - (EfiTime.Second & 0x0F))));
  } else {
    Data8 = EfiTime.Second + PLATFORM_WAKE_SECONDS_BUFFER;
  }

  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOURS_ALARM);
  IoWrite8 (PCAT_RTC_DATA_REGISTER, EfiTime.Hour);
  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTES_ALARM);
  IoWrite8 (PCAT_RTC_DATA_REGISTER, EfiTime.Minute);
  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS_ALARM);
  IoWrite8 (PCAT_RTC_DATA_REGISTER, Data8);

  //
  // Enable RTC alarm interrupt
  //
  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B);
  Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
  IoWrite8 (PCAT_RTC_DATA_REGISTER, (Data8 | BIT5));

  //
  // Enable RTC alarm as WAKE event
  //
  Data16 = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E);
  IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, (Data16 | B_QNC_PM1BLK_PM1E_RTC));

  //
  // Enter S3
  //
  Data32 = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
  Data32  = (UINT32) ((Data32 & 0xffffc3fe) | V_S3 | B_QNC_PM1BLK_PM1C_SCIEN);
  IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Data32);
  Data32 = Data32 | B_QNC_PM1BLK_PM1C_SLPEN;
  IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Data32);

  //
  // Enable Interrupt if it's enabled before
  //
  if ( (Eflags & 0x200) ) {
     EnableInterrupts ();
  }
}
Beispiel #21
0
EFI_STATUS
ConfigureSoCGpio (
  IN SYSTEM_CONFIGURATION  *SystemConfiguration
  )
{

    DEBUG ((EFI_D_ERROR, "ConfigureSoCGpio------------start\n"));
    if (SystemConfiguration->eMMCBootMode== 1) {// Auto detection mode
     DEBUG ((EFI_D_ERROR, "Auto detection mode------------start\n"));

     //
     //Silicon Steppings
     //
     switch (PchStepping()) {
       case PchA0:  // SOC A0 and A1
       case PchA1:
         DEBUG ((EFI_D_ERROR, "SOC A0/A1: eMMC 4.41 GPIO Configuration\n"));
         SystemConfiguration->LpsseMMCEnabled            = 1;
         SystemConfiguration->LpsseMMC45Enabled          = 0;
         break;
       case PchB0:  // SOC B0 and later
       default:
         DEBUG ((EFI_D_ERROR, "SOC B0 and later: eMMC 4.5 GPIO Configuration\n"));
         SystemConfiguration->LpsseMMCEnabled            = 0;
         SystemConfiguration->LpsseMMC45Enabled          = 1;
         break;
     }
    } else if (SystemConfiguration->eMMCBootMode == 2) { // eMMC 4.41
        DEBUG ((EFI_D_ERROR, "Force to eMMC 4.41 GPIO Configuration\n"));
        SystemConfiguration->LpsseMMCEnabled            = 1;
        SystemConfiguration->LpsseMMC45Enabled          = 0;
    } else if (SystemConfiguration->eMMCBootMode == 3) { // eMMC 4.5
         DEBUG ((EFI_D_ERROR, "Force to eMMC 4.5 GPIO Configuration\n"));
         SystemConfiguration->LpsseMMCEnabled            = 0;
         SystemConfiguration->LpsseMMC45Enabled          = 1;

    } else { // Disable eMMC controllers
         DEBUG ((EFI_D_ERROR, "Disable eMMC GPIO controllers\n"));
         SystemConfiguration->LpsseMMCEnabled            = 0;
         SystemConfiguration->LpsseMMC45Enabled          = 0;
    }

  /*
  20.1.1  EMMC
  SDMMC1_CLK -         write 0x2003ED01 to IOBASE + 0x03E0
  SDMMC1_CMD -        write 0x2003EC81 to IOBASE + 0x0390
  SDMMC1_D0 -           write 0x2003EC81 to IOBASE + 0x03D0
  SDMMC1_D1 -           write 0x2003EC81 to IOBASE + 0x0400
  SDMMC1_D2 -           write 0x2003EC81 to IOBASE + 0x03B0
  SDMMC1_D3_CD_B - write 0x2003EC81 to IOBASE + 0x0360
  MMC1_D4_SD_WE -   write 0x2003EC81 to IOBASE + 0x0380
  MMC1_D5 -                write 0x2003EC81 to IOBASE + 0x03C0
  MMC1_D6 -                write 0x2003EC81 to IOBASE + 0x0370
  MMC1_D7 -                write 0x2003EC81 to IOBASE + 0x03F0
  MMC1_RESET_B -       write 0x2003ED01 to IOBASE + 0x0330
  */
  if (SystemConfiguration->LpsseMMCEnabled== 1) {
    MmioWrite32 (IO_BASE_ADDRESS + 0x03E0, 0x2003ED01); //EMMC 4.41
    MmioWrite32 (IO_BASE_ADDRESS + 0x0390, 0x2003EC81);
    MmioWrite32 (IO_BASE_ADDRESS + 0x03D0, 0x2003EC81);
    MmioWrite32 (IO_BASE_ADDRESS + 0x0400, 0x2003EC81);
    MmioWrite32 (IO_BASE_ADDRESS + 0x03B0, 0x2003EC81);
    MmioWrite32 (IO_BASE_ADDRESS + 0x0360, 0x2003EC81);
    MmioWrite32 (IO_BASE_ADDRESS + 0x0380, 0x2003EC81);
    MmioWrite32 (IO_BASE_ADDRESS + 0x03C0, 0x2003EC81);
    MmioWrite32 (IO_BASE_ADDRESS + 0x0370, 0x2003EC81);
    MmioWrite32 (IO_BASE_ADDRESS + 0x03F0, 0x2003EC81);
    MmioWrite32 (IO_BASE_ADDRESS + 0x0330, 0x2003ED01);
  }

  /*
  eMMC 4.5 controller
  SDMMC1_CLK -         write 0x2003ED03 to IOBASE + 0x03E0
  SDMMC1_CMD -        write 0x2003EC83 to IOBASE + 0x0390
  SDMMC1_D0 -           write 0x2003EC83 to IOBASE + 0x03D0
  SDMMC1_D1 -           write 0x2003EC83 to IOBASE + 0x0400
  SDMMC1_D2 -           write 0x2003EC83 to IOBASE + 0x03B0
  SDMMC1_D3_CD_B -  write 0x2003EC83 to IOBASE + 0x0360
  MMC1_D4_SD_WE -   write 0x2003EC83 to IOBASE + 0x0380
  MMC1_D5 -                write 0x2003EC83 to IOBASE + 0x03C0
  MMC1_D6 -                write 0x2003EC83 to IOBASE + 0x0370
  MMC1_D7 -                write 0x2003EC83 to IOBASE + 0x03F0
  MMC1_RESET_B -       write 0x2003ED03 to IOBASE + 0x0330
  */
  if (SystemConfiguration->LpsseMMC45Enabled== 1) {
    MmioWrite32 (IO_BASE_ADDRESS + 0x03E0, 0x2003ED03); // EMMC 4.5
    MmioWrite32 (IO_BASE_ADDRESS + 0x0390, 0x2003EC83);
    MmioWrite32 (IO_BASE_ADDRESS + 0x03D0, 0x2003EC83);
    MmioWrite32 (IO_BASE_ADDRESS + 0x0400, 0x2003EC83);
    MmioWrite32 (IO_BASE_ADDRESS + 0x03B0, 0x2003EC83);
    MmioWrite32 (IO_BASE_ADDRESS + 0x0360, 0x2003EC83);
    MmioWrite32 (IO_BASE_ADDRESS + 0x0380, 0x2003EC83);
    MmioWrite32 (IO_BASE_ADDRESS + 0x03C0, 0x2003EC83);
    MmioWrite32 (IO_BASE_ADDRESS + 0x0370, 0x2003EC83);
    MmioWrite32 (IO_BASE_ADDRESS + 0x03F0, 0x2003EC83);
    MmioWrite32 (IO_BASE_ADDRESS + 0x0330, 0x2003ED03);

  }

//
// Change GPIOC_0 setting to allow MMIO access under Android.
//
  IoWrite32 (GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL,
           (IoRead32(GPIO_BASE_ADDRESS + R_PCH_GPIO_SC_USE_SEL) & (UINT32)~BIT0));
  DEBUG ((EFI_D_ERROR, "ConfigureSoCGpio------------end\n"));
  return EFI_SUCCESS;
}
Beispiel #22
0
VOID
GetMacAddress()
{
  EFI_STATUS                  Status;
  EFI_MAC_ADDRESS             MacAddr;
  UINT8                       *HwAddress;
  UINTN                       HwAddressSize;
  UINTN                       Index, Index2;
  EFI_HANDLE                  *HandleBuffer;
  UINTN                       NumberOfHandles;
  EFI_DEVICE_PATH_PROTOCOL    *Node;
  EFI_DEVICE_PATH_PROTOCOL    *DevicePath;
  MAC_ADDR_DEVICE_PATH        *MacAddressNode;
  BOOLEAN                     Found;
  BOOLEAN                     Swab;
  UINT16                      PreviousVendor = 0;
  UINT32                      Mac0, Mac4;
  UINTN                       Offset;

  HwAddressSize = 6;
  //
  // Locate Service Binding handles.
  //
  NumberOfHandles = 0;
  HandleBuffer = NULL;
  Status = gBS->LocateHandleBuffer (
                                    ByProtocol,
                                    &gEfiDevicePathProtocolGuid,
                                    NULL,
                                    &NumberOfHandles,
                                    &HandleBuffer
                                    );
  if (EFI_ERROR (Status)) {
    return;
  }

  Found = FALSE;
  for (Index = 0; Index < NumberOfHandles; Index++) {
    Node = NULL;
    Status = gBS->HandleProtocol (
                                  HandleBuffer[Index],
                                  &gEfiDevicePathProtocolGuid,
                                  (VOID **) &Node
                                  );
    if (EFI_ERROR (Status)) {
      continue;
    }
    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node;

    //
    while (!IsDevicePathEnd (DevicePath)) {
      if ((DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) &&
          (DevicePathSubType (DevicePath) == MSG_MAC_ADDR_DP)) {
        //
        // Get MAC address.
        //
        MacAddressNode = (MAC_ADDR_DEVICE_PATH*)DevicePath;
        //HwAddressSize = sizeof (EFI_MAC_ADDRESS);
        //if (MacAddressNode->IfType == 0x01 || MacAddressNode->IfType == 0x00) {
        //  HwAddressSize = 6;
        //}
        CopyMem(&MacAddr, &MacAddressNode->MacAddress.Addr[0], HwAddressSize);
        DBG("MAC address of LAN #%d= ", Index);
        HwAddress = &MacAddressNode->MacAddress.Addr[0];
        for (Index2 = 0; Index2 < HwAddressSize; Index2++) {
          DBG("%02x:", *HwAddress++);
        }
        DBG("\n");
        Found = TRUE;
        CopyMem(&gLanMac[nLanPaths++], &MacAddressNode->MacAddress.Addr[0], HwAddressSize);
        break;
      }
      DevicePath = NextDevicePathNode (DevicePath);
    }
    if (nLanPaths > 3) {
      break;
    }
  }
  if (HandleBuffer != NULL) {
    FreePool (HandleBuffer);
  }
  if (!Found && GetLegacyLanAddress) {
    ////
    //
    //  Legacy boot. Get MAC-address from hardwaredirectly
    //
    ////
    DBG(" get legacy LAN MAC, %d card found\n", nLanCards);
    for (Index = 0; Index < nLanCards; Index++) {
      if (!gLanMmio[Index]) {  //security
        continue;
      }
      Offset = 0;
      Swab = FALSE;
      switch (gLanVendor[Index]) {
        case 0x11ab:   //Marvell Yukon
          if (PreviousVendor == gLanVendor[Index]) {
            Offset = B2_MAC_2;
          } else {
            Offset = B2_MAC_1;
          }
          CopyMem(&gLanMac[0][Index], gLanMmio[Index] + Offset, 6);
          goto done;

        case 0x10ec:   //Realtek
          Mac0 = IoRead32((UINTN)gLanMmio[Index]);
          Mac4 = IoRead32((UINTN)gLanMmio[Index] + 4);
          goto copy;
          
        case 0x14e4:   //Broadcom
          if (PreviousVendor == gLanVendor[Index]) {
            Offset = EMAC_MACADDR1_HI;
          } else {
            Offset = EMAC_MACADDR0_HI;
          }
          break;
        case 0x1969:   //Atheros
          Offset = L1C_STAD0;
          Swab = TRUE;
          break;
        case 0x8086:   //Intel
          if (PreviousVendor == gLanVendor[Index]) {
            Offset = INTEL_MAC_2;
          } else {
            Offset = INTEL_MAC_1;
          }
          break;
          
        default:
          break;
      }
      if (!Offset) {
        continue;
      }
      Mac0 = *(UINT32*)(gLanMmio[Index] + Offset);
      Mac4 = *(UINT32*)(gLanMmio[Index] + Offset + 4);
      if (Swab) {
        gLanMac[Index][0] = (UINT8)((Mac4 & 0xFF00) >> 8);
        gLanMac[Index][1] = (UINT8)(Mac4 & 0xFF);
        gLanMac[Index][2] = (UINT8)((Mac0 & 0xFF000000) >> 24);
        gLanMac[Index][3] = (UINT8)((Mac0 & 0x00FF0000) >> 16);
        gLanMac[Index][4] = (UINT8)((Mac0 & 0x0000FF00) >> 8);
        gLanMac[Index][5] = (UINT8)(Mac0 & 0x000000FF);
        goto done;
      }
    copy:
      CopyMem(&gLanMac[Index][0], &Mac0, 4);
      CopyMem(&gLanMac[Index][4], &Mac4, 2);
      
    done:
      PreviousVendor = gLanVendor[Index];
      DBG("Legacy MAC address of LAN #%d= ", Index);
      HwAddress = &gLanMac[Index][0];
      for (Index2 = 0; Index2 < HwAddressSize; Index2++) {
        DBG("%02x:", *HwAddress++);
      }
      DBG("\n");

    }
  }
Beispiel #23
0
EFI_STATUS
EnableAcpiCallback (
  IN  EFI_HANDLE                    DispatchHandle,
  IN  CONST VOID                    *DispatchContext,
  IN  OUT VOID                      *CommBuffer,
  IN  OUT UINTN                     *CommBufferSize
  )
/*++

Routine Description:
  SMI handler to enable ACPI mode

  Dispatched on reads from APM port with value 0xA0

  Disables the SW SMI Timer.
  ACPI events are disabled and ACPI event status is cleared.
  SCI mode is then enabled.

   Disable SW SMI Timer

   Clear all ACPI event status and disable all ACPI events
   Disable PM sources except power button
   Clear status bits

   Disable GPE0 sources
   Clear status bits

   Disable GPE1 sources
   Clear status bits

   Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)

   Enable SCI

Arguments:
  DispatchHandle  - EFI Handle
  DispatchContext - Pointer to the EFI_SMM_SW_DISPATCH_CONTEXT

Returns:
  Nothing

--*/
{
  EFI_STATUS  Status;
  UINT32      SmiEn;
  UINT16      Pm1Cnt;
  UINT8       Data8;

  Status  = GetAllQncPmBase (gSmst);
  ASSERT_EFI_ERROR (Status);

  SmiEn = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);

  //
  // Disable SW SMI Timer
  //
  SmiEn &= ~(B_QNC_GPE0BLK_SMIE_SWT);
  IoWrite32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE, SmiEn);

  //
  // Guarantee day-of-month alarm is invalid (ACPI 1.0 section 4.7.2.4)
  //
  Data8 = RTC_ADDRESS_REGISTER_D;
  IoWrite8 (R_IOPORT_CMOS_STANDARD_INDEX, Data8);
  Data8 = 0x0;
  IoWrite8 (R_IOPORT_CMOS_STANDARD_DATA, Data8);

  //
  // Enable SCI
  //
  Pm1Cnt = IoRead16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C);
  Pm1Cnt |= B_QNC_PM1BLK_PM1C_SCIEN;
  IoWrite16 (mAcpiSmm.QncPmBase + R_QNC_PM1BLK_PM1C, Pm1Cnt);

  //
  // Do platform specific stuff for ACPI enable SMI
  //


  return EFI_SUCCESS;
}
Beispiel #24
0
EFI_STATUS
SaveRuntimeScriptTable (
  IN EFI_SMM_SYSTEM_TABLE2       *Smst
  )
{
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  PciAddress;
  UINT32                Data32;
  UINT16                Data16;
  UINT8                 Mask;
  UINTN                 Index;
  UINTN                 Offset;
  UINT16                DeviceId;

  //
  // Check what Soc we are running on (read Host bridge DeviceId)
  //
  DeviceId = QncGetSocDeviceId();

  //
  // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
  // and vital to S3 resume. That's why we put save code here
  //
  Index = 0;
  while (mPciCfgRegTable[Index] != PCI_DEVICE_END) {

    PciAddress.Bus              = mPciCfgRegTable[Index++];
    PciAddress.Device           = mPciCfgRegTable[Index++];
    PciAddress.Function         = mPciCfgRegTable[Index++];
    PciAddress.Register         = 0;
    PciAddress.ExtendedRegister = 0;

    Data16 = PciRead16 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));
    if (Data16 == 0xFFFF) {
      Index += 8;
      continue;
    }

    for (Offset = 0, Mask = 0x01; Offset < 256; Offset += 4, Mask <<= 1) {

      if (Mask == 0x00) {
        Mask = 0x01;
      }

      if (mPciCfgRegTable[Index + Offset / 32] & Mask) {

        PciAddress.Register = (UINT8) Offset;
        Data32 = PciRead32 (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));


        //
        // Save latest settings to runtime script table
        //
        S3BootScriptSavePciCfgWrite (
             S3BootScriptWidthUint32,
             PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register)),
             1,
             &Data32
             );
      }
    }

    Index += 8;

  }

  //
  // Save message bus registers
  //
  Index = 0;
  while (QNCS3SaveExtReg[Index] != 0xFF) {
    Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);

    //
    // Save IMR settings with IMR protection disabled initially
    // HMBOUND and IMRs will be locked just before jumping to the OS waking vector
    //
    if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {
      if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) == QUARK_NC_MEMORY_MANAGER_IMRXL)) {
        Data32 &= ~IMR_LOCK;
        if (DeviceId == QUARK2_MC_DEVICE_ID) {
          Data32 &= ~IMR_EN;
        }
      }
      if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) >= QUARK_NC_MEMORY_MANAGER_IMRXRM)) {
        Data32 = (UINT32)IMRX_ALL_ACCESS;
      }
    }

    //
    // Save latest settings to runtime script table
    //
    S3BootScriptSavePciCfgWrite (
      S3BootScriptWidthUint32,
      PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),
      1,
      &Data32
     );

    Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);

    S3BootScriptSavePciCfgWrite (
      S3BootScriptWidthUint32,
      PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
      1,
      &Data32
     );
    Index += 2;
  }

  Index = 0;
  while (QNCS3SaveExtReg[Index] != 0xFF) {
    //
    // Save IMR settings with IMR protection enabled (above script was to handle restoring all settings first - now we want to enable)
    //
    if (QNCS3SaveExtReg[Index] == QUARK_NC_MEMORY_MANAGER_SB_PORT_ID) {
      if (DeviceId == QUARK2_MC_DEVICE_ID) {
        if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXL)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) == QUARK_NC_MEMORY_MANAGER_IMRXL)) {
          Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);
          Data32 &= ~IMR_LOCK;

          //
          // Save latest settings to runtime script table
          //
          S3BootScriptSavePciCfgWrite (
            S3BootScriptWidthUint32,
            PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),
            1,
            &Data32
          );

          Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);

          S3BootScriptSavePciCfgWrite (
            S3BootScriptWidthUint32,
            PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
            1,
            &Data32
          );
        }
      } else {
        if ((QNCS3SaveExtReg[Index + 1] >= (QUARK_NC_MEMORY_MANAGER_IMR0+QUARK_NC_MEMORY_MANAGER_IMRXRM)) && (QNCS3SaveExtReg[Index + 1] <= (QUARK_NC_MEMORY_MANAGER_IMR7+QUARK_NC_MEMORY_MANAGER_IMRXWM)) && ((QNCS3SaveExtReg[Index + 1] & 0x03) >= QUARK_NC_MEMORY_MANAGER_IMRXRM)) {
          Data32 = QNCPortRead (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);

          //
          // Save latest settings to runtime script table
          //
          S3BootScriptSavePciCfgWrite (
            S3BootScriptWidthUint32,
            PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MDR)),
            1,
            &Data32
          );

          Data32 = MESSAGE_WRITE_DW (QNCS3SaveExtReg[Index], QNCS3SaveExtReg[Index + 1]);

          S3BootScriptSavePciCfgWrite (
            S3BootScriptWidthUint32,
            PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
            1,
            &Data32
          );
        }
      }
    }
    Index += 2;
  }

  // Check if ECC scrub enabled and need re-enabling on resume
  // All scrub related configuration registers are saved on suspend
  // as part of QNCS3SaveExtReg configuration table script.
  // The code below extends the S3 resume script with scrub reactivation
  // message (if needed only)
  Data32 = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG);
  if( 0 != (Data32 & SCRUB_CFG_ACTIVE)) {

      Data32 = SCRUB_RESUME_MSG();

      S3BootScriptSavePciCfgWrite (
        S3BootScriptWidthUint32,
        PCILIB_TO_COMMON_ADDRESS (PCI_LIB_ADDRESS(0, 0, 0, QNC_ACCESS_PORT_MCR)),
        1,
        &Data32
       );
  }

  //
  // Save I/O ports to S3 script table
  //

  //
  // Important to trap Sx for SMM
  //
  Data32 = IoRead32 (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE);
  S3BootScriptSaveIoWrite(S3BootScriptWidthUint32, (mAcpiSmm.QncGpe0Base + R_QNC_GPE0BLK_SMIE), 1, &Data32);

  return EFI_SUCCESS;
}
Beispiel #25
0
// ------------------------------------------------------------------------------------------------
uint32 PciRead32(uint32 id, uint32 reg)
{
    uint32 addr = 0x80000000 | id | (reg & 0xfc);
    IoWrite32(PCI_CONFIG_ADDR, addr);
    return IoRead32(PCI_CONFIG_DATA);
}
Beispiel #26
0
VOID
EFIAPI
EnableAcpiCallback (
  IN  EFI_HANDLE                    DispatchHandle,
  IN  EFI_SMM_SW_DISPATCH_CONTEXT   *DispatchContext
  )
{
  UINT32 SmiEn;
  UINT16 Pm1Cnt;
  UINT16 wordValue;
  UINT32 RegData32;

  //
  // Disable SW SMI Timer
  //
  SmiEn = IoRead32(mAcpiBaseAddr + R_PCH_SMI_EN);
  SmiEn &= ~B_PCH_SMI_STS_SWSMI_TMR;
  IoWrite32(mAcpiBaseAddr + R_PCH_SMI_EN, SmiEn);

  wordValue = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_STS);
  if(wordValue & B_PCH_ACPI_PM1_STS_WAK) {
	  IoWrite32((mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN), 0x0000);
	  IoWrite32((mAcpiBaseAddr + R_PCH_ACPI_GPE0a_STS), 0xffffffff);
  }
  else {
		mPM1_SaveState16 = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_EN);

		//
		// Disable PM sources except power button
		//
    // power button is enabled only for PCAT. Disabled it on Tablet platform
    //
    IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_EN, B_PCH_ACPI_PM1_EN_PWRBTN);
		IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_STS, 0xffff);

		mGPE_SaveState32 = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN);
		IoWrite32(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_EN, 0x0000);
		IoWrite32(mAcpiBaseAddr + R_PCH_ACPI_GPE0a_STS, 0xffffffff);

  }

  //
  // Guarantee day-of-month alarm is invalid (ACPI 5.0 Section 4.8.2.4 "Real Time Clock Alarm")
  // Clear Status D reg VM bit, Date of month Alarm to make Data in CMOS RAM is no longer Valid
  //
  IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_D);
  IoWrite8 (PCAT_RTC_DATA_REGISTER, 0x0);


	RegData32 = IoRead32(ACPI_BASE_ADDRESS + R_PCH_ALT_GP_SMI_EN);
	RegData32 &= ~(BIT7);
    IoWrite32((ACPI_BASE_ADDRESS + R_PCH_ALT_GP_SMI_EN), RegData32);


  //
  // Enable SCI
  //
  Pm1Cnt = IoRead16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT);
  Pm1Cnt |= B_PCH_ACPI_PM1_CNT_SCI_EN;
  IoWrite16(mAcpiBaseAddr + R_PCH_ACPI_PM1_CNT, Pm1Cnt);


}
Beispiel #27
0
/**
  Reads I/O registers.

  @param[in]  PeiServices  An indirect pointer to the PEI Services Table
                           published by the PEI Foundation.
  @param[in]  This         Pointer to local data for the interface.
  @param[in]  Width        The width of the access. Enumerated in bytes.
  @param[in]  Address      The physical address of the access.
  @param[in]  Count        The number of accesses to perform.
  @param[out] Buffer       A pointer to the buffer of data.

  @retval EFI_SUCCESS            The function completed successfully.
  @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
  @retval EFI_INVALID_PARAMETER  Buffer is NULL.
  @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
                                 and Count is not valid for this EFI system.

**/
EFI_STATUS
EFIAPI
CpuIoServiceRead (
  IN  CONST EFI_PEI_SERVICES    **PeiServices,
  IN  CONST EFI_PEI_CPU_IO_PPI  *This,
  IN  EFI_PEI_CPU_IO_PPI_WIDTH  Width,
  IN  UINT64                    Address,
  IN  UINTN                     Count,
  OUT VOID                      *Buffer
  )
{
  EFI_STATUS                Status;
  UINT8                     InStride;
  UINT8                     OutStride;
  EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
  BOOLEAN                   Aligned;
  UINT8                     *Uint8Buffer;

  Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Select loop based on the width of the transfer
  //
  InStride = mInStride[Width];
  OutStride = mOutStride[Width];
  OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);

  //
  // Fifo operations supported for (mInStride[Width] == 0)
  //
  if (InStride == 0) {
    switch (OperationWidth) {
    case EfiPeiCpuIoWidthUint8:
      IoReadFifo8 ((UINTN)Address, Count, Buffer);
      return EFI_SUCCESS;
    case EfiPeiCpuIoWidthUint16:
      IoReadFifo16 ((UINTN)Address, Count, Buffer);
      return EFI_SUCCESS;
    case EfiPeiCpuIoWidthUint32:
      IoReadFifo32 ((UINTN)Address, Count, Buffer);
      return EFI_SUCCESS;
    default:
      //
      // The CpuIoCheckParameter call above will ensure that this
      // path is not taken.
      //
      ASSERT (FALSE);
      break;
    }
  }

  Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
  for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
    if (OperationWidth == EfiPeiCpuIoWidthUint8) {
      *Uint8Buffer = IoRead8 ((UINTN)Address);
    } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
      if (Aligned) {
        *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
      } else {
        WriteUnaligned16 ((UINT16 *)Uint8Buffer, IoRead16 ((UINTN)Address));
      }
    } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
      if (Aligned) {
        *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
      } else {
        WriteUnaligned32 ((UINT32 *)Uint8Buffer, IoRead32 ((UINTN)Address));
      }
    }
  }

  return EFI_SUCCESS;
}
Beispiel #28
0
EFI_STATUS
SaveRuntimeScriptTable (
  VOID
  )
{
  SMM_PCI_IO_ADDRESS    PciAddress;
  UINT32                Data32;
  UINT16                Data16;
  UINT8                 Data8;
  UINT8                 Mask;
  UINTN                 Index;
  UINTN                 Offset;
  UINT8                 RegTable[] = {

	  //
    //Bus  ,   Dev,  Func,    DMI
	  //
      0x00 ,  0x00,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
	  //
      0x00 ,  0x08,  0x00,  0x00,  0x30,  0x00,  0x00,  0xa0,

	  //
    //Bus  ,   Dev,  Func,    LPC device
	  //
      0x00 ,  0x1F,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x00 ,  0x08,  0x00,  0x07,  0x00,  0x00,  0x90,  0x00,

	  //
    //Bus  ,   Dev,  Func,    PCIE device
	 //
      0x00 ,  0x1C,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0xC0 ,  0x83,  0x30,  0x00,  0x00,  0x00,  0x00,  0x00,

	  //
    //Bus  ,   Dev,  Func,    PCIE device
    //
	  0x00 ,  0x1C,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x03 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

	  //
    //Bus  ,   Dev,  Func,    SATA device
	  //
      0x00 ,  0x13,  0x00,

	  //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0xf4 ,  0xab,  0x27,  0x10,  0xf1,  0x1d,  0x00,  0x40,

    //
    //Bus  ,   Dev,  Func,    EHCI device
    //
     0x00 ,  0x1D,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
     0x10 ,  0x88,  0x00,  0x00,  0x00,  0x00,  0x00,  0x80,

    //
    //Bus  ,   Dev,  Func,    SMBUS device
    //
     0x00 ,  0x1f,  0x03,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x10 ,  0x89,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    SMBUS device
    //
      0x00 ,  0x1f,  0x03,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x02 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    VGA bus1
    //
      0x01 ,  0x00,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x58 ,  0x81,  0x18,  0x01,  0xb0,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    VGA bus1
    //
      0x01 ,  0x00,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x02 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    VGA bus1 function 1
    //
      0x01 ,  0x00,  0x01,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x51 ,  0x80,  0x80,  0x01,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    VGA bus1 function 1
    //
      0x01 ,  0x00,  0x01,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x02 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    IGD bus0 function 0
    //
      0x00 ,  0x02,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x42 ,  0x81,  0x00,  0x00,  0x00,  0x00,  0x20,  0x00,

    //
    //Bus  ,   Dev,  Func,    USB bus0 function 0
    //
      0x00 ,  0x16,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x32 ,  0x80,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,

    //
    //Bus  ,   Dev,  Func,    HD Audio bus0 function 0
    //
      0x00 ,  0x1B,  0x00,

    //
    //00-1F, 20-3F, 40-5F, 60-7F, 80-9F, A0-BF, C0-DF, E0-FF
    //
      0x00 ,  0x00,  0x00,  0x00,  0x00,  0x00,  0x02,  0x00,

    //
    //0xFF indicates the end of the table
    //
      0xFF
 };

  //
  // These registers have to set in byte order
  //
  UINT8                 ExtReg[] = { 0x9E, 0x9D };  // SMRAM settings



  //
  // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
  // and vital to S3 resume. That's why we put save code here
  //
  PciAddress.Bus      = 0;
  PciAddress.Device   = 0;
  PciAddress.Function = 0;
  PciAddress.ExtendedRegister = 0;

  for (Index = 0; Index < 2; Index++) {
    //
    // Read SRAM setting from Pci(0, 0, 0)
    //
    PciAddress.Register = ExtReg[Index];
    Data8 = MmioRead8 (
              MmPciAddress (0,
                PciAddress.Bus,
                PciAddress.Device,
                PciAddress.Function,
                PciAddress.Register
              )
            );

    //
    // Save latest settings to runtime script table
    //
    S3BootScriptSavePciCfgWrite(
      S3BootScriptWidthUint8,
      *(UINT64*)&PciAddress,
      1,
      &Data8
      );
  }


  //
  // Save PCI-Host bridge settings (0, 0, 0). 0x90, 94 and 9c are changed by CSM
  // and vital to S3 resume. That's why we put save code here
  //
  Index = 0;
  while (RegTable[Index] != 0xFF) {

    PciAddress.Bus      = RegTable[Index++];
    PciAddress.Device   = RegTable[Index++];
    PciAddress.Function = RegTable[Index++];
    PciAddress.Register = 0;
    PciAddress.ExtendedRegister = 0;

    Data16 = MmioRead16 (
              MmPciAddress (0,
                PciAddress.Bus,
                PciAddress.Device,
                PciAddress.Function,
                PciAddress.Register
              )
            );

    if (Data16 == 0xFFFF) {
      Index+=8;
      continue;
    }

    for (Offset = 0, Mask = 0x01; Offset < 256; Offset+=4, Mask<<=1) {

      if (Mask == 0x00) {
        Mask = 0x01;
      }

      if (RegTable[Index + Offset/32] & Mask ) {

        PciAddress.Register = (UINT8)Offset;
        Data32 = MmioRead32 (MmPciAddress (0, PciAddress.Bus, PciAddress.Device, PciAddress.Function, PciAddress.Register));

        //
        // Save latest settings to runtime script table
        //
        S3BootScriptSavePciCfgWrite (
          S3BootScriptWidthUint32,
          *(UINT64*)&PciAddress,
          1,
          &Data32
        );
      }
    }

    Index += 8;

  }


  //
  // Save I/O ports to S3 script table
  //

  //
  // Selftest KBC
  //
  Data8 = 0xAA;
  S3BootScriptSaveIoWrite (
    S3BootScriptWidthUint8,
    0x64,
    (UINTN)1,
    &Data8
    );

  Data32 = IoRead32(mAcpiBaseAddr + R_PCH_SMI_EN);

  S3BootScriptSaveIoWrite (
      S3BootScriptWidthUint32,
      (mAcpiBaseAddr + R_PCH_SMI_EN),
      1,
      &Data32
      );

  //
  // Save B_ICH_TCO_CNT_LOCK so it will be done on S3 resume path.
  //
  Data16 = IoRead16(mAcpiBaseAddr + R_PCH_TCO_CNT);

  S3BootScriptSaveIoWrite (
      S3BootScriptWidthUint16,
      mAcpiBaseAddr + R_PCH_TCO_CNT,
      1,
      &Data16
      );


  return EFI_SUCCESS;
}
Beispiel #29
0
/**

  This function is IO instruction handler for SMM.

  @param Index CPU index

**/
VOID
SmmIoHandler (
  IN UINT32 Index
  )
{
  VM_EXIT_QUALIFICATION   Qualification;
  UINT16                  Port;
  UINTN                   *DataPtr;
  UINTN                   LinearAddr;
  X86_REGISTER            *Reg;
  STM_RSC_IO_DESC         *IoDesc;
  STM_RSC_PCI_CFG_DESC    *PciCfgDesc;
  UINT32                  PciAddress;
  STM_RSC_IO_DESC         LocalIoDesc;
  STM_RSC_PCI_CFG_DESC    *LocalPciCfgDescPtr;
  UINT8                   LocalPciCfgDescBuf[STM_LOG_ENTRY_SIZE];

  Reg = &mGuestContextCommonSmm.GuestContextPerCpu[Index].Register;

  Qualification.UintN = VmReadN (VMCS_N_RO_EXIT_QUALIFICATION_INDEX);

  if (Qualification.IoInstruction.Operand != 0) {
    Port = (UINT16)Qualification.IoInstruction.PortNum;
  } else {
    Port = (UINT16)Reg->Rdx;
  }
  DataPtr = (UINTN *)&Reg->Rax;

  //
  // We need handle case that CF9 is protected, but CF8, CFC need to be pass-through.
  // But DWORD CF8 programming will be caught here.
  // So add check here. CF8 will be bypassed, because it does not in CF9 scope.
  //
  IoDesc = GetStmResourceIo (mHostContextCommon.MleProtectedResource.Base, Port);
  if (IoDesc != NULL) {
    DEBUG ((EFI_D_ERROR, "IO violation!\n"));
    AddEventLogForResource (EvtHandledProtectionException, (STM_RSC *)IoDesc);
    SmmExceptionHandler (Index);
    CpuDeadLoop ();
  }

  IoDesc = GetStmResourceIo ((STM_RSC *)(UINTN)mGuestContextCommonSmm.BiosHwResourceRequirementsPtr, Port);
  if (IoDesc == NULL) {
    ZeroMem (&LocalIoDesc, sizeof(LocalIoDesc));
    LocalIoDesc.Hdr.RscType = IO_RANGE;
    LocalIoDesc.Hdr.Length = sizeof(LocalIoDesc);
    LocalIoDesc.Base = Port;
    LocalIoDesc.Length = (UINT16)(Qualification.IoInstruction.Size + 1);
    AddEventLogForResource (EvtBiosAccessToUnclaimedResource, (STM_RSC *)&LocalIoDesc);
  }

  //
  // Check PCI - 0xCF8, 0xCFC~0xCFF access
  //
  if (Port == 0xCF8) {
    // Access PciAddress

    //
    // We need make sure PciAddress access and PciData access is atomic.
    //
    AcquireSpinLock (&mHostContextCommon.PciLock);
  }
  if ((Port >= 0xCFC) && (Port <= 0xCFF)) {
    // Access PciData

    //
    // AcquireLock to prevent 0xCF8 access
    //
    AcquireSpinLock (&mHostContextCommon.PciLock);
    PciAddress = IoRead32 (0xCF8);
    PciCfgDesc = GetStmResourcePci (
                   mHostContextCommon.MleProtectedResource.Base,
                   BUS_FROM_CF8_ADDRESS(PciAddress),
                   DEVICE_FROM_CF8_ADDRESS(PciAddress),
                   FUNCTION_FROM_CF8_ADDRESS(PciAddress),
                   REGISTER_FROM_CF8_ADDRESS(PciAddress) + (Port & 0x3),
                   (Qualification.IoInstruction.Direction != 0) ? STM_RSC_PCI_CFG_R : STM_RSC_PCI_CFG_W
                   );
    if (PciCfgDesc != NULL) {
      DEBUG ((EFI_D_ERROR, "IO (PCI) violation!\n"));
      AddEventLogForResource (EvtHandledProtectionException, (STM_RSC *)PciCfgDesc);
      ReleaseSpinLock (&mHostContextCommon.PciLock);
      SmmExceptionHandler (Index);
      CpuDeadLoop ();
    }

    PciCfgDesc = GetStmResourcePci (
                   (STM_RSC *)(UINTN)mGuestContextCommonSmm.BiosHwResourceRequirementsPtr,
                   BUS_FROM_CF8_ADDRESS(PciAddress),
                   DEVICE_FROM_CF8_ADDRESS(PciAddress),
                   FUNCTION_FROM_CF8_ADDRESS(PciAddress),
                   REGISTER_FROM_CF8_ADDRESS(PciAddress) + (Port & 0x3),
                   (Qualification.IoInstruction.Direction != 0) ? STM_RSC_PCI_CFG_R : STM_RSC_PCI_CFG_W
                   );
    if (PciCfgDesc == NULL) {
      DEBUG((EFI_D_ERROR, "Add unclaimed PCI_RSC!\n"));
      LocalPciCfgDescPtr = (STM_RSC_PCI_CFG_DESC *)LocalPciCfgDescBuf;
      ZeroMem (LocalPciCfgDescBuf, sizeof(LocalPciCfgDescBuf));
      LocalPciCfgDescPtr->Hdr.RscType = PCI_CFG_RANGE;
      LocalPciCfgDescPtr->Hdr.Length = sizeof(STM_RSC_PCI_CFG_DESC); // BUGBUG: Just report this PCI device, it is hard to create PCI hierachy here.
      LocalPciCfgDescPtr->RWAttributes = (Qualification.IoInstruction.Direction != 0) ? STM_RSC_PCI_CFG_R : STM_RSC_PCI_CFG_W;
      LocalPciCfgDescPtr->Base = REGISTER_FROM_CF8_ADDRESS(PciAddress) + (Port & 0x3);
      LocalPciCfgDescPtr->Length = (UINT16)(Qualification.IoInstruction.Size + 1);
      LocalPciCfgDescPtr->OriginatingBusNumber = BUS_FROM_CF8_ADDRESS(PciAddress);
      LocalPciCfgDescPtr->LastNodeIndex = 0;
      LocalPciCfgDescPtr->PciDevicePath[0].Type = 1;
      LocalPciCfgDescPtr->PciDevicePath[0].Subtype = 1;
      LocalPciCfgDescPtr->PciDevicePath[0].Length = sizeof(STM_PCI_DEVICE_PATH_NODE);
      LocalPciCfgDescPtr->PciDevicePath[0].PciFunction = FUNCTION_FROM_CF8_ADDRESS(PciAddress);
      LocalPciCfgDescPtr->PciDevicePath[0].PciDevice = DEVICE_FROM_CF8_ADDRESS(PciAddress);
      AddEventLogForResource (EvtBiosAccessToUnclaimedResource, (STM_RSC *)LocalPciCfgDescPtr);
    }
  }

  if (Qualification.IoInstruction.Rep != 0) {
    UINT64 RcxMask;

    RcxMask = 0xFFFFFFFFFFFFFFFFull;
    if ((mGuestContextCommonSmm.GuestContextPerCpu[Index].Efer & IA32_EFER_MSR_MLA) == 0) {
      RcxMask = 0xFFFFFFFFull;
    }
    if ((Reg->Rcx & RcxMask) == 0) {
      // Skip
      if ((Port == 0xCF8) || ((Port >= 0xCFC) && (Port <= 0xCFF))) {
        ReleaseSpinLock (&mHostContextCommon.PciLock);
      }
      VmWriteN (VMCS_N_GUEST_RIP_INDEX, VmReadN(VMCS_N_GUEST_RIP_INDEX) + VmRead32(VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
      return ;
    }
  }

  if (Qualification.IoInstruction.String != 0) {
    LinearAddr = VmReadN (VMCS_N_RO_GUEST_LINEAR_ADDR_INDEX);
    if (VmReadN (VMCS_N_GUEST_CR0_INDEX) & CR0_PG) {
      DataPtr = (UINTN *)(UINTN)GuestLinearToHostPhysical (Index, LinearAddr);
    } else {
      DataPtr = (UINTN *)LinearAddr;
    }

    if ((VmReadN (VMCS_N_GUEST_RFLAGS_INDEX) & RFLAGS_DF) != 0) {
      if (Qualification.IoInstruction.Direction != 0) {
        Reg->Rdi -= Qualification.IoInstruction.Size + 1;
      } else {
        Reg->Rsi -= Qualification.IoInstruction.Size + 1;
      }
    } else {
      if (Qualification.IoInstruction.Direction != 0) {
        Reg->Rdi += Qualification.IoInstruction.Size + 1;
      } else {
        Reg->Rsi += Qualification.IoInstruction.Size + 1;
      }
    }
  }

  if (Qualification.IoInstruction.Direction != 0) { // IN
    switch (Qualification.IoInstruction.Size) {
    case 0:
      *(UINT8 *)DataPtr = IoRead8 (Port);
      goto Ret;
      break;
    case 1:
      *(UINT16 *)DataPtr = IoRead16 (Port);
      goto Ret;
      break;
    case 3:
      *(UINT32 *)DataPtr = IoRead32 (Port);
      goto Ret;
      break;
    default:
      break;
    }
  } else { // OUT
    switch (Qualification.IoInstruction.Size) {
    case 0:
      IoWrite8 (Port, (UINT8)*DataPtr);
      goto Ret;
      break;
    case 1:
      IoWrite16 (Port, (UINT16)*DataPtr);
      goto Ret;
      break;
    case 3:
      IoWrite32 (Port, (UINT32)*DataPtr);
      goto Ret;
      break;
    default:
      break;
    }
  }

  if ((Port == 0xCF8) || ((Port >= 0xCFC) && (Port <= 0xCFF))) {
    ReleaseSpinLock (&mHostContextCommon.PciLock);
  }
  DEBUG ((EFI_D_INFO, "!!!IoHandler!!!\n"));
  DumpVmcsAllField ();

  CpuDeadLoop ();

Ret:
  if ((Port == 0xCF8) || ((Port >= 0xCFC) && (Port <= 0xCFF))) {
    ReleaseSpinLock (&mHostContextCommon.PciLock);
  }
  if (Qualification.IoInstruction.Rep != 0) {
    // replay
    Reg->Rcx --;
    return ;
  }

  VmWriteN (VMCS_N_GUEST_RIP_INDEX, VmReadN(VMCS_N_GUEST_RIP_INDEX) + VmRead32(VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
  return ;
}
Beispiel #30
0
EFI_STATUS
UpdateBootMode (
  IN CONST EFI_PEI_SERVICES                       **PeiServices,
  IN OUT EFI_PLATFORM_INFO_HOB                    *PlatformInfoHob
  )
{
  EFI_STATUS                        Status;
  EFI_BOOT_MODE                     BootMode;
  UINT16                            SleepType;
  CHAR16                            *strBootMode;
  PEI_CAPSULE_PPI                   *Capsule;
  EFI_PEI_READ_ONLY_VARIABLE2_PPI   *Variable;
  SYSTEM_CONFIGURATION              SystemConfiguration;
  UINTN                             VarSize;
  volatile UINT32                   GpioValue;
  BOOLEAN                           IsFirstBoot;
  UINT32                            Data32;

  Status = (*PeiServices)->GetBootMode(
                             PeiServices,
                             &BootMode
                             );
  ASSERT_EFI_ERROR (Status);
  if (BootMode  == BOOT_IN_RECOVERY_MODE){
    return Status;
  }
  GetWakeupEventAndSaveToHob (PeiServices);

  //
  // Let's assume things are OK if not told otherwise
  //
  BootMode = BOOT_WITH_FULL_CONFIGURATION;

  //
  // When this boot is WDT reset, the system needs booting with CrashDump function eanbled.
  //
  Data32 = IoRead32 (ACPI_BASE_ADDRESS + R_PCH_TCO_STS);

  //
  // Check Power Button, click the power button, the system will boot in fast boot mode,
  // if it is pressed and hold for a second, it will boot in FullConfiguration/setup mode.
  //
  GpioValue = MmioRead32 (IO_BASE_ADDRESS + GPIO_SSUS_OFFSET + PMU_PWRBTN_B_OFFSET);    // The value of GPIOS_16 (PMU_PWRBTN_B)
  if (((GpioValue & BIT0) != 0)&&((Data32 & B_PCH_TCO_STS_SECOND_TO) != B_PCH_TCO_STS_SECOND_TO)){
    IsFirstBoot = PcdGetBool(PcdBootState);
    if (!IsFirstBoot){
      VarSize = sizeof (SYSTEM_CONFIGURATION);
      ZeroMem (&SystemConfiguration, sizeof (SYSTEM_CONFIGURATION));

      Status = (*PeiServices)->LocatePpi (
                                 PeiServices,
                                 &gEfiPeiReadOnlyVariable2PpiGuid,
                                 0,
                                 NULL,
                                          (void **)&Variable
                                 );
      ASSERT_EFI_ERROR (Status);

      //
      // Use normal setup default from NVRAM variable,
      // the Platform Mode (manufacturing/safe/normal) is handle in PeiGetVariable.
      //
      VarSize = sizeof(SYSTEM_CONFIGURATION);
      Status = Variable->GetVariable (
                           Variable,
                           L"Setup",
                           &gEfiSetupVariableGuid,
                           NULL,
                           &VarSize,
                           &SystemConfiguration
                           );

      if (SystemConfiguration.FastBoot == 1) {
            BootMode = BOOT_WITH_MINIMAL_CONFIGURATION;
      }
    }
  }

  //
  // Check if we need to boot in forced recovery mode
  //
  if (CheckIfRecoveryMode(PeiServices, PlatformInfoHob)) {
    BootMode  = BOOT_IN_RECOVERY_MODE;
  }

  if (BootMode  == BOOT_IN_RECOVERY_MODE) {
    Status = (*PeiServices)->InstallPpi (
                               PeiServices,
                               &mPpiListRecoveryBootMode
                               );
    ASSERT_EFI_ERROR (Status);
  } else {
    if (GetSleepTypeAfterWakeup (PeiServices, &SleepType)) {
      switch (SleepType) {
        case V_PCH_ACPI_PM1_CNT_S3:
          BootMode = BOOT_ON_S3_RESUME;

          //
          // Determine if we're in capsule update mode
          //
          Status = (*PeiServices)->LocatePpi (
                                     PeiServices,
                                     &gPeiCapsulePpiGuid,
                                     0,
                                     NULL,
                                     (void **)&Capsule
                                     );

          if (Status == EFI_SUCCESS) {
            if (Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES**)PeiServices) == EFI_SUCCESS) {
              BootMode = BOOT_ON_FLASH_UPDATE;
            }
          }

          break;

        case V_PCH_ACPI_PM1_CNT_S4:
          BootMode = BOOT_ON_S4_RESUME;
          break;

        case V_PCH_ACPI_PM1_CNT_S5:
          BootMode = BOOT_ON_S5_RESUME;
          break;
      } // switch (SleepType)
    }

    //
    // Check for Safe Mode
    //
  }

  switch (BootMode) {
    case BOOT_WITH_FULL_CONFIGURATION:
      strBootMode = L"BOOT_WITH_FULL_CONFIGURATION";
      break;
    case BOOT_WITH_MINIMAL_CONFIGURATION:
      strBootMode = L"BOOT_WITH_MINIMAL_CONFIGURATION";
      break;
    case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES:
      strBootMode = L"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES";
      break;
    case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:
      strBootMode = L"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS";
      break;
    case BOOT_WITH_DEFAULT_SETTINGS:
      strBootMode = L"BOOT_WITH_DEFAULT_SETTINGS";
      break;
    case BOOT_ON_S4_RESUME:
      strBootMode = L"BOOT_ON_S4_RESUME";
      break;
    case BOOT_ON_S5_RESUME:
      strBootMode = L"BOOT_ON_S5_RESUME";
      break;
    case BOOT_ON_S2_RESUME:
      strBootMode = L"BOOT_ON_S2_RESUME";
      break;
    case BOOT_ON_S3_RESUME:
      strBootMode = L"BOOT_ON_S3_RESUME";
      break;
    case BOOT_ON_FLASH_UPDATE:
      strBootMode = L"BOOT_ON_FLASH_UPDATE";
      break;
    case BOOT_IN_RECOVERY_MODE:
      strBootMode = L"BOOT_IN_RECOVERY_MODE";
      break;
    default:
      strBootMode = L"Unknown boot mode";
  } // switch (BootMode)

  DEBUG ((EFI_D_ERROR, "Setting BootMode to %s\n", strBootMode));
  Status = (*PeiServices)->SetBootMode(
                             PeiServices,
                             BootMode
                             );
  ASSERT_EFI_ERROR (Status);

  return Status;
}