/* * 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; }