[syslinux:firmware] efi: Disk I/O support
syslinux-bot for Matt Fleming
matt.fleming at intel.com
Fri Nov 9 09:06:09 PST 2012
Commit-ID: 4567631499532d5515abbaeffe792ca50bba6be5
Gitweb: http://www.syslinux.org/commit/4567631499532d5515abbaeffe792ca50bba6be5
Author: Matt Fleming <matt.fleming at intel.com>
AuthorDate: Tue, 6 Dec 2011 15:49:41 +0000
Committer: Matt Fleming <matt.fleming at intel.com>
CommitDate: Fri, 16 Dec 2011 16:31:19 +0000
efi: Disk I/O support
Implement .disk_init() for the EFI firmware backend.
---
core/include/disk.h | 1 +
efi/diskio.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 99 insertions(+), 0 deletions(-)
diff --git a/core/include/disk.h b/core/include/disk.h
index dd37715..d0d50ed 100644
--- a/core/include/disk.h
+++ b/core/include/disk.h
@@ -13,6 +13,7 @@ typedef uint64_t block_t;
* contains the I/O function.
*/
struct disk {
+ void *private; /* Firmware-private disk info */
unsigned int disk_number; /* in BIOS style */
unsigned int sector_size; /* gener512B or 2048B */
unsigned int sector_shift;
diff --git a/efi/diskio.c b/efi/diskio.c
new file mode 100644
index 0000000..89779a5
--- /dev/null
+++ b/efi/diskio.c
@@ -0,0 +1,98 @@
+#define DEBUG 1
+#include <fs.h>
+#include <ilog2.h>
+#include <disk.h>
+#include <dprintf.h>
+#include "efi.h"
+
+struct disk_efi_private {
+ EFI_BLOCK_IO *bio;
+ EFI_DISK_IO *dio;
+};
+
+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 disk_efi_private *priv = disk->private;
+ EFI_BLOCK_IO *bio = priv->bio;
+ EFI_DISK_IO *dio = priv->dio;
+ 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 ? "write" : "read",
+ status);
+
+ return count << disk->sector_shift;
+}
+
+struct disk *efi_disk_init(EFI_HANDLE handle)
+{
+ static struct disk_efi_private priv;
+ static struct disk disk;
+ unsigned int hard_max_transfer;
+ EFI_BLOCK_IO *bio;
+ EFI_DISK_IO *dio;
+ EFI_STATUS status;
+ int sector_size;
+
+ 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("foo!\n");
+ Print(L"sector_size=%d, disk_number=%d\n", disk.sector_size,
+ disk.disk_number);
+
+ priv.bio = bio;
+ priv.dio = dio;
+ disk.private = &priv;
+#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;
+}
More information about the Syslinux-commits
mailing list