|
@@ -63,6 +63,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
63
|
63
|
#include <ipxe/efi/efi_hii.h>
|
64
|
64
|
#include <ipxe/efi/efi_snp.h>
|
65
|
65
|
#include <ipxe/efi/efi_strings.h>
|
|
66
|
+#include <ipxe/efi/efi_utils.h>
|
66
|
67
|
#include <config/branding.h>
|
67
|
68
|
|
68
|
69
|
/** EFI platform setup formset GUID */
|
|
@@ -653,6 +654,9 @@ static EFI_HII_CONFIG_ACCESS_PROTOCOL efi_snp_device_hii = {
|
653
|
654
|
*/
|
654
|
655
|
int efi_snp_hii_install ( struct efi_snp_device *snpdev ) {
|
655
|
656
|
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
|
657
|
+ VENDOR_DEVICE_PATH *vendor_path;
|
|
658
|
+ EFI_DEVICE_PATH_PROTOCOL *path_end;
|
|
659
|
+ size_t path_prefix_len;
|
656
|
660
|
int efirc;
|
657
|
661
|
int rc;
|
658
|
662
|
|
|
@@ -674,9 +678,46 @@ int efi_snp_hii_install ( struct efi_snp_device *snpdev ) {
|
674
|
678
|
goto err_build_package_list;
|
675
|
679
|
}
|
676
|
680
|
|
|
681
|
+ /* Allocate the new device path */
|
|
682
|
+ path_prefix_len = efi_devpath_len ( snpdev->path );
|
|
683
|
+ snpdev->hii_child_path = zalloc ( path_prefix_len +
|
|
684
|
+ sizeof ( *vendor_path ) +
|
|
685
|
+ sizeof ( *path_end ) );
|
|
686
|
+ if ( ! snpdev->hii_child_path ) {
|
|
687
|
+ DBGC ( snpdev,
|
|
688
|
+ "SNPDEV %p could not allocate HII child device path\n",
|
|
689
|
+ snpdev );
|
|
690
|
+ rc = -ENOMEM;
|
|
691
|
+ goto err_alloc_child_path;
|
|
692
|
+ }
|
|
693
|
+
|
|
694
|
+ /* Populate the device path */
|
|
695
|
+ memcpy ( snpdev->hii_child_path, snpdev->path, path_prefix_len );
|
|
696
|
+ vendor_path = ( ( ( void * ) snpdev->hii_child_path ) +
|
|
697
|
+ path_prefix_len );
|
|
698
|
+ vendor_path->Header.Type = HARDWARE_DEVICE_PATH;
|
|
699
|
+ vendor_path->Header.SubType = HW_VENDOR_DP;
|
|
700
|
+ vendor_path->Header.Length[0] = sizeof ( *vendor_path );
|
|
701
|
+ efi_snp_hii_random_guid ( &vendor_path->Guid );
|
|
702
|
+ path_end = ( ( void * ) ( vendor_path + 1 ) );
|
|
703
|
+ path_end->Type = END_DEVICE_PATH_TYPE;
|
|
704
|
+ path_end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;
|
|
705
|
+ path_end->Length[0] = sizeof ( *path_end );
|
|
706
|
+
|
|
707
|
+ /* Create device path and child handle for HII association */
|
|
708
|
+ if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
|
|
709
|
+ &snpdev->hii_child_handle,
|
|
710
|
+ &efi_device_path_protocol_guid, snpdev->hii_child_path,
|
|
711
|
+ NULL ) ) != 0 ) {
|
|
712
|
+ rc = -EEFI ( efirc );
|
|
713
|
+ DBGC ( snpdev, "SNPDEV %p could not create HII child handle: "
|
|
714
|
+ "%s\n", snpdev, strerror ( rc ) );
|
|
715
|
+ goto err_hii_child_handle;
|
|
716
|
+ }
|
|
717
|
+
|
677
|
718
|
/* Add HII packages */
|
678
|
719
|
if ( ( efirc = efihii->NewPackageList ( efihii, snpdev->package_list,
|
679
|
|
- snpdev->handle,
|
|
720
|
+ snpdev->hii_child_handle,
|
680
|
721
|
&snpdev->hii_handle ) ) != 0 ) {
|
681
|
722
|
rc = -EEFI ( efirc );
|
682
|
723
|
DBGC ( snpdev, "SNPDEV %p could not add HII packages: %s\n",
|
|
@@ -686,7 +727,7 @@ int efi_snp_hii_install ( struct efi_snp_device *snpdev ) {
|
686
|
727
|
|
687
|
728
|
/* Install HII protocol */
|
688
|
729
|
if ( ( efirc = bs->InstallMultipleProtocolInterfaces (
|
689
|
|
- &snpdev->handle,
|
|
730
|
+ &snpdev->hii_child_handle,
|
690
|
731
|
&efi_hii_config_access_protocol_guid, &snpdev->hii,
|
691
|
732
|
NULL ) ) != 0 ) {
|
692
|
733
|
rc = -EEFI ( efirc );
|
|
@@ -695,15 +736,34 @@ int efi_snp_hii_install ( struct efi_snp_device *snpdev ) {
|
695
|
736
|
goto err_install_protocol;
|
696
|
737
|
}
|
697
|
738
|
|
|
739
|
+ /* Add as child of handle with SNP instance */
|
|
740
|
+ if ( ( rc = efi_child_add ( snpdev->handle,
|
|
741
|
+ snpdev->hii_child_handle ) ) != 0 ) {
|
|
742
|
+ DBGC ( snpdev,
|
|
743
|
+ "SNPDEV %p could not adopt HII child handle: %s\n",
|
|
744
|
+ snpdev, strerror ( rc ) );
|
|
745
|
+ goto err_efi_child_add;
|
|
746
|
+ }
|
|
747
|
+
|
698
|
748
|
return 0;
|
699
|
749
|
|
|
750
|
+ efi_child_del ( snpdev->handle, snpdev->hii_child_handle );
|
|
751
|
+ err_efi_child_add:
|
700
|
752
|
bs->UninstallMultipleProtocolInterfaces (
|
701
|
|
- snpdev->handle,
|
|
753
|
+ snpdev->hii_child_handle,
|
702
|
754
|
&efi_hii_config_access_protocol_guid, &snpdev->hii,
|
703
|
755
|
NULL );
|
704
|
756
|
err_install_protocol:
|
705
|
757
|
efihii->RemovePackageList ( efihii, snpdev->hii_handle );
|
706
|
758
|
err_new_package_list:
|
|
759
|
+ bs->UninstallMultipleProtocolInterfaces (
|
|
760
|
+ snpdev->hii_child_handle,
|
|
761
|
+ &efi_device_path_protocol_guid, snpdev->hii_child_path,
|
|
762
|
+ NULL );
|
|
763
|
+ err_hii_child_handle:
|
|
764
|
+ free ( snpdev->hii_child_path );
|
|
765
|
+ snpdev->hii_child_path = NULL;
|
|
766
|
+ err_alloc_child_path:
|
707
|
767
|
free ( snpdev->package_list );
|
708
|
768
|
snpdev->package_list = NULL;
|
709
|
769
|
err_build_package_list:
|
|
@@ -724,11 +784,18 @@ void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev ) {
|
724
|
784
|
return;
|
725
|
785
|
|
726
|
786
|
/* Uninstall protocols and remove package list */
|
|
787
|
+ efi_child_del ( snpdev->handle, snpdev->hii_child_handle );
|
727
|
788
|
bs->UninstallMultipleProtocolInterfaces (
|
728
|
|
- snpdev->handle,
|
|
789
|
+ snpdev->hii_child_handle,
|
729
|
790
|
&efi_hii_config_access_protocol_guid, &snpdev->hii,
|
730
|
791
|
NULL );
|
731
|
792
|
efihii->RemovePackageList ( efihii, snpdev->hii_handle );
|
|
793
|
+ bs->UninstallMultipleProtocolInterfaces (
|
|
794
|
+ snpdev->hii_child_handle,
|
|
795
|
+ &efi_device_path_protocol_guid, snpdev->hii_child_path,
|
|
796
|
+ NULL );
|
|
797
|
+ free ( snpdev->hii_child_path );
|
|
798
|
+ snpdev->hii_child_path = NULL;
|
732
|
799
|
free ( snpdev->package_list );
|
733
|
800
|
snpdev->package_list = NULL;
|
734
|
801
|
}
|