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

Loading…
Cancel
Save