/*
* Copyright 2011-2014 Intel Corporation - All Rights Reserved
*/
#include <fs.h>
#include <ilog2.h>
#include <disk.h>
#include <dprintf.h>
#include "efi.h"
static inline EFI_STATUS read_blocks(EFI_BLOCK_IO *bio, uint32_t id,
sector_t lba, UINTN bytes, void *buf)
{
return uefi_call_wrapper(bio->ReadBlocks, 5, bio, id, lba, bytes, buf);
}
static inline EFI_STATUS write_blocks(EFI_BLOCK_IO *bio, uint32_t id,
sector_t lba, UINTN bytes, void *buf)
{
return uefi_call_wrapper(bio->WriteBlocks, 5, bio, id, lba, bytes, buf);
}
static int efi_rdwr_sectors(struct disk *disk, void *buf,
sector_t lba, size_t count, bool is_write)
{
struct efi_disk_private *priv = (struct efi_disk_private *)disk->private;
EFI_BLOCK_IO *bio = priv->bio;
EFI_STATUS status;
UINTN bytes = count * disk->sector_size;
if (is_write)
status = write_blocks(bio, disk->disk_number, lba, bytes, buf);
else
status = read_blocks(bio, disk->disk_number, lba, bytes, buf);
if (status != EFI_SUCCESS)
Print(L"Failed to %s blocks: 0x%x\n",
is_write ? L"write" : L"read",
status);
return count << disk->sector_shift;
}
struct disk *efi_disk_init(void *private)
{
static struct disk disk;
struct efi_disk_private *priv = (struct efi_disk_private *)private;
EFI_HANDLE handle = priv->dev_handle;
EFI_BLOCK_IO *bio;
EFI_DISK_IO *dio;
EFI_STATUS status;
status = uefi_call_wrapper(BS->HandleProtocol, 3, handle,
&DiskIoProtocol, (void **)&dio);
if (status != EFI_SUCCESS)
return NULL;
status = uefi_call_wrapper(BS->HandleProtocol, 3, handle,
&BlockIoProtocol, (void **)&bio);
if (status != EFI_SUCCESS)
return NULL;
/*
* XXX Do we need to map this to a BIOS disk number?
*/
disk.disk_number = bio->Media->MediaId;
disk.sector_size = bio->Media->BlockSize;
disk.rdwr_sectors = efi_rdwr_sectors;
disk.sector_shift = ilog2(disk.sector_size);
dprintf("sector_size=%d, disk_number=%d\n", disk.sector_size,
disk.disk_number);
priv->bio = bio;
priv->dio = dio;
disk.private = private;
#if 0
disk.part_start = part_start;
disk.secpercyl = disk.h * disk.s;
disk.maxtransfer = MaxTransfer;
dprintf("disk %02x cdrom %d type %d sector %u/%u offset %llu limit %u\n",
media_id, cdrom, ebios, sector_size, disk.sector_shift,
part_start, disk.maxtransfer);
#endif
return &disk;
}