*
*/
+/** Dummy parent device path
+ *
+ * This is used as the parent device path when we need to construct a
+ * path for a device that has no EFI parent device.
+ */
+static struct {
+ BBS_BBS_DEVICE_PATH bbs;
+ CHAR8 tring[4];
+ EFI_DEVICE_PATH_PROTOCOL end;
+} __attribute__ (( packed )) efi_dummy_parent_path = {
+ .bbs = {
+ .Header = {
+ .Type = BBS_DEVICE_PATH,
+ .SubType = BBS_BBS_DP,
+ .Length[0] = ( sizeof ( efi_dummy_parent_path.bbs ) +
+ sizeof ( efi_dummy_parent_path.tring )),
+ },
+ .DeviceType = BBS_TYPE_UNKNOWN,
+ .String[0] = 'i',
+ },
+ .tring = "PXE",
+ .end = {
+ .Type = END_DEVICE_PATH_TYPE,
+ .SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ .Length[0] = sizeof ( efi_dummy_parent_path.end ),
+ },
+};
+
/** An EFI device path settings block */
struct efi_path_settings {
/** Settings interface */
return path;
}
+/**
+ * Construct EFI parent device path
+ *
+ * @v dev Generic device
+ * @ret path Parent (or dummy) device path
+ */
+static EFI_DEVICE_PATH_PROTOCOL * efi_parent_path ( struct device *dev ) {
+ struct efi_device *efidev;
+
+ /* Use EFI parent device's path, if possible */
+ efidev = efidev_parent ( dev );
+ if ( efidev )
+ return efidev->path;
+
+ /* Otherwise, use a dummy parent device path */
+ return &efi_dummy_parent_path.bbs.Header;
+}
+
/**
* Construct EFI device path for network device
*
* allocated device path.
*/
EFI_DEVICE_PATH_PROTOCOL * efi_netdev_path ( struct net_device *netdev ) {
- struct efi_device *efidev;
+ EFI_DEVICE_PATH_PROTOCOL *parent;
EFI_DEVICE_PATH_PROTOCOL *path;
MAC_ADDR_DEVICE_PATH *macpath;
VLAN_DEVICE_PATH *vlanpath;
size_t prefix_len;
size_t len;
- /* Find parent EFI device */
- efidev = efidev_parent ( netdev->dev );
- if ( ! efidev )
- return NULL;
+ /* Get parent EFI device path */
+ parent = efi_parent_path ( netdev->dev );
/* Calculate device path length */
- prefix_len = efi_path_len ( efidev->path );
+ prefix_len = efi_path_len ( parent );
len = ( prefix_len + sizeof ( *macpath ) + sizeof ( *vlanpath ) +
sizeof ( *end ) );
return NULL;
/* Construct device path */
- memcpy ( path, efidev->path, prefix_len );
+ memcpy ( path, parent, prefix_len );
macpath = ( ( ( void * ) path ) + prefix_len );
macpath->Header.Type = MESSAGING_DEVICE_PATH;
macpath->Header.SubType = MSG_MAC_ADDR_DP;
union ib_srp_target_port_id *id =
container_of ( &sbft->srp.target, union ib_srp_target_port_id,
srp );
- struct efi_device *efidev;
+ EFI_DEVICE_PATH_PROTOCOL *parent;
EFI_DEVICE_PATH_PROTOCOL *path;
INFINIBAND_DEVICE_PATH *ibpath;
EFI_DEVICE_PATH_PROTOCOL *end;
size_t prefix_len;
size_t len;
- /* Find parent EFI device */
- efidev = efidev_parent ( ib_srp->ibdev->dev );
- if ( ! efidev )
- return NULL;
+ /* Get parent EFI device path */
+ parent = efi_parent_path ( ib_srp->ibdev->dev );
/* Calculate device path length */
- prefix_len = efi_path_len ( efidev->path );
+ prefix_len = efi_path_len ( parent );
len = ( prefix_len + sizeof ( *ibpath ) + sizeof ( *end ) );
/* Allocate device path */
return NULL;
/* Construct device path */
- memcpy ( path, efidev->path, prefix_len );
+ memcpy ( path, parent, prefix_len );
ibpath = ( ( ( void * ) path ) + prefix_len );
ibpath->Header.Type = MESSAGING_DEVICE_PATH;
ibpath->Header.SubType = MSG_INFINIBAND_DP;
*/
EFI_DEVICE_PATH_PROTOCOL * efi_usb_path ( struct usb_function *func ) {
struct usb_device *usb = func->usb;
- struct efi_device *efidev;
+ EFI_DEVICE_PATH_PROTOCOL *parent;
EFI_DEVICE_PATH_PROTOCOL *path;
EFI_DEVICE_PATH_PROTOCOL *end;
USB_DEVICE_PATH *usbpath;
/* Sanity check */
assert ( func->desc.count >= 1 );
- /* Find parent EFI device */
- efidev = efidev_parent ( &func->dev );
- if ( ! efidev )
- return NULL;
+ /* Get parent EFI device path */
+ parent = efi_parent_path ( &func->dev );
/* Calculate device path length */
count = ( usb_depth ( usb ) + 1 );
- prefix_len = efi_path_len ( efidev->path );
+ prefix_len = efi_path_len ( parent );
len = ( prefix_len + ( count * sizeof ( *usbpath ) ) +
sizeof ( *end ) );
return NULL;
/* Construct device path */
- memcpy ( path, efidev->path, prefix_len );
+ memcpy ( path, parent, prefix_len );
end = ( ( ( void * ) path ) + len - sizeof ( *end ) );
efi_path_terminate ( end );
usbpath = ( ( ( void * ) end ) - sizeof ( *usbpath ) );
EFI_STATUS efirc;
int rc;
- /* Find parent EFI device */
- efidev = efidev_parent ( netdev->dev );
- if ( ! efidev ) {
- DBG ( "SNP skipping non-EFI device %s\n", netdev->name );
- rc = 0;
- goto err_no_efidev;
- }
-
/* Allocate the SNP device */
snpdev = zalloc ( sizeof ( *snpdev ) );
if ( ! snpdev ) {
goto err_alloc_snp;
}
snpdev->netdev = netdev_get ( netdev );
- snpdev->efidev = efidev;
INIT_LIST_HEAD ( &snpdev->rx );
+ /* Find parent EFI device, if any */
+ efidev = efidev_parent ( netdev->dev );
+ if ( efidev )
+ snpdev->parent = efidev->device;
+
/* Sanity check */
if ( netdev->ll_protocol->ll_addr_len > sizeof ( EFI_MAC_ADDRESS ) ) {
DBGC ( snpdev, "SNPDEV %p cannot support link-layer address "
goto err_open_nii31;
}
- /* Add as child of EFI parent device */
- if ( ( rc = efi_child_add ( efidev->device, snpdev->handle ) ) != 0 ) {
+ /* Add as child of EFI parent device, if applicable */
+ if ( snpdev->parent &&
+ ( ( rc = efi_child_add ( snpdev->parent,
+ snpdev->handle ) ) != 0 ) ) {
DBGC ( snpdev, "SNPDEV %p could not become child of %s: %s\n",
snpdev, efi_handle_name ( efidev->device ),
strerror ( rc ) );
list_del ( &snpdev->list );
if ( snpdev->package_list )
leak |= efi_snp_hii_uninstall ( snpdev );
- efi_child_del ( efidev->device, snpdev->handle );
+ if ( snpdev->parent )
+ efi_child_del ( snpdev->parent, snpdev->handle );
err_efi_child_add:
efi_close_by_driver ( snpdev->handle, &efi_nii31_protocol_guid );
err_open_nii31:
free ( snpdev );
}
err_alloc_snp:
- err_no_efidev:
if ( leak )
DBGC ( snpdev, "SNPDEV %p nullified and leaked\n", snpdev );
return rc;
list_del ( &snpdev->list );
if ( snpdev->package_list )
leak |= efi_snp_hii_uninstall ( snpdev );
- efi_child_del ( snpdev->efidev->device, snpdev->handle );
+ if ( snpdev->parent )
+ efi_child_del ( snpdev->parent, snpdev->handle );
efi_close_by_driver ( snpdev->handle, &efi_nii_protocol_guid );
efi_close_by_driver ( snpdev->handle, &efi_nii31_protocol_guid );
if ( ( ! efi_shutdown_in_progress ) &&