]> code.delx.au - refind/blob - filesystems/scandisk.c
Added primitive cache to most drivers to improve performance,
[refind] / filesystems / scandisk.c
1 /*
2 * scandisk.c
3 * Scanning disk for btrfs multi-devices
4 * by Samuel Liao
5 *
6 * Copyright (c) 2013 Tencent, Inc.
7 */
8 #include "fsw_efi.h"
9 #ifdef __MAKEWITH_GNUEFI
10 #include "edk2/DriverBinding.h"
11 #include "edk2/ComponentName.h"
12 #endif
13 #include "../include/refit_call_wrapper.h"
14
15 extern struct fsw_host_table fsw_efi_host_table;
16 static void dummy_volume_free(struct fsw_volume *vol) { }
17 static struct fsw_fstype_table dummy_fstype = {
18 { FSW_STRING_TYPE_UTF8, 4, 4, "dummy" },
19 sizeof(struct fsw_volume),
20 sizeof(struct fsw_dnode),
21
22 NULL, //volume_mount,
23 dummy_volume_free, //volume_free,
24 NULL, //volume_stat,
25 NULL, //dnode_fill,
26 NULL, //dnode_free,
27 NULL, //dnode_stat,
28 NULL, //get_extent,
29 NULL, //dir_lookup,
30 NULL, //dir_read,
31 NULL, //readlink,
32 };
33
34 static struct fsw_volume *create_dummy_volume(EFI_DISK_IO *diskio, UINT32 mediaid)
35 {
36 fsw_status_t err;
37 struct fsw_volume *vol;
38 FSW_VOLUME_DATA *Volume;
39
40 err = fsw_alloc_zero(sizeof(struct fsw_volume), (void **)&vol);
41 if(err)
42 return NULL;
43 err = fsw_alloc_zero(sizeof(FSW_VOLUME_DATA), (void **)&Volume);
44 if(err) {
45 fsw_free(vol);
46 return NULL;
47 }
48 /* fstype_table->volume_free for fsw_unmount */
49 vol->fstype_table = &dummy_fstype;
50 /* host_data needded to fsw_block_get()/fsw_efi_read_block() */
51 Volume->DiskIo = diskio;
52 Volume->MediaId = mediaid;
53
54 vol->host_data = Volume;
55 vol->host_table = &fsw_efi_host_table;
56 return vol;
57 }
58
59 static struct fsw_volume *clone_dummy_volume(struct fsw_volume *vol)
60 {
61 FSW_VOLUME_DATA *Volume = (FSW_VOLUME_DATA *)vol->host_data;
62 return create_dummy_volume(Volume->DiskIo, Volume->MediaId);
63 }
64
65 static void free_dummy_volume(struct fsw_volume *vol)
66 {
67 fsw_free(vol->host_data);
68 fsw_unmount(vol);
69 }
70
71 static int scan_disks(int (*hook)(struct fsw_volume *, struct fsw_volume *), struct fsw_volume *master)
72 {
73 EFI_STATUS Status;
74 EFI_HANDLE *Handles;
75 UINTN HandleCount = 0;
76 UINTN i;
77 UINTN scanned = 0;
78
79 // Driver hangs if compiled with GNU-EFI unless there's a Print() statement somewhere.
80 // I'm still trying to track that down; in the meantime, work around it....
81 #if defined(__MAKEWITH_GNUEFI)
82 Print(L" ");
83 #endif
84 DPRINT(L"Scanning disks\n");
85 Status = refit_call5_wrapper(BS->LocateHandleBuffer, ByProtocol, &PROTO_NAME(DiskIoProtocol), NULL, &HandleCount, &Handles);
86 if (Status == EFI_NOT_FOUND)
87 return -1; // no filesystems. strange, but true...
88 for (i = 0; i < HandleCount; i++) {
89 EFI_DISK_IO *diskio;
90 EFI_BLOCK_IO *blockio;
91 Status = refit_call3_wrapper(BS->HandleProtocol, Handles[i], &PROTO_NAME(DiskIoProtocol), (VOID **) &diskio);
92 if (Status != 0)
93 continue;
94 Status = refit_call3_wrapper(BS->HandleProtocol, Handles[i], &PROTO_NAME(BlockIoProtocol), (VOID **) &blockio);
95 if (Status != 0)
96 continue;
97 struct fsw_volume *vol = create_dummy_volume(diskio, blockio->Media->MediaId);
98 if(vol) {
99 DPRINT(L"Checking disk %d\n", i);
100 if(hook(master, vol) == FSW_SUCCESS)
101 scanned++;
102 free_dummy_volume(vol);
103 }
104 }
105 return scanned;
106 }
107