/** * The following function presumes that the block has already been unlocked. **/ EFI_STATUS NorFlashUnlockAndEraseSingleBlock ( IN NOR_FLASH_INSTANCE *Instance, IN UINTN BlockAddress ) { EFI_STATUS Status; UINTN Index; EFI_TPL OriginalTPL; // Raise TPL to TPL_HIGH to stop anyone from interrupting us. OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); Index = 0; // The block erase might fail a first time (SW bug ?). Retry it ... do { // Unlock the block if we have to Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress); if (!EFI_ERROR(Status)) { Status = NorFlashEraseSingleBlock (Instance, BlockAddress); } Index++; } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED)); if (Index == NOR_FLASH_ERASE_RETRY) { DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress,Index)); } // Interruptions can resume. gBS->RestoreTPL (OriginalTPL); return Status; }
/** * This function unlock and erase an entire NOR Flash block. **/ EFI_STATUS NorFlashUnlockAndEraseSingleBlock ( IN NOR_FLASH_INSTANCE *Instance, IN UINTN BlockAddress ) { EFI_STATUS Status; UINTN Index; EFI_TPL OriginalTPL; if (!EfiAtRuntime ()) { // Raise TPL to TPL_HIGH to stop anyone from interrupting us. OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); } else { // This initialization is only to prevent the compiler to complain about the // use of uninitialized variables OriginalTPL = TPL_HIGH_LEVEL; } Index = 0; // The block erase might fail a first time (SW bug ?). Retry it ... do { // Unlock the block if we have to Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress); if (EFI_ERROR (Status)) { break; } Status = NorFlashEraseSingleBlock (Instance, BlockAddress); Index++; } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED)); if (Index == NOR_FLASH_ERASE_RETRY) { DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress,Index)); } if (!EfiAtRuntime ()) { // Interruptions can resume. gBS->RestoreTPL (OriginalTPL); } return Status; }