Browse Source

[efi] Inhibit our driver Start() method during disconnection attempts

Some HP BIOSes (observed with a Z840) seem to attempt to connect our
drivers in the middle of our call to DisconnectController().  The
precise chain of events is unclear, but the symptom is that we see
several calls to our Supported() and Start() methods, followed by a
system lock-up.

Work around this dubious BIOS behaviour by explicitly failing calls to
our Start() method while we are in the middle of attempting to
disconnect drivers.

Reported-by: Jordan Wright <jordan.m.wright@disney.com>
Debugged-by: Adrian Lucrèce Céleste <adrianlucrececeleste@airmail.cc>
Debugged-by: Christian Nilsson <nikize@gmail.com>
Tested-by: Jordan Wright <jordan.m.wright@disney.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
74d90b33f8
1 changed files with 16 additions and 0 deletions
  1. 16
    0
      src/interface/efi/efi_driver.c

+ 16
- 0
src/interface/efi/efi_driver.c View File

44
 /** List of controlled EFI devices */
44
 /** List of controlled EFI devices */
45
 static LIST_HEAD ( efi_devices );
45
 static LIST_HEAD ( efi_devices );
46
 
46
 
47
+/** We are currently disconnecting drivers */
48
+static int efi_driver_disconnecting;
49
+
47
 /**
50
 /**
48
  * Find EFI device
51
  * Find EFI device
49
  *
52
  *
159
 		goto err_already_started;
162
 		goto err_already_started;
160
 	}
163
 	}
161
 
164
 
165
+	/* Do nothing if we are currently disconnecting drivers */
166
+	if ( efi_driver_disconnecting ) {
167
+		DBGC ( device, "EFIDRV %s refusing to start during "
168
+		       "disconnection\n", efi_handle_name ( device ) );
169
+		efirc = EFI_NOT_READY;
170
+		goto err_disconnecting;
171
+	}
172
+
162
 	/* Open device path */
173
 	/* Open device path */
163
 	if ( ( efirc = bs->OpenProtocol ( device,
174
 	if ( ( efirc = bs->OpenProtocol ( device,
164
 					  &efi_device_path_protocol_guid,
175
 					  &efi_device_path_protocol_guid,
220
 				    efi_image_handle, device );
231
 				    efi_image_handle, device );
221
 	}
232
 	}
222
  err_open_path:
233
  err_open_path:
234
+ err_disconnecting:
223
  err_already_started:
235
  err_already_started:
224
 	return efirc;
236
 	return efirc;
225
 }
237
 }
411
 	DBGC2_EFI_PROTOCOLS ( device, device );
423
 	DBGC2_EFI_PROTOCOLS ( device, device );
412
 	DBGC ( device, "EFIDRV %s disconnecting existing drivers\n",
424
 	DBGC ( device, "EFIDRV %s disconnecting existing drivers\n",
413
 	       efi_handle_name ( device ) );
425
 	       efi_handle_name ( device ) );
426
+	efi_driver_disconnecting = 1;
414
 	if ( ( efirc = bs->DisconnectController ( device, NULL,
427
 	if ( ( efirc = bs->DisconnectController ( device, NULL,
415
 						  NULL ) ) != 0 ) {
428
 						  NULL ) ) != 0 ) {
416
 		rc = -EEFI ( efirc );
429
 		rc = -EEFI ( efirc );
419
 		       strerror ( rc ) );
432
 		       strerror ( rc ) );
420
 		/* Ignore the error and attempt to connect our drivers */
433
 		/* Ignore the error and attempt to connect our drivers */
421
 	}
434
 	}
435
+	efi_driver_disconnecting = 0;
422
 	DBGC2 ( device, "EFIDRV %s after disconnecting:\n",
436
 	DBGC2 ( device, "EFIDRV %s after disconnecting:\n",
423
 		efi_handle_name ( device ) );
437
 		efi_handle_name ( device ) );
424
 	DBGC2_EFI_PROTOCOLS ( device, device );
438
 	DBGC2_EFI_PROTOCOLS ( device, device );
450
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
464
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
451
 
465
 
452
 	/* Disconnect our driver */
466
 	/* Disconnect our driver */
467
+	efi_driver_disconnecting = 1;
453
 	bs->DisconnectController ( device,
468
 	bs->DisconnectController ( device,
454
 				   efi_driver_binding.DriverBindingHandle,
469
 				   efi_driver_binding.DriverBindingHandle,
455
 				   NULL );
470
 				   NULL );
471
+	efi_driver_disconnecting = 0;
456
 	return 0;
472
 	return 0;
457
 }
473
 }
458
 
474
 

Loading…
Cancel
Save