Esempio n. 1
0
EFIAPI
AcquireSpinLock (
  IN OUT  SPIN_LOCK                 *SpinLock
  )
{
  UINT64  Current;
  UINT64  Previous;
  UINT64  Total;
  UINT64  Start;
  UINT64  End;
  UINT64  Timeout;
  INT64   Cycle;
  INT64   Delta;

  if (PcdGet32 (PcdSpinLockTimeout) > 0) {
    //
    // Get the current timer value
    //
    Current = GetPerformanceCounter();

    //
    // Initialize local variables
    //
    Start = 0;
    End   = 0;
    Total = 0;

    //
    // Retrieve the performance counter properties and compute the number of performance
    // counter ticks required to reach the timeout
    //
    Timeout = DivU64x32 (
                MultU64x32 (
                  GetPerformanceCounterProperties (&Start, &End),
                  PcdGet32 (PcdSpinLockTimeout)
                  ),
                1000000
                );
    Cycle = End - Start;
    if (Cycle < 0) {
      Cycle = -Cycle;
    }
    Cycle++;

    while (!AcquireSpinLockOrFail (SpinLock)) {
      CpuPause ();
      Previous = Current;
      Current  = GetPerformanceCounter();
      Delta = (INT64) (Current - Previous);
      if (Start > End) {
        Delta = -Delta;
      }
      if (Delta < 0) {
        Delta += Cycle;
      }
      Total += Delta;
      ASSERT (Total < Timeout);
    }
  } else {
    while (!AcquireSpinLockOrFail (SpinLock)) {
      CpuPause ();
    }
  }
  return SpinLock;
}
Esempio n. 2
0
/**
  Initialize the system (or sometimes called permanent) memory

  This memory is generally represented by the DRAM.

  This function is called from InitializeMemory() in MemoryInitPeim, in the PEI
  phase.
**/
VOID
ArmPlatformInitializeSystemMemory (
  VOID
  )
{
  VOID         *DeviceTreeBase;
  INT32        Node, Prev;
  UINT64       NewBase;
  UINT64       NewSize;
  CONST CHAR8  *Type;
  INT32        Len;
  CONST UINT64 *RegProp;

  NewBase = 0;
  NewSize = 0;

  DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
  ASSERT (DeviceTreeBase != NULL);

  //
  // Make sure we have a valid device tree blob
  //
  ASSERT (fdt_check_header (DeviceTreeBase) == 0);

  //
  // Look for a memory node
  //
  for (Prev = 0;; Prev = Node) {
    Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
    if (Node < 0) {
      break;
    }

    //
    // Check for memory node
    //
    Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len);
    if (Type && AsciiStrnCmp (Type, "memory", Len) == 0) {
      //
      // Get the 'reg' property of this node. For now, we will assume
      // two 8 byte quantities for base and size, respectively.
      //
      RegProp = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
      if (RegProp != 0 && Len == (2 * sizeof (UINT64))) {

        NewBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
        NewSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));

        //
        // Make sure the start of DRAM matches our expectation
        //
        ASSERT (FixedPcdGet64 (PcdSystemMemoryBase) == NewBase);
        PcdSet64 (PcdSystemMemorySize, NewSize);

        DEBUG ((EFI_D_INFO, "%a: System RAM @ 0x%lx - 0x%lx\n",
               __FUNCTION__, NewBase, NewBase + NewSize - 1));
      } else {
        DEBUG ((EFI_D_ERROR, "%a: Failed to parse FDT memory node\n",
               __FUNCTION__));
      }
      break;
    }
  }

  //
  // We need to make sure that the machine we are running on has at least
  // 128 MB of memory configured, and is currently executing this binary from
  // NOR flash. This prevents a device tree image in DRAM from getting
  // clobbered when our caller installs permanent PEI RAM, before we have a
  // chance of marking its location as reserved or copy it to a freshly
  // allocated block in the permanent PEI RAM in the platform PEIM.
  //
  ASSERT (NewSize >= SIZE_128MB);
  ASSERT (
    (((UINT64)PcdGet64 (PcdFdBaseAddress) +
      (UINT64)PcdGet32 (PcdFdSize)) <= NewBase) ||
    ((UINT64)PcdGet64 (PcdFdBaseAddress) >= (NewBase + NewSize)));
}
Esempio n. 3
0
BOOLEAN
ReadUsingMmio (
  IN UINTN  SpiOffset
  )
{
  return (BOOLEAN) ((SpiOffset >= BIOS_REGION_FLASH_OFFSET) && (SpiOffset < (BIOS_REGION_FLASH_OFFSET + PcdGet32 (PcdBiosImageSize))) && (!EfiAtRuntime ()));
}
/**
  Initialize the state information for the CPU Architectural Protocol

  @param  ImageHandle   of the loaded driver
  @param  SystemTable   Pointer to the System Table

  @retval EFI_SUCCESS           Protocol registered
  @retval EFI_OUT_OF_RESOURCES  Cannot allocate protocol data structure
  @retval EFI_DEVICE_ERROR      Hardware problems

**/
EFI_STATUS
InterruptDxeInitialize (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
{
  EFI_STATUS              Status;
  UINTN                   Index;
  UINT32                  RegOffset;
  UINTN                   RegShift;
  EFI_CPU_ARCH_PROTOCOL   *Cpu;
  
  // Make sure the Interrupt Controller Protocol is not already installed in the system.
  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);

  mGicNumInterrupts = ArmGicGetMaxNumInterrupts (PcdGet32(PcdGicDistributorBase));

  for (Index = 0; Index < mGicNumInterrupts; Index++) {
    DisableInterruptSource (&gHardwareInterruptProtocol, Index);
    
    // Set Priority 
    RegOffset = Index / 4;
    RegShift = (Index % 4) * 8;
    MmioAndThenOr32 (
      PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPR + (4*RegOffset),
      ~(0xff << RegShift), 
      ARM_GIC_DEFAULT_PRIORITY << RegShift
      );
  }

  // Configure interrupts for cpu 0
  for (Index = 0; Index < (mGicNumInterrupts / 4); Index++) {
    MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDIPTR + (Index*4), 0x01010101);
  }

  // Set binary point reg to 0x7 (no preemption)
  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCBPR, 0x7);

  // Set priority mask reg to 0xff to allow all priorities through
  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCPMR, 0xff);
  
  // Enable gic cpu interface
  MmioWrite32 (PcdGet32(PcdGicInterruptInterfaceBase) + ARM_GIC_ICCICR, 0x1);

  // Enable gic distributor
  MmioWrite32 (PcdGet32(PcdGicDistributorBase) + ARM_GIC_ICDDCR, 0x1);
  
  // Initialize the array for the Interrupt Handlers
  gRegisteredInterruptHandlers = (HARDWARE_INTERRUPT_HANDLER*)AllocateZeroPool (sizeof(HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
  
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &gHardwareInterruptHandle,
                  &gHardwareInterruptProtocolGuid,   &gHardwareInterruptProtocol,
                  NULL
                  );
  ASSERT_EFI_ERROR (Status);
  
  //
  // Get the CPU protocol that this driver requires.
  //
  Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
  ASSERT_EFI_ERROR(Status);

  //
  // Unregister the default exception handler.
  //
  Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL);
  ASSERT_EFI_ERROR(Status);

  //
  // Register to receive interrupts
  //
  Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, IrqInterruptHandler);
  ASSERT_EFI_ERROR(Status);

  // Register for an ExitBootServicesEvent
  Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
  ASSERT_EFI_ERROR (Status);

  return Status;
}
Esempio n. 5
0
/**
  The user Entry Point for Application. The user code starts with this function
  as the real entry point for the image goes into a library that calls this 
  function.

  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  
  @param[in] SystemTable    A pointer to the EFI System Table.
  
  @retval EFI_SUCCESS       The entry point is executed successfully.
  @retval other             Some error occurs when executing this entry point.

**/
EFI_STATUS
EFIAPI
InitializeUserInterface (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_HII_HANDLE                     HiiHandle;
  EFI_STATUS                         Status;
  EFI_GRAPHICS_OUTPUT_PROTOCOL       *GraphicsOutput;
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *SimpleTextOut;
  UINTN                              BootTextColumn;
  UINTN                              BootTextRow;

  if (!mModeInitialized) {
    //
    // After the console is ready, get current video resolution 
    // and text mode before launching setup at first time.
    //
    Status = gBS->HandleProtocol (
                    gST->ConsoleOutHandle,
                    &gEfiGraphicsOutputProtocolGuid,
                    (VOID**)&GraphicsOutput
                    );
    if (EFI_ERROR (Status)) {
      GraphicsOutput = NULL;
    }
    
    Status = gBS->HandleProtocol (
                    gST->ConsoleOutHandle,
                    &gEfiSimpleTextOutProtocolGuid,
                    (VOID**)&SimpleTextOut
                    );
    if (EFI_ERROR (Status)) {
      SimpleTextOut = NULL;
    }  

    if (GraphicsOutput != NULL) {
      //
      // Get current video resolution and text mode.
      //
      mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
      mBootVerticalResolution   = GraphicsOutput->Mode->Info->VerticalResolution;
    }

    if (SimpleTextOut != NULL) {
      Status = SimpleTextOut->QueryMode (
                                SimpleTextOut,
                                SimpleTextOut->Mode->Mode,
                                &BootTextColumn,
                                &BootTextRow
                                );
      mBootTextModeColumn = (UINT32)BootTextColumn;
      mBootTextModeRow    = (UINT32)BootTextRow;
    }

    //
    // Get user defined text mode for setup.
    //  
    mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
    mSetupVerticalResolution   = PcdGet32 (PcdSetupVideoVerticalResolution);      
    mSetupTextModeColumn       = PcdGet32 (PcdSetupConOutColumn);
    mSetupTextModeRow          = PcdGet32 (PcdSetupConOutRow);

    mModeInitialized           = TRUE;
  }

  gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
  gST->ConOut->ClearScreen (gST->ConOut);
  
  //
  // Install customized fonts needed by Front Page
  //
  
  HiiHandle = ExportFonts ();
  ASSERT (HiiHandle != NULL);

  InitializeStringSupport ();

  BdsSetConsoleMode (TRUE);
  UiEntry (FALSE);
  BdsSetConsoleMode (FALSE);

  UninitializeStringSupport ();
  HiiRemovePackages (HiiHandle);

  return EFI_SUCCESS;
}
Esempio n. 6
0
/**
  Initialize the state information for the CPU Architectural Protocol

  @param  ImageHandle   of the loaded driver
  @param  SystemTable   Pointer to the System Table

  @retval EFI_SUCCESS           Protocol registered
  @retval EFI_OUT_OF_RESOURCES  Cannot allocate protocol data structure
  @retval EFI_DEVICE_ERROR      Hardware problems

**/
EFI_STATUS
GicV2DxeInitialize (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
{
  EFI_STATUS              Status;
  UINTN                   Index;
  UINT32                  RegOffset;
  UINTN                   RegShift;
  UINT32                  CpuTarget;

  // Make sure the Interrupt Controller Protocol is not already installed in the system.
  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);

  mGicInterruptInterfaceBase = PcdGet32 (PcdGicInterruptInterfaceBase);
  mGicDistributorBase = PcdGet32 (PcdGicDistributorBase);
  mGicNumInterrupts = ArmGicGetMaxNumInterrupts (mGicDistributorBase);

  for (Index = 0; Index < mGicNumInterrupts; Index++) {
    GicV2DisableInterruptSource (&gHardwareInterruptV2Protocol, Index);

    // Set Priority
    RegOffset = Index / 4;
    RegShift = (Index % 4) * 8;
    MmioAndThenOr32 (
      mGicDistributorBase + ARM_GIC_ICDIPR + (4 * RegOffset),
      ~(0xff << RegShift),
      ARM_GIC_DEFAULT_PRIORITY << RegShift
      );
  }

  //
  // Targets the interrupts to the Primary Cpu
  //

  // Only Primary CPU will run this code. We can identify our GIC CPU ID by reading
  // the GIC Distributor Target register. The 8 first GICD_ITARGETSRn are banked to each
  // connected CPU. These 8 registers hold the CPU targets fields for interrupts 0-31.
  // More Info in the GIC Specification about "Interrupt Processor Targets Registers"
  //
  // Read the first Interrupt Processor Targets Register (that corresponds to the 4
  // first SGIs)
  CpuTarget = MmioRead32 (mGicDistributorBase + ARM_GIC_ICDIPTR);

  // The CPU target is a bit field mapping each CPU to a GIC CPU Interface. This value
  // is 0 when we run on a uniprocessor platform.
  if (CpuTarget != 0) {
    // The 8 first Interrupt Processor Targets Registers are read-only
    for (Index = 8; Index < (mGicNumInterrupts / 4); Index++) {
      MmioWrite32 (mGicDistributorBase + ARM_GIC_ICDIPTR + (Index * 4), CpuTarget);
    }
  }

  // Set binary point reg to 0x7 (no preemption)
  MmioWrite32 (mGicInterruptInterfaceBase + ARM_GIC_ICCBPR, 0x7);

  // Set priority mask reg to 0xff to allow all priorities through
  MmioWrite32 (mGicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0xff);

  // Enable gic cpu interface
  ArmGicEnableInterruptInterface (mGicInterruptInterfaceBase);

  // Enable gic distributor
  ArmGicEnableDistributor (mGicDistributorBase);

  Status = InstallAndRegisterInterruptService (
          &gHardwareInterruptV2Protocol, GicV2IrqInterruptHandler, GicV2ExitBootServicesEvent);

  return Status;
}
Esempio n. 7
0
/**
  Fault Tolerant Write protocol notification event handler.

  Non-Volatile variable write may needs FTW protocol to reclaim when
  writting variable.

  @param[in] Event    Event whose notification function is being invoked.
  @param[in] Context  Pointer to the notification function's context.

**/
VOID
EFIAPI
FtwNotificationEvent (
    IN  EFI_EVENT                           Event,
    IN  VOID                                *Context
)
{
    EFI_STATUS                              Status;
    EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL      *FvbProtocol;
    EFI_FAULT_TOLERANT_WRITE_PROTOCOL       *FtwProtocol;
    EFI_PHYSICAL_ADDRESS                    NvStorageVariableBase;
    EFI_GCD_MEMORY_SPACE_DESCRIPTOR         GcdDescriptor;
    EFI_PHYSICAL_ADDRESS                    BaseAddress;
    UINT64                                  Length;
    EFI_PHYSICAL_ADDRESS                    VariableStoreBase;
    UINT64                                  VariableStoreLength;

    //
    // Ensure FTW protocol is installed.
    //
    Status = GetFtwProtocol ((VOID**) &FtwProtocol);
    if (EFI_ERROR (Status)) {
        return ;
    }

    //
    // Find the proper FVB protocol for variable.
    //
    NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
    if (NvStorageVariableBase == 0) {
        NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
    }
    Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);
    if (EFI_ERROR (Status)) {
        return ;
    }
    mVariableModuleGlobal->FvbInstance = FvbProtocol;

    //
    // Mark the variable storage region of the FLASH as RUNTIME.
    //
    VariableStoreBase   = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
    VariableStoreLength = ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase)->Size;
    BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK);
    Length      = VariableStoreLength + (VariableStoreBase - BaseAddress);
    Length      = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);

    Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);
    if (EFI_ERROR (Status)) {
        DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));
    } else {
        Status = gDS->SetMemorySpaceAttributes (
                     BaseAddress,
                     Length,
                     GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME
                 );
        if (EFI_ERROR (Status)) {
            DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));
        }
    }

    Status = VariableWriteServiceInitialize ();
    ASSERT_EFI_ERROR (Status);

    //
    // Install the Variable Write Architectural protocol.
    //
    Status = gBS->InstallProtocolInterface (
                 &mHandle,
                 &gEfiVariableWriteArchProtocolGuid,
                 EFI_NATIVE_INTERFACE,
                 NULL
             );
    ASSERT_EFI_ERROR (Status);

    //
    // Close the notify event to avoid install gEfiVariableWriteArchProtocolGuid again.
    //
    gBS->CloseEvent (Event);

}
Esempio n. 8
0
/**
  This function will be called when MRC is done.

  @param  PeiServices General purpose services available to every PEIM.

  @param  NotifyDescriptor Information about the notify event..

  @param  Ppi The notify context.

  @retval EFI_SUCCESS If the function completed successfully.
**/
EFI_STATUS
EFIAPI
MemoryDiscoveredPpiNotifyCallback (
  IN EFI_PEI_SERVICES           **PeiServices,
  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
  IN VOID                       *Ppi
  )
{
  EFI_STATUS                            Status;
  EFI_BOOT_MODE                         BootMode;
  UINT64                                MemoryLength;
  EFI_SMRAM_DESCRIPTOR                  *SmramDescriptor;
  UINTN                                 NumSmramRegions;
  UINT32                                RmuMainBaseAddress;
  UINT32                                RegData32;
  UINT8                                 CpuAddressWidth;
  UINT32                                RegEax;
  MTRR_SETTINGS                         MtrrSettings;
  EFI_PEI_READ_ONLY_VARIABLE2_PPI       *VariableServices;
  UINT8                                 MorControl;
  UINTN                                 DataSize;

  DEBUG ((EFI_D_INFO, "Platform PEIM Memory Callback\n"));

  NumSmramRegions = 0;
  SmramDescriptor = NULL;
  RmuMainBaseAddress = 0;

  PERF_START (NULL, "SetCache", NULL, 0);

  InfoPostInstallMemory (&RmuMainBaseAddress, &SmramDescriptor, &NumSmramRegions);
  ASSERT (SmramDescriptor != NULL);
  ASSERT (RmuMainBaseAddress != 0);

  MemoryLength = ((UINT64) RmuMainBaseAddress) + 0x10000;

  Status = PeiServicesGetBootMode (&BootMode);
  ASSERT_EFI_ERROR (Status);

  //
  // Get current MTRR settings
  //
  MtrrGetAllMtrrs (&MtrrSettings);

  //
  // Set all DRAM cachability to CacheWriteBack
  //
  Status = MtrrSetMemoryAttributeInMtrrSettings (&MtrrSettings, 0, MemoryLength, CacheWriteBack);
  ASSERT_EFI_ERROR (Status);

  //
  // RTC:28208 - System hang/crash when entering probe mode(ITP) when relocating SMBASE
  //             Workaround to make default SMRAM UnCachable
  //
  Status = MtrrSetMemoryAttributeInMtrrSettings (&MtrrSettings, 0x30000, SIZE_64KB, CacheUncacheable);
  ASSERT_EFI_ERROR (Status);

  //
  // Set new MTRR settings
  //
  MtrrSetAllMtrrs (&MtrrSettings);

  PERF_END (NULL, "SetCache", NULL, 0);

  //
  // Get necessary PPI
  //
  Status = PeiServicesLocatePpi (
             &gEfiPeiReadOnlyVariable2PpiGuid,           // GUID
             0,                                          // INSTANCE
             NULL,                                       // EFI_PEI_PPI_DESCRIPTOR
             (VOID **)&VariableServices                  // PPI
             );
  ASSERT_EFI_ERROR (Status);

  //
  // Detect MOR request by the OS.
  //
  MorControl = 0;
  DataSize = sizeof (MorControl);
  Status = VariableServices->GetVariable (
                               VariableServices,
                               MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
                               &gEfiMemoryOverwriteControlDataGuid,
                               NULL,
                               &DataSize,
                               &MorControl
                               );
  //
  // If OS requested a memory overwrite perform it now for Embedded SRAM
  //
  if (MOR_CLEAR_MEMORY_VALUE (MorControl)) {
    DEBUG ((EFI_D_INFO, "Clear Embedded SRAM per MOR request.\n"));
    if (PcdGet32 (PcdESramMemorySize) > 0) {
      if (PcdGet32 (PcdEsramStage1Base) == 0) {
        //
        // ZeroMem() generates an ASSERT() if Buffer parameter is NULL.
        // Clear byte at 0 and start clear operation at address 1.
        //
        *(UINT8 *)(0) = 0;
        ZeroMem ((VOID *)1, (UINTN)PcdGet32 (PcdESramMemorySize) - 1);
      } else {
        ZeroMem (
          (VOID *)(UINTN)PcdGet32 (PcdEsramStage1Base),
          (UINTN)PcdGet32 (PcdESramMemorySize)
          );
      }
    }
  }

  //
  // Install PeiReset for PeiResetSystem service
  //
  Status = PeiServicesInstallPpi (&mPpiList[0]);
  ASSERT_EFI_ERROR (Status);

  //
  // Do QNC initialization after MRC
  //
  PeiQNCPostMemInit ();

  Status = PeiServicesInstallPpi (&mPpiStall[0]);
  ASSERT_EFI_ERROR (Status);

  //
  // Set E000/F000 Routing
  //
  RegData32 = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
  RegData32 |= (BIT2|BIT1);
  QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, RegData32);

  if (BootMode == BOOT_IN_RECOVERY_MODE) {
    Status = PeimInitializeRecovery (PeiServices);
    ASSERT_EFI_ERROR (Status);
  } else if (BootMode == BOOT_ON_S3_RESUME) {
    return EFI_SUCCESS;
  } else {
    PeiServicesInstallFvInfoPpi (
      NULL,
      (VOID *) (UINTN) PcdGet32 (PcdFlashFvMainBase),
      PcdGet32 (PcdFlashFvMainSize),
      NULL,
      NULL
      );

    //
    // Publish the FVMAIN FV so the DXE Phase can dispatch drivers from this FV
    // and produce Load File Protocols for UEFI Applications in this FV.
    //
    BuildFvHob (
      PcdGet32 (PcdFlashFvMainBase),
      PcdGet32 (PcdFlashFvMainSize)
      );

    //
    // Publish the Payload FV so the DXE Phase can dispatch drivers from this FV
    // and produce Load File Protocols for UEFI Applications in this FV.
    //
    BuildFvHob (
      PcdGet32 (PcdFlashFvPayloadBase),
      PcdGet32 (PcdFlashFvPayloadSize)
      );
  }

  //
  // Build flash HOB, it's going to be used by GCD and E820 building
  // Map full SPI flash decode range (regardless of smaller SPI flash parts installed)
  //
  BuildResourceDescriptorHob (
    EFI_RESOURCE_FIRMWARE_DEVICE,
    (EFI_RESOURCE_ATTRIBUTE_PRESENT    |
    EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
    EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
    (SIZE_4GB - SIZE_8MB),
    SIZE_8MB
    );

  //
  // Create a CPU hand-off information
  //
  CpuAddressWidth = 32;
  AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
  if (RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {
    AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &RegEax, NULL, NULL, NULL);
    CpuAddressWidth = (UINT8) (RegEax & 0xFF);
  }
  DEBUG ((EFI_D_INFO, "CpuAddressWidth: %d\n", CpuAddressWidth));

  BuildCpuHob (CpuAddressWidth, 16);

  ASSERT_EFI_ERROR (Status);

  return Status;
}
Esempio n. 9
0
/**
  Initialises the FV Header and Variable Store Header
  to support variable operations.

  @param[in]  Ptr - Location to initialise the headers

**/
EFI_STATUS
InitializeFvAndVariableStoreHeaders (
  IN NOR_FLASH_INSTANCE *Instance
  )
{
  EFI_STATUS                          Status;
  VOID*                               Headers;
  UINTN                               HeadersLength;
  EFI_FIRMWARE_VOLUME_HEADER          *FirmwareVolumeHeader;
  VARIABLE_STORE_HEADER               *VariableStoreHeader;

  if (!Instance->Initialized && Instance->Initialize) {
    Instance->Initialize (Instance);
  }

  HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER);
  Headers = AllocateZeroPool(HeadersLength);

  // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous.
  ASSERT(PcdGet32(PcdFlashNvStorageVariableBase) + PcdGet32(PcdFlashNvStorageVariableSize) == PcdGet32(PcdFlashNvStorageFtwWorkingBase));
  ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) == PcdGet32(PcdFlashNvStorageFtwSpareBase));

  // Check if the size of the area is at least one block size
  ASSERT((PcdGet32(PcdFlashNvStorageVariableSize) > 0) && (PcdGet32(PcdFlashNvStorageVariableSize) / Instance->Media.BlockSize > 0));
  ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwWorkingSize) / Instance->Media.BlockSize > 0));
  ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwSpareSize) / Instance->Media.BlockSize > 0));

  // Ensure the Variable area Base Addresses are aligned on a block size boundaries
  ASSERT(PcdGet32(PcdFlashNvStorageVariableBase) % Instance->Media.BlockSize == 0);
  ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) % Instance->Media.BlockSize == 0);
  ASSERT(PcdGet32(PcdFlashNvStorageFtwSpareBase) % Instance->Media.BlockSize == 0);

  //
  // EFI_FIRMWARE_VOLUME_HEADER
  //
  FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Headers;
  CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
  FirmwareVolumeHeader->FvLength =
      PcdGet32(PcdFlashNvStorageVariableSize) +
      PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
      PcdGet32(PcdFlashNvStorageFtwSpareSize);
  FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
  FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) (
                                          EFI_FVB2_READ_ENABLED_CAP   | // Reads may be enabled
                                          EFI_FVB2_READ_STATUS        | // Reads are currently enabled
                                          EFI_FVB2_STICKY_WRITE       | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
                                          EFI_FVB2_MEMORY_MAPPED      | // It is memory mapped
                                          EFI_FVB2_ERASE_POLARITY     | // After erasure all bits take this value (i.e. '1')
                                          EFI_FVB2_WRITE_STATUS       | // Writes are currently enabled
                                          EFI_FVB2_WRITE_ENABLED_CAP    // Writes may be enabled
                                      );
  FirmwareVolumeHeader->HeaderLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY);
  FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
  FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1;
  FirmwareVolumeHeader->BlockMap[0].Length      = Instance->Media.BlockSize;
  FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
  FirmwareVolumeHeader->BlockMap[1].Length      = 0;
  FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16*)FirmwareVolumeHeader,FirmwareVolumeHeader->HeaderLength);

  //
  // VARIABLE_STORE_HEADER
  //
  VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)Headers + FirmwareVolumeHeader->HeaderLength);
  CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid);
  VariableStoreHeader->Size = PcdGet32(PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength;
  VariableStoreHeader->Format            = VARIABLE_STORE_FORMATTED;
  VariableStoreHeader->State             = VARIABLE_STORE_HEALTHY;

  // Install the combined super-header in the NorFlash
  Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);

  FreePool (Headers);
  return Status;
}
Esempio n. 10
0
File: Service.c Progetto: M1cha/edk2
/**
  Get the PCD entry pointer in PCD database.
  
  This routine will visit PCD database to find the PCD entry according to given
  token number. The given token number is autogened by build tools and it will be 
  translated to local token number. Local token number contains PCD's type and 
  offset of PCD entry in PCD database.

  @param TokenNumber     Token's number, it is autogened by build tools
  @param GetSize         The size of token's value

  @return PCD entry pointer in PCD database

**/
VOID *
GetWorker (
  IN UINTN               TokenNumber,
  IN UINTN               GetSize
  )
{
  UINT32              Offset;
  EFI_GUID            *Guid;
  UINT16              *Name;
  VARIABLE_HEAD       *VariableHead;
  EFI_STATUS          Status;
  UINTN               DataSize;
  VOID                *Data;
  UINT8               *StringTable;
  STRING_HEAD         StringTableIdx;
  PEI_PCD_DATABASE    *PeiPcdDb;
  UINT32              LocalTokenNumber;
  UINT32              LocalTokenCount;
  UINT8               *VaraiableDefaultBuffer;

  //
  // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
  // We have to decrement TokenNumber by 1 to make it usable
  // as the array index.
  //
  TokenNumber--;

  PeiPcdDb        = GetPcdDatabase ();
  LocalTokenCount = PeiPcdDb->LocalTokenCount;

  // EBC compiler is very choosy. It may report warning about comparison
  // between UINTN and 0 . So we add 1 in each size of the 
  // comparison.
  ASSERT (TokenNumber + 1 < (LocalTokenCount + 1));

  ASSERT ((GetSize == PeiPcdGetSize(TokenNumber + 1)) || (GetSize == 0));

  LocalTokenNumber = GetLocalTokenNumber (PeiPcdDb, TokenNumber + 1);

  Offset      = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;
  StringTable = (UINT8 *)PeiPcdDb + PeiPcdDb->StringTableOffset;

  switch (LocalTokenNumber & PCD_TYPE_ALL_SET) {
    case PCD_TYPE_VPD:
    {
      VPD_HEAD *VpdHead;
      VpdHead = (VPD_HEAD *) ((UINT8 *)PeiPcdDb + Offset);
      return (VOID *) (UINTN) (PcdGet32 (PcdVpdBaseAddress) + VpdHead->Offset);
    }
      
    case PCD_TYPE_HII|PCD_TYPE_STRING:
    case PCD_TYPE_HII:
    {
      VariableHead = (VARIABLE_HEAD *) ((UINT8 *)PeiPcdDb + Offset);
      
      Guid = (EFI_GUID *) ((UINT8 *)PeiPcdDb + PeiPcdDb->GuidTableOffset) + VariableHead->GuidTableIndex;
      Name = (UINT16*)&StringTable[VariableHead->StringIndex];

      if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {
        //
        // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of 
        // string array in string table.
        //
        VaraiableDefaultBuffer = (UINT8 *) &StringTable[*(STRING_HEAD*)((UINT8*) PeiPcdDb + VariableHead->DefaultValueOffset)];   
      } else {
        VaraiableDefaultBuffer = (UINT8 *) PeiPcdDb + VariableHead->DefaultValueOffset;
      }
      Status = GetHiiVariable (Guid, Name, &Data, &DataSize);
      if ((Status == EFI_SUCCESS) && (DataSize >= (VariableHead->Offset + GetSize))) {
        if (GetSize == 0) {
          //
          // It is a pointer type. So get the MaxSize reserved for
          // this PCD entry.
          //
          GetPtrTypeSize (TokenNumber, &GetSize, PeiPcdDb);
          if (GetSize > (DataSize - VariableHead->Offset)) {
            //
            // Use actual valid size.
            //
            GetSize = DataSize - VariableHead->Offset;
          }
        }
        //
        // If the operation is successful, we copy the data
        // to the default value buffer in the PCD Database.
        //
        CopyMem (VaraiableDefaultBuffer, (UINT8 *) Data + VariableHead->Offset, GetSize);
      }
      return (VOID *) VaraiableDefaultBuffer;
    }

    case PCD_TYPE_DATA:
      return (VOID *) ((UINT8 *)PeiPcdDb + Offset);

    case PCD_TYPE_STRING:
      StringTableIdx = * (STRING_HEAD*) ((UINT8 *) PeiPcdDb + Offset);
      return (VOID *) (&StringTable[StringTableIdx]);

    default:
      ASSERT (FALSE);
      break;
      
  }

  ASSERT (FALSE);
      
  return NULL;
  
}
Esempio n. 11
0
EFI_STATUS
EFIAPI
MemoryDiscoveredPpiNotifyCallback (
  IN EFI_PEI_SERVICES           **PeiServices,
  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
  IN VOID                       *Ppi
  )
{

  EFI_STATUS       Status;
  EFI_BOOT_MODE    BootMode;
  UINT32           Pages;
  VOID*            Memory;
  UINTN            Size;

  //
  // Allocate LM memory and configure PDM if enabled by user.
  // ConfigureLM(PeiServices);
  //
  Status = (*PeiServices)->GetBootMode (
                             (const EFI_PEI_SERVICES **)PeiServices,
                             &BootMode
                             );

  if (BootMode != BOOT_ON_S3_RESUME) {
    Size = (PcdGet32 (PcdFlashFvRecovery2Base) - PcdGet32 (PcdFlashFvMainBase)) + FixedPcdGet32(PcdFlashFvRecovery2Size);
    Pages=  Size/0x1000;

    Memory = AllocatePages ( Pages );
    CopyMem(Memory , (VOID *) FixedPcdGet32(PcdFlashFvMainBase) , Size);

    //
    // We don't verify just load
    //
    PeiServicesInstallFvInfoPpi (
      NULL,
      (VOID *) ((UINTN) Memory + (PcdGet32 (PcdFlashFvRecovery2Base) - PcdGet32 (PcdFlashFvMainBase))),
      PcdGet32 (PcdFlashFvRecovery2Size),
      NULL,
      NULL
      );

    PeiServicesInstallFvInfoPpi (
      NULL,
      (VOID *)  Memory,
      PcdGet32 (PcdFlashFvMainSize),
      NULL,
      NULL
      );

  }

  if (BootMode == BOOT_ON_S3_RESUME) {
    PeiServicesInstallFvInfoPpi (
    NULL,
    (VOID *) (UINTN) (PcdGet32 (PcdFlashFvRecovery2Base)),
    PcdGet32 (PcdFlashFvRecovery2Size),
    NULL,
    NULL
    );
  }

  return EFI_SUCCESS;
}
Esempio n. 12
0
File: Service.c Progetto: M1cha/edk2
/**
  The function registers the CallBackOnSet fucntion
  according to TokenNumber and EFI_GUID space.

  @param  ExTokenNumber       The token number.
  @param  Guid              The GUID space.
  @param  CallBackFunction  The Callback function to be registered.
  @param  Register          To register or unregister the callback function.

  @retval EFI_SUCCESS If the Callback function is registered.
  @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space.
  @retval EFI_OUT_OF_RESOURCES If the callback function can't be registered because there is not free
                                slot left in the CallbackFnTable.
  @retval EFI_INVALID_PARAMETER If the callback function want to be de-registered can not be found.
**/
EFI_STATUS
PeiRegisterCallBackWorker (
  IN  UINTN                       ExTokenNumber,
  IN  CONST EFI_GUID              *Guid, OPTIONAL
  IN  PCD_PPI_CALLBACK            CallBackFunction,
  IN  BOOLEAN                     Register
)
{
  EFI_HOB_GUID_TYPE       *GuidHob;
  PCD_PPI_CALLBACK        *CallbackTable;
  PCD_PPI_CALLBACK        Compare;
  PCD_PPI_CALLBACK        Assign;
  UINT32                  LocalTokenNumber;
  UINT32                  LocalTokenCount;
  UINTN                   PeiNexTokenNumber;
  UINTN                   TokenNumber;
  UINTN                   Idx;
  PEI_PCD_DATABASE        *PeiPcdDb;

  PeiPcdDb          = GetPcdDatabase();
  LocalTokenCount   = PeiPcdDb->LocalTokenCount;
  PeiNexTokenNumber = PeiPcdDb->LocalTokenCount - PeiPcdDb->ExTokenCount;

  if (Guid == NULL) {
    TokenNumber = ExTokenNumber;
    //
    // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
    // We have to decrement TokenNumber by 1 to make it usable
    // as the array index.
    //
    TokenNumber--;
    ASSERT (TokenNumber + 1 < (PeiNexTokenNumber + 1));
  } else {
    TokenNumber = GetExPcdTokenNumber (Guid, ExTokenNumber);
    if (TokenNumber == PCD_INVALID_TOKEN_NUMBER) {
      return EFI_NOT_FOUND;
    }
    //
    // TokenNumber Zero is reserved as PCD_INVALID_TOKEN_NUMBER.
    // We have to decrement TokenNumber by 1 to make it usable
    // as the array index.
    //
    TokenNumber--;
    // EBC compiler is very choosy. It may report warning about comparison
    // between UINTN and 0 . So we add 1 in each size of the 
    // comparison.
    ASSERT ((TokenNumber + 1) < (LocalTokenCount + 1));
  }


  LocalTokenNumber = *((UINT32 *)((UINT8 *)PeiPcdDb + PeiPcdDb->LocalTokenNumberTableOffset) + TokenNumber);

  //
  // We don't support SET for HII and VPD type PCD entry in PEI phase.
  // So we will assert if any register callback for such PCD entry.
  //
  ASSERT ((LocalTokenNumber & PCD_TYPE_HII) == 0);
  ASSERT ((LocalTokenNumber & PCD_TYPE_VPD) == 0);

  GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
  ASSERT (GuidHob != NULL);
  
  CallbackTable = GET_GUID_HOB_DATA (GuidHob);
  CallbackTable = CallbackTable + (TokenNumber * PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry));

  Compare = Register? NULL: CallBackFunction;
  Assign  = Register? CallBackFunction: NULL;


  for (Idx = 0; Idx < PcdGet32 (PcdMaxPeiPcdCallBackNumberPerPcdEntry); Idx++) {
    if (CallbackTable[Idx] == Compare) {
      CallbackTable[Idx] = Assign;
      return EFI_SUCCESS;
    }
  }

  return Register? EFI_OUT_OF_RESOURCES : EFI_INVALID_PARAMETER;

}
Esempio n. 13
0
/**
  Function to Copy one file to another location

  If the destination exists the user will be prompted and the result put into *resp

  @param[in] Source     pointer to source file name
  @param[in] Dest       pointer to destination file name
  @param[out] Resp      pointer to response from question.  Pass back on looped calling
  @param[in] SilentMode whether to run in quiet mode or not
  @param[in] CmdName    Source command name requesting single file copy

  @retval SHELL_SUCCESS   The source file was copied to the destination
**/
SHELL_STATUS
CopySingleFile(
  IN CONST CHAR16 *Source,
  IN CONST CHAR16 *Dest,
  OUT VOID        **Resp,
  IN BOOLEAN      SilentMode,
  IN CONST CHAR16 *CmdName
  )
{
  VOID                  *Response;
  UINTN                 ReadSize;
  SHELL_FILE_HANDLE     SourceHandle;
  SHELL_FILE_HANDLE     DestHandle;
  EFI_STATUS            Status;
  VOID                  *Buffer;
  CHAR16                *TempName;
  UINTN                 Size;
  EFI_SHELL_FILE_INFO   *List;
  SHELL_STATUS          ShellStatus;
  UINT64                SourceFileSize;
  UINT64                DestFileSize;
  EFI_FILE_PROTOCOL     *DestVolumeFP;
  EFI_FILE_SYSTEM_INFO  *DestVolumeInfo;
  UINTN                 DestVolumeInfoSize;

  ASSERT(Resp != NULL);

  SourceHandle    = NULL;
  DestHandle      = NULL;
  Response        = *Resp;
  List            = NULL;
  DestVolumeInfo  = NULL;
  ShellStatus     = SHELL_SUCCESS;

  ReadSize = PcdGet32(PcdShellFileOperationSize);
  // Why bother copying a file to itself
  if (StrCmp(Source, Dest) == 0) {
    return (SHELL_SUCCESS);
  }

  //
  // if the destination file existed check response and possibly prompt user
  //
  if (ShellFileExists(Dest) == EFI_SUCCESS) {
    if (Response == NULL && !SilentMode) {
      Status = ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response);
    }
    //
    // possibly return based on response
    //
    if (!SilentMode) {
      switch (*(SHELL_PROMPT_RESPONSE*)Response) {
        case ShellPromptResponseNo:
          //
          // return success here so we dont stop the process
          //
          return (SHELL_SUCCESS);
        case ShellPromptResponseCancel:
          *Resp = Response;
          //
          // indicate to stop everything
          //
          return (SHELL_ABORTED);
        case ShellPromptResponseAll:
          *Resp = Response;
        case ShellPromptResponseYes:
          break;
        default:
          return SHELL_ABORTED;
      }
    }
  }

  if (ShellIsDirectory(Source) == EFI_SUCCESS) {
    Status = ShellCreateDirectory(Dest, &DestHandle);
    if (EFI_ERROR(Status)) {
      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_DIR_FAIL), gShellLevel2HiiHandle, CmdName, Dest);  
      return (SHELL_ACCESS_DENIED);
    }

    //
    // Now copy all the files under the directory...
    //
    TempName    = NULL;
    Size        = 0;
    StrnCatGrow(&TempName, &Size, Source, 0);
    StrnCatGrow(&TempName, &Size, L"\\*", 0);
    if (TempName != NULL) {
      ShellOpenFileMetaArg((CHAR16*)TempName, EFI_FILE_MODE_READ, &List);
      *TempName = CHAR_NULL;
      StrnCatGrow(&TempName, &Size, Dest, 0);
      StrnCatGrow(&TempName, &Size, L"\\", 0);
      ShellStatus = ValidateAndCopyFiles(List, TempName, SilentMode, TRUE, Resp);
      ShellCloseFileMetaArg(&List);
      SHELL_FREE_NON_NULL(TempName);
      Size = 0;
    }
  } else {
    Status = ShellDeleteFileByName(Dest);

    //
    // open file with create enabled
    //
    Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
    if (EFI_ERROR(Status)) {
      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_OPEN_FAIL), gShellLevel2HiiHandle, CmdName, Dest);  
      return (SHELL_ACCESS_DENIED);
    }

    //
    // open source file
    //
    Status = ShellOpenFileByName (Source, &SourceHandle, EFI_FILE_MODE_READ, 0);
    if (EFI_ERROR (Status)) {
      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_SRC_OPEN_FAIL), gShellLevel2HiiHandle, CmdName, Source);
      return (SHELL_ACCESS_DENIED);
    }

    //
    //get file size of source file and freespace available on destination volume
    //
    ShellGetFileSize(SourceHandle, &SourceFileSize);
    ShellGetFileSize(DestHandle, &DestFileSize);

    //
    //if the destination file already exists then it will be replaced, meaning the sourcefile effectively needs less storage space
    //
    if(DestFileSize < SourceFileSize){
      SourceFileSize -= DestFileSize;
    } else {
      SourceFileSize = 0;
    }

    //
    //get the system volume info to check the free space
    //
    DestVolumeFP = ConvertShellHandleToEfiFileProtocol(DestHandle);
    DestVolumeInfo = NULL;
    DestVolumeInfoSize = 0;
    Status = DestVolumeFP->GetInfo(
      DestVolumeFP,
      &gEfiFileSystemInfoGuid,
      &DestVolumeInfoSize,
      DestVolumeInfo
      );

    if (Status == EFI_BUFFER_TOO_SMALL) {
      DestVolumeInfo = AllocateZeroPool(DestVolumeInfoSize);
      Status = DestVolumeFP->GetInfo(
        DestVolumeFP,
        &gEfiFileSystemInfoGuid,
        &DestVolumeInfoSize,
        DestVolumeInfo
        );
    }

    //
    //check if enough space available on destination drive to complete copy
    //
    if (DestVolumeInfo!= NULL && (DestVolumeInfo->FreeSpace < SourceFileSize)) {
      //
      //not enough space on destination directory to copy file
      //
      SHELL_FREE_NON_NULL(DestVolumeInfo);
      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_FAIL), gShellLevel2HiiHandle, CmdName);  
      return(SHELL_VOLUME_FULL);
    } else {
      //
      // copy data between files
      //
      Buffer = AllocateZeroPool(ReadSize);
      if (Buffer == NULL) {
        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, CmdName);
        return SHELL_OUT_OF_RESOURCES;
      }
      while (ReadSize == PcdGet32(PcdShellFileOperationSize) && !EFI_ERROR(Status)) {
        Status = ShellReadFile(SourceHandle, &ReadSize, Buffer);
        if (!EFI_ERROR(Status)) {
          Status = ShellWriteFile(DestHandle, &ReadSize, Buffer);
          if (EFI_ERROR(Status)) {
            ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT));
            ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_WRITE_ERROR), gShellLevel2HiiHandle, CmdName, Dest);   
            break;
          }
        } else {
          ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT));
          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_READ_ERROR), gShellLevel2HiiHandle, CmdName, Source);  
          break;
        }
      }
    }
    SHELL_FREE_NON_NULL(DestVolumeInfo);
  }
  
  //
  // close files
  //
  if (DestHandle != NULL) {
    ShellCloseFile(&DestHandle);
    DestHandle   = NULL;
  }
  if (SourceHandle != NULL) {
    ShellCloseFile(&SourceHandle);
    SourceHandle = NULL;
  }

  //
  // return
  //
  return ShellStatus;
}
/**
  The module Entry Point of the Firmware Performance Data Table DXE driver.

  @param[in]  ImageHandle    The firmware allocated handle for the EFI image.
  @param[in]  SystemTable    A pointer to the EFI System Table.

  @retval EFI_SUCCESS    The entry point is executed successfully.
  @retval Other          Some error occurs when executing this entry point.

**/
EFI_STATUS
EFIAPI
FirmwarePerformanceDxeEntryPoint (
  IN EFI_HANDLE          ImageHandle,
  IN EFI_SYSTEM_TABLE    *SystemTable
  )
{
  EFI_STATUS               Status;
  EFI_HOB_GUID_TYPE        *GuidHob;
  FIRMWARE_SEC_PERFORMANCE *Performance;
  VOID                     *Registration;
  UINT64                   OemTableId;

  CopyMem (
    mFirmwarePerformanceTableTemplate.Header.OemId,
    PcdGetPtr (PcdAcpiDefaultOemId),
    sizeof (mFirmwarePerformanceTableTemplate.Header.OemId)
    );
  OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
  CopyMem (&mFirmwarePerformanceTableTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
  mFirmwarePerformanceTableTemplate.Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
  mFirmwarePerformanceTableTemplate.Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
  mFirmwarePerformanceTableTemplate.Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);

  //
  // Get Report Status Code Handler Protocol.
  //
  Status = gBS->LocateProtocol (&gEfiRscHandlerProtocolGuid, NULL, (VOID **) &mRscHandlerProtocol);
  ASSERT_EFI_ERROR (Status);

  //
  // Register report status code listener for OS Loader load and start.
  //
  Status = mRscHandlerProtocol->Register (FpdtStatusCodeListenerDxe, TPL_HIGH_LEVEL);
  ASSERT_EFI_ERROR (Status);

  //
  // Register the notify function to update FPDT on ExitBootServices Event.
  //
  Status = gBS->CreateEventEx (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  FpdtExitBootServicesEventNotify,
                  NULL,
                  &gEfiEventExitBootServicesGuid,
                  &mExitBootServicesEvent
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Create ready to boot event to install ACPI FPDT table.
  //
  Status = gBS->CreateEventEx (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  FpdtReadyToBootEventNotify,
                  NULL,
                  &gEfiEventReadyToBootGuid,
                  &mReadyToBootEvent
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Retrieve GUID HOB data that contains the ResetEnd.
  //
  GuidHob = GetFirstGuidHob (&gEfiFirmwarePerformanceGuid);
  if (GuidHob != NULL) {
    Performance = (FIRMWARE_SEC_PERFORMANCE *) GET_GUID_HOB_DATA (GuidHob);
    mBootPerformanceTableTemplate.BasicBoot.ResetEnd = Performance->ResetEnd;
  } else {
    //
    // SEC Performance Data Hob not found, ResetEnd in ACPI FPDT table will be 0.
    //
    DEBUG ((EFI_D_ERROR, "FPDT: WARNING: SEC Performance Data Hob not found, ResetEnd will be set to 0!\n"));
  }

  if (FeaturePcdGet (PcdFirmwarePerformanceDataTableS3Support)) {
    //
    // Register callback function upon VariableArchProtocol and LockBoxProtocol
    // to allocate S3 performance table memory and save the pointer to LockBox.
    //
    EfiCreateProtocolNotifyEvent (
      &gEfiVariableArchProtocolGuid,
      TPL_CALLBACK,
      FpdtAllocateS3PerformanceTableMemory,
      NULL,
      &Registration
      );
    EfiCreateProtocolNotifyEvent (
      &gEfiLockBoxProtocolGuid,
      TPL_CALLBACK,
      FpdtAllocateS3PerformanceTableMemory,
      NULL,
      &Registration
      );
  } else {
    //
    // Exclude S3 Performance Table Pointer from FPDT table template.
    //
    mFirmwarePerformanceTableTemplate.Header.Length -= sizeof (EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_POINTER_RECORD);
  }

  return EFI_SUCCESS;
}
Esempio n. 15
0
EFI_STATUS
EFIAPI
PeimInitializeWinNtFwh (
  IN EFI_FFS_FILE_HEADER       *FfsHeader,
  IN EFI_PEI_SERVICES          **PeiServices
  )
/*++

Routine Description:
  Perform a call-back into the SEC simulator to get address of the Firmware Hub

Arguments:
  FfsHeader   - Ffs Header available to every PEIM
  PeiServices - General purpose services available to every PEIM.
    
Returns:
  None

--*/
{
  EFI_STATUS                  Status;
  EFI_PEI_PPI_DESCRIPTOR      *PpiDescriptor;
  NT_FWH_PPI                  *FwhPpi;
  EFI_PHYSICAL_ADDRESS        FdBase;
  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
  UINT64                      FdSize;
  UINTN                       Index;

  DEBUG ((EFI_D_ERROR, "NT 32 Firmware Volume PEIM Loaded\n"));

  //
  // Get the Fwh Information PPI
  //
  Status = (**PeiServices).LocatePpi (
                            (const EFI_PEI_SERVICES **)PeiServices,
                            &gNtFwhPpiGuid, // GUID
                            0,              // INSTANCE
                            &PpiDescriptor, // EFI_PEI_PPI_DESCRIPTOR
                            (VOID**)&FwhPpi         // PPI
                            );
  ASSERT_EFI_ERROR (Status);

  Index = 0;
  do {
    //
    // Get information about all the FD's in the system
    //
    Status = FwhPpi->NtFwh (Index, &FdBase, &FdSize);
    if (!EFI_ERROR (Status)) {
      //
      // Assume the FD starts with an FV header
      //
      FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FdBase;

      //
      // Make an FV Hob for the first FV in the FD
      //
      BuildFvHob (FdBase, FvHeader->FvLength);

      if (Index == 0) {
        //
        // Assume the first FD was produced by the NT32.DSC
        //  All these strange offests are needed to keep in
        //  sync with the FlashMap and NT32.dsc file
        //
        BuildResourceDescriptorHob (
          EFI_RESOURCE_FIRMWARE_DEVICE,
          (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
          FdBase,
          ( 
            FvHeader->FvLength + 
            PcdGet32 (PcdFlashNvStorageVariableSize) +
            PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
            PcdGet32 (PcdFlashNvStorageFtwSpareSize) +
            PcdGet32 (PcdWinNtFlashNvStorageEventLogSize)
          )
          );
        //
        // Hard code the address of the spare block and variable services.
        //  Assume it's a hard coded offset from FV0 in FD0.
        //
        FdSize  = 
          PcdGet32 (PcdFlashNvStorageVariableSize) +
          PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
          PcdGet32 (PcdFlashNvStorageFtwSpareSize) +
          PcdGet32 (PcdWinNtFlashNvStorageEventLogSize);

        BuildFvHob (FdBase + PcdGet32 (PcdWinNtFlashNvStorageVariableBase), FdSize);
      } else {
        //
        // For other FD's just map them in.
        //
        BuildResourceDescriptorHob (
          EFI_RESOURCE_FIRMWARE_DEVICE,
          (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE),
          FdBase,
          FdSize
          );
      }
    }

    Index++;
  } while (!EFI_ERROR (Status));

  return Status;
}
Esempio n. 16
0
/**
  Publish TPM2 ACPI table

  @retval   EFI_SUCCESS     The TPM2 ACPI table is published successfully.
  @retval   Others          The TPM2 ACPI table is not published.

**/
EFI_STATUS
PublishTpm2 (
  VOID
  )
{
  EFI_STATUS                     Status;
  EFI_ACPI_TABLE_PROTOCOL        *AcpiTable;
  UINTN                          TableKey;
  UINT64                         OemTableId;
  EFI_TPM2_ACPI_CONTROL_AREA     *ControlArea;
  PTP_INTERFACE_TYPE             InterfaceType;

  //
  // Measure to PCR[0] with event EV_POST_CODE ACPI DATA
  //
  TpmMeasureAndLogData(
    0,
    EV_POST_CODE,
    EV_POSTCODE_INFO_ACPI_DATA,
    ACPI_DATA_LEN,
    &mTpm2AcpiTemplate,
    sizeof(mTpm2AcpiTemplate)
    );

  InterfaceType = GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
  switch (InterfaceType) {
  case PtpInterfaceCrb:
    mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE;
    mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40;
    ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;
    ControlArea->CommandSize  = 0xF80;
    ControlArea->ResponseSize = 0xF80;
    ControlArea->Command      = PcdGet64 (PcdTpmBaseAddress) + 0x80;
    ControlArea->Response     = PcdGet64 (PcdTpmBaseAddress) + 0x80;
    break;
  case PtpInterfaceFifo:
  case PtpInterfaceTis:
    break;
  default:
    DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));
    break;
  }

  CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));
  OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
  CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
  mTpm2AcpiTemplate.Header.OemRevision      = PcdGet32 (PcdAcpiDefaultOemRevision);
  mTpm2AcpiTemplate.Header.CreatorId        = PcdGet32 (PcdAcpiDefaultCreatorId);
  mTpm2AcpiTemplate.Header.CreatorRevision  = PcdGet32 (PcdAcpiDefaultCreatorRevision);

  //
  // Construct ACPI table
  //
  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
  ASSERT_EFI_ERROR (Status);

  Status = AcpiTable->InstallAcpiTable (
                        AcpiTable,
                        &mTpm2AcpiTemplate,
                        sizeof(mTpm2AcpiTemplate),
                        &TableKey
                        );
  ASSERT_EFI_ERROR (Status);

  return Status;
}
Esempio n. 17
0
VOID
MemMapInitialization (
  VOID
  )
{
  //
  // Create Memory Type Information HOB
  //
  BuildGuidDataHob (
    &gEfiMemoryTypeInformationGuid,
    mDefaultMemoryTypeInformation,
    sizeof(mDefaultMemoryTypeInformation)
    );

  //
  // Add PCI IO Port space available for PCI resource allocations.
  //
  BuildResourceDescriptorHob (
    EFI_RESOURCE_IO,
    EFI_RESOURCE_ATTRIBUTE_PRESENT     |
    EFI_RESOURCE_ATTRIBUTE_INITIALIZED,
    PcdGet64 (PcdPciIoBase),
    PcdGet64 (PcdPciIoSize)
    );

  //
  // Video memory + Legacy BIOS region
  //
  AddIoMemoryRangeHob (0x0A0000, BASE_1MB);

  if (!mXen) {
    UINT32  TopOfLowRam;
    UINT64  PciExBarBase;
    UINT32  PciBase;
    UINT32  PciSize;

    TopOfLowRam = GetSystemMemorySizeBelow4gb ();
    PciExBarBase = 0;
    if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
      //
      // The MMCONFIG area is expected to fall between the top of low RAM and
      // the base of the 32-bit PCI host aperture.
      //
      PciExBarBase = FixedPcdGet64 (PcdPciExpressBaseAddress);
      ASSERT (TopOfLowRam <= PciExBarBase);
      ASSERT (PciExBarBase <= MAX_UINT32 - SIZE_256MB);
      PciBase = (UINT32)(PciExBarBase + SIZE_256MB);
    } else {
      PciBase = (TopOfLowRam < BASE_2GB) ? BASE_2GB : TopOfLowRam;
    }

    //
    // address       purpose   size
    // ------------  --------  -------------------------
    // max(top, 2g)  PCI MMIO  0xFC000000 - max(top, 2g)
    // 0xFC000000    gap                           44 MB
    // 0xFEC00000    IO-APIC                        4 KB
    // 0xFEC01000    gap                         1020 KB
    // 0xFED00000    HPET                           1 KB
    // 0xFED00400    gap                          111 KB
    // 0xFED1C000    gap (PIIX4) / RCRB (ICH9)     16 KB
    // 0xFED20000    gap                          896 KB
    // 0xFEE00000    LAPIC                          1 MB
    //
    PciSize = 0xFC000000 - PciBase;
    AddIoMemoryBaseSizeHob (PciBase, PciSize);
    PcdSet64 (PcdPciMmio32Base, PciBase);
    PcdSet64 (PcdPciMmio32Size, PciSize);
    AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB);
    AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB);
    if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
      AddIoMemoryBaseSizeHob (ICH9_ROOT_COMPLEX_BASE, SIZE_16KB);
      //
      // Note: there should be an
      //
      //   AddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB);
      //
      // call below, just like the one above for RCBA. However, Linux insists
      // that the MMCONFIG area be marked in the E820 or UEFI memory map as
      // "reserved memory" -- Linux does not content itself with a simple gap
      // in the memory map wherever the MCFG ACPI table points to.
      //
      // This appears to be a safety measure. The PCI Firmware Specification
      // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can
      // *optionally* be returned in [...] EFIGetMemoryMap as reserved memory
      // [...]". (Emphasis added here.)
      //
      // Normally we add memory resource descriptor HOBs in
      // QemuInitializeRam(), and pre-allocate from those with memory
      // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area
      // is most definitely not RAM; so, as an exception, cover it with
      // uncacheable reserved memory right here.
      //
      AddReservedMemoryBaseSizeHob (PciExBarBase, SIZE_256MB, FALSE);
      BuildMemoryAllocationHob (PciExBarBase, SIZE_256MB,
        EfiReservedMemoryType);
    }
    AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB);
  }
}
Esempio n. 18
0
/**
  The module Entry Point of the CPU SMM driver.

  @param  ImageHandle    The firmware allocated handle for the EFI image.
  @param  SystemTable    A pointer to the EFI System Table.

  @retval EFI_SUCCESS    The entry point is executed successfully.
  @retval Other          Some error occurs when executing this entry point.

**/
EFI_STATUS
EFIAPI
PiCpuSmmEntry (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS                 Status;
  EFI_MP_SERVICES_PROTOCOL   *MpServices;
  UINTN                      NumberOfEnabledProcessors;
  UINTN                      Index;
  VOID                       *Buffer;
  UINTN                      BufferPages;
  UINTN                      TileCodeSize;
  UINTN                      TileDataSize;
  UINTN                      TileSize;
  UINT8                      *Stacks;
  VOID                       *Registration;
  UINT32                     RegEax;
  UINT32                     RegEdx;
  UINTN                      FamilyId;
  UINTN                      ModelId;
  UINT32                     Cr3;

  //
  // Initialize Debug Agent to support source level debug in SMM code
  //
  InitializeDebugAgent (DEBUG_AGENT_INIT_SMM, NULL, NULL);

  //
  // Report the start of CPU SMM initialization.
  //
  REPORT_STATUS_CODE (
    EFI_PROGRESS_CODE,
    EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_PC_SMM_INIT
    );

  //
  // Fix segment address of the long-mode-switch jump
  //
  if (sizeof (UINTN) == sizeof (UINT64)) {
    gSmmJmpAddr.Segment = LONG_MODE_CODE_SEGMENT;
  }

  //
  // Find out SMRR Base and SMRR Size
  //
  FindSmramInfo (&mCpuHotPlugData.SmrrBase, &mCpuHotPlugData.SmrrSize);

  //
  // Get MP Services Protocol
  //
  Status = SystemTable->BootServices->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices);
  ASSERT_EFI_ERROR (Status);

  //
  // Use MP Services Protocol to retrieve the number of processors and number of enabled processors
  //
  Status = MpServices->GetNumberOfProcessors (MpServices, &mNumberOfCpus, &NumberOfEnabledProcessors);
  ASSERT_EFI_ERROR (Status);
  ASSERT (mNumberOfCpus <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber));

  //
  // If support CPU hot plug, PcdCpuSmmEnableBspElection should be set to TRUE.
  // A constant BSP index makes no sense because it may be hot removed.
  //
  DEBUG_CODE (
    if (FeaturePcdGet (PcdCpuHotPlugSupport)) {

      ASSERT (FeaturePcdGet (PcdCpuSmmEnableBspElection));
    }
  );
Esempio n. 19
0
/** Perform USB erratas after MRC init.

**/
VOID
PlatformUsbErratasPostMrc (
  VOID
  )
{
  UINT32                            Index;
  UINT32                            TempBar0Addr;
  UINT16                            SaveCmdReg;
  UINT32                            SaveBar0Reg;

  TempBar0Addr = PcdGet32(PcdPeiQNCUsbControllerMemoryBaseAddress);

  //
  // Apply EHCI controller erratas.
  //
  for (Index = 0; Index < IOH_MAX_EHCI_USB_CONTROLLERS; Index++, TempBar0Addr += IOH_USB_CONTROLLER_MMIO_RANGE) {

    if ((PciRead16 (IohEhciPciReg[Index] + R_IOH_USB_VENDOR_ID)) != V_IOH_USB_VENDOR_ID) {
      continue;  // Device not enabled, skip.
    }

    //
    // Save current settings for PCI CMD/BAR0 registers
    //
    SaveCmdReg = PciRead16 (IohEhciPciReg[Index] + R_IOH_USB_COMMAND);
    SaveBar0Reg = PciRead32 (IohEhciPciReg[Index] + R_IOH_USB_MEMBAR);

    //
    // Temp. assign base address register, Enable Memory Space.
    //
    PciWrite32 ((IohEhciPciReg[Index] + R_IOH_USB_MEMBAR), TempBar0Addr);
    PciWrite16 (IohEhciPciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg | B_IOH_USB_COMMAND_MSE);


    //
    // Set packet buffer OUT/IN thresholds.
    //
    MmioAndThenOr32 (
      TempBar0Addr + R_IOH_EHCI_INSNREG01,
      (UINT32) (~(B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_MASK | B_IOH_EHCI_INSNREG01_IN_THRESHOLD_MASK)),
      (UINT32) ((EHCI_OUT_THRESHOLD_VALUE << B_IOH_EHCI_INSNREG01_OUT_THRESHOLD_BP) | (EHCI_IN_THRESHOLD_VALUE << B_IOH_EHCI_INSNREG01_IN_THRESHOLD_BP))
      );

    //
    // Restore settings for PCI CMD/BAR0 registers
    //
    PciWrite32 ((IohEhciPciReg[Index] + R_IOH_USB_MEMBAR), SaveBar0Reg);
    PciWrite16 (IohEhciPciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg);
  }

  //
  // Apply USB device controller erratas.
  //
  for (Index = 0; Index < IOH_MAX_USBDEVICE_USB_CONTROLLERS; Index++, TempBar0Addr += IOH_USB_CONTROLLER_MMIO_RANGE) {

    if ((PciRead16 (IohUsbDevicePciReg[Index] + R_IOH_USB_VENDOR_ID)) != V_IOH_USB_VENDOR_ID) {
      continue;  // Device not enabled, skip.
    }

    //
    // Save current settings for PCI CMD/BAR0 registers
    //
    SaveCmdReg = PciRead16 (IohUsbDevicePciReg[Index] + R_IOH_USB_COMMAND);
    SaveBar0Reg = PciRead32 (IohUsbDevicePciReg[Index] + R_IOH_USB_MEMBAR);

    //
    // Temp. assign base address register, Enable Memory Space.
    //
    PciWrite32 ((IohUsbDevicePciReg[Index] + R_IOH_USB_MEMBAR), TempBar0Addr);
    PciWrite16 (IohUsbDevicePciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg | B_IOH_USB_COMMAND_MSE);

    //
    // Erratas for USB Device interrupt registers.
    //

    //
    // 1st Mask interrupts.
    //
    MmioWrite32 (
      TempBar0Addr + R_IOH_USBDEVICE_D_INTR_MSK_UDC_REG,
      V_IOH_USBDEVICE_D_INTR_MSK_UDC_REG
      );
    //
    // 2nd RW/1C of equivalent status bits.
    //
    MmioWrite32 (
      TempBar0Addr + R_IOH_USBDEVICE_D_INTR_UDC_REG,
      V_IOH_USBDEVICE_D_INTR_MSK_UDC_REG
      );

    //
    // 1st Mask end point interrupts.
    //
    MmioWrite32 (
      TempBar0Addr + R_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG,
      V_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG
      );
    //
    // 2nd RW/1C of equivalent end point status bits.
    //
    MmioWrite32 (
      TempBar0Addr + R_IOH_USBDEVICE_EP_INTR_UDC_REG,
      V_IOH_USBDEVICE_EP_INTR_MSK_UDC_REG
      );

    //
    // Restore settings for PCI CMD/BAR0 registers
    //
    PciWrite32 ((IohUsbDevicePciReg[Index] + R_IOH_USB_MEMBAR), SaveBar0Reg);
    PciWrite16 (IohUsbDevicePciReg[Index] + R_IOH_USB_COMMAND, SaveCmdReg);
  }
}
Esempio n. 20
0
/*++

Routine Description:



Arguments:

  FileHandle  - Handle of the file being invoked.
  PeiServices - Describes the list of possible PEI Services.

Returns:

  Status -  EFI_SUCCESS if the boot mode could be set

--*/
EFI_STATUS
EFIAPI
MemoryPeim (
  IN EFI_PHYSICAL_ADDRESS               UefiMemoryBase,
  IN UINT64                             UefiMemorySize
  )
{
  EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes;
  UINT64                      ResourceLength;
  EFI_PEI_HOB_POINTERS        NextHob;
  EFI_PHYSICAL_ADDRESS        FdTop;
  EFI_PHYSICAL_ADDRESS        SystemMemoryTop;
  EFI_PHYSICAL_ADDRESS        ResourceTop;
  BOOLEAN                     Found;

  // Ensure PcdSystemMemorySize has been set
  ASSERT (PcdGet32 (PcdSystemMemorySize) != 0);

  //
  // Now, the permanent memory has been installed, we can call AllocatePages()
  //
  ResourceAttributes = (
      EFI_RESOURCE_ATTRIBUTE_PRESENT |
      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
      EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
      EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
      EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
      EFI_RESOURCE_ATTRIBUTE_TESTED
  );

  // Reserved the memory space occupied by the firmware volume
  BuildResourceDescriptorHob (
      EFI_RESOURCE_SYSTEM_MEMORY,
      ResourceAttributes,
      PcdGet32 (PcdSystemMemoryBase),
      PcdGet32 (PcdSystemMemorySize)
  );

  SystemMemoryTop = PcdGet32 (PcdSystemMemoryBase) + PcdGet32 (PcdSystemMemorySize);
  FdTop = PcdGet32(PcdFdBaseAddress) + PcdGet32(PcdFdSize);

  // EDK2 does not have the concept of boot firmware copied into DRAM. To avoid the DXE
  // core to overwrite this area we must mark the region with the attribute non-present
  if ((PcdGet32 (PcdFdBaseAddress) >= PcdGet32 (PcdSystemMemoryBase)) && (FdTop <= SystemMemoryTop)) {
    Found = FALSE;

    // Search for System Memory Hob that contains the firmware
    NextHob.Raw = GetHobList ();
    while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) {
      if ((NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
          (PcdGet32(PcdFdBaseAddress) >= NextHob.ResourceDescriptor->PhysicalStart) &&
          (FdTop <= NextHob.ResourceDescriptor->PhysicalStart + NextHob.ResourceDescriptor->ResourceLength))
      {
        ResourceAttributes = NextHob.ResourceDescriptor->ResourceAttribute;
        ResourceLength = NextHob.ResourceDescriptor->ResourceLength;
        ResourceTop = NextHob.ResourceDescriptor->PhysicalStart + ResourceLength;

        if (PcdGet32(PcdFdBaseAddress) == NextHob.ResourceDescriptor->PhysicalStart) {
          if (SystemMemoryTop == FdTop) {
            NextHob.ResourceDescriptor->ResourceAttribute = ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT;
          } else {
            // Create the System Memory HOB for the firmware with the non-present attribute
            BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
                                        ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT,
                                        PcdGet32(PcdFdBaseAddress),
                                        PcdGet32(PcdFdSize));

            // Top of the FD is system memory available for UEFI
            NextHob.ResourceDescriptor->PhysicalStart += PcdGet32(PcdFdSize);
            NextHob.ResourceDescriptor->ResourceLength -= PcdGet32(PcdFdSize);
          }
        } else {
          // Create the System Memory HOB for the firmware with the non-present attribute
          BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
                                      ResourceAttributes & ~EFI_RESOURCE_ATTRIBUTE_PRESENT,
                                      PcdGet32(PcdFdBaseAddress),
                                      PcdGet32(PcdFdSize));

          // Update the HOB
          NextHob.ResourceDescriptor->ResourceLength = PcdGet32(PcdFdBaseAddress) - NextHob.ResourceDescriptor->PhysicalStart;

          // If there is some memory available on the top of the FD then create a HOB
          if (FdTop < NextHob.ResourceDescriptor->PhysicalStart + ResourceLength) {
            // Create the System Memory HOB for the remaining region (top of the FD)
            BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY,
                                        ResourceAttributes,
                                        FdTop,
                                        ResourceTop - FdTop);
          }
        }
        Found = TRUE;
        break;
      }
      NextHob.Raw = GET_NEXT_HOB (NextHob);
    }

    ASSERT(Found);
  }

  // Build Memory Allocation Hob
  InitMmu ();

  if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) {
    // Optional feature that helps prevent EFI memory map fragmentation.
    BuildMemoryTypeInformationHob ();
  }

  return EFI_SUCCESS;
}
/**
  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);
      }

      //
      // Fixup for PeiService's address
      //
      SetPeiServicesTablePointer ((CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);

      //
      // Initialize libraries that the PEI Core is linked against
      //
      ProcessLibraryConstructorList (NULL, (CONST EFI_PEI_SERVICES **)&OldCoreData->Ps);

      //
      // Update HandOffHob for new installed permanent 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 MemoryBaseAddress in memory allocation HOBs
      //
      ConvertMemoryAllocationHobs (OldCoreData);

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

      //
      // After the whole temporary memory is migrated, then we can allocate page in
      // permanent 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();

      UNREACHABLE ();
    }
Esempio n. 22
0
/**
  Determine whether a given device path is valid.

  @param  DevicePath  A pointer to a device path data structure.
  @param  MaxSize     The maximum size of the device path data structure.

  @retval TRUE        DevicePath is valid.
  @retval FALSE       DevicePath is NULL.
  @retval FALSE       Maxsize is less than sizeof(EFI_DEVICE_PATH_PROTOCOL).
  @retval FALSE       The length of any node node in the DevicePath is less
                      than sizeof (EFI_DEVICE_PATH_PROTOCOL).
  @retval FALSE       If MaxSize is not zero, the size of the DevicePath
                      exceeds MaxSize.
  @retval FALSE       If PcdMaximumDevicePathNodeCount is not zero, the node
                      count of the DevicePath exceeds PcdMaximumDevicePathNodeCount.
**/
BOOLEAN
EFIAPI
IsDevicePathValid (
  IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
  IN       UINTN                    MaxSize
  )
{
  UINTN Count;
  UINTN Size;
  UINTN NodeLength;

  //
  //Validate the input whether exists and its size big enough to touch the first node
  //
  if (DevicePath == NULL || (MaxSize > 0 && MaxSize < END_DEVICE_PATH_LENGTH)) {
    return FALSE;
  }

  if (MaxSize == 0) {
    MaxSize = MAX_UINTN;
  }

  for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) {
    NodeLength = DevicePathNodeLength (DevicePath);
    if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
      return FALSE;
    }

    if (NodeLength > MAX_UINTN - Size) {
      return FALSE;
    }
    Size += NodeLength;

    //
    // Validate next node before touch it.
    //
    if (Size > MaxSize - END_DEVICE_PATH_LENGTH ) {
      return FALSE;
    }

    if (PcdGet32 (PcdMaximumDevicePathNodeCount) > 0) {
      Count++;
      if (Count >= PcdGet32 (PcdMaximumDevicePathNodeCount)) {
        return FALSE;
      }
    }

    //
    // FilePath must be a NULL-terminated string.
    //
    if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH &&
        DevicePathSubType (DevicePath) == MEDIA_FILEPATH_DP &&
        *(CHAR16 *)((UINT8 *)DevicePath + NodeLength - 2) != 0) {
      return FALSE;
    }
  }

  //
  // Only return TRUE when the End Device Path node is valid.
  //
  return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH);
}
Esempio n. 23
0
/**
  Initial the boot mode related parameters.

**/
VOID
BmInitialBootModeInfo (
  VOID
  )
{
  EFI_STATUS                         Status;
  EFI_GRAPHICS_OUTPUT_PROTOCOL       *GraphicsOutput;
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *SimpleTextOut;
  UINTN                              BootTextColumn;
  UINTN                              BootTextRow;

  if (mBmModeInitialized) {
    return;
  }

  //
  // After the console is ready, get current video resolution
  // and text mode before launching setup at first time.
  //
  Status = gBS->HandleProtocol (
                  gST->ConsoleOutHandle,
                  &gEfiGraphicsOutputProtocolGuid,
                  (VOID**)&GraphicsOutput
                  );
  if (EFI_ERROR (Status)) {
    GraphicsOutput = NULL;
  }

  Status = gBS->HandleProtocol (
                  gST->ConsoleOutHandle,
                  &gEfiSimpleTextOutProtocolGuid,
                  (VOID**)&SimpleTextOut
                  );
  if (EFI_ERROR (Status)) {
    SimpleTextOut = NULL;
  }

  if (GraphicsOutput != NULL) {
    //
    // Get current video resolution and text mode.
    //
    mBmBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
    mBmBootVerticalResolution   = GraphicsOutput->Mode->Info->VerticalResolution;
  }

  if (SimpleTextOut != NULL) {
    Status = SimpleTextOut->QueryMode (
                              SimpleTextOut,
                              SimpleTextOut->Mode->Mode,
                              &BootTextColumn,
                              &BootTextRow
                              );
    mBmBootTextModeColumn = (UINT32)BootTextColumn;
    mBmBootTextModeRow    = (UINT32)BootTextRow;
  }

  //
  // Get user defined text mode for setup.
  //
  mBmSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
  mBmSetupVerticalResolution   = PcdGet32 (PcdSetupVideoVerticalResolution);
  mBmSetupTextModeColumn       = PcdGet32 (PcdSetupConOutColumn);
  mBmSetupTextModeRow          = PcdGet32 (PcdSetupConOutRow);

  mBmModeInitialized           = TRUE;
}
Esempio n. 24
0
/*
**  Entry point for the LAN9118 driver
**
*/
EFI_STATUS
Lan9118DxeEntry (
  IN EFI_HANDLE Handle,
  IN EFI_SYSTEM_TABLE *SystemTable
  )
{
  EFI_STATUS                   Status;
  LAN9118_DRIVER              *LanDriver;
  EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
  EFI_SIMPLE_NETWORK_MODE     *SnpMode;
  LAN9118_DEVICE_PATH         *Lan9118Path;
  EFI_HANDLE                   ControllerHandle;

  // The PcdLan9118DxeBaseAddress PCD must be defined
  ASSERT (PcdGet32 (PcdLan9118DxeBaseAddress) != 0);

  // Allocate Resources
  LanDriver = AllocateZeroPool (sizeof (LAN9118_DRIVER));
  if (LanDriver == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }
  Lan9118Path = (LAN9118_DEVICE_PATH*)AllocateCopyPool (sizeof (LAN9118_DEVICE_PATH), &Lan9118PathTemplate);
  if (Lan9118Path == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  // Initialize pointers
  Snp = &(LanDriver->Snp);
  SnpMode = &(LanDriver->SnpMode);
  Snp->Mode = SnpMode;

  // Set the signature of the LAN Driver structure
  LanDriver->Signature = LAN9118_SIGNATURE;

  // Assign fields and func pointers
  Snp->Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
  Snp->WaitForPacket = NULL;
  Snp->Initialize = SnpInitialize;
  Snp->Start = SnpStart;
  Snp->Stop = SnpStop;
  Snp->Reset = SnpReset;
  Snp->Shutdown = SnpShutdown;
  Snp->ReceiveFilters = SnpReceiveFilters;
  Snp->StationAddress = SnpStationAddress;
  Snp->Statistics = SnpStatistics;
  Snp->MCastIpToMac = SnpMcastIptoMac;
  Snp->NvData = SnpNvData;
  Snp->GetStatus = SnpGetStatus;
  Snp->Transmit = SnpTransmit;
  Snp->Receive = SnpReceive;

  // Start completing simple network mode structure
  SnpMode->State = EfiSimpleNetworkStopped;
  SnpMode->HwAddressSize = NET_ETHER_ADDR_LEN; // HW address is 6 bytes
  SnpMode->MediaHeaderSize = sizeof(ETHER_HEAD); // Not sure of this
  SnpMode->MaxPacketSize = EFI_PAGE_SIZE; // Preamble + SOF + Ether Frame (with VLAN tag +4bytes)
  SnpMode->NvRamSize = 0;           // No NVRAM with this device
  SnpMode->NvRamAccessSize = 0; // No NVRAM with this device

  //
  // Claim that all receive filter settings are supported, though the MULTICAST mode
  // is not completely supported. The LAN9118 Ethernet controller is only able to
  // do a "hash filtering" and not a perfect filtering on multicast addresses. The
  // controller does not filter the multicast addresses directly but a hash value
  // of them. The hash value of a multicast address is derived from its CRC and
  // ranges from 0 to 63 included.
  // We claim that the perfect MULTICAST filtering mode is supported because
  // we do not want the user to switch directly to the PROMISCOUS_MULTICAST mode
  // and thus not being able to take advantage of the hash filtering.
  //
  SnpMode->ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST              |
                               EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST            |
                               EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST            |
                               EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS          |
                               EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;

  // We do not intend to receive anything for the time being.
  SnpMode->ReceiveFilterSetting = 0;

  // LAN9118 has 64bit hash table, can filter 64 MCast MAC Addresses
  SnpMode->MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;
  SnpMode->MCastFilterCount = 0;
  ZeroMem (&SnpMode->MCastFilter, MAX_MCAST_FILTER_CNT * sizeof(EFI_MAC_ADDRESS));

  // Set the interface type (1: Ethernet or 6: IEEE 802 Networks)
  SnpMode->IfType = NET_IFTYPE_ETHERNET;

  // Mac address is changeable as it is loaded from erasable memory
  SnpMode->MacAddressChangeable = TRUE;

  // Can only transmit one packet at a time
  SnpMode->MultipleTxSupported = FALSE;

  // MediaPresent checks for cable connection and partner link
  SnpMode->MediaPresentSupported = TRUE;
  SnpMode->MediaPresent = FALSE;

  // Set broadcast address
  SetMem (&SnpMode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);

  // Power up the device so we can find the MAC address
  Status = Lan9118Initialize (Snp);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "LAN9118: Error initialising hardware\n"));
    return EFI_DEVICE_ERROR;
  }

  // Assign fields for device path
  CopyMem (&Lan9118Path->Lan9118.MacAddress, &Snp->Mode->CurrentAddress, NET_ETHER_ADDR_LEN);
  Lan9118Path->Lan9118.IfType = Snp->Mode->IfType;

  // Initialise the protocol
  ControllerHandle = NULL;
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &ControllerHandle,
                  &gEfiSimpleNetworkProtocolGuid, Snp,
                  &gEfiDevicePathProtocolGuid, Lan9118Path,
                  NULL
                  );
  // Say what the status of loading the protocol structure is
  if (EFI_ERROR(Status)) {
    FreePool (LanDriver);
  } else {
    LanDriver->ControllerHandle = ControllerHandle;
  }

  return Status;
}
Esempio n. 25
0
  //
  PERF_END (NULL, "DXE", NULL, 0);
  PERF_START (NULL, "BDS", NULL, 0);
  DEBUG ((EFI_D_INFO, "[Bds] Entry...\n"));

  PERF_CODE (
    BdsAllocateMemoryForPerformanceData ();
  );

  //
  // Fill in FirmwareVendor and FirmwareRevision from PCDs
  //
  FirmwareVendor = (CHAR16 *) PcdGetPtr (PcdFirmwareVendor);
  gST->FirmwareVendor = AllocateRuntimeCopyPool (StrSize (FirmwareVendor), FirmwareVendor);
  ASSERT (gST->FirmwareVendor != NULL);
  gST->FirmwareRevision = PcdGet32 (PcdFirmwareRevision);

  //
  // Fixup Tasble CRC after we updated Firmware Vendor and Revision
  //
  gST->Hdr.CRC32 = 0;
  gBS->CalculateCrc32 ((VOID *) gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32);

  //
  // Validate Variable.
  //
  BdsFormalizeEfiGlobalVariable ();

  //
  // Mark the read-only variables if the Variable Lock protocol exists
  //
Esempio n. 26
0
/**
  Install ACPI Firmware Performance Data Table (FPDT).

  @return Status code.

**/
EFI_STATUS
InstallFirmwarePerformanceDataTable (
  VOID
  )
{
  EFI_STATUS                    Status;
  EFI_ACPI_TABLE_PROTOCOL       *AcpiTableProtocol;
  UINTN                         Size;
  UINT8                         *SmmBootRecordCommBuffer;
  EFI_SMM_COMMUNICATE_HEADER    *SmmCommBufferHeader;
  SMM_BOOT_RECORD_COMMUNICATE   *SmmCommData;
  UINTN                         CommSize;
  UINTN                         BootPerformanceDataSize;
  UINT8                         *BootPerformanceData; 
  EFI_SMM_COMMUNICATION_PROTOCOL  *Communication;
  FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable;

  //
  // Get AcpiTable Protocol.
  //
  Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTableProtocol);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Collect boot records from SMM drivers.
  //
  SmmBootRecordCommBuffer = NULL;
  SmmCommData             = NULL;
  Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &Communication);
  if (!EFI_ERROR (Status)) {
    //
    // Initialize communicate buffer 
    //
    SmmBootRecordCommBuffer = AllocateZeroPool (SMM_BOOT_RECORD_COMM_SIZE);
    ASSERT (SmmBootRecordCommBuffer != NULL);
    SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER*)SmmBootRecordCommBuffer;
    SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)SmmCommBufferHeader->Data;
    ZeroMem((UINT8*)SmmCommData, sizeof(SMM_BOOT_RECORD_COMMUNICATE));

    CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gEfiFirmwarePerformanceGuid);
    SmmCommBufferHeader->MessageLength = sizeof(SMM_BOOT_RECORD_COMMUNICATE);
    CommSize = SMM_BOOT_RECORD_COMM_SIZE;
  
    //
    // Get the size of boot records.
    //
    SmmCommData->Function       = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE;
    SmmCommData->BootRecordData = NULL;
    Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
    ASSERT_EFI_ERROR (Status);
  
    if (!EFI_ERROR (SmmCommData->ReturnStatus) && SmmCommData->BootRecordSize != 0) {
      //
      // Get all boot records
      //
      SmmCommData->Function       = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA;
      SmmCommData->BootRecordData = AllocateZeroPool(SmmCommData->BootRecordSize);
      ASSERT (SmmCommData->BootRecordData != NULL);
      
      Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
      ASSERT_EFI_ERROR (Status);
      ASSERT_EFI_ERROR(SmmCommData->ReturnStatus);
    }
  }

  //
  // Prepare memory for Boot Performance table.
  // Boot Performance table includes BasicBoot record, and one or more appended Boot Records. 
  //
  BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);
  if (SmmCommData != NULL) {
    BootPerformanceDataSize += SmmCommData->BootRecordSize;
  }

  //
  // Try to allocate the same runtime buffer as last time boot.
  //
  ZeroMem (&PerformanceVariable, sizeof (PerformanceVariable));
  Size = sizeof (PerformanceVariable);
  Status = gRT->GetVariable (
                  EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
                  &gEfiFirmwarePerformanceGuid,
                  NULL,
                  &Size,
                  &PerformanceVariable
                  );
  if (!EFI_ERROR (Status)) {
    Status = gBS->AllocatePages (
                    AllocateAddress,
                    EfiReservedMemoryType,
                    EFI_SIZE_TO_PAGES (BootPerformanceDataSize),
                    &PerformanceVariable.BootPerformanceTablePointer
                    );
    if (!EFI_ERROR (Status)) {
      mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.BootPerformanceTablePointer;
    }
  }

  if (mAcpiBootPerformanceTable == NULL) {
    //
    // Fail to allocate at specified address, continue to allocate at any address.
    //
    mAcpiBootPerformanceTable = (BOOT_PERFORMANCE_TABLE *) FpdtAllocateReservedMemoryBelow4G (BootPerformanceDataSize);
  }
  DEBUG ((EFI_D_INFO, "FPDT: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable));

  if (mAcpiBootPerformanceTable == NULL) {
    if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) {
      FreePool (SmmCommData->BootRecordData);
    }
    if (SmmBootRecordCommBuffer != NULL) {
      FreePool (SmmBootRecordCommBuffer);
    }
    if (mAcpiS3PerformanceTable != NULL) {
      FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)));
    }
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Prepare Boot Performance Table.
  //
  BootPerformanceData = (UINT8 *) mAcpiBootPerformanceTable;
  //
  // Fill Basic Boot record to Boot Performance Table.
  //
  CopyMem (mAcpiBootPerformanceTable, &mBootPerformanceTableTemplate, sizeof (mBootPerformanceTableTemplate));
  BootPerformanceData = BootPerformanceData + mAcpiBootPerformanceTable->Header.Length;
  //
  // Fill Boot records from boot drivers.
  //
  CopyMem (BootPerformanceData, mBootRecordBuffer, mBootRecordSize);
  mAcpiBootPerformanceTable->Header.Length += mBootRecordSize;
  BootPerformanceData = BootPerformanceData + mBootRecordSize;
  if (SmmCommData != NULL && SmmCommData->BootRecordData != NULL) {
    //
    // Fill Boot records from SMM drivers.
    //
    CopyMem (BootPerformanceData, SmmCommData->BootRecordData, SmmCommData->BootRecordSize);
    FreePool (SmmCommData->BootRecordData);
    mAcpiBootPerformanceTable->Header.Length = (UINT32) (mAcpiBootPerformanceTable->Header.Length + SmmCommData->BootRecordSize);
    BootPerformanceData = BootPerformanceData + SmmCommData->BootRecordSize;
  }
  if (SmmBootRecordCommBuffer != NULL) {
    FreePool (SmmBootRecordCommBuffer);
  }

  //
  // Save Boot Performance Table address to Variable for use in S4 resume.
  //
  PerformanceVariable.BootPerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiBootPerformanceTable;
  //
  // Update Boot Performance Table Pointer in template.
  //
  mFirmwarePerformanceTableTemplate.BootPointerRecord.BootPerformanceTablePointer = (UINT64) (UINTN) mAcpiBootPerformanceTable;

  //
  // Save S3 Performance Table address to Variable for use in S4 resume.
  //
  PerformanceVariable.S3PerformanceTablePointer = (EFI_PHYSICAL_ADDRESS) (UINTN) mAcpiS3PerformanceTable;
  //
  // Update S3 Performance Table Pointer in template.
  //
  mFirmwarePerformanceTableTemplate.S3PointerRecord.S3PerformanceTablePointer = (UINT64) (UINTN) mAcpiS3PerformanceTable;
  //
  // Save Runtime Performance Table pointers to Variable.
  //
  Status = gRT->SetVariable (
                  EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
                  &gEfiFirmwarePerformanceGuid,
                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
                  sizeof (PerformanceVariable),
                  &PerformanceVariable
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Publish Firmware Performance Data Table.
  //
  FpdtAcpiTableChecksum ((UINT8 *) &mFirmwarePerformanceTableTemplate, mFirmwarePerformanceTableTemplate.Header.Length);
  Status = AcpiTableProtocol->InstallAcpiTable (
                                AcpiTableProtocol,
                                &mFirmwarePerformanceTableTemplate,
                                mFirmwarePerformanceTableTemplate.Header.Length,
                                &mFirmwarePerformanceTableTemplateKey
                                );
  if (EFI_ERROR (Status)) {
    FreePages (mAcpiBootPerformanceTable, EFI_SIZE_TO_PAGES (BootPerformanceDataSize));
    if (mAcpiS3PerformanceTable != NULL) {
      FreePages (mAcpiS3PerformanceTable, EFI_SIZE_TO_PAGES (sizeof (S3_PERFORMANCE_TABLE)));
    }
    mAcpiBootPerformanceTable = NULL;
    mAcpiS3PerformanceTable = NULL;
    return Status;
  }
  
  //
  // Free temp Boot record, and update Boot Record to point to Basic Boot performance table.
  //
  if (mBootRecordBuffer != NULL) {
    FreePool (mBootRecordBuffer);
  }
  mBootRecordBuffer  = (UINT8 *) mAcpiBootPerformanceTable;
  mBootRecordSize    = mAcpiBootPerformanceTable->Header.Length;
  mBootRecordMaxSize = mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize);
  
  return EFI_SUCCESS;
}
Esempio n. 27
0
/**
  Provides the service of deferring image load based on platform policy control,
  and installs Deferred Image Load Protocol.

  @param[in]  AuthenticationStatus  This is the authentication status returned from the 
                                    security measurement services for the input file.
  @param[in]  File                  This is a pointer to the device path of the file that
                                    is being dispatched. This will optionally be used for
                                    logging.
  @param[in]  FileBuffer            File buffer matches the input file device path.
  @param[in]  FileSize              Size of File buffer matches the input file device path.
  @param[in]  BootPolicy            A boot policy that was used to call LoadImage() UEFI service.

  @retval EFI_SUCCESS               FileBuffer is NULL and current user has permission to start
                                    UEFI device drivers on the device path specified by DevicePath.
  @retval EFI_SUCCESS               The file specified by DevicePath and non-NULL
                                    FileBuffer did authenticate, and the platform policy dictates
                                    that the DXE Foundation may use the file.
  @retval EFI_SECURITY_VIOLATION    FileBuffer is NULL and the user has no
                                    permission to start UEFI device drivers on the device path specified
                                    by DevicePath.
  @retval EFI_SECURITY_VIOLATION    FileBuffer is not NULL and the user has no permission to load
                                    drivers from the device path specified by DevicePath. The
                                    image has been added into the list of the deferred images.
  @retval EFI_ACCESS_DENIED         The file specified by File and FileBuffer did not
                                    authenticate, and the platform policy dictates that the DXE
                                    Foundation many not use File.

**/
EFI_STATUS
EFIAPI
DxeDeferImageLoadHandler (
  IN  UINT32                           AuthenticationStatus,
  IN  CONST EFI_DEVICE_PATH_PROTOCOL   *File,
  IN  VOID                             *FileBuffer,
  IN  UINTN                            FileSize,
  IN  BOOLEAN                          BootPolicy
  )
{
  EFI_STATUS                           Status;
  EFI_USER_PROFILE_HANDLE              CurrentUser;
  UINT32                               Policy;
  UINT32                               FileType;

  //
  // Ignore if File is NULL.
  //
  if (File == NULL) {
    return EFI_SUCCESS;
  }

  //
  // Check whether user has a logon.
  // 
  CurrentUser = NULL;
  if (mUserManager != NULL) {
    mUserManager->Current (mUserManager, &CurrentUser);
    if (CurrentUser != NULL) {
      //
      // The user is logon; verify the FilePath by current user access policy.
      //
      if (!VerifyDevicePath (File)) {
        DEBUG ((EFI_D_ERROR, "[Security] The image is forbidden to load!\n"));
        return EFI_SECURITY_VIOLATION;
      }
      return EFI_SUCCESS;
    }
  }
  
  //
  // Still no user logon.
  // Check the file type and get policy setting.
  //
  FileType = GetFileType (File);
  Policy   = PcdGet32 (PcdDeferImageLoadPolicy);
  if ((Policy & FileType) == FileType) {
    //
    // This file type is secure to load.
    //
    return EFI_SUCCESS;
  }
 
  DEBUG ((EFI_D_ERROR, "[Security] No user identified, the image is deferred to load!\n"));
  PutDefferedImageInfo (File, FileBuffer, FileSize);

  //
  // Install the Deferred Image Load Protocol onto a new handle.
  //
  if (!mIsProtocolInstalled) {
    Status = gBS->InstallMultipleProtocolInterfaces (
                    &mDeferredImageHandle,
                    &gEfiDeferredImageLoadProtocolGuid,
                    &gDeferredImageLoad,
                    NULL
                    );
    ASSERT_EFI_ERROR (Status);
    mIsProtocolInstalled = TRUE;
  }

  return EFI_ACCESS_DENIED;
}
Esempio n. 28
0
/**
  Report status code listener of FPDT. This is used to collect performance data
  for OsLoaderLoadImageStart and OsLoaderStartImageStart in FPDT.

  @param[in]  CodeType            Indicates the type of status code being reported.
  @param[in]  Value               Describes the current status of a hardware or software entity.
                                  This included information about the class and subclass that is used to
                                  classify the entity as well as an operation.
  @param[in]  Instance            The enumeration of a hardware or software entity within
                                  the system. Valid instance numbers start with 1.
  @param[in]  CallerId            This optional parameter may be used to identify the caller.
                                  This parameter allows the status code driver to apply different rules to
                                  different callers.
  @param[in]  Data                This optional parameter may be used to pass additional data.

  @retval EFI_SUCCESS             Status code is what we expected.
  @retval EFI_UNSUPPORTED         Status code not supported.

**/
EFI_STATUS
EFIAPI
FpdtStatusCodeListenerDxe (
  IN EFI_STATUS_CODE_TYPE     CodeType,
  IN EFI_STATUS_CODE_VALUE    Value,
  IN UINT32                   Instance,
  IN EFI_GUID                 *CallerId,
  IN EFI_STATUS_CODE_DATA     *Data
  )
{
  EFI_STATUS  Status;

  //
  // Check whether status code is what we are interested in.
  //
  if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) {
    return EFI_UNSUPPORTED;
  }

  Status = EFI_SUCCESS;
  if (Value == PcdGet32 (PcdProgressCodeOsLoaderLoad)) {
    //
    // Progress code for OS Loader LoadImage.
    //
    if (mAcpiBootPerformanceTable == NULL) {
      return Status;
    }

    //
    // Update OS Loader LoadImage Start for UEFI boot.
    //
    mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());
  } else if (Value == PcdGet32 (PcdProgressCodeOsLoaderStart)) {
    //
    // Progress code for OS Loader StartImage.
    //
    if (mAcpiBootPerformanceTable == NULL) {
      return Status;
    }

    //
    // Update OS Loader StartImage Start for UEFI boot.
    //
    mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());
  } else if (Value == (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES)) {
    //
    // Progress code for ExitBootServices.
    //
    if (mAcpiBootPerformanceTable == NULL) {
      return Status;
    }

    //
    // Update ExitBootServicesExit for UEFI boot.
    //
    mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesExit = GetTimeInNanoSecond (GetPerformanceCounter ());

    //
    // Unregister boot time report status code listener.
    //
    mRscHandlerProtocol->Unregister (FpdtStatusCodeListenerDxe);
  } else if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) {
    //
    // Append one or more Boot records
    //
    if (mAcpiBootPerformanceTable == NULL) {
      //
      // Append Boot records before FPDT ACPI table is installed. 
      //
      if (mBootRecordSize + Data->Size > mBootRecordMaxSize) {
        mBootRecordBuffer = ReallocatePool (mBootRecordSize, mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE, mBootRecordBuffer);
        ASSERT (mBootRecordBuffer != NULL);
        mBootRecordMaxSize = mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE;
      }
      //
      // Save boot record into the temp memory space.
      //
      CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size);
      mBootRecordSize += Data->Size;
    } else {
      //
      // Append Boot records after FPDT ACPI table is installed. 
      //
      if (mBootRecordSize + Data->Size > mBootRecordMaxSize) {
        //
        // No enough space to save boot record.
        //
        Status = EFI_OUT_OF_RESOURCES;
      } else {
        //
        // Save boot record into BootPerformance table
        //
        CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size);
        mBootRecordSize += Data->Size;
        mAcpiBootPerformanceTable->Header.Length = mBootRecordSize;
      }
    }
  } else {
    //
    // Ignore else progress code.
    //
    Status = EFI_UNSUPPORTED;
  }

  return Status;
}
Esempio n. 29
0
EFI_STATUS
EFIAPI
InitSpiDevice (
  IN EFI_HANDLE           ImageHandle,
  IN EFI_SYSTEM_TABLE     *SystemTable
  )
{
  EFI_EVENT                     Event;
  CONST FLASH_PART_DESCRIPTION  *FlashDescription;
  UINT64                        FlashSize;
  EFI_HANDLE                    Handle;
  EFI_STATUS                    Status;

  mNvStorageBase = PcdGet32 (PcdFlashNvStorageVariableBase);

  //
  // Locate the SPI controller protocol and save it for later.
  //
  DEBUG((EFI_D_INFO, "Locating SPI Controller Protocol.\n"));
  Status = gBS->LocateProtocol (
                  &gEfiSpiProtocolGuid,
                  NULL,
                  (VOID **) &mSpiProtocol
                  );
  ASSERT_EFI_ERROR(Status);
  
  //
  // Loop through all the flash devices that are supported and see if one will
  // initialize the SPI Controller interface.
  //
  FlashSize = FindFlashSupport (
                &JedecIdRead,
                NULL,
                &FlashDescription
                );
  if (FlashSize == 0) {
    DEBUG((EFI_D_ERROR, "No SPI flash part description found!\r\n"));
  } else {
    //
    // Attempt to configure the SPI controller for this device.
    //
    DEBUG((EFI_D_INFO, "SPI flash size: %d MBytes\n", DivU64x32(FlashSize, 1024 * 1024 )));
    DEBUG((EFI_D_INFO, "Configuring SPI Controller.\n"));
    
    Status = SpiFlashInit (FlashDescription);    
    if (!EFI_ERROR (Status)) {
      //
      // Publish the SPI Device protocol.
      //
      DEBUG((EFI_D_INFO, "Installing SPI Device Protocol.\n"));
      Handle = NULL;
      Status = gBS->InstallMultipleProtocolInterfaces (
                      &Handle,
                      &gSpiDeviceProtocolGuid,
                      &mSpiDevProtocol,
                      NULL
                      );
      if (EFI_ERROR (Status)) {
        return EFI_OUT_OF_RESOURCES;
      }

      //
      // Make sure we can handle virtual address changes.
      //
      Event = NULL;
      Status = gBS->CreateEventEx (
                      EVT_NOTIFY_SIGNAL,
                      TPL_NOTIFY,
                      SpiDeviceVirtualAddressChangeEvent,
                      NULL,
                      &gEfiEventVirtualAddressChangeGuid,
                      &Event
                      );      

      return EFI_SUCCESS;
    }
  }

  //
  // Unable to find a supported SPI device
  //
  DEBUG((EFI_D_ERROR, "Unable to configure SPI Controller for SPI device present.\n"));

  return EFI_UNSUPPORTED;
}
Esempio n. 30
0
/**
  Stalls the CPU for at least the given number of microseconds.

  Stalls the CPU for the number of microseconds specified by MicroSeconds.
  The hardware timer is 32 bits.
  The maximum possible delay is (0xFFFFFFFF / TimerFrequencyMHz), i.e. ([32bits] / FreqInMHz)
  For example:
  +----------------+------------+----------+----------+
  | TimerFrequency |  MaxDelay  | MaxDelay | MaxDelay |
  |     (MHz)      |    (us)    |   (s)    |  (min)   |
  +----------------+------------+----------+----------+
  |        1       | 0xFFFFFFFF |   4294   |   71.5   |
  |        5       | 0x33333333 |    859   |   14.3   |
  |       10       | 0x19999999 |    429   |    7.2   |
  |       50       | 0x051EB851 |     86   |    1.4   |
  +----------------+------------+----------+----------+
  If it becomes necessary to support higher delays, then consider using the
  real time clock.

  During this delay, the cpu is not yielded to any other process, with one exception:
  events that are triggered off a timer and which execute at a higher TPL than
  this function. These events may call MicroSecondDelay (or NanoSecondDelay) to
  fulfil their own needs.
  Therefore, this function must be re-entrant, as it may be interrupted and re-started.

  @param  MicroSeconds  The minimum number of microseconds to delay.

  @return The value of MicroSeconds inputted.

**/
UINTN
EFIAPI
MicroSecondDelay (
  IN  UINTN MicroSeconds
  )
{
  UINT64    DelayTicks64;         // Convert from microseconds to timer ticks, more bits to detect over-range conditions.
  UINTN     DelayTicks;           // Convert from microseconds to timer ticks, native size for general calculations.
  UINTN     StartTicks;           // Timer value snapshot at the start of the delay
  UINTN     TargetTicks;          // Timer value to signal the end of the delay
  UINTN     CurrentTicks;         // Current value of the 64-bit timer value at any given moment

  // If we snapshot the timer at the start of the delay function then we minimise unaccounted overheads.
  StartTicks = MmioRead32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CURRENT_REG);

  // We are operating at the limit of 32bits. For the range checking work in 64 bits to avoid overflows.
  DelayTicks64 = MultU64x32((UINT64)MicroSeconds, PcdGet32(PcdSP804TimerFrequencyInMHz));

  // We are limited to 32 bits.
  // If the specified delay is exactly equal to the max range of the timer,
  // then the start will be equal to the stop plus one timer overflow (wrap-around).
  // To avoid having to check for that, reduce the maximum acceptable range by 1 tick,
  // i.e. reject delays equal or greater than the max range of the timer.
  if (DelayTicks64 >= (UINT64)SP804_MAX_TICKS) {
    DEBUG((EFI_D_ERROR,"MicroSecondDelay: ERROR: MicroSeconds=%d exceed SP804 count range. Max MicroSeconds=%d\n",
      MicroSeconds,
      ((UINTN)SP804_MAX_TICKS/PcdGet32(PcdSP804TimerFrequencyInMHz))));
  }
  ASSERT(DelayTicks64 < (UINT64)SP804_MAX_TICKS);

  // From now on do calculations only in native bit size.
  DelayTicks = (UINTN)DelayTicks64;

  // Calculate the target value of the timer.

  //Note: SP804 timer is counting down
  if (StartTicks >= DelayTicks) {
    // In this case we do not expect a wrap-around of the timer to occur.
    // CurrentTicks must be less than StartTicks and higher than TargetTicks.
    // If this is not the case, then the delay has been reached and may even have been exceeded if this
    // function was suspended by a higher priority interrupt.

    TargetTicks = StartTicks - DelayTicks;

    do {
      CurrentTicks = MmioRead32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CURRENT_REG);
    } while ((CurrentTicks > TargetTicks) && (CurrentTicks <= StartTicks));

  } else {
    // In this case TargetTicks is larger than StartTicks.
    // This means we expect a wrap-around of the timer to occur and we must wait for it.
    // Before the wrap-around, CurrentTicks must be less than StartTicks and less than TargetTicks.
    // After the wrap-around, CurrentTicks must be larger than StartTicks and larger than TargetTicks.
    // If this is not the case, then the delay has been reached and may even have been exceeded if this
    // function was suspended by a higher priority interrupt.

    // The order of operations is essential to avoid arithmetic overflow problems
    TargetTicks = ((UINTN)SP804_MAX_TICKS - DelayTicks) + StartTicks;

    // First wait for the wrap-around to occur
    do {
      CurrentTicks = MmioRead32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CURRENT_REG);
    } while (CurrentTicks <= StartTicks);

    // Then wait for the target
    do {
      CurrentTicks = MmioRead32 (SP804_TIMER_METRONOME_BASE + SP804_TIMER_CURRENT_REG);
    } while (CurrentTicks > TargetTicks);
  }

  return MicroSeconds;
}