#include <blk.h>
#include <dm.h>
#include <efi_loader.h>
+#include <fs.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;
/**
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)
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)
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);
}
.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)
return handler->protocol_interface;
}
-/*
- * Create a handle for a partition or disk
+/**
+ * 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
- * @offset offset into disk for simple partitions
- * @return disk object
+ * @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
+ * @part: partition
+ * @disk: pointer to receive the created handle
+ * Return: disk object
*/
static efi_status_t efi_disk_add_dev(
efi_handle_t parent,
diskobj->dp);
if (ret != EFI_SUCCESS)
return ret;
- if (part >= 1) {
+ /* partitions or whole disk without partitions */
+ 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,
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;
+
+ /* Store first EFI system partition */
+ if (part && !efi_system_partition.if_type) {
+ int r;
+ disk_partition_t info;
+
+ r = part_get_info(desc, part, &info);
+ if (r)
+ return EFI_DEVICE_ERROR;
+ if (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 %d:%d\n",
+ blk_get_if_type_name(desc->if_type),
+ desc->devnum, part);
+ }
+ }
return EFI_SUCCESS;
}
-/*
- * Create handles and protocols for the partitions of a block device
+/**
+ * efi_disk_create_partitions() - create handles and protocols for partitions
+ *
+ * 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
+ * @parent: handle of the parent disk
+ * @desc: block device
+ * @if_typename: interface type
+ * @diskid: device number
+ * @pdevname: device name
+ * Return: number of partitions created
*/
int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc,
const char *if_typename, int diskid,
return disks;
}
-/*
+/**
+ * efi_disk_register() - register block devices
+ *
* 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.
*
+ * This function is called in efi_init_obj_list().
+ *
* TODO(sjg@chromium.org): 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.
*
- * This gets called from do_bootefi_exec().
+ * Return: status code
*/
efi_status_t efi_disk_register(void)
{