mirror of https://github.com/ipxe/ipxe.git
[efi] Nullify interfaces and leak memory on uninstallation failure
The UEFI specification allows uninstallation of a protocol interface to fail. There is no sensible way for code to react to this, since uninstallation is likely to be taking place on a code path that cannot itself fail (e.g. a code path that is itself a failure path). Where the protocol structure exists within a dynamically allocated block of memory, this leads to possible use-after-free bugs. Work around this unfortunate design choice by nullifying the protocol (i.e. overwriting the method pointers with no-ops) and leaking the memory containing the protocol structure. Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/171/head
parent
86c6c79fcd
commit
5b41b9a80f
|
@ -0,0 +1,31 @@
|
|||
#ifndef _IPXE_EFI_NULL_H
|
||||
#define _IPXE_EFI_NULL_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* EFI null interfaces
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <ipxe/efi/efi.h>
|
||||
#include <ipxe/efi/Protocol/AppleNetBoot.h>
|
||||
#include <ipxe/efi/Protocol/BlockIo.h>
|
||||
#include <ipxe/efi/Protocol/ComponentName2.h>
|
||||
#include <ipxe/efi/Protocol/HiiConfigAccess.h>
|
||||
#include <ipxe/efi/Protocol/LoadFile.h>
|
||||
#include <ipxe/efi/Protocol/NetworkInterfaceIdentifier.h>
|
||||
#include <ipxe/efi/Protocol/PxeBaseCode.h>
|
||||
#include <ipxe/efi/Protocol/SimpleNetwork.h>
|
||||
|
||||
extern void efi_nullify_snp ( EFI_SIMPLE_NETWORK_PROTOCOL *snp );
|
||||
extern void efi_nullify_nii ( EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *nii );
|
||||
extern void efi_nullify_name2 ( EFI_COMPONENT_NAME2_PROTOCOL *name2 );
|
||||
extern void efi_nullify_load_file ( EFI_LOAD_FILE_PROTOCOL *load_file );
|
||||
extern void efi_nullify_hii ( EFI_HII_CONFIG_ACCESS_PROTOCOL *hii );
|
||||
extern void efi_nullify_block ( EFI_BLOCK_IO_PROTOCOL *block );
|
||||
extern void efi_nullify_pxe ( EFI_PXE_BASE_CODE_PROTOCOL *pxe );
|
||||
extern void efi_nullify_apple ( EFI_APPLE_NET_BOOT_PROTOCOL *apple );
|
||||
|
||||
#endif /* _IPXE_EFI_NULL_H */
|
|
@ -76,7 +76,7 @@ struct efi_snp_device {
|
|||
};
|
||||
|
||||
extern int efi_snp_hii_install ( struct efi_snp_device *snpdev );
|
||||
extern void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev );
|
||||
extern int efi_snp_hii_uninstall ( struct efi_snp_device *snpdev );
|
||||
extern struct efi_snp_device * find_snpdev ( EFI_HANDLE handle );
|
||||
extern struct efi_snp_device * last_opened_snpdev ( void );
|
||||
extern void efi_snp_add_claim ( int delta );
|
||||
|
|
|
@ -55,6 +55,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
#include <ipxe/efi/efi_strings.h>
|
||||
#include <ipxe/efi/efi_snp.h>
|
||||
#include <ipxe/efi/efi_path.h>
|
||||
#include <ipxe/efi/efi_null.h>
|
||||
#include <ipxe/efi/efi_block.h>
|
||||
|
||||
/** ACPI table protocol protocol */
|
||||
|
@ -244,6 +245,7 @@ static int efi_block_hook ( unsigned int drive, struct uri **uris,
|
|||
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
||||
struct san_device *sandev;
|
||||
struct efi_block_data *block;
|
||||
int leak = 0;
|
||||
EFI_STATUS efirc;
|
||||
int rc;
|
||||
|
||||
|
@ -317,20 +319,33 @@ static int efi_block_hook ( unsigned int drive, struct uri **uris,
|
|||
|
||||
return drive;
|
||||
|
||||
bs->UninstallMultipleProtocolInterfaces (
|
||||
if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
|
||||
block->handle,
|
||||
&efi_block_io_protocol_guid, &block->block_io,
|
||||
&efi_device_path_protocol_guid, block->path, NULL );
|
||||
&efi_device_path_protocol_guid, block->path,
|
||||
NULL ) ) != 0 ) {
|
||||
DBGC ( sandev, "EFIBLK %#02x could not uninstall protocols: "
|
||||
"%s\n", sandev->drive, strerror ( -EEFI ( efirc ) ) );
|
||||
efi_nullify_block ( &block->block_io );
|
||||
leak = 1;
|
||||
}
|
||||
err_install:
|
||||
free ( block->path );
|
||||
block->path = NULL;
|
||||
if ( ! leak ) {
|
||||
free ( block->path );
|
||||
block->path = NULL;
|
||||
}
|
||||
err_describe:
|
||||
err_active:
|
||||
unregister_sandev ( sandev );
|
||||
err_register:
|
||||
sandev_put ( sandev );
|
||||
if ( ! leak )
|
||||
sandev_put ( sandev );
|
||||
err_alloc:
|
||||
err_no_uris:
|
||||
if ( leak ) {
|
||||
DBGC ( sandev, "EFIBLK %#02x nullified and leaked\n",
|
||||
sandev->drive );
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -343,6 +358,8 @@ static void efi_block_unhook ( unsigned int drive ) {
|
|||
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
||||
struct san_device *sandev;
|
||||
struct efi_block_data *block;
|
||||
int leak = 0;
|
||||
EFI_STATUS efirc;
|
||||
|
||||
/* Find SAN device */
|
||||
sandev = sandev_find ( drive );
|
||||
|
@ -353,20 +370,35 @@ static void efi_block_unhook ( unsigned int drive ) {
|
|||
block = sandev->priv;
|
||||
|
||||
/* Uninstall protocols */
|
||||
bs->UninstallMultipleProtocolInterfaces (
|
||||
if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
|
||||
block->handle,
|
||||
&efi_block_io_protocol_guid, &block->block_io,
|
||||
&efi_device_path_protocol_guid, block->path, NULL );
|
||||
&efi_device_path_protocol_guid, block->path,
|
||||
NULL ) ) != 0 ) {
|
||||
DBGC ( sandev, "EFIBLK %#02x could not uninstall protocols: "
|
||||
"%s\n", sandev->drive, strerror ( -EEFI ( efirc ) ) );
|
||||
efi_nullify_block ( &block->block_io );
|
||||
leak = 1;
|
||||
}
|
||||
|
||||
/* Free device path */
|
||||
free ( block->path );
|
||||
block->path = NULL;
|
||||
if ( ! leak ) {
|
||||
free ( block->path );
|
||||
block->path = NULL;
|
||||
}
|
||||
|
||||
/* Unregister SAN device */
|
||||
unregister_sandev ( sandev );
|
||||
|
||||
/* Drop reference to drive */
|
||||
sandev_put ( sandev );
|
||||
if ( ! leak )
|
||||
sandev_put ( sandev );
|
||||
|
||||
/* Report leakage, if applicable */
|
||||
if ( leak ) {
|
||||
DBGC ( sandev, "EFIBLK %#02x nullified and leaked\n",
|
||||
sandev->drive );
|
||||
}
|
||||
}
|
||||
|
||||
/** An installed ACPI table */
|
||||
|
|
|
@ -0,0 +1,532 @@
|
|||
/*
|
||||
* Copyright (C) 2020 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* You can also choose to distribute this program under the terms of
|
||||
* the Unmodified Binary Distribution Licence (as given in the file
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <string.h>
|
||||
#include <ipxe/efi/efi.h>
|
||||
#include <ipxe/efi/efi_null.h>
|
||||
|
||||
/** @file
|
||||
*
|
||||
* EFI null interfaces
|
||||
*
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Simple Network Protocol
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_start ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_stop ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_initialize ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused,
|
||||
UINTN extra_rx_bufsize __unused,
|
||||
UINTN extra_tx_bufsize __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_reset ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused,
|
||||
BOOLEAN ext_verify __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_shutdown ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_receive_filters ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused,
|
||||
UINT32 enable __unused,
|
||||
UINT32 disable __unused,
|
||||
BOOLEAN mcast_reset __unused,
|
||||
UINTN mcast_count __unused,
|
||||
EFI_MAC_ADDRESS *mcast __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_station_address ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused,
|
||||
BOOLEAN reset __unused,
|
||||
EFI_MAC_ADDRESS *new __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_statistics ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused,
|
||||
BOOLEAN reset __unused, UINTN *stats_len __unused,
|
||||
EFI_NETWORK_STATISTICS *stats __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_mcast_ip_to_mac ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused,
|
||||
BOOLEAN ipv6 __unused,
|
||||
EFI_IP_ADDRESS *ip __unused,
|
||||
EFI_MAC_ADDRESS *mac __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_nvdata ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused,
|
||||
BOOLEAN read __unused, UINTN offset __unused,
|
||||
UINTN len __unused, VOID *data __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_get_status ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused,
|
||||
UINT32 *interrupts __unused, VOID **txbuf __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_transmit ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused,
|
||||
UINTN ll_header_len __unused, UINTN len __unused,
|
||||
VOID *data __unused, EFI_MAC_ADDRESS *ll_src __unused,
|
||||
EFI_MAC_ADDRESS *ll_dest __unused,
|
||||
UINT16 *net_proto __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp __unused,
|
||||
UINTN *ll_header_len __unused, UINTN *len __unused,
|
||||
VOID *data __unused, EFI_MAC_ADDRESS *ll_src __unused,
|
||||
EFI_MAC_ADDRESS *ll_dest __unused,
|
||||
UINT16 *net_proto __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_SIMPLE_NETWORK_PROTOCOL efi_null_snp = {
|
||||
.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION,
|
||||
.Start = efi_null_snp_start,
|
||||
.Stop = efi_null_snp_stop,
|
||||
.Initialize = efi_null_snp_initialize,
|
||||
.Reset = efi_null_snp_reset,
|
||||
.Shutdown = efi_null_snp_shutdown,
|
||||
.ReceiveFilters = efi_null_snp_receive_filters,
|
||||
.StationAddress = efi_null_snp_station_address,
|
||||
.Statistics = efi_null_snp_statistics,
|
||||
.MCastIpToMac = efi_null_snp_mcast_ip_to_mac,
|
||||
.NvData = efi_null_snp_nvdata,
|
||||
.GetStatus = efi_null_snp_get_status,
|
||||
.Transmit = efi_null_snp_transmit,
|
||||
.Receive = efi_null_snp_receive,
|
||||
};
|
||||
|
||||
/**
|
||||
* Nullify SNP interface
|
||||
*
|
||||
* @v snp SNP interface
|
||||
*/
|
||||
void efi_nullify_snp ( EFI_SIMPLE_NETWORK_PROTOCOL *snp ) {
|
||||
|
||||
memcpy ( snp, &efi_null_snp,
|
||||
offsetof ( typeof ( *snp ), WaitForPacket ) );
|
||||
snp->Mode->State = EfiSimpleNetworkStopped;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Network Interface Identification protocol
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
static EFIAPI VOID efi_null_undi_issue ( UINT64 cdb_phys ) {
|
||||
PXE_CDB *cdb = ( ( void * ) ( intptr_t ) cdb_phys );
|
||||
|
||||
cdb->StatCode = PXE_STATCODE_UNSUPPORTED;
|
||||
cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
|
||||
}
|
||||
|
||||
static PXE_SW_UNDI efi_null_undi __attribute__ (( aligned ( 16 ) )) = {
|
||||
.Signature = PXE_ROMID_SIGNATURE,
|
||||
.Len = sizeof ( efi_null_undi ),
|
||||
.Rev = PXE_ROMID_REV,
|
||||
.MajorVer = PXE_ROMID_MAJORVER,
|
||||
.MinorVer = PXE_ROMID_MINORVER,
|
||||
.Implementation = PXE_ROMID_IMP_SW_VIRT_ADDR,
|
||||
};
|
||||
|
||||
/**
|
||||
* Nullify NII interface
|
||||
*
|
||||
* @v nii NII interface
|
||||
*/
|
||||
void efi_nullify_nii ( EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *nii ) {
|
||||
efi_null_undi.EntryPoint = ( ( intptr_t ) efi_null_undi_issue );
|
||||
nii->Id = ( ( intptr_t ) &efi_null_undi );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Component name protocol
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_get_driver_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2 __unused,
|
||||
CHAR8 *language __unused,
|
||||
CHAR16 **driver_name __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_get_controller_name ( EFI_COMPONENT_NAME2_PROTOCOL *name2 __unused,
|
||||
EFI_HANDLE device __unused,
|
||||
EFI_HANDLE child __unused,
|
||||
CHAR8 *language __unused,
|
||||
CHAR16 **controller_name __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_COMPONENT_NAME2_PROTOCOL efi_null_name2 = {
|
||||
.GetDriverName = efi_null_get_driver_name,
|
||||
.GetControllerName = efi_null_get_controller_name,
|
||||
.SupportedLanguages = "",
|
||||
};
|
||||
|
||||
/**
|
||||
* Nullify Component Name Protocol interface
|
||||
*
|
||||
* @v name2 Component name protocol
|
||||
*/
|
||||
void efi_nullify_name2 ( EFI_COMPONENT_NAME2_PROTOCOL *name2 ) {
|
||||
|
||||
memcpy ( name2, &efi_null_name2, sizeof ( name2 ) );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Load file protocol
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_load_file ( EFI_LOAD_FILE_PROTOCOL *load_file __unused,
|
||||
EFI_DEVICE_PATH_PROTOCOL *path __unused,
|
||||
BOOLEAN booting __unused, UINTN *len __unused,
|
||||
VOID *data __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nullify Load File Protocol interface
|
||||
*
|
||||
* @v load_file Load file protocol
|
||||
*/
|
||||
void efi_nullify_load_file ( EFI_LOAD_FILE_PROTOCOL *load_file ) {
|
||||
load_file->LoadFile = efi_null_load_file;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* HII configuration access protocol
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_hii_extract ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii __unused,
|
||||
EFI_STRING request __unused,
|
||||
EFI_STRING *progress __unused,
|
||||
EFI_STRING *results __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_hii_route ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii __unused,
|
||||
EFI_STRING config __unused,
|
||||
EFI_STRING *progress __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_hii_callback ( const EFI_HII_CONFIG_ACCESS_PROTOCOL *hii __unused,
|
||||
EFI_BROWSER_ACTION action __unused,
|
||||
EFI_QUESTION_ID question_id __unused,
|
||||
UINT8 type __unused, EFI_IFR_TYPE_VALUE *value __unused,
|
||||
EFI_BROWSER_ACTION_REQUEST *action_request __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_HII_CONFIG_ACCESS_PROTOCOL efi_null_hii = {
|
||||
.ExtractConfig = efi_null_hii_extract,
|
||||
.RouteConfig = efi_null_hii_route,
|
||||
.Callback = efi_null_hii_callback,
|
||||
};
|
||||
|
||||
/**
|
||||
* Nullify HII configuration access protocol
|
||||
*
|
||||
* @v hii HII configuration access protocol
|
||||
*/
|
||||
void efi_nullify_hii ( EFI_HII_CONFIG_ACCESS_PROTOCOL *hii ) {
|
||||
|
||||
memcpy ( hii, &efi_null_hii, sizeof ( *hii ) );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Block I/O protocol
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_block_reset ( EFI_BLOCK_IO_PROTOCOL *block __unused,
|
||||
BOOLEAN verify __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_block_read ( EFI_BLOCK_IO_PROTOCOL *block __unused,
|
||||
UINT32 media __unused, EFI_LBA lba __unused,
|
||||
UINTN len __unused, VOID *data __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_block_write ( EFI_BLOCK_IO_PROTOCOL *block __unused,
|
||||
UINT32 media __unused, EFI_LBA lba __unused,
|
||||
UINTN len __unused, VOID *data __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_block_flush ( EFI_BLOCK_IO_PROTOCOL *block __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_BLOCK_IO_MEDIA efi_null_block_media;
|
||||
|
||||
static EFI_BLOCK_IO_PROTOCOL efi_null_block = {
|
||||
.Revision = EFI_BLOCK_IO_INTERFACE_REVISION,
|
||||
.Media = &efi_null_block_media,
|
||||
.Reset = efi_null_block_reset,
|
||||
.ReadBlocks = efi_null_block_read,
|
||||
.WriteBlocks = efi_null_block_write,
|
||||
.FlushBlocks = efi_null_block_flush,
|
||||
};
|
||||
|
||||
/**
|
||||
* Nullify block I/O protocol
|
||||
*
|
||||
* @v block Block I/O protocol
|
||||
*/
|
||||
void efi_nullify_block ( EFI_BLOCK_IO_PROTOCOL *block ) {
|
||||
|
||||
memcpy ( block, &efi_null_block, sizeof ( *block ) );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* PXE base code protocol
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_pxe_start ( EFI_PXE_BASE_CODE_PROTOCOL *pxe __unused,
|
||||
BOOLEAN use_ipv6 __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_pxe_stop ( EFI_PXE_BASE_CODE_PROTOCOL *pxe __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_pxe_dhcp ( EFI_PXE_BASE_CODE_PROTOCOL *pxe __unused,
|
||||
BOOLEAN sort __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_pxe_discover ( EFI_PXE_BASE_CODE_PROTOCOL *pxe __unused,
|
||||
UINT16 type __unused, UINT16 *layer __unused,
|
||||
BOOLEAN bis __unused,
|
||||
EFI_PXE_BASE_CODE_DISCOVER_INFO *info __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_pxe_mtftp ( EFI_PXE_BASE_CODE_PROTOCOL *pxe __unused,
|
||||
EFI_PXE_BASE_CODE_TFTP_OPCODE opcode __unused,
|
||||
VOID *data __unused, BOOLEAN overwrite __unused,
|
||||
UINT64 *len __unused, UINTN *blksize __unused,
|
||||
EFI_IP_ADDRESS *ip __unused, UINT8 *filename __unused,
|
||||
EFI_PXE_BASE_CODE_MTFTP_INFO *info __unused,
|
||||
BOOLEAN callback __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_pxe_udp_write ( EFI_PXE_BASE_CODE_PROTOCOL *pxe __unused,
|
||||
UINT16 flags __unused,
|
||||
EFI_IP_ADDRESS *dest_ip __unused,
|
||||
EFI_PXE_BASE_CODE_UDP_PORT *dest_port __unused,
|
||||
EFI_IP_ADDRESS *gateway __unused,
|
||||
EFI_IP_ADDRESS *src_ip __unused,
|
||||
EFI_PXE_BASE_CODE_UDP_PORT *src_port __unused,
|
||||
UINTN *hdr_len __unused, VOID *hdr __unused,
|
||||
UINTN *len __unused, VOID *data __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_pxe_udp_read ( EFI_PXE_BASE_CODE_PROTOCOL *pxe __unused,
|
||||
UINT16 flags __unused,
|
||||
EFI_IP_ADDRESS *dest_ip __unused,
|
||||
EFI_PXE_BASE_CODE_UDP_PORT *dest_port __unused,
|
||||
EFI_IP_ADDRESS *src_ip __unused,
|
||||
EFI_PXE_BASE_CODE_UDP_PORT *src_port __unused,
|
||||
UINTN *hdr_len __unused, VOID *hdr __unused,
|
||||
UINTN *len __unused, VOID *data __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_pxe_set_ip_filter ( EFI_PXE_BASE_CODE_PROTOCOL *pxe __unused,
|
||||
EFI_PXE_BASE_CODE_IP_FILTER *filter __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_pxe_arp ( EFI_PXE_BASE_CODE_PROTOCOL *pxe __unused,
|
||||
EFI_IP_ADDRESS *ip __unused,
|
||||
EFI_MAC_ADDRESS *mac __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_pxe_set_parameters ( EFI_PXE_BASE_CODE_PROTOCOL *pxe __unused,
|
||||
BOOLEAN *autoarp __unused,
|
||||
BOOLEAN *sendguid __unused, UINT8 *ttl __unused,
|
||||
UINT8 *tos __unused,
|
||||
BOOLEAN *callback __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_pxe_set_station_ip ( EFI_PXE_BASE_CODE_PROTOCOL *pxe __unused,
|
||||
EFI_IP_ADDRESS *ip __unused,
|
||||
EFI_IP_ADDRESS *netmask __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_pxe_set_packets ( EFI_PXE_BASE_CODE_PROTOCOL *pxe __unused,
|
||||
BOOLEAN *dhcpdisc_ok __unused,
|
||||
BOOLEAN *dhcpack_ok __unused,
|
||||
BOOLEAN *proxyoffer_ok __unused,
|
||||
BOOLEAN *pxebsdisc_ok __unused,
|
||||
BOOLEAN *pxebsack_ok __unused,
|
||||
BOOLEAN *pxebsbis_ok __unused,
|
||||
EFI_PXE_BASE_CODE_PACKET *dhcpdisc __unused,
|
||||
EFI_PXE_BASE_CODE_PACKET *dhcpack __unused,
|
||||
EFI_PXE_BASE_CODE_PACKET *proxyoffer __unused,
|
||||
EFI_PXE_BASE_CODE_PACKET *pxebsdisc __unused,
|
||||
EFI_PXE_BASE_CODE_PACKET *pxebsack __unused,
|
||||
EFI_PXE_BASE_CODE_PACKET *pxebsbis __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_PXE_BASE_CODE_PROTOCOL efi_null_pxe = {
|
||||
.Revision = EFI_PXE_BASE_CODE_PROTOCOL_REVISION,
|
||||
.Start = efi_null_pxe_start,
|
||||
.Stop = efi_null_pxe_stop,
|
||||
.Dhcp = efi_null_pxe_dhcp,
|
||||
.Discover = efi_null_pxe_discover,
|
||||
.Mtftp = efi_null_pxe_mtftp,
|
||||
.UdpWrite = efi_null_pxe_udp_write,
|
||||
.UdpRead = efi_null_pxe_udp_read,
|
||||
.SetIpFilter = efi_null_pxe_set_ip_filter,
|
||||
.Arp = efi_null_pxe_arp,
|
||||
.SetParameters = efi_null_pxe_set_parameters,
|
||||
.SetStationIp = efi_null_pxe_set_station_ip,
|
||||
.SetPackets = efi_null_pxe_set_packets,
|
||||
};
|
||||
|
||||
/**
|
||||
* Nullify PXE base code protocol
|
||||
*
|
||||
* @v pxe PXE base code protocol
|
||||
*/
|
||||
void efi_nullify_pxe ( EFI_PXE_BASE_CODE_PROTOCOL *pxe ) {
|
||||
|
||||
memcpy ( pxe, &efi_null_pxe, offsetof ( typeof ( *pxe ), Mode ) );
|
||||
pxe->Mode->Started = FALSE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Apple Net Boot protocol
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_apple_dhcp ( EFI_APPLE_NET_BOOT_PROTOCOL *apple __unused,
|
||||
UINTN *len __unused, VOID *data __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_STATUS EFIAPI
|
||||
efi_null_apple_bsdp ( EFI_APPLE_NET_BOOT_PROTOCOL *apple __unused,
|
||||
UINTN *len __unused, VOID *data __unused ) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static EFI_APPLE_NET_BOOT_PROTOCOL efi_null_apple = {
|
||||
.GetDhcpResponse = efi_null_apple_dhcp,
|
||||
.GetBsdpResponse = efi_null_apple_bsdp,
|
||||
};
|
||||
|
||||
/**
|
||||
* Nullify Apple Net Boot protocol
|
||||
*
|
||||
* @v apple Apple Net Boot protocol
|
||||
*/
|
||||
void efi_nullify_apple ( EFI_APPLE_NET_BOOT_PROTOCOL *apple ) {
|
||||
|
||||
memcpy ( apple, &efi_null_apple, sizeof ( *apple ) );
|
||||
}
|
|
@ -41,6 +41,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
#include <ipxe/efi/efi.h>
|
||||
#include <ipxe/efi/efi_snp.h>
|
||||
#include <ipxe/efi/efi_pxe.h>
|
||||
#include <ipxe/efi/efi_null.h>
|
||||
#include <ipxe/efi/Protocol/PxeBaseCode.h>
|
||||
#include <ipxe/efi/Protocol/AppleNetBoot.h>
|
||||
#include <usr/ifmgmt.h>
|
||||
|
@ -1591,6 +1592,7 @@ int efi_pxe_install ( EFI_HANDLE handle, struct net_device *netdev ) {
|
|||
struct efi_pxe *pxe;
|
||||
struct in_addr ip;
|
||||
BOOLEAN use_ipv6;
|
||||
int leak = 0;
|
||||
EFI_STATUS efirc;
|
||||
int rc;
|
||||
|
||||
|
@ -1643,14 +1645,23 @@ int efi_pxe_install ( EFI_HANDLE handle, struct net_device *netdev ) {
|
|||
pxe->name, efi_handle_name ( handle ) );
|
||||
return 0;
|
||||
|
||||
bs->UninstallMultipleProtocolInterfaces (
|
||||
if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
|
||||
handle,
|
||||
&efi_pxe_base_code_protocol_guid, &pxe->base,
|
||||
&efi_apple_net_boot_protocol_guid, &pxe->apple,
|
||||
NULL );
|
||||
NULL ) ) != 0 ) {
|
||||
DBGC ( pxe, "PXE %s could not uninstall: %s\n",
|
||||
pxe->name, strerror ( -EEFI ( efirc ) ) );
|
||||
efi_nullify_pxe ( &pxe->base );
|
||||
efi_nullify_apple ( &pxe->apple );
|
||||
leak = 1;
|
||||
}
|
||||
err_install_protocol:
|
||||
ref_put ( &pxe->refcnt );
|
||||
if ( ! leak )
|
||||
ref_put ( &pxe->refcnt );
|
||||
err_alloc:
|
||||
if ( leak )
|
||||
DBGC ( pxe, "PXE %s nullified and leaked\n", pxe->name );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1662,6 +1673,8 @@ int efi_pxe_install ( EFI_HANDLE handle, struct net_device *netdev ) {
|
|||
void efi_pxe_uninstall ( EFI_HANDLE handle ) {
|
||||
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
||||
struct efi_pxe *pxe;
|
||||
int leak = 0;
|
||||
EFI_STATUS efirc;
|
||||
|
||||
/* Locate PXE base code */
|
||||
pxe = efi_pxe_find ( handle );
|
||||
|
@ -1675,13 +1688,24 @@ void efi_pxe_uninstall ( EFI_HANDLE handle ) {
|
|||
efi_pxe_stop ( &pxe->base );
|
||||
|
||||
/* Uninstall PXE base code protocol */
|
||||
bs->UninstallMultipleProtocolInterfaces (
|
||||
if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
|
||||
handle,
|
||||
&efi_pxe_base_code_protocol_guid, &pxe->base,
|
||||
&efi_apple_net_boot_protocol_guid, &pxe->apple,
|
||||
NULL );
|
||||
NULL ) ) != 0 ) {
|
||||
DBGC ( pxe, "PXE %s could not uninstall: %s\n",
|
||||
pxe->name, strerror ( -EEFI ( efirc ) ) );
|
||||
efi_nullify_pxe ( &pxe->base );
|
||||
efi_nullify_apple ( &pxe->apple );
|
||||
leak = 1;
|
||||
}
|
||||
|
||||
/* Remove from list and drop list's reference */
|
||||
list_del ( &pxe->list );
|
||||
ref_put ( &pxe->refcnt );
|
||||
if ( ! leak )
|
||||
ref_put ( &pxe->refcnt );
|
||||
|
||||
/* Report leakage, if applicable */
|
||||
if ( leak )
|
||||
DBGC ( pxe, "PXE %s nullified and leaked\n", pxe->name );
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
|||
#include <ipxe/efi/efi_path.h>
|
||||
#include <ipxe/efi/efi_utils.h>
|
||||
#include <ipxe/efi/efi_watchdog.h>
|
||||
#include <ipxe/efi/efi_null.h>
|
||||
#include <ipxe/efi/efi_snp.h>
|
||||
#include <usr/autoboot.h>
|
||||
#include <config/general.h>
|
||||
|
@ -1626,6 +1627,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
|
|||
struct efi_snp_device *snpdev;
|
||||
unsigned int ifcnt;
|
||||
void *interface;
|
||||
int leak = 0;
|
||||
EFI_STATUS efirc;
|
||||
int rc;
|
||||
|
||||
|
@ -1794,7 +1796,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
|
|||
|
||||
list_del ( &snpdev->list );
|
||||
if ( snpdev->package_list )
|
||||
efi_snp_hii_uninstall ( snpdev );
|
||||
leak |= efi_snp_hii_uninstall ( snpdev );
|
||||
efi_child_del ( efidev->device, snpdev->handle );
|
||||
err_efi_child_add:
|
||||
bs->CloseProtocol ( snpdev->handle, &efi_nii31_protocol_guid,
|
||||
|
@ -1803,7 +1805,7 @@ static int efi_snp_probe ( struct net_device *netdev ) {
|
|||
bs->CloseProtocol ( snpdev->handle, &efi_nii_protocol_guid,
|
||||
efi_image_handle, snpdev->handle );
|
||||
err_open_nii:
|
||||
bs->UninstallMultipleProtocolInterfaces (
|
||||
if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
|
||||
snpdev->handle,
|
||||
&efi_simple_network_protocol_guid, &snpdev->snp,
|
||||
&efi_device_path_protocol_guid, snpdev->path,
|
||||
|
@ -1811,17 +1813,30 @@ static int efi_snp_probe ( struct net_device *netdev ) {
|
|||
&efi_nii31_protocol_guid, &snpdev->nii,
|
||||
&efi_component_name2_protocol_guid, &snpdev->name2,
|
||||
&efi_load_file_protocol_guid, &snpdev->load_file,
|
||||
NULL );
|
||||
NULL ) ) != 0 ) {
|
||||
DBGC ( snpdev, "SNPDEV %p could not uninstall: %s\n",
|
||||
snpdev, strerror ( -EEFI ( efirc ) ) );
|
||||
efi_nullify_snp ( &snpdev->snp );
|
||||
efi_nullify_nii ( &snpdev->nii );
|
||||
efi_nullify_name2 ( &snpdev->name2 );
|
||||
efi_nullify_load_file ( &snpdev->load_file );
|
||||
leak = 1;
|
||||
}
|
||||
err_install_protocol_interface:
|
||||
free ( snpdev->path );
|
||||
if ( ! leak )
|
||||
free ( snpdev->path );
|
||||
err_path:
|
||||
bs->CloseEvent ( snpdev->snp.WaitForPacket );
|
||||
err_create_event:
|
||||
err_ll_addr_len:
|
||||
netdev_put ( netdev );
|
||||
free ( snpdev );
|
||||
if ( ! leak ) {
|
||||
netdev_put ( netdev );
|
||||
free ( snpdev );
|
||||
}
|
||||
err_alloc_snp:
|
||||
err_no_efidev:
|
||||
if ( leak )
|
||||
DBGC ( snpdev, "SNPDEV %p nullified and leaked\n", snpdev );
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1858,6 +1873,8 @@ static void efi_snp_notify ( struct net_device *netdev ) {
|
|||
static void efi_snp_remove ( struct net_device *netdev ) {
|
||||
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
||||
struct efi_snp_device *snpdev;
|
||||
int leak = 0;
|
||||
EFI_STATUS efirc;
|
||||
|
||||
/* Locate SNP device */
|
||||
snpdev = efi_snp_demux ( netdev );
|
||||
|
@ -1869,13 +1886,13 @@ static void efi_snp_remove ( struct net_device *netdev ) {
|
|||
/* Uninstall the SNP */
|
||||
list_del ( &snpdev->list );
|
||||
if ( snpdev->package_list )
|
||||
efi_snp_hii_uninstall ( snpdev );
|
||||
leak |= efi_snp_hii_uninstall ( snpdev );
|
||||
efi_child_del ( snpdev->efidev->device, snpdev->handle );
|
||||
bs->CloseProtocol ( snpdev->handle, &efi_nii_protocol_guid,
|
||||
efi_image_handle, snpdev->handle );
|
||||
bs->CloseProtocol ( snpdev->handle, &efi_nii31_protocol_guid,
|
||||
efi_image_handle, snpdev->handle );
|
||||
bs->UninstallMultipleProtocolInterfaces (
|
||||
if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
|
||||
snpdev->handle,
|
||||
&efi_simple_network_protocol_guid, &snpdev->snp,
|
||||
&efi_device_path_protocol_guid, snpdev->path,
|
||||
|
@ -1883,11 +1900,26 @@ static void efi_snp_remove ( struct net_device *netdev ) {
|
|||
&efi_nii31_protocol_guid, &snpdev->nii,
|
||||
&efi_component_name2_protocol_guid, &snpdev->name2,
|
||||
&efi_load_file_protocol_guid, &snpdev->load_file,
|
||||
NULL );
|
||||
free ( snpdev->path );
|
||||
NULL ) ) != 0 ) {
|
||||
DBGC ( snpdev, "SNPDEV %p could not uninstall: %s\n",
|
||||
snpdev, strerror ( -EEFI ( efirc ) ) );
|
||||
efi_nullify_snp ( &snpdev->snp );
|
||||
efi_nullify_nii ( &snpdev->nii );
|
||||
efi_nullify_name2 ( &snpdev->name2 );
|
||||
efi_nullify_load_file ( &snpdev->load_file );
|
||||
leak = 1;
|
||||
}
|
||||
if ( ! leak )
|
||||
free ( snpdev->path );
|
||||
bs->CloseEvent ( snpdev->snp.WaitForPacket );
|
||||
netdev_put ( snpdev->netdev );
|
||||
free ( snpdev );
|
||||
if ( ! leak ) {
|
||||
netdev_put ( snpdev->netdev );
|
||||
free ( snpdev );
|
||||
}
|
||||
|
||||
/* Report leakage, if applicable */
|
||||
if ( leak )
|
||||
DBGC ( snpdev, "SNPDEV %p nullified and leaked\n", snpdev );
|
||||
}
|
||||
|
||||
/** SNP driver */
|
||||
|
|
|
@ -65,6 +65,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
#include <ipxe/efi/efi_strings.h>
|
||||
#include <ipxe/efi/efi_path.h>
|
||||
#include <ipxe/efi/efi_utils.h>
|
||||
#include <ipxe/efi/efi_null.h>
|
||||
#include <config/branding.h>
|
||||
|
||||
/** EFI platform setup formset GUID */
|
||||
|
@ -659,7 +660,8 @@ int efi_snp_hii_install ( struct efi_snp_device *snpdev ) {
|
|||
VENDOR_DEVICE_PATH *vendor_path;
|
||||
EFI_DEVICE_PATH_PROTOCOL *path_end;
|
||||
size_t path_prefix_len;
|
||||
int efirc;
|
||||
int leak = 0;
|
||||
EFI_STATUS efirc;
|
||||
int rc;
|
||||
|
||||
/* Do nothing if HII database protocol is not supported */
|
||||
|
@ -751,23 +753,37 @@ int efi_snp_hii_install ( struct efi_snp_device *snpdev ) {
|
|||
|
||||
efi_child_del ( snpdev->handle, snpdev->hii_child_handle );
|
||||
err_efi_child_add:
|
||||
bs->UninstallMultipleProtocolInterfaces (
|
||||
if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
|
||||
snpdev->hii_child_handle,
|
||||
&efi_hii_config_access_protocol_guid, &snpdev->hii,
|
||||
NULL );
|
||||
NULL ) ) != 0 ) {
|
||||
DBGC ( snpdev, "SNPDEV %p could not uninstall HII protocol: "
|
||||
"%s\n", snpdev, strerror ( -EEFI ( efirc ) ) );
|
||||
efi_nullify_hii ( &snpdev->hii );
|
||||
leak = 1;
|
||||
}
|
||||
err_install_protocol:
|
||||
efihii->RemovePackageList ( efihii, snpdev->hii_handle );
|
||||
if ( ! leak )
|
||||
efihii->RemovePackageList ( efihii, snpdev->hii_handle );
|
||||
err_new_package_list:
|
||||
bs->UninstallMultipleProtocolInterfaces (
|
||||
if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
|
||||
snpdev->hii_child_handle,
|
||||
&efi_device_path_protocol_guid, snpdev->hii_child_path,
|
||||
NULL );
|
||||
NULL ) ) != 0 ) {
|
||||
DBGC ( snpdev, "SNPDEV %p could not uninstall HII path: %s\n",
|
||||
snpdev, strerror ( -EEFI ( efirc ) ) );
|
||||
leak = 1;
|
||||
}
|
||||
err_hii_child_handle:
|
||||
free ( snpdev->hii_child_path );
|
||||
snpdev->hii_child_path = NULL;
|
||||
if ( ! leak ) {
|
||||
free ( snpdev->hii_child_path );
|
||||
snpdev->hii_child_path = NULL;
|
||||
}
|
||||
err_alloc_child_path:
|
||||
free ( snpdev->package_list );
|
||||
snpdev->package_list = NULL;
|
||||
if ( ! leak ) {
|
||||
free ( snpdev->package_list );
|
||||
snpdev->package_list = NULL;
|
||||
}
|
||||
err_build_package_list:
|
||||
err_no_hii:
|
||||
return rc;
|
||||
|
@ -777,27 +793,47 @@ int efi_snp_hii_install ( struct efi_snp_device *snpdev ) {
|
|||
* Uninstall HII protocol and package for SNP device
|
||||
*
|
||||
* @v snpdev SNP device
|
||||
* @ret leak Uninstallation failed: leak memory
|
||||
*/
|
||||
void efi_snp_hii_uninstall ( struct efi_snp_device *snpdev ) {
|
||||
int efi_snp_hii_uninstall ( struct efi_snp_device *snpdev ) {
|
||||
EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
|
||||
int leak = 0;
|
||||
EFI_STATUS efirc;
|
||||
|
||||
/* Do nothing if HII database protocol is not supported */
|
||||
if ( ! efihii )
|
||||
return;
|
||||
return 0;
|
||||
|
||||
/* Uninstall protocols and remove package list */
|
||||
efi_child_del ( snpdev->handle, snpdev->hii_child_handle );
|
||||
bs->UninstallMultipleProtocolInterfaces (
|
||||
if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
|
||||
snpdev->hii_child_handle,
|
||||
&efi_hii_config_access_protocol_guid, &snpdev->hii,
|
||||
NULL );
|
||||
efihii->RemovePackageList ( efihii, snpdev->hii_handle );
|
||||
bs->UninstallMultipleProtocolInterfaces (
|
||||
NULL ) ) != 0 ) {
|
||||
DBGC ( snpdev, "SNPDEV %p could not uninstall HII protocol: "
|
||||
"%s\n", snpdev, strerror ( -EEFI ( efirc ) ) );
|
||||
efi_nullify_hii ( &snpdev->hii );
|
||||
leak = 1;
|
||||
}
|
||||
if ( ! leak )
|
||||
efihii->RemovePackageList ( efihii, snpdev->hii_handle );
|
||||
if ( ( efirc = bs->UninstallMultipleProtocolInterfaces (
|
||||
snpdev->hii_child_handle,
|
||||
&efi_device_path_protocol_guid, snpdev->hii_child_path,
|
||||
NULL );
|
||||
free ( snpdev->hii_child_path );
|
||||
snpdev->hii_child_path = NULL;
|
||||
free ( snpdev->package_list );
|
||||
snpdev->package_list = NULL;
|
||||
NULL ) ) != 0 ) {
|
||||
DBGC ( snpdev, "SNPDEV %p could not uninstall HII path: %s\n",
|
||||
snpdev, strerror ( -EEFI ( efirc ) ) );
|
||||
leak = 1;
|
||||
}
|
||||
if ( ! leak ) {
|
||||
free ( snpdev->hii_child_path );
|
||||
snpdev->hii_child_path = NULL;
|
||||
free ( snpdev->package_list );
|
||||
snpdev->package_list = NULL;
|
||||
}
|
||||
|
||||
/* Report leakage, if applicable */
|
||||
if ( leak )
|
||||
DBGC ( snpdev, "SNPDEV %p HII nullified and leaked\n", snpdev );
|
||||
return leak;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue