Просмотр исходного кода

[efi] Provide ACPI table description for SAN devices

Provide a basic proof of concept ACPI table description (e.g. iBFT for
iSCSI) for SAN devices in a UEFI environment, using a control flow
that is functionally identical to that used in a BIOS environment.

Originally-implemented-by: Vishvananda Ishaya Abrams <vish.ishaya@oracle.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 лет назад
Родитель
Сommit
fdcdc5203b
1 измененных файлов: 69 добавлений и 0 удалений
  1. 69
    0
      src/interface/efi/efi_block.c

+ 69
- 0
src/interface/efi/efi_block.c Просмотреть файл

@@ -46,15 +46,21 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
46 46
 #include <ipxe/process.h>
47 47
 #include <ipxe/sanboot.h>
48 48
 #include <ipxe/iso9660.h>
49
+#include <ipxe/acpi.h>
49 50
 #include <ipxe/efi/efi.h>
50 51
 #include <ipxe/efi/Protocol/BlockIo.h>
51 52
 #include <ipxe/efi/Protocol/SimpleFileSystem.h>
53
+#include <ipxe/efi/Protocol/AcpiTable.h>
52 54
 #include <ipxe/efi/efi_driver.h>
53 55
 #include <ipxe/efi/efi_strings.h>
54 56
 #include <ipxe/efi/efi_snp.h>
55 57
 #include <ipxe/efi/efi_utils.h>
56 58
 #include <ipxe/efi/efi_block.h>
57 59
 
60
+/** ACPI table protocol protocol */
61
+static EFI_ACPI_TABLE_PROTOCOL *acpi;
62
+EFI_REQUEST_PROTOCOL ( EFI_ACPI_TABLE_PROTOCOL, &acpi );
63
+
58 64
 /** Boot filename */
59 65
 static wchar_t efi_block_boot_filename[] = EFI_REMOVABLE_MEDIA_FILE_NAME;
60 66
 
@@ -399,7 +405,17 @@ static void efi_block_unhook ( unsigned int drive ) {
399 405
  * @ret rc		Return status code
400 406
  */
401 407
 static int efi_block_describe ( unsigned int drive ) {
408
+	static union {
409
+		/** ACPI header */
410
+		struct acpi_description_header acpi;
411
+		/** Padding */
412
+		char pad[768];
413
+	} xbftab;
414
+	static UINTN key;
402 415
 	struct san_device *sandev;
416
+	size_t len;
417
+	EFI_STATUS efirc;
418
+	int rc;
403 419
 
404 420
 	/* Find SAN device */
405 421
 	sandev = sandev_find ( drive );
@@ -408,6 +424,59 @@ static int efi_block_describe ( unsigned int drive ) {
408 424
 		return -ENODEV;
409 425
 	}
410 426
 
427
+	/* Sanity check */
428
+	if ( ! acpi ) {
429
+		DBGC ( sandev, "EFIBLK %#02x has no ACPI table protocol\n",
430
+		       sandev->drive );
431
+		return -ENOTSUP;
432
+	}
433
+
434
+	/* Remove existing table, if any */
435
+	if ( key ) {
436
+		if ( ( efirc = acpi->UninstallAcpiTable ( acpi, key ) ) != 0 ) {
437
+			rc = -EEFI ( efirc );
438
+			DBGC ( sandev, "EFIBLK %#02x could not uninstall ACPI "
439
+			       "table: %s\n", sandev->drive, strerror ( rc ) );
440
+			/* Continue anyway */
441
+		}
442
+		key = 0;
443
+	}
444
+
445
+	/* Reopen block device if necessary */
446
+	if ( sandev_needs_reopen ( sandev ) &&
447
+	     ( ( rc = sandev_reopen ( sandev ) ) != 0 ) )
448
+		return rc;
449
+
450
+	/* Clear table */
451
+	memset ( &xbftab, 0, sizeof ( xbftab ) );
452
+
453
+	/* Fill in common parameters */
454
+	strncpy ( xbftab.acpi.oem_id, "FENSYS",
455
+		  sizeof ( xbftab.acpi.oem_id ) );
456
+	strncpy ( xbftab.acpi.oem_table_id, "iPXE",
457
+		  sizeof ( xbftab.acpi.oem_table_id ) );
458
+
459
+	/* Fill in remaining parameters */
460
+	if ( ( rc = acpi_describe ( &sandev->block, &xbftab.acpi,
461
+				    sizeof ( xbftab ) ) ) != 0 ) {
462
+		DBGC ( sandev, "EFIBLK %#02x could not create ACPI "
463
+		       "description: %s\n", sandev->drive, strerror ( rc ) );
464
+		return rc;
465
+	}
466
+	len = le32_to_cpu ( xbftab.acpi.length );
467
+
468
+	/* Fix up ACPI checksum */
469
+	acpi_fix_checksum ( &xbftab.acpi );
470
+
471
+	/* Install table */
472
+	if ( ( efirc = acpi->InstallAcpiTable ( acpi, &xbftab, len,
473
+						&key ) ) != 0 ) {
474
+		rc = -EEFI ( efirc );
475
+		DBGC ( sandev, "EFIBLK %#02x could not install ACPI table: "
476
+		       "%s\n", sandev->drive, strerror ( rc ) );
477
+		return rc;
478
+	}
479
+
411 480
 	return 0;
412 481
 }
413 482
 

Загрузка…
Отмена
Сохранить