X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=lib%2Fefi_loader%2Fefi_disk.c;h=fd3df80b0b9627649cc47328cfcab91bad36a49d;hb=04da42770b0cc3bea8841972bfc9568299ece826;hp=9007a5f77f3d05950cf37e066c03f43ff1c295e7;hpb=6128e61429a5d989cbb1e1a92b02791f69615c42;p=platform%2Fkernel%2Fu-boot.git diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 9007a5f..fd3df80 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -9,9 +9,12 @@ #include #include #include +#include #include #include +struct efi_system_partition efi_system_partition; + const efi_guid_t efi_block_io_guid = EFI_BLOCK_IO_PROTOCOL_GUID; /** @@ -107,6 +110,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) @@ -156,6 +174,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) @@ -207,9 +241,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); } @@ -221,15 +268,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) @@ -262,16 +311,39 @@ 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, @@ -315,7 +387,9 @@ static efi_status_t efi_disk_add_dev( 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, @@ -341,23 +415,43 @@ static efi_status_t efi_disk_add_dev( 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, @@ -394,16 +488,20 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc, 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) {