/** This function flushes the range of addresses from Start to Start+Length from the processor's data cache. If Start is not aligned to a cache line boundary, then the bytes before Start to the preceding cache line boundary are also flushed. If Start+Length is not aligned to a cache line boundary, then the bytes past Start+Length to the end of the next cache line boundary are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be supported. If the data cache is fully coherent with all DMA operations, then this function can just return EFI_SUCCESS. If the processor does not support flushing a range of the data cache, then the entire data cache can be flushed. @param This The EFI_CPU_ARCH_PROTOCOL instance. @param Start The beginning physical address to flush from the processor's data cache. @param Length The number of bytes to flush from the processor's data cache. This function may flush more bytes than Length specifies depending upon the granularity of the flush operation that the processor supports. @param FlushType Specifies the type of flush operation to perform. @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from the processor's data cache. @retval EFI_UNSUPPORTED The processor does not support the cache flush type specified by FlushType. @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed from the processor's data cache. **/ EFI_STATUS EFIAPI CpuFlushCpuDataCache ( IN EFI_CPU_ARCH_PROTOCOL *This, IN EFI_PHYSICAL_ADDRESS Start, IN UINT64 Length, IN EFI_CPU_FLUSH_TYPE FlushType ) { switch (FlushType) { case EfiCpuFlushTypeWriteBack: WriteBackDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length); break; case EfiCpuFlushTypeInvalidate: InvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length); break; case EfiCpuFlushTypeWriteBackInvalidate: WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length); break; default: return EFI_INVALID_PARAMETER; } return EFI_SUCCESS; }
/** Routine Description: Write a block of data. Arguments: BaseAddress - Base address of the block. Buffer - Data buffer. BufferSize - Size of the buffer. Returns: EFI_SUCCESS - The command completed successfully. EFI_INVALID_PARAMETER - Invalid parameter, can not proceed. Other - Device error or wirte-locked, operation failed. **/ EFI_STATUS InternalWriteBlock ( IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT8 *Buffer, IN UINT32 BufferSize ) { EFI_STATUS Status; Status = SpiFlashWrite ((UINTN) BaseAddress, &BufferSize, Buffer); if (EFI_ERROR (Status)) { DEBUG((DEBUG_ERROR, "\nFlash write error.")); return Status; } WriteBackInvalidateDataCacheRange ((VOID *) (UINTN) BaseAddress, BLOCK_SIZE); Status = InternalCompareBlock (BaseAddress, Buffer); if (EFI_ERROR (Status)) { DEBUG((DEBUG_ERROR, "\nError when writing to BaseAddress %x with different at offset %x.", BaseAddress, Status)); } else { DEBUG((DEBUG_INFO, "\nVerified data written to Block at %x is correct.", BaseAddress)); } return Status; }
/** Erases and initializes a firmware volume block @param[in] Instance The FV instance to be erased @param[in] Lba The logical block index to be erased @retval EFI_SUCCESS The erase request was successfully completed @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written. Firmware device may have been partially erased @retval EFI_INVALID_PARAMETER Instance not found **/ EFI_STATUS FvbEraseBlock ( IN UINTN Instance, IN EFI_LBA Lba ) { EFI_FVB_ATTRIBUTES_2 Attributes; UINTN LbaAddress; EFI_FW_VOL_INSTANCE *FwhInstance; UINTN LbaLength; EFI_STATUS Status; EFI_STATUS Status1; UINTN FlashAddress; // // Find the right instance of the FVB private data // FwhInstance = GetFvbInstance (Instance); // // Check if the FV is write enabled // Attributes = FvbGetVolumeAttributes (Instance); if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { return EFI_ACCESS_DENIED; } // // Get the starting address of the block for erase. // Status = FvbGetLbaAddress (Instance, Lba, &FlashAddress, &LbaAddress, &LbaLength, NULL); if (EFI_ERROR (Status)) { return EFI_INVALID_PARAMETER; } // // Perform erase. // mSpiDeviceProtocol->SpiLock (FlashAddress, LbaLength, FALSE); Status1 = mSpiDeviceProtocol->SpiErase (FlashAddress, LbaLength); mSpiDeviceProtocol->SpiLock (FlashAddress, LbaLength, TRUE); WriteBackInvalidateDataCacheRange ((VOID *) LbaAddress, LbaLength); // // Check to see if the erase was successful. If not return a device error to // meet PI required return values. // if (Status1 == EFI_DEVICE_ERROR) { return Status1; } return EFI_SUCCESS; }
EFI_STATUS EFIAPI VirtualKeyboardClear ( IN VIRTUAL_KBD_KEY *VirtualKey ) { if (VirtualKey == NULL) { return EFI_INVALID_PARAMETER; } if (MmioRead32 (ADB_REBOOT_ADDRESS) == ADB_REBOOT_BOOTLOADER) { MmioWrite32 (ADB_REBOOT_ADDRESS, ADB_REBOOT_NONE); WriteBackInvalidateDataCacheRange ((VOID *)ADB_REBOOT_ADDRESS, 4); } return EFI_SUCCESS; }
EFI_STATUS EFIAPI EarlyConfigEntry ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { DEBUG((EFI_D_ERROR,"SMMU CONFIG.........")); SmmuConfigForOS(); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"ITS CONFIG.........")); ITSCONFIG(); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"AP CONFIG.........")); MmioWrite64(FixedPcdGet64(PcdMailBoxAddress), 0x0); (void)WriteBackInvalidateDataCacheRange((VOID *) FixedPcdGet64(PcdMailBoxAddress), 8); asm("DSB SY"); asm("ISB"); CoreSelectBoot(); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"MN CONFIG.........")); MN_CONFIG (); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"RTC CONFIG.........")); MmioWrite32(0xA00021F0, 0xF); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"Tsensor CONFIG.........")); MmioWrite32(0x80010000 + 0x5000, 0x1); *(volatile UINT32*)0xA0000A8C = 0x1f; DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"Timer CONFIG.........")); PlatformTimerStart (); DEBUG((EFI_D_ERROR,"Done\n")); return EFI_SUCCESS; }
STATIC EFI_STATUS InternalWriteBlock ( IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT8 *Buffer, IN UINT32 BufferSize ) /*++ Routine Description: Write a block of data. Arguments: BaseAddress - Base address of the block. Buffer - Data buffer. BufferSize - Size of the buffer. Returns: EFI_SUCCESS - The command completed successfully. EFI_INVALID_PARAMETER - Invalid parameter, can not proceed. Other - Device error or wirte-locked, operation failed. --*/ { EFI_STATUS Status; Status = SpiFlashWrite ((UINTN) BaseAddress, &BufferSize, Buffer); ASSERT_EFI_ERROR(Status); if (EFI_ERROR (Status)) { DEBUG((EFI_D_ERROR, "\nFlash write error.")); return Status; } WriteBackInvalidateDataCacheRange ((VOID *) (UINTN) BaseAddress, BLOCK_SIZE); Status = InternalCompareBlock (BaseAddress, Buffer); if (EFI_ERROR (Status)) { DEBUG((EFI_D_ERROR, "\nError when writing to BaseAddress %lx with different at offset %x.", BaseAddress, Status)); } else { DEBUG((EFI_D_INFO, "\nVerified data written to Block at %lx is correct.", BaseAddress)); } return Status; }
/** The driver entry point for Firmware Volume Block Driver. The function does the necessary initialization work Firmware Volume Block Driver. @param[in] ImageHandle The firmware allocated handle for the UEFI image. @param[in] SystemTable A pointer to the EFI system table. @retval EFI_SUCCESS This funtion always return EFI_SUCCESS. It will ASSERT on errors. **/ EFI_STATUS FvbInitialize ( ) { EFI_FW_VOL_INSTANCE *FwhInstance; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; EFI_FIRMWARE_VOLUME_HEADER *FvHeader; EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; EFI_PHYSICAL_ADDRESS BaseAddress; EFI_STATUS Status; UINTN BufferSize; UINTN TmpHeaderLength; UINTN Idx; UINT32 MaxLbaSize; BOOLEAN FvHeaderValid; UINTN FvFlashLinearAddress; EFI_BOOT_MODE BootMode; UINT32 Index; UINT32 PlatformFvBaseAddress[5]; UINT32 PlatformFvBaseAddressCount; UINT32 PlatformFvLockList[4]; UINT32 PlatformFvLockListCount; // // This platform driver knows there are 3 FVs on // FD, which are FvRecovery, FvMain and FvNvStorage. // BootMode = GetBootModeHob (); if (BootMode == BOOT_IN_RECOVERY_MODE) { // // On recovery boot, don't report any firmware FV images except payload, because their data can't be trusted. // PlatformFvBaseAddressCount = 2; PlatformFvBaseAddress[0] = PcdGet32 (PcdFlashNvStorageVariableBase); PlatformFvBaseAddress[1] = PcdGet32 (PcdFlashPayloadBase); } else { PlatformFvBaseAddressCount = 5; PlatformFvBaseAddress[0] = PcdGet32 (PcdFlashFvMainBase); PlatformFvBaseAddress[1] = PcdGet32 (PcdFlashNvStorageVariableBase); PlatformFvBaseAddress[2] = PcdGet32 (PcdFlashFvRecoveryBase); PlatformFvBaseAddress[3] = PcdGet32 (PcdFlashFvRecovery2Base); PlatformFvBaseAddress[4] = PcdGet32 (PcdFlashPayloadBase); } // // List of FVs that should be write protected on normal boots. // PlatformFvLockListCount = 4; PlatformFvLockList[0] = PcdGet32 (PcdFlashFvMainBase); PlatformFvLockList[1] = PcdGet32 (PcdFlashFvRecoveryBase); PlatformFvLockList[2] = PcdGet32 (PcdFlashFvRecovery2Base); PlatformFvLockList[3] = PcdGet32 (PcdFlashPayloadBase); // // Calculate the total size for all firmware volume block instances and // allocate a buffer to store them in. // BufferSize = 0; for (Idx = 0; Idx < PlatformFvBaseAddressCount; Idx++) { FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PlatformFvBaseAddress[Idx]; if (FvHeader == NULL) { continue; } BufferSize += (FvHeader->HeaderLength + sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER) ); } mFvbModuleGlobal.FvInstance = (EFI_FW_VOL_INSTANCE *) AllocateRuntimeZeroPool (BufferSize); ASSERT (NULL != mFvbModuleGlobal.FvInstance); // // Perform other variable initialization. // MaxLbaSize = 0; FwhInstance = mFvbModuleGlobal.FvInstance; mFvbModuleGlobal.NumFv = 0; for (Idx = 0; Idx < PlatformFvBaseAddressCount; Idx++) { if ((BootMode == BOOT_ASSUMING_NO_CONFIGURATION_CHANGES) && PlatformFvBaseAddress[Idx]!= PcdGet32 (PcdFlashNvStorageVariableBase) && PlatformFvBaseAddress[Idx]!= PcdGet32 (PcdFlashPayloadBase)) { continue; } // // Get base address information. // BaseAddress = PlatformFvBaseAddress[Idx]; FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; if (FwVolHeader == NULL) { continue; } // // Find the flash linear address of the current FV. // FvFlashLinearAddress = (UINTN) FLASH_LINEAR_ADDRESS(BaseAddress); if (!IsFvHeaderValid (BaseAddress, FwVolHeader)) { FvHeaderValid = FALSE; // // If not valid, get FvbInfo from the information carried in // FVB driver. // DEBUG ((EFI_D_ERROR, "Fvb: FV header @ 0x%lx invalid\n", BaseAddress)); Status = GetFvbInfo (BaseAddress, &FwVolHeader); ASSERT_EFI_ERROR(Status); // // Write back a healthy FV header. // DEBUG ((EFI_D_INFO, "FwBlockService.c: Writing back healthy FV header\n")); mSpiDeviceProtocol->SpiLock (FvFlashLinearAddress, FwVolHeader->BlockMap->Length, FALSE); Status = mSpiDeviceProtocol->SpiErase (FvFlashLinearAddress, FwVolHeader->BlockMap->Length); TmpHeaderLength = (UINTN) FwVolHeader->HeaderLength; Status = mSpiDeviceProtocol->SpiWrite ( FvFlashLinearAddress, &TmpHeaderLength, (UINT8 *) FwVolHeader ); mSpiDeviceProtocol->SpiLock (FvFlashLinearAddress, FwVolHeader->BlockMap->Length, TRUE); WriteBackInvalidateDataCacheRange ( (VOID *) (UINTN) BaseAddress, FwVolHeader->BlockMap->Length ); } // // Copy FV header into local storage and assign base address. // CopyMem (&(FwhInstance->VolumeHeader), FwVolHeader, FwVolHeader->HeaderLength); FwVolHeader = &(FwhInstance->VolumeHeader); FwhInstance->FvBase = (UINTN)BaseAddress; FwhInstance->FvFlashLinearAddress = FvFlashLinearAddress; // // In some cases the Recovery and Main FVs should be considered locked from // write access by this protocol. Only in the case of flash updates and // configuration mode should they be left unlocked. // if (BootMode != BOOT_IN_RECOVERY_MODE && BootMode != BOOT_ON_FLASH_UPDATE) { for (Index = 0; Index < PlatformFvLockListCount; Index++) { if (FwhInstance->FvBase == PlatformFvLockList[Index]) { // // For all FVs in the lock list we need to clear the write status bit // and lock write status updates. This will make sure this protocol // will not attempt to write to the FV. // FwhInstance->VolumeHeader.Attributes &= (UINT64) ~EFI_FVB2_WRITE_STATUS; FwhInstance->VolumeHeader.Attributes |= (EFI_FVB2_LOCK_STATUS | EFI_FVB2_WRITE_LOCK_STATUS); } } } // // Process the block map for each FV // FwhInstance->NumOfBlocks = 0; for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { // // Get the maximum size of a block. // if (MaxLbaSize < PtrBlockMapEntry->Length) { MaxLbaSize = PtrBlockMapEntry->Length; } FwhInstance->NumOfBlocks += PtrBlockMapEntry->NumBlocks; } // // Add a FVB Protocol Instance // mFvbModuleGlobal.NumFv++; InstallFvbProtocol (FwhInstance, mFvbModuleGlobal.NumFv - 1); // // Move on to the next FwhInstance // FwhInstance = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhInstance) + FwVolHeader->HeaderLength + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))); } if ((PcdGet32 (PcdFlashNvStorageFtwWorkingBase) == 0) || (PcdGet32 (PcdFlashNvStorageFtwSpareBase) == 0)) { return EFI_SUCCESS; } // // Install FVB protocols for FTW spare space and FTW working space. // These is no FV header for these 2 spaces. // mFvbModuleGlobal.FvInstance = (EFI_FW_VOL_INSTANCE *) ReallocateRuntimePool ( BufferSize, BufferSize + (sizeof (EFI_FW_VOL_INSTANCE) + sizeof (EFI_FV_BLOCK_MAP_ENTRY)) * 2, mFvbModuleGlobal.FvInstance ); ASSERT (NULL != mFvbModuleGlobal.FvInstance); PlatformFvBaseAddress[0] = PcdGet32 (PcdFlashNvStorageFtwWorkingBase); PlatformFvBaseAddress[1] = PcdGet32 (PcdFlashNvStorageFtwSpareBase); for (Idx = 0; Idx < 2; Idx++) { BaseAddress = PlatformFvBaseAddress[Idx]; Status = GetFtwFvbInfo (BaseAddress, &FwVolHeader); ASSERT_EFI_ERROR(Status); // // Copy FV header into local storage and assign base address. // mFvbModuleGlobal.NumFv++; FwhInstance = GetFvbInstance (mFvbModuleGlobal.NumFv - 1); CopyMem (&(FwhInstance->VolumeHeader), FwVolHeader, FwVolHeader->HeaderLength); FwVolHeader = &(FwhInstance->VolumeHeader); // // Process the block map for each FV // FwhInstance->NumOfBlocks = 0; for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { FwhInstance->NumOfBlocks += PtrBlockMapEntry->NumBlocks; } FwhInstance->FvBase = (UINTN)BaseAddress; FwhInstance->FvFlashLinearAddress = (UINTN) FLASH_LINEAR_ADDRESS(BaseAddress); InstallFvbProtocol (FwhInstance, mFvbModuleGlobal.NumFv - 1); } return EFI_SUCCESS; }
/** Writes specified number of bytes from the input buffer to the block @param[in] Instance The FV instance to be written to @param[in] Lba The starting logical block index to write to @param[in] BlockOffset Offset into the block at which to begin writing @param[in] NumBytes Pointer that on input contains the total size of the buffer. On output, it contains the total number of bytes actually written @param[in] Buffer Pointer to a caller allocated buffer that contains the source for the write @retval EFI_SUCCESS The firmware volume was written successfully @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output, NumBytes contains the total number of bytes actually written @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer are NULL **/ EFI_STATUS FvbWriteBlock ( IN UINTN Instance, IN EFI_LBA Lba, IN UINTN BlockOffset, IN OUT UINTN *NumBytes, IN UINT8 *Buffer ) { EFI_FVB_ATTRIBUTES_2 Attributes; UINTN LbaAddress; UINTN LbaLength; EFI_FW_VOL_INSTANCE *FwhInstance; EFI_STATUS Status; EFI_STATUS Status1; UINTN FlashAddress; // // Validate input parameters. // if ((NumBytes == NULL) || (Buffer == NULL)) { return (EFI_INVALID_PARAMETER); } if (*NumBytes == 0) { return (EFI_INVALID_PARAMETER); } // // Get the information for the FV specified. // FwhInstance = GetFvbInstance (Instance); Status = FvbGetLbaAddress (Instance, Lba, &FlashAddress, &LbaAddress, &LbaLength, NULL); if (EFI_ERROR (Status)) { return EFI_INVALID_PARAMETER; } // // Check if the FV is write enabled // Attributes = FvbGetVolumeAttributes (Instance); if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { return EFI_ACCESS_DENIED; } // // Perform boundary checks and adjust NumBytes if needed. // if (BlockOffset > LbaLength) { return EFI_INVALID_PARAMETER; } if ( LbaLength < ( *NumBytes + BlockOffset ) ) { *NumBytes = (UINT32) (LbaLength - BlockOffset); Status = EFI_BAD_BUFFER_SIZE; } // // Perform the write and flush the cache. // mSpiDeviceProtocol->SpiLock (FlashAddress, LbaLength, FALSE); Status1 = mSpiDeviceProtocol->SpiWrite (FlashAddress + BlockOffset, NumBytes, Buffer); mSpiDeviceProtocol->SpiLock (FlashAddress, LbaLength, TRUE); WriteBackInvalidateDataCacheRange ((VOID *) (LbaAddress + BlockOffset), *NumBytes); // // Determine the error to return based on PI spec. // if (Status1 == EFI_DEVICE_ERROR) { return Status1; } return Status; }