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