mirror of
https://github.com/u-boot/u-boot.git
synced 2025-05-08 19:11:53 +00:00
efi_driver: fix error handling
If creating the block device fails, * delete all created objects and references * close the protocol interface on the controller Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
This commit is contained in:
parent
16b27b67c5
commit
43a5891c66
3 changed files with 45 additions and 38 deletions
|
@ -25,7 +25,7 @@
|
||||||
struct efi_driver_ops {
|
struct efi_driver_ops {
|
||||||
const efi_guid_t *protocol;
|
const efi_guid_t *protocol;
|
||||||
const efi_guid_t *child_protocol;
|
const efi_guid_t *child_protocol;
|
||||||
int (*bind)(efi_handle_t handle, void *interface);
|
efi_status_t (*bind)(efi_handle_t handle, void *interface);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -112,12 +112,13 @@ static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt,
|
||||||
*
|
*
|
||||||
* @handle: handle
|
* @handle: handle
|
||||||
* @interface: block io protocol
|
* @interface: block io protocol
|
||||||
* Return: 0 = success
|
* Return: status code
|
||||||
*/
|
*/
|
||||||
static int efi_bl_bind(efi_handle_t handle, void *interface)
|
static efi_status_t efi_bl_bind(efi_handle_t handle, void *interface)
|
||||||
{
|
{
|
||||||
struct udevice *bdev, *parent = dm_root();
|
struct udevice *bdev = NULL, *parent = dm_root();
|
||||||
int ret, devnum;
|
efi_status_t ret;
|
||||||
|
int devnum;
|
||||||
char *name;
|
char *name;
|
||||||
struct efi_object *obj = efi_search_obj(handle);
|
struct efi_object *obj = efi_search_obj(handle);
|
||||||
struct efi_block_io *io = interface;
|
struct efi_block_io *io = interface;
|
||||||
|
@ -125,28 +126,28 @@ static int efi_bl_bind(efi_handle_t handle, void *interface)
|
||||||
|
|
||||||
EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io);
|
EFI_PRINT("%s: handle %p, interface %p\n", __func__, handle, io);
|
||||||
|
|
||||||
if (!obj)
|
if (!obj || !interface)
|
||||||
return -ENOENT;
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
devnum = blk_find_max_devnum(UCLASS_EFI_LOADER);
|
devnum = blk_find_max_devnum(UCLASS_EFI_LOADER);
|
||||||
if (devnum == -ENODEV)
|
if (devnum == -ENODEV)
|
||||||
devnum = 0;
|
devnum = 0;
|
||||||
else if (devnum < 0)
|
else if (devnum < 0)
|
||||||
return devnum;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
|
||||||
name = calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */
|
name = calloc(1, 18); /* strlen("efiblk#2147483648") + 1 */
|
||||||
if (!name)
|
if (!name)
|
||||||
return -ENOMEM;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
sprintf(name, "efiblk#%d", devnum);
|
sprintf(name, "efiblk#%d", devnum);
|
||||||
|
|
||||||
/* Create driver model udevice for the EFI block io device */
|
/* Create driver model udevice for the EFI block io device */
|
||||||
ret = blk_create_device(parent, "efi_blk", name, UCLASS_EFI_LOADER,
|
if (blk_create_device(parent, "efi_blk", name, UCLASS_EFI_LOADER,
|
||||||
devnum, io->media->block_size,
|
devnum, io->media->block_size,
|
||||||
(lbaint_t)io->media->last_block, &bdev);
|
(lbaint_t)io->media->last_block, &bdev)) {
|
||||||
if (ret)
|
ret = EFI_OUT_OF_RESOURCES;
|
||||||
return ret;
|
free(name);
|
||||||
if (!bdev)
|
goto err;
|
||||||
return -ENOENT;
|
}
|
||||||
/* Set the DM_FLAG_NAME_ALLOCED flag to avoid a memory leak */
|
/* Set the DM_FLAG_NAME_ALLOCED flag to avoid a memory leak */
|
||||||
device_set_name_alloced(bdev);
|
device_set_name_alloced(bdev);
|
||||||
|
|
||||||
|
@ -154,20 +155,25 @@ static int efi_bl_bind(efi_handle_t handle, void *interface)
|
||||||
plat->handle = handle;
|
plat->handle = handle;
|
||||||
plat->io = interface;
|
plat->io = interface;
|
||||||
|
|
||||||
/*
|
if (efi_link_dev(handle, bdev)) {
|
||||||
* FIXME: necessary because we won't do almost nothing in
|
ret = EFI_OUT_OF_RESOURCES;
|
||||||
* efi_disk_create() when called from device_probe().
|
goto err;
|
||||||
*/
|
}
|
||||||
if (efi_link_dev(handle, bdev))
|
|
||||||
/* FIXME: cleanup for bdev */
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = device_probe(bdev);
|
if (device_probe(bdev)) {
|
||||||
if (ret)
|
ret = EFI_DEVICE_ERROR;
|
||||||
return ret;
|
goto err;
|
||||||
|
}
|
||||||
EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
|
EFI_PRINT("%s: block device '%s' created\n", __func__, bdev->name);
|
||||||
|
|
||||||
return 0;
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
|
err:
|
||||||
|
efi_unlink_dev(handle);
|
||||||
|
if (bdev)
|
||||||
|
device_unbind(bdev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Block device driver operators */
|
/* Block device driver operators */
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
* The uclass provides the bind, start, and stop entry points for the driver
|
* The uclass provides the bind, start, and stop entry points for the driver
|
||||||
* binding protocol.
|
* binding protocol.
|
||||||
*
|
*
|
||||||
* In bind() and stop() it checks if the controller implements the protocol
|
* In supported() and bind() it checks if the controller implements the protocol
|
||||||
* supported by the EFI driver. In the start() function it calls the bind()
|
* supported by the EFI driver. In the start() function it calls the bind()
|
||||||
* function of the EFI driver. In the stop() function it destroys the child
|
* function of the EFI driver. In the stop() function it destroys the child
|
||||||
* controllers.
|
* controllers.
|
||||||
|
@ -144,18 +144,19 @@ static efi_status_t EFIAPI efi_uc_start(
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = check_node_type(controller_handle);
|
ret = check_node_type(controller_handle);
|
||||||
if (ret != EFI_SUCCESS) {
|
if (ret != EFI_SUCCESS)
|
||||||
r = EFI_CALL(systab.boottime->close_protocol(
|
goto err;
|
||||||
controller_handle, bp->ops->protocol,
|
ret = bp->ops->bind(controller_handle, interface);
|
||||||
this->driver_binding_handle,
|
if (ret == EFI_SUCCESS)
|
||||||
controller_handle));
|
|
||||||
if (r != EFI_SUCCESS)
|
|
||||||
EFI_PRINT("Failure to close handle\n");
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: driver specific stuff */
|
err:
|
||||||
bp->ops->bind(controller_handle, interface);
|
r = EFI_CALL(systab.boottime->close_protocol(
|
||||||
|
controller_handle, bp->ops->protocol,
|
||||||
|
this->driver_binding_handle,
|
||||||
|
controller_handle));
|
||||||
|
if (r != EFI_SUCCESS)
|
||||||
|
EFI_PRINT("Failure to close handle\n");
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return EFI_EXIT(ret);
|
return EFI_EXIT(ret);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue