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