/** This is the main worker function that manages the state of the interrupt handlers. It both installs and uninstalls interrupt handlers based on the value of NewCallback. If NewCallback is NULL, then uninstall is indicated. If NewCallback is non-NULL, then install is indicated. @param NewCallback If non-NULL, NewCallback specifies the new handler to register. If NULL, specifies that the previously registered handler should be uninstalled. @param ExceptionType Indicates which entry to manage. @retval EFI_SUCCESS Installing or Uninstalling operation is ok. @retval EFI_INVALID_PARAMETER Requested uninstalling a handler from a vector that has no handler registered for it @retval EFI_ALREADY_STARTED Requested install to a vector that already has a handler registered. **/ EFI_STATUS ManageIdtEntryTable ( CALLBACK_FUNC NewCallback, EFI_EXCEPTION_TYPE ExceptionType ) { EFI_STATUS Status; Status = EFI_SUCCESS; if (CompareMem (&IdtEntryTable[ExceptionType].NewDesc, &NullDesc, sizeof (IA32_IDT_GATE_DESCRIPTOR)) != 0) { // // we've already installed to this vector // if (NewCallback != NULL) { // // if the input handler is non-null, error // Status = EFI_ALREADY_STARTED; } else { UnhookEntry (ExceptionType); } } else { // // no user handler installed on this vector // if (NewCallback == NULL) { // // if the input handler is null, error // Status = EFI_INVALID_PARAMETER; } else { HookEntry (ExceptionType, NewCallback); } } return Status; }
/** This is the worker function that uninstalls and removes all handlers. @param ExceptionType Specifies which processor exception. @param NewBundles New Boundles. @param NewCallback A pointer to the new function to be registered. @retval EFI_ALEADY_STARTED Ivt already hooked. @retval EFI_SUCCESS Successfully uninstalled. **/ EFI_STATUS ManageIvtEntryTable ( IN EFI_EXCEPTION_TYPE ExceptionType, IN BUNDLE NewBundles[NUM_BUNDLES_IN_STUB], IN CALLBACK_FUNC NewCallback ) { BUNDLE *B0Ptr; UINT64 InterruptFlags; EFI_TPL OldTpl; // // Get address of bundle 0 // GetHandlerEntryPoint (ExceptionType, (VOID **) &B0Ptr); if (IvtEntryTable[ExceptionType].RegisteredCallback != NULL) { // // we've already installed to this vector // if (NewCallback != NULL) { // // if the input handler is non-null, error // return EFI_ALREADY_STARTED; } else { // // else remove the previously installed handler // OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); InterruptFlags = ProgramInterruptFlags (DISABLE_INTERRUPTS); if (ExceptionType == EXCEPT_IPF_EXTERNAL_INTERRUPT) { UnchainExternalInterrupt (); } else { UnhookEntry (ExceptionType); } ProgramInterruptFlags (InterruptFlags); gBS->RestoreTPL (OldTpl); // // re-init IvtEntryTable // ZeroMem (&IvtEntryTable[ExceptionType], sizeof (IVT_ENTRY)); } } else { // // no user handler installed on this vector // if (NewCallback != NULL) { OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); InterruptFlags = ProgramInterruptFlags (DISABLE_INTERRUPTS); if (ExceptionType == EXCEPT_IPF_EXTERNAL_INTERRUPT) { ChainExternalInterrupt (NewCallback); } else { HookEntry (ExceptionType, NewBundles, NewCallback); } ProgramInterruptFlags (InterruptFlags); gBS->RestoreTPL (OldTpl); } } return EFI_SUCCESS; }