]> Git Repo - u-boot.git/blobdiff - lib/efi_loader/efi_disk.c
efi_loader: disk: a helper function to delete efi_disk objects
[u-boot.git] / lib / efi_loader / efi_disk.c
index 4d4937c8ba85b054891551d74597a44442c49961..940390ac8bcc3c8f9cddd2c417d256b0f15f9826 100644 (file)
@@ -5,14 +5,24 @@
  *  Copyright (c) 2016 Alexander Graf
  */
 
+#define LOG_CATEGORY LOGC_EFI
+
 #include <common.h>
 #include <blk.h>
 #include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/tag.h>
+#include <event.h>
 #include <efi_loader.h>
+#include <fs.h>
+#include <log.h>
 #include <part.h>
 #include <malloc.h>
 
+struct efi_system_partition efi_system_partition;
+
 const efi_guid_t efi_block_io_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
+const efi_guid_t efi_system_partition_guid = PARTITION_SYSTEM_GUID;
 
 /**
  * struct efi_disk_obj - EFI disk object
@@ -41,11 +51,26 @@ struct efi_disk_obj {
        struct blk_desc *desc;
 };
 
+/**
+ * efi_disk_reset() - reset block device
+ *
+ * This function implements the Reset service of the EFI_BLOCK_IO_PROTOCOL.
+ *
+ * As U-Boot's block devices do not have a reset function simply return
+ * EFI_SUCCESS.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this:                      pointer to the BLOCK_IO_PROTOCOL
+ * @extended_verification:     extended verification
+ * Return:                     status code
+ */
 static efi_status_t EFIAPI efi_disk_reset(struct efi_block_io *this,
                        char extended_verification)
 {
        EFI_ENTRY("%p, %x", this, extended_verification);
-       return EFI_EXIT(EFI_DEVICE_ERROR);
+       return EFI_EXIT(EFI_SUCCESS);
 }
 
 enum efi_disk_direction {
@@ -92,6 +117,21 @@ static efi_status_t efi_disk_rw_blocks(struct efi_block_io *this,
        return EFI_SUCCESS;
 }
 
+/**
+ * efi_disk_read_blocks() - reads blocks from device
+ *
+ * This function implements the ReadBlocks service of the EFI_BLOCK_IO_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this:                      pointer to the BLOCK_IO_PROTOCOL
+ * @media_id:                  id of the medium to be read from
+ * @lba:                       starting logical block for reading
+ * @buffer_size:               size of the read buffer
+ * @buffer:                    pointer to the destination buffer
+ * Return:                     status code
+ */
 static efi_status_t EFIAPI efi_disk_read_blocks(struct efi_block_io *this,
                        u32 media_id, u64 lba, efi_uintn_t buffer_size,
                        void *buffer)
@@ -106,11 +146,12 @@ static efi_status_t EFIAPI efi_disk_read_blocks(struct efi_block_io *this,
                return EFI_MEDIA_CHANGED;
        if (!this->media->media_present)
                return EFI_NO_MEDIA;
-       /* media->io_align is a power of 2 */
-       if ((uintptr_t)buffer & (this->media->io_align - 1))
+       /* media->io_align is a power of 2 or 0 */
+       if (this->media->io_align &&
+           (uintptr_t)buffer & (this->media->io_align - 1))
                return EFI_INVALID_PARAMETER;
        if (lba * this->media->block_size + buffer_size >
-           this->media->last_block * this->media->block_size)
+           (this->media->last_block + 1) * this->media->block_size)
                return EFI_INVALID_PARAMETER;
 
 #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
@@ -141,6 +182,22 @@ static efi_status_t EFIAPI efi_disk_read_blocks(struct efi_block_io *this,
        return EFI_EXIT(r);
 }
 
+/**
+ * efi_disk_write_blocks() - writes blocks to device
+ *
+ * This function implements the WriteBlocks service of the
+ * EFI_BLOCK_IO_PROTOCOL.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this:                      pointer to the BLOCK_IO_PROTOCOL
+ * @media_id:                  id of the medium to be written to
+ * @lba:                       starting logical block for writing
+ * @buffer_size:               size of the write buffer
+ * @buffer:                    pointer to the source buffer
+ * Return:                     status code
+ */
 static efi_status_t EFIAPI efi_disk_write_blocks(struct efi_block_io *this,
                        u32 media_id, u64 lba, efi_uintn_t buffer_size,
                        void *buffer)
@@ -157,11 +214,12 @@ static efi_status_t EFIAPI efi_disk_write_blocks(struct efi_block_io *this,
                return EFI_MEDIA_CHANGED;
        if (!this->media->media_present)
                return EFI_NO_MEDIA;
-       /* media->io_align is a power of 2 */
-       if ((uintptr_t)buffer & (this->media->io_align - 1))
+       /* media->io_align is a power of 2 or 0 */
+       if (this->media->io_align &&
+           (uintptr_t)buffer & (this->media->io_align - 1))
                return EFI_INVALID_PARAMETER;
        if (lba * this->media->block_size + buffer_size >
-           this->media->last_block * this->media->block_size)
+           (this->media->last_block + 1) * this->media->block_size)
                return EFI_INVALID_PARAMETER;
 
 #ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
@@ -192,9 +250,22 @@ static efi_status_t EFIAPI efi_disk_write_blocks(struct efi_block_io *this,
        return EFI_EXIT(r);
 }
 
+/**
+ * efi_disk_flush_blocks() - flushes modified data to the device
+ *
+ * This function implements the FlushBlocks service of the
+ * EFI_BLOCK_IO_PROTOCOL.
+ *
+ * As we always write synchronously nothing is done here.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this:                      pointer to the BLOCK_IO_PROTOCOL
+ * Return:                     status code
+ */
 static efi_status_t EFIAPI efi_disk_flush_blocks(struct efi_block_io *this)
 {
-       /* We always write synchronously */
        EFI_ENTRY("%p", this);
        return EFI_EXIT(EFI_SUCCESS);
 }
@@ -206,15 +277,17 @@ static const struct efi_block_io block_io_disk_template = {
        .flush_blocks = &efi_disk_flush_blocks,
 };
 
-/*
- * Get the simple file system protocol for a file device path.
+/**
+ * efi_fs_from_path() - retrieve simple file system protocol
+ *
+ * Gets the simple file system protocol for a file device path.
  *
  * The full path provided is split into device part and into a file
  * part. The device part is used to find the handle on which the
  * simple file system protocol is installed.
  *
- * @full_path  device path including device and file
- * @return     simple file system protocol
+ * @full_path: device path including device and file
+ * Return:     simple file system protocol
  */
 struct efi_simple_file_system_protocol *
 efi_fs_from_path(struct efi_device_path *full_path)
@@ -232,7 +305,7 @@ efi_fs_from_path(struct efi_device_path *full_path)
        efi_free_pool(file_path);
 
        /* Get the EFI object for the partition */
-       efiobj = efi_dp_find_obj(device_path, NULL);
+       efiobj = efi_dp_find_obj(device_path, NULL, NULL);
        efi_free_pool(device_path);
        if (!efiobj)
                return NULL;
@@ -247,16 +320,39 @@ efi_fs_from_path(struct efi_device_path *full_path)
        return handler->protocol_interface;
 }
 
-/*
- * Create a handle for a partition or disk
- *
- * @parent     parent handle
- * @dp_parent  parent device path
- * @if_typename interface name for block device
- * @desc       internal block device
- * @dev_index   device index for block device
- * @offset     offset into disk for simple partitions
- * @return     disk object
+/**
+ * efi_fs_exists() - check if a partition bears a file system
+ *
+ * @desc:      block device descriptor
+ * @part:      partition number
+ * Return:     1 if a file system exists on the partition
+ *             0 otherwise
+ */
+static int efi_fs_exists(struct blk_desc *desc, int part)
+{
+       if (fs_set_blk_dev_with_part(desc, part))
+               return 0;
+
+       if (fs_get_type() == FS_TYPE_ANY)
+               return 0;
+
+       fs_close();
+
+       return 1;
+}
+
+/**
+ * efi_disk_add_dev() - create a handle for a partition or disk
+ *
+ * @parent:            parent handle
+ * @dp_parent:         parent device path
+ * @if_typename:       interface name for block device
+ * @desc:              internal block device
+ * @dev_index:         device index for block device
+ * @part_info:         partition info
+ * @part:              partition
+ * @disk:              pointer to receive the created handle
+ * Return:             disk object
  */
 static efi_status_t efi_disk_add_dev(
                                efi_handle_t parent,
@@ -264,11 +360,13 @@ static efi_status_t efi_disk_add_dev(
                                const char *if_typename,
                                struct blk_desc *desc,
                                int dev_index,
-                               lbaint_t offset,
+                               struct disk_partition *part_info,
                                unsigned int part,
                                struct efi_disk_obj **disk)
 {
        struct efi_disk_obj *diskobj;
+       struct efi_object *handle;
+       const efi_guid_t *guid = NULL;
        efi_status_t ret;
 
        /* Don't add empty devices */
@@ -283,24 +381,60 @@ static efi_status_t efi_disk_add_dev(
        efi_add_handle(&diskobj->header);
 
        /* Fill in object data */
-       if (part) {
+       if (part_info) {
                struct efi_device_path *node = efi_dp_part_node(desc, part);
+               struct efi_handler *handler;
+               void *protocol_interface;
+
+               /* Parent must expose EFI_BLOCK_IO_PROTOCOL */
+               ret = efi_search_protocol(parent, &efi_block_io_guid, &handler);
+               if (ret != EFI_SUCCESS)
+                       goto error;
+
+               /*
+                * Link the partition (child controller) to the block device
+                * (controller).
+                */
+               ret = efi_protocol_open(handler, &protocol_interface, NULL,
+                                       &diskobj->header,
+                                       EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
+               if (ret != EFI_SUCCESS)
+                               goto error;
 
                diskobj->dp = efi_dp_append_node(dp_parent, node);
                efi_free_pool(node);
+               diskobj->offset = part_info->start;
+               diskobj->media.last_block = part_info->size - 1;
+               if (part_info->bootable & PART_EFI_SYSTEM_PARTITION)
+                       guid = &efi_system_partition_guid;
        } else {
                diskobj->dp = efi_dp_from_part(desc, part);
+               diskobj->offset = 0;
+               diskobj->media.last_block = desc->lba - 1;
        }
        diskobj->part = part;
-       ret = efi_add_protocol(&diskobj->header, &efi_block_io_guid,
-                              &diskobj->ops);
-       if (ret != EFI_SUCCESS)
-               return ret;
-       ret = efi_add_protocol(&diskobj->header, &efi_guid_device_path,
-                              diskobj->dp);
+
+       /*
+        * Install the device path and the block IO protocol.
+        *
+        * InstallMultipleProtocolInterfaces() checks if the device path is
+        * already installed on an other handle and returns EFI_ALREADY_STARTED
+        * in this case.
+        */
+       handle = &diskobj->header;
+       ret = EFI_CALL(efi_install_multiple_protocol_interfaces(
+                       &handle, &efi_guid_device_path, diskobj->dp,
+                       &efi_block_io_guid, &diskobj->ops,
+                       guid, NULL, NULL));
        if (ret != EFI_SUCCESS)
-               return ret;
-       if (part >= 1) {
+               goto error;
+
+       /*
+        * On partitions or whole disks without partitions install the
+        * simple file system protocol if a file system is available.
+        */
+       if ((part || desc->part_type == PART_TYPE_UNKNOWN) &&
+           efi_fs_exists(desc, part)) {
                diskobj->volume = efi_simple_file_system(desc, part,
                                                         diskobj->dp);
                ret = efi_add_protocol(&diskobj->header,
@@ -312,7 +446,6 @@ static efi_status_t efi_disk_add_dev(
        diskobj->ops = block_io_disk_template;
        diskobj->ifname = if_typename;
        diskobj->dev_index = dev_index;
-       diskobj->offset = offset;
        diskobj->desc = desc;
 
        /* Fill in EFI IO Media info (for read/write callbacks) */
@@ -325,153 +458,281 @@ static efi_status_t efi_disk_add_dev(
        diskobj->media.media_id = 1;
        diskobj->media.block_size = desc->blksz;
        diskobj->media.io_align = desc->blksz;
-       diskobj->media.last_block = desc->lba - offset;
-       if (part != 0)
+       if (part)
                diskobj->media.logical_partition = 1;
        diskobj->ops.media = &diskobj->media;
        if (disk)
                *disk = diskobj;
+
+       EFI_PRINT("BlockIO: part %u, present %d, logical %d, removable %d"
+                 ", offset " LBAF ", last_block %llu\n",
+                 diskobj->part,
+                 diskobj->media.media_present,
+                 diskobj->media.logical_partition,
+                 diskobj->media.removable_media,
+                 diskobj->offset,
+                 diskobj->media.last_block);
+
+       /* Store first EFI system partition */
+       if (part && !efi_system_partition.if_type) {
+               if (part_info->bootable & PART_EFI_SYSTEM_PARTITION) {
+                       efi_system_partition.if_type = desc->if_type;
+                       efi_system_partition.devnum = desc->devnum;
+                       efi_system_partition.part = part;
+                       EFI_PRINT("EFI system partition: %s %x:%x\n",
+                                 blk_get_if_type_name(desc->if_type),
+                                 desc->devnum, part);
+               }
+       }
        return EFI_SUCCESS;
+error:
+       efi_delete_handle(&diskobj->header);
+       return ret;
 }
 
 /*
- * Create handles and protocols for the partitions of a block device
- *
- * @parent             handle of the parent disk
- * @blk_desc           block device
- * @if_typename                interface type
- * @diskid             device number
- * @pdevname           device name
- * @return             number of partitions created
+ * Create a handle for a whole raw disk
+ *
+ * @dev                uclass device (UCLASS_BLK)
+ *
+ * Create an efi_disk object which is associated with @dev.
+ * The type of @dev must be UCLASS_BLK.
+ *
+ * @return     0 on success, -1 otherwise
  */
-int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
-                              const char *if_typename, int diskid,
-                              const char *pdevname)
+static int efi_disk_create_raw(struct udevice *dev)
 {
-       int disks = 0;
-       char devname[32] = { 0 }; /* dp->str is u16[32] long */
-       disk_partition_t info;
-       int part;
-       struct efi_device_path *dp = NULL;
+       struct efi_disk_obj *disk;
+       struct blk_desc *desc;
+       const char *if_typename;
+       int diskid;
        efi_status_t ret;
-       struct efi_handler *handler;
 
-       /* Get the device path of the parent */
-       ret = efi_search_protocol(parent, &efi_guid_device_path, &handler);
-       if (ret == EFI_SUCCESS)
-               dp = handler->protocol_interface;
-
-       /* Add devices for each partition */
-       for (part = 1; part <= MAX_SEARCH_PARTITIONS; part++) {
-               if (part_get_info(desc, part, &info))
-                       continue;
-               snprintf(devname, sizeof(devname), "%s:%d", pdevname,
-                        part);
-               ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid,
-                                      info.start, part, NULL);
-               if (ret != EFI_SUCCESS) {
-                       printf("Adding partition %s failed\n", pdevname);
-                       continue;
-               }
-               disks++;
+       desc = dev_get_uclass_plat(dev);
+       if_typename = blk_get_if_type_name(desc->if_type);
+       diskid = desc->devnum;
+
+       ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
+                              diskid, NULL, 0, &disk);
+       if (ret != EFI_SUCCESS) {
+               if (ret == EFI_NOT_READY)
+                       log_notice("Disk %s not ready\n", dev->name);
+               else
+                       log_err("Adding disk for %s failed\n", dev->name);
+
+               return -1;
+       }
+       if (dev_tag_set_ptr(dev, DM_TAG_EFI, &disk->header)) {
+               efi_free_pool(disk->dp);
+               efi_delete_handle(&disk->header);
+
+               return -1;
        }
 
-       return disks;
+       return 0;
 }
 
 /*
- * U-Boot doesn't have a list of all online disk devices. So when running our
- * EFI payload, we scan through all of the potentially available ones and
- * store them in our object pool.
+ * Create a handle for a disk partition
+ *
+ * @dev                uclass device (UCLASS_PARTITION)
  *
- * TODO([email protected]): Actually with CONFIG_BLK, U-Boot does have this.
- * Consider converting the code to look up devices as needed. The EFI device
- * could be a child of the UCLASS_BLK block device, perhaps.
+ * Create an efi_disk object which is associated with @dev.
+ * The type of @dev must be UCLASS_PARTITION.
  *
- * This gets called from do_bootefi_exec().
+ * @return     0 on success, -1 otherwise
  */
-efi_status_t efi_disk_register(void)
+static int efi_disk_create_part(struct udevice *dev)
 {
+       efi_handle_t parent;
+       struct blk_desc *desc;
+       const char *if_typename;
+       struct disk_part *part_data;
+       struct disk_partition *info;
+       unsigned int part;
+       int diskid;
+       struct efi_handler *handler;
+       struct efi_device_path *dp_parent;
        struct efi_disk_obj *disk;
-       int disks = 0;
        efi_status_t ret;
-#ifdef CONFIG_BLK
+
+       if (dev_tag_get_ptr(dev_get_parent(dev), DM_TAG_EFI, (void **)&parent))
+               return -1;
+
+       desc = dev_get_uclass_plat(dev_get_parent(dev));
+       if_typename = blk_get_if_type_name(desc->if_type);
+       diskid = desc->devnum;
+
+       part_data = dev_get_uclass_plat(dev);
+       part = part_data->partnum;
+       info = &part_data->gpt_part_info;
+
+       ret = efi_search_protocol(parent, &efi_guid_device_path, &handler);
+       if (ret != EFI_SUCCESS)
+               return -1;
+       dp_parent = (struct efi_device_path *)handler->protocol_interface;
+
+       ret = efi_disk_add_dev(parent, dp_parent, if_typename, desc, diskid,
+                              info, part, &disk);
+       if (ret != EFI_SUCCESS) {
+               log_err("Adding partition for %s failed\n", dev->name);
+               return -1;
+       }
+       if (dev_tag_set_ptr(dev, DM_TAG_EFI, &disk->header)) {
+               efi_free_pool(disk->dp);
+               efi_delete_handle(&disk->header);
+
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Create efi_disk objects for a block device
+ *
+ * @dev                uclass device (UCLASS_BLK)
+ *
+ * Create efi_disk objects for partitions as well as a raw disk
+ * which is associated with @dev.
+ * The type of @dev must be UCLASS_BLK.
+ * This function is expected to be called at EV_PM_POST_PROBE.
+ *
+ * @return     0 on success, -1 otherwise
+ */
+static int efi_disk_probe(void *ctx, struct event *event)
+{
        struct udevice *dev;
+       enum uclass_id id;
+       struct blk_desc *desc;
+       struct udevice *child;
+       int ret;
 
-       for (uclass_first_device_check(UCLASS_BLK, &dev); dev;
-            uclass_next_device_check(&dev)) {
-               struct blk_desc *desc = dev_get_uclass_platdata(dev);
-               const char *if_typename = blk_get_if_type_name(desc->if_type);
-
-               /* Add block device for the full device */
-               printf("Scanning disk %s...\n", dev->name);
-               ret = efi_disk_add_dev(NULL, NULL, if_typename,
-                                       desc, desc->devnum, 0, 0, &disk);
-               if (ret == EFI_NOT_READY) {
-                       printf("Disk %s not ready\n", dev->name);
-                       continue;
-               }
-               if (ret) {
-                       printf("ERROR: failure to add disk device %s, r = %lu\n",
-                              dev->name, ret & ~EFI_ERROR_MASK);
-                       return ret;
-               }
-               disks++;
+       dev = event->data.dm.dev;
+       id = device_get_uclass_id(dev);
 
-               /* Partitions show up as block devices in EFI */
-               disks += efi_disk_create_partitions(
-                                       &disk->header, desc, if_typename,
-                                       desc->devnum, dev->name);
+       /* TODO: We won't support partitions in a partition */
+       if (id != UCLASS_BLK)
+               return 0;
+
+       /*
+        * avoid creating duplicated objects now that efi_driver
+        * has already created an efi_disk at this moment.
+        */
+       desc = dev_get_uclass_plat(dev);
+       if (desc->if_type != IF_TYPE_EFI_LOADER) {
+               ret = efi_disk_create_raw(dev);
+               if (ret)
+                       return -1;
        }
-#else
-       int i, if_type;
-
-       /* Search for all available disk devices */
-       for (if_type = 0; if_type < IF_TYPE_COUNT; if_type++) {
-               const struct blk_driver *cur_drvr;
-               const char *if_typename;
-
-               cur_drvr = blk_driver_lookup_type(if_type);
-               if (!cur_drvr)
-                       continue;
-
-               if_typename = cur_drvr->if_typename;
-               printf("Scanning disks on %s...\n", if_typename);
-               for (i = 0; i < 4; i++) {
-                       struct blk_desc *desc;
-                       char devname[32] = { 0 }; /* dp->str is u16[32] long */
-
-                       desc = blk_get_devnum_by_type(if_type, i);
-                       if (!desc)
-                               continue;
-                       if (desc->type == DEV_TYPE_UNKNOWN)
-                               continue;
-
-                       snprintf(devname, sizeof(devname), "%s%d",
-                                if_typename, i);
-
-                       /* Add block device for the full device */
-                       ret = efi_disk_add_dev(NULL, NULL, if_typename, desc,
-                                              i, 0, 0, &disk);
-                       if (ret == EFI_NOT_READY) {
-                               printf("Disk %s not ready\n", devname);
-                               continue;
-                       }
-                       if (ret) {
-                               printf("ERROR: failure to add disk device %s, r = %lu\n",
-                                      devname, ret & ~EFI_ERROR_MASK);
-                               return ret;
-                       }
-                       disks++;
-
-                       /* Partitions show up as block devices in EFI */
-                       disks += efi_disk_create_partitions
-                                               (&disk->header, desc,
-                                                if_typename, i, devname);
-               }
+
+       device_foreach_child(child, dev) {
+               ret = efi_disk_create_part(child);
+               if (ret)
+                       return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Delete an efi_disk object for a whole raw disk
+ *
+ * @dev                uclass device (UCLASS_BLK)
+ *
+ * Delete an efi_disk object which is associated with @dev.
+ * The type of @dev must be UCLASS_BLK.
+ *
+ * @return     0 on success, -1 otherwise
+ */
+static int efi_disk_delete_raw(struct udevice *dev)
+{
+       efi_handle_t handle;
+       struct efi_disk_obj *diskobj;
+
+       if (dev_tag_get_ptr(dev, DM_TAG_EFI, (void **)&handle))
+               return -1;
+
+       diskobj = container_of(handle, struct efi_disk_obj, header);
+       efi_free_pool(diskobj->dp);
+
+       efi_delete_handle(handle);
+       dev_tag_del(dev, DM_TAG_EFI);
+
+       return 0;
+}
+
+/*
+ * Delete an efi_disk object for a disk partition
+ *
+ * @dev                uclass device (UCLASS_PARTITION)
+ *
+ * Delete an efi_disk object which is associated with @dev.
+ * The type of @dev must be UCLASS_PARTITION.
+ *
+ * @return     0 on success, -1 otherwise
+ */
+static int efi_disk_delete_part(struct udevice *dev)
+{
+       efi_handle_t handle;
+       struct efi_disk_obj *diskobj;
+
+       if (dev_tag_get_ptr(dev, DM_TAG_EFI, (void **)&handle))
+               return -1;
+
+       diskobj = container_of(handle, struct efi_disk_obj, header);
+
+       efi_free_pool(diskobj->dp);
+       efi_delete_handle(handle);
+       dev_tag_del(dev, DM_TAG_EFI);
+
+       return 0;
+}
+
+/*
+ * Delete an efi_disk object for a block device
+ *
+ * @dev                uclass device (UCLASS_BLK or UCLASS_PARTITION)
+ *
+ * Delete an efi_disk object which is associated with @dev.
+ * The type of @dev must be either UCLASS_BLK or UCLASS_PARTITION.
+ * This function is expected to be called at EV_PM_PRE_REMOVE.
+ *
+ * @return     0 on success, -1 otherwise
+ */
+static int efi_disk_remove(void *ctx, struct event *event)
+{
+       enum uclass_id id;
+       struct udevice *dev;
+
+       dev = event->data.dm.dev;
+       id = device_get_uclass_id(dev);
+
+       if (id == UCLASS_BLK)
+               return efi_disk_delete_raw(dev);
+       else if (id == UCLASS_PARTITION)
+               return efi_disk_delete_part(dev);
+       else
+               return 0;
+}
+
+efi_status_t efi_disk_init(void)
+{
+       int ret;
+
+       ret = event_register("efi_disk add", EVT_DM_POST_PROBE,
+                            efi_disk_probe, NULL);
+       if (ret) {
+               log_err("Event registration for efi_disk add failed\n");
+               return EFI_OUT_OF_RESOURCES;
+       }
+
+       ret = event_register("efi_disk del", EVT_DM_PRE_REMOVE,
+                            efi_disk_remove, NULL);
+       if (ret) {
+               log_err("Event registration for efi_disk del failed\n");
+               return EFI_OUT_OF_RESOURCES;
        }
-#endif
-       printf("Found %d disks\n", disks);
 
        return EFI_SUCCESS;
 }
This page took 0.046851 seconds and 4 git commands to generate.