#include <common.h>
#include <blk.h>
+ #include <dm.h>
#include <efi_loader.h>
#include <inttypes.h>
#include <part.h>
int blocks;
unsigned long n;
- EFI_ENTRY("%p, %x, %"PRIx64", %lx, %p", this, media_id, lba,
- buffer_size, buffer);
-
diskobj = container_of(this, struct efi_disk_obj, ops);
if (!(desc = blk_get_dev(diskobj->ifname, diskobj->dev_index)))
return EFI_EXIT(EFI_DEVICE_ERROR);
if (buffer_size & (blksz - 1))
return EFI_EXIT(EFI_DEVICE_ERROR);
- if (direction == EFI_DISK_READ) {
- n = desc->block_read(desc, lba, blocks, buffer);
- } else {
- n = desc->block_write(desc, lba, blocks, buffer);
- }
+ if (direction == EFI_DISK_READ)
+ n = blk_dread(desc, lba, blocks, buffer);
+ else
+ n = blk_dwrite(desc, lba, blocks, buffer);
/* We don't do interrupts, so check for timers cooperatively */
efi_timer_check();
u32 media_id, u64 lba, unsigned long buffer_size,
void *buffer)
{
- return efi_disk_rw_blocks(this, media_id, lba, buffer_size, buffer,
- EFI_DISK_READ);
+ void *real_buffer = buffer;
+ efi_status_t r;
+
+#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
+ if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) {
+ r = efi_disk_read_blocks(this, media_id, lba,
+ EFI_LOADER_BOUNCE_BUFFER_SIZE, buffer);
+ if (r != EFI_SUCCESS)
+ return r;
+ return efi_disk_read_blocks(this, media_id, lba +
+ EFI_LOADER_BOUNCE_BUFFER_SIZE / this->media->block_size,
+ buffer_size - EFI_LOADER_BOUNCE_BUFFER_SIZE,
+ buffer + EFI_LOADER_BOUNCE_BUFFER_SIZE);
+ }
+
+ real_buffer = efi_bounce_buffer;
+#endif
+
+ EFI_ENTRY("%p, %x, %"PRIx64", %lx, %p", this, media_id, lba,
+ buffer_size, buffer);
+
+ r = efi_disk_rw_blocks(this, media_id, lba, buffer_size, real_buffer,
+ EFI_DISK_READ);
+
+ /* Copy from bounce buffer to real buffer if necessary */
+ if ((r == EFI_SUCCESS) && (real_buffer != buffer))
+ memcpy(buffer, real_buffer, buffer_size);
+
+ return EFI_EXIT(r);
}
static efi_status_t efi_disk_write_blocks(struct efi_block_io *this,
u32 media_id, u64 lba, unsigned long buffer_size,
void *buffer)
{
- return efi_disk_rw_blocks(this, media_id, lba, buffer_size, buffer,
- EFI_DISK_WRITE);
+ void *real_buffer = buffer;
+ efi_status_t r;
+
+#ifdef CONFIG_EFI_LOADER_BOUNCE_BUFFER
+ if (buffer_size > EFI_LOADER_BOUNCE_BUFFER_SIZE) {
+ r = efi_disk_write_blocks(this, media_id, lba,
+ EFI_LOADER_BOUNCE_BUFFER_SIZE, buffer);
+ if (r != EFI_SUCCESS)
+ return r;
+ return efi_disk_write_blocks(this, media_id, lba +
+ EFI_LOADER_BOUNCE_BUFFER_SIZE / this->media->block_size,
+ buffer_size - EFI_LOADER_BOUNCE_BUFFER_SIZE,
+ buffer + EFI_LOADER_BOUNCE_BUFFER_SIZE);
+ }
+
+ real_buffer = efi_bounce_buffer;
+#endif
+
+ EFI_ENTRY("%p, %x, %"PRIx64", %lx, %p", this, media_id, lba,
+ buffer_size, buffer);
+
+ /* Populate bounce buffer if necessary */
+ if (real_buffer != buffer)
+ memcpy(real_buffer, buffer, buffer_size);
+
+ r = efi_disk_rw_blocks(this, media_id, lba, buffer_size, real_buffer,
+ EFI_DISK_WRITE);
+
+ return EFI_EXIT(r);
}
static efi_status_t EFIAPI efi_disk_flush_blocks(struct efi_block_io *this)
.flush_blocks = &efi_disk_flush_blocks,
};
- static void efi_disk_add_dev(char *name,
- const struct blk_driver *cur_drvr,
+ static void efi_disk_add_dev(const char *name,
+ const char *if_typename,
const struct blk_desc *desc,
int dev_index,
lbaint_t offset)
diskobj->parent.protocols[1].open = efi_disk_open_dp;
diskobj->parent.handle = diskobj;
diskobj->ops = block_io_disk_template;
- diskobj->ifname = cur_drvr->if_typename;
+ diskobj->ifname = if_typename;
diskobj->dev_index = dev_index;
diskobj->offset = offset;
}
static int efi_disk_create_eltorito(struct blk_desc *desc,
- const struct blk_driver *cur_drvr,
+ const char *if_typename,
int diskid)
{
int disks = 0;
return 0;
while (!part_get_info(desc, part, &info)) {
- snprintf(devname, sizeof(devname), "%s%d:%d",
- cur_drvr->if_typename, diskid, part);
- efi_disk_add_dev(devname, cur_drvr, desc, diskid, info.start);
+ snprintf(devname, sizeof(devname), "%s%d:%d", if_typename,
+ diskid, part);
+ efi_disk_add_dev(devname, if_typename, desc, diskid,
+ info.start);
part++;
disks++;
}
* EFI payload, we scan through all of the potentially available ones and
* store them in our object pool.
*
+ * 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().
*/
int efi_disk_register(void)
{
- const struct blk_driver *cur_drvr;
- int i, if_type;
int disks = 0;
+ #ifdef CONFIG_BLK
+ struct udevice *dev;
+
+ for (uclass_first_device(UCLASS_BLK, &dev);
+ dev;
+ uclass_next_device(&dev)) {
+ struct blk_desc *desc = dev_get_uclass_platdata(dev);
+ const char *if_typename = dev->driver->name;
+
+ printf("Scanning disk %s...\n", dev->name);
+ efi_disk_add_dev(dev->name, if_typename, desc, desc->devnum, 0);
+ disks++;
+
+ /*
+ * El Torito images show up as block devices in an EFI world,
+ * so let's create them here
+ */
+ disks += efi_disk_create_eltorito(desc, if_typename,
+ desc->devnum);
+ }
+ #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;
- printf("Scanning disks on %s...\n", cur_drvr->if_typename);
+ 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 */
continue;
snprintf(devname, sizeof(devname), "%s%d",
- cur_drvr->if_typename, i);
- efi_disk_add_dev(devname, cur_drvr, desc, i, 0);
+ if_typename, i);
+ efi_disk_add_dev(devname, if_typename, desc, i, 0);
disks++;
/*
* El Torito images show up as block devices
* in an EFI world, so let's create them here
*/
- disks += efi_disk_create_eltorito(desc, cur_drvr, i);
+ disks += efi_disk_create_eltorito(desc, if_typename, i);
}
}
+ #endif
printf("Found %d disks\n", disks);
return 0;