[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