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 | |
---|
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 | |
---|
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 | |
---|
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 | |
---|
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 | } |
---|