|
@@ -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
|
|