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