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