Example #1
0
/**
  EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.

  @param  InterruptType    Defines the type of interrupt or exception that
                           occurred on the processor.This parameter is processor
                           architecture specific.
  @param  SystemContext    A pointer to the processor context when
                           the interrupt occurred on the processor.

  @return None

**/
STATIC
VOID
EFIAPI
IrqInterruptHandler (
  IN EFI_EXCEPTION_TYPE           InterruptType,
  IN EFI_SYSTEM_CONTEXT           SystemContext
  )
{
  HARDWARE_INTERRUPT_HANDLER  InterruptHandler;
  HARDWARE_INTERRUPT_SOURCE   Source;
  UINT32                      RegVal;

  RegVal = MmioRead32 (RegBase + BCM2836_INTC_TIMER_PENDING_OFFSET) &
    ((1 << NUM_IRQS) - 1);
  Source = HighBitSet32 (RegVal);
  if (Source < 0) {
    return;
  }

  InterruptHandler = mRegisteredInterruptHandlers[Source];
  if (InterruptHandler != NULL) {
    // Call the registered interrupt handler.
    InterruptHandler (Source, SystemContext);
  }
}
Example #2
0
/**
  Returns the bit position of the highest bit set in a 64-bit value. Equivalent
  to log2(x).

  This function computes the bit position of the highest bit set in the 64-bit
  value specified by Operand. If Operand is zero, then -1 is returned.
  Otherwise, a value between 0 and 63 is returned.

  @param  Operand The 64-bit operand to evaluate.

  @return Position of the highest bit set in Operand if found.
  @retval -1  Operand is zero.

**/
INTN
EFIAPI
HighBitSet64 (
  IN      UINT64                    Operand
  )
{
  if (Operand == (UINT32)Operand) {
    //
    // Operand is just a 32-bit integer
    //
    return HighBitSet32 ((UINT32)Operand);
  }

  //
  // Operand is really a 64-bit integer
  //
  if (sizeof (UINTN) == sizeof (UINT32)) {
    return HighBitSet32 (((UINT32*)&Operand)[1]) + 32;
  } else {
    return HighBitSet32 ((UINT32)RShiftU64 (Operand, 32)) + 32;
  }
}
/**

  Detects FAT file system on Disk and set relevant fields of Volume.

  @param Volume                - The volume structure.

  @retval EFI_SUCCESS           - The Fat File System is detected successfully
  @retval EFI_UNSUPPORTED       - The volume is not FAT file system.
  @retval EFI_VOLUME_CORRUPTED  - The volume is corrupted.

**/
EFI_STATUS
FatOpenDevice (
  IN OUT FAT_VOLUME           *Volume
  )
{
  EFI_STATUS            Status;
  UINT32                BlockSize;
  UINT32                DirtyMask;
  EFI_DISK_IO_PROTOCOL  *DiskIo;
  FAT_BOOT_SECTOR       FatBs;
  FAT_VOLUME_TYPE       FatType;
  UINTN                 RootDirSectors;
  UINTN                 FatLba;
  UINTN                 RootLba;
  UINTN                 FirstClusterLba;
  UINTN                 Sectors;
  UINTN                 SectorsPerFat;
  UINT8                 SectorsPerClusterAlignment;
  UINT8                 BlockAlignment;

  //
  // Read the FAT_BOOT_SECTOR BPB info
  // This is the only part of FAT code that uses parent DiskIo,
  // Others use FatDiskIo which utilizes a Cache.
  //
  DiskIo  = Volume->DiskIo;
  Status  = DiskIo->ReadDisk (DiskIo, Volume->MediaId, 0, sizeof (FatBs), &FatBs);

  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_INIT, "FatOpenDevice: read of part_lba failed %r\n", Status));
    return Status;
  }

  FatType = FatUndefined;

  //
  // Use LargeSectors if Sectors is 0
  //
  Sectors = FatBs.FatBsb.Sectors;
  if (Sectors == 0) {
    Sectors = FatBs.FatBsb.LargeSectors;
  }

  SectorsPerFat = FatBs.FatBsb.SectorsPerFat;
  if (SectorsPerFat == 0) {
    SectorsPerFat = FatBs.FatBse.Fat32Bse.LargeSectorsPerFat;
    FatType       = Fat32;
  }
  //
  // Is boot sector a fat sector?
  // (Note that so far we only know if the sector is FAT32 or not, we don't
  // know if the sector is Fat16 or Fat12 until later when we can compute
  // the volume size)
  //
  if (FatBs.FatBsb.ReservedSectors == 0 || FatBs.FatBsb.NumFats == 0 || Sectors == 0) {
    return EFI_UNSUPPORTED;
  }

  if ((FatBs.FatBsb.SectorSize & (FatBs.FatBsb.SectorSize - 1)) != 0) {
    return EFI_UNSUPPORTED;
  }

  BlockAlignment = (UINT8) HighBitSet32 (FatBs.FatBsb.SectorSize);
  if (BlockAlignment > MAX_BLOCK_ALIGNMENT || BlockAlignment < MIN_BLOCK_ALIGNMENT) {
    return EFI_UNSUPPORTED;
  }

  if ((FatBs.FatBsb.SectorsPerCluster & (FatBs.FatBsb.SectorsPerCluster - 1)) != 0) {
    return EFI_UNSUPPORTED;
  }

  SectorsPerClusterAlignment = (UINT8) HighBitSet32 (FatBs.FatBsb.SectorsPerCluster);
  if (SectorsPerClusterAlignment > MAX_SECTORS_PER_CLUSTER_ALIGNMENT) {
    return EFI_UNSUPPORTED;
  }

  if (FatBs.FatBsb.Media <= 0xf7 &&
      FatBs.FatBsb.Media != 0xf0 &&
      FatBs.FatBsb.Media != 0x00 &&
      FatBs.FatBsb.Media != 0x01
      ) {
    return EFI_UNSUPPORTED;
  }
  //
  // Initialize fields the volume information for this FatType
  //
  if (FatType != Fat32) {
    if (FatBs.FatBsb.RootEntries == 0) {
      return EFI_UNSUPPORTED;
    }
    //
    // Unpack fat12, fat16 info
    //
    Volume->RootEntries = FatBs.FatBsb.RootEntries;
  } else {
    //
    // If this is fat32, refuse to mount mirror-disabled volumes
    //
    if ((SectorsPerFat == 0 || FatBs.FatBse.Fat32Bse.FsVersion != 0) || (FatBs.FatBse.Fat32Bse.ExtendedFlags & 0x80)) {
      return EFI_UNSUPPORTED;
    }
    //
    // Unpack fat32 info
    //
    Volume->RootCluster = FatBs.FatBse.Fat32Bse.RootDirFirstCluster;
  }

  Volume->NumFats           = FatBs.FatBsb.NumFats;
  //
  // Compute some fat locations
  //
  BlockSize                 = FatBs.FatBsb.SectorSize;
  RootDirSectors            = ((Volume->RootEntries * sizeof (FAT_DIRECTORY_ENTRY)) + (BlockSize - 1)) / BlockSize;

  FatLba                    = FatBs.FatBsb.ReservedSectors;
  RootLba                   = FatBs.FatBsb.NumFats * SectorsPerFat + FatLba;
  FirstClusterLba           = RootLba + RootDirSectors;

  Volume->FatPos            = FatLba * BlockSize;
  Volume->FatSize           = SectorsPerFat * BlockSize;

  Volume->VolumeSize        = LShiftU64 (Sectors, BlockAlignment);
  Volume->RootPos           = LShiftU64 (RootLba, BlockAlignment);
  Volume->FirstClusterPos   = LShiftU64 (FirstClusterLba, BlockAlignment);
  Volume->MaxCluster        = (Sectors - FirstClusterLba) >> SectorsPerClusterAlignment;
  Volume->ClusterAlignment  = (UINT8)(BlockAlignment + SectorsPerClusterAlignment);
  Volume->ClusterSize       = (UINTN)1 << (Volume->ClusterAlignment);

  //
  // If this is not a fat32, determine if it's a fat16 or fat12
  //
  if (FatType != Fat32) {
    if (Volume->MaxCluster >= FAT_MAX_FAT16_CLUSTER) {
      return EFI_VOLUME_CORRUPTED;
    }

    FatType = Volume->MaxCluster < FAT_MAX_FAT12_CLUSTER ? Fat12 : Fat16;
    //
    // fat12 & fat16 fat-entries are 2 bytes
    //
    Volume->FatEntrySize = sizeof (UINT16);
    DirtyMask            = FAT16_DIRTY_MASK;
  } else {
    if (Volume->MaxCluster < FAT_MAX_FAT16_CLUSTER) {
      return EFI_VOLUME_CORRUPTED;
    }
    //
    // fat32 fat-entries are 4 bytes
    //
    Volume->FatEntrySize = sizeof (UINT32);
    DirtyMask            = FAT32_DIRTY_MASK;
  }
  //
  // Get the DirtyValue and NotDirtyValue
  // We should keep the initial value as the NotDirtyValue
  // in case the volume is dirty already
  //
  if (FatType != Fat12) {
    Status = FatAccessVolumeDirty (Volume, ReadDisk, &Volume->NotDirtyValue);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Volume->DirtyValue = Volume->NotDirtyValue & DirtyMask;
  }
  //
  // If present, read the fat hint info
  //
  if (FatType == Fat32) {
    Volume->FreeInfoPos = FatBs.FatBse.Fat32Bse.FsInfoSector * BlockSize;
    if (FatBs.FatBse.Fat32Bse.FsInfoSector != 0) {
      FatDiskIo (Volume, ReadDisk, Volume->FreeInfoPos, sizeof (FAT_INFO_SECTOR), &Volume->FatInfoSector, NULL);
      if (Volume->FatInfoSector.Signature == FAT_INFO_SIGNATURE &&
          Volume->FatInfoSector.InfoBeginSignature == FAT_INFO_BEGIN_SIGNATURE &&
          Volume->FatInfoSector.InfoEndSignature == FAT_INFO_END_SIGNATURE &&
          Volume->FatInfoSector.FreeInfo.ClusterCount <= Volume->MaxCluster
          ) {
        Volume->FreeInfoValid = TRUE;
      }
    }
  }
  //
  // Just make up a FreeInfo.NextCluster for use by allocate cluster
  //
  if (FAT_MIN_CLUSTER > Volume->FatInfoSector.FreeInfo.NextCluster ||
     Volume->FatInfoSector.FreeInfo.NextCluster > Volume->MaxCluster + 1
     ) {
    Volume->FatInfoSector.FreeInfo.NextCluster = FAT_MIN_CLUSTER;
  }
  //
  // We are now defining FAT Type
  //
  Volume->FatType = FatType;
  ASSERT (FatType != FatUndefined);

  return EFI_SUCCESS;
}
UINTN
PciParseBar (
  IN PCI_IO_DEVICE  *PciIoDevice,
  IN UINTN          Offset,
  IN UINTN          BarIndex
  )
/*++

Routine Description:

Arguments:

Returns:

  None

--*/
{
  UINT32      Value;
  //UINT64      BarValue64;
  UINT32      OriginalValue;
  UINT32      Mask;
  EFI_STATUS  Status;

  OriginalValue = 0;
  Value         = 0;
  //BarValue64    = 0;

  Status = BarExisted (
            PciIoDevice,
            Offset,
            &Value,
            &OriginalValue
            );

  if (EFI_ERROR (Status)) {
    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
    PciIoDevice->PciBar[BarIndex].Length      = 0;
    PciIoDevice->PciBar[BarIndex].Alignment   = 0;

    //
    // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
    //
    PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
    return Offset + 4;
  }

  PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
  if (Value & 0x01) {
    //
    // Device I/Os
    //
    Mask = 0xfffffffc;

    if (Value & 0xFFFF0000) {
      //
      // It is a IO32 bar
      //
      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo32;
      PciIoDevice->PciBar[BarIndex].Length    = ((~(Value & Mask)) + 1);
      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;

    } else {
      //
      // It is a IO16 bar
      //
      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo16;
      PciIoDevice->PciBar[BarIndex].Length    = 0x0000FFFF & ((~(Value & Mask)) + 1);
      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;

    }
    //
    // Workaround. Some platforms inplement IO bar with 0 length
    // Need to treat it as no-bar
    //
    if (PciIoDevice->PciBar[BarIndex].Length == 0) {
      PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
    }

    PciIoDevice->PciBar[BarIndex].Prefetchable  = FALSE;
    PciIoDevice->PciBar[BarIndex].BaseAddress   = OriginalValue & Mask;

  } else {

    Mask  = 0xfffffff0;

    PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;

    switch (Value & 0x07) {

    //
    //memory space; anywhere in 32 bit address space
    //
    case 0x00:
      if (Value & 0x08) {
        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
      } else {
        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
      }

      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;

      break;

    //
    // memory space; anywhere in 64 bit address space
    //
    case 0x04:
      if (Value & 0x08) {
        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
      } else {
        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
      }

      //
      // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
      // is regarded as an extension for the first bar. As a result
      // the sizing will be conducted on combined 64 bit value
      // Here just store the masked first 32bit value for future size
      // calculation
      //
      PciIoDevice->PciBar[BarIndex].Length    = Value & Mask;
      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;

      //
      // Increment the offset to point to next DWORD
      //
      Offset += 4;

      Status = BarExisted (
                PciIoDevice,
                Offset,
                &Value,
                &OriginalValue
                );

      if (EFI_ERROR (Status)) {
        return Offset + 4;
      }

      //
      // Fix the length to support some spefic 64 bit BAR
      //
      Value |= ((UINT32)(-1) << HighBitSet32 (Value)); 

      //
      // Calculate the size of 64bit bar
      //
      PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);

      PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
      PciIoDevice->PciBar[BarIndex].Length    = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;

      break;

    //
    // reserved
    //
    default:
      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;
      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;
      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;

      break;
    }
  }
  
  //
  // Check the length again so as to keep compatible with some special bars
  //
  if (PciIoDevice->PciBar[BarIndex].Length == 0) {
    PciIoDevice->PciBar[BarIndex].BarType     = PciBarTypeUnknown;
    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
    PciIoDevice->PciBar[BarIndex].Alignment   = 0;
  }
  
  //
  // Increment number of bar
  //
  return Offset + 4;
}
Example #5
0
/**
  The user code starts with this function.

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

  @retval EFI_SUCCESS            The driver is successfully initialized.
  @retval Others                 Can't initialize the driver.

**/
EFI_STATUS
EFIAPI
InitializeSdMmcHcPeim (
  IN EFI_PEI_FILE_HANDLE       FileHandle,
  IN CONST EFI_PEI_SERVICES    **PeiServices
  )
{
  EFI_BOOT_MODE                BootMode;
  EFI_STATUS                   Status;
  UINT16                       Bus;
  UINT16                       Device;
  UINT16                       Function;
  UINT32                       Size;
  UINT64                       MmioSize;
  UINT8                        SubClass;
  UINT8                        BaseClass;
  UINT8                        SlotInfo;
  UINT8                        SlotNum;
  UINT8                        FirstBar;
  UINT8                        Index;
  UINT8                        Slot;
  UINT32                       BarAddr;
  SD_MMC_HC_PEI_PRIVATE_DATA   *Private;

  //
  // Shadow this PEIM to run from memory
  //
  if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
    return EFI_SUCCESS;
  }

  Status = PeiServicesGetBootMode (&BootMode);
  ///
  /// We do not expose this in S3 boot path, because it is only for recovery.
  ///
  if (BootMode == BOOT_ON_S3_RESUME) {
    return EFI_SUCCESS;
  }

  Private = (SD_MMC_HC_PEI_PRIVATE_DATA *) AllocateZeroPool (sizeof (SD_MMC_HC_PEI_PRIVATE_DATA));
  if (Private == NULL) {
    DEBUG ((EFI_D_ERROR, "Failed to allocate memory for SD_MMC_HC_PEI_PRIVATE_DATA! \n"));
    return EFI_OUT_OF_RESOURCES;
  }

  Private->Signature              = SD_MMC_HC_PEI_SIGNATURE;
  Private->SdMmcHostControllerPpi = mSdMmcHostControllerPpi;
  Private->PpiList                = mPpiList;
  Private->PpiList.Ppi            = &Private->SdMmcHostControllerPpi;

  BarAddr = PcdGet32 (PcdSdMmcPciHostControllerMmioBase);
  for (Bus = 0; Bus < 256; Bus++) {
    for (Device = 0; Device < 32; Device++) {
      for (Function = 0; Function < 8; Function++) {
        SubClass  = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));
        BaseClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));

        if ((SubClass == PCI_SUBCLASS_SD_HOST_CONTROLLER) && (BaseClass == PCI_CLASS_SYSTEM_PERIPHERAL)) {
          //
          // Get the SD/MMC Pci host controller's Slot Info.
          //
          SlotInfo = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, SD_MMC_HC_PEI_SLOT_OFFSET));
          FirstBar = (*(SD_MMC_HC_PEI_SLOT_INFO*)&SlotInfo).FirstBar;
          SlotNum  = (*(SD_MMC_HC_PEI_SLOT_INFO*)&SlotInfo).SlotNum + 1;
          ASSERT ((FirstBar + SlotNum) < MAX_SD_MMC_SLOTS);

          for (Index = 0, Slot = FirstBar; Slot < (FirstBar + SlotNum); Index++, Slot++) {
            //
            // Get the SD/MMC Pci host controller's MMIO region size.
            //
            PciAnd16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), (UINT16)~(EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));
            PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4 * Slot), 0xFFFFFFFF);
            Size = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4 * Slot));

            switch (Size & 0x07) {
              case 0x0:
                //
                // Memory space: anywhere in 32 bit address space
                //
                MmioSize = (~(Size & 0xFFFFFFF0)) + 1;
                break;
              case 0x4:
                //
                // Memory space: anywhere in 64 bit address space
                //
                MmioSize = Size & 0xFFFFFFF0;
                PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4), 0xFFFFFFFF);
                Size = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4));      
                //
                // Fix the length to support some spefic 64 bit BAR
                //
                Size |= ((UINT32)(-1) << HighBitSet32 (Size));
                //
                // Calculate the size of 64bit bar
                //
                MmioSize  |= LShiftU64 ((UINT64) Size, 32);
                MmioSize  = (~(MmioSize)) + 1;
                //
                // Clean the high 32bits of this 64bit BAR to 0 as we only allow a 32bit BAR.
                //
                PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4 * Slot + 4), 0);
                break;
              default:
                //
                // Unknown BAR type
                //
                ASSERT (FALSE);
                continue;
            };
            //
            // Assign resource to the SdMmc Pci host controller's MMIO BAR.
            // Enable the SdMmc Pci host controller by setting BME and MSE bits of PCI_CMD register.
            //
            PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4 * Slot), BarAddr);
            PciOr16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), (EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));
            //
            // Record the allocated Mmio base address.
            //
            Private->MmioBar[Private->TotalSdMmcHcs].SlotNum++;
            Private->MmioBar[Private->TotalSdMmcHcs].MmioBarAddr[Index] = BarAddr;
            BarAddr += (UINT32)MmioSize;
          }
          Private->TotalSdMmcHcs++;
          ASSERT (Private->TotalSdMmcHcs < MAX_SD_MMC_HCS);
        }
      }
    }
  }

  ///
  /// Install SdMmc Host Controller PPI
  ///
  Status = PeiServicesInstallPpi (&Private->PpiList);

  ASSERT_EFI_ERROR (Status);
  return Status;
}