1 /*
2  * Copyright 2011-2014 Intel Corporation - All Rights Reserved
3  */
4 
5 #include <fs.h>
6 #include <ilog2.h>
7 #include <disk.h>
8 #include <dprintf.h>
9 #include "efi.h"
10 
read_blocks(EFI_BLOCK_IO * bio,uint32_t id,sector_t lba,UINTN bytes,void * buf)11 static inline EFI_STATUS read_blocks(EFI_BLOCK_IO *bio, uint32_t id,
12 				     sector_t lba, UINTN bytes, void *buf)
13 {
14 	return uefi_call_wrapper(bio->ReadBlocks, 5, bio, id, lba, bytes, buf);
15 }
16 
write_blocks(EFI_BLOCK_IO * bio,uint32_t id,sector_t lba,UINTN bytes,void * buf)17 static inline EFI_STATUS write_blocks(EFI_BLOCK_IO *bio, uint32_t id,
18 				     sector_t lba, UINTN bytes, void *buf)
19 {
20 	return uefi_call_wrapper(bio->WriteBlocks, 5, bio, id, lba, bytes, buf);
21 }
22 
efi_rdwr_sectors(struct disk * disk,void * buf,sector_t lba,size_t count,bool is_write)23 static int efi_rdwr_sectors(struct disk *disk, void *buf,
24 			    sector_t lba, size_t count, bool is_write)
25 {
26 	struct efi_disk_private *priv = (struct efi_disk_private *)disk->private;
27 	EFI_BLOCK_IO *bio = priv->bio;
28 	EFI_STATUS status;
29 	UINTN bytes = count * disk->sector_size;
30 
31 	if (is_write)
32 		status = write_blocks(bio, disk->disk_number, lba, bytes, buf);
33 	else
34 		status = read_blocks(bio, disk->disk_number, lba, bytes, buf);
35 
36 	if (status != EFI_SUCCESS)
37 		Print(L"Failed to %s blocks: 0x%x\n",
38 			is_write ? L"write" : L"read",
39 			status);
40 
41 	return count << disk->sector_shift;
42 }
43 
efi_disk_init(void * private)44 struct disk *efi_disk_init(void *private)
45 {
46     static struct disk disk;
47     struct efi_disk_private *priv = (struct efi_disk_private *)private;
48     EFI_HANDLE handle = priv->dev_handle;
49     EFI_BLOCK_IO *bio;
50     EFI_DISK_IO *dio;
51     EFI_STATUS status;
52 
53     status = uefi_call_wrapper(BS->HandleProtocol, 3, handle,
54 			       &DiskIoProtocol, (void **)&dio);
55     if (status != EFI_SUCCESS)
56 	    return NULL;
57 
58     status = uefi_call_wrapper(BS->HandleProtocol, 3, handle,
59 			       &BlockIoProtocol, (void **)&bio);
60     if (status != EFI_SUCCESS)
61 	    return NULL;
62 
63     /*
64      * XXX Do we need to map this to a BIOS disk number?
65      */
66     disk.disk_number   = bio->Media->MediaId;
67 
68     disk.sector_size   = bio->Media->BlockSize;
69     disk.rdwr_sectors  = efi_rdwr_sectors;
70     disk.sector_shift  = ilog2(disk.sector_size);
71 
72     dprintf("sector_size=%d, disk_number=%d\n", disk.sector_size,
73 	    disk.disk_number);
74 
75     priv->bio = bio;
76     priv->dio = dio;
77     disk.private = private;
78 #if 0
79 
80     disk.part_start    = part_start;
81     disk.secpercyl     = disk.h * disk.s;
82 
83 
84     disk.maxtransfer   = MaxTransfer;
85 
86     dprintf("disk %02x cdrom %d type %d sector %u/%u offset %llu limit %u\n",
87 	    media_id, cdrom, ebios, sector_size, disk.sector_shift,
88 	    part_start, disk.maxtransfer);
89 #endif
90 
91     return &disk;
92 }
93