]> code.delx.au - refind/blob - filesystems/scandisk.c
eac4cd5facb4a979be7b6a07d0862b1fb1634ec6
[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 DPRINT(L"Scanning disks\n");
80 Status = BS->LocateHandleBuffer(ByProtocol, &PROTO_NAME(DiskIoProtocol), NULL, &HandleCount, &Handles);
81 if (Status == EFI_NOT_FOUND)
82 return -1; // no filesystems. strange, but true...
83 for (i = 0; i < HandleCount; i++) {
84 EFI_DISK_IO *diskio;
85 EFI_BLOCK_IO *blockio;
86 Status = refit_call3_wrapper(BS->HandleProtocol, Handles[i], &PROTO_NAME(DiskIoProtocol), (VOID **) &diskio);
87 if (Status != 0)
88 continue;
89 Status = refit_call3_wrapper(BS->HandleProtocol, Handles[i], &PROTO_NAME(BlockIoProtocol), (VOID **) &blockio);
90 if (Status != 0)
91 continue;
92 struct fsw_volume *vol = create_dummy_volume(diskio, blockio->Media->MediaId);
93 if(vol) {
94 DPRINT(L"Checking disk %d\n", i);
95 if(hook(master, vol) == FSW_SUCCESS)
96 scanned++;
97 free_dummy_volume(vol);
98 }
99 }
100 return scanned;
101 }
102